//==========================================================================; // COMMENTS DO NOT YET APPLY TO MSVIDEO.DLL/MSVFW32.DLL // thunk.c // // Copyright (c) 1991-1994 Microsoft Corporation. All Rights Reserved. // // Description: // This module contains routines for thunking the // ICM APIs (messages) from 16-bit Windows to 32-bit WOW. // // History: // //==========================================================================; // This stuff is not going to work 64-bit #pragma warning(disable:4312) /* WOW Thunking design: Thunks are generated as follows : 16-bit : acmBootDrivers->acmInitThunks : Generate calls to 32-bit drivers if we're in WOW call across to KERNEL to find thunking entry points. If we're thunking 'load' all the 32-bit ACM drivers as well as the 16-bit ones. Priority is always to find a 32-bit driver first but this is done via searching for one on open. The internal flag ACM_DRIVERADDF_32BIT is specified when calling IDriverAdd and this flag is stored in the ACMDRIVERID structure. IDriverAdd->IDriverLoad->IDriverLoad32 The 16-bit side calls the 32-bit side passing in the driver alias which is used to compare against the aliases on the 32 bit side and the 32-bit HACMDRIVERID is passed back for the relevant driver and stored in the hdrvr field of the ACMDRIVERID structure. IDriverOpen->IDriverOpen32 The parameters are passed to the 32-bit side using the hdrvr field deduced from the HACMDRIVERID as the 32-bit HACMDRIVERID. IDriverMessageId->IDriverMessageId32 : If the driver is 32-bit (as identified in the ACMDRIVERID structure) then call IDriverMessageId32. The hadid for the 32-bit driver is stored in the hdrvr field of ACMDRIVERID on the 16-bit side. IDriverMessage->IDriverMessage32 If the driver is 32-bit (as identified in the ACMDRIVERID structure pointed to by the ACMDRIVER structure) then call IDriverMessage32. The had for the 32-bit driver is stored in the hdrvr field of ACMDRIVER on the 16-bit side. Stream headers These must be persistent on the 32-bit side too and kept in synch. They are allocated on the 32-bit side for ACMDM_STREAM_PREPARE and freed on ACMDM_STREAM_UNPREPARE. While in existence the 32-bit stream header is stored in the dwDriver field in */ //==========================================================================; #define _INC_COMPMAN #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #ifdef DAYTONA #include #endif #include // for mbstowcs and wcstombs #endif // _WIN32 #ifdef _WIN32 #include "compmn16.h" #endif #include "compmani.h" #include "thunk.h" #include "debug.h" #ifdef NT_THUNK32 //==========================================================================; // // // --- === 32 BIT SIDE === --- // // //==========================================================================; /* ------------------------------------------------------------------------- ** Handle and memory mapping functions. ** ------------------------------------------------------------------------- */ LPWOWHANDLE32 lpWOWHandle32; LPWOWHANDLE16 lpWOWHandle16; LPGETVDMPOINTER GetVDMPointer; LPWOWCALLBACK16 lpWOWCallback16; int ThunksInitialized; // // These wrap around whatever mapping mechanism is used on the platform // we are compiling for. // INLINE PVOID ptrFixMap16To32(const VOID * pv, DWORD cb); INLINE VOID ptrUnFix16(const VOID * pv); #ifdef CHICAGO // // -= Chicago implementation of memory mapping functions =- // // // Thunk helper routines in Chicago kernel // extern PVOID WINAPI MapSL(const VOID * pv); extern PVOID WINAPI MapSLFix(const VOID * pv); extern VOID WINAPI UnMapSLFixArray(DWORD dwCnt, const VOID * lpSels[]); PVOID INLINE ptrFixMap16To32(const VOID * pv, DWORD cb) { return MapSLFix(pv); } VOID INLINE ptrUnFix16(const VOID * pv) { UnMapSLFixArray(1, &pv); } #else // CHICAGO ELSE // // -= Daytona implementation of memory mapping functions =- // // Use #define to avoid having a function call #define ptrFixMap16To32(spv, cb) \ GetVDMPointer( (DWORD) (DWORD_PTR) (spv), (cb), TRUE ) //PVOID ptrFixMap16To32(const VOID * pv, DWORD cb) //{ // return GetVDMPointer( (DWORD)pv, cb, TRUE ); //} // // The unfix routine is a total noop. // We should really call WOWGetVDMPointerUnfix... // #define ptrUnFix16(spv) //VOID ptrUnFix16(const VOID * pv) //{ // return; //} #endif // !CHICAGO //--------------------------------------------------------------------------; // // // //--------------------------------------------------------------------------; // // 16-bit structures // typedef struct { DWORD dwDCISize; LPCSTR lpszDCISectionName; LPCSTR lpszDCIAliasName; } DRVCONFIGINFO16; // // Useful functions // // // CopyAlloc - allocate a new piece of memory, and copy the data in // Must use LocalFree to release the memory later // PVOID CopyAlloc(PVOID pvSrc, UINT uSize) { PVOID pvDest; pvDest = (PVOID)LocalAlloc(LMEM_FIXED, uSize); if (pvDest != NULL) { CopyMemory(pvDest, pvSrc, uSize); } return pvDest; } /* * Copy data from source to dest where source is a 32bit pointer * and dest is a 16bit pointer */ void CopyTo16Bit(LPVOID Dest16, LPVOID Src32, DWORD Length) { PVOID Dest32; if (Src32 == NULL) { return; } Dest32 = ptrFixMap16To32(Dest16, Length); CopyMemory(Dest32, Src32, Length); ptrUnFix16(Dest16); } /* * Copy data from source to dest where source is a 16bit pointer * and dest is a 32bit pointer */ void CopyTo32Bit(LPVOID Dest32, LPVOID Src16, DWORD Length) { PVOID Src32; if (Src16 == NULL) { return; } Src32 = ptrFixMap16To32(Src16, Length); CopyMemory(Dest32, Src32, Length); ptrUnFix16(Src16); } #ifdef _INC_COMPMAN /*--------------------------------------------------------------------------*\ | | | Now thunk the compman functions | | | | | | | | | \*--------------------------------------------------------------------------*/ /* * Convert ICDRAWBEGIN structures */ INLINE STATICFN void ConvertICDRAWBEGIN(ICDRAWBEGIN *DrawBegin32, LPBITMAPINFOHEADER lpBmi, DWORD dw) { ICDRAWBEGIN16 DrawBegin16; CopyTo32Bit(&DrawBegin16, (LPVOID)dw, sizeof(ICDRAWBEGIN16)); DrawBegin32->dwFlags = DrawBegin16.dwFlags; DrawBegin32->hpal = ThunkHPAL(DrawBegin16.hpal); if (DrawBegin16.dwFlags & ICDRAW_HDC) { DrawBegin32->hwnd = ThunkHWND(DrawBegin16.hwnd); DrawBegin32->hdc = ThunkHDC(DrawBegin16.hdc); } DrawBegin32->xDst = (int)DrawBegin16.xDst; DrawBegin32->yDst = (int)DrawBegin16.yDst; DrawBegin32->dxDst = (int)DrawBegin16.dxDst; DrawBegin32->dyDst = (int)DrawBegin16.dyDst; CopyTo32Bit(lpBmi, DrawBegin16.lpbi, sizeof(BITMAPINFOHEADER)); DrawBegin32->lpbi = lpBmi; DrawBegin32->xSrc = (int)DrawBegin16.xSrc; DrawBegin32->ySrc = (int)DrawBegin16.ySrc; DrawBegin32->dxSrc = (int)DrawBegin16.dxSrc; DrawBegin32->dySrc = (int)DrawBegin16.dySrc; DrawBegin32->dwRate = DrawBegin16.dwRate; DrawBegin32->dwScale = DrawBegin16.dwScale; } /* * Following logic copied from mvdm\wow32\wstruc.c - however since we * don't have the usage parameter we're a bit stuck on the size of the * entries. * * See also the video for windows documentation - only a limited range of * bitmap types are discussed. */ INT GetBMI16Size(UNALIGNED BITMAPINFOHEADER *pbmi16) { int nHdrSize; int nEntSize; int nEntries; int nBitCount; DWORD dwClrUsed; nHdrSize = (int)pbmi16->biSize; /* * We don't have some of the info we need so assume RGBQUAD */ nEntSize = sizeof(RGBQUAD); nBitCount = pbmi16->biBitCount; dwClrUsed = pbmi16->biClrUsed; /* the following block of code should be this: * * if ( nBitCount > 8 ) { // true colour * nEntries = 0; (ordinary case) * nEntries = 3; (BI_BITFIELDS case) * } * else if ( dwClrUsed ) { * nEntries = dwClrUsed; * } * else { * nEntries = 1 << nBitCount; * } * * but due to the fact that many apps don't initialize the biBitCount & * biClrUsed fields (especially biClrUsed) we have to do the following * sanity checking instead. v-cjones */ if ( nBitCount <= 8 ) { nEntries = 1 << nBitCount; // sanity check for apps (lots) that don't init the dwClrUsed field if(dwClrUsed) { nEntries = (int)min((DWORD)nEntries, dwClrUsed); } } else { if (pbmi16->biCompression == BI_BITFIELDS) nEntries = 3; else nEntries = 0; } return ( nHdrSize + (nEntries * nEntSize) ); } INLINE LPBITMAPINFO CopyBitmapInfo(DWORD Bi16) { UNALIGNED BITMAPINFOHEADER *pbmi16; LPBITMAPINFO lpbmi; pbmi16 = ptrFixMap16To32((PVOID)Bi16, 0); if ((int)pbmi16->biSize == 0) { pbmi16->biSize = sizeof(BITMAPINFOHEADER); DPF(0, "WARNING: null bitmap info size, setting it correctly"); } lpbmi = (LPBITMAPINFO)CopyAlloc((LPVOID)pbmi16, GetBMI16Size(pbmi16)); ptrUnFix16((PVOID)Bi16); return (lpbmi); } /* * Allocate a BITMAPINFO structure to contain 256 colours */ INLINE LPBITMAPINFO AllocBitmapInfo() { return (PVOID)LocalAlloc(LMEM_FIXED, sizeof(BITMAPINFOHEADER)+ (sizeof(RGBQUAD)*256)); } INLINE LPBITMAPINFOHEADER CopyBitmapInfoHeader(DWORD Bi16) { UNALIGNED BITMAPINFOHEADER *pbmi16; LPBITMAPINFOHEADER lpbmi; pbmi16 = ptrFixMap16To32((PVOID)Bi16, 0); lpbmi = (LPBITMAPINFOHEADER)CopyAlloc((LPVOID)pbmi16, pbmi16->biSize); ptrUnFix16((PVOID)Bi16); return (lpbmi); } DWORD CopyICINFOTo16bit(DWORD dw, ICINFO *IcInfoCopy, DWORD Length) { ICINFO16 IcInfo; LONG ReturnCode; /* * Make a copy since the behaviour of wcstombs is undefined * for overlapping input and output */ memcpy(&IcInfo, IcInfoCopy, FIELD_OFFSET(ICINFO, szName[0])); /* * Massage the strings */ wcstombs(IcInfo.szName, IcInfoCopy->szName, sizeof(IcInfo.szName)); // HACK : overwrite the last five characters with "[32]\0" if ((IcInfo.szName[0])) { UINT n = min(sizeof(IcInfo.szName)-5, lstrlenA(IcInfo.szName)); IcInfo.szName[n++] = '['; IcInfo.szName[n++] = '3'; IcInfo.szName[n++] = '2'; IcInfo.szName[n++] = ']'; IcInfo.szName[n] = '\0'; } wcstombs(IcInfo.szDescription, IcInfoCopy->szDescription, sizeof(IcInfo.szDescription)); // HACK : overwrite the last five characters with "[32]\0" if ((IcInfo.szDescription[0])) { UINT n = min(sizeof(IcInfo.szDescription)-5, lstrlenA(IcInfo.szDescription)); IcInfo.szDescription[n++] = '['; IcInfo.szDescription[n++] = '3'; IcInfo.szDescription[n++] = '2'; IcInfo.szDescription[n++] = ']'; IcInfo.szDescription[n] = '\0'; } wcstombs(IcInfo.szDriver, IcInfoCopy->szDriver, sizeof(IcInfo.szDriver)); IcInfo.dwSize = sizeof(IcInfo); ReturnCode = min(Length, IcInfo.dwSize); CopyTo16Bit((LPVOID)dw, &IcInfo, ReturnCode); return ReturnCode; } /* * We need to convert the various fields in the ICDECOMPRESS/EX * structure(s). Fortunately(?) the EX structure is a simple * extension. */ typedef struct { // // same as ICM_DECOMPRESS // DWORD dwFlags; LPBITMAPINFOHEADER lpbiSrc; // BITMAPINFO of compressed data LPVOID lpSrc; // compressed data LPBITMAPINFOHEADER lpbiDst; // DIB to decompress to LPVOID lpDst; // output data // // new for ICM_DECOMPRESSEX // short xDst; // destination rectangle short yDst; short dxDst; short dyDst; short xSrc; // source rectangle short ySrc; short dxSrc; short dySrc; } ICDECOMPRESSEX16; STATICFN DWORD DoICM_DecompressX(DWORD hic, UINT msg, DWORD_PTR dwP1, DWORD_PTR dwP2) { ICDECOMPRESSEX16 UNALIGNED *lpicdmpr16; ICDECOMPRESSEX ICDecompressEx; LRESULT l; BOOL fQuery = TRUE; /* Copy the standard or extended structure */ lpicdmpr16 = ptrFixMap16To32( (PVOID)dwP1, (DWORD) dwP2 ); ICDecompressEx.dwFlags = lpicdmpr16->dwFlags; ICDecompressEx.lpbiSrc = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)lpicdmpr16->lpbiSrc); if (NULL == ICDecompressEx.lpbiSrc) { ptrUnFix16( (PVOID)dwP1 ); return (DWORD)ICERR_MEMORY; } ICDecompressEx.lpbiDst = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)lpicdmpr16->lpbiDst); if ((NULL == ICDecompressEx.lpbiDst) && (msg != ICM_DECOMPRESSEX_QUERY)) { LocalFree( (HLOCAL)ICDecompressEx.lpbiSrc ); ptrUnFix16( (PVOID)dwP1 ); return (DWORD)ICERR_MEMORY; } if (msg == ICM_DECOMPRESSEX || msg == ICM_DECOMPRESS) { // map the source and destination pointers ICDecompressEx.lpSrc = ptrFixMap16To32(lpicdmpr16->lpSrc, ICDecompressEx.lpbiSrc->biSizeImage); ICDecompressEx.lpDst = ptrFixMap16To32(lpicdmpr16->lpDst, ICDecompressEx.lpbiDst->biSizeImage); fQuery = FALSE; // remember } else { // it is a query and we do not map the pointers ICDecompressEx.lpSrc = NULL; ICDecompressEx.lpDst = NULL; } if (dwP2 == sizeof(ICDECOMPRESSEX16) ) { ICDecompressEx.xDst = (int)lpicdmpr16->xDst; ICDecompressEx.yDst = (int)lpicdmpr16->yDst; ICDecompressEx.dxDst = (int)lpicdmpr16->dxDst; ICDecompressEx.dyDst = (int)lpicdmpr16->dyDst; ICDecompressEx.xSrc = (int)lpicdmpr16->xSrc; ICDecompressEx.ySrc = (int)lpicdmpr16->ySrc; ICDecompressEx.dxSrc = (int)lpicdmpr16->dxSrc; ICDecompressEx.dySrc = (int)lpicdmpr16->dySrc; dwP2 = sizeof(ICDecompressEx); // Make the size relate to 32 bit } l = ICSendMessage( (HIC)hic, (UINT)msg, (LPARAM)&ICDecompressEx, dwP2 ); /* I don't think the following is needed // FrankYe 11/18/94 // If we do, don't just uncomment this. You gotta use biUnMapSL if ( l == ICERR_OK) { CopyTo16Bit( lpicdmpr16->lpbiDst, ICDecompressEx.lpbiDst, sizeof(BITMAPINFOHEADER) ); } */ LocalFree( (HLOCAL)ICDecompressEx.lpbiSrc ); if (ICDecompressEx.lpbiDst) { LocalFree( (HLOCAL)ICDecompressEx.lpbiDst ); } if (!fQuery) { ptrUnFix16( lpicdmpr16->lpSrc ); ptrUnFix16( lpicdmpr16->lpDst ); } ptrUnFix16( (PVOID)dwP1 ); return (DWORD) l; } /* * Generate our thunks - refer to msvideo!compman.c for definitions of * functions. * * NOTE - we often rely here on the fact that most of the message * parameter structures are identical for 16 and 32-bit - ie they * contain DWORDs and 32-bit pointers. */ //--------------------------------------------------------------------------; // // LONG thkStatusProc32 // // When a client calls the 16-bit ICSetStatusProc while using a // 32-bit codec, this function is set as the StatusProc in 32-bit codec. // This function will then thunk down to 16-bits and call the // client's StatusProc. // // Arguments: // LPARAM lParam : contains linear ptr to an ICSTATUSTHUNKDESC. The // ICSTATUSTHUNKDESC is created during the call to ICSetStatusProc. // // UINT uMsg : // // LONG l : // // Return value: // LONG : // //--------------------------------------------------------------------------; LONG CALLBACK thkStatusProc32(LPARAM lParam, UINT uMsg, LONG l) { LPICSTATUSTHUNKDESC lpstd; LONG lr; DPFS(dbgThunks, 4, "thkStatusProc32()"); lpstd = (LPICSTATUSTHUNKDESC)lParam; ASSERT( lpstd->fnStatusProcS ); ASSERT( lpstd->pfnthkStatusProc16S ); lr = 0; // // TODO: Thunk error string for ICSTATUS_ERROR. Currently I'm not // sure if ICSTATUS_ERROR is documented. // //#pragma message(REMIND("thkStatusProc32: thunk ICSTATUS_ERROR")) if (ICSTATUS_ERROR == uMsg) { // // Is l supposed to be an LPSTR to an error string??? // l = (LONG)0; } // // // lpstd->uMsg = uMsg; lpstd->l = l; lr = lpWOWCallback16(lpstd->pfnthkStatusProc16S, (DWORD)lpstd->lpstdS); return (lr); } //--------------------------------------------------------------------------; // // LRESULT thkSetStatusProc // // This function is called as a result of thunking up from a call to // the 16-bit ICSetStatusProc. It will call the 32-bit ICSetStatusProc // to install thkStatusProc32. // // Arguments: // HIC hic : handle to 32-bit codec // // LPARAM lParam : contains linear ptr to an ICSTATUSTHUNKDESC. The // ICSTATUSTHUNKDESC is created in the call to the 16-bit // ICSetStatusProc. This will be set as the lParam to be passed // to our thkStatusProc32. // // Return value: // LRESULT : // //--------------------------------------------------------------------------; LRESULT WINAPI thkSetStatusProc(HIC hic, LPICSTATUSTHUNKDESC lpstd) { DPFS(dbgThunks, 3, "thkSetStatusProc()"); return ICSetStatusProc(hic, 0L, (LPARAM)lpstd, thkStatusProc32); } //--------------------------------------------------------------------------; // // // //--------------------------------------------------------------------------; LRESULT FAR PASCAL ICInfo32(DWORD fccType, DWORD fccHandler, ICINFO16 FAR * lpicInfo) { ICINFO ReturnedICInfo; StartThunk(ICInfo); //DPF2(("Calling ICInfo %4.4hs %4.4hs %8X", &fccType, &fccHandler, lpicInfo)); ReturnedICInfo.fccHandler = 0; // Initialise... ReturnCode = ICInfo(fccType, fccHandler, &ReturnedICInfo); CopyICINFOTo16bit((DWORD)(DWORD_PTR)lpicInfo, &ReturnedICInfo, sizeof(ReturnedICInfo)); EndThunk() } LRESULT FAR PASCAL ICInfoInternal32(DWORD fccType, DWORD fccHandler, ICINFO16 FAR * lpicInfo, ICINFOI FAR * lpicInfoI) { return ICInfo32(fccType, fccHandler, lpicInfo); #if 0 ICINFO ReturnedICInfo; ICINFOI ReturnedICInfoI; StartThunk(ICInfo); // DPF(1, "Calling ICInfo %4.4hs %4.4hs %8X", &fccType, &fccHandler, lpicInfo); ReturnedICInfo.fccHandler = 0; // Initialise... ReturnCode = ICInfoInternal(fccType, fccHandler, &ReturnedICInfo, &ReturnedICInfoI); if (NULL != lpicInfoI) { // // Assuming no members of ICINFOI need special thunking // CopyTo16Bit(lpicInfoI, &ReturnedICInfoI, sizeof(*lpicInfoI)); } CopyICINFOTo16bit((DWORD)(DWORD_PTR)lpicInfo, &ReturnedICInfo, sizeof(ReturnedICInfo)); EndThunk() #endif } LRESULT FAR PASCAL ICSendMessage32(DWORD hic, UINT msg, DWORD_PTR dwP1, DWORD_PTR dwP2) { StartThunk(ICSendMessage); DPF(2,"Calling ICSendMessage %4X %4X %8X %8X", hic, msg, dwP1, dwP2); switch (msg) { case ICM_GETSTATE: case ICM_SETSTATE: if (dwP1 == 0) { ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, dwP1, dwP2); } else { PVOID pState; /* * Create some aligned memory to return or pass on the data */ pState = (PVOID)LocalAlloc(LPTR, dwP2); if (pState == NULL) { ReturnCode = 0; } else { if ((UINT)msg == ICM_SETSTATE) { // Copy the data from 16 bit land CopyTo32Bit(pState, (LPVOID)dwP1, (DWORD) dwP2); } ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)pState, dwP2); /* * Copy back the state, if the driver returned any data */ if (ReturnCode > 0 && (UINT)msg == ICM_GETSTATE) { CopyTo16Bit((LPVOID)dwP1, pState, min((DWORD)ReturnCode, (DWORD) dwP2)); } LocalFree((HLOCAL)pState); } } break; case ICM_GETINFO: { ICINFO IcInfo; ReturnCode = ICGetInfo((HIC)(DWORD)hic, &IcInfo, sizeof(IcInfo)); if (ReturnCode != 0) { ReturnCode = CopyICINFOTo16bit((DWORD) (DWORD_PTR) dwP1, &IcInfo, (DWORD) ReturnCode); } } break; case ICM_CONFIGURE: case ICM_ABOUT: /* * dwP1 = -1 is a special value asking if config is supported, * otherwise it's a window handle */ ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, dwP1 == (DWORD_PTR)-1 ? (DWORD_PTR)-1 : (DWORD_PTR)ThunkHWND(LOWORD(dwP1)), dwP2); break; case ICM_COMPRESS: { if (dwP2 != sizeof(ICCOMPRESS)) { // validation code ReturnCode = ICERR_BADSIZE; } else { DWORD dwFlags; LPDWORD lpdwFlags16, lpckid16; LPBITMAPINFOHEADER lpbih16; LPVOID lpInput, lpOutput, lpPrev; DWORD ckid; ICCOMPRESS IcCompress; ReturnCode = ICERR_OK; /* * We need to convert the various fields in the ICCOMPRESS * structure */ CopyTo32Bit( &IcCompress, (LPVOID)dwP1, (DWORD) dwP2 ); IcCompress.lpbiInput = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)IcCompress.lpbiInput); if (NULL == IcCompress.lpbiInput) { ReturnCode = ICERR_MEMORY; break; } lpbih16 = IcCompress.lpbiOutput; IcCompress.lpbiOutput = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)IcCompress.lpbiOutput); if (NULL == IcCompress.lpbiOutput) { LocalFree((HLOCAL)IcCompress.lpbiInput); ReturnCode = ICERR_MEMORY; break; } lpInput = IcCompress.lpInput; IcCompress.lpInput = ptrFixMap16To32(IcCompress.lpInput, IcCompress.lpbiInput->biSizeImage); lpOutput = IcCompress.lpOutput; IcCompress.lpOutput = ptrFixMap16To32(IcCompress.lpOutput, IcCompress.lpbiOutput->biSizeImage); lpPrev = NULL; if (IcCompress.lpbiPrev) { IcCompress.lpbiPrev = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)IcCompress.lpbiPrev); if (NULL == IcCompress.lpbiPrev) { LocalFree((HLOCAL)IcCompress.lpbiOutput); LocalFree((HLOCAL)IcCompress.lpbiInput); ptrUnFix16(lpOutput); ptrUnFix16(lpInput); ReturnCode = ICERR_MEMORY; break; } lpPrev = IcCompress.lpPrev; IcCompress.lpPrev = ptrFixMap16To32(IcCompress.lpPrev, IcCompress.lpbiPrev->biSizeImage); } lpdwFlags16 = IcCompress.lpdwFlags; if (lpdwFlags16 != NULL) { CopyTo32Bit(&dwFlags, lpdwFlags16, sizeof(DWORD)); IcCompress.lpdwFlags = &dwFlags; } if (IcCompress.lpckid != NULL) { lpckid16 = IcCompress.lpckid; IcCompress.lpckid = &ckid; } ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)&IcCompress, dwP2); if (ReturnCode == ICERR_OK) { CopyTo16Bit( lpbih16, IcCompress.lpbiOutput, sizeof(BITMAPINFOHEADER) ); if (lpdwFlags16 != NULL) { CopyTo16Bit(lpdwFlags16, &dwFlags, sizeof(DWORD)); } if (IcCompress.lpckid != NULL) { CopyTo16Bit(lpckid16, &ckid, sizeof(DWORD)); } } /* ** Free the bitmap info storage regardless of the return code */ if (NULL != IcCompress.lpbiPrev) { LocalFree((HLOCAL)IcCompress.lpbiPrev); } LocalFree((HLOCAL)IcCompress.lpbiOutput); LocalFree((HLOCAL)IcCompress.lpbiInput); if (NULL != lpPrev) { ptrUnFix16(lpPrev); } ptrUnFix16(lpOutput); ptrUnFix16(lpInput); } } break; case ICM_COMPRESS_GET_SIZE: case ICM_COMPRESS_BEGIN: case ICM_COMPRESS_QUERY: case ICM_DECOMPRESS_BEGIN: case ICM_DECOMPRESS_GET_PALETTE: case ICM_DECOMPRESS_SET_PALETTE: // only takes one BitmapInfoHeader case ICM_DECOMPRESS_QUERY: { LPBITMAPINFO bmi1, bmi2; bmi1 = bmi2 = NULL; if (dwP1 != 0) { bmi1 = CopyBitmapInfo((DWORD) (DWORD_PTR) dwP1); } if (dwP2 != 0) { bmi2 = CopyBitmapInfo((DWORD) (DWORD_PTR) dwP2); } if ( (NULL == bmi1 && 0 != dwP1) || (NULL == bmi2 && 0 != dwP2) ) { if (NULL != bmi1) LocalFree((HLOCAL)bmi1); if (NULL != bmi2) LocalFree((HLOCAL)bmi2); ReturnCode = (UINT)msg == ICM_COMPRESS_GET_SIZE ? 0 : ICERR_MEMORY; } else { ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)bmi1, (DWORD_PTR)bmi2); if (bmi2 != NULL) { // We might have to return data to the 16 bit side. // The messages for which we have to do this are: // ICM_DECOMPRESS_QUERY (iff retcode == ICERR_OK) // ICM_DECOMPRESS_GET_PALETTE (iff retcode >= 0) if (((ReturnCode == ICERR_OK) && (msg == ICM_DECOMPRESS_QUERY)) || ((ReturnCode >= 0) && (msg == ICM_DECOMPRESS_GET_PALETTE))) { CopyTo16Bit((LPVOID)dwP2, bmi2, GetBMI16Size((LPBITMAPINFOHEADER)bmi2)); } LocalFree((HLOCAL)bmi2); } } if (bmi1 != NULL) { LocalFree((HLOCAL)bmi1); } } break; case ICM_COMPRESS_END: case ICM_DECOMPRESS_END: case ICM_DECOMPRESSEX_END: case ICM_DRAW_END: case ICM_DRAW_FLUSH: case ICM_DRAW_START: //?? case ICM_DRAW_STOP: //?? case ICM_DRAW_SETTIME: case ICM_DRAW_RENDERBUFFER: case ICM_SETQUALITY: ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, dwP1, dwP2); break; case ICM_DRAW_GETTIME: case ICM_GETBUFFERSWANTED: case ICM_GETDEFAULTQUALITY: case ICM_GETDEFAULTKEYFRAMERATE: case ICM_GETQUALITY: { DWORD dwReturn; ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)&dwReturn, dwP2); // Note: although the definition of these messages state // that dwParam2 is not used, trouble will brew if the // decompressor ever tries to use dwParam2. We cannot // thunk non-standard uses of this parameter. if (ReturnCode == ICERR_OK) { CopyTo16Bit((LPVOID)dwP1, &dwReturn, sizeof(DWORD)); } } break; case ICM_COMPRESS_GET_FORMAT: case ICM_DECOMPRESS_GET_FORMAT: /* * This is a tricky one - we first have to find the size of * the output format so we can get a copy of the (aligned) * version before passing it back to the app */ { LPBITMAPINFO bmi1, bmi2; if ( dwP1 == 0L ) { ReturnCode = ICERR_OK; break; } bmi1 = CopyBitmapInfo((DWORD) (DWORD_PTR) dwP1); if (bmi1 == NULL) { ReturnCode = ICERR_MEMORY; } else { ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)bmi1, 0); if (ReturnCode > 0 && dwP2 != 0) { bmi2 = LocalAlloc(LMEM_FIXED, ReturnCode); if (bmi2 == NULL) { /* * Can't do anything!!! - there's not good return code */ ReturnCode = ICERR_MEMORY; } else { DWORD Length; Length = (DWORD) ReturnCode; /* preserve length */ ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)bmi1, (DWORD_PTR)bmi2); if (ReturnCode >= 0) { CopyTo16Bit((LPVOID)dwP2, bmi2, Length); } LocalFree((HLOCAL)bmi2); } } LocalFree((HLOCAL)bmi1); } } break; case ICM_DECOMPRESS: if (dwP2 != sizeof(ICDECOMPRESS)) { ReturnCode = ICERR_BADSIZE; } else { ReturnCode = DoICM_DecompressX(hic, msg, dwP1, dwP2); } break; case ICM_DECOMPRESSEX: case ICM_DECOMPRESSEX_BEGIN: case ICM_DECOMPRESSEX_QUERY: if (dwP2 != sizeof(ICDECOMPRESSEX16)) { ReturnCode = ICERR_BADSIZE; } else { ReturnCode = DoICM_DecompressX(hic, msg, dwP1, dwP2); } break; case ICM_DRAW: /* * We can't support unknown extensions */ if (dwP2 != sizeof(ICDRAW)) { ReturnCode = ICERR_BADSIZE; } else { ICDRAW ICDraw; BITMAPINFOHEADER bmi; LPVOID lpData; CopyTo32Bit(&ICDraw, (LPVOID)dwP1, (DWORD) dwP2); /* * We have to assume this is a draw for video */ CopyTo32Bit(&bmi, ICDraw.lpFormat, sizeof(BITMAPINFOHEADER)); ICDraw.lpFormat = (LPVOID)&bmi; lpData = ICDraw.lpData; ICDraw.lpData = ptrFixMap16To32(ICDraw.lpData, ICDraw.cbData); ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)&ICDraw, dwP2); ptrUnFix16(lpData); } break; case ICM_DRAW_BEGIN: { ICDRAWBEGIN InputFormat; BITMAPINFOHEADER bmihInput; ConvertICDRAWBEGIN(&InputFormat, &bmihInput, (DWORD) (DWORD_PTR) dwP1); ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)&InputFormat, dwP2); } break; case ICM_DRAW_CHANGEPALETTE: case ICM_DRAW_QUERY: { LPBITMAPINFO lpbi; lpbi = CopyBitmapInfo((DWORD) (DWORD_PTR) dwP1); if (lpbi == NULL) { ReturnCode = ICERR_MEMORY; } else { ReturnCode = ICSendMessage((HIC)(DWORD_PTR)hic, (UINT)msg, (DWORD_PTR)lpbi, dwP2); LocalFree((HLOCAL)lpbi); } } break; case ICM_DRAW_REALIZE: ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)ThunkHDC(LOWORD(dwP1)), dwP2); break; case ICM_DRAW_WINDOW: { RECT_SHORT SRect; RECT Rect; CopyTo32Bit(&SRect, (LPVOID)dwP1, sizeof(SRect)); SHORT_RECT_TO_RECT(Rect, SRect); ReturnCode = ICSendMessage((HIC)(DWORD_PTR)hic, (UINT)msg, (DWORD_PTR)&Rect, dwP2); } break; // The next three messages are INTERNAL ones case ICM_GETERRORTEXT: break; case ICM_GETFORMATNAME: break; case ICM_ENUMFORMATS: break; case ICM_COMPRESS_FRAMES_INFO: { ICCOMPRESSFRAMES icf32; // We might explode if we get too small a length and start treating // some of the elements as pointers anyway. Just fail the call. // (WIN95C bug 8615). // dwP2 is the length of the 16 bit structure and we only know // the size of the 32 bit structure, but thankfully they're the // same. if (dwP2 < sizeof(ICCOMPRESSFRAMES)) { ReturnCode = ICERR_BADPARAM; break; } CopyTo32Bit(&icf32, (LPBYTE)dwP1, (DWORD) dwP2); // Now fix up the 32 bit structure icf32.PutData = icf32.GetData = NULL; // For safety. should not be used for this message if (icf32.lpbiOutput) { icf32.lpbiOutput = CopyBitmapInfoHeader((DWORD)(DWORD_PTR)icf32.lpbiOutput); } if (icf32.lpbiInput) { icf32.lpbiInput = CopyBitmapInfoHeader((DWORD)(DWORD_PTR)icf32.lpbiInput); } // According to the documentation, lInput and lOutput are undefined. Treating // them as pointers is as scary as a really scary thing. #if 0 lInput = icf32.lInput; icf32.lInput = (LPARAM)ptrFixMap16To32((LPVOID)icf32.lInput, icf32.lpbiInput->biSizeImage); lOutput = icf32.lOutput; icf32.lOutput = (LPARAM)ptrFixMap16To32((LPVOID)icf32.lOutput, icf32.lpbiOutput->biSizeImage); #endif // After the fixups have been done, call the actual routine ReturnCode = ICSendMessage((HIC)(DWORD_PTR)hic, (UINT)msg, (DWORD_PTR)&icf32, dwP2); #if 0 ptrUnFix16((LPVOID)lOutput); ptrUnFix16((LPVOID)lInput); #endif if (icf32.lpbiOutput) { LocalFree(icf32.lpbiOutput); } if (icf32.lpbiInput) { LocalFree(icf32.lpbiInput); } } break; case ICM_DRAW_GET_PALETTE: { ReturnCode = ICSendMessage((HIC) hic, (UINT)msg, dwP1, dwP2); if ((ReturnCode != 0L) && (ReturnCode != ICERR_UNSUPPORTED)) { #ifdef CHICAGO ReturnCode = (LRESULT)(WORD)ReturnCode; #else FARPROC lpWOWHandle16; HMODULE hmodWow; if ( (hmodWow = GetModuleHandle( GET_MAPPING_MODULE_NAME )) && (lpWOWHandle16 = GetProcAddress(hmodWow, "WOWHandle16"))) { ReturnCode = (WORD)(lpWOWHandle16((HANDLE)ReturnCode, (WOW_HANDLE_TYPE)WOW_TYPE_HPALETTE)); } else { ReturnCode = ICERR_ERROR; } #endif } } break; case ICM_DRAW_SUGGESTFORMAT: { ICDRAWSUGGEST icdrwsug; LPBITMAPINFOHEADER lpbiSuggest16; LPBITMAPINFOHEADER lpbiSuggest; DPF(4, "!ICMSendMessage32: ICM_DRAW_SUGGESTFORMAT: dwP1=%08lXh, dwP2=%08lXh", dwP1, dwP2); // CopyTo32Bit(&icdrwsug, (LPBYTE)dwP1, (DWORD) dwP2); lpbiSuggest = NULL; lpbiSuggest16 = icdrwsug.lpbiSuggest; if (lpbiSuggest16) { lpbiSuggest = ptrFixMap16To32(lpbiSuggest16, 0); } // Now fix up the 32 bit structure if (icdrwsug.lpbiIn) { icdrwsug.lpbiIn = CopyBitmapInfoHeader((DWORD)(DWORD_PTR)icdrwsug.lpbiIn); } if (icdrwsug.lpbiSuggest) { icdrwsug.lpbiSuggest = CopyBitmapInfoHeader((DWORD)(DWORD_PTR)icdrwsug.lpbiSuggest); } // After the fixups have been done, call the actual routine ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg, (DWORD_PTR)&icdrwsug, dwP2); if (icdrwsug.lpbiIn) { LocalFree(icdrwsug.lpbiIn); } // We must return the 32 bit suggested format to 16 bit land if (icdrwsug.lpbiSuggest) { if (ReturnCode == ICERR_OK) { CopyMemory( lpbiSuggest, icdrwsug.lpbiSuggest, lpbiSuggest->biSize); } LocalFree(icdrwsug.lpbiSuggest); ptrUnFix16(lpbiSuggest16); } } break; case ICM_SET_STATUS_PROC: // We do not need to support this under NT. It is much // easier not to add the callback support... even if we could // guarantee to be on the right thread to actually do the callback. // // This message has its own thunk! // ASSERT( FALSE ); default: ReturnCode = ICERR_UNSUPPORTED; break; } EndThunk() } INLINE LRESULT FAR PASCAL ICOpen32(DWORD fccType, DWORD fccHandler, UINT wMode) { StartThunk(ICOpen); DPF(1, "Calling ICOpen %4.4hs %4.4hs %4X", &fccType, &fccHandler, wMode); ReturnCode = (LONG_PTR)ICOpen(fccType, fccHandler, (UINT)wMode); EndThunk(); } INLINE LRESULT FAR PASCAL ICClose32(DWORD hic) { StartThunk(ICClose); ReturnCode = ICClose((HIC)hic); EndThunk(); } #endif // _INC_COMPMAN DWORD ICMThunk32(DWORD dwThunkId,DWORD dw1,DWORD dw2,DWORD dw3,DWORD dw4) { // // Make sure we've got thunking functionality // #if 0 { char szBuffer[80]; char szMsg[32]; switch (dwThunkId) { case compThunkICSendMessage32: lstrcpyA( szMsg, "ICSendMessage32" ); break; case compThunkICInfoInternal32: lstrcpyA( szMsg, "ICInfoInternal32" ); break; case compThunkICOpen32: lstrcpyA( szMsg, "ICOpen32" ); break; case compThunkICClose32: lstrcpyA( szMsg, "ICClose32" ); break; default: lstrcpyA( szMsg, "Unknown" ); break; } wsprintfA( szBuffer, "%18.18s 0x%08X 0x%08X 0x%08X 0x%08X\r\n", szMsg, dw1, dw2, dw3, dw4); OutputDebugStringA( szBuffer ); } #endif if (ThunksInitialized <= 0) { HMODULE hMod; if (ThunksInitialized == -1) { return (DWORD)ICERR_ERROR; } hMod = GetModuleHandle(GET_MAPPING_MODULE_NAME); if (hMod != NULL) { GetVDMPointer = (LPGETVDMPOINTER)GetProcAddress(hMod, GET_VDM_POINTER_NAME); lpWOWHandle32 = (LPWOWHANDLE32)GetProcAddress(hMod, GET_HANDLE_MAPPER32 ); lpWOWHandle16 = (LPWOWHANDLE16)GetProcAddress(hMod, GET_HANDLE_MAPPER16 ); lpWOWCallback16 = (LPWOWCALLBACK16)GetProcAddress(hMod, GET_CALLBACK16); } if ( GetVDMPointer == NULL || lpWOWHandle16 == NULL || lpWOWHandle32 == NULL || lpWOWCallback16 == NULL ) { ThunksInitialized = -1; return (DWORD)ICERR_ERROR; } else { ThunksInitialized = 1; } } // // Perform the requested function // switch (dwThunkId) { case compThunkICSendMessage32: return (DWORD) ICSendMessage32(dw1, (UINT)dw2, dw3, dw4); break; case compThunkICInfoInternal32: return (DWORD) ICInfoInternal32(dw1, dw2, (ICINFOA FAR * )dw3, (ICINFOI FAR *)dw4); break; case compThunkICOpen32: return (DWORD) ICOpen32(dw1, dw2, (UINT)dw3); break; case compThunkICClose32: return (DWORD) ICClose32(dw1); break; case compThunkICOpenFunction32: { DWORD fccType; DWORD fccHandler; UINT uMode; FARPROC lpfnHandler; fccType = dw1; fccHandler = dw2; uMode = (UINT)dw3; lpfnHandler = (FARPROC)dw4; // !!! this won't work return (DWORD) (DWORD_PTR) ICOpenFunction( fccType, fccHandler, uMode, lpfnHandler ); break; } case compThunkICSetStatusProc32: { DWORD lpstdS; DWORD cbStruct; HIC hic; LPICSTATUSTHUNKDESC lpstd; LRESULT lr; hic = (HIC)dw1; lpstdS = dw2; cbStruct = dw3; lpstd = ptrFixMap16To32((LPVOID)lpstdS, sizeof(*lpstd)); lr = thkSetStatusProc(hic, lpstd); ptrUnFix16((LPVOID)lpstdS); return (DWORD)lr; } default: return(0); } } #endif // NT_THUNK32 #ifdef NT_THUNK16 //==========================================================================; // // // --- === 16 BIT SIDE === --- // // //==========================================================================; // // --== Global garbage ==-- // DWORD (FAR PASCAL *lpfnCallproc32W)(DWORD, DWORD, DWORD, DWORD, DWORD, LPVOID, DWORD, DWORD); DWORD (FAR PASCAL *lpfnFreeLibrary32W)(DWORD); TCHAR gszKernel[] = TEXT("KERNEL"); TCHAR gszLoadLibraryEx32W[] = TEXT("LoadLibraryEx32W"); TCHAR gszFreeLibrary32W[] = TEXT("FreeLibrary32W"); TCHAR gszGetProcAddress32W[] = TEXT("GetProcAddress32W"); TCHAR gszCallproc32W[] = TEXT("CallProc32W"); TCHAR gszThunkEntry[] = TEXT("ICMThunk32"); TCHAR gszMsvfw32[] = TEXT("msvfw32.dll"); // // --== ==-- // //--------------------------------------------------------------------------; // // PICMGARB thunkInitialize // // Description: // Thunk initialization under NT WOW or Chicago 16-bit. // // Arguments: // // Return (PICMGARB): // NULL if thunks are not functional. Otherwise, a pointer to the // ICMGARB structure for the current process is returned. // // History: // 07/07/94 frankye // // Notes: // The lack of a pig for the current process implies that a thunk // is being called in the context of a process in which we were never // loaded. If this happens, we allocate a new pig for this process // and continue the thunk initialization. Since we were never // loaded in the process, we *probably* will never be freed. We // cannot reliably determine when we can thunkTerminate in the process. // //--------------------------------------------------------------------------; PICMGARB WINAPI thunkInitialize(VOID) { HMODULE hmodKernel; DWORD (FAR PASCAL *lpfnLoadLibraryEx32W)(LPCSTR, DWORD, DWORD); LPVOID (FAR PASCAL *lpfnGetProcAddress32W)(DWORD, LPCSTR); PICMGARB pig; if (NULL == (pig = pigFind())) { DPF(0, "thunkInitialize: WARNING: ICM called from process %08lXh in which it was never loaded.", GetCurrentProcessId()); DebugErr(DBF_WARNING, "thunkInitialize: WARNING: ICM called from process in which it was never loaded."); return NULL; } // // If we've already tried and failed... // if (pig->fThunkError) { return NULL; } // // If we already successfully initialized thunks... // if (pig->fThunksInitialized) { return pig; } // // Try to initialize our connection the the 32-bit side... // DPFS(dbgInit, 1, "thunkInitialize()"); // // For now, we'll assume we hit an error... // pig->fThunkError = TRUE; // // See if we can find the thunking routine entry points in KERNEL // hmodKernel = GetModuleHandle(gszKernel); if (hmodKernel == NULL) { DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetModuleHandle(kernel)"); return NULL; } *(FARPROC *)&lpfnLoadLibraryEx32W = GetProcAddress(hmodKernel, gszLoadLibraryEx32W); if (lpfnLoadLibraryEx32W == NULL) { DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress(kernel, LoadLibraryEx32W)"); return NULL; } *(FARPROC *)&lpfnFreeLibrary32W = GetProcAddress(hmodKernel, gszFreeLibrary32W); if (lpfnFreeLibrary32W == NULL) { DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress(kernel, FreeLibrary32W)"); return NULL; } *(FARPROC *)&lpfnGetProcAddress32W = GetProcAddress(hmodKernel, gszGetProcAddress32W); if (lpfnGetProcAddress32W == NULL) { DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress(kernel, GetProcAddress32W)"); return NULL; } *(FARPROC *)&lpfnCallproc32W = GetProcAddress(hmodKernel, gszCallproc32W); if (lpfnCallproc32W == NULL) { DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress(kernel, CallProc32W)"); return NULL; } // // See if we can get a pointer to our thunking entry points // pig->dwMsvfw32Handle = (*lpfnLoadLibraryEx32W)(gszMsvfw32, 0L, 0L); if (pig->dwMsvfw32Handle == 0) { DPFS(dbgInit, 0, "thunkInitialize: Couldn't LoadLibraryEx32W(msvfw32.dll)"); return NULL; } pig->lpvThunkEntry = (*lpfnGetProcAddress32W)(pig->dwMsvfw32Handle, gszThunkEntry); if (pig->lpvThunkEntry == NULL) { DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress32W(msvfw32, ICMThunk32)"); (*lpfnFreeLibrary32W)(pig->dwMsvfw32Handle); return NULL; } pig->fThunkError = FALSE; pig->fThunksInitialized = TRUE; DPFS(dbgInit, 4, "thunkInitialize: Done!"); return pig; } //--------------------------------------------------------------------------; // // VOID thunkTerminate // // Description: // Thunk termination under NT WOW or Chicago. Called for each process // by 16-bit side to terminate thunks. // // Arguments: // PICMGARB pig: // // Return (VOID): // // History: // 07/07/94 frankye // // Notes: // //--------------------------------------------------------------------------; VOID WINAPI thunkTerminate(PICMGARB pig) { ASSERT( NULL != pig ); if (pig->fThunksInitialized) { lpfnFreeLibrary32W(pig->dwMsvfw32Handle); pig->fThunksInitialized = FALSE; } return; } //--------------------------------------------------------------------------; // // // // //--------------------------------------------------------------------------; /* * Generate our thunks - refer to msvideo!compman.c for definitions of * functions. * * NOTE - we often rely here on the fact that most of the message * parameter structures are identical for 16 and 32-bit - ie they * contain DWORDs and 32-bit pointers. */ //--------------------------------------------------------------------------; // // LONG thkStatusProc // // This is reached by thunking down from the 32-bit thkStatusProc32. // It will call the client's StatusProc. // // Arguments: // DWORD dwParam : contains segmented ptr to an ICSTATUSTHUNKDESC. // The ICSTATUSTHUNKDESC is created during the call to ICSetStatusProc. // // Return value: // LONG : // //--------------------------------------------------------------------------; LONG FAR PASCAL _loadds thkStatusProc(DWORD dwParam) { LPICSTATUSTHUNKDESC lpstd; DPFS(dbgThunks, 4, "thkStatusProc()"); lpstd = (LPICSTATUSTHUNKDESC)dwParam; ASSERT( NULL != lpstd ); ASSERT( NULL != lpstd->fnStatusProcS ); return (lpstd->fnStatusProcS)(lpstd->lParam, (UINT)lpstd->uMsg, lpstd->l); } //--------------------------------------------------------------------------; // // LRESULT ICSendSetStatusProc32 // // Called from 16-bit ICSendMessage to thunk the ICM_SET_STATUS_PROC // message to 32-bits // // Arguments: // HIC hic : // // LPICSETSTATUSPROC lpissp : // // DWORD : cbStruct // // Return value: // LRESULT : // // Notes: // !!! For Daytona, we fail this. If we ever decide to support this // on Daytona, then I think we have much more work to do since linear // addresses in use by the 32-bit codec may change when the status // callback thunks down to 16-bits. On Chicago, all the linear addresses // our fixed when we convert from the segmented address to the linear // address. WHY DOESN'T NT GIVE US AN EASY WAY TO FIX LINEAR ADDRESSES? // //--------------------------------------------------------------------------; LRESULT WINAPI ICSendSetStatusProc32(HIC hic, ICSETSTATUSPROC FAR* lpissp, DWORD cbStruct) { #ifdef DAYTONA return ICERR_UNSUPPORTED; #else PICMGARB pig; PIC pic; LPICSTATUSTHUNKDESC lpstd; LRESULT lr; DPFS(dbgThunks, 4, "ICSendSetStatusProc32()"); if (NULL == (pig = thunkInitialize())) { return ICERR_ERROR; } pic = (PIC)hic; // // This should never fail since the structure was allocated by // our own code in the ICSetStatusProc macro. // if (cbStruct < sizeof(*lpissp)) { ASSERT( FALSE ); return ICERR_BADPARAM; } // // // if (NULL != pic->lpstd) { DPFS(dbgThunks, 1, "ICSendSetStatusProc32: replacing existing status proc!"); GlobalUnfix(GlobalPtrHandle(pic->lpstd)); GlobalFreePtr(pic->lpstd); pic->lpstd = NULL; } // // Allocate a ICSTATUSTHUNKDESC status thunk descriptor. We fix it // in linear memory here so that it's linear address remains constant // throughout it use. It's linear address will be given to the 32-bit // codec which will cache it for use in callbacks. // lpstd = (LPICSTATUSTHUNKDESC)GlobalAllocPtr(GHND, sizeof(*lpstd)); if (NULL == lpstd) { return (ICERR_MEMORY); } GlobalFix(GlobalPtrHandle(lpstd)); pic->lpstd = lpstd; lpstd->lpstdS = lpstd; lpstd->dwFlags = lpissp->dwFlags; lpstd->lParam = lpissp->lParam; lpstd->fnStatusProcS = lpissp->Status; lpstd->pfnthkStatusProc16S = thkStatusProc; lr = (LRESULT)(*lpfnCallproc32W)(compThunkICSetStatusProc32, (DWORD)pic->h32, (DWORD)lpstd, (DWORD)0, (DWORD)0, pig->lpvThunkEntry, 0L, // Don't map pointers 5L); if (0 != lr) { DPFS(dbgThunks, 1, "ICSendSetStatusProc32: fail"); GlobalUnfix(GlobalPtrHandle(pic->lpstd)); GlobalFreePtr(pic->lpstd); pic->lpstd = NULL; } return lr; #endif } BOOL FAR PASCAL ICInfoInternal32(DWORD fccType, DWORD fccHandler, ICINFO FAR * lpicInfo, ICINFOI FAR * lpicInfoI) { PICMGARB pig; DPFS(dbgThunks, 4, "ICInfoInternal32"); if (NULL == (pig = thunkInitialize())) { return FALSE; } return (BOOL)(*lpfnCallproc32W)(compThunkICInfoInternal32, (DWORD)fccType, (DWORD)fccHandler, (DWORD)lpicInfo, (DWORD)lpicInfoI, pig->lpvThunkEntry, 0L, // Don't map pointers 5L); } LRESULT FAR PASCAL ICSendMessage32(DWORD hic, UINT msg, DWORD dwP1, DWORD dwP2) { PICMGARB pig; DPFS(dbgThunks, 4, "ICSendMessage32(hic=%08lXh, msg=%04Xh, dwP1=%08lXh, dwP2=%08lXh)", hic, msg, dwP1, dwP2); if (NULL == (pig = thunkInitialize())) { switch (msg) { case ICM_GETSTATE: case ICM_SETSTATE: case ICM_GETINFO: case ICM_COMPRESS_GET_SIZE: return 0; } return (LRESULT)ICERR_ERROR; } return (LRESULT)(*lpfnCallproc32W)(compThunkICSendMessage32, (DWORD)hic, (DWORD)msg, (DWORD)dwP1, (DWORD)dwP2, pig->lpvThunkEntry, 0L, // Don't map pointers 5L); } LRESULT FAR PASCAL ICOpen32(DWORD fccType, DWORD fccHandler, UINT wMode) { PICMGARB pig; DPFS(dbgThunks, 4, "ICOpen32"); if (NULL == (pig = thunkInitialize())) { return NULL; } return (DWORD)(lpfnCallproc32W)(compThunkICOpen32, (DWORD)fccType, (DWORD)fccHandler, (DWORD)wMode, (DWORD)0L, pig->lpvThunkEntry, 0L, // Don't map pointers 5L); } LRESULT FAR PASCAL ICOpenFunction32(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler) { PICMGARB pig; DPFS(dbgThunks, 4, "ICOpenFunction32"); if (NULL == (pig = thunkInitialize())) { return NULL; } return (LRESULT)(lpfnCallproc32W)(compThunkICOpenFunction32, (DWORD)fccType, (DWORD)fccHandler, (DWORD)wMode, (DWORD)lpfnHandler, pig->lpvThunkEntry, 0L, // Don't map pointers 5L); } LRESULT FAR PASCAL ICClose32(DWORD hic) { PICMGARB pig; DPFS(dbgThunks, 4, "ICClose32"); if (NULL == (pig = thunkInitialize())) { return (LRESULT)ICERR_ERROR; } return (DWORD)(lpfnCallproc32W)(compThunkICClose32, (DWORD)hic, (DWORD)0L, (DWORD)0L, (DWORD)0L, pig->lpvThunkEntry, 0L, // Don't map pointers 5L); } #endif // NT_THUNK16