 ==============================================================
 Patch for SoftIce DriverStudio (all versions) to fix problem
 of Symbol Loader not breaking at WinMain

 Kayaker Oct/2002 
 ww_paddler@hotmail.com
================================================================


Ever since the DriverStudio versions of SoftIce came out people seemed to be having problems with getting Symbol Loader to break at WinMain.  As it turns out there is a small difference in the winice driver from earlier versions in the routine which sets the "CC" breakpoint on the program entry point.  This patcher fixes the problem by making a small patch in nmtrans.dll and should be universal for all versions of DriverStudio.  Here is a *brief* explanation of the source of the problem...

============================================
To start with, here is the patch in the DriverStudio v2.7 nmtrans.dll. By changing the 1 instruction we affect a variable used in winice, and *ensure* that Symbol Loader will break at WinMain.

Original:

:1001CD7A 25FFFF0000              AND EAX, 0000FFFF	; PATCH HERE

:1001CD7F 50                      push eax
:1001CD80 8B4DDA                  mov ecx, dword ptr [ebp-26]
:1001CD83 51                      push ecx
:1001CD84 8D55B0                  lea edx, dword ptr [ebp-50]
:1001CD87 52                      push edx
* Reference To: nmtrans.DevIO_SetWLDRBreak

Patched:

:1001CD7A B8FFFF0000              MOV EAX, 0000FFFF	; PATCH

:1001CD7F 50                      push eax
:1001CD80 8B4DDA                  mov ecx, dword ptr [ebp-26]
:1001CD83 51                      push ecx
:1001CD84 8D55B0                  lea edx, dword ptr [ebp-50]
:1001CD87 52                      push edx
* Reference To: nmtrans.DevIO_SetWLDRBreak
==============================================


The nmtrans.dll function DevIO_SetWLDRBreak is used to communicate to the winice driver via a DeviceIOControl call that the user wants to break at the program entry point. The DevIO_ConnectToSoftICE function opens the vxd in the usual way with CreateFileA and returns a valid handle. Then DeviceIOControl is called, pushing the dwIoControlCode (9C40601C) for the proper function within the winice vxd to set the "Stop at WinMain" flag.  For more info on the functioning of nmtrans.dll, see IceLoad by The Owl, G-RoM and Muffin.


This unique dwIoControlCode (9C40601C) in nmtrans.dll is our "ticket" into the correct function in winice itself. (All addresses are from DriverStudio v2.7)

...
_text:1001FFBD                 push    9C40601Ch       ; dwIoControlCode
_text:1001FFC2                 push    esi             ; hDevice
_text:1001FFC3                 call    ds:DeviceIoControl ; communicate with winice


A search in winice.exe reveals the following code:

LCOD:C00007B0                 mov     ecx, [esi+0Ch]	; DeviceIOControl dwIoControlCode
LCOD:C00007B3                 mov     edx, ecx		; 9C40601Ch
LCOD:C00007B5                 shr     edx, 10h		; isolate HiWord		
LCOD:C00007B8                 cmp     edx, 9C40h	; equal to 1st part of dwIoControlCode?
LCOD:C00007BE                 jnz     short loc_0_C00007E0
LCOD:C00007C0                 mov     edx, ecx		; 9C40601Ch
LCOD:C00007C2                 shr     edx, 2		; E7101807h
LCOD:C00007C5                 and     edx, 0FFFh	; 807h
LCOD:C00007CB                 cmp     edx, 800h
LCOD:C00007D1                 jl      loc_0_C0000AAD
LCOD:C00007D7                 sub     edx, 800h		; 07h
LCOD:C00007DD                 inc     edx		; 08h
LCOD:C00007DE                 mov     ecx, edx
LCOD:C00007E0 
LCOD:C00007E0 loc_0_C00007E0:                         ; CODE XREF: LCOD:C00007BEj
LCOD:C00007E0                 inc     ecx		; 09h
LCOD:C00007E1                 cmp     ecx, 17h
LCOD:C00007E7                 jnb     loc_0_C0000AAD
LCOD:C00007ED                 jmp     ds:off_0_C0007E10[ecx*4] ; jump to correct routine
-------------------------------------------------


What all this boils down to is getting the correct Index value of 09h in ECX.  The JMP statement address then becomes C0007E10 + [09h*4], which leads to:

LCOD:C0007E34                 dd offset loc_0_C0000928 ; main function called by DeviceIO_WLDR

Following the code...

LCOD:C000093F                 push    dword ptr [eax+0Ch]	; 1
LCOD:C0000942                 push    dword ptr [eax+10h]	; 0
LCOD:C0000945                 push    dword ptr [eax+8]		; 0, BUT THIS IS THE CRITICAL VARIABLE!
LCOD:C0000948                 push    dword ptr [eax+4]		; CCh (ooh, what's this? ;-)
LCOD:C000094B                 push    dword ptr [eax]		; filename of program to be loaded
LCOD:C000094D                 call    sub_0_C003718D

That middle variable, dword ptr [eax+8], is going to turn out to be the critical one. It is moved into CX, then later into a small buffer containing the name of the program to be loaded, the "CC", some other flags and the word WINMAIN.

LCOD:C003719A                 mov     ebx, [ebp+arg_0] ; filename of program to be loaded
...
LCOD:C00371B9                 mov     edx, [ebp+arg_4] ; CCh
LCOD:C00371BC                 mov     cx, [ebp+arg_8]  ; CRITICAL VALUE MOVED INTO CX


Now comes the major difference in the code between DriverStudio 2.7 and Softice 4.05, and the how and why that patching that instruction in nmtrans.dll works.  Basically all we are doing is duplicating the code that existed in the 4.05 version.

--------------------------------------
DriverStudio 2.7:
LCOD:C003714A                 mov     ds:dword_0_C0037FA6, edx
LCOD:C0037150                 mov     ds:byte_0_C0037F7E, 4
LCOD:C0037157                 mov     ds:word_0_C0037FA2, 0FFFFh
LCOD:C0037160                 mov     ds:word_0_C0037FA0, cx ; WE WANT THIS TO BE 0FFFFh
LCOD:C0037167                 mov     ds:dword_0_C0037FAE, 0
LCOD:C0037171                 movzx   ecx, byte ptr [ebx]

Softice 4.05:
LCOD:C00607E4                 mov     ds:dword_0_C0061642, edx
LCOD:C00607EA                 mov     ds:byte_0_C006161A, 4
LCOD:C00607F1                 mov     ds:word_0_C006163E, 0FFFFh
LCOD:C00607FA                 mov     ds:word_0_C006163C, 0FFFFh ; Lacking in DriverStudio
LCOD:C0060803                 mov     ds:dword_0_C006164A, 0
LCOD:C006080D                 movzx   ecx, byte ptr [ebx]
---------------------------------------


This is basically the crux of the matter, but certainly doesn't convey the complexity of the Softice code or give an appreciation of the true excellence of the debugger.  Getting lost in the codewoods is the only way to do that ;-)

Enjoy the patch

Kayaker