Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1579 lines
51 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WMMSTRU1.C
  8. * WOW32 16-bit MultiMedia structure conversion support
  9. * Contains support for mciSendCommand Thunk message Parms.
  10. * Also contains some debug support functions.
  11. *
  12. * History:
  13. * Created 14-Jul-1992 by Stephen Estrop (stephene)
  14. *
  15. --*/
  16. //
  17. // We define NO_STRICT so that the compiler doesn't moan and groan when
  18. // I use the FARPROC type for the Multi-Media api loading.
  19. //
  20. #define NO_STRICT
  21. #include "precomp.h"
  22. #pragma hdrstop
  23. #if 0
  24. MODNAME(wmmstru1.c);
  25. #if DBG
  26. int mmDebugLevel = -1;
  27. MCI_MESSAGE_NAMES mciMessageNames[32] = {
  28. { MCI_OPEN, "MCI_OPEN" },
  29. { MCI_CLOSE, "MCI_CLOSE" },
  30. { MCI_ESCAPE, "MCI_ESCAPE" },
  31. { MCI_PLAY, "MCI_PLAY" },
  32. { MCI_SEEK, "MCI_SEEK" },
  33. { MCI_STOP, "MCI_STOP" },
  34. { MCI_PAUSE, "MCI_PAUSE" },
  35. { MCI_INFO, "MCI_INFO" },
  36. { MCI_GETDEVCAPS, "MCI_GETDEVCAPS" },
  37. { MCI_SPIN, "MCI_SPIN" },
  38. { MCI_SET, "MCI_SET" },
  39. { MCI_STEP, "MCI_STEP" },
  40. { MCI_RECORD, "MCI_RECORD" },
  41. { MCI_SYSINFO, "MCI_SYSINFO" },
  42. { MCI_BREAK, "MCI_BREAK" },
  43. { MCI_SOUND, "MCI_SOUND" },
  44. { MCI_SAVE, "MCI_SAVE" },
  45. { MCI_STATUS, "MCI_STATUS" },
  46. { MCI_CUE, "MCI_CUE" },
  47. { MCI_REALIZE, "MCI_REALIZE" },
  48. { MCI_WINDOW, "MCI_WINDOW" },
  49. { MCI_PUT, "MCI_PUT" },
  50. { MCI_WHERE, "MCI_WHERE" },
  51. { MCI_FREEZE, "MCI_FREEZE" },
  52. { MCI_UNFREEZE, "MCI_UNFREEZE" },
  53. { MCI_LOAD, "MCI_LOAD" },
  54. { MCI_CUT, "MCI_CUT" },
  55. { MCI_COPY, "MCI_COPY" },
  56. { MCI_PASTE, "MCI_PASTE" },
  57. { MCI_UPDATE, "MCI_UPDATE" },
  58. { MCI_RESUME, "MCI_RESUME" },
  59. { MCI_DELETE, "MCI_DELETE" }
  60. };
  61. #endif
  62. //
  63. // The following are required for the dynamic linking of Multi-Media code
  64. // from within WOW. They are all defined in wmmedia.c
  65. //
  66. extern FARPROC mmAPIEatCmdEntry;
  67. extern FARPROC mmAPIGetParamSize;
  68. extern FARPROC mmAPISendCmdW;
  69. extern FINDCMDITEM mmAPIFindCmdItem;
  70. /**********************************************************************\
  71. *
  72. * ThunkMciCommand16
  73. *
  74. * This function converts a 16 bit mci command request into an
  75. * equiverlant 32 bit request.
  76. *
  77. * The ideas behind this function were stolen from ThunkWMMsg16,
  78. * see wmsg16.c and mciDebugOut see mci.c
  79. *
  80. * We return 0 if the thunk was OK, any other value should be used as
  81. * an error code. If the thunk failed all allocated resources will
  82. * be freed by this function. If the thunk was sucessful (ie. returned 0)
  83. * UnThunkMciCommand16 MUST be called to free allocated resources.
  84. *
  85. * Here are the assumptions that I have used to perform the thunking:
  86. *
  87. * 1. MCI_OPEN is a special case.
  88. *
  89. * 2. If the message is NOT defined in mmsystem.h then it is treated as a
  90. * "user" command. If a user command table is associated with the given
  91. * device ID we use this command table as an aid to perform the thunking.
  92. * If a user command table is NOT associated with the device ID the
  93. * command does NOT GET THUNKED, we return straight away, calling
  94. * mciSendCommand only to get a relevant error code.
  95. *
  96. * 3. If the command IS defined in mmsystem.h we perfrom a "manual" thunk
  97. * of the command IF the associated PARMS structure contains ReservedX
  98. * fields. We mask out the associated flags as each field is thunked.
  99. *
  100. * 4. If there are any flags left then we use the command table
  101. * as an aid to perform the thunking.
  102. *
  103. \**********************************************************************/
  104. INT ThunkMciCommand16( MCIDEVICEID DeviceID, UINT OrigCommand, DWORD OrigFlags,
  105. DWORD OrigParms, PDWORD pNewParms, LPWSTR *lplpCommand,
  106. PUINT puTable )
  107. {
  108. #if DBG
  109. register int i;
  110. int n;
  111. dprintf3(( "ThunkMciCommand16 :" ));
  112. dprintf5(( " OrigDevice -> %lX", DeviceID ));
  113. n = sizeof(mciMessageNames) / sizeof(MCI_MESSAGE_NAMES);
  114. for ( i = 0; i < n; i++ ) {
  115. if ( mciMessageNames[i].uMsg == OrigCommand ) {
  116. break;
  117. }
  118. }
  119. dprintf3(( "OrigCommand -> 0x%lX", (DWORD)OrigCommand ));
  120. //
  121. // Special case MCI_STATUS. I get loads of these from mplayer.
  122. // I only want to display MCI_STATUS messages if the debug level is
  123. // set to level 3, that way I won't get swamped with them.
  124. //
  125. if ( mciMessageNames[i].uMsg != MCI_STATUS ) {
  126. if ( i != n ) {
  127. dprintf2(( "Command Name -> %s", mciMessageNames[i].lpstMsgName ));
  128. }
  129. else {
  130. dprintf2(( "Command Name -> UNKNOWN COMMAND (%x)", OrigCommand ));
  131. }
  132. }
  133. else {
  134. dprintf3(( "Command Name -> MCI_STATUS" ));
  135. }
  136. dprintf5(( "OrigFlags -> 0x%lX", OrigFlags ));
  137. dprintf5(( "OrigParms -> 0x%lX", OrigParms ));
  138. #endif
  139. //
  140. // Get some storage for the Mci parameter block, and handle the
  141. // notify window handle (if supplied).
  142. //
  143. if ( (*pNewParms = AllocMciParmBlock( &OrigFlags, OrigParms )) == 0L ) {
  144. return MCIERR_OUT_OF_MEMORY;
  145. }
  146. //
  147. // We thunk the MCI_OPEN command and all other commands that contain a
  148. // "ReservedX" field in their PARMS structure here. We mask out each
  149. // flag as it is processed, if any flags are left we use the command
  150. // table to complete the thunk.
  151. //
  152. // The following commands have ReservedX fields:
  153. // MCI_WINDOW
  154. // MCI_SET
  155. //
  156. // This means that MOST COMMANDS GET THUNKED VIA THE COMMAND TABLE.
  157. //
  158. switch ( OrigCommand ) {
  159. case MCI_OPEN:
  160. //
  161. // MCI_OPEN is a special case message that I don't
  162. // how to deal with yet.
  163. //
  164. ThunkOpenCmd( &OrigFlags, OrigParms, *pNewParms );
  165. return 0;
  166. //
  167. // The next four commands have Reserved padding fields
  168. // these have to thunked manually.
  169. //
  170. case MCI_SET:
  171. ThunkSetCmd( DeviceID, &OrigFlags, OrigParms, *pNewParms );
  172. break;
  173. case MCI_WINDOW:
  174. ThunkWindowCmd( DeviceID, &OrigFlags, OrigParms, *pNewParms );
  175. break;
  176. //
  177. // Have to special case this command because the command table
  178. // is not correct.
  179. //
  180. case MCI_SETVIDEO:
  181. ThunkSetVideoCmd( DeviceID, &OrigFlags, OrigParms, *pNewParms );
  182. break;
  183. //
  184. // These two commands don't have any command extensions
  185. // so we return immediately.
  186. //
  187. case MCI_SYSINFO:
  188. ThunkSysInfoCmd( &OrigFlags, OrigParms, *pNewParms );
  189. return 0;
  190. case MCI_BREAK:
  191. ThunkBreakCmd( &OrigFlags, OrigParms, *pNewParms );
  192. return 0;
  193. }
  194. //
  195. // Find the command table for the given command ID.
  196. // We always load the command table this is because the command table is
  197. // needed for UnThunking.
  198. //
  199. *lplpCommand = (*mmAPIFindCmdItem)( DeviceID, NULL, (LPWSTR)OrigCommand,
  200. NULL, puTable );
  201. //
  202. // If the command table is not found we return straight away.
  203. // Note that storage has been allocated for pNewParms and that the
  204. // MCI_WAIT and MCI_NOTIFY flags have been thunked.
  205. // We do not return an error here, but call mciSendCommand to
  206. // let it determine a suitable error code, we must also call
  207. // UnthunkMciCommand to free the allocated storage.
  208. //
  209. if ( *lplpCommand == NULL ) {
  210. dprintf(( "Command table not found !!" ));
  211. return 0;
  212. }
  213. dprintf4(( "Command table has been loaded -> 0x%lX", *lplpCommand ));
  214. //
  215. // If OrigFlags is not equal to 0 we still have work to do !
  216. // Note that this will be true for the majority of cases.
  217. //
  218. if ( OrigFlags ) {
  219. dprintf3(( "Thunking via command table" ));
  220. //
  221. // Now we thunk the command
  222. //
  223. return ThunkCommandViaTable( *lplpCommand, OrigFlags, OrigParms,
  224. *pNewParms );
  225. }
  226. return 0;
  227. }
  228. /**********************************************************************\
  229. * AllocMciParmBlock
  230. *
  231. * Get some storage for the Mci parameter block. I always allocate
  232. * MCI_MAX_PARAM_SLOTS * DWORD amount as this allows for any command
  233. * extensions.
  234. *
  235. * As we know that the first dword field is a Window handle
  236. * this field is taken care of here. Also the MCI_WAIT flag is
  237. * masked out if it is set.
  238. *
  239. \**********************************************************************/
  240. DWORD AllocMciParmBlock( PDWORD pOrigFlags, DWORD OrigParms )
  241. {
  242. LPMCI_GENERIC_PARMS lpGenParms;
  243. PMCI_GENERIC_PARMS16 lpGenParmsOrig;
  244. UINT AllocSize = sizeof(DWORD) * MCI_MAX_PARAM_SLOTS;
  245. //
  246. // Get, check and set the required storage.
  247. //
  248. lpGenParms = (LPMCI_GENERIC_PARMS)malloc_w( AllocSize );
  249. if ( lpGenParms == NULL ) {
  250. return 0L;
  251. }
  252. RtlZeroMemory( lpGenParms, AllocSize );
  253. dprintf4(( "AllocMciParmBlock: Allocated storage -> 0x%lX", lpGenParms ));
  254. //
  255. // Look for the notify flag and thunk accordingly
  256. //
  257. if ( *pOrigFlags & MCI_NOTIFY ) {
  258. GETVDMPTR( OrigParms, sizeof(MCI_GENERIC_PARMS16), lpGenParmsOrig );
  259. dprintf4(( "AllocMciParmBlock: Got MCI_NOTIFY flag." ));
  260. // Note FETCHWORD of a DWORD below, same as LOWORD(FETCHDWORD(dw)),
  261. // only faster.
  262. lpGenParms->dwCallback =
  263. (DWORD)HWND32( FETCHWORD( lpGenParmsOrig->dwCallback ) );
  264. FREEVDMPTR( lpGenParmsOrig );
  265. *pOrigFlags ^= MCI_NOTIFY;
  266. }
  267. //
  268. // If the MCI_WAIT flag is present, mask it out.
  269. //
  270. if ( *pOrigFlags & MCI_WAIT ) {
  271. dprintf4(( "AllocMciParmBlock: Got MCI_WAIT flag." ));
  272. *pOrigFlags ^= MCI_WAIT;
  273. }
  274. return (DWORD)lpGenParms;
  275. }
  276. /**********************************************************************\
  277. * ThunkOpenCmd
  278. *
  279. * Thunk the Open mci command parms.
  280. \**********************************************************************/
  281. DWORD ThunkOpenCmd( PDWORD pOrigFlags, DWORD OrigParms, DWORD pNewParms )
  282. {
  283. //
  284. // The purpose of this union is to aid the creation of a 32 bit
  285. // Open Parms structure that is suitable for all known MCI devices.
  286. //
  287. typedef union {
  288. MCI_OPEN_PARMS OpenParms;
  289. MCI_WAVE_OPEN_PARMS OpenWaveParms;
  290. MCI_ANIM_OPEN_PARMS OpenAnimParms; // Note: Animation and
  291. MCI_OVLY_OPEN_PARMS OpenOvlyParms; // overlay parms are identical
  292. } MCI_ALL_OPEN_PARMS, *PMCI_ALL_OPEN_PARMS;
  293. //
  294. // The following pointers will be used to point to
  295. // the original 16-bit Parms structure.
  296. //
  297. PMCI_OPEN_PARMS16 lpOpenParms16;
  298. PMCI_WAVE_OPEN_PARMS16 lpOpenWaveParms16;
  299. //
  300. // Note: MCI_ANIM_OPEN_PARMS16 and MCI_OVLY_OPEN_PARMS16 structures are
  301. // identical.
  302. //
  303. PMCI_ANIM_OPEN_PARMS16 lpOpenAnimParms16;
  304. //
  305. // pOp will point to the 32 bit open Parms structure after
  306. // we have finished all the thunking.
  307. //
  308. PMCI_ALL_OPEN_PARMS pOp = (PMCI_ALL_OPEN_PARMS)pNewParms;
  309. //
  310. // We first do the fields that are common to all open requests.
  311. // Set up the VDM ptr for lpOpenParms16 to point to OrigParms
  312. //
  313. GETVDMPTR( OrigParms, sizeof(MCI_OPEN_PARMS16), lpOpenParms16 );
  314. //
  315. // Now scan our way thru all the known MCI_OPEN flags, thunking as
  316. // necessary.
  317. //
  318. // Start at the Device Type field
  319. //
  320. if ( *pOrigFlags & MCI_OPEN_TYPE ) {
  321. if ( *pOrigFlags & MCI_OPEN_TYPE_ID ) {
  322. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_TYPE_ID flag." ));
  323. pOp->OpenParms.lpstrDeviceType =
  324. (LPSTR)( FETCHDWORD( lpOpenParms16->lpstrDeviceType ) );
  325. dprintf5(( "lpstrDeviceType -> %ld", pOp->OpenParms.lpstrDeviceType ));
  326. *pOrigFlags ^= (MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID);
  327. }
  328. else {
  329. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_TYPE flag" ));
  330. GETPSZPTR( lpOpenParms16->lpstrDeviceType,
  331. pOp->OpenParms.lpstrDeviceType );
  332. dprintf5(( "lpstrDeviceType -> %s", pOp->OpenParms.lpstrDeviceType ));
  333. dprintf5(( "lpstrDeviceType -> 0x%lX", pOp->OpenParms.lpstrDeviceType ));
  334. *pOrigFlags ^= MCI_OPEN_TYPE;
  335. }
  336. }
  337. //
  338. // Now do the Element Name field
  339. //
  340. if ( *pOrigFlags & MCI_OPEN_ELEMENT ) {
  341. if ( *pOrigFlags & MCI_OPEN_ELEMENT_ID ) {
  342. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ELEMENT_ID flag" ));
  343. pOp->OpenParms.lpstrElementName =
  344. (LPSTR)( FETCHDWORD( lpOpenParms16->lpstrElementName ) );
  345. dprintf5(( "lpstrElementName -> %ld", pOp->OpenParms.lpstrElementName ));
  346. *pOrigFlags ^= (MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID);
  347. }
  348. else {
  349. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ELEMENT flag" ));
  350. GETPSZPTR( lpOpenParms16->lpstrElementName,
  351. pOp->OpenParms.lpstrElementName );
  352. dprintf5(( "lpstrElementName -> %s", pOp->OpenParms.lpstrElementName ));
  353. dprintf5(( "lpstrElementName -> 0x%lX", pOp->OpenParms.lpstrElementName ));
  354. *pOrigFlags ^= MCI_OPEN_ELEMENT;
  355. }
  356. }
  357. //
  358. // Now do the Alias Name field
  359. //
  360. if ( *pOrigFlags & MCI_OPEN_ALIAS ) {
  361. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ALIAS flag" ));
  362. GETPSZPTR( lpOpenParms16->lpstrAlias, pOp->OpenParms.lpstrAlias );
  363. dprintf5(( "lpstrAlias -> %s", pOp->OpenParms.lpstrAlias ));
  364. dprintf5(( "lpstrAlias -> 0x%lX", pOp->OpenParms.lpstrAlias ));
  365. *pOrigFlags ^= MCI_OPEN_ALIAS;
  366. }
  367. //
  368. // Clear the MCI_OPEN_SHAREABLE flag if it is set
  369. //
  370. if ( *pOrigFlags & MCI_OPEN_SHAREABLE ) {
  371. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_SHAREABLE flag." ));
  372. *pOrigFlags ^= MCI_OPEN_SHAREABLE;
  373. }
  374. //
  375. // Free the VDM pointer before returning
  376. //
  377. FREEVDMPTR( lpOpenParms16 );
  378. //
  379. // If we don't have any extended flags I can return now
  380. //
  381. if ( *pOrigFlags == 0 ) {
  382. return (DWORD)pOp;
  383. }
  384. //
  385. // If there are any flags left then these are intended for an extended
  386. // form of MCI open. Three different forms are known, these being:
  387. // MCI_ANIM_OPEN_PARMS
  388. // MCI_OVLY_OPEN_PARMS
  389. // MCI_WAVE_OPEN_PARMS
  390. //
  391. // If I could tell what sort of device I had I could thunk the
  392. // extensions with no problems, but we don't have a device ID yet
  393. // so I can't figure out what sort of device I have without parsing
  394. // the parameters that I already know about.
  395. //
  396. // But, I am in luck; MCI_WAVE_OPEN_PARMS has one extended parameter
  397. // dwBufferSeconds which has a MCI_WAVE_OPEN_BUFFER flag associated with
  398. // it. This field is also a DWORD in the other two parms structures.
  399. //
  400. if ( *pOrigFlags & MCI_WAVE_OPEN_BUFFER ) {
  401. //
  402. // Set up the VDM ptr for lpOpenWaveParms16 to point to OrigParms
  403. //
  404. GETVDMPTR( OrigParms, sizeof(MCI_WAVE_OPEN_PARMS16),
  405. lpOpenWaveParms16 );
  406. dprintf4(( "ThunkOpenCmd: Got MCI_WAVE_OPEN_BUFFER flag." ));
  407. pOp->OpenWaveParms.dwBufferSeconds =
  408. FETCHDWORD( lpOpenWaveParms16->dwBufferSeconds );
  409. dprintf5(( "dwBufferSeconds -> %ld", pOp->OpenWaveParms.dwBufferSeconds ));
  410. //
  411. // Free the VDM pointer before returning
  412. //
  413. FREEVDMPTR( lpOpenWaveParms16 );
  414. *pOrigFlags ^= MCI_WAVE_OPEN_BUFFER;
  415. }
  416. //
  417. // Now look for MCI_ANIM_OPEN_PARM and MCI_OVLY_OPEN_PARMS extensions.
  418. //
  419. if ( (*pOrigFlags & MCI_ANIM_OPEN_PARENT)
  420. || (*pOrigFlags & MCI_ANIM_OPEN_WS) ) {
  421. //
  422. // Set up the VDM ptr for lpOpenAnimParms16 to point to OrigParms
  423. //
  424. GETVDMPTR( OrigParms, sizeof(MCI_ANIM_OPEN_PARMS16),
  425. lpOpenAnimParms16 );
  426. //
  427. // Check MCI_ANIN_OPEN_PARENT flag, this also checks
  428. // the MCI_OVLY_OPEN_PARENT flag too.
  429. //
  430. if ( *pOrigFlags & MCI_ANIM_OPEN_PARENT ) {
  431. dprintf4(( "ThunkOpenCmd: Got MCI_Xxxx_OPEN_PARENT flag." ));
  432. pOp->OpenAnimParms.hWndParent =
  433. HWND32(FETCHWORD(lpOpenAnimParms16->hWndParent) );
  434. *pOrigFlags ^= MCI_ANIM_OPEN_PARENT;
  435. }
  436. //
  437. // Check MCI_ANIN_OPEN_WS flag, this also checks
  438. // the MCI_OVLY_OPEN_WS flag too.
  439. //
  440. if ( *pOrigFlags & MCI_ANIM_OPEN_WS ) {
  441. dprintf4(( "ThunkOpenCmd: Got MCI_Xxxx_OPEN_WS flag." ));
  442. pOp->OpenAnimParms.dwStyle =
  443. FETCHDWORD( lpOpenAnimParms16->dwStyle );
  444. dprintf5(( "dwStyle -> %ld", pOp->OpenAnimParms.dwStyle ));
  445. *pOrigFlags ^= MCI_ANIM_OPEN_WS;
  446. }
  447. //
  448. // Free the VDM pointer before returning
  449. //
  450. FREEVDMPTR( lpOpenAnimParms16 );
  451. }
  452. //
  453. // Check the MCI_ANIN_OPEN_NOSTATIC flag
  454. //
  455. if ( *pOrigFlags & MCI_ANIM_OPEN_NOSTATIC ) {
  456. dprintf4(( "ThunkOpenCmd: Got MCI_ANIM_OPEN_NOSTATIC flag." ));
  457. *pOrigFlags ^= MCI_ANIM_OPEN_NOSTATIC;
  458. }
  459. return (DWORD)pOp;
  460. }
  461. /**********************************************************************\
  462. * ThunkSetCmd
  463. *
  464. * Thunk the ThunkSetCmd mci command parms.
  465. *
  466. * The following are "basic" flags that all devices must support.
  467. * MCI_SET_AUDIO
  468. * MCI_SET_DOOR_CLOSED
  469. * MCI_SET_DOOR_OPEN
  470. * MCI_SET_TIME_FORMAT
  471. * MCI_SET_VIDEO
  472. * MCI_SET_ON
  473. * MCI_SET_OFF
  474. *
  475. * The following are "extended" flags that "sequencer" devices support.
  476. * MCI_SEQ_SET_MASTER
  477. * MCI_SEQ_SET_OFFSET
  478. * MCI_SEQ_SET_PORT
  479. * MCI_SEQ_SET_SLAVE
  480. * MCI_SEQ_SET_TEMPO
  481. *
  482. * The following are "extended" flags that "sequencer" devices support.
  483. * MCI_WAVE_INPUT
  484. * MCI_WAVE_OUTPUT
  485. * MCI_WAVE_SET_ANYINPUT
  486. * MCI_WAVE_SET_ANYOUTPUT
  487. * MCI_WAVE_SET_AVGBYTESPERSEC
  488. * MCI_WAVE_SET_BITSPERSAMPLES
  489. * MCI_WAVE_SET_BLOCKALIGN
  490. * MCI_WAVE_SET_CHANNELS
  491. * MCI_WAVE_SET_FORMAT_TAG
  492. * MCI_WAVE_SET_SAMPLESPERSEC
  493. *
  494. \**********************************************************************/
  495. DWORD ThunkSetCmd( MCIDEVICEID DeviceID, PDWORD pOrigFlags, DWORD OrigParms,
  496. DWORD pNewParms )
  497. {
  498. //
  499. // This purpose of this union is to aid the creation of a 32 bit Set
  500. // Parms structure that is suitable for all known MCI devices.
  501. //
  502. typedef union {
  503. MCI_SET_PARMS SetParms;
  504. MCI_WAVE_SET_PARMS SetWaveParms;
  505. MCI_SEQ_SET_PARMS SetSeqParms;
  506. } MCI_ALL_SET_PARMS, *PMCI_ALL_SET_PARMS;
  507. //
  508. // The following pointers will be used to point to the original
  509. // 16-bit Parms structure.
  510. //
  511. PMCI_SET_PARMS16 lpSetParms16;
  512. PMCI_WAVE_SET_PARMS16 lpSetWaveParms16;
  513. PMCI_SEQ_SET_PARMS16 lpSetSeqParms16;
  514. //
  515. // pSet will point to the 32 bit Set Parms structure after
  516. // we have finished all the thunking.
  517. //
  518. PMCI_ALL_SET_PARMS pSet = (PMCI_ALL_SET_PARMS)pNewParms;
  519. //
  520. // GetDevCaps is used to determine what sort of device are dealing
  521. // with. We need this information to determine if we should use
  522. // standard, wave or sequencer MCI_SET structure.
  523. //
  524. MCI_GETDEVCAPS_PARMS GetDevCaps;
  525. DWORD dwRetVal;
  526. //
  527. // Set up the VDM ptr for lpSetParms16 to point to OrigParms
  528. //
  529. GETVDMPTR( OrigParms, sizeof(MCI_SET_PARMS16), lpSetParms16 );
  530. //
  531. // First do the fields that are common to all devices. Thunk the
  532. // dwAudio field.
  533. //
  534. if ( *pOrigFlags & MCI_SET_AUDIO ) {
  535. dprintf4(( "ThunkSetCmd: Got MCI_SET_AUDIO flag." ));
  536. pSet->SetParms.dwAudio = FETCHDWORD( lpSetParms16->dwAudio );
  537. dprintf5(( "dwAudio -> %ld", pSet->SetParms.dwAudio ));
  538. *pOrigFlags ^= MCI_SET_AUDIO; // Mask out the flag
  539. }
  540. //
  541. // Thunk the dwTimeFormat field.
  542. //
  543. if ( *pOrigFlags & MCI_SET_TIME_FORMAT ) {
  544. dprintf4(( "ThunkSetCmd: Got MCI_SET_TIME_FORMAT flag." ));
  545. pSet->SetParms.dwTimeFormat = FETCHDWORD( lpSetParms16->dwTimeFormat );
  546. dprintf5(( "dwTimeFormat -> %ld", pSet->SetParms.dwTimeFormat ));
  547. *pOrigFlags ^= MCI_SET_TIME_FORMAT; // Mask out the flag
  548. }
  549. //
  550. // Mask out the MCI_SET_DOOR_CLOSED
  551. //
  552. if ( *pOrigFlags & MCI_SET_DOOR_CLOSED ) {
  553. dprintf4(( "ThunkSetCmd: Got MCI_SET_DOOR_CLOSED flag." ));
  554. *pOrigFlags ^= MCI_SET_DOOR_CLOSED; // Mask out the flag
  555. }
  556. //
  557. // Mask out the MCI_SET_DOOR_OPEN
  558. //
  559. if ( *pOrigFlags & MCI_SET_DOOR_OPEN ) {
  560. dprintf4(( "ThunkSetCmd: Got MCI_SET_DOOR_OPEN flag." ));
  561. *pOrigFlags ^= MCI_SET_DOOR_OPEN; // Mask out the flag
  562. }
  563. //
  564. // Mask out the MCI_SET_VIDEO
  565. //
  566. if ( *pOrigFlags & MCI_SET_VIDEO ) {
  567. dprintf4(( "ThunkSetCmd: Got MCI_SET_VIDEO flag." ));
  568. *pOrigFlags ^= MCI_SET_VIDEO; // Mask out the flag
  569. }
  570. //
  571. // Mask out the MCI_SET_ON
  572. //
  573. if ( *pOrigFlags & MCI_SET_ON ) {
  574. dprintf4(( "ThunkSetCmd: Got MCI_SET_ON flag." ));
  575. *pOrigFlags ^= MCI_SET_ON; // Mask out the flag
  576. }
  577. //
  578. // Mask out the MCI_SET_OFF
  579. //
  580. if ( *pOrigFlags & MCI_SET_OFF ) {
  581. dprintf4(( "ThunkSetCmd: Got MCI_SET_OFF flag." ));
  582. *pOrigFlags ^= MCI_SET_OFF; // Mask out the flag
  583. }
  584. //
  585. // Free the VDM pointer as we have finished with it
  586. //
  587. FREEVDMPTR( lpSetParms16 );
  588. //
  589. // We have done all the standard flags. If there are any flags
  590. // still set we must have an extended command.
  591. //
  592. if ( *pOrigFlags == 0 ) {
  593. return (DWORD)pSet;
  594. }
  595. //
  596. // Now we need to determine what type of device we are
  597. // dealing with. We can do this by send an MCI_GETDEVCAPS
  598. // command to the device. (We might as well use the Unicode
  599. // version of mciSendCommand and avoid another thunk).
  600. //
  601. RtlZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) );
  602. GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
  603. dwRetVal = (*mmAPISendCmdW)( DeviceID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM,
  604. (DWORD)&GetDevCaps );
  605. //
  606. // What do we do if dwRetCode is not equal to 0 ? If this is the
  607. // case it probably means that we have been given a duff device ID,
  608. // anyway it is pointless to carry on with the thunk so I will clear
  609. // the *pOrigFlags variable and return. This means that the 32 bit version
  610. // of mciSendCommand will get called with only half the message thunked,
  611. // but as there is probably already a problem with the device or
  612. // the device ID is duff, mciSendCommand should be able to work out a
  613. // suitable error code to return to the application.
  614. //
  615. if ( dwRetVal ) {
  616. *pOrigFlags = 0;
  617. return (DWORD)pSet;
  618. }
  619. switch ( GetDevCaps.dwReturn ) {
  620. case MCI_DEVTYPE_WAVEFORM_AUDIO:
  621. //
  622. // Set up the VDM ptr for lpSetWaveParms16 to point to OrigParms
  623. //
  624. dprintf3(( "ThunkSetCmd: Got a WaveAudio device." ));
  625. GETVDMPTR( OrigParms, sizeof(MCI_WAVE_SET_PARMS16),
  626. lpSetWaveParms16 );
  627. //
  628. // Thunk the wInput field.
  629. //
  630. if ( *pOrigFlags & MCI_WAVE_INPUT ) {
  631. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_INPUT flag." ));
  632. pSet->SetWaveParms.wInput =
  633. FETCHWORD( lpSetWaveParms16->wInput );
  634. dprintf5(( "wInput -> %u", pSet->SetWaveParms.wInput ));
  635. *pOrigFlags ^= MCI_WAVE_INPUT;
  636. }
  637. //
  638. // Thunk the wOutput field.
  639. //
  640. if ( *pOrigFlags & MCI_WAVE_OUTPUT ) {
  641. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_OUTPUT flag." ));
  642. pSet->SetWaveParms.wOutput =
  643. FETCHWORD( lpSetWaveParms16->wOutput );
  644. dprintf5(( "wOutput -> %u", pSet->SetWaveParms.wOutput ));
  645. *pOrigFlags ^= MCI_WAVE_OUTPUT;
  646. }
  647. //
  648. // Thunk the wFormatTag field.
  649. //
  650. if ( *pOrigFlags & MCI_WAVE_SET_FORMATTAG ) {
  651. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_FORMATTAG flag." ));
  652. pSet->SetWaveParms.wFormatTag =
  653. FETCHWORD( lpSetWaveParms16->wFormatTag );
  654. dprintf5(( "wFormatTag -> %u", pSet->SetWaveParms.wFormatTag ));
  655. *pOrigFlags ^= MCI_WAVE_SET_FORMATTAG;
  656. }
  657. //
  658. // Thunk the nChannels field.
  659. //
  660. if ( *pOrigFlags & MCI_WAVE_SET_CHANNELS ) {
  661. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_CHANNELS flag." ));
  662. pSet->SetWaveParms.nChannels =
  663. FETCHWORD( lpSetWaveParms16->nChannels );
  664. dprintf5(( "nChannels -> %u", pSet->SetWaveParms.nChannels ));
  665. *pOrigFlags ^= MCI_WAVE_SET_CHANNELS;
  666. }
  667. //
  668. // Thunk the nSamplesPerSec field.
  669. //
  670. if ( *pOrigFlags & MCI_WAVE_SET_SAMPLESPERSEC ) {
  671. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_SAMPLESPERSEC flag." ));
  672. pSet->SetWaveParms.nSamplesPerSec =
  673. FETCHDWORD( lpSetWaveParms16->nSamplesPerSecond );
  674. dprintf5(( "nSamplesPerSec -> %u", pSet->SetWaveParms.nSamplesPerSec ));
  675. *pOrigFlags ^= MCI_WAVE_SET_SAMPLESPERSEC;
  676. }
  677. //
  678. // Thunk the nAvgBytesPerSec field.
  679. //
  680. if ( *pOrigFlags & MCI_WAVE_SET_AVGBYTESPERSEC ) {
  681. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_AVGBYTESPERSEC flag." ));
  682. pSet->SetWaveParms.nAvgBytesPerSec =
  683. FETCHDWORD( lpSetWaveParms16->nAvgBytesPerSec );
  684. dprintf5(( "nAvgBytesPerSec -> %u", pSet->SetWaveParms.nAvgBytesPerSec ));
  685. *pOrigFlags ^= MCI_WAVE_SET_AVGBYTESPERSEC;
  686. }
  687. //
  688. // Thunk the nBlockAlign field.
  689. //
  690. if ( *pOrigFlags & MCI_WAVE_SET_BLOCKALIGN ) {
  691. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_BLOCKALIGN flag." ));
  692. pSet->SetWaveParms.nBlockAlign =
  693. FETCHWORD( lpSetWaveParms16->nBlockAlign );
  694. dprintf5(( "nBlockAlign -> %u", pSet->SetWaveParms.nBlockAlign ));
  695. *pOrigFlags ^= MCI_WAVE_SET_BLOCKALIGN;
  696. }
  697. //
  698. // Thunk the nBitsPerSample field.
  699. //
  700. if ( *pOrigFlags & MCI_WAVE_SET_BITSPERSAMPLE ) {
  701. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_BITSPERSAMPLE flag." ));
  702. pSet->SetWaveParms.wBitsPerSample =
  703. FETCHWORD( lpSetWaveParms16->wBitsPerSample );
  704. dprintf5(( "wBitsPerSamples -> %u", pSet->SetWaveParms.wBitsPerSample ));
  705. *pOrigFlags ^= MCI_WAVE_SET_BITSPERSAMPLE;
  706. }
  707. FREEVDMPTR( lpSetWaveParms16 );
  708. break;
  709. case MCI_DEVTYPE_SEQUENCER:
  710. //
  711. // Set up the VDM ptr for lpSetSeqParms16 to point to OrigParms
  712. //
  713. dprintf3(( "ThunkSetCmd: Got a Sequencer device." ));
  714. GETVDMPTR( OrigParms, sizeof(MCI_WAVE_SET_PARMS16),
  715. lpSetSeqParms16 );
  716. //
  717. // Thunk the dwMaster field.
  718. //
  719. if ( *pOrigFlags & MCI_SEQ_SET_MASTER ) {
  720. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_MASTER flag." ));
  721. pSet->SetSeqParms.dwMaster =
  722. FETCHDWORD( lpSetSeqParms16->dwMaster );
  723. dprintf5(( "dwMaster -> %ld", pSet->SetSeqParms.dwMaster ));
  724. *pOrigFlags ^= MCI_SEQ_SET_MASTER;
  725. }
  726. //
  727. // Thunk the dwPort field.
  728. //
  729. if ( *pOrigFlags & MCI_SEQ_SET_PORT ) {
  730. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_PORT flag." ));
  731. pSet->SetSeqParms.dwPort =
  732. FETCHDWORD( lpSetSeqParms16->dwPort );
  733. dprintf5(( "dwPort -> %ld", pSet->SetSeqParms.dwPort ));
  734. *pOrigFlags ^= MCI_SEQ_SET_PORT;
  735. }
  736. //
  737. // Thunk the dwOffset field.
  738. //
  739. if ( *pOrigFlags & MCI_SEQ_SET_OFFSET ) {
  740. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_OFFSET flag." ));
  741. pSet->SetSeqParms.dwOffset=
  742. FETCHDWORD( lpSetSeqParms16->dwOffset );
  743. dprintf5(( "dwOffset -> %ld", pSet->SetSeqParms.dwOffset ));
  744. *pOrigFlags ^= MCI_SEQ_SET_OFFSET;
  745. }
  746. //
  747. // Thunk the dwSlave field.
  748. //
  749. if ( *pOrigFlags & MCI_SEQ_SET_SLAVE ) {
  750. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_SLAVE flag." ));
  751. pSet->SetSeqParms.dwSlave =
  752. FETCHDWORD( lpSetSeqParms16->dwSlave );
  753. dprintf5(( "dwSlave -> %ld", pSet->SetSeqParms.dwSlave ));
  754. *pOrigFlags ^= MCI_SEQ_SET_SLAVE;
  755. }
  756. //
  757. // Thunk the dwTempo field.
  758. //
  759. if ( *pOrigFlags & MCI_SEQ_SET_TEMPO ) {
  760. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_TEMPO flag." ));
  761. pSet->SetSeqParms.dwTempo =
  762. FETCHDWORD( lpSetSeqParms16->dwTempo );
  763. dprintf5(( "dwTempo -> %ld", pSet->SetSeqParms.dwTempo ));
  764. *pOrigFlags ^= MCI_SEQ_SET_TEMPO;
  765. }
  766. FREEVDMPTR( lpSetSeqParms16 );
  767. break;
  768. }
  769. return (DWORD)pSet;
  770. }
  771. /**********************************************************************\
  772. * ThunkSetVideoCmd
  773. *
  774. * Thunk the SetVideo mci command parms.
  775. *
  776. \**********************************************************************/
  777. DWORD ThunkSetVideoCmd( MCIDEVICEID DeviceID, PDWORD pOrigFlags,
  778. DWORD OrigParms, DWORD pNewParms )
  779. {
  780. //
  781. // The following pointers will be used to point to the original
  782. // 16-bit Parms structure.
  783. //
  784. LPMCI_DGV_SETVIDEO_PARMS lpSetParms16;
  785. //
  786. // pSet will point to the 32 bit SetVideo Parms structure after
  787. // we have finished all the thunking.
  788. //
  789. LPMCI_DGV_SETVIDEO_PARMS pSet = (LPMCI_DGV_SETVIDEO_PARMS)pNewParms;
  790. //
  791. // Set up the VDM ptr for lpSetParms16 to point to OrigParms
  792. //
  793. GETVDMPTR( OrigParms, sizeof(MCI_DGV_SETVIDEO_PARMS), lpSetParms16 );
  794. if ( *pOrigFlags & MCI_DGV_SETVIDEO_ITEM ) {
  795. dprintf4(( "ThunkSetVideoCmd: Got MCI_DGV_SETVIDEO_ITEM flag." ));
  796. pSet->dwItem = FETCHDWORD( lpSetParms16->dwItem );
  797. dprintf5(( "dwItem -> %ld", pSet->dwItem ));
  798. *pOrigFlags ^= MCI_DGV_SETVIDEO_ITEM; // Mask out the flag
  799. }
  800. if ( *pOrigFlags & MCI_DGV_SETVIDEO_VALUE ) {
  801. if ( pSet->dwItem == MCI_DGV_SETVIDEO_PALHANDLE ) {
  802. HPAL16 hpal16;
  803. dprintf4(( "ThunkSetVideoCmd: Got MCI_DGV_SETVIDEO_PALHANLE." ));
  804. hpal16 = (HPAL16)LOWORD( FETCHDWORD( lpSetParms16->dwValue ) );
  805. pSet->dwValue = (DWORD)HPALETTE32( hpal16 );
  806. dprintf5(( "\t-> 0x%X", hpal16 ));
  807. }
  808. else {
  809. dprintf4(( "ThunkSetVideoCmd: Got an MCI_INTEGER." ));
  810. pSet->dwValue = FETCHDWORD( lpSetParms16->dwValue );
  811. dprintf5(( "dwValue -> %ld", pSet->dwValue ));
  812. }
  813. *pOrigFlags ^= MCI_DGV_SETVIDEO_VALUE; // Mask out the flag
  814. }
  815. //
  816. // Turn off the MCI_SET_ON FLAG.
  817. //
  818. if ( *pOrigFlags & MCI_SET_ON ) {
  819. dprintf4(( "ThunkSetVideoCmd: Got MCI_SET_ON flag." ));
  820. *pOrigFlags ^= MCI_SET_ON; // Mask out the flag
  821. }
  822. //
  823. // Turn off the MCI_SET_OFF FLAG.
  824. //
  825. if ( *pOrigFlags & MCI_SET_OFF ) {
  826. dprintf4(( "ThunkSetVideoCmd: Got MCI_SET_OFF flag." ));
  827. *pOrigFlags ^= MCI_SET_OFF; // Mask out the flag
  828. }
  829. return (DWORD)pSet;
  830. }
  831. /**********************************************************************\
  832. * ThunkSysInfoCmd
  833. *
  834. * Thunk the SysInfo mci command parms.
  835. \**********************************************************************/
  836. DWORD ThunkSysInfoCmd( PDWORD pOrigFlags, DWORD OrigParms, DWORD pNewParms )
  837. {
  838. //
  839. // lpSysInfoParms16 points to the 16 bit parameter block
  840. // passed to us by the WOW application.
  841. //
  842. PMCI_SYSINFO_PARMS16 lpSysInfoParms16;
  843. //
  844. // pSys will point to the 32 bit SysInfo Parms structure after
  845. // we have finished all the thunking.
  846. //
  847. PMCI_SYSINFO_PARMS pSys = (PMCI_SYSINFO_PARMS)pNewParms;
  848. //
  849. // Set up the VDM ptr for lpSysInfoParms16 to point to OrigParms
  850. //
  851. GETVDMPTR( OrigParms, sizeof(MCI_SYSINFO_PARMS16), lpSysInfoParms16 );
  852. //
  853. // Thunk the dwRetSize, dwNumber and wDeviceType parameters.
  854. //
  855. pSys->dwRetSize = FETCHDWORD( lpSysInfoParms16->dwRetSize );
  856. dprintf5(( "dwRetSize -> %ld", pSys->dwRetSize ));
  857. pSys->dwNumber = FETCHDWORD( lpSysInfoParms16->dwNumber );
  858. dprintf5(( "dwNumber -> %ld", pSys->dwNumber ));
  859. pSys->wDeviceType = (DWORD)FETCHWORD( lpSysInfoParms16->wDeviceType );
  860. dprintf5(( "wDeviceType -> %ld", pSys->wDeviceType ));
  861. //
  862. // Thunk lpstrReturn
  863. //
  864. if ( pSys->dwRetSize > 0 ) {
  865. GETVDMPTR( lpSysInfoParms16->lpstrReturn, pSys->dwRetSize,
  866. pSys->lpstrReturn );
  867. dprintf5(( "lpstrReturn -> 0x%lX", lpSysInfoParms16->lpstrReturn ));
  868. }
  869. else {
  870. dprintf1(( "ThunkSysInfoCmd: lpstrReturn is 0 bytes long !!!" ));
  871. /* lpstrReturn has been set to NULL by RtlZeroMemory above */
  872. }
  873. //
  874. // Free the VDM pointer as we have finished with it
  875. //
  876. FREEVDMPTR( lpSysInfoParms16 );
  877. return (DWORD)pSys;
  878. }
  879. /**********************************************************************\
  880. * ThunkBreakCmd
  881. *
  882. * Thunk the Break mci command parms.
  883. \**********************************************************************/
  884. DWORD ThunkBreakCmd( PDWORD pOrigFlags, DWORD OrigParms, DWORD pNewParms )
  885. {
  886. //
  887. // lpBreakParms16 points to the 16 bit parameter block
  888. // passed to us by the WOW application.
  889. //
  890. PMCI_BREAK_PARMS16 lpBreakParms16;
  891. //
  892. // pBrk will point to the 32 bit Break Parms structure after
  893. // we have finished all the thunking.
  894. //
  895. PMCI_BREAK_PARMS pBrk = (PMCI_BREAK_PARMS)pNewParms;
  896. //
  897. // Set up the VDM ptr for lpBreakParms16 to point to OrigParms
  898. //
  899. GETVDMPTR( OrigParms, sizeof(MCI_BREAK_PARMS16), lpBreakParms16 );
  900. //
  901. // Check for the MCI_BREAK_KEY flag
  902. //
  903. if ( *pOrigFlags & MCI_BREAK_KEY ) {
  904. dprintf4(( "ThunkBreakCmd: Got MCI_BREAK_KEY flag." ));
  905. pBrk->nVirtKey = (int)FETCHWORD( lpBreakParms16->nVirtKey );
  906. dprintf5(( "nVirtKey -> %d", pBrk->nVirtKey ));
  907. }
  908. //
  909. // Check for the MCI_BREAK_HWND flag
  910. //
  911. if ( *pOrigFlags & MCI_BREAK_HWND ) {
  912. dprintf4(( "ThunkBreakCmd: Got MCI_BREAK_HWND flag." ));
  913. pBrk->hwndBreak = HWND32(FETCHWORD(lpBreakParms16->hwndBreak));
  914. }
  915. //
  916. // Free the VDM pointer as we have finished with it
  917. //
  918. FREEVDMPTR( lpBreakParms16 );
  919. return (DWORD)pBrk;
  920. }
  921. /**********************************************************************\
  922. * ThunkWindowCmd
  923. *
  924. * Thunk the mci Window command parms.
  925. \**********************************************************************/
  926. DWORD ThunkWindowCmd( MCIDEVICEID DeviceID, PDWORD pOrigFlags, DWORD OrigParms,
  927. DWORD pNewParms )
  928. {
  929. //
  930. // lpAni will point to the 32 bit Anim Window Parms
  931. // structure after we have finished all the thunking.
  932. //
  933. PMCI_ANIM_WINDOW_PARMS lpAni = (PMCI_ANIM_WINDOW_PARMS)pNewParms;
  934. //
  935. // lpAniParms16 point to the 16 bit parameter block
  936. // passed to us by the WOW application.
  937. //
  938. PMCI_ANIM_WINDOW_PARMS16 lpAniParms16;
  939. //
  940. // GetDevCaps is used to determine what sort of device are dealing
  941. // with. We need this information to determine if we should use
  942. // overlay or animation MCI_WINDOW structure.
  943. //
  944. MCI_GETDEVCAPS_PARMS GetDevCaps;
  945. DWORD dwRetVal;
  946. //
  947. // Now we need to determine what type of device we are
  948. // dealing with. We can do this by send an MCI_GETDEVCAPS
  949. // command to the device. (We might as well use the Unicode
  950. // version of mciSendCommand and avoid another thunk).
  951. //
  952. RtlZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) );
  953. GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
  954. dwRetVal = (*mmAPISendCmdW)( DeviceID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM,
  955. (DWORD)&GetDevCaps );
  956. //
  957. // What do we do if dwRetCode is not equal to 0 ? If this is the
  958. // case it probably means that we have been given a duff device ID,
  959. // anyway it is pointless to carry on with the thunk so I will clear
  960. // the *pOrigFlags variable and return. This means that the 32 bit version
  961. // of mciSendCommand will get called with only half the message thunked,
  962. // but as there is probably already a problem with the device or
  963. // the device ID is duff, mciSendCommand should be able to work out a
  964. // suitable error code to return to the application.
  965. //
  966. if ( dwRetVal ) {
  967. *pOrigFlags = 0;
  968. return pNewParms;
  969. }
  970. //
  971. // Do we have an Animation or Overlay device type ?
  972. // Because Animation and Overlay have identical flags and
  973. // parms structures they can share the same code.
  974. //
  975. if ( GetDevCaps.dwReturn == MCI_DEVTYPE_ANIMATION
  976. || GetDevCaps.dwReturn == MCI_DEVTYPE_OVERLAY
  977. || GetDevCaps.dwReturn == MCI_DEVTYPE_DIGITAL_VIDEO ) {
  978. //
  979. // Set up the VDM ptr for lpWineParms16 to point to OrigParms
  980. //
  981. GETVDMPTR( OrigParms, sizeof(MCI_ANIM_WINDOW_PARMS16),
  982. lpAniParms16 );
  983. //
  984. // Check for the MCI_ANIM_WINDOW_TEXT
  985. //
  986. if ( *pOrigFlags & MCI_ANIM_WINDOW_TEXT ) {
  987. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_TEXT flag." ));
  988. GETPSZPTR( lpAniParms16->lpstrText, lpAni->lpstrText );
  989. dprintf5(( "lpstrText -> %s", lpAni->lpstrText ));
  990. dprintf5(( "lpstrText -> 0x%lX", lpAni->lpstrText ));
  991. *pOrigFlags ^= MCI_ANIM_WINDOW_TEXT;
  992. }
  993. //
  994. // Check for the MCI_ANIM_WINDOW_HWND flag
  995. //
  996. if ( *pOrigFlags & MCI_ANIM_WINDOW_HWND ) {
  997. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_HWND flag." ));
  998. lpAni->hWnd = HWND32( FETCHWORD( lpAniParms16->hWnd ) );
  999. dprintf5(( "hWnd -> 0x%lX", lpAni->hWnd ));
  1000. *pOrigFlags ^= MCI_ANIM_WINDOW_HWND;
  1001. }
  1002. //
  1003. // Check for the MCI_ANIM_WINDOW_STATE flag
  1004. //
  1005. if ( *pOrigFlags & MCI_ANIM_WINDOW_STATE ) {
  1006. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_STATE flag." ));
  1007. lpAni->nCmdShow = FETCHWORD( lpAniParms16->nCmdShow );
  1008. dprintf5(( "nCmdShow -> 0x%lX", lpAni->nCmdShow ));
  1009. *pOrigFlags ^= MCI_ANIM_WINDOW_STATE;
  1010. }
  1011. //
  1012. // Check for the MCI_ANIM_WINDOW_DISABLE_STRETCH flag
  1013. //
  1014. if ( *pOrigFlags & MCI_ANIM_WINDOW_DISABLE_STRETCH ) {
  1015. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_DISABLE_STRETCH flag." ));
  1016. *pOrigFlags ^= MCI_ANIM_WINDOW_DISABLE_STRETCH;
  1017. }
  1018. //
  1019. // Check for the MCI_ANIM_WINDOW_ENABLE_STRETCH flag
  1020. //
  1021. if ( *pOrigFlags & MCI_ANIM_WINDOW_ENABLE_STRETCH ) {
  1022. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_ENABLE_STRETCH flag." ));
  1023. *pOrigFlags ^= MCI_ANIM_WINDOW_ENABLE_STRETCH;
  1024. }
  1025. //
  1026. // Free the VDM pointer as we have finished with it
  1027. //
  1028. FREEVDMPTR( lpAniParms16 );
  1029. return (DWORD)lpAni;
  1030. }
  1031. return pNewParms;
  1032. }
  1033. /**********************************************************************\
  1034. * ThunkCommandViaTable
  1035. *
  1036. \**********************************************************************/
  1037. INT ThunkCommandViaTable( LPWSTR lpCommand, DWORD dwFlags, DWORD OrigParms,
  1038. DWORD pNewParms )
  1039. {
  1040. #if DBG
  1041. static LPSTR f_name = "ThunkCommandViaTable: ";
  1042. #endif
  1043. LPWSTR lpFirstParameter;
  1044. UINT wID;
  1045. DWORD dwValue;
  1046. UINT wOffset16, wOffset1stParm16;
  1047. UINT wOffset32, wOffset1stParm32;
  1048. UINT wParamSize;
  1049. DWORD dwParm16;
  1050. PDWORD pdwOrig16;
  1051. PDWORD pdwParm32;
  1052. DWORD dwMask = 1;
  1053. //
  1054. // Calculate the size of this command parameter block in terms
  1055. // of bytes, then get a VDM pointer to the OrigParms.
  1056. //
  1057. GETVDMPTR( OrigParms, GetSizeOfParameter( lpCommand ), pdwOrig16 );
  1058. dprintf3(( "%s16 bit Parms -> %lX", f_name, pdwOrig16 ));
  1059. //
  1060. // Skip past command entry
  1061. //
  1062. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1063. (*mmAPIEatCmdEntry)( lpCommand, NULL, NULL ));
  1064. //
  1065. // Get the next entry
  1066. //
  1067. lpFirstParameter = lpCommand;
  1068. //
  1069. // Skip past the DWORD return value
  1070. //
  1071. wOffset1stParm32 = wOffset1stParm16 = 4;
  1072. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1073. (*mmAPIEatCmdEntry)( lpCommand, &dwValue, &wID ));
  1074. //
  1075. // If it is a return value, skip it
  1076. //
  1077. if ( wID == MCI_RETURN ) {
  1078. //
  1079. // Look for a string return type, these are a special case.
  1080. //
  1081. if ( dwValue == MCI_STRING ) {
  1082. DWORD dwStrlen;
  1083. LPSTR *lplpStr;
  1084. //
  1085. // Get string pointer and length
  1086. //
  1087. dwParm16 = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + 4));
  1088. dwStrlen = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + 8));
  1089. //
  1090. // Copy string pointer
  1091. //
  1092. lplpStr = (LPSTR *)((LPBYTE)pNewParms + 4);
  1093. if ( dwStrlen > 0 ) {
  1094. GETVDMPTR( dwParm16, dwStrlen, *lplpStr );
  1095. dprintf5(( "%sReturn string -> 0x%lX", f_name, *lplpStr ));
  1096. dprintf5(( "%sReturn length -> 0x%lX", f_name, dwStrlen ));
  1097. }
  1098. //
  1099. // Copy string length
  1100. //
  1101. pdwParm32 = (LPDWORD)((LPBYTE)pNewParms + 8);
  1102. *pdwParm32 = dwStrlen;
  1103. }
  1104. //
  1105. // Adjust the offset of the first parameter. Remember that RECTS
  1106. // are a different size in 16-bit world.
  1107. //
  1108. wParamSize = (*mmAPIGetParamSize)( dwValue, wID );
  1109. wOffset1stParm16 += (dwValue == MCI_RECT ? sizeof(RECT16) : wParamSize);
  1110. wOffset1stParm32 += wParamSize;
  1111. //
  1112. // Save the new first parameter
  1113. //
  1114. lpFirstParameter = lpCommand;
  1115. }
  1116. //
  1117. // Walk through each flag
  1118. //
  1119. while ( dwMask != 0 ) {
  1120. //
  1121. // Is this bit set?
  1122. //
  1123. if ( (dwFlags & dwMask) != 0 ) {
  1124. wOffset16 = wOffset1stParm16;
  1125. wOffset32 = wOffset1stParm32;
  1126. lpCommand = (LPWSTR)((LPBYTE)lpFirstParameter +
  1127. (*mmAPIEatCmdEntry)( lpFirstParameter,
  1128. &dwValue, &wID ));
  1129. //
  1130. // What parameter uses this bit?
  1131. //
  1132. while ( wID != MCI_END_COMMAND && dwValue != dwMask ) {
  1133. wParamSize = (*mmAPIGetParamSize)( dwValue, wID );
  1134. wOffset16 += (wID == MCI_RECT ? sizeof( RECT16 ) : wParamSize);
  1135. wOffset32 += wParamSize;
  1136. if ( wID == MCI_CONSTANT ) {
  1137. while ( wID != MCI_END_CONSTANT ) {
  1138. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1139. (*mmAPIEatCmdEntry)( lpCommand, NULL, &wID ));
  1140. }
  1141. }
  1142. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1143. (*mmAPIEatCmdEntry)( lpCommand, &dwValue, &wID ));
  1144. }
  1145. if ( wID != MCI_END_COMMAND ) {
  1146. //
  1147. // Thunk the argument if there is one. The argument is at
  1148. // wOffset16 from the start of OrigParms.
  1149. // This offset is in bytes.
  1150. //
  1151. dprintf5(( "%sOffset 16 -> 0x%lX", f_name, wOffset16 ));
  1152. dprintf5(( "%sOffset 32 -> 0x%lX", f_name, wOffset32 ));
  1153. if ( wID != MCI_FLAG ) {
  1154. dwParm16 = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + wOffset16));
  1155. pdwParm32 = (LPDWORD)((LPBYTE)pNewParms + wOffset32);
  1156. }
  1157. switch ( wID ) {
  1158. case MCI_STRING:
  1159. {
  1160. LPSTR str16 = (LPSTR)dwParm16;
  1161. LPSTR str32 = (LPSTR)*pdwParm32;
  1162. dprintf4(( "%sGot STRING flag -> 0x%lX", f_name, dwMask ));
  1163. GETPSZPTR( str16, str32 );
  1164. dprintf5(( "%s\t-> 0x%lX", f_name, *pdwParm32 ));
  1165. dprintf5(( "%s\t-> %s", f_name, *pdwParm32 ));
  1166. }
  1167. break;
  1168. case MCI_HWND:
  1169. {
  1170. HWND16 hwnd16;
  1171. dprintf4(( "%sGot HWND flag -> 0x%lX", f_name, dwMask ));
  1172. hwnd16 = (HWND16)LOWORD( dwParm16 );
  1173. *pdwParm32 = (DWORD)HWND32( hwnd16 );
  1174. dprintf5(( "\t-> 0x%X", hwnd16 ));
  1175. }
  1176. break;
  1177. case MCI_HPAL:
  1178. {
  1179. HPAL16 hpal16;
  1180. dprintf4(( "%sGot HPAL flag -> 0x%lX", f_name, dwMask ));
  1181. hpal16 = (HPAL16)LOWORD( dwParm16 );
  1182. *pdwParm32 = (DWORD)HPALETTE32( hpal16 );
  1183. dprintf5(( "\t-> 0x%X", hpal16 ));
  1184. }
  1185. break;
  1186. case MCI_HDC:
  1187. {
  1188. HDC16 hdc16;
  1189. dprintf4(( "%sGot HDC flag -> 0x%lX", f_name, dwMask ));
  1190. hdc16 = (HDC16)LOWORD( dwParm16 );
  1191. *pdwParm32 = (DWORD)HDC32( hdc16 );
  1192. dprintf5(( "\t-> 0x%X", hdc16 ));
  1193. }
  1194. break;
  1195. case MCI_RECT:
  1196. {
  1197. PRECT16 pRect16 = (PRECT16)((LPBYTE)pdwOrig16 + wOffset16);
  1198. PRECT pRect32 = (PRECT)pdwParm32;
  1199. dprintf4(( "%sGot RECT flag -> 0x%lX", f_name, dwMask ));
  1200. pRect32->top = (LONG)pRect16->top;
  1201. pRect32->bottom = (LONG)pRect16->bottom;
  1202. pRect32->left = (LONG)pRect16->left;
  1203. pRect32->right = (LONG)pRect16->right;
  1204. }
  1205. break;
  1206. case MCI_CONSTANT:
  1207. case MCI_INTEGER:
  1208. dprintf4(( "%sGot INTEGER flag -> 0x%lX", f_name, dwMask ));
  1209. *pdwParm32 = dwParm16;
  1210. dprintf5(( "\t-> 0x%lX", dwParm16 ));
  1211. break;
  1212. }
  1213. }
  1214. }
  1215. //
  1216. // Go to the next flag
  1217. //
  1218. dwMask <<= 1;
  1219. }
  1220. //
  1221. // Free the VDM pointer as we have finished with it
  1222. //
  1223. FREEVDMPTR( pdwOrig16 );
  1224. return 0;
  1225. }
  1226. /**********************************************************************\
  1227. * GetSizeOfParameter
  1228. *
  1229. \**********************************************************************/
  1230. UINT GetSizeOfParameter( LPWSTR lpCommand )
  1231. {
  1232. #if DBG
  1233. static LPSTR f_name = "GetSizeOfParameter";
  1234. #endif
  1235. UINT wOffset;
  1236. UINT wID;
  1237. DWORD dwValue;
  1238. //
  1239. // Skip past command entry
  1240. //
  1241. lpCommand = (LPWSTR)((LPBYTE)lpCommand + (*mmAPIEatCmdEntry)( lpCommand,
  1242. NULL, NULL ));
  1243. //
  1244. // Skip past the DWORD return value
  1245. //
  1246. wOffset = 4;
  1247. //
  1248. // Get the first parameter slot entry
  1249. //
  1250. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1251. (*mmAPIEatCmdEntry)( lpCommand, &dwValue, &wID ));
  1252. //
  1253. // If it is a return value, skip it
  1254. //
  1255. if ( wID == MCI_RETURN ) {
  1256. //
  1257. // Don't forget that RECT's are smaller in 16-bit world.
  1258. // Other parameters are OK though
  1259. //
  1260. if ( dwValue == MCI_RECT ) {
  1261. wOffset += sizeof( RECT16 );
  1262. }
  1263. else {
  1264. wOffset += (*mmAPIGetParamSize)( dwValue, wID );
  1265. }
  1266. //
  1267. // Get first proper entry that is not a return field.
  1268. //
  1269. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1270. (*mmAPIEatCmdEntry)( lpCommand, &dwValue, &wID ));
  1271. }
  1272. //
  1273. // What parameter uses this bit?
  1274. //
  1275. while ( wID != MCI_END_COMMAND ) {
  1276. //
  1277. // Don't forget that RECT's are smaller in 16-bit world.
  1278. // Other parameters are OK though
  1279. //
  1280. if ( wID == MCI_RECT ) {
  1281. wOffset += sizeof( RECT16 );
  1282. }
  1283. else {
  1284. wOffset += (*mmAPIGetParamSize)( dwValue, wID );
  1285. }
  1286. //
  1287. // If we have a constant we need to skip the entries in
  1288. // the command table.
  1289. //
  1290. if ( wID == MCI_CONSTANT ) {
  1291. while ( wID != MCI_END_CONSTANT ) {
  1292. lpCommand = (LPWSTR)((LPBYTE)lpCommand
  1293. + (*mmAPIEatCmdEntry)( lpCommand, NULL, &wID ));
  1294. }
  1295. }
  1296. //
  1297. // Get the next entry
  1298. //
  1299. lpCommand = (LPWSTR)((LPBYTE)lpCommand
  1300. + (*mmAPIEatCmdEntry)( lpCommand, &dwValue, &wID ));
  1301. }
  1302. dprintf4(( "%sSizeof Cmd Params -> %u bytes", f_name, wOffset ));
  1303. return wOffset;
  1304. }
  1305. #if DBG
  1306. /*--------------------------------------------------------------------*\
  1307. MCI WOW DEBUGGING FUNCTIONS
  1308. \*--------------------------------------------------------------------*/
  1309. /**********************************************************************\
  1310. * wow32MciDebugOutput
  1311. *
  1312. * Output a formated message to the debug terminal.
  1313. *
  1314. \**********************************************************************/
  1315. VOID wow32MciDebugOutput( LPSTR lpszFormatStr, ... )
  1316. {
  1317. CHAR buf[256];
  1318. UINT n;
  1319. va_list va;
  1320. va_start(va, lpszFormatStr);
  1321. n = vsprintf(buf, lpszFormatStr, va);
  1322. va_end(va);
  1323. buf[n++] = '\n';
  1324. buf[n] = 0;
  1325. OutputDebugString(buf);
  1326. }
  1327. /**********************************************************************\
  1328. * wow32MciSetDebugLevel
  1329. *
  1330. * Query and set the debug level.
  1331. \**********************************************************************/
  1332. VOID wow32MciSetDebugLevel( VOID )
  1333. {
  1334. int DebugLevel;
  1335. //
  1336. // First see if a specific WOW32MCI key has been defined.
  1337. // If one hasn't been defined DebugLevel will be set to '999'.
  1338. //
  1339. DebugLevel = (int)GetProfileInt( "MMDEBUG", "WOW32MCI", 999 );
  1340. //
  1341. // If DebugLevel == '999' then an WOW32MCI key has not been defined,
  1342. // so try a "WOW32" key. This time if the key has not been defined
  1343. // set the debug level to 0, ie. no debugging info should be
  1344. // displayed.
  1345. //
  1346. if ( DebugLevel == 999 ) {
  1347. DebugLevel = (int)GetProfileInt( "MMDEBUG", "WOW32", 0 );
  1348. }
  1349. mmDebugLevel = DebugLevel;
  1350. }
  1351. #endif
  1352. #endif