/**************************************************************************** thunks.c Contains code for thunking msvideo.dll from 16bit to 32bit Copyright (c) Microsoft Corporation 1994. All rights reserved Basic Structure: When loaded, the 16 bit DLL will try to find the corresponding 32 bit DLL. There are two of these. The 32bit videoXXXX api entry points are in AVICAP32.DLL The 32bit ICM code is in MSVFW32.DLL The thunk initialisation routine will check the code is running on Windows NT. If not, no further initialisation is done. This ensures that the same binary can be used on NT, and other Windows platforms. The code then attempts to access the special entry points provided in KERNEL.DLL for loading and calling 32 bit entry points. If this link fails, no thunking can be done. Each of the 32 bit DLLs is loaded in turn, and GetProcAddress32 is called for the special thunk entry point. If all works then two global flags are set (independently of each other). gfVideo32 == TRUE means that the videoXXXX apis can be called. gfICM32 == TRUE means that the 32 bit ICM code is available. ****************************************************************************/ #include #define MMNOMCI #include #include #include #include #include #include "vidthunk.h" #include "msvideoi.h" SZCODE gszKernel[] = TEXT("KERNEL"); SZCODE gszLoadLibraryEx32W[] = TEXT("LoadLibraryEx32W"); //SZCODE gszFreeLibraryEx32W[] = TEXT("FreeLibraryEx32W"); SZCODE gszFreeLibrary32W[] = TEXT("FreeLibrary32W"); SZCODE gszGetProcAddress32W[] = TEXT("GetProcAddress32W"); SZCODE gszCallproc32W[] = TEXT("CallProc32W"); SZCODE gszVideoThunkEntry[] = TEXT("videoThunk32"); SZCODE gszVideo32[] = TEXT("avicap32.dll"); SZCODE gszICMThunkEntry[] = TEXT("ICMThunk32"); SZCODE gszICMThunkEntry2[] = TEXT("ICMTHUNK32"); SZCODE gszICM32[] = TEXT("msvfw32.dll"); VIDTHUNK pvth; #ifndef WIN32 //--------------------------------------------------------------------------; // // BOOL InitThunks // // Description: // // // Arguments: // None. // // Return (BOOL): // // History: // // //--------------------------------------------------------------------------; void FAR PASCAL InitThunks(VOID) { HMODULE hmodKernel; DWORD (FAR PASCAL *lpfnLoadLibraryEx32W)(LPCSTR, DWORD, DWORD); LPVOID (FAR PASCAL *lpfnGetProcAddress32W)(DWORD, LPCSTR); DWORD (FAR PASCAL *lpfnFreeLibrary32W)(DWORD hLibModule); // // Check if we're WOW // // if (!(GetWinFlags() & WF_WINNT)) { // //DPF(("Not running in WOW... returning FALSE\n")); // return; // } // // See if we can find the thunking routine entry points in KERNEL // hmodKernel = GetModuleHandle(gszKernel); if (hmodKernel == NULL) { DPF(("Cannot link to kernel module... returning FALSE\n")); return; // !!!! } *(FARPROC *)&lpfnLoadLibraryEx32W = GetProcAddress(hmodKernel, gszLoadLibraryEx32W); if (lpfnLoadLibraryEx32W == NULL) { DPF(("Cannot get address of LoadLibrary32... returning FALSE\n")); return; } *(FARPROC *)&lpfnGetProcAddress32W = GetProcAddress(hmodKernel, gszGetProcAddress32W); if (lpfnGetProcAddress32W == NULL) { DPF(("Cannot get address of GetProcAddress32... returning FALSE\n")); return; } *(FARPROC *)&pvth.lpfnCallproc32W = GetProcAddress(hmodKernel, gszCallproc32W); if (pvth.lpfnCallproc32W == NULL) { DPF(("Cannot get address of CallProc32... returning FALSE\n")); return; } // In case we need to unload our 32 bit libraries... *(FARPROC *)&lpfnFreeLibrary32W = GetProcAddress(hmodKernel, gszFreeLibrary32W); // // See if we can get pointers to our thunking entry points // pvth.dwVideo32Handle = (*lpfnLoadLibraryEx32W)(gszVideo32, 0L, 0L); if (pvth.dwVideo32Handle != 0) { pvth.lpVideoThunkEntry = (*lpfnGetProcAddress32W)(pvth.dwVideo32Handle, gszVideoThunkEntry); if (pvth.lpVideoThunkEntry != NULL) { gfVideo32 = TRUE; } else { DPF(("Cannot get address of video thunk entry...\n")); if (lpfnFreeLibrary32W) { (*lpfnFreeLibrary32W)(pvth.dwVideo32Handle); } } } else { DPF(("Cannot load Video32 DLL...\n")); } pvth.dwICM32Handle = (*lpfnLoadLibraryEx32W)(gszICM32, 0L, 0L); if (pvth.dwICM32Handle != 0) { pvth.lpICMThunkEntry = (*lpfnGetProcAddress32W)(pvth.dwICM32Handle, gszICMThunkEntry); if (pvth.lpICMThunkEntry != NULL) { DPF(("ICM thunks OK!!\n")); gfICM32 = TRUE; } else { DPF(("Cannot get address of ICM thunk entry... trying #2\n")); pvth.lpICMThunkEntry = (*lpfnGetProcAddress32W)(pvth.dwICM32Handle, gszICMThunkEntry2); if (pvth.lpICMThunkEntry != NULL) { DPF(("ICM thunks OK!! (at second time of trying)\n")); gfICM32 = TRUE; } else { DPF(("Cannot get address of ICM thunk entry2...\n")); if (lpfnFreeLibrary32W) { (*lpfnFreeLibrary32W)(pvth.dwICM32Handle); } } } } else { DPF(("Cannot load ICM32 DLL...\n")); } return; } #endif // !WIN32 // // The following functions generate calls to the 32-bit side // DWORD FAR PASCAL videoMessage32(HVIDEO hVideo, UINT msg, DWORD dwP1, DWORD dwP2) { /* * Check there's something on the other side! */ if (!gfVideo32) { DPF(("videoMessage32 - no video thunks... returning FALSE\n")); return DV_ERR_INVALHANDLE; } /* * Watch out for hvideos being passed */ if (msg == DVM_STREAM_INIT) { ((LPVIDEO_STREAM_INIT_PARMS)dwP1)->hVideo = hVideo; } return((DWORD)(pvth.lpfnCallproc32W)(vidThunkvideoMessage32, (DWORD)hVideo, (DWORD)msg, (DWORD)dwP1, (DWORD)dwP2, pvth.lpVideoThunkEntry, 0L, // no mapping of pointers 5L)); } DWORD FAR PASCAL videoGetNumDevs32(void) { if (!gfVideo32) { DPF(("videoGetNumDevs32 - no video thunks... returning FALSE\n")); return 0; } return((DWORD)(pvth.lpfnCallproc32W)(vidThunkvideoGetNumDevs32, (DWORD)0, (DWORD)0, (DWORD)0, (DWORD)0, pvth.lpVideoThunkEntry, 0L, // no mapping of pointers 5L)); } DWORD FAR PASCAL videoClose32(HVIDEO hVideo) { /* * Check there's something on the other side! */ if (!gfVideo32) { DPF(("videoClose32 - no video thunks... returning FALSE\n")); return DV_ERR_INVALHANDLE; } return((DWORD)(pvth.lpfnCallproc32W)(vidThunkvideoClose32, (DWORD)hVideo, (DWORD)0, (DWORD)0, (DWORD)0, pvth.lpVideoThunkEntry, 0L, // no mapping of pointers 5L)); } DWORD FAR PASCAL videoOpen32(LPHVIDEO lphVideo, DWORD dwDeviceID, DWORD dwFlags) { DWORD dwRetc; if (!gfVideo32) { DPF(("videoOpen32 - no video thunks... returning FALSE\n")); return DV_ERR_NOTDETECTED; } dwRetc = ((DWORD)(pvth.lpfnCallproc32W)(vidThunkvideoOpen32, (DWORD)lphVideo, (DWORD)dwDeviceID, (DWORD)dwFlags, (DWORD)0, pvth.lpVideoThunkEntry, 0L, // no mapping of pointers 5L)); if (dwRetc == DV_ERR_OK) { #ifdef DEBUG if (Is32bitHandle(*lphVideo)) { //OutputDebugString("\nMSVIDEO : 32-bit handle does not fit in 16 bits!"); DebugBreak(); } #endif *lphVideo = Make32bitHandle(*lphVideo); } return dwRetc; } DWORD FAR PASCAL videoGetDriverDesc32(DWORD wDriverIndex, LPSTR lpszName, short cbName, LPSTR lpszVer, short cbVer) { if (!gfVideo32) { DPF(("videoGetDriverDesc32 - no video thunks... returning FALSE\n")); return DV_ERR_NOTDETECTED; } return (BOOL)(pvth.lpfnCallproc32W)(vidThunkvideoGetDriverDesc32, (DWORD)wDriverIndex, (DWORD)lpszName, (DWORD)lpszVer, (DWORD) MAKELONG(cbName, cbVer), pvth.lpVideoThunkEntry, 0L, // no mapping of pointers 5L); // 5 params } /* * The ICM thunking uses the same mechanism as for Video, but calls to a * different 32 bit DLL. */ BOOL FAR PASCAL ICInfo32(DWORD fccType, DWORD fccHandler, ICINFO FAR * lpicInfo) { if (!gfICM32) { //OutputDebugString("ICInfo32: gfICM32 is not set - returning FALSE\n"); return FALSE; } return ((BOOL)(pvth.lpfnCallproc32W)(compThunkICInfo32, (DWORD)fccType, (DWORD)fccHandler, (DWORD)lpicInfo, (DWORD)0, pvth.lpICMThunkEntry, 0L, // no mapping of pointers 5L)); } LRESULT FAR PASCAL ICSendMessage32(DWORD hic, UINT msg, DWORD dwP1, DWORD dwP2) { /* * Check there's something on the other side! */ if (!gfICM32) { #ifdef DEBUG OutputDebugString("ICSendMessage32: gfICM32 is not set - returning FALSE\n"); #endif return ICERR_BADHANDLE; } return ((LRESULT)(pvth.lpfnCallproc32W)(compThunkICSendMessage32, (DWORD)hic, (DWORD)msg, (DWORD)dwP1, (DWORD)dwP2, pvth.lpICMThunkEntry, 0L, // no mapping of pointers 5L)); } DWORD FAR PASCAL ICOpen32(DWORD fccType, DWORD fccHandler, UINT wMode) { /* * Check there's something on the other side! */ if (!gfICM32) { #ifdef DEBUG OutputDebugString("ICOpen32: gfICM32 is not set - returning FALSE\n"); #endif return NULL; } return ((DWORD)(pvth.lpfnCallproc32W)(compThunkICOpen32, (DWORD)fccType, (DWORD)fccHandler, (DWORD)wMode, (DWORD)0, pvth.lpICMThunkEntry, 0L, // no mapping of pointers 5L)); } LRESULT FAR PASCAL ICClose32(DWORD hic) { /* * Check there's something on the other side! */ if (!gfICM32) { #ifdef DEBUG OutputDebugString("ICClose32: gfICM32 is not set - returning FALSE\n"); #endif return ICERR_BADHANDLE; } return ((LRESULT)(pvth.lpfnCallproc32W)(compThunkICClose32, (DWORD)hic, (DWORD)0, (DWORD)0, (DWORD)0, pvth.lpICMThunkEntry, 0L, // no mapping of pointers 5L)); }