407 lines
12 KiB
C
407 lines
12 KiB
C
|
/****************************************************************************
|
|||
|
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 <windows.h>
|
|||
|
#define MMNOMCI
|
|||
|
#include <win32.h>
|
|||
|
#include <mmsystem.h>
|
|||
|
#include <msvideo.h>
|
|||
|
#include <msviddrv.h>
|
|||
|
#include <compman.h>
|
|||
|
#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));
|
|||
|
}
|
|||
|
|