DC hook proc thunk management simplified.
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 7c09bea..9bfee33 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -157,8 +157,8 @@
180 pascal16 SetDCState(word word) SetDCState16
181 pascal16 RectInRegionOld(word ptr) RectInRegion16
188 stub GetTextExtentEx
-190 pascal16 SetDCHook(word segptr long) THUNK_SetDCHook
-191 pascal GetDCHook(word ptr) THUNK_GetDCHook
+190 pascal16 SetDCHook(word segptr long) SetDCHook
+191 pascal GetDCHook(word ptr) GetDCHook
192 pascal16 SetHookFlags(word word) SetHookFlags16
193 pascal16 SetBoundsRect(word ptr word) SetBoundsRect16
194 pascal16 GetBoundsRect(word ptr word) GetBoundsRect16
diff --git a/include/gdi.h b/include/gdi.h
index 0c9f295..da3a578 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -137,15 +137,19 @@
BOOL vport2WorldValid; /* Is xformVport2World valid? */
} WIN_DC_INFO;
+
+typedef BOOL16 (CALLBACK *DCHOOKPROC)(HDC16,WORD,DWORD,LPARAM);
+
typedef struct tagDC
{
- GDIOBJHDR header;
+ GDIOBJHDR header;
HDC hSelf; /* Handle to this DC */
const struct tagDC_FUNCS *funcs; /* DC function table */
- void *physDev; /* Physical device (driver-specific) */
+ void *physDev; /* Physical device (driver-specific) */
INT saveLevel;
- DWORD dwHookData;
- FARPROC16 hookProc;
+ DWORD dwHookData;
+ FARPROC16 hookProc; /* the original SEGPTR ... */
+ DCHOOKPROC hookThunk; /* ... and the thunk to call it */
INT wndOrgX; /* Window origin */
INT wndOrgY;
diff --git a/objects/.cvsignore b/objects/.cvsignore
index f3c7a7c..6c4db5d 100644
--- a/objects/.cvsignore
+++ b/objects/.cvsignore
@@ -1 +1,2 @@
Makefile
+dc.glue.c
diff --git a/objects/Makefile.in b/objects/Makefile.in
index 02a4311..1a9202b 100644
--- a/objects/Makefile.in
+++ b/objects/Makefile.in
@@ -24,6 +24,8 @@
region.c \
text.c
+GLUE = dc.c
+
all: $(MODULE).o
@MAKE_RULES@
diff --git a/objects/clipping.c b/objects/clipping.c
index 841ad8a..0484e3e 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -15,8 +15,8 @@
#define UPDATE_DIRTY_DC(dc) \
do { \
- if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
- (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
+ if ((dc)->hookThunk && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
+ (dc)->hookThunk( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
} while(0)
diff --git a/objects/dc.c b/objects/dc.c
index 7d074bc..1dfb530 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -99,6 +99,7 @@
dc->saveLevel = 0;
dc->dwHookData = 0L;
dc->hookProc = NULL;
+ dc->hookThunk = NULL;
dc->wndOrgX = 0;
dc->wndOrgY = 0;
dc->wndExtX = 1;
@@ -680,8 +681,8 @@
TRACE("%04x\n", hdc );
/* Call hook procedure to check whether is it OK to delete this DC */
- if ( dc->hookProc && !(dc->w.flags & (DC_SAVED | DC_MEMORY))
- && dc->hookProc( hdc, DCHC_DELETEDC, dc->dwHookData, 0 ) == FALSE )
+ if ( dc->hookThunk && !(dc->w.flags & (DC_SAVED | DC_MEMORY))
+ && dc->hookThunk( hdc, DCHC_DELETEDC, dc->dwHookData, 0 ) == FALSE )
{
GDI_HEAP_UNLOCK( hdc );
return FALSE;
@@ -710,6 +711,7 @@
if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
if (dc->w.pAbortProc) THUNK_Free( (FARPROC)dc->w.pAbortProc );
+ if (dc->hookThunk) THUNK_Free( (FARPROC)dc->hookThunk );
PATH_DestroyGdiPath(&dc->w.path);
return GDI_FreeObject( hdc );
@@ -1201,16 +1203,35 @@
/***********************************************************************
* SetDCHook (GDI.190)
*/
+/* ### start build ### */
+extern WORD CALLBACK GDI_CallTo16_word_wwll(FARPROC16,WORD,WORD,LONG,LONG);
+/* ### stop build ### */
BOOL16 WINAPI SetDCHook( HDC16 hdc, FARPROC16 hookProc, DWORD dwHookData )
{
DC *dc = (DC *)GDI_GetObjPtr( hdc, DC_MAGIC );
-
- TRACE("hookProc %08x, default is %08x\n",
- (UINT)hookProc, (UINT)DCHook16 );
-
if (!dc) return FALSE;
+
+ /*
+ * Note: We store the original SEGPTR 'hookProc' as we need to be
+ * able to return it verbatim in GetDCHook,
+ *
+ * On the other hand, we still call THUNK_Alloc and store the
+ * 32-bit thunk into another DC member, because THUNK_Alloc
+ * recognizes the (typical) case that the 'hookProc' is indeed
+ * the 16-bit API entry point of a built-in routine (e.g. DCHook16)
+ *
+ * We could perform that test every time the hook is about to
+ * be called (or else we could live with the 32->16->32 detour),
+ * but this way is the most efficient ...
+ */
+
dc->hookProc = hookProc;
dc->dwHookData = dwHookData;
+
+ THUNK_Free( (FARPROC)dc->hookThunk );
+ dc->hookThunk = (DCHOOKPROC)
+ THUNK_Alloc( hookProc, (RELAY)GDI_CallTo16_word_wwll );
+
GDI_HEAP_UNLOCK( hdc );
return TRUE;
}
diff --git a/windows/dce.c b/windows/dce.c
index e825596..2e24db5 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -27,7 +27,9 @@
#include "region.h"
#include "heap.h"
#include "local.h"
+#include "module.h"
#include "debugtools.h"
+#include "wine/winbase16.h"
#include "wine/winuser16.h"
DEFAULT_DEBUG_CHANNEL(dc)
@@ -71,6 +73,7 @@
*/
DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type )
{
+ FARPROC16 hookProc;
DCE * dce;
WND* wnd;
@@ -85,7 +88,8 @@
/* store DCE handle in DC hook data field */
- SetDCHook( dce->hDC, (FARPROC16)DCHook16, (DWORD)dce );
+ hookProc = (FARPROC16)NE_GetEntryPoint( GetModuleHandle16("USER"), 362 );
+ SetDCHook( dce->hDC, hookProc, (DWORD)dce );
dce->hwndCurrent = hWnd;
dce->hClipRgn = 0;