|
|
/******************************Module*Header*******************************\
* Module Name: mmwowmci.c * * Thunks for the mci api's. * * * Created: 28-09-93 * Author: Stephen Estrop [StephenE] * * Copyright (c) 1993-1998 Microsoft Corporation \**************************************************************************/ #include "winmmi.h"
#include "mci.h"
#include <digitalv.h>
#include <stdlib.h>
#include "mixer.h"
#define _INC_ALL_WOWSTUFF
#include "mmwow32.h"
#include "mmwowmci.h"
#include "mmwowcb.h"
extern void WOWAppExit( HANDLE hTask );
STATICFN void mciFreeDevice(LPMCI_DEVICE_NODE nodeWorking); STATICFN MCIDEVICEID NEAR mciAllocateNode ( DWORD dwFlags, LPCWSTR lpDeviceName, LPMCI_DEVICE_NODE FAR *lpnodeNew);
#ifndef _WIN64
/******************************Public*Routine******************************\
* mci32Message * * Entry point for all the mci thunks. * * History: * 22-11-93 - StephenE - Created * \**************************************************************************/ DWORD WINAPI mci32Message( DWORD dwApi, DWORD dwF1, DWORD dwF2, DWORD dwF3, DWORD dwF4 ) {
DWORD dwRet;
switch ( dwApi ) {
case THUNK_MCI_SENDCOMMAND: dwRet = WMM32mciSendCommand( dwF1, dwF2, dwF3, dwF4 ); break;
case THUNK_MCI_SENDSTRING: dwRet = WMM32mciSendString( dwF1, dwF2, dwF3, dwF4 ); break;
case THUNK_MCI_GETDEVICEID: dwRet = WMM32mciGetDeviceID( dwF1 ); break;
case THUNK_MCI_GETDEVIDFROMELEMID: dwRet = WMM32mciGetDeviceIDFromElementID( dwF1, dwF2 ); break;
case THUNK_MCI_GETERRORSTRING: dwRet = WMM32mciGetErrorString( dwF1, dwF2, dwF3 ); break;
case THUNK_MCI_SETYIELDPROC: dwRet = WMM32mciSetYieldProc( dwF1, dwF2, dwF3 ); break;
case THUNK_MCI_GETYIELDPROC: dwRet = WMM32mciGetYieldProc( dwF1, dwF2 ); break;
case THUNK_MCI_GETCREATORTASK: dwRet = WMM32mciGetCreatorTask( dwF1 ); break;
case THUNK_APP_EXIT: /*
** Now tidy up the other stuff. */ dwRet = 0; //Keep the compiler happy
WOWAppExit( (HANDLE)GetCurrentThreadId() ); break;
case THUNK_MCI_ALLOCATE_NODE: dwRet = WMM32mciAllocateNode( dwF1, dwF2 ); break;
case THUNK_MCI_FREE_NODE: dwRet = WMM32mciFreeNode( dwF1 ); break;
}
return dwRet; }
/**********************************************************************\
* WMM32mciSendCommand * * * This function sends a command message to the specified MCI device. * \**********************************************************************/ DWORD WMM32mciSendCommand( DWORD dwF1, DWORD dwF2, DWORD dwF3, DWORD dwF4 ) { PMCI_GENERIC_PARMS16 lp16OrigParms; DWORD ul; DWORD NewParms[MCI_MAX_PARAM_SLOTS]; LPWSTR lpCommand; UINT uTable;
if ( dwF2 == DRV_CONFIGURE ) {
typedef struct { DWORD dwDCISize; LPCSTR lpszDCISectionName; LPCSTR lpszDCIAliasName; } DRVCONFIGINFO16; typedef DRVCONFIGINFO16 UNALIGNED *LPDRVCONFIGINFO16;
LPDRVCONFIGINFO16 lpdrvConf;
lpdrvConf = GETVDMPTR(dwF4);
if (lpdrvConf && (lpdrvConf->dwDCISize == sizeof(DRVCONFIGINFO16))) {
DRVCONFIGINFO drvConf; LPCSTR lpStr1 = lpdrvConf->lpszDCISectionName; LPCSTR lpStr2 = lpdrvConf->lpszDCIAliasName;
drvConf.dwDCISize = sizeof(drvConf); drvConf.lpszDCISectionName = AllocUnicodeStr( GETVDMPTR(lpStr1) );
if (NULL == drvConf.lpszDCISectionName) { return MCIERR_OUT_OF_MEMORY; }
drvConf.lpszDCIAliasName = AllocUnicodeStr( GETVDMPTR(lpStr2) );
if (NULL == lpdrvConf->lpszDCIAliasName) {
FreeUnicodeStr((LPWSTR)drvConf.lpszDCISectionName); return MCIERR_OUT_OF_MEMORY; }
ul = mciSendCommandW( dwF1, dwF2, (DWORD)HWND32(LOWORD(dwF3)), (DWORD)(LPVOID)&drvConf );
FreeUnicodeStr( (LPWSTR)drvConf.lpszDCIAliasName ); FreeUnicodeStr( (LPWSTR)drvConf.lpszDCISectionName );
return ul;
}
return DRVCNF_CANCEL; }
/*
** lparam (dwF4) is a 16:16 pointer. This Requires parameter ** translation and probably memory copying, similar to the WM message ** thunks. A whole thunk/unthunk table should be created. ** ** Shouldn't these be FETCHDWORD, FETCHWORD macros? ** else MIPS problems ensue */ lpCommand = NULL; uTable = 0; lp16OrigParms = GETVDMPTR( dwF4 );
try {
ul = ThunkMciCommand16( (MCIDEVICEID)INT32( dwF1 ), (UINT)dwF2, dwF3, lp16OrigParms, NewParms, &lpCommand, &uTable );
/*
** OK so far ? If not don't bother calling into winmm. */ if ( ul == 0 ) {
dprintf3(( "About to call mciSendCommand." )); ul = (DWORD)mciSendCommandA( (MCIDEVICEID)INT32( dwF1 ), (UINT)dwF2, dwF3, (DWORD)NewParms ); dprintf3(( "return code-> %ld", ul ));
/*
** We have to special case the MCI_CLOSE command. MCI_CLOSE usually ** causes the device to become unloaded. This means that lpCommand ** now points to invalid memory. We can fix this by setting ** lpCommand to NULL. */ if ( dwF2 == MCI_CLOSE ) { lpCommand = NULL; }
UnThunkMciCommand16( (MCIDEVICEID)INT32( dwF1 ), UINT32( dwF2 ), DWORD32( dwF3 ), lp16OrigParms, NewParms, lpCommand, uTable ); /*
** Print a blank line so that I can distinguish the commands on the ** debugger. This is only necessary if the debug level is >= 3. */ dprintf3(( " " )); #if DBG
if ( DebugLevel >= 6 ) DebugBreak(); #endif
}
} except( GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
dprintf(( "UNKOWN access violation processing 0x%X command", UINT32(dwF2) ));
}
return ul; }
/**********************************************************************\
* * WMM32mciSendString * * This function sends a command string to an MCI device. The device that the * command is sent to is specified in the command string. * \**********************************************************************/ DWORD WMM32mciSendString( DWORD dwF1, DWORD dwF2, DWORD dwF3, DWORD dwF4 ) {
//
// The use of volatile here is to bypass a bug with the intel
// compiler.
//
# define MAX_MCI_CMD_LEN 256
volatile ULONG ul = MMSYSERR_INVALPARAM; PSZ pszCommand; PSZ pszReturnString = NULL; UINT uSize; CHAR szCopyCmd[MAX_MCI_CMD_LEN];
/*
** Test against a NULL pointer for the command name. */ pszCommand = GETVDMPTR(dwF1); if ( pszCommand ) {
# define MAP_INTEGER 0
# define MAP_HWND 1
# define MAP_HPALETTE 2
int MapReturn = MAP_INTEGER; WORD wMappedHandle; char *psz;
/*
** make a copy of the command string and then force it to ** all lower case. Then scan the string looking for the word ** "status". If we find it scan the string again looking for the ** word "handle", if we find it scan the the string again looking ** for palette or window. Then set a flag to remind us to convert ** the handle back from 32 to 16 bits. */ strncpy( szCopyCmd, pszCommand, MAX_MCI_CMD_LEN ); szCopyCmd[ MAX_MCI_CMD_LEN - 1 ] = '\0'; CharLowerBuff( szCopyCmd, MAX_MCI_CMD_LEN );
/*
** Skip past any white space ie. " \t\r\n" ** If the next 6 characters after any white space are not ** "status" don't bother with any other tests. */ psz = szCopyCmd + strspn( szCopyCmd, " \t\r\n" ); if ( strncmp( psz, "status", 6 ) == 0 ) {
if ( strstr( psz, "handle" ) ) {
if ( strstr( psz, "window" ) ) { MapReturn = MAP_HWND; } else if ( strstr( psz, "palette" ) ) { MapReturn = MAP_HPALETTE; } } }
/*
** Test against a zero length string and a NULL pointer */ uSize = (UINT)dwF3; if( uSize != 0 ) {
MMGETOPTPTR(dwF2, uSize, pszReturnString);
if ( pszReturnString == NULL ) { uSize = 0; } }
dprintf3(( "wow32: mciSendString -> %s", pszCommand ));
ul = (DWORD)mciSendStringA( pszCommand, pszReturnString, uSize, HWND32(LOWORD(dwF4)) );
#if DBG
if ( pszReturnString && *pszReturnString ) { dprintf3(( "wow32: mciSendString return -> %s", pszReturnString )); } #endif
if ( pszReturnString && *pszReturnString ) {
switch ( MapReturn ) {
case MAP_HWND: MapReturn = atoi( pszReturnString ); wMappedHandle = (WORD)GETHWND16( (HWND)MapReturn ); wsprintf( pszReturnString, "%d", wMappedHandle ); dprintf2(( "Mapped 32 bit Window %s to 16 bit %u", pszReturnString, wMappedHandle )); break;
case MAP_HPALETTE: MapReturn = atoi( pszReturnString ); dprintf2(( "Mapped 32 bit palette %s", pszReturnString )); wMappedHandle = (WORD)GETHPALETTE16( (HPALETTE)MapReturn ); wsprintf( pszReturnString, "%d", wMappedHandle ); dprintf2(( "Mapped 32 bit Palette %s to 16 bit %u", pszReturnString, wMappedHandle )); break; } }
}
return ul;
# undef MAP_INTEGER
# undef MAP_HWND
# undef MAP_HPALETTE
# undef MAX_MCI_CMD_LEN
}
/**********************************************************************\
* * WMM32mciGetDeviceID * * This assumes that the string is incoming, and the ID is returned in the WORD. * * This function retrieves the device ID corresponding to the name of an * open MCI device. * \**********************************************************************/ DWORD WMM32mciGetDeviceID( DWORD dwF1 ) { DWORD ul = 0L; PSZ pszName;
/*
** Test against a NULL pointer for the device name. */ pszName = GETVDMPTR(dwF1); if ( pszName ) {
ul = mciGetDeviceIDA( pszName ); }
return ul; }
/**********************************************************************\
* * WMM32mciGetErrorString * * This function returns a textual description of the specified MCI error. * \**********************************************************************/ DWORD WMM32mciGetErrorString( DWORD dwF1, DWORD dwF2, DWORD dwF3 ) { PSZ pszBuffer; DWORD ul = 0;
/*
** Test against a zero length string and a NULL pointer */ MMGETOPTPTR( dwF2, dwF3, pszBuffer); if ( pszBuffer ) {
ul = (DWORD)mciGetErrorStringA( dwF1, pszBuffer, (UINT)dwF3 ); }
return ul; }
#if 0
/**********************************************************************\
* * WMM32mciExecute * * This function is a simplified version of the mciSendString function. It does * not take a buffer for return information, and it displays a message box when * errors occur. * * THIS FUNCTION SHOULD NOT BE USED - IT IS RETAINED ONLY FOR BACKWARD * COMPATABILITY WITH WIN 3.0 APPS - USE mciSendString INSTEAD... * \**********************************************************************/ DWORD WMM32mciExecute( DWORD dwF1 ) { DWORD ul = 0; PSZ pszCommand;
/*
** Test against a NULL pointer for the command string. */ pszCommand = GETVDMPTR(dwF1); if ( pszCommand ) {
ul = (DWORD)mciExecute( pszCommand ); }
return ul; } #endif
/**********************************************************************\
* * WMM32mciGetDeviceIDFromElementID * * This function - um, yes, well... * * It appears in the headers but not in the book... * \**********************************************************************/ DWORD WMM32mciGetDeviceIDFromElementID( DWORD dwF1, DWORD dwF2 ) { ULONG ul = 0; PSZ pszDeviceID;
/*
** Test against a NULL pointer for the device name. */ pszDeviceID = GETVDMPTR(dwF2); if ( pszDeviceID ) {
ul = (DWORD)mciGetDeviceIDFromElementIDA( dwF1, pszDeviceID );
} return ul; }
/**********************************************************************\
* * WMM32mciGetCreatorTask * * This function - um again. Ditto for book and headers also. * \**********************************************************************/ DWORD WMM32mciGetCreatorTask( DWORD dwF1 ) { ULONG ul;
ul = GETHTASK16( mciGetCreatorTask( (MCIDEVICEID)INT32(dwF1) ));
return ul; }
/**********************************************************************\
* * WMM32mciSetYieldProc * * \**********************************************************************/ DWORD WMM32mciSetYieldProc( DWORD dwF1, DWORD dwF2, DWORD dwF3 ) { ULONG ul; YIELDPROC YieldProc32; INSTANCEDATA *lpYieldProcInfo; DWORD dwYieldData = 0;
/*
** We may have already set a YieldProc for this device ID. If so we ** have to free the INSTANCEDATA structure here. mciGetYieldProc ** returns NULL is no YieldProc was specified. */ YieldProc32 = (YIELDPROC)mciGetYieldProc( (MCIDEVICEID)INT32(dwF1), &dwYieldData );
if ( (YieldProc32 == WMM32mciYieldProc) && (dwYieldData != 0) ) { winmmFree( (INSTANCEDATA *)dwYieldData ); }
if ( dwF2 == 0 ) { YieldProc32 = NULL; dwYieldData = 0; } else { /*
** Allocate some storage for a INSTANCEDATA structure and save ** the passed 16 bit parameters. This storage get freed when the ** application calls mciSetYieldProc with a NULL YieldProc. */ lpYieldProcInfo = winmmAlloc( sizeof(INSTANCEDATA) ); if ( lpYieldProcInfo == NULL ) { ul = (ULONG)MMSYSERR_NOMEM; goto exit_app; }
dwYieldData = (DWORD)lpYieldProcInfo; YieldProc32 = WMM32mciYieldProc;
lpYieldProcInfo->dwCallback = dwF2; lpYieldProcInfo->dwCallbackInstance = dwF3; }
ul = (DWORD)mciSetYieldProc( (MCIDEVICEID)INT32(dwF1), YieldProc32, dwYieldData ); /*
** If the call failed free the storage here. */ if ( ul == FALSE ) { winmmFree( (INSTANCEDATA *)dwYieldData ); }
exit_app: return ul; }
/**********************************************************************\
* * WMM32mciYieldProc * * Here we call the real 16 bit YieldProc. This function assumes that * we yield on the wow thread. If this is not the case we get instant * death inside CallBack16. * * 12th Jan 1993 - The bad news is that the mci yield proc is NOT always * called back on the thread that set it. This means that we cannot callback * into the 16bit code because the calling thread does not have a 16bit * stack. * \**********************************************************************/ UINT WMM32mciYieldProc( MCIDEVICEID wDeviceID, DWORD dwYieldData ) { wDeviceID = (MCIDEVICEID)0; dwYieldData = 0; return 0; }
/**********************************************************************\
* * WMM32mciGetYieldProc * * \**********************************************************************/ DWORD WMM32mciGetYieldProc( DWORD dwF1, DWORD dwF2 ) { ULONG ul = 0; YIELDPROC YieldProc32; DWORD dwYieldData = 0; DWORD UNALIGNED *pdw1;
/*
** Get the address of the 32 bit yield proc. */ YieldProc32 = (YIELDPROC)mciGetYieldProc( (MCIDEVICEID)INT32(dwF1), &dwYieldData );
/*
** Did we set it ? If so it must point to WMM32mciYieldProc. */ if ( ((YieldProc32 == WMM32mciYieldProc) && (dwYieldData != 0)) ) {
ul = ((INSTANCEDATA *)dwYieldData)->dwCallback;
pdw1 = GETVDMPTR( dwF2 ); *pdw1 = ((INSTANCEDATA *)dwYieldData)->dwCallbackInstance; }
return ul; }
/**********************************************************************\
* * WMM32mciAllocateNode * * \**********************************************************************/ DWORD WMM32mciAllocateNode( DWORD dwF1, // dwOpenFlags
DWORD dwF2 // lpszDeviceName
) { LPMCI_DEVICE_NODE lpNode32; LPWSTR lpDeviceName32; ULONG ul = 0;
// Thunk 16-bit params and allocate a 32-bit device node
if ((lpDeviceName32 = AllocUnicodeStr(GETVDMPTR(dwF2))) != NULL) { if ((ul = mciAllocateNode(dwF1, lpDeviceName32, &lpNode32)) != 0) { // Mark this device as 16-bit
lpNode32->dwMCIFlags |= MCINODE_16BIT_DRIVER; } FreeUnicodeStr(lpDeviceName32); } return ul; }
/**********************************************************************\
* * WMM32mciFreeNode * * \**********************************************************************/ DWORD WMM32mciFreeNode( DWORD dwF2 ) { LPMCI_DEVICE_NODE lpNode32;
if ((lpNode32 = MCI_lpDeviceList[dwF2]) != NULL) { mciFreeDevice(lpNode32); }
return 0; }
#if DBG
MCI_MESSAGE_NAMES mciMessageNames[32] = { { MCI_OPEN, "MCI_OPEN" }, { MCI_CLOSE, "MCI_CLOSE" }, { MCI_ESCAPE, "MCI_ESCAPE" }, { MCI_PLAY, "MCI_PLAY" }, { MCI_SEEK, "MCI_SEEK" }, { MCI_STOP, "MCI_STOP" }, { MCI_PAUSE, "MCI_PAUSE" }, { MCI_INFO, "MCI_INFO" }, { MCI_GETDEVCAPS, "MCI_GETDEVCAPS" }, { MCI_SPIN, "MCI_SPIN" }, { MCI_SET, "MCI_SET" }, { MCI_STEP, "MCI_STEP" }, { MCI_RECORD, "MCI_RECORD" }, { MCI_SYSINFO, "MCI_SYSINFO" }, { MCI_BREAK, "MCI_BREAK" }, { MCI_SOUND, "MCI_SOUND" }, { MCI_SAVE, "MCI_SAVE" }, { MCI_STATUS, "MCI_STATUS" }, { MCI_CUE, "MCI_CUE" }, { MCI_REALIZE, "MCI_REALIZE" }, { MCI_WINDOW, "MCI_WINDOW" }, { MCI_PUT, "MCI_PUT" }, { MCI_WHERE, "MCI_WHERE" }, { MCI_FREEZE, "MCI_FREEZE" }, { MCI_UNFREEZE, "MCI_UNFREEZE" }, { MCI_LOAD, "MCI_LOAD" }, { MCI_CUT, "MCI_CUT" }, { MCI_COPY, "MCI_COPY" }, { MCI_PASTE, "MCI_PASTE" }, { MCI_UPDATE, "MCI_UPDATE" }, { MCI_RESUME, "MCI_RESUME" }, { MCI_DELETE, "MCI_DELETE" } }; #endif
/**********************************************************************\
* * ThunkMciCommand16 * * This function converts a 16 bit mci command request into an * equiverlant 32 bit request. * * The ideas behind this function were stolen from ThunkWMMsg16, * see wmsg16.c and mciDebugOut see mci.c * * We return 0 if the thunk was OK, any other value should be used as * an error code. If the thunk failed all allocated resources will * be freed by this function. If the thunk was sucessful (ie. returned 0) * UnThunkMciCommand16 MUST be called to free allocated resources. * * Here are the assumptions that I have used to perform the thunking: * * 1. MCI_OPEN is a special case. * * 2. If the message is NOT defined in mmsystem.h then it is treated as a * "user" command. If a user command table is associated with the given * device ID we use this command table as an aid to perform the thunking. * If a user command table is NOT associated with the device ID the * command does NOT GET THUNKED, we return straight away, calling * mciSendCommand only to get a relevant error code. * * 3. If the command IS defined in mmsystem.h we perfrom a "manual" thunk * of the command IF the associated PARMS structure contains ReservedX * fields. We mask out the associated flags as each field is thunked. * * 4. If there are any flags left then we use the command table * as an aid to perform the thunking. * \**********************************************************************/ DWORD ThunkMciCommand16( MCIDEVICEID DeviceID, UINT OrigCommand, DWORD OrigFlags, PMCI_GENERIC_PARMS16 lp16OrigParms, PDWORD pNewParms, LPWSTR *lplpCommand, PUINT puTable ) { #if DBG
register int i; int n;
dprintf3(( "ThunkMciCommand16 :" )); dprintf5(( " OrigDevice -> %lX", DeviceID ));
n = sizeof(mciMessageNames) / sizeof(MCI_MESSAGE_NAMES); for ( i = 0; i < n; i++ ) { if ( mciMessageNames[i].uMsg == OrigCommand ) { break; } } dprintf3(( "OrigCommand -> 0x%lX", (DWORD)OrigCommand ));
//
// Special case MCI_STATUS. I get loads of these from mplayer.
// I only want to display MCI_STATUS messages if the debug level is
// set to level 3, that way I won't get swamped with them.
//
if ( mciMessageNames[i].uMsg != MCI_STATUS ) { if ( i != n ) { dprintf2(( "Command Name -> %s", mciMessageNames[i].lpstMsgName )); } else { dprintf2(( "Command Name -> UNKNOWN COMMAND (%x)", OrigCommand )); } } else { dprintf3(( "Command Name -> MCI_STATUS" )); }
dprintf5(( "OrigFlags -> 0x%lX", OrigFlags )); dprintf5(( "OrigParms -> 0x%lX", lp16OrigParms )); #endif
//
// Thunk the generic params. These are common to all mci devices.
//
ThunkGenericParms( &OrigFlags, lp16OrigParms, (PMCI_GENERIC_PARMS)pNewParms );
//
// We thunk the MCI_OPEN command and all other commands that contain a
// "ReservedX" field in their PARMS structure here. We mask out each
// flag as it is processed, if any flags are left we use the command
// table to complete the thunk.
//
// The following commands have ReservedX fields:
// MCI_WINDOW
// MCI_SET
//
// This means that MOST COMMANDS GET THUNKED VIA THE COMMAND TABLE.
//
switch ( OrigCommand ) {
case MCI_OPEN: //
// MCI_OPEN is a special case message that I don't
// how to deal with yet.
//
ThunkOpenCmd( &OrigFlags, (PMCI_OPEN_PARMS16)lp16OrigParms, (PMCI_OPEN_PARMS)pNewParms ); return 0;
//
// The next four commands have Reserved padding fields
// these have to thunked manually.
//
case MCI_SET: ThunkSetCmd( DeviceID, &OrigFlags, (PMCI_SET_PARMS16)lp16OrigParms, (PMCI_SET_PARMS)pNewParms ); break;
case MCI_WINDOW: ThunkWindowCmd( DeviceID, &OrigFlags, (PMCI_ANIM_WINDOW_PARMS16)lp16OrigParms, (PMCI_ANIM_WINDOW_PARMS)pNewParms ); break;
//
// Have to special case this command because the command table
// is not correct.
//
case MCI_SETVIDEO: ThunkSetVideoCmd( &OrigFlags, (PMCI_DGV_SETVIDEO_PARMS16)lp16OrigParms, (LPMCI_DGV_SETVIDEO_PARMS)pNewParms ); break;
//
// These two commands don't have any command extensions
// so we return immediately.
//
case MCI_SYSINFO: ThunkSysInfoCmd( (PMCI_SYSINFO_PARMS16)lp16OrigParms, (PMCI_SYSINFO_PARMS)pNewParms ); return 0;
case MCI_BREAK: ThunkBreakCmd( &OrigFlags, (PMCI_BREAK_PARMS16)lp16OrigParms, (PMCI_BREAK_PARMS)pNewParms ); return 0; }
//
// Find the command table for the given command ID.
// We always load the command table this is because the command table is
// needed for UnThunking.
//
*lplpCommand = FindCommandItem( DeviceID, NULL, (LPWSTR)OrigCommand, NULL, puTable ); //
// If the command table is not found we return straight away.
// Note that storage has been allocated for pNewParms and that the
// MCI_WAIT and MCI_NOTIFY flags have been thunked.
// We do not return an error here, but call mciSendCommand to
// let it determine a suitable error code, we must also call
// UnthunkMciCommand to free the allocated storage.
//
if ( *lplpCommand == NULL ) { dprintf(( "Command table not found !!" )); return 0; } dprintf4(( "Command table has been loaded -> 0x%lX", *lplpCommand ));
//
// If OrigFlags is not equal to 0 we still have work to do !
// Note that this will be true for the majority of cases.
//
if ( OrigFlags ) {
dprintf3(( "Thunking via command table" ));
//
// Now we thunk the command
//
return ThunkCommandViaTable( *lplpCommand, OrigFlags, (DWORD UNALIGNED *)lp16OrigParms, (LPBYTE)pNewParms ); }
return 0;
}
/*****************************Private*Routine******************************\
* ThunkGenericParms * * As we know that the first dword field is a Window handle * this field is taken care of here. Also the MCI_WAIT flag is * masked out if it is set. * * * History: * 22-11-93 - StephenE - Created * \**************************************************************************/ VOID ThunkGenericParms( PDWORD pOrigFlags, PMCI_GENERIC_PARMS16 lp16GenParms, PMCI_GENERIC_PARMS lp32GenParms ) {
// Look for the notify flag and thunk accordingly
//
if ( *pOrigFlags & MCI_NOTIFY ) {
dprintf4(( "AllocMciParmBlock: Got MCI_NOTIFY flag." ));
lp32GenParms->dwCallback = (DWORD)HWND32( FETCHWORD( lp16GenParms->dwCallback ) );
}
*pOrigFlags &= ~(MCI_WAIT | MCI_NOTIFY); }
/**********************************************************************\
* ThunkOpenCmd * * Thunk the Open mci command parms. \**********************************************************************/ DWORD ThunkOpenCmd( PDWORD pOrigFlags, PMCI_OPEN_PARMS16 lp16OpenParms, PMCI_OPEN_PARMS p32OpenParms ) { PMCI_ANIM_OPEN_PARMS p32OpenAnimParms; PMCI_WAVE_OPEN_PARMS p32OpenWaveParms;
PMCI_ANIM_OPEN_PARMS16 lpOpenAnimParms16; PMCI_WAVE_OPEN_PARMS16 lp16OpenWaveParms;
//
// Now scan our way thru all the known MCI_OPEN flags, thunking as
// necessary.
//
// Start at the Device Type field
//
if ( *pOrigFlags & MCI_OPEN_TYPE ) { if ( *pOrigFlags & MCI_OPEN_TYPE_ID ) {
dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_TYPE_ID flag." ));
p32OpenParms->lpstrDeviceType = (LPSTR)lp16OpenParms->lpstrDeviceType;
dprintf5(( "lpstrDeviceType -> %ld", p32OpenParms->lpstrDeviceType ));
} else {
dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_TYPE flag" ));
p32OpenParms->lpstrDeviceType = GETVDMPTR( lp16OpenParms->lpstrDeviceType );
dprintf5(( "lpstrDeviceType -> %s", p32OpenParms->lpstrDeviceType )); dprintf5(( "lpstrDeviceType -> 0x%lX", p32OpenParms->lpstrDeviceType )); } }
//
// Now do the Element Name field
//
if ( *pOrigFlags & MCI_OPEN_ELEMENT ) { if ( *pOrigFlags & MCI_OPEN_ELEMENT_ID ) {
dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ELEMENT_ID flag" )); p32OpenParms->lpstrElementName = (LPSTR)( FETCHDWORD( lp16OpenParms->lpstrElementName ) ); dprintf5(( "lpstrElementName -> %ld", p32OpenParms->lpstrElementName ));
} else {
dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ELEMENT flag" )); p32OpenParms->lpstrElementName = GETVDMPTR( lp16OpenParms->lpstrElementName ); dprintf5(( "lpstrElementName -> %s", p32OpenParms->lpstrElementName )); dprintf5(( "lpstrElementName -> 0x%lX", p32OpenParms->lpstrElementName )); } }
//
// Now do the Alias Name field
//
if ( *pOrigFlags & MCI_OPEN_ALIAS ) {
dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ALIAS flag" )); p32OpenParms->lpstrAlias = GETVDMPTR( lp16OpenParms->lpstrAlias ); dprintf5(( "lpstrAlias -> %s", p32OpenParms->lpstrAlias )); dprintf5(( "lpstrAlias -> 0x%lX", p32OpenParms->lpstrAlias )); }
//
// Clear the MCI_OPEN_SHAREABLE flag if it is set
//
#if DBG
if ( *pOrigFlags & MCI_OPEN_SHAREABLE ) { dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_SHAREABLE flag." )); } #endif
*pOrigFlags &= ~(MCI_OPEN_SHAREABLE | MCI_OPEN_ALIAS | MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID | MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID);
//
// If we don't have any extended flags I can return now
//
if ( *pOrigFlags == 0 ) { return (DWORD)p32OpenParms; }
//
// If there are any flags left then these are intended for an extended
// form of MCI open. Three different forms are known, these being:
// MCI_ANIM_OPEN_PARMS
// MCI_OVLY_OPEN_PARMS
// MCI_WAVE_OPEN_PARMS
//
// If I could tell what sort of device I had I could thunk the
// extensions with no problems, but we don't have a device ID yet
// so I can't figure out what sort of device I have without parsing
// the parameters that I already know about.
//
// But, I am in luck; MCI_WAVE_OPEN_PARMS has one extended parameter
// dwBufferSeconds which has a MCI_WAVE_OPEN_BUFFER flag associated with
// it. This field is also a DWORD in the other two parms structures.
//
if ( *pOrigFlags & MCI_WAVE_OPEN_BUFFER ) { //
// Set up the VDM ptr for lpOpenWaveParms16 to point to OrigParms
//
lp16OpenWaveParms = (PMCI_WAVE_OPEN_PARMS16)lp16OpenParms; p32OpenWaveParms = (PMCI_WAVE_OPEN_PARMS)p32OpenParms;
dprintf4(( "ThunkOpenCmd: Got MCI_WAVE_OPEN_BUFFER flag." )); p32OpenWaveParms->dwBufferSeconds = FETCHDWORD( lp16OpenWaveParms->dwBufferSeconds ); dprintf5(( "dwBufferSeconds -> %ld", p32OpenWaveParms->dwBufferSeconds )); }
//
// Now look for MCI_ANIM_OPEN_PARM and MCI_OVLY_OPEN_PARMS extensions.
// Set up the VDM ptr for lpOpenAnimParms16 to point to OrigParms
//
lpOpenAnimParms16 = (PMCI_ANIM_OPEN_PARMS16)lp16OpenParms; p32OpenAnimParms = (PMCI_ANIM_OPEN_PARMS)p32OpenParms;
//
// Check MCI_ANIN_OPEN_PARENT flag, this also checks
// the MCI_OVLY_OPEN_PARENT flag too.
//
if ( *pOrigFlags & MCI_ANIM_OPEN_PARENT ) {
dprintf4(( "ThunkOpenCmd: Got MCI_Xxxx_OPEN_PARENT flag." ));
p32OpenAnimParms->hWndParent = HWND32(FETCHWORD(lpOpenAnimParms16->hWndParent) ); }
//
// Check MCI_ANIN_OPEN_WS flag, this also checks
// the MCI_OVLY_OPEN_WS flag too.
//
if ( *pOrigFlags & MCI_ANIM_OPEN_WS ) {
dprintf4(( "ThunkOpenCmd: Got MCI_Xxxx_OPEN_WS flag." ));
p32OpenAnimParms->dwStyle = FETCHDWORD( lpOpenAnimParms16->dwStyle );
dprintf5(( "dwStyle -> %ld", p32OpenAnimParms->dwStyle )); }
#if DBG
//
// Check the MCI_ANIN_OPEN_NOSTATIC flag
//
if ( *pOrigFlags & MCI_ANIM_OPEN_NOSTATIC ) { dprintf4(( "ThunkOpenCmd: Got MCI_ANIM_OPEN_NOSTATIC flag." )); } #endif
*pOrigFlags &= ~(MCI_ANIM_OPEN_NOSTATIC | MCI_ANIM_OPEN_WS | MCI_ANIM_OPEN_PARENT | MCI_WAVE_OPEN_BUFFER);
return (DWORD)p32OpenParms; }
/**********************************************************************\
* ThunkSetCmd * * Thunk the ThunkSetCmd mci command parms. * * The following are "basic" flags that all devices must support. * MCI_SET_AUDIO * MCI_SET_DOOR_CLOSED * MCI_SET_DOOR_OPEN * MCI_SET_TIME_FORMAT * MCI_SET_VIDEO * MCI_SET_ON * MCI_SET_OFF * * The following are "extended" flags that "sequencer" devices support. * MCI_SEQ_SET_MASTER * MCI_SEQ_SET_OFFSET * MCI_SEQ_SET_PORT * MCI_SEQ_SET_SLAVE * MCI_SEQ_SET_TEMPO * * The following are "extended" flags that "waveaudio" devices support. * MCI_WAVE_INPUT * MCI_WAVE_OUTPUT * MCI_WAVE_SET_ANYINPUT * MCI_WAVE_SET_ANYOUTPUT * MCI_WAVE_SET_AVGBYTESPERSEC * MCI_WAVE_SET_BITSPERSAMPLES * MCI_WAVE_SET_BLOCKALIGN * MCI_WAVE_SET_CHANNELS * MCI_WAVE_SET_FORMAT_TAG * MCI_WAVE_SET_SAMPLESPERSEC * \**********************************************************************/ DWORD ThunkSetCmd( MCIDEVICEID DeviceID, PDWORD pOrigFlags, PMCI_SET_PARMS16 lpSetParms16, PMCI_SET_PARMS lpSetParms32 ) {
//
// The following pointers will be used to point to the original
// 16-bit Parms structure.
//
PMCI_WAVE_SET_PARMS16 lpSetWaveParms16; PMCI_SEQ_SET_PARMS16 lpSetSeqParms16;
//
// The following pointers will be used to point to the new
// 32-bit Parms structure.
//
PMCI_WAVE_SET_PARMS lpSetWaveParms32; PMCI_SEQ_SET_PARMS lpSetSeqParms32;
//
// GetDevCaps is used to determine what sort of device are dealing
// with. We need this information to determine if we should use
// standard, wave or sequencer MCI_SET structure.
//
MCI_GETDEVCAPS_PARMS GetDevCaps; DWORD dwRetVal;
//
// First do the fields that are common to all devices. Thunk the
// dwAudio field.
//
if ( *pOrigFlags & MCI_SET_AUDIO ) {
dprintf4(( "ThunkSetCmd: Got MCI_SET_AUDIO flag." )); lpSetParms32->dwAudio = FETCHDWORD( lpSetParms16->dwAudio ); dprintf5(( "dwAudio -> %ld", lpSetParms32->dwAudio )); }
//
// Thunk the dwTimeFormat field.
//
if ( *pOrigFlags & MCI_SET_TIME_FORMAT ) {
dprintf4(( "ThunkSetCmd: Got MCI_SET_TIME_FORMAT flag." )); lpSetParms32->dwTimeFormat = FETCHDWORD( lpSetParms16->dwTimeFormat ); dprintf5(( "dwTimeFormat -> %ld", lpSetParms32->dwTimeFormat )); }
#if DBG
//
// Mask out the MCI_SET_DOOR_CLOSED
//
if ( *pOrigFlags & MCI_SET_DOOR_CLOSED ) { dprintf4(( "ThunkSetCmd: Got MCI_SET_DOOR_CLOSED flag." )); }
//
// Mask out the MCI_SET_DOOR_OPEN
//
if ( *pOrigFlags & MCI_SET_DOOR_OPEN ) { dprintf4(( "ThunkSetCmd: Got MCI_SET_DOOR_OPEN flag." )); }
//
// Mask out the MCI_SET_VIDEO
//
if ( *pOrigFlags & MCI_SET_VIDEO ) { dprintf4(( "ThunkSetCmd: Got MCI_SET_VIDEO flag." )); }
//
// Mask out the MCI_SET_ON
//
if ( *pOrigFlags & MCI_SET_ON ) { dprintf4(( "ThunkSetCmd: Got MCI_SET_ON flag." )); }
//
// Mask out the MCI_SET_OFF
//
if ( *pOrigFlags & MCI_SET_OFF ) { dprintf4(( "ThunkSetCmd: Got MCI_SET_OFF flag." )); } #endif
*pOrigFlags &= ~(MCI_SET_AUDIO | MCI_SET_TIME_FORMAT | MCI_SET_OFF | MCI_SET_ON | MCI_SET_VIDEO | MCI_SET_DOOR_OPEN | MCI_SET_DOOR_CLOSED | MCI_SET_AUDIO | MCI_SET_TIME_FORMAT );
//
// We have done all the standard flags. If there are any flags
// still set we must have an extended command.
//
if ( *pOrigFlags == 0 ) { return (DWORD)lpSetParms32; }
//
// Now 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).
//
ZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) ); GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE; dwRetVal = mciSendCommandW( DeviceID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM, (DWORD)&GetDevCaps );
//
// What do we do if dwRetCode is not equal to 0 ? If this is the
// case it probably means that we have been given a duff device ID,
// anyway it is pointless to carry on with the thunk so I will clear
// the *pOrigFlags variable and return. This means that the 32 bit version
// of mciSendCommand will get called with only half the message thunked,
// but as there is probably already a problem with the device or
// the device ID is duff, mciSendCommand should be able to work out a
// suitable error code to return to the application.
//
if ( dwRetVal ) { *pOrigFlags = 0; return (DWORD)lpSetParms32; }
switch ( GetDevCaps.dwReturn ) {
case MCI_DEVTYPE_WAVEFORM_AUDIO:
//
// Set up the VDM ptr for lpSetWaveParms16 to point to OrigParms
//
dprintf3(( "ThunkSetCmd: Got a WaveAudio device." )); lpSetWaveParms16 = (PMCI_WAVE_SET_PARMS16)lpSetParms16; lpSetWaveParms32 = (PMCI_WAVE_SET_PARMS)lpSetParms32;
//
// Thunk the wInput field.
//
if ( *pOrigFlags & MCI_WAVE_INPUT ) {
dprintf4(( "ThunkSetCmd: Got MCI_WAVE_INPUT flag." )); lpSetWaveParms32->wInput = FETCHWORD( lpSetWaveParms16->wInput ); dprintf5(( "wInput -> %u", lpSetWaveParms32->wInput )); }
//
// Thunk the wOutput field.
//
if ( *pOrigFlags & MCI_WAVE_OUTPUT ) {
dprintf4(( "ThunkSetCmd: Got MCI_WAVE_OUTPUT flag." )); lpSetWaveParms32->wOutput = FETCHWORD( lpSetWaveParms16->wOutput ); dprintf5(( "wOutput -> %u", lpSetWaveParms32->wOutput )); }
//
// Thunk the wFormatTag field.
//
if ( *pOrigFlags & MCI_WAVE_SET_FORMATTAG ) {
dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_FORMATTAG flag." )); lpSetWaveParms32->wFormatTag = FETCHWORD( lpSetWaveParms16->wFormatTag ); dprintf5(( "wFormatTag -> %u", lpSetWaveParms32->wFormatTag )); }
//
// Thunk the nChannels field.
//
if ( *pOrigFlags & MCI_WAVE_SET_CHANNELS ) {
dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_CHANNELS flag." )); lpSetWaveParms32->nChannels = FETCHWORD( lpSetWaveParms16->nChannels ); dprintf5(( "nChannels -> %u", lpSetWaveParms32->nChannels )); }
//
// Thunk the nSamplesPerSec field.
//
if ( *pOrigFlags & MCI_WAVE_SET_SAMPLESPERSEC ) {
dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_SAMPLESPERSEC flag." )); lpSetWaveParms32->nSamplesPerSec = FETCHDWORD( lpSetWaveParms16->nSamplesPerSecond ); dprintf5(( "nSamplesPerSec -> %u", lpSetWaveParms32->nSamplesPerSec )); }
//
// Thunk the nAvgBytesPerSec field.
//
if ( *pOrigFlags & MCI_WAVE_SET_AVGBYTESPERSEC ) {
dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_AVGBYTESPERSEC flag." )); lpSetWaveParms32->nAvgBytesPerSec = FETCHDWORD( lpSetWaveParms16->nAvgBytesPerSec ); dprintf5(( "nAvgBytesPerSec -> %u", lpSetWaveParms32->nAvgBytesPerSec )); }
//
// Thunk the nBlockAlign field.
//
if ( *pOrigFlags & MCI_WAVE_SET_BLOCKALIGN ) {
dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_BLOCKALIGN flag." )); lpSetWaveParms32->nBlockAlign = FETCHWORD( lpSetWaveParms16->nBlockAlign ); dprintf5(( "nBlockAlign -> %u", lpSetWaveParms32->nBlockAlign )); }
//
// Thunk the nBitsPerSample field.
//
if ( *pOrigFlags & MCI_WAVE_SET_BITSPERSAMPLE ) { dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_BITSPERSAMPLE flag." )); lpSetWaveParms32->wBitsPerSample = FETCHWORD( lpSetWaveParms16->wBitsPerSample ); dprintf5(( "wBitsPerSamples -> %u", lpSetWaveParms32->wBitsPerSample )); }
//
// Turn off all the flags in one go.
//
*pOrigFlags &= ~(MCI_WAVE_INPUT | MCI_WAVE_SET_BITSPERSAMPLE | MCI_WAVE_SET_BLOCKALIGN | MCI_WAVE_SET_AVGBYTESPERSEC | MCI_WAVE_SET_SAMPLESPERSEC | MCI_WAVE_SET_CHANNELS | MCI_WAVE_SET_FORMATTAG | MCI_WAVE_OUTPUT);
break;
case MCI_DEVTYPE_SEQUENCER: //
// Set up the VDM ptr for lpSetSeqParms16 to point to OrigParms
//
dprintf3(( "ThunkSetCmd: Got a Sequencer device." )); lpSetSeqParms16 = (PMCI_SEQ_SET_PARMS16)lpSetParms16; lpSetSeqParms32 = (PMCI_SEQ_SET_PARMS)lpSetParms32;
//
// Thunk the dwMaster field.
//
if ( *pOrigFlags & MCI_SEQ_SET_MASTER ) {
dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_MASTER flag." )); lpSetSeqParms32->dwMaster = FETCHDWORD( lpSetSeqParms16->dwMaster ); dprintf5(( "dwMaster -> %ld", lpSetSeqParms32->dwMaster )); }
//
// Thunk the dwPort field.
//
if ( *pOrigFlags & MCI_SEQ_SET_PORT ) {
dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_PORT flag." )); lpSetSeqParms32->dwPort = FETCHDWORD( lpSetSeqParms16->dwPort ); dprintf5(( "dwPort -> %ld", lpSetSeqParms32->dwPort )); }
//
// Thunk the dwOffset field.
//
if ( *pOrigFlags & MCI_SEQ_SET_OFFSET ) {
dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_OFFSET flag." )); lpSetSeqParms32->dwOffset= FETCHDWORD( lpSetSeqParms16->dwOffset ); dprintf5(( "dwOffset -> %ld", lpSetSeqParms32->dwOffset )); }
//
// Thunk the dwSlave field.
//
if ( *pOrigFlags & MCI_SEQ_SET_SLAVE ) {
dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_SLAVE flag." )); lpSetSeqParms32->dwSlave = FETCHDWORD( lpSetSeqParms16->dwSlave ); dprintf5(( "dwSlave -> %ld", lpSetSeqParms32->dwSlave )); }
//
// Thunk the dwTempo field.
//
if ( *pOrigFlags & MCI_SEQ_SET_TEMPO ) {
dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_TEMPO flag." )); lpSetSeqParms32->dwTempo = FETCHDWORD( lpSetSeqParms16->dwTempo ); dprintf5(( "dwTempo -> %ld", lpSetSeqParms32->dwTempo )); }
//
// Turn off all the flags in one go.
//
*pOrigFlags &= ~(MCI_SEQ_SET_MASTER | MCI_SEQ_SET_PORT | MCI_SEQ_SET_OFFSET | MCI_SEQ_SET_SLAVE | MCI_SEQ_SET_TEMPO); break;
}
return (DWORD)lpSetParms32; }
/**********************************************************************\
* ThunkSetVideoCmd * * Thunk the SetVideo mci command parms. * \**********************************************************************/ DWORD ThunkSetVideoCmd( PDWORD pOrigFlags, PMCI_DGV_SETVIDEO_PARMS16 lpSetParms16, LPMCI_DGV_SETVIDEO_PARMS lpSetParms32 ) {
if ( *pOrigFlags & MCI_DGV_SETVIDEO_ITEM ) {
dprintf4(( "ThunkSetVideoCmd: Got MCI_DGV_SETVIDEO_ITEM flag." )); lpSetParms32->dwItem = FETCHDWORD( lpSetParms16->dwItem ); dprintf5(( "dwItem -> %ld", lpSetParms32->dwItem )); }
if ( *pOrigFlags & MCI_DGV_SETVIDEO_VALUE ) {
if ( lpSetParms32->dwItem == MCI_DGV_SETVIDEO_PALHANDLE ) {
HPAL16 hpal16;
dprintf4(( "ThunkSetVideoCmd: Got MCI_DGV_SETVIDEO_PALHANDLE." ));
hpal16 = (HPAL16)LOWORD( FETCHDWORD( lpSetParms16->dwValue ) ); lpSetParms32->dwValue = (DWORD)HPALETTE32( hpal16 ); dprintf5(( "\t-> 0x%X", hpal16 ));
} else {
dprintf4(( "ThunkSetVideoCmd: Got an MCI_INTEGER." )); lpSetParms32->dwValue = FETCHDWORD( lpSetParms16->dwValue ); dprintf5(( "dwValue -> %ld", lpSetParms32->dwValue )); } }
#if DBG
//
// Turn off the MCI_SET_ON FLAG.
//
if ( *pOrigFlags & MCI_SET_ON ) { dprintf4(( "ThunkSetVideoCmd: Got MCI_SET_ON flag." )); }
//
// Turn off the MCI_SET_OFF FLAG.
//
if ( *pOrigFlags & MCI_SET_OFF ) { dprintf4(( "ThunkSetVideoCmd: Got MCI_SET_OFF flag." )); } #endif
*pOrigFlags &= ~(MCI_DGV_SETVIDEO_ITEM | MCI_DGV_SETVIDEO_VALUE | MCI_SET_ON | MCI_SET_OFF);
return (DWORD)lpSetParms32;
}
/**********************************************************************\
* ThunkSysInfoCmd * * Thunk the SysInfo mci command parms. \**********************************************************************/ DWORD ThunkSysInfoCmd( PMCI_SYSINFO_PARMS16 lpSysInfo16, PMCI_SYSINFO_PARMS lpSysInfo32 ) {
//
// Thunk the dwRetSize, dwNumber and wDeviceType parameters.
//
lpSysInfo32->dwRetSize = FETCHDWORD( lpSysInfo16->dwRetSize ); dprintf5(( "dwRetSize -> %ld", lpSysInfo32->dwRetSize ));
lpSysInfo32->dwNumber = FETCHDWORD( lpSysInfo16->dwNumber ); dprintf5(( "dwNumber -> %ld", lpSysInfo32->dwNumber ));
lpSysInfo32->wDeviceType = (UINT)FETCHWORD( lpSysInfo16->wDeviceType ); dprintf5(( "wDeviceType -> %ld", lpSysInfo32->wDeviceType ));
//
// Thunk lpstrReturn
//
if ( lpSysInfo32->dwRetSize > 0 ) {
lpSysInfo32->lpstrReturn = GETVDMPTR( lpSysInfo16->lpstrReturn ); dprintf5(( "lpstrReturn -> 0x%lX", lpSysInfo16->lpstrReturn )); } else { dprintf1(( "ThunkSysInfoCmd: lpstrReturn is 0 bytes long !!!" ));
/* lpstrReturn has been set to NULL by ZeroMemory above */ }
return (DWORD)lpSysInfo32;
}
/**********************************************************************\
* ThunkBreakCmd * * Thunk the Break mci command parms. \**********************************************************************/ DWORD ThunkBreakCmd( PDWORD pOrigFlags, PMCI_BREAK_PARMS16 lpBreak16, PMCI_BREAK_PARMS lpBreak32 ) { //
// Check for the MCI_BREAK_KEY flag
//
if ( *pOrigFlags & MCI_BREAK_KEY ) { dprintf4(( "ThunkBreakCmd: Got MCI_BREAK_KEY flag." )); lpBreak32->nVirtKey = (int)FETCHWORD( lpBreak16->nVirtKey ); dprintf5(( "nVirtKey -> %d", lpBreak32->nVirtKey )); }
//
// Check for the MCI_BREAK_HWND flag
//
if ( *pOrigFlags & MCI_BREAK_HWND ) { dprintf4(( "ThunkBreakCmd: Got MCI_BREAK_HWND flag." )); lpBreak32->hwndBreak = HWND32(FETCHWORD(lpBreak16->hwndBreak)); } return (DWORD)lpBreak32;
}
/**********************************************************************\
* ThunkWindowCmd * * Thunk the mci Window command parms. \**********************************************************************/ DWORD ThunkWindowCmd( MCIDEVICEID DeviceID, PDWORD pOrigFlags, PMCI_ANIM_WINDOW_PARMS16 lpAniParms16, PMCI_ANIM_WINDOW_PARMS lpAniParms32 ) { //
// GetDevCaps is used to determine what sort of device are dealing
// with. We need this information to determine if we should use
// overlay or animation MCI_WINDOW structure.
//
MCI_GETDEVCAPS_PARMS GetDevCaps; DWORD dwRetVal;
//
// Now 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).
//
ZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) ); GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE; dwRetVal = mciSendCommandW( DeviceID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM, (DWORD)&GetDevCaps ); //
// What do we do if dwRetCode is not equal to 0 ? If this is the
// case it probably means that we have been given a duff device ID,
// anyway it is pointless to carry on with the thunk so I will clear
// the *pOrigFlags variable and return. This means that the 32 bit version
// of mciSendCommand will get called with only half the message thunked,
// but as there is probably already a problem with the device or
// the device ID is duff, mciSendCommand should be able to work out a
// suitable error code to return to the application.
//
if ( dwRetVal ) { *pOrigFlags = 0; return (DWORD)lpAniParms32; }
//
// Do we have an Animation or Overlay device type ?
// Because Animation and Overlay have identical flags and
// parms structures they can share the same code.
//
if ( GetDevCaps.dwReturn == MCI_DEVTYPE_ANIMATION || GetDevCaps.dwReturn == MCI_DEVTYPE_OVERLAY || GetDevCaps.dwReturn == MCI_DEVTYPE_DIGITAL_VIDEO ) {
//
// Check for the MCI_ANIM_WINDOW_TEXT
//
if ( *pOrigFlags & MCI_ANIM_WINDOW_TEXT ) {
dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_TEXT flag." ));
lpAniParms32->lpstrText = GETVDMPTR( lpAniParms16->lpstrText );
dprintf5(( "lpstrText -> %s", lpAniParms32->lpstrText )); dprintf5(( "lpstrText -> 0x%lX", lpAniParms32->lpstrText ));
}
//
// Check for the MCI_ANIM_WINDOW_HWND flag
//
if ( *pOrigFlags & MCI_ANIM_WINDOW_HWND ) {
dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_HWND flag." )); lpAniParms32->hWnd = HWND32( FETCHWORD( lpAniParms16->hWnd ) ); dprintf5(( "hWnd -> 0x%lX", lpAniParms32->hWnd )); }
//
// Check for the MCI_ANIM_WINDOW_STATE flag
//
if ( *pOrigFlags & MCI_ANIM_WINDOW_STATE ) {
dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_STATE flag." )); lpAniParms32->nCmdShow = FETCHWORD( lpAniParms16->nCmdShow ); dprintf5(( "nCmdShow -> 0x%lX", lpAniParms32->nCmdShow )); }
#if DBG
//
// Check for the MCI_ANIM_WINDOW_DISABLE_STRETCH flag
//
if ( *pOrigFlags & MCI_ANIM_WINDOW_DISABLE_STRETCH ) { dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_DISABLE_STRETCH flag." )); }
//
// Check for the MCI_ANIM_WINDOW_ENABLE_STRETCH flag
//
if ( *pOrigFlags & MCI_ANIM_WINDOW_ENABLE_STRETCH ) { dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_ENABLE_STRETCH flag." )); } #endif
*pOrigFlags &= ~(MCI_ANIM_WINDOW_TEXT | MCI_ANIM_WINDOW_HWND | MCI_ANIM_WINDOW_STATE | MCI_ANIM_WINDOW_DISABLE_STRETCH | MCI_ANIM_WINDOW_ENABLE_STRETCH ); }
return (DWORD)lpAniParms32; }
/**********************************************************************\
* ThunkCommandViaTable * \**********************************************************************/ int ThunkCommandViaTable( LPWSTR lpCommand, DWORD dwFlags, DWORD UNALIGNED *pdwOrig16, LPBYTE pNewParms ) {
#if DBG
static LPSTR f_name = "ThunkCommandViaTable: "; #endif
LPWSTR lpFirstParameter;
UINT wID; DWORD dwValue;
UINT wOffset16, wOffset1stParm16; UINT wOffset32, wOffset1stParm32;
UINT wParamSize;
DWORD dwParm16; 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.
//
dprintf3(( "%s16 bit Parms -> %lX", f_name, pdwOrig16 ));
//
// Skip past command entry
//
lpCommand = (LPWSTR)((LPBYTE)lpCommand + mciEatCommandEntry( lpCommand, NULL, NULL )); //
// Get the next entry
//
lpFirstParameter = lpCommand;
//
// Skip past the DWORD return value
//
wOffset1stParm32 = wOffset1stParm16 = 4;
lpCommand = (LPWSTR)((LPBYTE)lpCommand + mciEatCommandEntry( lpCommand, &dwValue, &wID )); //
// If it is a return value, skip it
//
if ( wID == MCI_RETURN ) {
//
// Look for a string return type, these are a special case.
//
if ( dwValue == MCI_STRING ) {
DWORD dwStrlen; LPSTR *lplpStr;
//
// Get string pointer and length
//
dwParm16 = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + 4)); dwStrlen = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + 8));
//
// Copy string pointer
//
lplpStr = (LPSTR *)(pNewParms + 4); if ( dwStrlen > 0 ) { *lplpStr = GETVDMPTR( dwParm16 ); dprintf5(( "%sReturn string -> 0x%lX", f_name, *lplpStr )); dprintf5(( "%sReturn length -> 0x%lX", f_name, dwStrlen )); }
//
// Copy string length
//
pdwParm32 = (LPDWORD)(pNewParms + 8); *pdwParm32 = dwStrlen; }
//
// Adjust the offset of the first parameter. Remember that RECTS
// are a different size in 16-bit world.
//
wParamSize = mciGetParamSize( dwValue, wID ); wOffset1stParm16 += (dwValue == MCI_RECT ? sizeof(RECT16) : wParamSize); wOffset1stParm32 += wParamSize;
//
// Save the new first parameter
//
lpFirstParameter = lpCommand; }
//
// Walk through each flag
//
while ( dwMask != 0 ) {
//
// Is this bit set?
//
if ( (dwFlags & dwMask) != 0 ) {
wOffset16 = wOffset1stParm16; wOffset32 = wOffset1stParm32; lpCommand = (LPWSTR)((LPBYTE)lpFirstParameter + mciEatCommandEntry( lpFirstParameter, &dwValue, &wID ));
//
// What parameter uses this bit?
//
while ( wID != MCI_END_COMMAND && dwValue != dwMask ) {
wParamSize = mciGetParamSize( dwValue, wID ); wOffset16 += (wID == MCI_RECT ? sizeof( RECT16 ) : wParamSize); wOffset32 += wParamSize;
if ( wID == MCI_CONSTANT ) {
while ( wID != MCI_END_CONSTANT ) {
lpCommand = (LPWSTR)((LPBYTE)lpCommand + mciEatCommandEntry( lpCommand, NULL, &wID )); } } lpCommand = (LPWSTR)((LPBYTE)lpCommand + mciEatCommandEntry( lpCommand, &dwValue, &wID )); }
if ( wID != MCI_END_COMMAND ) {
//
// Thunk the argument if there is one. The argument is at
// wOffset16 from the start of OrigParms.
// This offset is in bytes.
//
dprintf5(( "%sOffset 16 -> 0x%lX", f_name, wOffset16 )); dprintf5(( "%sOffset 32 -> 0x%lX", f_name, wOffset32 ));
if ( wID != MCI_FLAG ) { dwParm16 = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + wOffset16)); pdwParm32 = (LPDWORD)(pNewParms + wOffset32); }
switch ( wID ) {
case MCI_STRING: { LPSTR str16 = (LPSTR)dwParm16; dprintf4(( "%sGot STRING flag -> 0x%lX", f_name, dwMask )); *pdwParm32 = (DWORD)GETVDMPTR( str16 ); dprintf5(( "%s\t-> 0x%lX", f_name, *pdwParm32 )); dprintf5(( "%s\t-> %s", f_name, *pdwParm32 )); } break;
case MCI_HWND: { HWND16 hwnd16; dprintf4(( "%sGot HWND flag -> 0x%lX", f_name, dwMask )); hwnd16 = (HWND16)LOWORD( dwParm16 ); *pdwParm32 = (DWORD)HWND32( hwnd16 ); dprintf5(( "\t-> 0x%X", hwnd16 )); } break;
case MCI_HPAL: { HPAL16 hpal16; dprintf4(( "%sGot HPAL flag -> 0x%lX", f_name, dwMask )); hpal16 = (HPAL16)LOWORD( dwParm16 ); *pdwParm32 = (DWORD)HPALETTE32( hpal16 ); dprintf5(( "\t-> 0x%X", hpal16 )); } break;
case MCI_HDC: { HDC16 hdc16; dprintf4(( "%sGot HDC flag -> 0x%lX", f_name, dwMask )); hdc16 = (HDC16)LOWORD( dwParm16 ); *pdwParm32 = (DWORD)HDC32( hdc16 ); dprintf5(( "\t-> 0x%X", hdc16 )); } break;
case MCI_RECT: { PRECT16 pRect16 = (PRECT16)((LPBYTE)pdwOrig16 + wOffset16); PRECT pRect32 = (PRECT)pdwParm32;
dprintf4(( "%sGot RECT flag -> 0x%lX", f_name, dwMask )); pRect32->top = (LONG)pRect16->top; pRect32->bottom = (LONG)pRect16->bottom; pRect32->left = (LONG)pRect16->left; pRect32->right = (LONG)pRect16->right; } break;
case MCI_CONSTANT: case MCI_INTEGER: dprintf4(( "%sGot INTEGER flag -> 0x%lX", f_name, dwMask )); *pdwParm32 = dwParm16; dprintf5(( "\t-> 0x%lX", dwParm16 )); break; } } }
//
// Go to the next flag
//
dwMask <<= 1; } return 0; }
/**********************************************************************\
* * 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, PMCI_GENERIC_PARMS16 lp16GenericParms, PDWORD 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", lp16GenericParms )); 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( (PMCI_OPEN_PARMS16)lp16GenericParms, (PMCI_OPEN_PARMS)NewParms ); break;
case MCI_SYSINFO: #if DBG
UnThunkSysInfoCmd( OrigFlags, (PMCI_SYSINFO_PARMS)NewParms ); #endif
break;
case MCI_STATUS: UnThunkStatusCmd( devID, OrigFlags, (DWORD UNALIGNED *)lp16GenericParms, (DWORD)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, (DWORD UNALIGNED *)lp16GenericParms, (DWORD)NewParms, fReturnValNotThunked );
//
// Now we have finished with the command table we should unlock it.
//
dprintf4(( "%sUnlocking custom command table", f_name )); mciUnlockCommandTable( uTable ); }
return 0; }
/**********************************************************************\
* UnThunkOpenCmd * * UnThunk the Open mci command parms. \**********************************************************************/ VOID UnThunkOpenCmd( PMCI_OPEN_PARMS16 lpOpenParms16, PMCI_OPEN_PARMS lpOpenParms32 ) { WORD wDevice;
dprintf4(( "Copying Device ID." ));
wDevice = LOWORD( lpOpenParms32->wDeviceID ); STOREWORD( lpOpenParms16->wDeviceID, wDevice );
dprintf5(( "wDeviceID -> %u", wDevice ));
}
#if DBG
/**********************************************************************\
* UnThunkSysInfoCmd * * UnThunk the SysInfo mci command parms. \**********************************************************************/ VOID UnThunkSysInfoCmd( DWORD OrigFlags, PMCI_SYSINFO_PARMS lpSysParms ) { //
// Had better check that we did actually allocate
// a pointer.
//
if ( lpSysParms->lpstrReturn && lpSysParms->dwRetSize ) {
if ( !(OrigFlags & MCI_SYSINFO_QUANTITY) ) { dprintf5(( "lpstrReturn -> %s", lpSysParms->lpstrReturn )); } else { dprintf5(( "lpstrReturn -> %d", *(LPDWORD)lpSysParms->lpstrReturn )); } } } #endif
/**********************************************************************\
* UnThunkMciStatus * * UnThunk the Status mci command parms. \**********************************************************************/ VOID UnThunkStatusCmd( MCIDEVICEID devID, DWORD OrigFlags, DWORD UNALIGNED *pdwOrig16, DWORD NewParms ) { #if DBG
static LPSTR f_name = "UnThunkStatusCmd: "; #endif
MCI_GETDEVCAPS_PARMS GetDevCaps; DWORD dwRetVal; DWORD dwParm16; 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). */ ZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) ); GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE; dwRetVal = mciSendCommandW( 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 */ 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
} }
/**********************************************************************\
* UnThunkCommandViaTable * * Thunks the return field if there is one and then frees and pointers * that were got via GETVDMPTR or GETVDMPTR. \**********************************************************************/ int UnThunkCommandViaTable( LPWSTR lpCommand, DWORD UNALIGNED *pdwOrig16, DWORD pNewParms, BOOL fReturnValNotThunked ) {
#if DBG
static LPSTR f_name = "UnThunkCommandViaTable: "; #endif
LPWSTR lpFirstParameter;
UINT wID; DWORD dwValue;
UINT wOffset1stParm32;
DWORD dwParm16; DWORD Size; PDWORD pdwParm32;
DWORD dwMask = 1;
//
// Skip past command entry
//
lpCommand = (LPWSTR)((LPBYTE)lpCommand + mciEatCommandEntry( lpCommand, NULL, NULL )); //
// Get the next entry
//
lpFirstParameter = lpCommand;
//
// Skip past the DWORD return value
//
wOffset1stParm32 = 4;
lpCommand = (LPWSTR)((LPBYTE)lpCommand + mciEatCommandEntry( lpCommand, &dwValue, &wID )); //
// If it is a return value, skip it
//
if ( (wID == MCI_RETURN) && (fReturnValNotThunked) ) {
pdwParm32 = (LPDWORD)((LPBYTE)pNewParms + 4);
//
// Look for a string return type, these are a special case.
//
switch ( dwValue ) {
#if DBG
case MCI_STRING: dprintf4(( "Found a STRING return field" )); //
// 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 )); } break; #endif
case MCI_RECT: { PRECT pRect32 = (PRECT)((LPBYTE)pNewParms + 4); PRECT16 pRect16 = (PRECT16)((LPBYTE)pdwOrig16 + 4);
dprintf4(( "%sFound a RECT return field", f_name )); pRect16->top = (SHORT)LOWORD(pRect32->top); pRect16->bottom = (SHORT)LOWORD(pRect32->bottom); pRect16->left = (SHORT)LOWORD(pRect32->left); pRect16->right = (SHORT)LOWORD(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; }
}
return 0; }
#endif // _WIN64
|