From 33a04dc69c5cb60e9008e3c4fd6caf6803c2a1f4 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Thu, 14 May 2009 21:36:29 +0200 Subject: [PATCH] msvfw32: Clearly separate the 16-bit code out of the rest by wrapping 16-bit message functions in thunks. --- dlls/msvfw32/msvideo16.c | 252 ++++++++++++++++++++------------- dlls/msvfw32/msvideo_main.c | 37 ++--- dlls/msvfw32/msvideo_private.h | 14 -- 3 files changed, 164 insertions(+), 139 deletions(-) diff --git a/dlls/msvfw32/msvideo16.c b/dlls/msvfw32/msvideo16.c index c873da57f45..69321f567d2 100644 --- a/dlls/msvfw32/msvideo16.c +++ b/dlls/msvfw32/msvideo16.c @@ -30,7 +30,6 @@ #include "winreg.h" #include "winuser.h" #include "vfw16.h" -#include "msvideo_private.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(msvideo); @@ -38,6 +37,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvideo); /* Drivers32 settings */ #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32" +/* handle16 --> handle conversions */ +#define HDRAWDIB_32(h16) ((HDRAWDIB)(ULONG_PTR)(h16)) +#define HIC_32(h16) ((HIC)(ULONG_PTR)(h16)) + +/* handle --> handle16 conversions */ +#define HDRVR_16(h32) (LOWORD(h32)) +#define HDRAWDIB_16(h32) (LOWORD(h32)) +#define HIC_16(h32) (LOWORD(h32)) + /*********************************************************************** * DrawDibOpen [MSVIDEO.102] */ @@ -134,14 +142,6 @@ HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode) return HIC_16(ICOpen(fccType, fccHandler, wMode)); } -/*********************************************************************** - * ICClose [MSVIDEO.204] - */ -LRESULT WINAPI ICClose16(HIC16 hic) -{ - return ICClose(HIC_32(hic)); -} - /*********************************************************************** * _ICMessage [MSVIDEO.207] */ @@ -670,40 +670,99 @@ BOOL16 VFWAPI ICInfo16(DWORD fccType, DWORD fccHandler, ICINFO16 *lpicinfo) * * */ -static LRESULT CALLBACK IC_Callback3216(HIC hic, HDRVR hdrv, UINT msg, DWORD lp1, DWORD lp2) +static LRESULT CALLBACK IC_Callback3216(DWORD pfn16, HIC hic, HDRVR hdrv, UINT msg, DWORD lp1, DWORD lp2) { - WINE_HIC* whic; WORD args[8]; + DWORD ret = 0; - whic = MSVIDEO_GetHicPtr(hic); - if (whic) + switch (msg) { - DWORD ret = 0; - switch (msg) - { - case DRV_OPEN: - lp2 = (DWORD)MapLS((void*)lp2); - break; - } - args[7] = HIWORD(hic); - args[6] = LOWORD(hic); - args[5] = HDRVR_16(whic->hdrv); - args[4] = msg; - args[3] = HIWORD(lp1); - args[2] = LOWORD(lp1); - args[1] = HIWORD(lp2); - args[0] = LOWORD(lp2); - WOWCallback16Ex( whic->driverproc16, WCB16_PASCAL, sizeof(args), args, &ret ); - - switch (msg) - { - case DRV_OPEN: - UnMapLS(lp2); - break; - } - return ret; + case DRV_OPEN: + lp2 = (DWORD)MapLS((void*)lp2); + break; } - else return ICERR_BADHANDLE; + args[7] = HIWORD(hic); + args[6] = LOWORD(hic); + args[5] = HDRVR_16(hdrv); + args[4] = msg; + args[3] = HIWORD(lp1); + args[2] = LOWORD(lp1); + args[1] = HIWORD(lp2); + args[0] = LOWORD(lp2); + WOWCallback16Ex( pfn16, WCB16_PASCAL, sizeof(args), args, &ret ); + + switch (msg) + { + case DRV_OPEN: + UnMapLS(lp2); + break; + } + return ret; +} + +#define MAX_THUNKS 32 + +static struct msvideo_thunk +{ + BYTE popl_eax; /* popl %eax (return address) */ + BYTE pushl_func; /* pushl $pfn16 (16bit callback function) */ + DWORD pfn16; + BYTE pushl_eax; /* pushl %eax */ + BYTE jmp; /* ljmp WDML_InvokeCallback16 */ + DWORD callback; + HIC16 hIC16; /* driver's handle */ +} *MSVIDEO_Thunks; + +static CRITICAL_SECTION msvideo_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &msvideo_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": msvideo_cs") } +}; +static CRITICAL_SECTION msvideo_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + +static struct msvideo_thunk* MSVIDEO_AddThunk(DWORD pfn16) +{ + struct msvideo_thunk* thunk; + + if (!MSVIDEO_Thunks) + { + MSVIDEO_Thunks = VirtualAlloc(NULL, MAX_THUNKS * sizeof(*MSVIDEO_Thunks), MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (!MSVIDEO_Thunks) return NULL; + for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_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 IC_Callback3216 */ + thunk->callback = (char *)IC_Callback3216 - (char *)(&thunk->callback + 1); + thunk->hIC16 = 0; + } + } + for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++) + { + if (thunk->pfn16 == 0) + { + thunk->pfn16 = pfn16; + return thunk; + } + } + FIXME("Out of msvideo-thunks. Bump MAX_THUNKS\n"); + return NULL; +} + +static struct msvideo_thunk* MSVIDEO_HasThunk(HIC16 hic) +{ + struct msvideo_thunk* thunk; + + for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++) + { + if (thunk->hIC16 == hic) return thunk; + } + return NULL; } /*********************************************************************** @@ -712,9 +771,15 @@ static LRESULT CALLBACK IC_Callback3216(HIC hic, HDRVR hdrv, UINT msg, DWORD l HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler) { HIC hic32; + struct msvideo_thunk* thunk; - hic32 = MSVIDEO_OpenFunction(fccType, fccHandler, wMode, - (DRIVERPROC)IC_Callback3216, (DWORD)lpfnHandler); + EnterCriticalSection(&msvideo_cs); + if (!(thunk = MSVIDEO_AddThunk((DWORD)lpfnHandler))) return 0; + if ((hic32 = ICOpenFunction(fccType, fccHandler, wMode, IC_Callback3216))) + thunk->hIC16 = HIC_16(hic32); + else + thunk->pfn16 = 0; + LeaveCriticalSection(&msvideo_cs); return HIC_16(hic32); } @@ -724,40 +789,57 @@ HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FAR LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2) { LRESULT ret = ICERR_BADHANDLE; - WINE_HIC* whic; + struct msvideo_thunk* thunk; - whic = MSVIDEO_GetHicPtr(HIC_32(hic)); - if (whic) + if ((thunk = MSVIDEO_HasThunk(hic))) { - /* we've got a 16 bit driver proc... call it directly */ - if (whic->driverproc16) - { - WORD args[8]; - DWORD result; + WORD args[8]; + DWORD result; - /* FIXME: original code was passing hdrv first and hic second */ - /* but this doesn't match what IC_Callback3216 does */ - args[7] = HIWORD(hic); - args[6] = LOWORD(hic); - args[5] = HDRVR_16(whic->hdrv); - args[4] = msg; - args[3] = HIWORD(lParam1); - args[2] = LOWORD(lParam1); - args[1] = HIWORD(lParam2); - args[0] = LOWORD(lParam2); - WOWCallback16Ex( whic->driverproc16, WCB16_PASCAL, sizeof(args), args, &result ); - ret = result; - } - else - { - /* map the message for a 32 bit infrastructure, and pass it along */ - void* data16 = MSVIDEO_MapMsg16To32(msg, &lParam1, &lParam2); - - ret = MSVIDEO_SendMessage(whic, msg, lParam1, lParam2); - if (data16) - MSVIDEO_UnmapMsg16To32(msg, data16, &lParam1, &lParam2); - } + /* FIXME: original code was passing hdrv first and hic second */ + /* but this doesn't match what IC_Callback3216 does */ + args[7] = HIWORD(hic); + args[6] = LOWORD(hic); + args[5] = 0; /* the 32bit also sets it to NULL */ + args[4] = msg; + args[3] = HIWORD(lParam1); + args[2] = LOWORD(lParam1); + args[1] = HIWORD(lParam2); + args[0] = LOWORD(lParam2); + WOWCallback16Ex( thunk->pfn16, WCB16_PASCAL, sizeof(args), args, &result ); + ret = result; } + else + { + /* map the message for a 32 bit infrastructure, and pass it along */ + void* data16 = MSVIDEO_MapMsg16To32(msg, &lParam1, &lParam2); + + ret = ICSendMessage(HIC_32(hic), msg, lParam1, lParam2); + if (data16) + MSVIDEO_UnmapMsg16To32(msg, data16, &lParam1, &lParam2); + } + return ret; +} + +/*********************************************************************** + * ICClose [MSVIDEO.204] + */ +LRESULT WINAPI ICClose16(HIC16 hic) +{ + BOOL ret = ICClose(HIC_32(hic)); + + EnterCriticalSection(&msvideo_cs); + if (ret) + { + struct msvideo_thunk* thunk; + if ((thunk = MSVIDEO_HasThunk(hic))) + { + thunk->pfn16 = 0; + thunk->hIC16 = 0; + } + else ret = FALSE; + } + LeaveCriticalSection(&msvideo_cs); return ret; } @@ -863,32 +945,6 @@ DWORD WINAPI VideoCapDriverDescAndVer16(WORD nr, LPSTR buf1, WORD buf1len, return 0; } -/****************************************************************** - * IC_CallTo16 - * - * - */ -static LRESULT CALLBACK IC_CallTo16(HDRVR hdrv, HIC hic, UINT msg, LPARAM lp1, LPARAM lp2) -{ -#if 0 - WINE_HIC* whic = IC_GetPtr(hic); - LRESULT ret = 0; - - - if (whic->driverproc) - { - ret = whic->driverproc(hic, whic->hdrv, msg, lParam1, lParam2); - } - else - { - ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2); - } -#else - FIXME("No 32=>16 conversion yet\n"); -#endif - return 0; -} - /************************************************************************** * DllEntryPoint (MSVIDEO.3) * @@ -901,12 +957,8 @@ BOOL WINAPI VIDEO_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds, switch (fdwReason) { case DLL_PROCESS_ATTACH: - /* hook in our 16 bit management functions */ - pFnCallTo16 = IC_CallTo16; break; case DLL_PROCESS_DETACH: - /* remove our 16 bit management functions */ - pFnCallTo16 = NULL; break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: diff --git a/dlls/msvfw32/msvideo_main.c b/dlls/msvfw32/msvideo_main.c index 962d6efe95f..7c98a1613c9 100644 --- a/dlls/msvfw32/msvideo_main.c +++ b/dlls/msvfw32/msvideo_main.c @@ -53,8 +53,6 @@ static inline const char *wine_dbgstr_fcc( DWORD fcc ) LOBYTE(HIWORD(fcc)), HIBYTE(HIWORD(fcc))); } -LRESULT (CALLBACK *pFnCallTo16)(HDRVR, HIC, UINT, LPARAM, LPARAM) = NULL; - static WINE_HIC* MSVIDEO_FirstHic /* = NULL */; typedef struct _reg_driver reg_driver; @@ -327,7 +325,7 @@ HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) if (driver && driver->proc) /* The driver has been registered at runtime with its driverproc */ - return MSVIDEO_OpenFunction(fccType, fccHandler, wMode, driver->proc, 0); + return ICOpenFunction(fccType, fccHandler, wMode, driver->proc); /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the * same layout as ICOPEN @@ -360,9 +358,10 @@ HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) } bIs16 = GetDriverFlags(hdrv) & 0x10000000; /* undocumented flag: WINE_GDF_16BIT */ - if (bIs16 && !pFnCallTo16) + if (bIs16) { FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n"); + CloseDriver(hdrv, 0, 0); return 0; } whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC)); @@ -372,13 +371,11 @@ HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) return FALSE; } whic->hdrv = hdrv; - /* FIXME: is the signature the real one ? */ - whic->driverproc = bIs16 ? (DRIVERPROC)pFnCallTo16 : NULL; - whic->driverproc16 = 0; + whic->driverproc = NULL; whic->type = fccType; whic->handler = fccHandler; - while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++; - whic->hic = HIC_32(IC_HandleRef++); + while (MSVIDEO_GetHicPtr((HIC)(ULONG_PTR)IC_HandleRef) != NULL) IC_HandleRef++; + whic->hic = (HIC)(ULONG_PTR)IC_HandleRef++; whic->next = MSVIDEO_FirstHic; MSVIDEO_FirstHic = whic; @@ -387,16 +384,15 @@ HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) } /*********************************************************************** - * MSVIDEO_OpenFunction + * ICOpenFunction [MSVFW32.@] */ -HIC MSVIDEO_OpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, - DRIVERPROC lpfnHandler, DWORD lpfnHandler16) +HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler) { ICOPEN icopen; WINE_HIC* whic; - TRACE("(%s,%s,%d,%p,%08x)\n", - wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode, lpfnHandler, lpfnHandler16); + TRACE("(%s,%s,%d,%p)\n", + wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode, lpfnHandler); icopen.dwSize = sizeof(ICOPEN); icopen.fccType = fccType; @@ -412,9 +408,8 @@ HIC MSVIDEO_OpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, if (!whic) return 0; whic->driverproc = lpfnHandler; - whic->driverproc16 = lpfnHandler16; - while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++; - whic->hic = HIC_32(IC_HandleRef++); + while (MSVIDEO_GetHicPtr((HIC)(ULONG_PTR)IC_HandleRef) != NULL) IC_HandleRef++; + whic->hic = (HIC)(ULONG_PTR)IC_HandleRef++; whic->next = MSVIDEO_FirstHic; MSVIDEO_FirstHic = whic; @@ -447,14 +442,6 @@ HIC MSVIDEO_OpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, return whic->hic; } -/*********************************************************************** - * ICOpenFunction [MSVFW32.@] - */ -HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler) -{ - return MSVIDEO_OpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)lpfnHandler, 0); -} - /*********************************************************************** * ICGetInfo [MSVFW32.@] */ diff --git a/dlls/msvfw32/msvideo_private.h b/dlls/msvfw32/msvideo_private.h index 6bd8e936463..d1e5f8d0d65 100644 --- a/dlls/msvfw32/msvideo_private.h +++ b/dlls/msvfw32/msvideo_private.h @@ -36,26 +36,12 @@ typedef struct tagWINE_HIC { WORD x2; /* 20: */ DWORD x3; /* 22: */ /* 26: */ - DWORD driverproc16; /* Wine specific flags */ HIC hic; DWORD driverId; struct tagWINE_HIC* next; } WINE_HIC; -HIC MSVIDEO_OpenFunction(DWORD, DWORD, UINT, DRIVERPROC, DWORD); LRESULT MSVIDEO_SendMessage(WINE_HIC*, UINT, DWORD_PTR, DWORD_PTR); -WINE_HIC* MSVIDEO_GetHicPtr(HIC); - -extern LRESULT (CALLBACK *pFnCallTo16)(HDRVR, HIC, UINT, LPARAM, LPARAM); - -/* handle16 --> handle conversions */ -#define HDRAWDIB_32(h16) ((HDRAWDIB)(ULONG_PTR)(h16)) -#define HIC_32(h16) ((HIC)(ULONG_PTR)(h16)) - -/* handle --> handle16 conversions */ -#define HDRVR_16(h32) (LOWORD(h32)) -#define HDRAWDIB_16(h32) (LOWORD(h32)) -#define HIC_16(h32) (LOWORD(h32)) #define IDC_CONFIGURE 882 #define IDC_ABOUT 883