[PATCH 1/2] [User32]: clearly separe the 16bit code out of user32

Eric Pouech eric.pouech at orange.fr
Tue May 5 14:25:25 CDT 2009




A+
---

 dlls/user32/dde_misc.c    |   21 ++------
 dlls/user32/dde_private.h |    6 --
 dlls/user32/ddeml16.c     |  112 +++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 109 insertions(+), 30 deletions(-)


diff --git a/dlls/user32/dde_misc.c b/dlls/user32/dde_misc.c
index fda8255..1a9b662 100644
--- a/dlls/user32/dde_misc.c
+++ b/dlls/user32/dde_misc.c
@@ -341,7 +341,7 @@ static LRESULT CALLBACK WDML_EventProc(HWND hwndEvent, UINT uMsg, WPARAM wParam,
  *
  */
 UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
-		     DWORD afCmd, DWORD ulRes, BOOL bUnicode, BOOL b16)
+		     DWORD afCmd, DWORD ulRes, BOOL bUnicode)
 {
     WDML_INSTANCE*		pInstance;
     WDML_INSTANCE*		reference_inst;
@@ -377,7 +377,6 @@ UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
     pInstance->threadID = GetCurrentThreadId();
     pInstance->callback = *pfnCallback;
     pInstance->unicode = bUnicode;
-    pInstance->win16 = b16;
     pInstance->nodeList = NULL; /* node will be added later */
     pInstance->monitorFlags = afCmd & MF_MASK;
     pInstance->wStatus = 0;
@@ -591,7 +590,7 @@ UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
 UINT WINAPI DdeInitializeA(LPDWORD pidInst, PFNCALLBACK pfnCallback,
 			   DWORD afCmd, DWORD ulRes)
 {
-    return WDML_Initialize(pidInst, pfnCallback, afCmd, ulRes, FALSE, FALSE);
+    return WDML_Initialize(pidInst, pfnCallback, afCmd, ulRes, FALSE);
 }
 
 /******************************************************************************
@@ -611,7 +610,7 @@ UINT WINAPI DdeInitializeA(LPDWORD pidInst, PFNCALLBACK pfnCallback,
 UINT WINAPI DdeInitializeW(LPDWORD pidInst, PFNCALLBACK pfnCallback,
 			   DWORD afCmd, DWORD ulRes)
 {
-    return WDML_Initialize(pidInst, pfnCallback, afCmd, ulRes, TRUE, FALSE);
+    return WDML_Initialize(pidInst, pfnCallback, afCmd, ulRes, TRUE);
 }
 
 /*****************************************************************
@@ -728,18 +727,10 @@ HDDEDATA 	WDML_InvokeCallback(WDML_INSTANCE* pInstance, UINT uType, UINT uFmt, H
     if (pInstance == NULL)
 	return NULL;
 
-    TRACE("invoking CB%d[%p] (%x %x %p %p %p %p %lx %lx)\n",
-	  pInstance->win16 ? 16 : 32, pInstance->callback, uType, uFmt,
+    TRACE("invoking CB[%p] (%x %x %p %p %p %p %lx %lx)\n",
+	  pInstance->callback, uType, uFmt,
 	  hConv, hsz1, hsz2, hdata, dwData1, dwData2);
-    if (pInstance->win16)
-    {
-	ret = WDML_InvokeCallback16(pInstance->callback, uType, uFmt, hConv,
-				    hsz1, hsz2, hdata, dwData1, dwData2);
-    }
-    else
-    {
-	ret = pInstance->callback(uType, uFmt, hConv, hsz1, hsz2, hdata, dwData1, dwData2);
-    }
+    ret = pInstance->callback(uType, uFmt, hConv, hsz1, hsz2, hdata, dwData1, dwData2);
     TRACE("done => %p\n", ret);
     return ret;
 }
diff --git a/dlls/user32/dde_private.h b/dlls/user32/dde_private.h
index ed88ce3..c4e4fb4 100644
--- a/dlls/user32/dde_private.h
+++ b/dlls/user32/dde_private.h
@@ -157,7 +157,6 @@ typedef struct tagWDML_INSTANCE
     BOOL			monitor;        /* have these two as full Booleans cos they'll be tested frequently */
     BOOL			clientOnly;	/* bit wasteful of space but it will be faster */
     BOOL			unicode;	/* Flag to indicate Win32 API used to initialise */
-    BOOL			win16;          /* flag to indicate Win16 API used to initialize */
     HSZNode*			nodeList;	/* for cleaning upon exit */
     PFNCALLBACK     		callback;
     DWORD           		CBFflags;
@@ -189,9 +188,6 @@ typedef enum {
 extern	HDDEDATA 	WDML_InvokeCallback(WDML_INSTANCE* pInst, UINT uType, UINT uFmt, HCONV hConv,
 					    HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
 					    ULONG_PTR dwData1, ULONG_PTR dwData2) DECLSPEC_HIDDEN;
-extern	HDDEDATA 	WDML_InvokeCallback16(PFNCALLBACK pfn, UINT uType, UINT uFmt, HCONV hConv,
-					      HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
-					      DWORD dwData1, DWORD dwData2) DECLSPEC_HIDDEN;
 extern	WDML_SERVER*	WDML_AddServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic) DECLSPEC_HIDDEN;
 extern	void		WDML_RemoveServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic) DECLSPEC_HIDDEN;
 extern	WDML_SERVER*	WDML_FindServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic) DECLSPEC_HIDDEN;
@@ -201,7 +197,7 @@ extern WDML_QUEUE_STATE WDML_ServerHandle(WDML_CONV* pConv, WDML_XACT* pXAct) DE
 HDDEDATA WDML_ClientHandle(WDML_CONV *pConv, WDML_XACT *pXAct, DWORD dwTimeout, LPDWORD pdwResult) DECLSPEC_HIDDEN;
 /* called both in DdeClientTransaction and server side. */
 extern	UINT		WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
-					DWORD afCmd, DWORD ulRes, BOOL bUnicode, BOOL b16) DECLSPEC_HIDDEN;
+					DWORD afCmd, DWORD ulRes, BOOL bUnicode) DECLSPEC_HIDDEN;
 extern	WDML_CONV* 	WDML_AddConv(WDML_INSTANCE* pInstance, WDML_SIDE side,
 				     HSZ hszService, HSZ hszTopic, HWND hwndClient, HWND hwndServer) DECLSPEC_HIDDEN;
 extern	void		WDML_RemoveConv(WDML_CONV* pConv, WDML_SIDE side) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/ddeml16.c b/dlls/user32/ddeml16.c
index 375ee45..be73f89 100644
--- a/dlls/user32/ddeml16.c
+++ b/dlls/user32/ddeml16.c
@@ -5,7 +5,7 @@
  * Copyright 1997 Len White
  * Copyright 1999 Keith Matthews
  * Copyright 2000 Corel
- * Copyright 2001,2002 Eric Pouech
+ * Copyright 2001,2002,2009 Eric Pouech
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +22,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <config.h>
+#include "wine/port.h"
+
 #include <stdarg.h>
 #include <string.h>
 #include "windef.h"
@@ -30,7 +33,6 @@
 #include "wownt32.h"
 #include "dde.h"
 #include "ddeml.h"
-#include "dde_private.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ddeml);
@@ -87,15 +89,14 @@ static void map3216_conv_context(CONVCONTEXT16* cc16, const CONVCONTEXT* cc32)
     cc16->dwSecurity = cc32->dwSecurity;
 }
 
-
 /******************************************************************
  *		WDML_InvokeCallback16
  *
  *
  */
-HDDEDATA	WDML_InvokeCallback16(PFNCALLBACK pfn, UINT uType, UINT uFmt,
-                                      HCONV hConv, HSZ hsz1, HSZ hsz2,
-                                      HDDEDATA hdata, DWORD dwData1, DWORD dwData2)
+static HDDEDATA	CALLBACK WDML_InvokeCallback16(DWORD pfn16, UINT uType, UINT uFmt,
+                                               HCONV hConv, HSZ hsz1, HSZ hsz2,
+                                               HDDEDATA hdata, ULONG_PTR dwData1, ULONG_PTR dwData2)
 {
     DWORD               d1 = 0;
     HDDEDATA            ret;
@@ -133,7 +134,7 @@ HDDEDATA	WDML_InvokeCallback16(PFNCALLBACK pfn, UINT uType, UINT uFmt,
     args[2]  = LOWORD(d1);
     args[1]  = HIWORD(dwData2);
     args[0]  = LOWORD(dwData2);
-    WOWCallback16Ex( (DWORD)pfn, WCB16_PASCAL, sizeof(args), args, (DWORD *)&ret );
+    WOWCallback16Ex(pfn16, WCB16_PASCAL, sizeof(args), args, (DWORD *)&ret);
 
     switch (uType)
     {
@@ -145,14 +146,89 @@ HDDEDATA	WDML_InvokeCallback16(PFNCALLBACK pfn, UINT uType, UINT uFmt,
     return ret;
 }
 
+#define MAX_THUNKS      32
+/* As DDEML doesn't provide a way to get back to an InstanceID when
+ * a callback is run, we use thunk in order to implement simply the
+ * 32bit->16bit callback mechanism.
+ * For each 16bit instance, we create a thunk, which will be passed as
+ * a 32bit callback. This thunk also stores (in the code!) the 16bit
+ * address of the 16bit callback, and passes it back to
+ * WDML_InvokeCallback16.
+ * The code below is mainly to create the thunks themselved
+ */
+static struct ddeml_thunk
+{
+    BYTE        popl_eax;        /* popl  %eax (return address) */
+    BYTE        pushl_func;      /* pushl $pfn16 (16bit callback function) */
+    SEGPTR      pfn16;
+    BYTE        pushl_eax;       /* pushl %eax */
+    BYTE        jmp;             /* ljmp WDML_InvokeCallback16 */
+    DWORD       callback;
+    DWORD       instId;          /* instance ID */
+} *DDEML16_Thunks;
+
+static CRITICAL_SECTION ddeml_cs;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &ddeml_cs,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": ddeml_cs") }
+};
+static CRITICAL_SECTION ddeml_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+static struct ddeml_thunk*      DDEML_AddThunk(DWORD instId, DWORD pfn16)
+{
+    struct ddeml_thunk* thunk;
+
+    if (!DDEML16_Thunks)
+    {
+        DDEML16_Thunks = VirtualAlloc(NULL, MAX_THUNKS * sizeof(*DDEML16_Thunks), MEM_COMMIT,
+                                      PAGE_EXECUTE_READWRITE);
+        if (!DDEML16_Thunks) return NULL;
+        for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
+        {
+            thunk->popl_eax     = 0x58;   /* popl  %eax */
+            thunk->pushl_func   = 0x68;   /* pushl $pfn16 */
+            thunk->pfn16        = 0;
+            thunk->pushl_eax    = 0x50;   /* pushl %eax */
+            thunk->jmp          = 0xe9;   /* jmp WDML_InvokeCallback16 */
+            thunk->callback     = (DWORD_PTR)WDML_InvokeCallback16 - ((DWORD)&thunk->callback + sizeof(DWORD));
+            thunk->instId       = 0;
+        }
+    }
+    for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
+    {
+        /* either instId is 0, and we're looking for an empty slot, or
+         * instId is an already existing instance, and we should find its thunk
+         */
+        if (thunk->instId == instId)
+        {
+            thunk->pfn16 = pfn16;
+            return thunk;
+        }
+    }
+    FIXME("Out of ddeml-thunks. Bump MAX_THUNKS\n");
+    return NULL;
+}
+
 /******************************************************************************
  *            DdeInitialize   (DDEML.2)
  */
 UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
 			      DWORD afCmd, DWORD ulRes)
 {
-    return WDML_Initialize(pidInst, (PFNCALLBACK)pfnCallback, afCmd, ulRes,
-                           FALSE, TRUE);
+    UINT16 ret;
+    struct ddeml_thunk* thunk;
+
+    EnterCriticalSection(&ddeml_cs);
+    if ((thunk = DDEML_AddThunk(*pidInst, (DWORD)pfnCallback)))
+    {
+        ret = DdeInitializeA(pidInst, (PFNCALLBACK)thunk, afCmd, ulRes);
+        if (ret == DMLERR_NO_ERROR) thunk->instId = *pidInst;
+    }
+    else ret = DMLERR_SYS_ERROR;
+    LeaveCriticalSection(&ddeml_cs);
+    return ret;
 }
 
 /*****************************************************************
@@ -160,7 +236,23 @@ UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
  */
 BOOL16 WINAPI DdeUninitialize16(DWORD idInst)
 {
-    return (BOOL16)DdeUninitialize(idInst);
+    struct ddeml_thunk* thunk;
+    BOOL16              ret = FALSE;
+
+    if (!DdeUninitialize(idInst)) return FALSE;
+    EnterCriticalSection(&ddeml_cs);
+    for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
+    {
+        if (thunk->instId == idInst)
+        {
+            thunk->instId = 0;
+            ret = TRUE;
+            break;
+        }
+    }
+    LeaveCriticalSection(&ddeml_cs);
+    if (!ret) FIXME("Should never happen\n");
+    return ret;
 }
 
 /*****************************************************************





More information about the wine-patches mailing list