From 7d155d6706552faa643b3f38cc4c17aad178d892 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Mon, 17 Dec 2001 20:58:06 +0000
Subject: [PATCH] Changed DC hook and abort proc handling to avoid having to
 allocate thunks dynamically.

---
 dlls/gdi/gdi32.spec     |  1 +
 dlls/gdi/printdrv.c     | 32 +++++++++++++++++-----
 graphics/escape.c       |  2 +-
 include/gdi.h           |  3 +--
 include/wine/wingdi16.h |  7 +++--
 objects/.cvsignore      |  4 +++
 objects/Makefile.in     |  7 ++++-
 objects/dc.c            | 60 +++++++++++++++++++++--------------------
 windows/dce.c           |  4 +--
 9 files changed, 75 insertions(+), 45 deletions(-)

diff --git a/dlls/gdi/gdi32.spec b/dlls/gdi/gdi32.spec
index 81c8aa203d7..3f15020929e 100644
--- a/dlls/gdi/gdi32.spec
+++ b/dlls/gdi/gdi32.spec
@@ -421,3 +421,4 @@ debug_channels (bitblt bitmap clipping dc ddraw driver enhmetafile font gdi
 #
 @ stdcall CreateMetaFile16(str) CreateMetaFile16
 @ stdcall CloseMetaFile16(long) CloseMetaFile16
+@ stdcall SetDCHook(long ptr long) SetDCHook
diff --git a/dlls/gdi/printdrv.c b/dlls/gdi/printdrv.c
index 9402fa65db3..acf9eb25ada 100644
--- a/dlls/gdi/printdrv.c
+++ b/dlls/gdi/printdrv.c
@@ -17,6 +17,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include "winbase.h"
+#include "winuser.h"
 #include "wine/winbase16.h"
 #include "wine/wingdi16.h"
 #include "winspool.h"
@@ -24,7 +25,6 @@
 #include "winreg.h"
 #include "debugtools.h"
 #include "gdi.h"
-#include "callback.h"
 #include "heap.h"
 #include "file.h"
 
@@ -249,15 +249,33 @@ BOOL16 WINAPI QueryAbort16(HDC16 hdc, INT16 reserved)
 extern WORD CALLBACK PRTDRV_CallTo16_word_ww(FARPROC16,WORD,WORD);
 /* ### stop build ### */
 
+/**********************************************************************
+ *           call_abort_proc16
+ */
+static BOOL CALLBACK call_abort_proc16( HDC hdc, INT code )
+{
+    ABORTPROC16 proc16;
+    DC *dc = DC_GetDCPtr( hdc );
+
+    if (!dc) return FALSE;
+    proc16 = dc->pAbortProc16;
+    GDI_ReleaseObj( hdc );
+    if (proc16) return PRTDRV_CallTo16_word_ww( (FARPROC16)proc16, hdc, code );
+    return TRUE;
+}
+
+
 /**********************************************************************
  *           SetAbortProc   (GDI.381)
- *
  */
-INT16 WINAPI SetAbortProc16(HDC16 hdc, SEGPTR abrtprc)
+INT16 WINAPI SetAbortProc16(HDC16 hdc, ABORTPROC16 abrtprc)
 {
-    ABORTPROC proc32 = (ABORTPROC)THUNK_Alloc((FARPROC16)abrtprc,
-					      (RELAY)PRTDRV_CallTo16_word_ww);
-    return SetAbortProc(hdc, proc32);
+    DC *dc = DC_GetDCPtr( hdc );
+
+    if (!dc) return FALSE;
+    dc->pAbortProc16 = abrtprc;
+    GDI_ReleaseObj( hdc );
+    return SetAbortProc( hdc, call_abort_proc16 );
 }
 
 /**********************************************************************
@@ -268,7 +286,7 @@ INT WINAPI SetAbortProc(HDC hdc, ABORTPROC abrtprc)
 {
     DC *dc = DC_GetDCPtr( hdc );
 
-    if(dc->pAbortProc) THUNK_Free((FARPROC)dc->pAbortProc);
+    if (!dc) return FALSE;
     dc->pAbortProc = abrtprc;
     GDI_ReleaseObj( hdc );
     return TRUE;
diff --git a/graphics/escape.c b/graphics/escape.c
index 75b28c8ffc9..0271ae2c016 100644
--- a/graphics/escape.c
+++ b/graphics/escape.c
@@ -103,7 +103,7 @@ INT16 WINAPI Escape16( HDC16 hdc, INT16 escape, INT16 in_count,
 
     /* Escape(hdc,SETABORTPROC,ABORTPROC,NULL); */
     case SETABORTPROC:
-        return SetAbortProc16( hdc, in_data );
+        return SetAbortProc16( hdc, (ABORTPROC16)in_data );
 
     /* Escape(hdc,STARTDOC,LPSTR,LPDOCINFO16);
      * lpvOutData is actually a pointer to the DocInfo structure and used as
diff --git a/include/gdi.h b/include/gdi.h
index bb0eec13323..f0c9f680de1 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -46,8 +46,6 @@ typedef struct tagGDIOBJHDR
 } GDIOBJHDR;
 
 
-typedef BOOL16 CALLBACK (*DCHOOKPROC)(HDC16,WORD,DWORD,LPARAM);
-
 typedef struct tagGdiFont *GdiFont;
 
 typedef struct tagDC
@@ -109,6 +107,7 @@ typedef struct tagDC
     INT           DCOrgX;            /* DC origin */
     INT           DCOrgY;
     ABORTPROC     pAbortProc;        /* AbortProc for Printing */
+    ABORTPROC16   pAbortProc16;
     INT           CursPosX;          /* Current position */
     INT           CursPosY;
     INT           ArcDirection;
diff --git a/include/wine/wingdi16.h b/include/wine/wingdi16.h
index 157801f2ad0..cbd0b83ade9 100644
--- a/include/wine/wingdi16.h
+++ b/include/wine/wingdi16.h
@@ -216,11 +216,13 @@ typedef struct
     FONTSIGNATURE       ntmFontSig;
 } NEWTEXTMETRICEX16,*LPNEWTEXTMETRICEX16;
 
+typedef BOOL16 CALLBACK (*DCHOOKPROC)(HDC16,WORD,DWORD,LPARAM);
 typedef INT16 CALLBACK (*FONTENUMPROC16)(SEGPTR,SEGPTR,UINT16,LPARAM);
 typedef INT16 CALLBACK (*FONTENUMPROCEX16)(SEGPTR,SEGPTR,UINT16,LPARAM);
 typedef VOID  CALLBACK (*LINEDDAPROC16)(INT16,INT16,LPARAM);
 typedef INT16 CALLBACK (*GOBJENUMPROC16)(SEGPTR,LPARAM);
 
+
 typedef struct
 {
     UINT16	gmBlackBoxX;
@@ -505,7 +507,7 @@ BOOL16      WINAPI SelectClipPath16(HDC16,INT16);
 INT16       WINAPI SelectClipRgn16(HDC16,HRGN16);
 HGDIOBJ16   WINAPI SelectObject16(HDC16,HGDIOBJ16);
 INT16       WINAPI SelectVisRgn16(HDC16,HRGN16);
-INT16       WINAPI SetAbortProc16(HDC16,SEGPTR);
+INT16       WINAPI SetAbortProc16(HDC16,ABORTPROC16);
 INT16       WINAPI SetArcDirection16(HDC16,INT16);
 LONG        WINAPI SetBitmapBits16(HBITMAP16,LONG,LPCVOID);
 DWORD       WINAPI SetBitmapDimension16(HBITMAP16,INT16,INT16);
@@ -514,7 +516,8 @@ COLORREF    WINAPI SetBkColor16(HDC16,COLORREF);
 INT16       WINAPI SetBkMode16(HDC16,INT16);
 UINT16      WINAPI SetBoundsRect16(HDC16,const RECT16*,UINT16);
 DWORD       WINAPI SetBrushOrg16(HDC16,INT16,INT16);
-BOOL16      WINAPI SetDCHook(HDC16,FARPROC16,DWORD);
+BOOL        WINAPI SetDCHook(HDC,DCHOOKPROC,DWORD);
+BOOL16      WINAPI SetDCHook16(HDC16,FARPROC16,DWORD);
 DWORD       WINAPI SetDCOrg16(HDC16,INT16,INT16);
 VOID        WINAPI SetDCState16(HDC16,HDC16);
 UINT16      WINAPI SetDIBColorTable16(HDC16,UINT16,UINT16,RGBQUAD*);
diff --git a/objects/.cvsignore b/objects/.cvsignore
index 6c4db5dab95..ce0b3286392 100644
--- a/objects/.cvsignore
+++ b/objects/.cvsignore
@@ -1,2 +1,6 @@
 Makefile
 dc.glue.c
+font.glue.c
+gdiobj.glue.c
+linedda.glue.c
+metafile.glue.c
diff --git a/objects/Makefile.in b/objects/Makefile.in
index a198d091df1..9a77c2496ec 100644
--- a/objects/Makefile.in
+++ b/objects/Makefile.in
@@ -23,7 +23,12 @@ C_SRCS = \
 	region.c \
 	text.c
 
-GLUE = dc.c
+GLUE = \
+	dc.c \
+	font.c \
+	gdiobj.c \
+	linedda.c \
+	metafile.c
 
 all: $(MODULE).o
 
diff --git a/objects/dc.c b/objects/dc.c
index 24b16ef6dc8..b06de93473e 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -13,7 +13,6 @@
 #include "heap.h"
 #include "debugtools.h"
 #include "font.h"
-#include "callback.h"
 #include "winerror.h"
 #include "windef.h"
 #include "wingdi.h"
@@ -21,6 +20,9 @@
 
 DEFAULT_DEBUG_CHANNEL(dc);
 
+/* ### start build ### */
+extern WORD CALLBACK GDI_CallTo16_word_wwll(FARPROC16,WORD,WORD,LONG,LONG);
+/* ### stop build ### */
 
 /***********************************************************************
  *           DC_AllocDC
@@ -773,8 +775,6 @@ BOOL WINAPI DeleteDC( HDC hdc )
     if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
     if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
     if (dc->hGCClipRgn) DeleteObject( dc->hGCClipRgn );
-    if (dc->pAbortProc) THUNK_Free( (FARPROC)dc->pAbortProc );
-    if (dc->hookThunk) THUNK_Free( (FARPROC)dc->hookThunk );
     if (dc->gdiFont) WineEngDecRefFont( dc->gdiFont );
     PATH_DestroyGdiPath(&dc->path);
 
@@ -1181,43 +1181,45 @@ BOOL WINAPI CombineTransform( LPXFORM xformResult, const XFORM *xform1,
 
 
 /***********************************************************************
- *           SetDCHook   (GDI.190)
+ *           SetDCHook   (GDI32.@)
+ *
+ * Note: this doesn't exist in Win32, we add it here because user32 needs it.
  */
+BOOL WINAPI SetDCHook( HDC hdc, DCHOOKPROC hookProc, DWORD dwHookData )
+{
+    DC *dc = DC_GetDCPtr( hdc );
 
-/* ### start build ### */
-extern WORD CALLBACK GDI_CallTo16_word_wwll(FARPROC16,WORD,WORD,LONG,LONG);
-/* ### stop build ### */
+    if (!dc) return FALSE;
+    dc->dwHookData = dwHookData;
+    dc->hookThunk = hookProc;
+    GDI_ReleaseObj( hdc );
+    return TRUE;
+}
 
-/**********************************************************************/
 
-BOOL16 WINAPI SetDCHook( HDC16 hdc, FARPROC16 hookProc, DWORD dwHookData )
+/* relay function to call the 16-bit DC hook proc */
+static BOOL16 WINAPI call_dc_hook16( HDC16 hdc, WORD code, DWORD data, LPARAM lParam )
 {
+    FARPROC16 proc = NULL;
     DC *dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
+    proc = dc->hookProc;
+    GDI_ReleaseObj( hdc );
+    if (!proc) return FALSE;
+    return GDI_CallTo16_word_wwll( proc, hdc, code, data, lParam );
+}
 
-    /*
-     * 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 ...
-     */
+/***********************************************************************
+ *           SetDCHook   (GDI.190)
+ */
+BOOL16 WINAPI SetDCHook16( HDC16 hdc, FARPROC16 hookProc, DWORD dwHookData )
+{
+    DC *dc = DC_GetDCPtr( hdc );
+    if (!dc) return FALSE;
 
     dc->hookProc = hookProc;
-    dc->dwHookData = dwHookData;
-
-    THUNK_Free( (FARPROC)dc->hookThunk );
-    dc->hookThunk = (DCHOOKPROC)
-                    THUNK_Alloc( hookProc, (RELAY)GDI_CallTo16_word_wwll );
-
     GDI_ReleaseObj( hdc );
-    return TRUE;
+    return SetDCHook( hdc, call_dc_hook16, dwHookData );
 }
 
 
diff --git a/windows/dce.c b/windows/dce.c
index 49d9ff4eb16..4f27e65dc44 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -68,7 +68,6 @@ static void DCE_DumpCache(void)
  */
 DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type )
 {
-    FARPROC16 hookProc;
     DCE * dce;
     
     if (!(dce = HeapAlloc( GetProcessHeap(), 0, sizeof(DCE) ))) return NULL;
@@ -81,8 +80,7 @@ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type )
 
     /* store DCE handle in DC hook data field */
 
-    hookProc = GetProcAddress16( GetModuleHandle16("USER"), (LPCSTR)362 );
-    SetDCHook( dce->hDC, hookProc, (DWORD)dce );
+    SetDCHook( dce->hDC, DCHook16, (DWORD)dce );
 
     dce->hwndCurrent = WIN_GetFullHandle( hWnd );
     dce->hClipRgn    = 0;
-- 
GitLab