diff --git a/if1632/gdi.spec b/if1632/gdi.spec index 7c09bea694421a9ebd3881344898fbda5326ad28..9bfee33599d390eaa218220a0a3fd4a3ceaadeef 100644 --- a/if1632/gdi.spec +++ b/if1632/gdi.spec @@ -157,8 +157,8 @@ file gdi.exe 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 0c9f295ef1efab271a34c73aae7008852cad3680..da3a5781ff4344d0edc7b24b7b3961d9ba5dd037 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -137,15 +137,19 @@ typedef struct 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 f3c7a7c5da68804a1bdf391127ba34aed33c3cca..6c4db5dab95390d2ab7afb7568f7e605aeb0d681 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 02a4311dfe9625217e9bd7da483e698ee5e34220..1a9202b804da458d716253f32a8ea0c8217719db 100644 --- a/objects/Makefile.in +++ b/objects/Makefile.in @@ -24,6 +24,8 @@ C_SRCS = \ region.c \ text.c +GLUE = dc.c + all: $(MODULE).o @MAKE_RULES@ diff --git a/objects/clipping.c b/objects/clipping.c index 841ad8a36cd6c80936f028f2432f469b22fda00f..0484e3ebaad1635c9e8d510ad19abe6e25cc6243 100644 --- a/objects/clipping.c +++ b/objects/clipping.c @@ -15,8 +15,8 @@ DECLARE_DEBUG_CHANNEL(region) #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 7d074bc6afde4aaa92bcab5bf19d7d9f6abf3a3d..1dfb530aab13ac334c2533e5f9dbdfc8715ef605 100644 --- a/objects/dc.c +++ b/objects/dc.c @@ -99,6 +99,7 @@ DC *DC_AllocDC( const DC_FUNCTIONS *funcs ) 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 @@ BOOL WINAPI DeleteDC( HDC hdc ) 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 @@ BOOL WINAPI DeleteDC( HDC hdc ) 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 @@ BOOL WINAPI CombineTransform( LPXFORM xformResult, const XFORM *xform1, /*********************************************************************** * 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 ); + if (!dc) return FALSE; - TRACE("hookProc %08x, default is %08x\n", - (UINT)hookProc, (UINT)DCHook16 ); + /* + * 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 ... + */ - 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_HEAP_UNLOCK( hdc ); return TRUE; } diff --git a/windows/dce.c b/windows/dce.c index e825596db433d5566314d408ed42fc12974b119a..2e24db52a68be35b1f7e7d880503038232a89061 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 @@ static void DCE_DumpCache(void) */ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type ) { + FARPROC16 hookProc; DCE * dce; WND* wnd; @@ -85,7 +88,8 @@ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type ) /* 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;