[PATCH 1/2] [User32]: clearly separe the 16bit code out of user32
Eric Pouech
eric.pouech at orange.fr
Mon May 4 14:37:10 CDT 2009
A+
---
dlls/user32/dde_misc.c | 21 ++------
dlls/user32/dde_private.h | 6 --
dlls/user32/ddeml16.c | 124 +++++++++++++++++++++++++++++++++++++++++----
3 files changed, 121 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..3a7147c 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,101 @@ 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
+{
+ DWORD instId; /* instance ID */
+ SEGPTR pfn16; /* 16bit callback address */
+ /* start: ; 32bit callback */
+ BYTE call; /* call get_eip */
+ DWORD call_rel32; /* */
+ /* get_eip: */
+ BYTE pop_eax; /* pop %eax ; eip of get_eip */
+ BYTE pop_ecx; /* pop %ecx ; return address */
+ BYTE push_pfn[3];/* pushl -0x9(%eax) ; push pfn16 */
+ BYTE push_ecx; /* pushl %ecx */
+ BYTE push; /* push $DDEML_InstanceCallback16 */
+ DWORD cb16; /* */
+ BYTE ret; /* ret ; jmp DDEML_InstanceCal...*/
+} *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)
+{
+ int i;
+
+ if (!DDEML16_Thunks)
+ {
+ DDEML16_Thunks = VirtualAlloc(NULL, MAX_THUNKS * sizeof(*DDEML16_Thunks), MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+ if (!DDEML16_Thunks) return NULL;
+ for (i = 0; i < MAX_THUNKS; i++)
+ {
+ DDEML16_Thunks[i].instId = 0;
+ DDEML16_Thunks[i].pfn16 = 0;
+ DDEML16_Thunks[i].call = 0xe8;
+ DDEML16_Thunks[i].call_rel32 = 0;
+ DDEML16_Thunks[i].pop_eax = 0x58;
+ DDEML16_Thunks[i].pop_ecx = 0x59;
+ DDEML16_Thunks[i].push_pfn[0] = 0xff;
+ DDEML16_Thunks[i].push_pfn[1] = 0x70;
+ DDEML16_Thunks[i].push_pfn[2] = 0xfc;
+ DDEML16_Thunks[i].push_ecx = 0x51;
+ DDEML16_Thunks[i].push = 0x68;
+ DDEML16_Thunks[i].cb16 = (DWORD_PTR)WDML_InvokeCallback16;
+ DDEML16_Thunks[i].ret = 0xc3;
+ }
+ }
+ for (i = 0; i < MAX_THUNKS; i++)
+ {
+ /* 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 (DDEML16_Thunks[i].instId == instId)
+ {
+ DDEML16_Thunks[i].pfn16 = pfn16;
+ return &DDEML16_Thunks[i];
+ }
+ }
+ 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->call, afCmd, ulRes);
+ if (ret == DMLERR_NO_ERROR) thunk->instId = *pidInst;
+ }
+ else ret = DMLERR_SYS_ERROR;
+ LeaveCriticalSection(&ddeml_cs);
+ return ret;
}
/*****************************************************************
@@ -160,7 +248,23 @@ UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
*/
BOOL16 WINAPI DdeUninitialize16(DWORD idInst)
{
- return (BOOL16)DdeUninitialize(idInst);
+ unsigned i;
+ BOOL16 ret = FALSE;
+
+ if (!DdeUninitialize(idInst)) return FALSE;
+ EnterCriticalSection(&ddeml_cs);
+ for (i = 0; i < MAX_THUNKS; i++)
+ {
+ if (DDEML16_Thunks[i].instId == idInst)
+ {
+ DDEML16_Thunks[i].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