540 lines
16 KiB
C
540 lines
16 KiB
C
/*++
|
|
*
|
|
* WOW v1.0
|
|
*
|
|
* Copyright (c) 1991, Microsoft Corporation
|
|
*
|
|
* WMMSTRU2.C
|
|
* WOW32 16-bit MultiMedia structure conversion support
|
|
* Contains support for mciSendCommand UnThunk message Parms.
|
|
*
|
|
* History:
|
|
* Created 17-Jul-1992 by Stephen Estrop (stephene)
|
|
*
|
|
--*/
|
|
|
|
//
|
|
// We define NO_STRICT so that the compiler doesn't moan and groan when
|
|
// I use the FARPROC type for the Multi-Media api loading.
|
|
//
|
|
#define NO_STRICT
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#if 0
|
|
|
|
MODNAME(wmmstru2.c);
|
|
|
|
//
|
|
// The following are required for the dynamic linking of Multi-Media code
|
|
// from within WOW. They are all defined in wmmedia.c
|
|
//
|
|
|
|
extern FARPROC mmAPIEatCmdEntry;
|
|
extern FARPROC mmAPIGetParamSize;
|
|
extern FARPROC mmAPIUnlockCmdTable;
|
|
extern FARPROC mmAPISendCmdW;
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* UnThunkMciCommand16
|
|
*
|
|
* This function "unthunks" a 32 bit mci send command request.
|
|
*
|
|
* The ideas behind this function were stolen from UnThunkWMMsg16,
|
|
* see wmsg16.c
|
|
*
|
|
\**********************************************************************/
|
|
INT UnThunkMciCommand16( MCIDEVICEID devID, UINT OrigCommand, DWORD OrigFlags,
|
|
DWORD OrigParms, DWORD NewParms, LPWSTR lpCommand,
|
|
UINT uTable )
|
|
{
|
|
BOOL fReturnValNotThunked = FALSE;
|
|
|
|
#if DBG
|
|
static LPSTR f_name = "UnThunkMciCommand16: ";
|
|
register int i;
|
|
int n;
|
|
|
|
dprintf3(( "UnThunkMciCommand :" ));
|
|
n = sizeof(mciMessageNames) / sizeof(MCI_MESSAGE_NAMES);
|
|
for ( i = 0; i < n; i++ ) {
|
|
if ( mciMessageNames[i].uMsg == OrigCommand ) {
|
|
break;
|
|
}
|
|
}
|
|
dprintf3(( "OrigCommand -> %lX", (DWORD)OrigCommand ));
|
|
dprintf3(( " Name -> %s", i != n ? mciMessageNames[i].lpstMsgName : "Unkown Name" ));
|
|
|
|
dprintf5(( " OrigFlags -> %lX", OrigFlags ));
|
|
dprintf5(( " OrigParms -> %lX", OrigParms ));
|
|
dprintf5(( " NewParms -> %lX", NewParms ));
|
|
|
|
//
|
|
// If NewParms is 0 we shouldn't be here, I haven't got an assert
|
|
// macro, but the following we do the same thing.
|
|
//
|
|
if ( NewParms == 0 ) {
|
|
dprintf(( "%scalled with NewParms == NULL !!", f_name ));
|
|
dprintf(( "Call StephenE NOW !!" ));
|
|
DebugBreak();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// We have to do a manual unthunk of MCI_SYSINFO because the
|
|
// command table is not consistent. As a command table should be
|
|
// available now we can load it and then use it to unthunk MCI_OPEN.
|
|
//
|
|
switch ( OrigCommand ) {
|
|
|
|
case MCI_OPEN:
|
|
UnThunkOpenCmd( OrigFlags, OrigParms, NewParms );
|
|
break;
|
|
|
|
case MCI_SYSINFO:
|
|
UnThunkSysInfoCmd( OrigFlags, OrigParms, NewParms );
|
|
break;
|
|
|
|
case MCI_STATUS:
|
|
UnThunkStatusCmd( devID, OrigFlags, OrigParms, NewParms );
|
|
break;
|
|
|
|
default:
|
|
fReturnValNotThunked = TRUE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Do we have a command table ? It is possible that we have
|
|
// a custom command but we did not find a custom command table, in which
|
|
// case we should just free the pNewParms storage.
|
|
//
|
|
if ( lpCommand != NULL ) {
|
|
|
|
//
|
|
// We now parse the custom command table to see if there is a
|
|
// return field in the parms structure.
|
|
//
|
|
dprintf3(( "%sUnthunking via command table", f_name ));
|
|
UnThunkCommandViaTable( lpCommand, OrigFlags, OrigParms,
|
|
NewParms, fReturnValNotThunked );
|
|
|
|
//
|
|
// Now we have finished with the command table we should unlock it.
|
|
//
|
|
dprintf4(( "%sUnlocking custom command table", f_name ));
|
|
(*mmAPIUnlockCmdTable)( uTable );
|
|
}
|
|
|
|
//
|
|
// All that needs to be done now is to free the storage
|
|
// that was allocated during the ThunkXxxCmd function.
|
|
//
|
|
dprintf4(( "%sFreeing storage.", f_name ));
|
|
free_w( (PBYTE)NewParms );
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
* UnThunkOpenCmd
|
|
*
|
|
* UnThunk the Open mci command parms.
|
|
\**********************************************************************/
|
|
VOID UnThunkOpenCmd( DWORD OrigFlags, DWORD OrigParms, DWORD NewParms )
|
|
{
|
|
|
|
#if DBG
|
|
static LPSTR f_name = "UnThunkOpenCmd: ";
|
|
#endif
|
|
|
|
LPMCI_OPEN_PARMS lpOpeParms = (LPMCI_OPEN_PARMS)NewParms;
|
|
PMCI_OPEN_PARMS16 lpOpeParms16;
|
|
WORD wDevice;
|
|
|
|
dprintf4(( "%sCopying Device ID.", f_name ));
|
|
|
|
GETVDMPTR( OrigParms, sizeof(MCI_OPEN_PARMS16), lpOpeParms16 );
|
|
wDevice = LOWORD( lpOpeParms->wDeviceID );
|
|
STOREWORD( lpOpeParms16->wDeviceID, wDevice );
|
|
FLUSHVDMPTR( OrigParms, sizeof(MCI_OPEN_PARMS16), lpOpeParms16 );
|
|
FREEVDMPTR( lpOpeParms16 );
|
|
|
|
dprintf5(( "wDeviceID -> %u", wDevice ));
|
|
|
|
if ( (OrigParms & MCI_OPEN_TYPE) && !(OrigParms & MCI_OPEN_TYPE_ID ) ) {
|
|
|
|
dprintf3(( "%sFreeing a STRING pointer", f_name ));
|
|
FREEPSZPTR( lpOpeParms->lpstrDeviceType );
|
|
}
|
|
|
|
if ( (OrigParms & MCI_OPEN_ELEMENT)
|
|
&& !(OrigParms & MCI_OPEN_ELEMENT_ID ) ) {
|
|
|
|
dprintf3(( "%sFreeing a STRING pointer", f_name ));
|
|
FREEPSZPTR( lpOpeParms->lpstrElementName );
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
* UnThunkSysInfoCmd
|
|
*
|
|
* UnThunk the SysInfo mci command parms.
|
|
\**********************************************************************/
|
|
VOID UnThunkSysInfoCmd( DWORD OrigFlags, DWORD OrigParms, DWORD NewParms )
|
|
{
|
|
|
|
#if DBG
|
|
static LPSTR f_name = "UnThunkSysInfoCmd: ";
|
|
#endif
|
|
|
|
LPMCI_SYSINFO_PARMS lpSysParms = (LPMCI_SYSINFO_PARMS)NewParms;
|
|
|
|
//
|
|
// Had better check that we did actually allocate
|
|
// a pointer.
|
|
//
|
|
if ( lpSysParms->lpstrReturn && lpSysParms->dwRetSize ) {
|
|
|
|
#if DBG
|
|
if ( !(OrigFlags & MCI_SYSINFO_QUANTITY) ) {
|
|
dprintf5(( "lpstrReturn -> %s", lpSysParms->lpstrReturn ));
|
|
}
|
|
else {
|
|
dprintf5(( "lpstrReturn -> %d", *(LPDWORD)lpSysParms->lpstrReturn ));
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Free lpSysParms->lpstrReturn;
|
|
//
|
|
dprintf4(( "%sFreeing lpstrReturn", f_name ));
|
|
FREEVDMPTR( lpSysParms->lpstrReturn );
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
* UnThunkMciStatus
|
|
*
|
|
* UnThunk the Status mci command parms.
|
|
\**********************************************************************/
|
|
VOID UnThunkStatusCmd( MCIDEVICEID devID, DWORD OrigFlags,
|
|
DWORD OrigParms, DWORD NewParms )
|
|
{
|
|
#if DBG
|
|
static LPSTR f_name = "UnThunkStatusCmd: ";
|
|
#endif
|
|
|
|
MCI_GETDEVCAPS_PARMS GetDevCaps;
|
|
DWORD dwRetVal;
|
|
DWORD dwParm16;
|
|
PDWORD pdwOrig16;
|
|
PDWORD pdwParm32;
|
|
int iReturnType = MCI_INTEGER;
|
|
|
|
/*
|
|
** If the MCI_STATUS_ITEM flag is not specified don't bother
|
|
** doing any unthunking.
|
|
*/
|
|
if ( !(OrigFlags & MCI_STATUS_ITEM) ) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** We need to determine what type of device we are
|
|
** dealing with. We can do this by send an MCI_GETDEVCAPS
|
|
** command to the device. (We might as well use the Unicode
|
|
** version of mciSendCommand and avoid another thunk).
|
|
*/
|
|
RtlZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) );
|
|
GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
|
|
dwRetVal = (*mmAPISendCmdW)( devID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM,
|
|
(DWORD)&GetDevCaps );
|
|
/*
|
|
** If we can't get the DevCaps then we are doomed.
|
|
*/
|
|
if ( dwRetVal ) {
|
|
dprintf(("%sFailure to get devcaps", f_name));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** Determine the dwReturn type.
|
|
*/
|
|
switch ( GetDevCaps.dwReturn ) {
|
|
|
|
case MCI_DEVTYPE_ANIMATION:
|
|
switch ( ((LPDWORD)NewParms)[2] ) {
|
|
|
|
case MCI_ANIM_STATUS_HWND:
|
|
iReturnType = MCI_HWND;
|
|
break;
|
|
|
|
case MCI_ANIM_STATUS_HPAL:
|
|
iReturnType = MCI_HPAL;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case MCI_DEVTYPE_OVERLAY:
|
|
if ( ((LPDWORD)NewParms)[2] == MCI_OVLY_STATUS_HWND ) {
|
|
iReturnType = MCI_HWND;
|
|
}
|
|
break;
|
|
|
|
case MCI_DEVTYPE_DIGITAL_VIDEO:
|
|
switch ( ((LPDWORD)NewParms)[2] ) {
|
|
|
|
case MCI_DGV_STATUS_HWND:
|
|
iReturnType = MCI_HWND;
|
|
break;
|
|
|
|
case MCI_DGV_STATUS_HPAL:
|
|
iReturnType = MCI_HPAL;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
/*
|
|
** Thunk the dwReturn value according to the required type
|
|
*/
|
|
GETVDMPTR( OrigParms, sizeof( MCI_STATUS_PARMS), pdwOrig16 );
|
|
pdwParm32 = (LPDWORD)((LPBYTE)NewParms + 4);
|
|
|
|
switch ( iReturnType ) {
|
|
case MCI_HPAL:
|
|
dprintf4(( "%sFound an HPAL return field", f_name ));
|
|
dwParm16 = MAKELONG( GETHPALETTE16( (HPALETTE)*pdwParm32 ), 0 );
|
|
STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
|
|
dprintf5(( "HDC32 -> 0x%lX", *pdwParm32 ));
|
|
dprintf5(( "HDC16 -> 0x%lX", dwParm16 ));
|
|
break;
|
|
|
|
case MCI_HWND:
|
|
dprintf4(( "%sFound an HWND return field", f_name ));
|
|
dwParm16 = MAKELONG( GETHWND16( (HWND)*pdwParm32 ), 0 );
|
|
STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
|
|
dprintf5(( "HWND32 -> 0x%lX", *pdwParm32 ));
|
|
dprintf5(( "HWND16 -> 0x%lX", dwParm16 ));
|
|
break;
|
|
|
|
case MCI_INTEGER:
|
|
dprintf4(( "%sFound an INTEGER return field", f_name ));
|
|
STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), *pdwParm32 );
|
|
dprintf5(( "INTEGER -> %ld", *pdwParm32 ));
|
|
break;
|
|
|
|
// no default: all possible cases accounted for
|
|
}
|
|
|
|
/*
|
|
** Free the VDM pointer as we have finished with it
|
|
*/
|
|
FLUSHVDMPTR( OrigParms, sizeof( MCI_STATUS_PARMS), pdwOrig16 );
|
|
FREEVDMPTR( pdwOrig16 );
|
|
|
|
}
|
|
/**********************************************************************\
|
|
* UnThunkCommandViaTable
|
|
*
|
|
* Thunks the return field if there is one and then frees and pointers
|
|
* that were got via GETVDMPTR or GETPSZPTR.
|
|
\**********************************************************************/
|
|
INT UnThunkCommandViaTable( LPWSTR lpCommand, DWORD dwFlags, DWORD OrigParms,
|
|
DWORD pNewParms, BOOL fReturnValNotThunked )
|
|
{
|
|
|
|
#if DBG
|
|
static LPSTR f_name = "UnThunkCommandViaTable: ";
|
|
#endif
|
|
|
|
LPWSTR lpFirstParameter;
|
|
|
|
UINT wID;
|
|
DWORD dwValue;
|
|
|
|
UINT wOffset32, wOffset1stParm32;
|
|
|
|
DWORD dwParm16;
|
|
DWORD Size;
|
|
PDWORD pdwOrig16;
|
|
PDWORD pdwParm32;
|
|
|
|
DWORD dwMask = 1;
|
|
|
|
//
|
|
// Calculate the size of this command parameter block in terms
|
|
// of bytes, then get a VDM pointer to the OrigParms.
|
|
//
|
|
Size = GetSizeOfParameter( lpCommand );
|
|
|
|
//
|
|
// Skip past command entry
|
|
//
|
|
lpCommand = (LPWSTR)((LPBYTE)lpCommand +
|
|
(*mmAPIEatCmdEntry)( lpCommand, NULL, NULL ));
|
|
//
|
|
// Get the next entry
|
|
//
|
|
lpFirstParameter = lpCommand;
|
|
|
|
//
|
|
// Skip past the DWORD return value
|
|
//
|
|
wOffset1stParm32 = 4;
|
|
|
|
lpCommand = (LPWSTR)((LPBYTE)lpCommand +
|
|
(*mmAPIEatCmdEntry)( lpCommand, &dwValue, &wID ));
|
|
//
|
|
// If it is a return value, skip it
|
|
//
|
|
if ( (wID == MCI_RETURN) && (fReturnValNotThunked) ) {
|
|
|
|
GETVDMPTR( OrigParms, Size, pdwOrig16 );
|
|
pdwParm32 = (LPDWORD)((LPBYTE)pNewParms + 4);
|
|
|
|
//
|
|
// Look for a string return type, these are a special case.
|
|
//
|
|
switch ( dwValue ) {
|
|
|
|
case MCI_STRING:
|
|
dprintf4(( "%sFound a STRING return field", f_name ));
|
|
//
|
|
// Get string pointer and length
|
|
//
|
|
Size = *(LPDWORD)((LPBYTE)pNewParms + 8);
|
|
|
|
//
|
|
// Get the 32 bit string pointer
|
|
//
|
|
if ( Size > 0 ) {
|
|
|
|
dprintf4(( "%sFreeing a return STRING pointer", f_name ));
|
|
dprintf5(( "STRING -> %s", (LPSTR)*pdwParm32 ));
|
|
FREEVDMPTR( (LPSTR)*pdwParm32 );
|
|
}
|
|
break;
|
|
|
|
case MCI_RECT:
|
|
{
|
|
PRECT pRect32 = (PRECT)((LPBYTE)pNewParms + 4);
|
|
PRECT16 pRect16 = (PRECT16)((LPBYTE)pdwOrig16 + 4);
|
|
|
|
dprintf4(( "%sFound a RECT return field", f_name ));
|
|
STORESHORT( pRect16->top, (SHORT)pRect32->top );
|
|
STORESHORT( pRect16->bottom, (SHORT)pRect32->bottom );
|
|
STORESHORT( pRect16->left, (SHORT)pRect32->left );
|
|
STORESHORT( pRect16->right, (SHORT)pRect32->right );
|
|
}
|
|
break;
|
|
|
|
case MCI_INTEGER:
|
|
//
|
|
// Get the 32 bit return integer and store it in the
|
|
// 16 bit parameter structure.
|
|
//
|
|
dprintf4(( "%sFound an INTEGER return field", f_name ));
|
|
STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), *pdwParm32 );
|
|
dprintf5(( "INTEGER -> %ld", *pdwParm32 ));
|
|
break;
|
|
|
|
case MCI_HWND:
|
|
dprintf4(( "%sFound an HWND return field", f_name ));
|
|
dwParm16 = MAKELONG( GETHWND16( (HWND)*pdwParm32 ), 0 );
|
|
STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
|
|
dprintf5(( "HWND32 -> 0x%lX", *pdwParm32 ));
|
|
dprintf5(( "HWND16 -> 0x%lX", dwParm16 ));
|
|
break;
|
|
|
|
case MCI_HPAL:
|
|
dprintf4(( "%sFound an HPAL return field", f_name ));
|
|
dwParm16 = MAKELONG( GETHPALETTE16( (HPALETTE)*pdwParm32 ), 0 );
|
|
STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
|
|
dprintf5(( "HDC32 -> 0x%lX", *pdwParm32 ));
|
|
dprintf5(( "HDC16 -> 0x%lX", dwParm16 ));
|
|
break;
|
|
|
|
case MCI_HDC:
|
|
dprintf4(( "%sFound an HDC return field", f_name ));
|
|
dwParm16 = MAKELONG( GETHDC16( (HDC)*pdwParm32 ), 0 );
|
|
STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
|
|
dprintf5(( "HDC32 -> 0x%lX", *pdwParm32 ));
|
|
dprintf5(( "HDC16 -> 0x%lX", dwParm16 ));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Free the VDM pointer as we have finished with it
|
|
//
|
|
FLUSHVDMPTR( OrigParms, Size, pdwOrig16 );
|
|
FREEVDMPTR( pdwOrig16 );
|
|
|
|
//
|
|
// Adjust the offset of the first parameter.
|
|
//
|
|
wOffset1stParm32 = (*mmAPIGetParamSize)( dwValue, wID );
|
|
|
|
//
|
|
// Save the new first parameter
|
|
//
|
|
lpFirstParameter = lpCommand;
|
|
}
|
|
|
|
//
|
|
// Walk through each flag looking for strings to free
|
|
//
|
|
while ( dwMask != 0 ) {
|
|
|
|
//
|
|
// Is this bit set?
|
|
//
|
|
if ( (dwFlags & dwMask) != 0 ) {
|
|
|
|
wOffset32 = wOffset1stParm32;
|
|
lpCommand = (LPWSTR)((LPBYTE)lpFirstParameter +
|
|
(*mmAPIEatCmdEntry)( lpFirstParameter,
|
|
&dwValue, &wID ));
|
|
|
|
//
|
|
// What parameter uses this bit?
|
|
//
|
|
while ( wID != MCI_END_COMMAND && dwValue != dwMask ) {
|
|
|
|
wOffset32 = (*mmAPIGetParamSize)( dwValue, wID );
|
|
|
|
if ( wID == MCI_CONSTANT ) {
|
|
|
|
while ( wID != MCI_END_CONSTANT ) {
|
|
|
|
lpCommand = (LPWSTR)((LPBYTE)lpCommand +
|
|
(*mmAPIEatCmdEntry)( lpCommand, NULL, &wID ));
|
|
}
|
|
}
|
|
lpCommand = (LPWSTR)((LPBYTE)lpCommand +
|
|
(*mmAPIEatCmdEntry)( lpCommand, &dwValue, &wID ));
|
|
}
|
|
|
|
if ( wID == MCI_STRING ) {
|
|
dprintf4(( "%sFreeing a STRING pointer", f_name ));
|
|
pdwParm32 = (LPDWORD)((LPBYTE)pNewParms + wOffset32);
|
|
FREEPSZPTR( (LPSTR)*pdwParm32 );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go to the next flag
|
|
//
|
|
dwMask <<= 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|