/* * msvideo 16-bit functions * * Copyright 1998 Marcus Meissner * Copyright 2000 Bradley Baetz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include "windef.h" #include "winbase.h" #include "winver.h" #include "winnls.h" #include "winreg.h" #include "winternl.h" #include "winuser.h" #include "wine/winbase16.h" #include "wownt32.h" #include "vfw16.h" #include "wine/debug.h" 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] */ HDRAWDIB16 VFWAPI DrawDibOpen16(void) { return HDRAWDIB_16(DrawDibOpen()); } /*********************************************************************** * DrawDibClose [MSVIDEO.103] */ BOOL16 VFWAPI DrawDibClose16(HDRAWDIB16 hdd) { return DrawDibClose(HDRAWDIB_32(hdd)); } /************************************************************************ * DrawDibBegin [MSVIDEO.104] */ BOOL16 VFWAPI DrawDibBegin16(HDRAWDIB16 hdd, HDC16 hdc, INT16 dxDst, INT16 dyDst, LPBITMAPINFOHEADER lpbi, INT16 dxSrc, INT16 dySrc, UINT16 wFlags) { return DrawDibBegin(HDRAWDIB_32(hdd), HDC_32(hdc), dxDst, dyDst, lpbi, dxSrc, dySrc, wFlags); } /*********************************************************************** * DrawDibEnd [MSVIDEO.105] */ BOOL16 VFWAPI DrawDibEnd16(HDRAWDIB16 hdd) { return DrawDibEnd(HDRAWDIB_32(hdd)); } /********************************************************************** * DrawDibDraw [MSVIDEO.106] */ BOOL16 VFWAPI DrawDibDraw16(HDRAWDIB16 hdd, HDC16 hdc, INT16 xDst, INT16 yDst, INT16 dxDst, INT16 dyDst, LPBITMAPINFOHEADER lpbi, LPVOID lpBits, INT16 xSrc, INT16 ySrc, INT16 dxSrc, INT16 dySrc, UINT16 wFlags) { return DrawDibDraw(HDRAWDIB_32(hdd), HDC_32(hdc), xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags); } /*********************************************************************** * DrawDibGetPalette [MSVIDEO.108] */ HPALETTE16 VFWAPI DrawDibGetPalette16(HDRAWDIB16 hdd) { return HPALETTE_16(DrawDibGetPalette(HDRAWDIB_32(hdd))); } /*********************************************************************** * DrawDibSetPalette [MSVIDEO.110] */ BOOL16 VFWAPI DrawDibSetPalette16(HDRAWDIB16 hdd, HPALETTE16 hpal) { return DrawDibSetPalette(HDRAWDIB_32(hdd), HPALETTE_32(hpal)); } /*********************************************************************** * DrawDibRealize [MSVIDEO.112] */ UINT16 VFWAPI DrawDibRealize16(HDRAWDIB16 hdd, HDC16 hdc, BOOL16 fBackground) { return (UINT16)DrawDibRealize(HDRAWDIB_32(hdd), HDC_32(hdc), fBackground); } /************************************************************************* * DrawDibProfileDisplay [MSVIDEO.114] */ BOOL16 VFWAPI DrawDibProfileDisplay16(LPBITMAPINFOHEADER lpbi) { TRACE("(%p)\n", lpbi); return DrawDibProfileDisplay(lpbi); } /************************************************************************* * DrawDibStart [MSVIDEO.118] */ BOOL16 VFWAPI DrawDibStart16(HDRAWDIB16 hdd, DWORD rate) { return DrawDibStart(HDRAWDIB_32(hdd), rate); } /************************************************************************* * DrawDibStop [MSVIDEO.119] */ BOOL16 VFWAPI DrawDibStop16(HDRAWDIB16 hdd) { return DrawDibStop(HDRAWDIB_32(hdd)); } /*********************************************************************** * ICOpen [MSVIDEO.203] */ HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode) { return HIC_16(ICOpen(fccType, fccHandler, wMode)); } /*********************************************************************** * _ICMessage [MSVIDEO.207] */ LRESULT VFWAPIV ICMessage16( HIC16 hic, UINT16 msg, UINT16 cb, VA_LIST16 valist ) { LPWORD lpData; SEGPTR segData; LRESULT ret; UINT16 i; lpData = HeapAlloc(GetProcessHeap(), 0, cb); TRACE("0x%08x, %u, %u, ...)\n", (DWORD) hic, msg, cb); for (i = 0; i < cb / sizeof(WORD); i++) { lpData[i] = VA_ARG16(valist, WORD); } segData = MapLS(lpData); ret = ICSendMessage16(hic, msg, segData, (DWORD) cb); UnMapLS(segData); HeapFree(GetProcessHeap(), 0, lpData); return ret; } /*********************************************************************** * ICGetInfo [MSVIDEO.212] */ LRESULT VFWAPI ICGetInfo16(HIC16 hic, ICINFO16 * picinfo, DWORD cb) { LRESULT ret; TRACE("(0x%08x,%p,%d)\n", (DWORD) hic, picinfo, cb); ret = ICSendMessage16(hic, ICM_GETINFO, (DWORD) picinfo, cb); TRACE(" -> 0x%08lx\n", ret); return ret; } /*********************************************************************** * ICLocate [MSVIDEO.213] */ HIC16 VFWAPI ICLocate16(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut, WORD wFlags) { return HIC_16(ICLocate(fccType, fccHandler, lpbiIn, lpbiOut, wFlags)); } /*********************************************************************** * _ICCompress [MSVIDEO.224] */ DWORD VFWAPIV ICCompress16(HIC16 hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiOutput, LPVOID lpData, LPBITMAPINFOHEADER lpbiInput, LPVOID lpBits, LPDWORD lpckid, LPDWORD lpdwFlags, LONG lFrameNum, DWORD dwFrameSize, DWORD dwQuality, LPBITMAPINFOHEADER lpbiPrev, LPVOID lpPrev) { DWORD ret; ICCOMPRESS iccmp; SEGPTR seg_iccmp; TRACE("(0x%08x,%d,%p,%p,%p,%p,...)\n", (DWORD) hic, dwFlags, lpbiOutput, lpData, lpbiInput, lpBits); iccmp.dwFlags = dwFlags; iccmp.lpbiOutput = lpbiOutput; iccmp.lpOutput = lpData; iccmp.lpbiInput = lpbiInput; iccmp.lpInput = lpBits; iccmp.lpckid = lpckid; iccmp.lpdwFlags = lpdwFlags; iccmp.lFrameNum = lFrameNum; iccmp.dwFrameSize = dwFrameSize; iccmp.dwQuality = dwQuality; iccmp.lpbiPrev = lpbiPrev; iccmp.lpPrev = lpPrev; seg_iccmp = MapLS(&iccmp); ret = ICSendMessage16(hic, ICM_COMPRESS, seg_iccmp, sizeof(ICCOMPRESS)); UnMapLS(seg_iccmp); return ret; } /*********************************************************************** * _ICDecompress [MSVIDEO.230] */ DWORD VFWAPIV ICDecompress16(HIC16 hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiFormat, LPVOID lpData, LPBITMAPINFOHEADER lpbi, LPVOID lpBits) { ICDECOMPRESS icd; SEGPTR segptr; DWORD ret; TRACE("(0x%08x,%d,%p,%p,%p,%p)\n", (DWORD) hic, dwFlags, lpbiFormat, lpData, lpbi, lpBits); icd.dwFlags = dwFlags; icd.lpbiInput = lpbiFormat; icd.lpInput = lpData; icd.lpbiOutput = lpbi; icd.lpOutput = lpBits; icd.ckid = 0; segptr = MapLS(&icd); ret = ICSendMessage16(hic, ICM_DECOMPRESS, segptr, sizeof(ICDECOMPRESS)); UnMapLS(segptr); return ret; } /*********************************************************************** * _ICDrawBegin [MSVIDEO.232] */ DWORD VFWAPIV ICDrawBegin16(HIC16 hic, /* [in] */ DWORD dwFlags, /* [in] flags */ HPALETTE16 hpal, /* [in] palette to draw with */ HWND16 hwnd, /* [in] window to draw to */ HDC16 hdc, /* [in] HDC to draw to */ INT16 xDst, /* [in] destination rectangle */ INT16 yDst, /* [in] */ INT16 dxDst, /* [in] */ INT16 dyDst, /* [in] */ LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw NOTE: SEGPTR */ INT16 xSrc, /* [in] source rectangle */ INT16 ySrc, /* [in] */ INT16 dxSrc, /* [in] */ INT16 dySrc, /* [in] */ DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */ DWORD dwScale) /* [in] */ { DWORD ret; ICDRAWBEGIN16 icdb; SEGPTR seg_icdb; TRACE ("(0x%08x,%d,0x%08x,0x%08x,0x%08x,%u,%u,%u,%u,%p,%u,%u,%u,%u,%d,%d)\n", (DWORD) hic, dwFlags, (DWORD) hpal, (DWORD) hwnd, (DWORD) hdc, xDst, yDst, dxDst, dyDst, lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale); icdb.dwFlags = dwFlags; icdb.hpal = hpal; icdb.hwnd = hwnd; icdb.hdc = hdc; icdb.xDst = xDst; icdb.yDst = yDst; icdb.dxDst = dxDst; icdb.dyDst = dyDst; icdb.lpbi = lpbi; /* Keep this as SEGPTR for the mapping code to deal with */ icdb.xSrc = xSrc; icdb.ySrc = ySrc; icdb.dxSrc = dxSrc; icdb.dySrc = dySrc; icdb.dwRate = dwRate; icdb.dwScale = dwScale; seg_icdb = MapLS(&icdb); ret = (DWORD) ICSendMessage16(hic, ICM_DRAW_BEGIN, seg_icdb, sizeof(ICDRAWBEGIN16)); UnMapLS(seg_icdb); return ret; } /*********************************************************************** * _ICDraw [MSVIDEO.234] */ DWORD VFWAPIV ICDraw16(HIC16 hic, DWORD dwFlags, LPVOID lpFormat, /* [???] NOTE: SEGPTR */ LPVOID lpData, /* [???] NOTE: SEGPTR */ DWORD cbData, LONG lTime) { DWORD ret; ICDRAW icd; SEGPTR seg_icd; TRACE("(0x%08x,0x%08x,%p,%p,%d,%d)\n", (DWORD) hic, dwFlags, lpFormat, lpData, cbData, lTime); icd.dwFlags = dwFlags; icd.lpFormat = lpFormat; icd.lpData = lpData; icd.cbData = cbData; icd.lTime = lTime; seg_icd = MapLS(&icd); ret = ICSendMessage16(hic, ICM_DRAW, seg_icd, sizeof(ICDRAW)); UnMapLS(seg_icd); return ret; } /*********************************************************************** * ICGetDisplayFormat [MSVIDEO.239] */ HIC16 VFWAPI ICGetDisplayFormat16(HIC16 hic, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut, INT16 depth, INT16 dx, INT16 dy) { return HIC_16(ICGetDisplayFormat(HIC_32(hic), lpbiIn, lpbiOut, depth, dx, dy)); } #define COPY(x,y) (x->y = x##16->y); #define COPYPTR(x,y) (x->y = MapSL((SEGPTR)x##16->y)); /****************************************************************** * MSVIDEO_MapICDEX16To32 * * */ static LPVOID MSVIDEO_MapICDEX16To32(LPDWORD lParam) { LPVOID ret; ICDECOMPRESSEX *icdx = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDECOMPRESSEX)); ICDECOMPRESSEX16 *icdx16 = MapSL(*lParam); ret = icdx16; COPY(icdx, dwFlags); COPYPTR(icdx, lpbiSrc); COPYPTR(icdx, lpSrc); COPYPTR(icdx, lpbiDst); COPYPTR(icdx, lpDst); COPY(icdx, xDst); COPY(icdx, yDst); COPY(icdx, dxDst); COPY(icdx, dyDst); COPY(icdx, xSrc); COPY(icdx, ySrc); COPY(icdx, dxSrc); COPY(icdx, dySrc); *lParam = (DWORD)(icdx); return ret; } /****************************************************************** * MSVIDEO_MapMsg16To32 * * */ static LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2) { LPVOID ret = 0; TRACE("Mapping %d\n", msg); switch (msg) { case DRV_LOAD: case DRV_ENABLE: case DRV_CLOSE: case DRV_DISABLE: case DRV_FREE: case ICM_ABOUT: case ICM_CONFIGURE: case ICM_COMPRESS_END: case ICM_DECOMPRESS_END: case ICM_DECOMPRESSEX_END: case ICM_SETQUALITY: case ICM_DRAW_START_PLAY: case ICM_DRAW_STOP_PLAY: case ICM_DRAW_REALIZE: case ICM_DRAW_RENDERBUFFER: case ICM_DRAW_END: break; case DRV_OPEN: case ICM_GETDEFAULTQUALITY: case ICM_GETQUALITY: case ICM_SETSTATE: case ICM_DRAW_WINDOW: case ICM_GETBUFFERSWANTED: *lParam1 = (DWORD)MapSL(*lParam1); break; case ICM_GETINFO: { ICINFO *ici = HeapAlloc(GetProcessHeap(), 0, sizeof(ICINFO)); ICINFO16 *ici16; ici16 = MapSL(*lParam1); ret = ici16; ici->dwSize = sizeof(ICINFO); COPY(ici, fccType); COPY(ici, fccHandler); COPY(ici, dwFlags); COPY(ici, dwVersion); COPY(ici, dwVersionICM); MultiByteToWideChar( CP_ACP, 0, ici16->szName, -1, ici->szName, 16 ); MultiByteToWideChar( CP_ACP, 0, ici16->szDescription, -1, ici->szDescription, 128 ); MultiByteToWideChar( CP_ACP, 0, ici16->szDriver, -1, ici->szDriver, 128 ); *lParam1 = (DWORD)(ici); *lParam2 = sizeof(ICINFO); } break; case ICM_COMPRESS: { ICCOMPRESS *icc = HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS)); ICCOMPRESS *icc16; icc16 = MapSL(*lParam1); ret = icc16; COPY(icc, dwFlags); COPYPTR(icc, lpbiOutput); COPYPTR(icc, lpOutput); COPYPTR(icc, lpbiInput); COPYPTR(icc, lpInput); COPYPTR(icc, lpckid); COPYPTR(icc, lpdwFlags); COPY(icc, lFrameNum); COPY(icc, dwFrameSize); COPY(icc, dwQuality); COPYPTR(icc, lpbiPrev); COPYPTR(icc, lpPrev); *lParam1 = (DWORD)(icc); *lParam2 = sizeof(ICCOMPRESS); } break; case ICM_DECOMPRESS: { ICDECOMPRESS *icd = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDECOMPRESS)); ICDECOMPRESS *icd16; /* Same structure except for the pointers */ icd16 = MapSL(*lParam1); ret = icd16; COPY(icd, dwFlags); COPYPTR(icd, lpbiInput); COPYPTR(icd, lpInput); COPYPTR(icd, lpbiOutput); COPYPTR(icd, lpOutput); COPY(icd, ckid); *lParam1 = (DWORD)(icd); *lParam2 = sizeof(ICDECOMPRESS); } break; case ICM_COMPRESS_BEGIN: case ICM_COMPRESS_GET_FORMAT: case ICM_COMPRESS_GET_SIZE: case ICM_COMPRESS_QUERY: case ICM_DECOMPRESS_GET_FORMAT: case ICM_DECOMPRESS_QUERY: case ICM_DECOMPRESS_BEGIN: case ICM_DECOMPRESS_SET_PALETTE: case ICM_DECOMPRESS_GET_PALETTE: *lParam1 = (DWORD)MapSL(*lParam1); *lParam2 = (DWORD)MapSL(*lParam2); break; case ICM_DECOMPRESSEX_QUERY: if ((*lParam2 != sizeof(ICDECOMPRESSEX16)) && (*lParam2 != 0)) WARN("*lParam2 has unknown value %p\n", (ICDECOMPRESSEX16*)*lParam2); /* FIXME: *lParm2 is meant to be 0 or an ICDECOMPRESSEX16*, but is sizeof(ICDECOMRPESSEX16) * This is because of ICMessage(). Special case it? { LPVOID* addr = HeapAlloc(GetProcessHeap(), 0, 2*sizeof(LPVOID)); addr[0] = MSVIDEO_MapICDEX16To32(lParam1); if (*lParam2) addr[1] = MSVIDEO_MapICDEX16To32(lParam2); else addr[1] = 0; ret = addr; } break;*/ case ICM_DECOMPRESSEX_BEGIN: case ICM_DECOMPRESSEX: ret = MSVIDEO_MapICDEX16To32(lParam1); *lParam2 = sizeof(ICDECOMPRESSEX); break; case ICM_DRAW_BEGIN: { ICDRAWBEGIN *icdb = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAWBEGIN)); ICDRAWBEGIN16 *icdb16 = MapSL(*lParam1); ret = icdb16; COPY(icdb, dwFlags); icdb->hpal = HPALETTE_32(icdb16->hpal); icdb->hwnd = HWND_32(icdb16->hwnd); icdb->hdc = HDC_32(icdb16->hdc); COPY(icdb, xDst); COPY(icdb, yDst); COPY(icdb, dxDst); COPY(icdb, dyDst); COPYPTR(icdb, lpbi); COPY(icdb, xSrc); COPY(icdb, ySrc); COPY(icdb, dxSrc); COPY(icdb, dySrc); COPY(icdb, dwRate); COPY(icdb, dwScale); *lParam1 = (DWORD)(icdb); *lParam2 = sizeof(ICDRAWBEGIN); } break; case ICM_DRAW_SUGGESTFORMAT: { ICDRAWSUGGEST *icds = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAWSUGGEST)); ICDRAWSUGGEST16 *icds16 = MapSL(*lParam1); ret = icds16; COPY(icds, dwFlags); COPYPTR(icds, lpbiIn); COPYPTR(icds, lpbiSuggest); COPY(icds, dxSrc); COPY(icds, dySrc); COPY(icds, dxDst); COPY(icds, dyDst); icds->hicDecompressor = HIC_32(icds16->hicDecompressor); *lParam1 = (DWORD)(icds); *lParam2 = sizeof(ICDRAWSUGGEST); } break; case ICM_DRAW: { ICDRAW *icd = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAW)); ICDRAW *icd16 = MapSL(*lParam1); ret = icd16; COPY(icd, dwFlags); COPYPTR(icd, lpFormat); COPYPTR(icd, lpData); COPY(icd, cbData); COPY(icd, lTime); *lParam1 = (DWORD)(icd); *lParam2 = sizeof(ICDRAW); } break; case ICM_DRAW_START: case ICM_DRAW_STOP: break; default: FIXME("%d is not yet handled. Expect a crash.\n", msg); } return ret; } #undef COPY #undef COPYPTR /****************************************************************** * MSVIDEO_UnmapMsg16To32 * * */ static void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID data16, LPDWORD lParam1, LPDWORD lParam2) { TRACE("Unmapping %d\n", msg); #define UNCOPY(x, y) (x##16->y = x->y); switch (msg) { case ICM_GETINFO: { ICINFO *ici = (ICINFO*)(*lParam1); ICINFO16 *ici16 = data16; UNCOPY(ici, fccType); UNCOPY(ici, fccHandler); UNCOPY(ici, dwFlags); UNCOPY(ici, dwVersion); UNCOPY(ici, dwVersionICM); WideCharToMultiByte( CP_ACP, 0, ici->szName, -1, ici16->szName, sizeof(ici16->szName), NULL, NULL ); ici16->szName[sizeof(ici16->szName)-1] = 0; WideCharToMultiByte( CP_ACP, 0, ici->szDescription, -1, ici16->szDescription, sizeof(ici16->szDescription), NULL, NULL ); ici16->szDescription[sizeof(ici16->szDescription)-1] = 0; /* This just gives garbage for some reason - BB lstrcpynWtoA(ici16->szDriver, ici->szDriver, 128);*/ HeapFree(GetProcessHeap(), 0, ici); } break; case ICM_DECOMPRESS_QUERY: /*{ LPVOID* x = data16; HeapFree(GetProcessHeap(), 0, x[0]); if (x[1]) HeapFree(GetProcessHeap(), 0, x[1]); } break;*/ case ICM_COMPRESS: case ICM_DECOMPRESS: case ICM_DECOMPRESSEX_QUERY: case ICM_DECOMPRESSEX_BEGIN: case ICM_DECOMPRESSEX: case ICM_DRAW_BEGIN: case ICM_DRAW_SUGGESTFORMAT: case ICM_DRAW: HeapFree(GetProcessHeap(), 0, data16); break; default: ERR("Unmapping unmapped msg %d\n", msg); } #undef UNCOPY } /*********************************************************************** * ICInfo [MSVIDEO.200] */ BOOL16 VFWAPI ICInfo16(DWORD fccType, DWORD fccHandler, ICINFO16 *lpicinfo) { BOOL16 ret; LPVOID lpv; DWORD lParam = (DWORD)lpicinfo; DWORD size = ((ICINFO*)(MapSL((SEGPTR)lpicinfo)))->dwSize; /* Use the mapping functions to map the ICINFO structure */ lpv = MSVIDEO_MapMsg16To32(ICM_GETINFO, &lParam, &size); ret = ICInfo(fccType, fccHandler, (ICINFO*)lParam); MSVIDEO_UnmapMsg16To32(ICM_GETINFO, lpv, &lParam, &size); return ret; } /****************************************************************** * IC_Callback3216 * * */ static LRESULT CALLBACK IC_Callback3216(DWORD pfn16, HIC hic, HDRVR hdrv, UINT msg, LPARAM lp1, LPARAM lp2) { WORD args[8]; 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(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 #include "pshpack1.h" 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; #include "poppack.h" 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; if (!MSVIDEO_Thunks) return NULL; for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++) { if (thunk->hIC16 == hic) return thunk; } return NULL; } /*********************************************************************** * ICOpenFunction [MSVIDEO.206] */ HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler) { HIC hic32; struct msvideo_thunk* thunk; EnterCriticalSection(&msvideo_cs); if (!(thunk = MSVIDEO_AddThunk((DWORD)lpfnHandler))) { LeaveCriticalSection(&msvideo_cs); return 0; } if ((hic32 = ICOpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)thunk))) thunk->hIC16 = HIC_16(hic32); else thunk->pfn16 = 0; LeaveCriticalSection(&msvideo_cs); return HIC_16(hic32); } /*********************************************************************** * ICSendMessage [MSVIDEO.205] */ LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2) { LRESULT ret = ICERR_BADHANDLE; struct msvideo_thunk* thunk; if ((thunk = MSVIDEO_HasThunk(hic))) { 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] = 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; } /*********************************************************************** * VideoCapDriverDescAndVer [MSVIDEO.22] */ DWORD WINAPI VideoCapDriverDescAndVer16(WORD nr, LPSTR buf1, WORD buf1len, LPSTR buf2, WORD buf2len) { static const char version_info_spec[] = "\\StringFileInfo\\040904E4\\FileDescription"; DWORD verhandle; DWORD infosize; UINT subblocklen; char *s, buf[2048], fn[260]; LPBYTE infobuf; LPVOID subblock; DWORD i, cnt = 0, lRet; DWORD bufLen, fnLen; FILETIME lastWrite; HKEY hKey; BOOL found = FALSE; TRACE("(%d,%p,%d,%p,%d)\n", nr, buf1, buf1len, buf2, buf2len); lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, HKLM_DRIVERS32, 0, KEY_QUERY_VALUE, &hKey); if (lRet == ERROR_SUCCESS) { RegQueryInfoKeyA( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0); for (i = 0; i < cnt; i++) { bufLen = ARRAY_SIZE(buf); lRet = RegEnumKeyExA(hKey, i, buf, &bufLen, 0, 0, 0, &lastWrite); if (lRet != ERROR_SUCCESS) continue; if (_strnicmp(buf, "vid", 3)) continue; if (nr--) continue; fnLen = sizeof(fn); lRet = RegQueryValueExA(hKey, buf, 0, 0, (LPBYTE)fn, &fnLen); if (lRet == ERROR_SUCCESS) found = TRUE; break; } RegCloseKey( hKey ); } /* search system.ini if not found in the registry */ if (!found && GetPrivateProfileStringA("drivers32", NULL, NULL, buf, sizeof(buf), "system.ini")) { for (s = buf; *s; s += strlen(s) + 1) { if (_strnicmp(s, "vid", 3)) continue; if (nr--) continue; if (GetPrivateProfileStringA("drivers32", s, NULL, fn, sizeof(fn), "system.ini")) found = TRUE; break; } } if (!found) { TRACE("No more VID* entries found nr=%d\n", nr); return 20; } infosize = GetFileVersionInfoSizeA(fn, &verhandle); if (!infosize) { TRACE("%s has no fileversioninfo.\n", fn); return 18; } infobuf = HeapAlloc(GetProcessHeap(), 0, infosize); if (GetFileVersionInfoA(fn, verhandle, infosize, infobuf)) { /* Yes, two space behind : */ /* FIXME: test for buflen */ snprintf(buf2, buf2len, "Version: %d.%d.%d.%d\n", ((WORD*)infobuf)[0x0f], ((WORD*)infobuf)[0x0e], ((WORD*)infobuf)[0x11], ((WORD*)infobuf)[0x10] ); TRACE("version of %s is %s\n", fn, buf2); } else { TRACE("GetFileVersionInfoA failed for %s.\n", fn); lstrcpynA(buf2, fn, buf2len); /* msvideo.dll appears to copy fn*/ } /* FIXME: language problem? */ if (VerQueryValueA( infobuf, version_info_spec, &subblock, &subblocklen )) { UINT copylen = min(subblocklen,buf1len-1); memcpy(buf1, subblock, copylen); buf1[copylen] = '\0'; TRACE("VQA returned %s\n", (LPCSTR)subblock); } else { TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n"); lstrcpynA(buf1, fn, buf1len); /* msvideo.dll appears to copy fn*/ } HeapFree(GetProcessHeap(), 0, infobuf); return 0; } /************************************************************************** * DllEntryPoint (MSVIDEO.3) * * MSVIDEO DLL entry point * */ BOOL WINAPI VIDEO_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds, WORD wHeapSize, DWORD dwReserved1, WORD wReserved2) { switch (fdwReason) { case DLL_PROCESS_ATTACH: break; case DLL_PROCESS_DETACH: DeleteCriticalSection(&msvideo_cs); break; } return TRUE; } /*********************************************************************** * MCIWndRegisterClass(MSVIDEO.251) */ BOOL CDECL MCIWndRegisterClass16(void) { return MCIWndRegisterClass(); } static LRESULT (WINAPI *pMCIWndProc)(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); static LRESULT WINAPI MCIWndProc16(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case MCIWNDM_SENDSTRINGA: case MCIWNDM_SETTIMEFORMATA: lparam = (ULONG_PTR)MapSL(lparam); break; default: break; } return CallWindowProcA(pMCIWndProc, hwnd, msg, wparam, lparam); } /*********************************************************************** * MCIWndCreate(MSVIDEO.250) */ HWND16 CDECL MCIWndCreate16(HWND16 parent, HINSTANCE16 hinst16, DWORD style, LPSTR file) { HWND hwnd = MCIWndCreateA(HWND_32(parent), 0, style, file); if (hwnd) pMCIWndProc = (void *)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)MCIWndProc16); return HWND_16(hwnd); }