                        DbgView patch
                                        derok of ARTeam

Well story goes like this, one day I was playing with some system wide injections
and suddenly my system started blocking. Of course, I spent some time checking 
my code, and couldn't find any bug which is responsible for this hang. So as 
always I fired up debugger and tried to locate the problem. Suddenly my application
caused serious delay in OutputDebugStringW. Bingo, seems like I found my trouble
causer.

Now lets see how actually OutputDebugStringsA/W work:

Application which sends string will do:

[1] WaitForSingleObject(DBWinMutex, INFINITE);
[2] wait_status = WaitForSingleObject(DWBIN_BUFFER_READY, 10000);      //10 sec
[3] if (wait_status == WAIT_TIMEOUT) __goto [7]
[4] OpenMapSection(DBWIN_BUFFER);
[5] write string to this section
[6] SetEvent(DBWIN_DATA_READY);
[7] ReleaseMutex(DBWinMutex);
[8] continue with execution

DbgView will more or less do something like this:

while (1){
        wait_status = WaitForSingleObject(DBWIN_DATA_READY, some_delay);
        if (wait_status == WAIT_TIMEOUT) continue;
        
        OpenMapSection(DBWIN_BUFFER);
        read data from section
        SetEvent(DBWIN_BUFFER_READY);
}

Now comes funny part, if application which clears event DBWIN_BUFFER_READY [2] dies before
setting DBWIN_DATA_READY [6], DbgView.exe will never, ever set DBWIN_BUFFER_READY in this
case. WaitForSingleObject at [2] will thus block this application for 10sec (well more
to say this thread). Now lets say that I hooked some API, and I'm monitoring output via
OutputDebugStringA/W? What will happen? Basically all applications which call this API
will block for at least 10sec, but thanks to the mutex ownership, if 10 applications call
this API in more or less same time we will get 10 * 10s until last application responds.
Now imagin that this was, for example, SendMessageA/W hooked or some API which will be
called frequently, we hang system.

So what's this patch doing? 

while (1){
        wait_status = WaitForSingleObject(DBWIN_DATA_READY, some_delay);
        if (wait_status == WAIT_TIMEOUT){
                SetEvent(DBWIN_BUFFER_READY);   <---- MaGiC patch
                continue;
        }
        
        OpenMapSection(DBWIN_BUFFER);
        read data from section
        SetEvent(DBWIN_BUFFER_READY);
}
        
So, after all, there was no bug in my code. With a little bit reversing we found our 
trouble maker. Well I was thinking to write my own DbgView.exe, but making patch was
much faster, and I already got used to DbgView.exe highlithing :)

                                                                deroko of ARTeam
        