Partial implementation of NotifyRegister notifications

Joshua Thielen thielen at netprince.net
Wed Aug 21 21:17:55 CDT 2002


Hello!

This patch implements the ToolHelpHook and NotifyRegister notifications, 
NFY_STARTTASK, NFY_STARTDLL, NFY_LOADSEG, NFY_FREESEG, NFY_EXITTASK and 
NFY_DELMODULE, needed to fix bug 575 (SmartForms installer).

I expect there to be problems with this patch (some of it is probably a 
bit over my head) so eyes are requested, please! I already know that the 
number and order of the segment messages (NFY_LOADSEG and FREESEG) 
doesn't exactly match those sent in Windows, and I'm not totally sure of 
the affect this patch will have on 16-bit memory and threading details 
in wine.

Well anyway, here it goes...

Changelog:
Implemented NotifyRegister notifications, NFY_STARTTASK, NFY_STARTDLL,
NFY_LOADSEG, NFY_FREESEG, NFY_EXITTASK and NFY_DELMODULE

Modified Files:
wine/dlls/kernel/toolhelp.c
wine/dlls/kernel/toolhelp.spec
wine/dlls/ntdll/Makefile.in
wine/include/toolhelp.h
wine/loader/task.c
wine/loader/ne/module.c
wine/loader/ne/segment.c
wine/scheduler/thread.c

License:
GPL, X11

Josh Thielen


-------------- next part --------------
Index: wine/dlls/kernel/toolhelp.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/toolhelp.c,v
retrieving revision 1.17
diff -u -r1.17 toolhelp.c
--- wine/dlls/kernel/toolhelp.c	31 May 2002 23:25:48 -0000	1.17
+++ wine/dlls/kernel/toolhelp.c	18 Aug 2002 21:20:32 -0000
@@ -27,18 +27,15 @@
 #include "wine/winbase16.h"
 #include "winerror.h"
 #include "local.h"
+#include "stackframe.h"
 #include "tlhelp32.h"
 #include "toolhelp.h"
 #include "wine/server.h"
 #include "wine/debug.h"
+#include "miscemu.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(toolhelp);
 
-
-/* FIXME: to make this work, we have to call back all these registered
- * functions from all over the WINE code. Someone with more knowledge than
- * me please do that. -Marcus
- */
 static struct notify
 {
     HTASK16   htask;
@@ -46,9 +43,96 @@
     WORD     wFlags;
 } *notifys = NULL;
 
-static int nrofnotifys = 0;
+static int num_notifys = 0;
+/* ### start build ### */
+extern WORD CALLBACK TOOLHELP_CallTo16_word_wl(FARPROC16,WORD,DWORD);
+/* ### stop build ### */
+
+FARPROC16 ToolHelpHookProc = NULL;
+
+FARPROC16 WINAPI ToolHelpHook16(FARPROC16 lpfnNotifyHandler);
+
+void NotifyRegisterHook(CONTEXT86 *context)
+{
+    WORD wID = NFY_UNKNOWN;
+    DWORD dwData = 0;
+    NFYLOADSEG nfyls;
+    NFYSTARTDLL nfysd;
+    TEB *teb = NtCurrentTeb();
+    HANDLE16 handle = 0;
+    LPVOID p;
+    int i;
+
+    /* see INT 41h */
+    switch(context->Eax) 
+    { 
+        case 0x50:
+            wID = NFY_LOADSEG;
+            nfyls.dwSize = sizeof(nfyls);
+            nfyls.wSelector = CX_reg(context);
+            nfyls.wSegNum = BX_reg(context);
+            nfyls.wType = SI_reg(context);
+            nfyls.wcInstance = DX_reg(context);
+            nfyls.lpstrModuleName = CTX_SEG_OFF_TO_LIN(context, 
+                                        context->SegEs, context->Edi);
+            handle = GlobalAlloc16(0, sizeof(nfyls));
+            p = GlobalLock16(handle);
+            memcpy(p, &nfyls, sizeof(nfyls));
+            GlobalUnlock16(handle);
+            dwData = K32WOWGlobalLock16(handle);
+            break;
+
+        case 0x52:
+            wID = NFY_FREESEG;
+            dwData = context->Ebx; /* selector of freed segment */
+            break;
+
+        case 0x59:
+            wID = NFY_STARTTASK;
+            dwData = (DWORD) CTX_SEG_OFF_TO_LIN(context, 
+                    context->SegCs, context->Esi);
+            break;
+
+        case 0x62:
+            wID = NFY_EXITTASK;
+            dwData = *(BYTE *)MapSL((SEGPTR)teb->cur_stack + 6);
+            stack16_pop(6);
+            NotifyUnRegister16(GetCurrentTask());
+            break;
+
+        case 0x64:
+            wID = NFY_STARTDLL;
+            nfysd.dwSize = sizeof(NFYSTARTDLL);
+            nfysd.hModule = SI_reg(context);
+            nfysd.wCS = context->Ecx;
+            nfysd.wIP = context->Ebx;
+            handle = GlobalAlloc16(0, sizeof(nfysd));
+            p = GlobalLock16(handle);
+            memcpy(p, &nfysd, sizeof(nfysd));
+            GlobalUnlock16(handle);
+            dwData = K32WOWGlobalLock16(handle);
+            break;
+
+        case 0x65:
+            wID = NFY_DELMODULE;
+            dwData = context->SegEs;
+            break;
+
+        default:
+            wID = NFY_UNKNOWN;
+    }
 
-static FARPROC16 HookNotify = NULL;
+    /* Call the registered notification handlers */
+    for(i = 0; i < num_notifys; i++) 
+    {
+        TOOLHELP_CallTo16_word_wl(notifys[i].lpfnCallback, wID, dwData);
+    }
+
+    if(handle) {
+        GlobalUnlock16(handle);
+        GlobalFree16(handle);
+    }
+}
 
 /***********************************************************************
  *		NotifyRegister (TOOLHELP.73)
@@ -56,48 +140,75 @@
 BOOL16 WINAPI NotifyRegister16( HTASK16 htask, FARPROC16 lpfnCallback,
                               WORD wFlags )
 {
-    int	i;
+    int i;
 
-    FIXME("(%x,%lx,%x), semi-stub.\n",
+    FIXME("(%x,%lx,%x), not all notifications are implemented.\n",
                       htask, (DWORD)lpfnCallback, wFlags );
+    if(!num_notifys) 
+    {
+        FARPROC16 proc = GetProcAddress16(GetModuleHandle16("TOOLHELP"), 
+                    "NotifyRegisterHook");
+        ToolHelpHook16(proc);
+    }
+
     if (!htask) htask = GetCurrentTask();
-    for (i=0;i<nrofnotifys;i++)
-        if (notifys[i].htask==htask)
+    for (i = 0; i < num_notifys; i++) 
+    {
+        if (notifys[i].htask == htask)
+        {
             break;
-    if (i==nrofnotifys) {
-        if (notifys==NULL)
-            notifys=(struct notify*)HeapAlloc( GetProcessHeap(), 0,
-                                               sizeof(struct notify) );
-        else
-            notifys=(struct notify*)HeapReAlloc( GetProcessHeap(), 0, notifys,
-                                        sizeof(struct notify)*(nrofnotifys+1));
+        }
+    }
+    if (i == num_notifys) 
+    {
+        if (notifys == NULL) 
+        {
+            notifys = (struct notify*)HeapAlloc( GetProcessHeap(), 0,
+                                  sizeof(struct notify) );
+        } 
+        else 
+        {
+            notifys = (struct notify*)HeapReAlloc( GetProcessHeap(), 0, 
+                    notifys, sizeof(struct notify) * (num_notifys + 1));
+        }
         if (!notifys) return FALSE;
-        nrofnotifys++;
+        num_notifys++;
     }
-    notifys[i].htask=htask;
-    notifys[i].lpfnCallback=lpfnCallback;
-    notifys[i].wFlags=wFlags;
+    notifys[i].htask = htask;
+    notifys[i].lpfnCallback = lpfnCallback;
+    notifys[i].wFlags = wFlags;
     return TRUE;
 }
 
 /***********************************************************************
- *		NotifyUnregister (TOOLHELP.74)
+ *		NotifyUnRegister (TOOLHELP.74)
  */
-BOOL16 WINAPI NotifyUnregister16( HTASK16 htask )
+BOOL16 WINAPI NotifyUnRegister16( HTASK16 htask )
 {
     int	i;
 
-    FIXME("(%x), semi-stub.\n", htask );
     if (!htask) htask = GetCurrentTask();
-    for (i=nrofnotifys;i--;)
-        if (notifys[i].htask==htask)
+    for (i = 0; i < num_notifys; i++)
+    {
+        if (notifys[i].htask == htask)
+        {
             break;
-    if (i==-1)
+        }
+    }
+    if (i == num_notifys)
+    {
         return FALSE;
-    memcpy(notifys+i,notifys+(i+1),sizeof(struct notify)*(nrofnotifys-i-1));
-    notifys=(struct notify*)HeapReAlloc( GetProcessHeap(), 0, notifys,
-                                        (nrofnotifys-1)*sizeof(struct notify));
-    nrofnotifys--;
+    }
+    memcpy(notifys+i, notifys+i+1, sizeof(struct notify)*(num_notifys-i-1));
+    notifys = (struct notify *) HeapReAlloc( GetProcessHeap(), 0, notifys, 
+            (num_notifys-1) * sizeof(struct notify));
+    num_notifys--;
+
+    if(!num_notifys) 
+    {
+         /* remove hook proc */
+         ToolHelpHook16(0);
+    }
     return TRUE;
 }
 
@@ -191,9 +302,9 @@
 {
 	FARPROC16 tmp;
 
-	FIXME("(%p), stub.\n", lpfnNotifyHandler);
-	tmp = HookNotify;
-	HookNotify = lpfnNotifyHandler;
+	tmp = ToolHelpHookProc;
+	ToolHelpHookProc = lpfnNotifyHandler;
+    TRACE("installed tool help hook function %p\n", ToolHelpHookProc);
 	/* just return previously installed notification function */
 	return tmp;
 }
Index: wine/dlls/kernel/toolhelp.spec
===================================================================
RCS file: /home/wine/wine/dlls/kernel/toolhelp.spec,v
retrieving revision 1.5
diff -u -r1.5 toolhelp.spec
--- wine/dlls/kernel/toolhelp.spec	21 Jun 2002 19:15:47 -0000	1.5
+++ wine/dlls/kernel/toolhelp.spec	18 Aug 2002 21:20:32 -0000
@@ -25,7 +25,7 @@
 71 pascal16 SystemHeapInfo(ptr) SystemHeapInfo16
 72 pascal16 MemManInfo(ptr) MemManInfo16
 73 pascal16 NotifyRegister(word segptr word) NotifyRegister16
-74 pascal16 NotifyUnregister(word) NotifyUnregister16
+74 pascal16 NotifyUnRegister(word) NotifyUnRegister16
 75 pascal16 InterruptRegister(word segptr) InterruptRegister16
 76 pascal16 InterruptUnRegister(word) InterruptUnRegister16
 77 pascal16 TerminateApp(word word) TerminateApp16
@@ -38,3 +38,5 @@
 84 pascal16 Local32Info(ptr word) Local32Info16
 85 pascal16 Local32First(ptr word) Local32First16
 86 pascal16 Local32Next(ptr) Local32Next16
+# wine-specific
+100 pascal16 -register NotifyRegisterHook() NotifyRegisterHook
Index: wine/dlls/ntdll/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/Makefile.in,v
retrieving revision 1.31
diff -u -r1.31 Makefile.in
--- wine/dlls/ntdll/Makefile.in	1 Aug 2002 18:36:58 -0000	1.31
+++ wine/dlls/ntdll/Makefile.in	18 Aug 2002 21:20:37 -0000
@@ -7,6 +7,7 @@
 EXTRALIBS = $(LIBUNICODE)
 
 C_SRCS = \
+	$(TOPOBJDIR)/dlls/kernel/toolhelp.c \
 	$(TOPOBJDIR)/files/change.c \
 	$(TOPOBJDIR)/files/directory.c \
 	$(TOPOBJDIR)/files/dos_fs.c \
===================================================================
RCS file: /home/wine/wine/include/task.h,v
retrieving revision 1.30
diff -u -r1.30 task.h
--- wine/include/task.h	31 May 2002 23:06:49 -0000	1.30
+++ wine/include/task.h	18 Aug 2002 21:21:20 -0000
@@ -162,7 +162,7 @@
 extern void TASK_CreateMainTask(void);
 extern HTASK16 TASK_SpawnTask( struct _NE_MODULE *pModule, WORD cmdShow,
                                LPCSTR cmdline, BYTE len, HANDLE *hThread );
-extern void TASK_ExitTask(void);
+extern void TASK_ExitTask(DWORD code);
 extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
 extern TDB *TASK_GetPtr( HTASK16 hTask );
 extern TDB *TASK_GetCurrent(void);
Index: wine/include/toolhelp.h
===================================================================
RCS file: /home/wine/wine/include/toolhelp.h,v
retrieving revision 1.13
diff -u -r1.13 toolhelp.h
--- wine/include/toolhelp.h	10 Mar 2002 00:02:34 -0000	1.13
+++ wine/include/toolhelp.h	18 Aug 2002 21:21:21 -0000
@@ -328,6 +328,7 @@
 #define NF_RIP		2	/* get debugerrors of system */
 
 BOOL16 WINAPI NotifyRegister16(HTASK16 htask,FARPROC16 lpfnCallback,WORD wFlags);
+BOOL16 WINAPI NotifyUnRegister16(HTASK16 hTask);
 
 #define NFY_UNKNOWN	0
 #define NFY_LOADSEG	1
@@ -338,6 +339,7 @@
 	WORD	wSegNum;
 	WORD	wType;		/* bit 0 set if this is a code segment */
 	WORD	wcInstance;	/* only valid for data segment */
+    LPCSTR lpstrModuleName;
 } NFYLOADSEG;
 /* called when freeing a segment. LOWORD(dwData) is the freed selector */
 #define NFY_FREESEG	2
@@ -385,7 +387,7 @@
 #define NFY_INCHAR	10
 
 /* output debugstring (pointed to by dwData) */
-#define NFY_OUTSTRING	11
+#define NFY_OUTSTR	11
 
 /* log errors */
 #define NFY_LOGERROR	12
Index: wine/loader/task.c
===================================================================
RCS file: /home/wine/wine/loader/task.c,v
retrieving revision 1.120
diff -u -r1.120 task.c
--- wine/loader/task.c	28 Jul 2002 23:48:28 -0000	1.120
+++ wine/loader/task.c	18 Aug 2002 21:21:30 -0000
@@ -56,6 +56,7 @@
   /* Min. number of thunks allocated when creating a new segment */
 #define MIN_THUNKS  32
 
+extern FARPROC16 ToolHelpHookProc;
 
 static THHOOK DefaultThhook;
 THHOOK *pThhook = &DefaultThhook;
@@ -338,10 +339,7 @@
     pTask->pdb.cmdLine[0] = len;
     memcpy( pTask->pdb.cmdLine + 1, cmdline, len );
     /* pTask->pdb.cmdLine[len+1] = 0; */
-
-    TRACE("module='%s' cmdline='%.*s' task=%04x\n", name, len, cmdline, hTask );
-
-      /* Get the compatibility flags */
+    /* Get the compatibility flags */
 
     pTask->compat_flags = GetProfileIntA( "Compatibility", name, 0 );
 
@@ -468,10 +466,28 @@
 /***********************************************************************
  *           TASK_ExitTask
  */
-void TASK_ExitTask(void)
+void TASK_ExitTask(DWORD code)
 {
     TDB *pTask;
     DWORD lockCount;
+    CONTEXT86 context;
+    SEGPTR ptr;
+
+    /* send notification */
+    if(ToolHelpHookProc) 
+    {
+        TRACE_(toolhelp)("Sending termination notification\n");
+        memset(&context, 0, sizeof(context));
+        context.SegCs = SELECTOROF(ToolHelpHookProc); 
+        context.Eip = OFFSETOF(ToolHelpHookProc);
+        context.Ebp = OFFSETOF(NtCurrentTeb()->cur_stack) 
+            + (WORD)&((STACK16FRAME*)0)->bp;
+        context.Eax = 0x62;
+        ptr = stack16_push(6);
+        *(BYTE *)MapSL(ptr) = LOBYTE(code);
+        context.Esp -= 6;
+        wine_call_to_16_regs_short( &context, 0 );
+    }
 
     /* Enter the Win16Lock to protect global data structures */
     _EnterWin16Lock();
@@ -516,10 +532,10 @@
     if ( hLockedTask == pTask->hSelf )
         hLockedTask = 0;
 
-    TASK_DeleteTask( pTask->hSelf );
-
     /* ... and completely release the Win16Lock, just in case. */
     ReleaseThunkLock( &lockCount );
+
+    TASK_DeleteTask( pTask->hSelf );
 }
 
 
@@ -1535,6 +1555,7 @@
         ERR( "%s\n", debugstr_a(str) );
     }
  done:
+    NotifyUnRegister16(pTask->hSelf);
     ExitThread(0xff);
 }
 
Index: wine/loader/ne/module.c
===================================================================
RCS file: /home/wine/wine/loader/ne/module.c,v
retrieving revision 1.116
diff -u -r1.116 module.c
--- wine/loader/ne/module.c	31 Jul 2002 19:26:04 -0000	1.116
+++ wine/loader/ne/module.c	18 Aug 2002 21:21:36 -0000
@@ -42,6 +42,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(module);
 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
+WINE_DECLARE_DEBUG_CHANNEL(toolhelp);
 
 /*
  * Segment table entry
@@ -56,6 +57,7 @@
 
 #define hFirstModule (pThhook->hExeHead)
 
+extern FARPROC16 ToolHelpHookProc;
 static NE_MODULE *pCachedModule = 0;  /* Module cached by NE_OpenFile */
 
 static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only );
@@ -1187,6 +1189,22 @@
         sp -= sizeof(STACK16FRAME);
         pTask->teb->cur_stack = MAKESEGPTR( GlobalHandleToSel16(hInstance), sp );
 
+        /* send notification */
+        if(ToolHelpHookProc) 
+        {
+            TRACE_(toolhelp)("Sending start task notification\n");
+            pSegTable = NE_SEG_TABLE( pModule );
+            memset(&context, 0, sizeof(context));
+            context.SegCs = SELECTOROF(ToolHelpHookProc); 
+            context.Eip = OFFSETOF(ToolHelpHookProc);
+            context.Ebp = OFFSETOF(NtCurrentTeb()->cur_stack) 
+                + (WORD)&((STACK16FRAME*)0)->bp;
+            context.Eax = 0x59;
+            context.Ecx = pModule->cs;
+            context.Ebx = pModule->ip;
+            wine_call_to_16_regs_short( &context, 0 );
+        }
+
         /* Registers at initialization must be:
          * ax   zero
          * bx   stack size in bytes
@@ -1245,6 +1263,38 @@
     return NE_CallTo16_word_w( WEP, WEP_FREE_DLL );
 }
 
+/**********************************************************************
+ *	    NE_FreeModuleSegments
+ *
+ * Does not actually free the segment memory. Simply sends the free 
+ * segment notification for each segment in the module.
+ */
+void NE_FreeModuleSegments(NE_MODULE *pModule)
+{
+    SEGTABLEENTRY *pSegTable, *pSeg;
+    CONTEXT86 context;
+    int i;
+
+    pSegTable = NE_SEG_TABLE( pModule );
+    for(i = 0; i < pModule->seg_count; i++) {
+        memset(&context, 0, sizeof(context));
+        pSeg = pSegTable + i;
+
+        /* send notification */
+        if(ToolHelpHookProc) {
+            TRACE_(toolhelp)("sending free segment notification\n");
+            memset(&context, 0, sizeof(context));
+            context.SegCs = SELECTOROF(ToolHelpHookProc); 
+            context.Eip = OFFSETOF(ToolHelpHookProc);
+            context.Ebp = OFFSETOF(NtCurrentTeb()->cur_stack) 
+                + (WORD)&((STACK16FRAME*)0)->bp;
+            context.Eax = 0x52;
+            context.Ebx = GlobalHandleToSel16( pSeg->hSeg );
+            context.SegEs = pModule->self;
+            wine_call_to_16_regs_short(&context, 0);
+        }
+    }
+}
 
 /**********************************************************************
  *	    NE_FreeModule
@@ -1256,6 +1306,7 @@
     HMODULE16 *hPrevModule;
     NE_MODULE *pModule;
     HMODULE16 *pModRef;
+    CONTEXT86 context;
     int i;
 
     if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
@@ -1266,6 +1317,22 @@
     if (((INT16)(--pModule->count)) > 0 ) return TRUE;
     else pModule->count = 0;
 
+    /* send notifications */
+    if(ToolHelpHookProc) {
+        TRACE_(toolhelp)("sending toolhelp notification to hook proc %p\n", ToolHelpHookProc);
+        memset(&context, 0, sizeof(context));
+        context.SegCs = SELECTOROF(ToolHelpHookProc); 
+        context.Eip = OFFSETOF(ToolHelpHookProc);
+        context.Ebp = OFFSETOF(NtCurrentTeb()->cur_stack) 
+            + (WORD)&((STACK16FRAME*)0)->bp;
+        context.Eax = 0x65;
+        context.Ebx = GlobalHandleToSel16( pModule->self );
+        context.SegEs = pModule->self;
+        wine_call_to_16_regs_short(&context, 0);
+    }
+
+    NE_FreeModuleSegments(pModule);
+
     if (pModule->flags & NE_FFLAGS_BUILTIN)
         return FALSE;  /* Can't free built-in module */
 
Index: wine/loader/ne/segment.c
===================================================================
RCS file: /home/wine/wine/loader/ne/segment.c,v
retrieving revision 1.46
diff -u -r1.46 segment.c
--- wine/loader/ne/segment.c	31 Jul 2002 17:20:01 -0000	1.46
+++ wine/loader/ne/segment.c	18 Aug 2002 21:21:40 -0000
@@ -42,6 +42,7 @@
 WINE_DECLARE_DEBUG_CHANNEL(fixup);
 WINE_DECLARE_DEBUG_CHANNEL(module);
 WINE_DECLARE_DEBUG_CHANNEL(segment);
+WINE_DECLARE_DEBUG_CHANNEL(toolhelp);
 
 /*
  * Relocation table entry
@@ -76,6 +77,7 @@
 
 #define SEL(x) ((x)|1)
 
+extern FARPROC16 ToolHelpHookProc;
 static void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum);
 
 /* ### start build ### */
@@ -113,14 +115,17 @@
     FARPROC16 address = 0;
     HANDLE hf;
     DWORD res;
+    LPSTR lpstrModuleName;
     struct relocation_entry_s *rep, *reloc_entries;
     BYTE *func_name;
     int size;
     char* mem;
-
     char buffer[256];
     int ordinal, additive;
-    unsigned short *sp;
+    unsigned short *sp; 
+    CONTEXT86 context;
+    
+    lpstrModuleName = (char *) pModule + pModule->name_table + 1,
 
     pSegTable = NE_SEG_TABLE( pModule );
     pSeg = pSegTable + segnum - 1;
@@ -143,6 +148,27 @@
     hf = NE_OpenFile( pModule );
     TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n",
                     segnum, pSeg->hSeg, pSeg->flags );
+
+    /* send notification */
+    if(ToolHelpHookProc) 
+    {
+        TRACE_(toolhelp)("sending segment load notification\n");
+        /* send segment load notification */
+        memset(&context, 0, sizeof(context));
+        context.SegCs = SELECTOROF(ToolHelpHookProc); 
+        context.Eip = OFFSETOF(ToolHelpHookProc);
+        context.Ebp = OFFSETOF(NtCurrentTeb()->cur_stack) 
+            + (WORD)&((STACK16FRAME*)0)->bp;
+        context.Eax = 0x50;
+        context.Ebx = segnum;
+        context.Ecx = GlobalHandleToSel16(pSeg->hSeg);
+        context.Edx = pModule->self;
+        context.SegDs = SELECTOROF(lpstrModuleName);
+        context.Edi = OFFSETOF(lpstrModuleName);
+        context.Esi = pSeg->flags;
+        wine_call_to_16_regs_short(&context, 0);
+    }
+
     SetFilePointer( hf, pSeg->filepos << pModule->alignment, NULL, SEEK_SET );
     if (pSeg->size) size = pSeg->size;
     else size = pSeg->minsize ? pSeg->minsize : 0x10000;
@@ -644,9 +670,6 @@
     /* Call USER signal handler for Win3.1 compatibility. */
     TASK_CallTaskSignalProc( USIG16_DLL_LOAD, pModule->self );
 
-    if (!pModule->cs) return TRUE;  /* no initialization code */
-
-
     /* Registers at initialization must be:
      * cx     heap size
      * di     library instance
@@ -656,6 +679,32 @@
 
     memset( &context, 0, sizeof(context) );
 
+    /* send notification */
+    if(ToolHelpHookProc) 
+    {
+        TRACE_(toolhelp)("sending start DLL notification\n");
+        memset(&context, 0, sizeof(context));
+        context.SegCs = SELECTOROF(ToolHelpHookProc); 
+        context.Eip = OFFSETOF(ToolHelpHookProc);
+        context.Ebp = OFFSETOF(NtCurrentTeb()->cur_stack) 
+            + (WORD)&((STACK16FRAME*)0)->bp;
+        context.Eax = 0x64;
+        if (!pModule->cs) 
+        {
+            context.Ecx = 0;
+            context.Ebx = 0;
+        } 
+        else 
+        {
+            context.Ecx = SEL(pSegTable[pModule->cs-1].hSeg);
+            context.Ebx = pModule->ip;
+        }
+        context.Esi = pModule->self;
+        wine_call_to_16_regs_short(&context, 0);
+    }
+
+    if (!pModule->cs) return TRUE;  /* no initialization code */
+
     NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
 
     context.Ecx = heap;
@@ -667,12 +716,13 @@
     context.Eip = pModule->ip;
     context.Ebp = OFFSETOF(NtCurrentTeb()->cur_stack) + (WORD)&((STACK16FRAME*)0)->bp;
 
-
     pModule->cs = 0;  /* Don't initialize it twice */
+
     TRACE_(dll)("Calling LibMain, cs:ip=%04lx:%04lx ds=%04lx di=%04x cx=%04x\n",
                  context.SegCs, context.Eip, context.SegDs,
                  LOWORD(context.Edi), LOWORD(context.Ecx) );
     wine_call_to_16_regs_short( &context, 0 );
+
     return TRUE;
 }
 
Index: wine/scheduler/thread.c
===================================================================
RCS file: /home/wine/wine/scheduler/thread.c,v
retrieving revision 1.119
diff -u -r1.119 thread.c
--- wine/scheduler/thread.c	31 Jul 2002 19:26:05 -0000	1.119
+++ wine/scheduler/thread.c	18 Aug 2002 21:21:54 -0000
@@ -377,7 +377,8 @@
     else
     {
         MODULE_DllThreadDetach( NULL );
-        if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_ExitTask();
+        TRACE("Exit code=%08x\n", code);
+        if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_ExitTask(code);
         SYSDEPS_ExitThread( code );
     }
 }


More information about the wine-patches mailing list