|
|
//==========================================================================;
// thunk32.c
//
// Copyright (c) 1991-1994 Microsoft Corporation. All Rights Reserved.
//
// Description:
// This module contains routines for thunking the video APIs
// 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 :
*/
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <mmddk.h>
#include <mmreg.h>
#include <memory.h>
#include <win32.h>
#ifdef _WIN32
#include <ivideo32.h>
#ifndef _INC_MSVIDEO
#define _INC_MSVIDEO 50 /* version number */
#endif
#else
#include <vfw.h>
#endif
#include <msviddrv.h>
#include <msvideoi.h>
#ifdef _WIN32
#include <wownt32.h>
#include <stdlib.h> // for mbstowcs and wcstombs
#include <video16.h>
#ifdef UNICODE
#include "profile.h" // NT only (for now?)
#endif
#endif // WIN32
// in capinit.c
BOOL capInternalGetDriverDescA(UINT wDriverIndex, LPSTR lpszName, int cbName, LPSTR lpszVer, int cbVer);
//
// pick up the function definitions
//
#include "vidthunk.h"
#ifdef DEBUG
#define MODNAME "AVICAP32"
int videoDebugLevel = -1; void videoDebugInit(VOID) { if (videoDebugLevel == -1) videoDebugLevel = GetProfileIntA("Debug", MODNAME, 0); } #else
#define videoDebugInit()
#endif
/* -------------------------------------------------------------------------
** Handle and memory mapping functions. ** ------------------------------------------------------------------------- */ LPWOWHANDLE32 lpWOWHandle32; LPWOWHANDLE16 lpWOWHandle16; LPWOWCALLBACK16 lpWOWCallback16; LPGETVDMPOINTER GetVdmPointer; int ThunksInitialized;
#ifdef WIN32
#ifdef DEBUG
void FAR cdecl thkdprintf(LPSTR szFormat, ...) { char ach[128]; va_list va;
#define MARKER "AVICAP (thunk): "
lstrcpyA(ach, MARKER);
va_start(va, szFormat); wvsprintfA(ach+sizeof(MARKER), szFormat, va); va_end(va); OutputDebugStringA(ach); } #endif
#endif
//
// 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 = GetVdmPointer((DWORD)(DWORD_PTR)Dest16, Length, TRUE);
CopyMemory(Dest32, Src32, Length); }
/*
* 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 = GetVdmPointer((DWORD)(DWORD_PTR)Src16, Length, TRUE);
CopyMemory(Dest32, Src32, Length); }
/*
* Copy data from source to dest where source is a 16bit pointer * and dest is a 32bit pointer ONLY if the source is not aligned * * Returns which pointer to use (src or dest) */ LPVOID CopyIfNotAligned(LPVOID Dest32, LPVOID Src16, DWORD Length) { PVOID Src32;
if (Src16 == NULL) { return Dest32; }
Src32 = GetVdmPointer((DWORD)(DWORD_PTR)Src16, Length, TRUE);
CopyMemory(Dest32, Src32, Length);
return Dest32; }
typedef struct _callback { WORD flags; WORD hVideo16; WORD msg; DWORD dwCallback16inst; DWORD dw1; DWORD dw2; } CALLBACK16; typedef CALLBACK16 * PCALLBACK16;
/*
* Callbacks */
void MyVideoCallback(HANDLE handle, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) { PVIDEOINSTANCEDATA32 pInst; BOOL fFree = FALSE;
pInst = (PVIDEOINSTANCEDATA32)dwUser;
DPF3(("Video callback - handle = %8X, msg = %8X, dwUser = %8X, dw1 = %8X, dw2 = %8X\n", handle, msg, dwUser, dw1, dw2));
switch (msg) {
/*
* What are the parameters for these messages ?? */
case MM_DRVM_OPEN:
/*
* We get this when we INIT_STREAM */
break;
case MM_DRVM_CLOSE:
/*
* Device is closing - this is where we free our structures * (just in case the 32-bit side called close to clean up). * dwUser points to our data */
fFree = TRUE;
break;
case MM_DRVM_DATA:
/*
* We have data - this means a buffer has been returned in * dw1 */
{ PVIDEOHDR32 pHdr32;
pHdr32 = CONTAINING_RECORD((PVIDEOHDR)dw1, VIDEOHDR32, videoHdr);
dw1 = (DWORD)(DWORD_PTR)pHdr32->pHdr16; // For callback below
/*
* Map back the data and free our structure */
{ VIDEOHDR Hdr16; Hdr16 = pHdr32->videoHdr; Hdr16.lpData = pHdr32->lpData16; memcpy(pHdr32->pHdr32, (LPVOID)&Hdr16, sizeof(VIDEOHDR)); }
/*
* Clean up our local structure */
LocalFree((HLOCAL)pHdr32);
}
break;
case MM_DRVM_ERROR: /*
* dw1 = frames skipped - unfortunately there's nobody to tell! */
break; }
/*
* Call back the application if appropriate */
switch (pInst->dwFlags & CALLBACK_TYPEMASK) { case CALLBACK_WINDOW: PostMessage(ThunkHWND(LOWORD(pInst->dwCallback)), msg, (WPARAM)handle, (LPARAM)dw1); break;
case CALLBACK_FUNCTION: #if 0
// Must call a generic 16 bit callback passing a pointer to
// a parameter array.
{
WORD hMem; PCALLBACK16 pCallStruct; pCallStruct = WOWGlobalAllocLock16(0, sizeof(CALLBACK16), &hMem); if (pCallStruct) { pCallStruct->flags = HIWORD(pInst->dwFlags); pCallStruct->hVideo16 = (WORD)pInst->hVideo; pCallStruct->msg = (WORD)msg; pCallStruct->dwCallback16inst = pInst->dwCallbackInst; pCallStruct->dw1 = (DWORD)dw1; pCallStruct->dw2 = (DWORD)dw2;
lpWOWCallback16(pInst->dwCallback, pCallStruct);
// Now free off the callback structure
WOWGlobalUnlockFree16(pCallStruct);
} } #endif
break; }
if (fFree) { LocalFree((HLOCAL)pInst); } }
//
// Thunking callbacks to WOW32 (or wherever)
//
typedef struct tag_video_stream_init_parms16 { DWORD dwMicroSecPerFrame; DWORD dwCallback; DWORD dwCallbackInst; DWORD dwFlags; DWORD_PTR hVideo; } VIDEO_STREAM_INIT_PARMS16, FAR * LPVIDEO_STREAM_INIT_PARMS16;
//--------------------------------------------------------------------------;
//
// DWORD videoThunk32
//
// Description:
//
// 32-bit function dispatcher for thunks.
//
// Arguments:
// DWORD dwThunkId:
//
// DWORD dw1:
//
// DWORD dw2:
//
// DWORD dw3:
//
// DWORD dw4:
//
// Return (DWORD):
//
// History:
//
//--------------------------------------------------------------------------;
DWORD videoThunk32(DWORD dwThunkId,DWORD dw1,DWORD dw2,DWORD dw3,DWORD dw4) { //
// Make sure we've got thunking functionality
//
if (ThunksInitialized <= 0) {
HMODULE hMod;
if (ThunksInitialized == -1) { return MMSYSERR_ERROR; }
videoDebugInit();
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 ) {
ThunksInitialized = -1; return MMSYSERR_ERROR;
} else { ThunksInitialized = 1; } }
//
// Perform the requested function
//
switch (dwThunkId) {
case vidThunkvideoMessage32: return (DWORD) videoMessage32((HVIDEO)dw1, (UINT)dw2, dw3, dw4); break;
case vidThunkvideoGetNumDevs32: return (DWORD) videoGetNumDevs32(); break;
case vidThunkvideoOpen32: return (DWORD) videoOpen32((LPHVIDEO)dw1, dw2, dw3); break;
case vidThunkvideoClose32: return (DWORD) videoClose32((HVIDEO)dw1); break;
case vidThunkvideoGetDriverDesc32: { LPSTR lpszName = NULL, lpszVer = NULL; short cbName, cbVer; DWORD dwRet;
cbName = (short) LOWORD(dw4); cbVer = (short) HIWORD(dw4);
// for chicago, need to call WOW32GetVdmPointerFix
// (via getprocaddr!)
if ((dw2 != 0) && (cbName > 0)) { lpszName = WOW32ResolveMemory(dw2); } if ((dw3 != 0) && (cbVer > 0)) { lpszVer = WOW32ResolveMemory(dw3); }
dwRet = capInternalGetDriverDescA( dw1, // device id
lpszName, cbName, lpszVer, cbVer);
#if 0 //should do this for chicago
if (lpszName) { WOWGetVDMPointerUnfix(dw2); } if (lpszVer) { WOWGetVDMPointerUnfix(dw3); } #endif
return dwRet; }
default: return(0); } }
LRESULT FAR PASCAL videoMessage32(HVIDEO hVideo, UINT msg, DWORD dwP1, DWORD dwP2) { StartThunk(videoMessage); DPF2(("\tvideoMessage id = %4X, lParam1 = %8X, lParam2 = %8X", msg, dwP1, dwP2));
/*
* We ONLY support (and we only ever will support) messages which * have ALREADY been defined. New 32-bit driver messages will NOT * be supported from 16-bit apps. */
switch (msg) { case DVM_GETVIDEOAPIVER: { DWORD ApiVer;
ReturnCode = videoMessage((HVIDEO)hVideo, (UINT)msg, (DWORD_PTR)&ApiVer, dwP2);
if (ReturnCode == DV_ERR_OK) { CopyTo16Bit((LPVOID)dwP1, &ApiVer, sizeof(DWORD)); } } break;
case DVM_GETERRORTEXT: { VIDEO_GETERRORTEXT_PARMS vet; VIDEO_GETERRORTEXT_PARMS MappedVet;
/*
* Get the parameter block */
CopyTo32Bit((LPVOID)&vet, (LPVOID)dwP1, sizeof(vet)); MappedVet = vet;
/*
* Map the string pointer */
MappedVet.lpText = WOW32ResolveMemory(vet.lpText);
ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)&MappedVet, 0); } break;
case DVM_GET_CHANNEL_CAPS: { CHANNEL_CAPS Caps;
ReturnCode = videoMessage((HVIDEO)hVideo, (UINT)msg, (DWORD_PTR)&Caps, dwP2);
/*
* If successful return the data to the 16-bit app */
if (ReturnCode == DV_ERR_OK) { CopyTo16Bit((LPVOID)dwP1, (LPVOID)&Caps, sizeof(Caps)); }
} break;
case DVM_UPDATE: { ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)ThunkHWND(dwP1), (DWORD_PTR)ThunkHDC(dwP2)); } break;
case DVM_PALETTE: case DVM_PALETTERGB555: case DVM_FORMAT: /*
* This stuff all comes from videoConfigure * * Let's hope this data is all DWORDs! */ { VIDEOCONFIGPARMS vcp, MappedVcp; DWORD dwReturn;
BOOL Ok;
Ok = TRUE;
CopyTo32Bit((LPVOID)&vcp, (LPVOID)dwP2, sizeof(vcp)); MappedVcp.lpdwReturn = &dwReturn; MappedVcp.dwSize1 = vcp.dwSize1; MappedVcp.dwSize2 = vcp.dwSize2;
/*
* Get some storage to store the answer */
if (MappedVcp.dwSize1 != 0) { MappedVcp.lpData1 = (LPSTR)LocalAlloc(LPTR, MappedVcp.dwSize1); if (MappedVcp.lpData1 == NULL) { Ok = FALSE; } else { if (MappedVcp.dwSize2 != 0) { MappedVcp.lpData2 = (LPSTR)LocalAlloc(LPTR, MappedVcp.dwSize2); if (MappedVcp.lpData2 == NULL) { Ok = FALSE;
if (MappedVcp.dwSize1 != 0) { LocalFree((HLOCAL)MappedVcp.lpData1); } } } } }
if (Ok) {
CopyTo32Bit(MappedVcp.lpData1, vcp.lpData1, MappedVcp.dwSize1); CopyTo32Bit(MappedVcp.lpData2, vcp.lpData2, MappedVcp.dwSize2);
ReturnCode = videoMessage(hVideo, msg, dwP1, (DWORD_PTR)&MappedVcp);
if (ReturnCode == DV_ERR_OK) {
if (vcp.lpdwReturn != NULL) { CopyTo16Bit(vcp.lpdwReturn, MappedVcp.lpdwReturn, sizeof(DWORD)); }
CopyTo16Bit(vcp.lpData1, MappedVcp.lpData1, MappedVcp.dwSize1); CopyTo16Bit(vcp.lpData2, MappedVcp.lpData2, MappedVcp.dwSize2); }
if (MappedVcp.dwSize1 != 0) { LocalFree((HLOCAL)MappedVcp.lpData1); } if (MappedVcp.dwSize2 != 0) { LocalFree((HLOCAL)MappedVcp.lpData2); } } else { ReturnCode = DV_ERR_NOMEM; } } break;
case DVM_CONFIGURESTORAGE: { LPSTR lpStrIdent; lpStrIdent = WOW32ResolveMemory(dwP1);
ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)lpStrIdent, dwP2);
} break;
case DVM_DIALOG: { ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)ThunkHWND(dwP1), dwP2); } break;
case DVM_SRC_RECT: case DVM_DST_RECT: /*
* If it's a query only then don't bother with the * rectangle */
if (dwP2 & VIDEO_CONFIGURE_QUERY) { ReturnCode = videoMessage(hVideo, msg, dwP1, dwP2); } else {
/*
* The rectangle is regarded as 'in' and 'out' * We need to translate between 16-bit and 32-bit rectangle structures */
RECT_SHORT SRect; RECT Rect;
CopyTo32Bit((LPVOID)&SRect, (LPVOID)dwP1, sizeof(SRect));
SHORT_RECT_TO_RECT(Rect, SRect);
ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)&Rect, dwP2);
if (ReturnCode == DV_ERR_OK) { RECT_TO_SHORT_RECT(SRect, Rect); CopyTo16Bit((LPVOID)dwP1, (LPVOID)&SRect, sizeof(SRect)); } } break;
case DVM_STREAM_PREPAREHEADER: case DVM_STREAM_UNPREPAREHEADER: case DVM_FRAME: case DVM_STREAM_ADDBUFFER: { VIDEOHDR Hdr32; LPBYTE pData16, pData32; DWORD dwSize;
dwSize = (UINT)msg == DVM_FRAME ? sizeof(VIDEOHDR) : min(dwP2, sizeof(VIDEOHDR));
CopyTo32Bit((LPVOID)&Hdr32, (LPVOID)dwP1, dwSize);
pData16 = Hdr32.lpData;
/*
* Create a mapping for the pointer */
pData32 = GetVdmPointer((DWORD)(DWORD_PTR)pData16, Hdr32.dwBufferLength, TRUE); Hdr32.lpData = pData32;
if (msg == DVM_STREAM_ADDBUFFER) {
PVIDEOHDR32 pHdr32;
/*
* Allocate our callback structure and pass this * as our header (suitably offset to the video header part). */
pHdr32 = (PVIDEOHDR32)LocalAlloc(LPTR, sizeof(VIDEOHDR32));
if (pHdr32 == NULL) { ReturnCode = DV_ERR_NOMEM; } else {
/*
* Remember the old header so we can pass it back * and the old data pointer so we can flush it */
pHdr32->pHdr16 = (LPVOID)dwP1;
/*
* Some systems can't handle GetVdmPointer at interrupt * time so get a pointer here */
pHdr32->pHdr32 = WOW32ResolveMemory(dwP1); pHdr32->lpData16 = pData16; pHdr32->videoHdr = Hdr32;
ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)&pHdr32->videoHdr, dwP2); /*
* If everything was OK copy it back */
if (ReturnCode == DV_ERR_OK) { Hdr32.lpData = pData16; CopyTo16Bit((LPVOID)dwP1, (LPVOID)&Hdr32, dwSize); } }
} else {
/*
* Prepare/unprepare the header for 32bit */
ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)&Hdr32, dwP2);
/*
* If everything was OK copy it back */
if (ReturnCode == DV_ERR_OK) { Hdr32.lpData = pData16; CopyTo16Bit((LPVOID)dwP1, (LPVOID)&Hdr32, dwSize); } } } break;
case DVM_STREAM_RESET: case DVM_STREAM_FINI: case DVM_STREAM_STOP: case DVM_STREAM_START:
/*
* Note that the MM_DRVM_CLOSE message will cause us to clean up our * callback structures on DVM_STREAM_FINI. */
ReturnCode = videoMessage(hVideo, msg, 0, 0); break;
case DVM_STREAM_GETPOSITION: { MMTIME mmTime; MMTIME16 mmTime16;
ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)&mmTime, sizeof(mmTime));
if (ReturnCode == DV_ERR_OK) { mmTime16.wType = (WORD)mmTime.wType; CopyMemory((LPVOID)&mmTime16.u, (LPVOID)&mmTime.u, sizeof(mmTime16.u));
CopyTo16Bit((LPVOID)dwP1, (LPVOID)&mmTime16, min(sizeof(mmTime16), dwP2));
} }
break;
case DVM_STREAM_INIT: { VIDEO_STREAM_INIT_PARMS vsip; VIDEO_STREAM_INIT_PARMS16 vsip16; PVIDEOINSTANCEDATA32 pInst32;
#if 0
// always do callback
VIDEO_STREAM_INIT_PARMS16 * pvsip = WOW32ResolveMemory(dwP1); if (!(pvsip->dwFlags & CALLBACK_TYPEMASK)) { // No callback wanted by the 16 bit code. Pass call
// straight through
ReturnCode = videoMessage((HVIDEO)hVideo, (UINT)msg, (DWORD_PTR)pvsip, (DWORD_PTR)dwP2);
} else #endif
{ // We set up a callback to a 32 bit routine, that in
// turn will callback to the 16 bit function/window
pInst32 = (PVIDEOINSTANCEDATA32) LocalAlloc(LPTR, sizeof(VIDEOINSTANCEDATA32));
if (pInst32 == NULL) { ReturnCode = DV_ERR_NOMEM; } else { CopyTo32Bit((LPVOID)&vsip16, (LPVOID)dwP1, min(sizeof(vsip16), dwP2));
pInst32->dwFlags = vsip16.dwFlags; pInst32->dwCallbackInst = vsip16.dwCallbackInst; pInst32->dwCallback = vsip16.dwCallback; pInst32->hVideo = (HVIDEO16)vsip16.hVideo;
/*
* Make up our own parms. Only set up a callback if * the user wanted one */
vsip.dwCallback = (DWORD_PTR)MyVideoCallback; vsip.dwFlags = (vsip.dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION; vsip.dwCallbackInst = (DWORD_PTR)pInst32;
ReturnCode = videoMessage((HVIDEO)hVideo, (UINT)msg, (DWORD_PTR)&vsip, (DWORD_PTR)dwP2);
if (ReturnCode != DV_ERR_OK) { LocalFree((HLOCAL)pInst32); } else { // The instance block will be freed off by the
// 32 bit callback routine when all over
} } } } break;
case DVM_STREAM_GETERROR: { DWORD dwError; DWORD dwFramesSkipped;
ReturnCode = videoMessage(hVideo, msg, (DWORD_PTR)&dwError, (DWORD_PTR)&dwFramesSkipped);
if (ReturnCode == DV_ERR_OK) { CopyTo16Bit((LPVOID)dwP1, &dwError, sizeof(DWORD)); CopyTo16Bit((LPVOID)dwP2, &dwFramesSkipped, sizeof(DWORD)); } } break;
default: DPF2(("videoMessage - Message not implemented %X\n", (UINT)msg)); ReturnCode = DV_ERR_NOTSUPPORTED;
} EndThunk(); }
INLINE LRESULT FAR PASCAL videoGetNumDevs32(void) { StartThunk(videoGetNumDevs); ReturnCode = videoGetNumDevs(); EndThunk(); }
LRESULT FAR PASCAL videoClose32(HVIDEO hVideo) { StartThunk(videoClose) ReturnCode = videoClose(hVideo); EndThunk(); }
LRESULT FAR PASCAL videoOpen32(LPHVIDEO lphVideo, DWORD dwDeviceID, DWORD dwFlags) { HVIDEO hVideo; StartThunk(videoOpen);
ReturnCode = videoOpen( &hVideo, dwDeviceID, dwFlags);
if (ReturnCode == DV_ERR_OK) { lphVideo = WOW32ResolveMemory((PVOID)lphVideo); * (HVIDEO UNALIGNED *)lphVideo = hVideo; } EndThunk(); }
|