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.

2400 lines
70 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: mmwowmci.c
  3. *
  4. * Thunks for the mci api's.
  5. *
  6. *
  7. * Created: 28-09-93
  8. * Author: Stephen Estrop [StephenE]
  9. *
  10. * Copyright (c) 1993-1998 Microsoft Corporation
  11. \**************************************************************************/
  12. #include "winmmi.h"
  13. #include "mci.h"
  14. #include <digitalv.h>
  15. #include <stdlib.h>
  16. #include "mixer.h"
  17. #define _INC_ALL_WOWSTUFF
  18. #include "mmwow32.h"
  19. #include "mmwowmci.h"
  20. #include "mmwowcb.h"
  21. extern void
  22. WOWAppExit(
  23. HANDLE hTask
  24. );
  25. STATICFN void mciFreeDevice(LPMCI_DEVICE_NODE nodeWorking);
  26. STATICFN MCIDEVICEID NEAR mciAllocateNode (
  27. DWORD dwFlags,
  28. LPCWSTR lpDeviceName,
  29. LPMCI_DEVICE_NODE FAR *lpnodeNew);
  30. #ifndef _WIN64
  31. /******************************Public*Routine******************************\
  32. * mci32Message
  33. *
  34. * Entry point for all the mci thunks.
  35. *
  36. * History:
  37. * 22-11-93 - StephenE - Created
  38. *
  39. \**************************************************************************/
  40. DWORD WINAPI
  41. mci32Message(
  42. DWORD dwApi,
  43. DWORD dwF1,
  44. DWORD dwF2,
  45. DWORD dwF3,
  46. DWORD dwF4
  47. )
  48. {
  49. DWORD dwRet;
  50. switch ( dwApi ) {
  51. case THUNK_MCI_SENDCOMMAND:
  52. dwRet = WMM32mciSendCommand( dwF1, dwF2, dwF3, dwF4 );
  53. break;
  54. case THUNK_MCI_SENDSTRING:
  55. dwRet = WMM32mciSendString( dwF1, dwF2, dwF3, dwF4 );
  56. break;
  57. case THUNK_MCI_GETDEVICEID:
  58. dwRet = WMM32mciGetDeviceID( dwF1 );
  59. break;
  60. case THUNK_MCI_GETDEVIDFROMELEMID:
  61. dwRet = WMM32mciGetDeviceIDFromElementID( dwF1, dwF2 );
  62. break;
  63. case THUNK_MCI_GETERRORSTRING:
  64. dwRet = WMM32mciGetErrorString( dwF1, dwF2, dwF3 );
  65. break;
  66. case THUNK_MCI_SETYIELDPROC:
  67. dwRet = WMM32mciSetYieldProc( dwF1, dwF2, dwF3 );
  68. break;
  69. case THUNK_MCI_GETYIELDPROC:
  70. dwRet = WMM32mciGetYieldProc( dwF1, dwF2 );
  71. break;
  72. case THUNK_MCI_GETCREATORTASK:
  73. dwRet = WMM32mciGetCreatorTask( dwF1 );
  74. break;
  75. case THUNK_APP_EXIT:
  76. /*
  77. ** Now tidy up the other stuff.
  78. */
  79. dwRet = 0; //Keep the compiler happy
  80. WOWAppExit( (HANDLE)GetCurrentThreadId() );
  81. break;
  82. case THUNK_MCI_ALLOCATE_NODE:
  83. dwRet = WMM32mciAllocateNode( dwF1, dwF2 );
  84. break;
  85. case THUNK_MCI_FREE_NODE:
  86. dwRet = WMM32mciFreeNode( dwF1 );
  87. break;
  88. }
  89. return dwRet;
  90. }
  91. /**********************************************************************\
  92. * WMM32mciSendCommand
  93. *
  94. *
  95. * This function sends a command message to the specified MCI device.
  96. *
  97. \**********************************************************************/
  98. DWORD
  99. WMM32mciSendCommand(
  100. DWORD dwF1,
  101. DWORD dwF2,
  102. DWORD dwF3,
  103. DWORD dwF4
  104. )
  105. {
  106. PMCI_GENERIC_PARMS16 lp16OrigParms;
  107. DWORD ul;
  108. DWORD NewParms[MCI_MAX_PARAM_SLOTS];
  109. LPWSTR lpCommand;
  110. UINT uTable;
  111. if ( dwF2 == DRV_CONFIGURE ) {
  112. typedef struct {
  113. DWORD dwDCISize;
  114. LPCSTR lpszDCISectionName;
  115. LPCSTR lpszDCIAliasName;
  116. } DRVCONFIGINFO16;
  117. typedef DRVCONFIGINFO16 UNALIGNED *LPDRVCONFIGINFO16;
  118. LPDRVCONFIGINFO16 lpdrvConf;
  119. lpdrvConf = GETVDMPTR(dwF4);
  120. if (lpdrvConf && (lpdrvConf->dwDCISize == sizeof(DRVCONFIGINFO16))) {
  121. DRVCONFIGINFO drvConf;
  122. LPCSTR lpStr1 = lpdrvConf->lpszDCISectionName;
  123. LPCSTR lpStr2 = lpdrvConf->lpszDCIAliasName;
  124. drvConf.dwDCISize = sizeof(drvConf);
  125. drvConf.lpszDCISectionName = AllocUnicodeStr( GETVDMPTR(lpStr1) );
  126. if (NULL == drvConf.lpszDCISectionName) {
  127. return MCIERR_OUT_OF_MEMORY;
  128. }
  129. drvConf.lpszDCIAliasName = AllocUnicodeStr( GETVDMPTR(lpStr2) );
  130. if (NULL == lpdrvConf->lpszDCIAliasName) {
  131. FreeUnicodeStr((LPWSTR)drvConf.lpszDCISectionName);
  132. return MCIERR_OUT_OF_MEMORY;
  133. }
  134. ul = mciSendCommandW( dwF1, dwF2, (DWORD)HWND32(LOWORD(dwF3)),
  135. (DWORD)(LPVOID)&drvConf );
  136. FreeUnicodeStr( (LPWSTR)drvConf.lpszDCIAliasName );
  137. FreeUnicodeStr( (LPWSTR)drvConf.lpszDCISectionName );
  138. return ul;
  139. }
  140. return DRVCNF_CANCEL;
  141. }
  142. /*
  143. ** lparam (dwF4) is a 16:16 pointer. This Requires parameter
  144. ** translation and probably memory copying, similar to the WM message
  145. ** thunks. A whole thunk/unthunk table should be created.
  146. **
  147. ** Shouldn't these be FETCHDWORD, FETCHWORD macros?
  148. ** else MIPS problems ensue
  149. */
  150. lpCommand = NULL;
  151. uTable = 0;
  152. lp16OrigParms = GETVDMPTR( dwF4 );
  153. try {
  154. ul = ThunkMciCommand16( (MCIDEVICEID)INT32( dwF1 ), (UINT)dwF2,
  155. dwF3, lp16OrigParms, NewParms,
  156. &lpCommand, &uTable );
  157. /*
  158. ** OK so far ? If not don't bother calling into winmm.
  159. */
  160. if ( ul == 0 ) {
  161. dprintf3(( "About to call mciSendCommand." ));
  162. ul = (DWORD)mciSendCommandA( (MCIDEVICEID)INT32( dwF1 ),
  163. (UINT)dwF2, dwF3, (DWORD)NewParms );
  164. dprintf3(( "return code-> %ld", ul ));
  165. /*
  166. ** We have to special case the MCI_CLOSE command. MCI_CLOSE usually
  167. ** causes the device to become unloaded. This means that lpCommand
  168. ** now points to invalid memory. We can fix this by setting
  169. ** lpCommand to NULL.
  170. */
  171. if ( dwF2 == MCI_CLOSE ) {
  172. lpCommand = NULL;
  173. }
  174. UnThunkMciCommand16( (MCIDEVICEID)INT32( dwF1 ), UINT32( dwF2 ),
  175. DWORD32( dwF3 ), lp16OrigParms,
  176. NewParms, lpCommand, uTable );
  177. /*
  178. ** Print a blank line so that I can distinguish the commands on the
  179. ** debugger. This is only necessary if the debug level is >= 3.
  180. */
  181. dprintf3(( " " ));
  182. #if DBG
  183. if ( DebugLevel >= 6 ) DebugBreak();
  184. #endif
  185. }
  186. } except( GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
  187. ? EXCEPTION_EXECUTE_HANDLER
  188. : EXCEPTION_CONTINUE_SEARCH ) {
  189. dprintf(( "UNKOWN access violation processing 0x%X command",
  190. UINT32(dwF2) ));
  191. }
  192. return ul;
  193. }
  194. /**********************************************************************\
  195. *
  196. * WMM32mciSendString
  197. *
  198. * This function sends a command string to an MCI device. The device that the
  199. * command is sent to is specified in the command string.
  200. *
  201. \**********************************************************************/
  202. DWORD
  203. WMM32mciSendString(
  204. DWORD dwF1,
  205. DWORD dwF2,
  206. DWORD dwF3,
  207. DWORD dwF4
  208. )
  209. {
  210. //
  211. // The use of volatile here is to bypass a bug with the intel
  212. // compiler.
  213. //
  214. # define MAX_MCI_CMD_LEN 256
  215. volatile ULONG ul = MMSYSERR_INVALPARAM;
  216. PSZ pszCommand;
  217. PSZ pszReturnString = NULL;
  218. UINT uSize;
  219. CHAR szCopyCmd[MAX_MCI_CMD_LEN];
  220. /*
  221. ** Test against a NULL pointer for the command name.
  222. */
  223. pszCommand = GETVDMPTR(dwF1);
  224. if ( pszCommand ) {
  225. # define MAP_INTEGER 0
  226. # define MAP_HWND 1
  227. # define MAP_HPALETTE 2
  228. int MapReturn = MAP_INTEGER;
  229. WORD wMappedHandle;
  230. char *psz;
  231. /*
  232. ** make a copy of the command string and then force it to
  233. ** all lower case. Then scan the string looking for the word
  234. ** "status". If we find it scan the string again looking for the
  235. ** word "handle", if we find it scan the the string again looking
  236. ** for palette or window. Then set a flag to remind us to convert
  237. ** the handle back from 32 to 16 bits.
  238. */
  239. strncpy( szCopyCmd, pszCommand, MAX_MCI_CMD_LEN );
  240. szCopyCmd[ MAX_MCI_CMD_LEN - 1 ] = '\0';
  241. CharLowerBuff( szCopyCmd, MAX_MCI_CMD_LEN );
  242. /*
  243. ** Skip past any white space ie. " \t\r\n"
  244. ** If the next 6 characters after any white space are not
  245. ** "status" don't bother with any other tests.
  246. */
  247. psz = szCopyCmd + strspn( szCopyCmd, " \t\r\n" );
  248. if ( strncmp( psz, "status", 6 ) == 0 ) {
  249. if ( strstr( psz, "handle" ) ) {
  250. if ( strstr( psz, "window" ) ) {
  251. MapReturn = MAP_HWND;
  252. }
  253. else if ( strstr( psz, "palette" ) ) {
  254. MapReturn = MAP_HPALETTE;
  255. }
  256. }
  257. }
  258. /*
  259. ** Test against a zero length string and a NULL pointer
  260. */
  261. uSize = (UINT)dwF3;
  262. if( uSize != 0 ) {
  263. MMGETOPTPTR(dwF2, uSize, pszReturnString);
  264. if ( pszReturnString == NULL ) {
  265. uSize = 0;
  266. }
  267. }
  268. dprintf3(( "wow32: mciSendString -> %s", pszCommand ));
  269. ul = (DWORD)mciSendStringA( pszCommand, pszReturnString, uSize,
  270. HWND32(LOWORD(dwF4)) );
  271. #if DBG
  272. if ( pszReturnString && *pszReturnString ) {
  273. dprintf3(( "wow32: mciSendString return -> %s", pszReturnString ));
  274. }
  275. #endif
  276. if ( pszReturnString && *pszReturnString ) {
  277. switch ( MapReturn ) {
  278. case MAP_HWND:
  279. MapReturn = atoi( pszReturnString );
  280. wMappedHandle = (WORD)GETHWND16( (HWND)MapReturn );
  281. wsprintf( pszReturnString, "%d", wMappedHandle );
  282. dprintf2(( "Mapped 32 bit Window %s to 16 bit %u",
  283. pszReturnString,
  284. wMappedHandle ));
  285. break;
  286. case MAP_HPALETTE:
  287. MapReturn = atoi( pszReturnString );
  288. dprintf2(( "Mapped 32 bit palette %s", pszReturnString ));
  289. wMappedHandle = (WORD)GETHPALETTE16( (HPALETTE)MapReturn );
  290. wsprintf( pszReturnString, "%d", wMappedHandle );
  291. dprintf2(( "Mapped 32 bit Palette %s to 16 bit %u",
  292. pszReturnString,
  293. wMappedHandle ));
  294. break;
  295. }
  296. }
  297. }
  298. return ul;
  299. # undef MAP_INTEGER
  300. # undef MAP_HWND
  301. # undef MAP_HPALETTE
  302. # undef MAX_MCI_CMD_LEN
  303. }
  304. /**********************************************************************\
  305. *
  306. * WMM32mciGetDeviceID
  307. *
  308. * This assumes that the string is incoming, and the ID is returned in the WORD.
  309. *
  310. * This function retrieves the device ID corresponding to the name of an
  311. * open MCI device.
  312. *
  313. \**********************************************************************/
  314. DWORD
  315. WMM32mciGetDeviceID(
  316. DWORD dwF1
  317. )
  318. {
  319. DWORD ul = 0L;
  320. PSZ pszName;
  321. /*
  322. ** Test against a NULL pointer for the device name.
  323. */
  324. pszName = GETVDMPTR(dwF1);
  325. if ( pszName ) {
  326. ul = mciGetDeviceIDA( pszName );
  327. }
  328. return ul;
  329. }
  330. /**********************************************************************\
  331. *
  332. * WMM32mciGetErrorString
  333. *
  334. * This function returns a textual description of the specified MCI error.
  335. *
  336. \**********************************************************************/
  337. DWORD
  338. WMM32mciGetErrorString(
  339. DWORD dwF1,
  340. DWORD dwF2,
  341. DWORD dwF3
  342. )
  343. {
  344. PSZ pszBuffer;
  345. DWORD ul = 0;
  346. /*
  347. ** Test against a zero length string and a NULL pointer
  348. */
  349. MMGETOPTPTR( dwF2, dwF3, pszBuffer);
  350. if ( pszBuffer ) {
  351. ul = (DWORD)mciGetErrorStringA( dwF1, pszBuffer, (UINT)dwF3 );
  352. }
  353. return ul;
  354. }
  355. #if 0
  356. /**********************************************************************\
  357. *
  358. * WMM32mciExecute
  359. *
  360. * This function is a simplified version of the mciSendString function. It does
  361. * not take a buffer for return information, and it displays a message box when
  362. * errors occur.
  363. *
  364. * THIS FUNCTION SHOULD NOT BE USED - IT IS RETAINED ONLY FOR BACKWARD
  365. * COMPATABILITY WITH WIN 3.0 APPS - USE mciSendString INSTEAD...
  366. *
  367. \**********************************************************************/
  368. DWORD
  369. WMM32mciExecute(
  370. DWORD dwF1
  371. )
  372. {
  373. DWORD ul = 0;
  374. PSZ pszCommand;
  375. /*
  376. ** Test against a NULL pointer for the command string.
  377. */
  378. pszCommand = GETVDMPTR(dwF1);
  379. if ( pszCommand ) {
  380. ul = (DWORD)mciExecute( pszCommand );
  381. }
  382. return ul;
  383. }
  384. #endif
  385. /**********************************************************************\
  386. *
  387. * WMM32mciGetDeviceIDFromElementID
  388. *
  389. * This function - um, yes, well...
  390. *
  391. * It appears in the headers but not in the book...
  392. *
  393. \**********************************************************************/
  394. DWORD
  395. WMM32mciGetDeviceIDFromElementID(
  396. DWORD dwF1,
  397. DWORD dwF2
  398. )
  399. {
  400. ULONG ul = 0;
  401. PSZ pszDeviceID;
  402. /*
  403. ** Test against a NULL pointer for the device name.
  404. */
  405. pszDeviceID = GETVDMPTR(dwF2);
  406. if ( pszDeviceID ) {
  407. ul = (DWORD)mciGetDeviceIDFromElementIDA( dwF1, pszDeviceID );
  408. }
  409. return ul;
  410. }
  411. /**********************************************************************\
  412. *
  413. * WMM32mciGetCreatorTask
  414. *
  415. * This function - um again. Ditto for book and headers also.
  416. *
  417. \**********************************************************************/
  418. DWORD
  419. WMM32mciGetCreatorTask(
  420. DWORD dwF1
  421. )
  422. {
  423. ULONG ul;
  424. ul = GETHTASK16( mciGetCreatorTask( (MCIDEVICEID)INT32(dwF1) ));
  425. return ul;
  426. }
  427. /**********************************************************************\
  428. *
  429. * WMM32mciSetYieldProc
  430. *
  431. *
  432. \**********************************************************************/
  433. DWORD
  434. WMM32mciSetYieldProc(
  435. DWORD dwF1,
  436. DWORD dwF2,
  437. DWORD dwF3
  438. )
  439. {
  440. ULONG ul;
  441. YIELDPROC YieldProc32;
  442. INSTANCEDATA *lpYieldProcInfo;
  443. DWORD dwYieldData = 0;
  444. /*
  445. ** We may have already set a YieldProc for this device ID. If so we
  446. ** have to free the INSTANCEDATA structure here. mciGetYieldProc
  447. ** returns NULL is no YieldProc was specified.
  448. */
  449. YieldProc32 = (YIELDPROC)mciGetYieldProc( (MCIDEVICEID)INT32(dwF1),
  450. &dwYieldData );
  451. if ( (YieldProc32 == WMM32mciYieldProc) && (dwYieldData != 0) ) {
  452. winmmFree( (INSTANCEDATA *)dwYieldData );
  453. }
  454. if ( dwF2 == 0 ) {
  455. YieldProc32 = NULL;
  456. dwYieldData = 0;
  457. }
  458. else {
  459. /*
  460. ** Allocate some storage for a INSTANCEDATA structure and save
  461. ** the passed 16 bit parameters. This storage get freed when the
  462. ** application calls mciSetYieldProc with a NULL YieldProc.
  463. */
  464. lpYieldProcInfo = winmmAlloc( sizeof(INSTANCEDATA) );
  465. if ( lpYieldProcInfo == NULL ) {
  466. ul = (ULONG)MMSYSERR_NOMEM;
  467. goto exit_app;
  468. }
  469. dwYieldData = (DWORD)lpYieldProcInfo;
  470. YieldProc32 = WMM32mciYieldProc;
  471. lpYieldProcInfo->dwCallback = dwF2;
  472. lpYieldProcInfo->dwCallbackInstance = dwF3;
  473. }
  474. ul = (DWORD)mciSetYieldProc( (MCIDEVICEID)INT32(dwF1),
  475. YieldProc32, dwYieldData );
  476. /*
  477. ** If the call failed free the storage here.
  478. */
  479. if ( ul == FALSE ) {
  480. winmmFree( (INSTANCEDATA *)dwYieldData );
  481. }
  482. exit_app:
  483. return ul;
  484. }
  485. /**********************************************************************\
  486. *
  487. * WMM32mciYieldProc
  488. *
  489. * Here we call the real 16 bit YieldProc. This function assumes that
  490. * we yield on the wow thread. If this is not the case we get instant
  491. * death inside CallBack16.
  492. *
  493. * 12th Jan 1993 - The bad news is that the mci yield proc is NOT always
  494. * called back on the thread that set it. This means that we cannot callback
  495. * into the 16bit code because the calling thread does not have a 16bit
  496. * stack.
  497. *
  498. \**********************************************************************/
  499. UINT
  500. WMM32mciYieldProc(
  501. MCIDEVICEID wDeviceID,
  502. DWORD dwYieldData
  503. )
  504. {
  505. wDeviceID = (MCIDEVICEID)0;
  506. dwYieldData = 0;
  507. return 0;
  508. }
  509. /**********************************************************************\
  510. *
  511. * WMM32mciGetYieldProc
  512. *
  513. *
  514. \**********************************************************************/
  515. DWORD
  516. WMM32mciGetYieldProc(
  517. DWORD dwF1,
  518. DWORD dwF2
  519. )
  520. {
  521. ULONG ul = 0;
  522. YIELDPROC YieldProc32;
  523. DWORD dwYieldData = 0;
  524. DWORD UNALIGNED *pdw1;
  525. /*
  526. ** Get the address of the 32 bit yield proc.
  527. */
  528. YieldProc32 = (YIELDPROC)mciGetYieldProc( (MCIDEVICEID)INT32(dwF1),
  529. &dwYieldData );
  530. /*
  531. ** Did we set it ? If so it must point to WMM32mciYieldProc.
  532. */
  533. if ( ((YieldProc32 == WMM32mciYieldProc) && (dwYieldData != 0)) ) {
  534. ul = ((INSTANCEDATA *)dwYieldData)->dwCallback;
  535. pdw1 = GETVDMPTR( dwF2 );
  536. *pdw1 = ((INSTANCEDATA *)dwYieldData)->dwCallbackInstance;
  537. }
  538. return ul;
  539. }
  540. /**********************************************************************\
  541. *
  542. * WMM32mciAllocateNode
  543. *
  544. *
  545. \**********************************************************************/
  546. DWORD
  547. WMM32mciAllocateNode(
  548. DWORD dwF1, // dwOpenFlags
  549. DWORD dwF2 // lpszDeviceName
  550. )
  551. {
  552. LPMCI_DEVICE_NODE lpNode32;
  553. LPWSTR lpDeviceName32;
  554. ULONG ul = 0;
  555. // Thunk 16-bit params and allocate a 32-bit device node
  556. if ((lpDeviceName32 = AllocUnicodeStr(GETVDMPTR(dwF2))) != NULL) {
  557. if ((ul = mciAllocateNode(dwF1, lpDeviceName32, &lpNode32)) != 0) {
  558. // Mark this device as 16-bit
  559. lpNode32->dwMCIFlags |= MCINODE_16BIT_DRIVER;
  560. }
  561. FreeUnicodeStr(lpDeviceName32);
  562. }
  563. return ul;
  564. }
  565. /**********************************************************************\
  566. *
  567. * WMM32mciFreeNode
  568. *
  569. *
  570. \**********************************************************************/
  571. DWORD
  572. WMM32mciFreeNode(
  573. DWORD dwF2
  574. )
  575. {
  576. LPMCI_DEVICE_NODE lpNode32;
  577. if ((lpNode32 = MCI_lpDeviceList[dwF2]) != NULL) {
  578. mciFreeDevice(lpNode32);
  579. }
  580. return 0;
  581. }
  582. #if DBG
  583. MCI_MESSAGE_NAMES mciMessageNames[32] = {
  584. { MCI_OPEN, "MCI_OPEN" },
  585. { MCI_CLOSE, "MCI_CLOSE" },
  586. { MCI_ESCAPE, "MCI_ESCAPE" },
  587. { MCI_PLAY, "MCI_PLAY" },
  588. { MCI_SEEK, "MCI_SEEK" },
  589. { MCI_STOP, "MCI_STOP" },
  590. { MCI_PAUSE, "MCI_PAUSE" },
  591. { MCI_INFO, "MCI_INFO" },
  592. { MCI_GETDEVCAPS, "MCI_GETDEVCAPS" },
  593. { MCI_SPIN, "MCI_SPIN" },
  594. { MCI_SET, "MCI_SET" },
  595. { MCI_STEP, "MCI_STEP" },
  596. { MCI_RECORD, "MCI_RECORD" },
  597. { MCI_SYSINFO, "MCI_SYSINFO" },
  598. { MCI_BREAK, "MCI_BREAK" },
  599. { MCI_SOUND, "MCI_SOUND" },
  600. { MCI_SAVE, "MCI_SAVE" },
  601. { MCI_STATUS, "MCI_STATUS" },
  602. { MCI_CUE, "MCI_CUE" },
  603. { MCI_REALIZE, "MCI_REALIZE" },
  604. { MCI_WINDOW, "MCI_WINDOW" },
  605. { MCI_PUT, "MCI_PUT" },
  606. { MCI_WHERE, "MCI_WHERE" },
  607. { MCI_FREEZE, "MCI_FREEZE" },
  608. { MCI_UNFREEZE, "MCI_UNFREEZE" },
  609. { MCI_LOAD, "MCI_LOAD" },
  610. { MCI_CUT, "MCI_CUT" },
  611. { MCI_COPY, "MCI_COPY" },
  612. { MCI_PASTE, "MCI_PASTE" },
  613. { MCI_UPDATE, "MCI_UPDATE" },
  614. { MCI_RESUME, "MCI_RESUME" },
  615. { MCI_DELETE, "MCI_DELETE" }
  616. };
  617. #endif
  618. /**********************************************************************\
  619. *
  620. * ThunkMciCommand16
  621. *
  622. * This function converts a 16 bit mci command request into an
  623. * equiverlant 32 bit request.
  624. *
  625. * The ideas behind this function were stolen from ThunkWMMsg16,
  626. * see wmsg16.c and mciDebugOut see mci.c
  627. *
  628. * We return 0 if the thunk was OK, any other value should be used as
  629. * an error code. If the thunk failed all allocated resources will
  630. * be freed by this function. If the thunk was sucessful (ie. returned 0)
  631. * UnThunkMciCommand16 MUST be called to free allocated resources.
  632. *
  633. * Here are the assumptions that I have used to perform the thunking:
  634. *
  635. * 1. MCI_OPEN is a special case.
  636. *
  637. * 2. If the message is NOT defined in mmsystem.h then it is treated as a
  638. * "user" command. If a user command table is associated with the given
  639. * device ID we use this command table as an aid to perform the thunking.
  640. * If a user command table is NOT associated with the device ID the
  641. * command does NOT GET THUNKED, we return straight away, calling
  642. * mciSendCommand only to get a relevant error code.
  643. *
  644. * 3. If the command IS defined in mmsystem.h we perfrom a "manual" thunk
  645. * of the command IF the associated PARMS structure contains ReservedX
  646. * fields. We mask out the associated flags as each field is thunked.
  647. *
  648. * 4. If there are any flags left then we use the command table
  649. * as an aid to perform the thunking.
  650. *
  651. \**********************************************************************/
  652. DWORD
  653. ThunkMciCommand16(
  654. MCIDEVICEID DeviceID,
  655. UINT OrigCommand,
  656. DWORD OrigFlags,
  657. PMCI_GENERIC_PARMS16 lp16OrigParms,
  658. PDWORD pNewParms,
  659. LPWSTR *lplpCommand,
  660. PUINT puTable
  661. )
  662. {
  663. #if DBG
  664. register int i;
  665. int n;
  666. dprintf3(( "ThunkMciCommand16 :" ));
  667. dprintf5(( " OrigDevice -> %lX", DeviceID ));
  668. n = sizeof(mciMessageNames) / sizeof(MCI_MESSAGE_NAMES);
  669. for ( i = 0; i < n; i++ ) {
  670. if ( mciMessageNames[i].uMsg == OrigCommand ) {
  671. break;
  672. }
  673. }
  674. dprintf3(( "OrigCommand -> 0x%lX", (DWORD)OrigCommand ));
  675. //
  676. // Special case MCI_STATUS. I get loads of these from mplayer.
  677. // I only want to display MCI_STATUS messages if the debug level is
  678. // set to level 3, that way I won't get swamped with them.
  679. //
  680. if ( mciMessageNames[i].uMsg != MCI_STATUS ) {
  681. if ( i != n ) {
  682. dprintf2(( "Command Name -> %s", mciMessageNames[i].lpstMsgName ));
  683. }
  684. else {
  685. dprintf2(( "Command Name -> UNKNOWN COMMAND (%x)", OrigCommand ));
  686. }
  687. }
  688. else {
  689. dprintf3(( "Command Name -> MCI_STATUS" ));
  690. }
  691. dprintf5(( "OrigFlags -> 0x%lX", OrigFlags ));
  692. dprintf5(( "OrigParms -> 0x%lX", lp16OrigParms ));
  693. #endif
  694. //
  695. // Thunk the generic params. These are common to all mci devices.
  696. //
  697. ThunkGenericParms( &OrigFlags, lp16OrigParms,
  698. (PMCI_GENERIC_PARMS)pNewParms );
  699. //
  700. // We thunk the MCI_OPEN command and all other commands that contain a
  701. // "ReservedX" field in their PARMS structure here. We mask out each
  702. // flag as it is processed, if any flags are left we use the command
  703. // table to complete the thunk.
  704. //
  705. // The following commands have ReservedX fields:
  706. // MCI_WINDOW
  707. // MCI_SET
  708. //
  709. // This means that MOST COMMANDS GET THUNKED VIA THE COMMAND TABLE.
  710. //
  711. switch ( OrigCommand ) {
  712. case MCI_OPEN:
  713. //
  714. // MCI_OPEN is a special case message that I don't
  715. // how to deal with yet.
  716. //
  717. ThunkOpenCmd( &OrigFlags, (PMCI_OPEN_PARMS16)lp16OrigParms,
  718. (PMCI_OPEN_PARMS)pNewParms );
  719. return 0;
  720. //
  721. // The next four commands have Reserved padding fields
  722. // these have to thunked manually.
  723. //
  724. case MCI_SET:
  725. ThunkSetCmd( DeviceID, &OrigFlags,
  726. (PMCI_SET_PARMS16)lp16OrigParms,
  727. (PMCI_SET_PARMS)pNewParms );
  728. break;
  729. case MCI_WINDOW:
  730. ThunkWindowCmd( DeviceID, &OrigFlags,
  731. (PMCI_ANIM_WINDOW_PARMS16)lp16OrigParms,
  732. (PMCI_ANIM_WINDOW_PARMS)pNewParms );
  733. break;
  734. //
  735. // Have to special case this command because the command table
  736. // is not correct.
  737. //
  738. case MCI_SETVIDEO:
  739. ThunkSetVideoCmd( &OrigFlags,
  740. (PMCI_DGV_SETVIDEO_PARMS16)lp16OrigParms,
  741. (LPMCI_DGV_SETVIDEO_PARMS)pNewParms );
  742. break;
  743. //
  744. // These two commands don't have any command extensions
  745. // so we return immediately.
  746. //
  747. case MCI_SYSINFO:
  748. ThunkSysInfoCmd( (PMCI_SYSINFO_PARMS16)lp16OrigParms,
  749. (PMCI_SYSINFO_PARMS)pNewParms );
  750. return 0;
  751. case MCI_BREAK:
  752. ThunkBreakCmd( &OrigFlags,
  753. (PMCI_BREAK_PARMS16)lp16OrigParms,
  754. (PMCI_BREAK_PARMS)pNewParms );
  755. return 0;
  756. }
  757. //
  758. // Find the command table for the given command ID.
  759. // We always load the command table this is because the command table is
  760. // needed for UnThunking.
  761. //
  762. *lplpCommand = FindCommandItem( DeviceID, NULL, (LPWSTR)OrigCommand,
  763. NULL, puTable );
  764. //
  765. // If the command table is not found we return straight away.
  766. // Note that storage has been allocated for pNewParms and that the
  767. // MCI_WAIT and MCI_NOTIFY flags have been thunked.
  768. // We do not return an error here, but call mciSendCommand to
  769. // let it determine a suitable error code, we must also call
  770. // UnthunkMciCommand to free the allocated storage.
  771. //
  772. if ( *lplpCommand == NULL ) {
  773. dprintf(( "Command table not found !!" ));
  774. return 0;
  775. }
  776. dprintf4(( "Command table has been loaded -> 0x%lX", *lplpCommand ));
  777. //
  778. // If OrigFlags is not equal to 0 we still have work to do !
  779. // Note that this will be true for the majority of cases.
  780. //
  781. if ( OrigFlags ) {
  782. dprintf3(( "Thunking via command table" ));
  783. //
  784. // Now we thunk the command
  785. //
  786. return ThunkCommandViaTable( *lplpCommand, OrigFlags,
  787. (DWORD UNALIGNED *)lp16OrigParms,
  788. (LPBYTE)pNewParms );
  789. }
  790. return 0;
  791. }
  792. /*****************************Private*Routine******************************\
  793. * ThunkGenericParms
  794. *
  795. * As we know that the first dword field is a Window handle
  796. * this field is taken care of here. Also the MCI_WAIT flag is
  797. * masked out if it is set.
  798. *
  799. *
  800. * History:
  801. * 22-11-93 - StephenE - Created
  802. *
  803. \**************************************************************************/
  804. VOID
  805. ThunkGenericParms(
  806. PDWORD pOrigFlags,
  807. PMCI_GENERIC_PARMS16 lp16GenParms,
  808. PMCI_GENERIC_PARMS lp32GenParms
  809. )
  810. {
  811. // Look for the notify flag and thunk accordingly
  812. //
  813. if ( *pOrigFlags & MCI_NOTIFY ) {
  814. dprintf4(( "AllocMciParmBlock: Got MCI_NOTIFY flag." ));
  815. lp32GenParms->dwCallback =
  816. (DWORD)HWND32( FETCHWORD( lp16GenParms->dwCallback ) );
  817. }
  818. *pOrigFlags &= ~(MCI_WAIT | MCI_NOTIFY);
  819. }
  820. /**********************************************************************\
  821. * ThunkOpenCmd
  822. *
  823. * Thunk the Open mci command parms.
  824. \**********************************************************************/
  825. DWORD
  826. ThunkOpenCmd(
  827. PDWORD pOrigFlags,
  828. PMCI_OPEN_PARMS16 lp16OpenParms,
  829. PMCI_OPEN_PARMS p32OpenParms
  830. )
  831. {
  832. PMCI_ANIM_OPEN_PARMS p32OpenAnimParms;
  833. PMCI_WAVE_OPEN_PARMS p32OpenWaveParms;
  834. PMCI_ANIM_OPEN_PARMS16 lpOpenAnimParms16;
  835. PMCI_WAVE_OPEN_PARMS16 lp16OpenWaveParms;
  836. //
  837. // Now scan our way thru all the known MCI_OPEN flags, thunking as
  838. // necessary.
  839. //
  840. // Start at the Device Type field
  841. //
  842. if ( *pOrigFlags & MCI_OPEN_TYPE ) {
  843. if ( *pOrigFlags & MCI_OPEN_TYPE_ID ) {
  844. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_TYPE_ID flag." ));
  845. p32OpenParms->lpstrDeviceType =
  846. (LPSTR)lp16OpenParms->lpstrDeviceType;
  847. dprintf5(( "lpstrDeviceType -> %ld", p32OpenParms->lpstrDeviceType ));
  848. }
  849. else {
  850. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_TYPE flag" ));
  851. p32OpenParms->lpstrDeviceType =
  852. GETVDMPTR( lp16OpenParms->lpstrDeviceType );
  853. dprintf5(( "lpstrDeviceType -> %s", p32OpenParms->lpstrDeviceType ));
  854. dprintf5(( "lpstrDeviceType -> 0x%lX", p32OpenParms->lpstrDeviceType ));
  855. }
  856. }
  857. //
  858. // Now do the Element Name field
  859. //
  860. if ( *pOrigFlags & MCI_OPEN_ELEMENT ) {
  861. if ( *pOrigFlags & MCI_OPEN_ELEMENT_ID ) {
  862. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ELEMENT_ID flag" ));
  863. p32OpenParms->lpstrElementName =
  864. (LPSTR)( FETCHDWORD( lp16OpenParms->lpstrElementName ) );
  865. dprintf5(( "lpstrElementName -> %ld", p32OpenParms->lpstrElementName ));
  866. }
  867. else {
  868. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ELEMENT flag" ));
  869. p32OpenParms->lpstrElementName =
  870. GETVDMPTR( lp16OpenParms->lpstrElementName );
  871. dprintf5(( "lpstrElementName -> %s", p32OpenParms->lpstrElementName ));
  872. dprintf5(( "lpstrElementName -> 0x%lX", p32OpenParms->lpstrElementName ));
  873. }
  874. }
  875. //
  876. // Now do the Alias Name field
  877. //
  878. if ( *pOrigFlags & MCI_OPEN_ALIAS ) {
  879. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_ALIAS flag" ));
  880. p32OpenParms->lpstrAlias = GETVDMPTR( lp16OpenParms->lpstrAlias );
  881. dprintf5(( "lpstrAlias -> %s", p32OpenParms->lpstrAlias ));
  882. dprintf5(( "lpstrAlias -> 0x%lX", p32OpenParms->lpstrAlias ));
  883. }
  884. //
  885. // Clear the MCI_OPEN_SHAREABLE flag if it is set
  886. //
  887. #if DBG
  888. if ( *pOrigFlags & MCI_OPEN_SHAREABLE ) {
  889. dprintf4(( "ThunkOpenCmd: Got MCI_OPEN_SHAREABLE flag." ));
  890. }
  891. #endif
  892. *pOrigFlags &= ~(MCI_OPEN_SHAREABLE | MCI_OPEN_ALIAS |
  893. MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID |
  894. MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID);
  895. //
  896. // If we don't have any extended flags I can return now
  897. //
  898. if ( *pOrigFlags == 0 ) {
  899. return (DWORD)p32OpenParms;
  900. }
  901. //
  902. // If there are any flags left then these are intended for an extended
  903. // form of MCI open. Three different forms are known, these being:
  904. // MCI_ANIM_OPEN_PARMS
  905. // MCI_OVLY_OPEN_PARMS
  906. // MCI_WAVE_OPEN_PARMS
  907. //
  908. // If I could tell what sort of device I had I could thunk the
  909. // extensions with no problems, but we don't have a device ID yet
  910. // so I can't figure out what sort of device I have without parsing
  911. // the parameters that I already know about.
  912. //
  913. // But, I am in luck; MCI_WAVE_OPEN_PARMS has one extended parameter
  914. // dwBufferSeconds which has a MCI_WAVE_OPEN_BUFFER flag associated with
  915. // it. This field is also a DWORD in the other two parms structures.
  916. //
  917. if ( *pOrigFlags & MCI_WAVE_OPEN_BUFFER ) {
  918. //
  919. // Set up the VDM ptr for lpOpenWaveParms16 to point to OrigParms
  920. //
  921. lp16OpenWaveParms = (PMCI_WAVE_OPEN_PARMS16)lp16OpenParms;
  922. p32OpenWaveParms = (PMCI_WAVE_OPEN_PARMS)p32OpenParms;
  923. dprintf4(( "ThunkOpenCmd: Got MCI_WAVE_OPEN_BUFFER flag." ));
  924. p32OpenWaveParms->dwBufferSeconds =
  925. FETCHDWORD( lp16OpenWaveParms->dwBufferSeconds );
  926. dprintf5(( "dwBufferSeconds -> %ld", p32OpenWaveParms->dwBufferSeconds ));
  927. }
  928. //
  929. // Now look for MCI_ANIM_OPEN_PARM and MCI_OVLY_OPEN_PARMS extensions.
  930. // Set up the VDM ptr for lpOpenAnimParms16 to point to OrigParms
  931. //
  932. lpOpenAnimParms16 = (PMCI_ANIM_OPEN_PARMS16)lp16OpenParms;
  933. p32OpenAnimParms = (PMCI_ANIM_OPEN_PARMS)p32OpenParms;
  934. //
  935. // Check MCI_ANIN_OPEN_PARENT flag, this also checks
  936. // the MCI_OVLY_OPEN_PARENT flag too.
  937. //
  938. if ( *pOrigFlags & MCI_ANIM_OPEN_PARENT ) {
  939. dprintf4(( "ThunkOpenCmd: Got MCI_Xxxx_OPEN_PARENT flag." ));
  940. p32OpenAnimParms->hWndParent =
  941. HWND32(FETCHWORD(lpOpenAnimParms16->hWndParent) );
  942. }
  943. //
  944. // Check MCI_ANIN_OPEN_WS flag, this also checks
  945. // the MCI_OVLY_OPEN_WS flag too.
  946. //
  947. if ( *pOrigFlags & MCI_ANIM_OPEN_WS ) {
  948. dprintf4(( "ThunkOpenCmd: Got MCI_Xxxx_OPEN_WS flag." ));
  949. p32OpenAnimParms->dwStyle =
  950. FETCHDWORD( lpOpenAnimParms16->dwStyle );
  951. dprintf5(( "dwStyle -> %ld", p32OpenAnimParms->dwStyle ));
  952. }
  953. #if DBG
  954. //
  955. // Check the MCI_ANIN_OPEN_NOSTATIC flag
  956. //
  957. if ( *pOrigFlags & MCI_ANIM_OPEN_NOSTATIC ) {
  958. dprintf4(( "ThunkOpenCmd: Got MCI_ANIM_OPEN_NOSTATIC flag." ));
  959. }
  960. #endif
  961. *pOrigFlags &= ~(MCI_ANIM_OPEN_NOSTATIC | MCI_ANIM_OPEN_WS |
  962. MCI_ANIM_OPEN_PARENT | MCI_WAVE_OPEN_BUFFER);
  963. return (DWORD)p32OpenParms;
  964. }
  965. /**********************************************************************\
  966. * ThunkSetCmd
  967. *
  968. * Thunk the ThunkSetCmd mci command parms.
  969. *
  970. * The following are "basic" flags that all devices must support.
  971. * MCI_SET_AUDIO
  972. * MCI_SET_DOOR_CLOSED
  973. * MCI_SET_DOOR_OPEN
  974. * MCI_SET_TIME_FORMAT
  975. * MCI_SET_VIDEO
  976. * MCI_SET_ON
  977. * MCI_SET_OFF
  978. *
  979. * The following are "extended" flags that "sequencer" devices support.
  980. * MCI_SEQ_SET_MASTER
  981. * MCI_SEQ_SET_OFFSET
  982. * MCI_SEQ_SET_PORT
  983. * MCI_SEQ_SET_SLAVE
  984. * MCI_SEQ_SET_TEMPO
  985. *
  986. * The following are "extended" flags that "waveaudio" devices support.
  987. * MCI_WAVE_INPUT
  988. * MCI_WAVE_OUTPUT
  989. * MCI_WAVE_SET_ANYINPUT
  990. * MCI_WAVE_SET_ANYOUTPUT
  991. * MCI_WAVE_SET_AVGBYTESPERSEC
  992. * MCI_WAVE_SET_BITSPERSAMPLES
  993. * MCI_WAVE_SET_BLOCKALIGN
  994. * MCI_WAVE_SET_CHANNELS
  995. * MCI_WAVE_SET_FORMAT_TAG
  996. * MCI_WAVE_SET_SAMPLESPERSEC
  997. *
  998. \**********************************************************************/
  999. DWORD
  1000. ThunkSetCmd(
  1001. MCIDEVICEID DeviceID,
  1002. PDWORD pOrigFlags,
  1003. PMCI_SET_PARMS16 lpSetParms16,
  1004. PMCI_SET_PARMS lpSetParms32
  1005. )
  1006. {
  1007. //
  1008. // The following pointers will be used to point to the original
  1009. // 16-bit Parms structure.
  1010. //
  1011. PMCI_WAVE_SET_PARMS16 lpSetWaveParms16;
  1012. PMCI_SEQ_SET_PARMS16 lpSetSeqParms16;
  1013. //
  1014. // The following pointers will be used to point to the new
  1015. // 32-bit Parms structure.
  1016. //
  1017. PMCI_WAVE_SET_PARMS lpSetWaveParms32;
  1018. PMCI_SEQ_SET_PARMS lpSetSeqParms32;
  1019. //
  1020. // GetDevCaps is used to determine what sort of device are dealing
  1021. // with. We need this information to determine if we should use
  1022. // standard, wave or sequencer MCI_SET structure.
  1023. //
  1024. MCI_GETDEVCAPS_PARMS GetDevCaps;
  1025. DWORD dwRetVal;
  1026. //
  1027. // First do the fields that are common to all devices. Thunk the
  1028. // dwAudio field.
  1029. //
  1030. if ( *pOrigFlags & MCI_SET_AUDIO ) {
  1031. dprintf4(( "ThunkSetCmd: Got MCI_SET_AUDIO flag." ));
  1032. lpSetParms32->dwAudio = FETCHDWORD( lpSetParms16->dwAudio );
  1033. dprintf5(( "dwAudio -> %ld", lpSetParms32->dwAudio ));
  1034. }
  1035. //
  1036. // Thunk the dwTimeFormat field.
  1037. //
  1038. if ( *pOrigFlags & MCI_SET_TIME_FORMAT ) {
  1039. dprintf4(( "ThunkSetCmd: Got MCI_SET_TIME_FORMAT flag." ));
  1040. lpSetParms32->dwTimeFormat = FETCHDWORD( lpSetParms16->dwTimeFormat );
  1041. dprintf5(( "dwTimeFormat -> %ld", lpSetParms32->dwTimeFormat ));
  1042. }
  1043. #if DBG
  1044. //
  1045. // Mask out the MCI_SET_DOOR_CLOSED
  1046. //
  1047. if ( *pOrigFlags & MCI_SET_DOOR_CLOSED ) {
  1048. dprintf4(( "ThunkSetCmd: Got MCI_SET_DOOR_CLOSED flag." ));
  1049. }
  1050. //
  1051. // Mask out the MCI_SET_DOOR_OPEN
  1052. //
  1053. if ( *pOrigFlags & MCI_SET_DOOR_OPEN ) {
  1054. dprintf4(( "ThunkSetCmd: Got MCI_SET_DOOR_OPEN flag." ));
  1055. }
  1056. //
  1057. // Mask out the MCI_SET_VIDEO
  1058. //
  1059. if ( *pOrigFlags & MCI_SET_VIDEO ) {
  1060. dprintf4(( "ThunkSetCmd: Got MCI_SET_VIDEO flag." ));
  1061. }
  1062. //
  1063. // Mask out the MCI_SET_ON
  1064. //
  1065. if ( *pOrigFlags & MCI_SET_ON ) {
  1066. dprintf4(( "ThunkSetCmd: Got MCI_SET_ON flag." ));
  1067. }
  1068. //
  1069. // Mask out the MCI_SET_OFF
  1070. //
  1071. if ( *pOrigFlags & MCI_SET_OFF ) {
  1072. dprintf4(( "ThunkSetCmd: Got MCI_SET_OFF flag." ));
  1073. }
  1074. #endif
  1075. *pOrigFlags &= ~(MCI_SET_AUDIO | MCI_SET_TIME_FORMAT |
  1076. MCI_SET_OFF | MCI_SET_ON | MCI_SET_VIDEO |
  1077. MCI_SET_DOOR_OPEN | MCI_SET_DOOR_CLOSED |
  1078. MCI_SET_AUDIO | MCI_SET_TIME_FORMAT );
  1079. //
  1080. // We have done all the standard flags. If there are any flags
  1081. // still set we must have an extended command.
  1082. //
  1083. if ( *pOrigFlags == 0 ) {
  1084. return (DWORD)lpSetParms32;
  1085. }
  1086. //
  1087. // Now we need to determine what type of device we are
  1088. // dealing with. We can do this by send an MCI_GETDEVCAPS
  1089. // command to the device. (We might as well use the Unicode
  1090. // version of mciSendCommand and avoid another thunk).
  1091. //
  1092. ZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) );
  1093. GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
  1094. dwRetVal = mciSendCommandW( DeviceID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM,
  1095. (DWORD)&GetDevCaps );
  1096. //
  1097. // What do we do if dwRetCode is not equal to 0 ? If this is the
  1098. // case it probably means that we have been given a duff device ID,
  1099. // anyway it is pointless to carry on with the thunk so I will clear
  1100. // the *pOrigFlags variable and return. This means that the 32 bit version
  1101. // of mciSendCommand will get called with only half the message thunked,
  1102. // but as there is probably already a problem with the device or
  1103. // the device ID is duff, mciSendCommand should be able to work out a
  1104. // suitable error code to return to the application.
  1105. //
  1106. if ( dwRetVal ) {
  1107. *pOrigFlags = 0;
  1108. return (DWORD)lpSetParms32;
  1109. }
  1110. switch ( GetDevCaps.dwReturn ) {
  1111. case MCI_DEVTYPE_WAVEFORM_AUDIO:
  1112. //
  1113. // Set up the VDM ptr for lpSetWaveParms16 to point to OrigParms
  1114. //
  1115. dprintf3(( "ThunkSetCmd: Got a WaveAudio device." ));
  1116. lpSetWaveParms16 = (PMCI_WAVE_SET_PARMS16)lpSetParms16;
  1117. lpSetWaveParms32 = (PMCI_WAVE_SET_PARMS)lpSetParms32;
  1118. //
  1119. // Thunk the wInput field.
  1120. //
  1121. if ( *pOrigFlags & MCI_WAVE_INPUT ) {
  1122. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_INPUT flag." ));
  1123. lpSetWaveParms32->wInput = FETCHWORD( lpSetWaveParms16->wInput );
  1124. dprintf5(( "wInput -> %u", lpSetWaveParms32->wInput ));
  1125. }
  1126. //
  1127. // Thunk the wOutput field.
  1128. //
  1129. if ( *pOrigFlags & MCI_WAVE_OUTPUT ) {
  1130. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_OUTPUT flag." ));
  1131. lpSetWaveParms32->wOutput = FETCHWORD( lpSetWaveParms16->wOutput );
  1132. dprintf5(( "wOutput -> %u", lpSetWaveParms32->wOutput ));
  1133. }
  1134. //
  1135. // Thunk the wFormatTag field.
  1136. //
  1137. if ( *pOrigFlags & MCI_WAVE_SET_FORMATTAG ) {
  1138. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_FORMATTAG flag." ));
  1139. lpSetWaveParms32->wFormatTag =
  1140. FETCHWORD( lpSetWaveParms16->wFormatTag );
  1141. dprintf5(( "wFormatTag -> %u", lpSetWaveParms32->wFormatTag ));
  1142. }
  1143. //
  1144. // Thunk the nChannels field.
  1145. //
  1146. if ( *pOrigFlags & MCI_WAVE_SET_CHANNELS ) {
  1147. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_CHANNELS flag." ));
  1148. lpSetWaveParms32->nChannels =
  1149. FETCHWORD( lpSetWaveParms16->nChannels );
  1150. dprintf5(( "nChannels -> %u", lpSetWaveParms32->nChannels ));
  1151. }
  1152. //
  1153. // Thunk the nSamplesPerSec field.
  1154. //
  1155. if ( *pOrigFlags & MCI_WAVE_SET_SAMPLESPERSEC ) {
  1156. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_SAMPLESPERSEC flag." ));
  1157. lpSetWaveParms32->nSamplesPerSec =
  1158. FETCHDWORD( lpSetWaveParms16->nSamplesPerSecond );
  1159. dprintf5(( "nSamplesPerSec -> %u", lpSetWaveParms32->nSamplesPerSec ));
  1160. }
  1161. //
  1162. // Thunk the nAvgBytesPerSec field.
  1163. //
  1164. if ( *pOrigFlags & MCI_WAVE_SET_AVGBYTESPERSEC ) {
  1165. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_AVGBYTESPERSEC flag." ));
  1166. lpSetWaveParms32->nAvgBytesPerSec =
  1167. FETCHDWORD( lpSetWaveParms16->nAvgBytesPerSec );
  1168. dprintf5(( "nAvgBytesPerSec -> %u", lpSetWaveParms32->nAvgBytesPerSec ));
  1169. }
  1170. //
  1171. // Thunk the nBlockAlign field.
  1172. //
  1173. if ( *pOrigFlags & MCI_WAVE_SET_BLOCKALIGN ) {
  1174. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_BLOCKALIGN flag." ));
  1175. lpSetWaveParms32->nBlockAlign =
  1176. FETCHWORD( lpSetWaveParms16->nBlockAlign );
  1177. dprintf5(( "nBlockAlign -> %u", lpSetWaveParms32->nBlockAlign ));
  1178. }
  1179. //
  1180. // Thunk the nBitsPerSample field.
  1181. //
  1182. if ( *pOrigFlags & MCI_WAVE_SET_BITSPERSAMPLE ) {
  1183. dprintf4(( "ThunkSetCmd: Got MCI_WAVE_SET_BITSPERSAMPLE flag." ));
  1184. lpSetWaveParms32->wBitsPerSample =
  1185. FETCHWORD( lpSetWaveParms16->wBitsPerSample );
  1186. dprintf5(( "wBitsPerSamples -> %u", lpSetWaveParms32->wBitsPerSample ));
  1187. }
  1188. //
  1189. // Turn off all the flags in one go.
  1190. //
  1191. *pOrigFlags &= ~(MCI_WAVE_INPUT | MCI_WAVE_SET_BITSPERSAMPLE |
  1192. MCI_WAVE_SET_BLOCKALIGN | MCI_WAVE_SET_AVGBYTESPERSEC |
  1193. MCI_WAVE_SET_SAMPLESPERSEC | MCI_WAVE_SET_CHANNELS |
  1194. MCI_WAVE_SET_FORMATTAG | MCI_WAVE_OUTPUT);
  1195. break;
  1196. case MCI_DEVTYPE_SEQUENCER:
  1197. //
  1198. // Set up the VDM ptr for lpSetSeqParms16 to point to OrigParms
  1199. //
  1200. dprintf3(( "ThunkSetCmd: Got a Sequencer device." ));
  1201. lpSetSeqParms16 = (PMCI_SEQ_SET_PARMS16)lpSetParms16;
  1202. lpSetSeqParms32 = (PMCI_SEQ_SET_PARMS)lpSetParms32;
  1203. //
  1204. // Thunk the dwMaster field.
  1205. //
  1206. if ( *pOrigFlags & MCI_SEQ_SET_MASTER ) {
  1207. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_MASTER flag." ));
  1208. lpSetSeqParms32->dwMaster = FETCHDWORD( lpSetSeqParms16->dwMaster );
  1209. dprintf5(( "dwMaster -> %ld", lpSetSeqParms32->dwMaster ));
  1210. }
  1211. //
  1212. // Thunk the dwPort field.
  1213. //
  1214. if ( *pOrigFlags & MCI_SEQ_SET_PORT ) {
  1215. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_PORT flag." ));
  1216. lpSetSeqParms32->dwPort = FETCHDWORD( lpSetSeqParms16->dwPort );
  1217. dprintf5(( "dwPort -> %ld", lpSetSeqParms32->dwPort ));
  1218. }
  1219. //
  1220. // Thunk the dwOffset field.
  1221. //
  1222. if ( *pOrigFlags & MCI_SEQ_SET_OFFSET ) {
  1223. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_OFFSET flag." ));
  1224. lpSetSeqParms32->dwOffset= FETCHDWORD( lpSetSeqParms16->dwOffset );
  1225. dprintf5(( "dwOffset -> %ld", lpSetSeqParms32->dwOffset ));
  1226. }
  1227. //
  1228. // Thunk the dwSlave field.
  1229. //
  1230. if ( *pOrigFlags & MCI_SEQ_SET_SLAVE ) {
  1231. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_SLAVE flag." ));
  1232. lpSetSeqParms32->dwSlave = FETCHDWORD( lpSetSeqParms16->dwSlave );
  1233. dprintf5(( "dwSlave -> %ld", lpSetSeqParms32->dwSlave ));
  1234. }
  1235. //
  1236. // Thunk the dwTempo field.
  1237. //
  1238. if ( *pOrigFlags & MCI_SEQ_SET_TEMPO ) {
  1239. dprintf4(( "ThunkSetCmd: Got MCI_SEQ_SET_TEMPO flag." ));
  1240. lpSetSeqParms32->dwTempo = FETCHDWORD( lpSetSeqParms16->dwTempo );
  1241. dprintf5(( "dwTempo -> %ld", lpSetSeqParms32->dwTempo ));
  1242. }
  1243. //
  1244. // Turn off all the flags in one go.
  1245. //
  1246. *pOrigFlags &= ~(MCI_SEQ_SET_MASTER | MCI_SEQ_SET_PORT |
  1247. MCI_SEQ_SET_OFFSET | MCI_SEQ_SET_SLAVE |
  1248. MCI_SEQ_SET_TEMPO);
  1249. break;
  1250. }
  1251. return (DWORD)lpSetParms32;
  1252. }
  1253. /**********************************************************************\
  1254. * ThunkSetVideoCmd
  1255. *
  1256. * Thunk the SetVideo mci command parms.
  1257. *
  1258. \**********************************************************************/
  1259. DWORD
  1260. ThunkSetVideoCmd(
  1261. PDWORD pOrigFlags,
  1262. PMCI_DGV_SETVIDEO_PARMS16 lpSetParms16,
  1263. LPMCI_DGV_SETVIDEO_PARMS lpSetParms32
  1264. )
  1265. {
  1266. if ( *pOrigFlags & MCI_DGV_SETVIDEO_ITEM ) {
  1267. dprintf4(( "ThunkSetVideoCmd: Got MCI_DGV_SETVIDEO_ITEM flag." ));
  1268. lpSetParms32->dwItem = FETCHDWORD( lpSetParms16->dwItem );
  1269. dprintf5(( "dwItem -> %ld", lpSetParms32->dwItem ));
  1270. }
  1271. if ( *pOrigFlags & MCI_DGV_SETVIDEO_VALUE ) {
  1272. if ( lpSetParms32->dwItem == MCI_DGV_SETVIDEO_PALHANDLE ) {
  1273. HPAL16 hpal16;
  1274. dprintf4(( "ThunkSetVideoCmd: Got MCI_DGV_SETVIDEO_PALHANDLE." ));
  1275. hpal16 = (HPAL16)LOWORD( FETCHDWORD( lpSetParms16->dwValue ) );
  1276. lpSetParms32->dwValue = (DWORD)HPALETTE32( hpal16 );
  1277. dprintf5(( "\t-> 0x%X", hpal16 ));
  1278. }
  1279. else {
  1280. dprintf4(( "ThunkSetVideoCmd: Got an MCI_INTEGER." ));
  1281. lpSetParms32->dwValue = FETCHDWORD( lpSetParms16->dwValue );
  1282. dprintf5(( "dwValue -> %ld", lpSetParms32->dwValue ));
  1283. }
  1284. }
  1285. #if DBG
  1286. //
  1287. // Turn off the MCI_SET_ON FLAG.
  1288. //
  1289. if ( *pOrigFlags & MCI_SET_ON ) {
  1290. dprintf4(( "ThunkSetVideoCmd: Got MCI_SET_ON flag." ));
  1291. }
  1292. //
  1293. // Turn off the MCI_SET_OFF FLAG.
  1294. //
  1295. if ( *pOrigFlags & MCI_SET_OFF ) {
  1296. dprintf4(( "ThunkSetVideoCmd: Got MCI_SET_OFF flag." ));
  1297. }
  1298. #endif
  1299. *pOrigFlags &= ~(MCI_DGV_SETVIDEO_ITEM | MCI_DGV_SETVIDEO_VALUE |
  1300. MCI_SET_ON | MCI_SET_OFF);
  1301. return (DWORD)lpSetParms32;
  1302. }
  1303. /**********************************************************************\
  1304. * ThunkSysInfoCmd
  1305. *
  1306. * Thunk the SysInfo mci command parms.
  1307. \**********************************************************************/
  1308. DWORD
  1309. ThunkSysInfoCmd(
  1310. PMCI_SYSINFO_PARMS16 lpSysInfo16,
  1311. PMCI_SYSINFO_PARMS lpSysInfo32
  1312. )
  1313. {
  1314. //
  1315. // Thunk the dwRetSize, dwNumber and wDeviceType parameters.
  1316. //
  1317. lpSysInfo32->dwRetSize = FETCHDWORD( lpSysInfo16->dwRetSize );
  1318. dprintf5(( "dwRetSize -> %ld", lpSysInfo32->dwRetSize ));
  1319. lpSysInfo32->dwNumber = FETCHDWORD( lpSysInfo16->dwNumber );
  1320. dprintf5(( "dwNumber -> %ld", lpSysInfo32->dwNumber ));
  1321. lpSysInfo32->wDeviceType = (UINT)FETCHWORD( lpSysInfo16->wDeviceType );
  1322. dprintf5(( "wDeviceType -> %ld", lpSysInfo32->wDeviceType ));
  1323. //
  1324. // Thunk lpstrReturn
  1325. //
  1326. if ( lpSysInfo32->dwRetSize > 0 ) {
  1327. lpSysInfo32->lpstrReturn = GETVDMPTR( lpSysInfo16->lpstrReturn );
  1328. dprintf5(( "lpstrReturn -> 0x%lX", lpSysInfo16->lpstrReturn ));
  1329. }
  1330. else {
  1331. dprintf1(( "ThunkSysInfoCmd: lpstrReturn is 0 bytes long !!!" ));
  1332. /* lpstrReturn has been set to NULL by ZeroMemory above */
  1333. }
  1334. return (DWORD)lpSysInfo32;
  1335. }
  1336. /**********************************************************************\
  1337. * ThunkBreakCmd
  1338. *
  1339. * Thunk the Break mci command parms.
  1340. \**********************************************************************/
  1341. DWORD
  1342. ThunkBreakCmd(
  1343. PDWORD pOrigFlags,
  1344. PMCI_BREAK_PARMS16 lpBreak16,
  1345. PMCI_BREAK_PARMS lpBreak32
  1346. )
  1347. {
  1348. //
  1349. // Check for the MCI_BREAK_KEY flag
  1350. //
  1351. if ( *pOrigFlags & MCI_BREAK_KEY ) {
  1352. dprintf4(( "ThunkBreakCmd: Got MCI_BREAK_KEY flag." ));
  1353. lpBreak32->nVirtKey = (int)FETCHWORD( lpBreak16->nVirtKey );
  1354. dprintf5(( "nVirtKey -> %d", lpBreak32->nVirtKey ));
  1355. }
  1356. //
  1357. // Check for the MCI_BREAK_HWND flag
  1358. //
  1359. if ( *pOrigFlags & MCI_BREAK_HWND ) {
  1360. dprintf4(( "ThunkBreakCmd: Got MCI_BREAK_HWND flag." ));
  1361. lpBreak32->hwndBreak = HWND32(FETCHWORD(lpBreak16->hwndBreak));
  1362. }
  1363. return (DWORD)lpBreak32;
  1364. }
  1365. /**********************************************************************\
  1366. * ThunkWindowCmd
  1367. *
  1368. * Thunk the mci Window command parms.
  1369. \**********************************************************************/
  1370. DWORD
  1371. ThunkWindowCmd(
  1372. MCIDEVICEID DeviceID,
  1373. PDWORD pOrigFlags,
  1374. PMCI_ANIM_WINDOW_PARMS16 lpAniParms16,
  1375. PMCI_ANIM_WINDOW_PARMS lpAniParms32
  1376. )
  1377. {
  1378. //
  1379. // GetDevCaps is used to determine what sort of device are dealing
  1380. // with. We need this information to determine if we should use
  1381. // overlay or animation MCI_WINDOW structure.
  1382. //
  1383. MCI_GETDEVCAPS_PARMS GetDevCaps;
  1384. DWORD dwRetVal;
  1385. //
  1386. // Now we need to determine what type of device we are
  1387. // dealing with. We can do this by send an MCI_GETDEVCAPS
  1388. // command to the device. (We might as well use the Unicode
  1389. // version of mciSendCommand and avoid another thunk).
  1390. //
  1391. ZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) );
  1392. GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
  1393. dwRetVal = mciSendCommandW( DeviceID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM,
  1394. (DWORD)&GetDevCaps );
  1395. //
  1396. // What do we do if dwRetCode is not equal to 0 ? If this is the
  1397. // case it probably means that we have been given a duff device ID,
  1398. // anyway it is pointless to carry on with the thunk so I will clear
  1399. // the *pOrigFlags variable and return. This means that the 32 bit version
  1400. // of mciSendCommand will get called with only half the message thunked,
  1401. // but as there is probably already a problem with the device or
  1402. // the device ID is duff, mciSendCommand should be able to work out a
  1403. // suitable error code to return to the application.
  1404. //
  1405. if ( dwRetVal ) {
  1406. *pOrigFlags = 0;
  1407. return (DWORD)lpAniParms32;
  1408. }
  1409. //
  1410. // Do we have an Animation or Overlay device type ?
  1411. // Because Animation and Overlay have identical flags and
  1412. // parms structures they can share the same code.
  1413. //
  1414. if ( GetDevCaps.dwReturn == MCI_DEVTYPE_ANIMATION
  1415. || GetDevCaps.dwReturn == MCI_DEVTYPE_OVERLAY
  1416. || GetDevCaps.dwReturn == MCI_DEVTYPE_DIGITAL_VIDEO ) {
  1417. //
  1418. // Check for the MCI_ANIM_WINDOW_TEXT
  1419. //
  1420. if ( *pOrigFlags & MCI_ANIM_WINDOW_TEXT ) {
  1421. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_TEXT flag." ));
  1422. lpAniParms32->lpstrText = GETVDMPTR( lpAniParms16->lpstrText );
  1423. dprintf5(( "lpstrText -> %s", lpAniParms32->lpstrText ));
  1424. dprintf5(( "lpstrText -> 0x%lX", lpAniParms32->lpstrText ));
  1425. }
  1426. //
  1427. // Check for the MCI_ANIM_WINDOW_HWND flag
  1428. //
  1429. if ( *pOrigFlags & MCI_ANIM_WINDOW_HWND ) {
  1430. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_HWND flag." ));
  1431. lpAniParms32->hWnd = HWND32( FETCHWORD( lpAniParms16->hWnd ) );
  1432. dprintf5(( "hWnd -> 0x%lX", lpAniParms32->hWnd ));
  1433. }
  1434. //
  1435. // Check for the MCI_ANIM_WINDOW_STATE flag
  1436. //
  1437. if ( *pOrigFlags & MCI_ANIM_WINDOW_STATE ) {
  1438. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_STATE flag." ));
  1439. lpAniParms32->nCmdShow = FETCHWORD( lpAniParms16->nCmdShow );
  1440. dprintf5(( "nCmdShow -> 0x%lX", lpAniParms32->nCmdShow ));
  1441. }
  1442. #if DBG
  1443. //
  1444. // Check for the MCI_ANIM_WINDOW_DISABLE_STRETCH flag
  1445. //
  1446. if ( *pOrigFlags & MCI_ANIM_WINDOW_DISABLE_STRETCH ) {
  1447. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_DISABLE_STRETCH flag." ));
  1448. }
  1449. //
  1450. // Check for the MCI_ANIM_WINDOW_ENABLE_STRETCH flag
  1451. //
  1452. if ( *pOrigFlags & MCI_ANIM_WINDOW_ENABLE_STRETCH ) {
  1453. dprintf4(( "ThunkWindowCmd: Got MCI_Xxxx_WINDOW_ENABLE_STRETCH flag." ));
  1454. }
  1455. #endif
  1456. *pOrigFlags &= ~(MCI_ANIM_WINDOW_TEXT | MCI_ANIM_WINDOW_HWND |
  1457. MCI_ANIM_WINDOW_STATE |
  1458. MCI_ANIM_WINDOW_DISABLE_STRETCH |
  1459. MCI_ANIM_WINDOW_ENABLE_STRETCH );
  1460. }
  1461. return (DWORD)lpAniParms32;
  1462. }
  1463. /**********************************************************************\
  1464. * ThunkCommandViaTable
  1465. *
  1466. \**********************************************************************/
  1467. int
  1468. ThunkCommandViaTable(
  1469. LPWSTR lpCommand,
  1470. DWORD dwFlags,
  1471. DWORD UNALIGNED *pdwOrig16,
  1472. LPBYTE pNewParms
  1473. )
  1474. {
  1475. #if DBG
  1476. static LPSTR f_name = "ThunkCommandViaTable: ";
  1477. #endif
  1478. LPWSTR lpFirstParameter;
  1479. UINT wID;
  1480. DWORD dwValue;
  1481. UINT wOffset16, wOffset1stParm16;
  1482. UINT wOffset32, wOffset1stParm32;
  1483. UINT wParamSize;
  1484. DWORD dwParm16;
  1485. PDWORD pdwParm32;
  1486. DWORD dwMask = 1;
  1487. //
  1488. // Calculate the size of this command parameter block in terms
  1489. // of bytes, then get a VDM pointer to the OrigParms.
  1490. //
  1491. dprintf3(( "%s16 bit Parms -> %lX", f_name, pdwOrig16 ));
  1492. //
  1493. // Skip past command entry
  1494. //
  1495. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1496. mciEatCommandEntry( lpCommand, NULL, NULL ));
  1497. //
  1498. // Get the next entry
  1499. //
  1500. lpFirstParameter = lpCommand;
  1501. //
  1502. // Skip past the DWORD return value
  1503. //
  1504. wOffset1stParm32 = wOffset1stParm16 = 4;
  1505. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1506. mciEatCommandEntry( lpCommand, &dwValue, &wID ));
  1507. //
  1508. // If it is a return value, skip it
  1509. //
  1510. if ( wID == MCI_RETURN ) {
  1511. //
  1512. // Look for a string return type, these are a special case.
  1513. //
  1514. if ( dwValue == MCI_STRING ) {
  1515. DWORD dwStrlen;
  1516. LPSTR *lplpStr;
  1517. //
  1518. // Get string pointer and length
  1519. //
  1520. dwParm16 = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + 4));
  1521. dwStrlen = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + 8));
  1522. //
  1523. // Copy string pointer
  1524. //
  1525. lplpStr = (LPSTR *)(pNewParms + 4);
  1526. if ( dwStrlen > 0 ) {
  1527. *lplpStr = GETVDMPTR( dwParm16 );
  1528. dprintf5(( "%sReturn string -> 0x%lX", f_name, *lplpStr ));
  1529. dprintf5(( "%sReturn length -> 0x%lX", f_name, dwStrlen ));
  1530. }
  1531. //
  1532. // Copy string length
  1533. //
  1534. pdwParm32 = (LPDWORD)(pNewParms + 8);
  1535. *pdwParm32 = dwStrlen;
  1536. }
  1537. //
  1538. // Adjust the offset of the first parameter. Remember that RECTS
  1539. // are a different size in 16-bit world.
  1540. //
  1541. wParamSize = mciGetParamSize( dwValue, wID );
  1542. wOffset1stParm16 += (dwValue == MCI_RECT ? sizeof(RECT16) : wParamSize);
  1543. wOffset1stParm32 += wParamSize;
  1544. //
  1545. // Save the new first parameter
  1546. //
  1547. lpFirstParameter = lpCommand;
  1548. }
  1549. //
  1550. // Walk through each flag
  1551. //
  1552. while ( dwMask != 0 ) {
  1553. //
  1554. // Is this bit set?
  1555. //
  1556. if ( (dwFlags & dwMask) != 0 ) {
  1557. wOffset16 = wOffset1stParm16;
  1558. wOffset32 = wOffset1stParm32;
  1559. lpCommand = (LPWSTR)((LPBYTE)lpFirstParameter +
  1560. mciEatCommandEntry( lpFirstParameter,
  1561. &dwValue, &wID ));
  1562. //
  1563. // What parameter uses this bit?
  1564. //
  1565. while ( wID != MCI_END_COMMAND && dwValue != dwMask ) {
  1566. wParamSize = mciGetParamSize( dwValue, wID );
  1567. wOffset16 += (wID == MCI_RECT ? sizeof( RECT16 ) : wParamSize);
  1568. wOffset32 += wParamSize;
  1569. if ( wID == MCI_CONSTANT ) {
  1570. while ( wID != MCI_END_CONSTANT ) {
  1571. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1572. mciEatCommandEntry( lpCommand, NULL, &wID ));
  1573. }
  1574. }
  1575. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1576. mciEatCommandEntry( lpCommand, &dwValue, &wID ));
  1577. }
  1578. if ( wID != MCI_END_COMMAND ) {
  1579. //
  1580. // Thunk the argument if there is one. The argument is at
  1581. // wOffset16 from the start of OrigParms.
  1582. // This offset is in bytes.
  1583. //
  1584. dprintf5(( "%sOffset 16 -> 0x%lX", f_name, wOffset16 ));
  1585. dprintf5(( "%sOffset 32 -> 0x%lX", f_name, wOffset32 ));
  1586. if ( wID != MCI_FLAG ) {
  1587. dwParm16 = FETCHDWORD(*(LPDWORD)((LPBYTE)pdwOrig16 + wOffset16));
  1588. pdwParm32 = (LPDWORD)(pNewParms + wOffset32);
  1589. }
  1590. switch ( wID ) {
  1591. case MCI_STRING:
  1592. {
  1593. LPSTR str16 = (LPSTR)dwParm16;
  1594. dprintf4(( "%sGot STRING flag -> 0x%lX", f_name, dwMask ));
  1595. *pdwParm32 = (DWORD)GETVDMPTR( str16 );
  1596. dprintf5(( "%s\t-> 0x%lX", f_name, *pdwParm32 ));
  1597. dprintf5(( "%s\t-> %s", f_name, *pdwParm32 ));
  1598. }
  1599. break;
  1600. case MCI_HWND:
  1601. {
  1602. HWND16 hwnd16;
  1603. dprintf4(( "%sGot HWND flag -> 0x%lX", f_name, dwMask ));
  1604. hwnd16 = (HWND16)LOWORD( dwParm16 );
  1605. *pdwParm32 = (DWORD)HWND32( hwnd16 );
  1606. dprintf5(( "\t-> 0x%X", hwnd16 ));
  1607. }
  1608. break;
  1609. case MCI_HPAL:
  1610. {
  1611. HPAL16 hpal16;
  1612. dprintf4(( "%sGot HPAL flag -> 0x%lX", f_name, dwMask ));
  1613. hpal16 = (HPAL16)LOWORD( dwParm16 );
  1614. *pdwParm32 = (DWORD)HPALETTE32( hpal16 );
  1615. dprintf5(( "\t-> 0x%X", hpal16 ));
  1616. }
  1617. break;
  1618. case MCI_HDC:
  1619. {
  1620. HDC16 hdc16;
  1621. dprintf4(( "%sGot HDC flag -> 0x%lX", f_name, dwMask ));
  1622. hdc16 = (HDC16)LOWORD( dwParm16 );
  1623. *pdwParm32 = (DWORD)HDC32( hdc16 );
  1624. dprintf5(( "\t-> 0x%X", hdc16 ));
  1625. }
  1626. break;
  1627. case MCI_RECT:
  1628. {
  1629. PRECT16 pRect16 = (PRECT16)((LPBYTE)pdwOrig16 + wOffset16);
  1630. PRECT pRect32 = (PRECT)pdwParm32;
  1631. dprintf4(( "%sGot RECT flag -> 0x%lX", f_name, dwMask ));
  1632. pRect32->top = (LONG)pRect16->top;
  1633. pRect32->bottom = (LONG)pRect16->bottom;
  1634. pRect32->left = (LONG)pRect16->left;
  1635. pRect32->right = (LONG)pRect16->right;
  1636. }
  1637. break;
  1638. case MCI_CONSTANT:
  1639. case MCI_INTEGER:
  1640. dprintf4(( "%sGot INTEGER flag -> 0x%lX", f_name, dwMask ));
  1641. *pdwParm32 = dwParm16;
  1642. dprintf5(( "\t-> 0x%lX", dwParm16 ));
  1643. break;
  1644. }
  1645. }
  1646. }
  1647. //
  1648. // Go to the next flag
  1649. //
  1650. dwMask <<= 1;
  1651. }
  1652. return 0;
  1653. }
  1654. /**********************************************************************\
  1655. *
  1656. * UnThunkMciCommand16
  1657. *
  1658. * This function "unthunks" a 32 bit mci send command request.
  1659. *
  1660. * The ideas behind this function were stolen from UnThunkWMMsg16,
  1661. * see wmsg16.c
  1662. *
  1663. \**********************************************************************/
  1664. int
  1665. UnThunkMciCommand16(
  1666. MCIDEVICEID devID,
  1667. UINT OrigCommand,
  1668. DWORD OrigFlags,
  1669. PMCI_GENERIC_PARMS16 lp16GenericParms,
  1670. PDWORD NewParms,
  1671. LPWSTR lpCommand,
  1672. UINT uTable
  1673. )
  1674. {
  1675. BOOL fReturnValNotThunked = FALSE;
  1676. #if DBG
  1677. static LPSTR f_name = "UnThunkMciCommand16: ";
  1678. register int i;
  1679. int n;
  1680. dprintf3(( "UnThunkMciCommand :" ));
  1681. n = sizeof(mciMessageNames) / sizeof(MCI_MESSAGE_NAMES);
  1682. for ( i = 0; i < n; i++ ) {
  1683. if ( mciMessageNames[i].uMsg == OrigCommand ) {
  1684. break;
  1685. }
  1686. }
  1687. dprintf3(( "OrigCommand -> %lX", (DWORD)OrigCommand ));
  1688. dprintf3(( " Name -> %s", i != n ? mciMessageNames[i].lpstMsgName : "Unkown Name" ));
  1689. dprintf5(( " OrigFlags -> %lX", OrigFlags ));
  1690. dprintf5(( " OrigParms -> %lX", lp16GenericParms ));
  1691. dprintf5(( " NewParms -> %lX", NewParms ));
  1692. //
  1693. // If NewParms is 0 we shouldn't be here, I haven't got an assert
  1694. // macro, but the following we do the same thing.
  1695. //
  1696. if ( NewParms == 0 ) {
  1697. dprintf(( "%scalled with NewParms == NULL !!", f_name ));
  1698. dprintf(( "Call StephenE NOW !!" ));
  1699. DebugBreak();
  1700. }
  1701. #endif
  1702. //
  1703. // We have to do a manual unthunk of MCI_SYSINFO because the
  1704. // command table is not consistent. As a command table should be
  1705. // available now we can load it and then use it to unthunk MCI_OPEN.
  1706. //
  1707. switch ( OrigCommand ) {
  1708. case MCI_OPEN:
  1709. UnThunkOpenCmd( (PMCI_OPEN_PARMS16)lp16GenericParms,
  1710. (PMCI_OPEN_PARMS)NewParms );
  1711. break;
  1712. case MCI_SYSINFO:
  1713. #if DBG
  1714. UnThunkSysInfoCmd( OrigFlags,
  1715. (PMCI_SYSINFO_PARMS)NewParms );
  1716. #endif
  1717. break;
  1718. case MCI_STATUS:
  1719. UnThunkStatusCmd( devID, OrigFlags,
  1720. (DWORD UNALIGNED *)lp16GenericParms,
  1721. (DWORD)NewParms );
  1722. break;
  1723. default:
  1724. fReturnValNotThunked = TRUE;
  1725. break;
  1726. }
  1727. //
  1728. // Do we have a command table ? It is possible that we have
  1729. // a custom command but we did not find a custom command table, in which
  1730. // case we should just free the pNewParms storage.
  1731. //
  1732. if ( lpCommand != NULL ) {
  1733. //
  1734. // We now parse the custom command table to see if there is a
  1735. // return field in the parms structure.
  1736. //
  1737. dprintf3(( "%sUnthunking via command table", f_name ));
  1738. UnThunkCommandViaTable( lpCommand,
  1739. (DWORD UNALIGNED *)lp16GenericParms,
  1740. (DWORD)NewParms, fReturnValNotThunked );
  1741. //
  1742. // Now we have finished with the command table we should unlock it.
  1743. //
  1744. dprintf4(( "%sUnlocking custom command table", f_name ));
  1745. mciUnlockCommandTable( uTable );
  1746. }
  1747. return 0;
  1748. }
  1749. /**********************************************************************\
  1750. * UnThunkOpenCmd
  1751. *
  1752. * UnThunk the Open mci command parms.
  1753. \**********************************************************************/
  1754. VOID
  1755. UnThunkOpenCmd(
  1756. PMCI_OPEN_PARMS16 lpOpenParms16,
  1757. PMCI_OPEN_PARMS lpOpenParms32
  1758. )
  1759. {
  1760. WORD wDevice;
  1761. dprintf4(( "Copying Device ID." ));
  1762. wDevice = LOWORD( lpOpenParms32->wDeviceID );
  1763. STOREWORD( lpOpenParms16->wDeviceID, wDevice );
  1764. dprintf5(( "wDeviceID -> %u", wDevice ));
  1765. }
  1766. #if DBG
  1767. /**********************************************************************\
  1768. * UnThunkSysInfoCmd
  1769. *
  1770. * UnThunk the SysInfo mci command parms.
  1771. \**********************************************************************/
  1772. VOID
  1773. UnThunkSysInfoCmd(
  1774. DWORD OrigFlags,
  1775. PMCI_SYSINFO_PARMS lpSysParms
  1776. )
  1777. {
  1778. //
  1779. // Had better check that we did actually allocate
  1780. // a pointer.
  1781. //
  1782. if ( lpSysParms->lpstrReturn && lpSysParms->dwRetSize ) {
  1783. if ( !(OrigFlags & MCI_SYSINFO_QUANTITY) ) {
  1784. dprintf5(( "lpstrReturn -> %s", lpSysParms->lpstrReturn ));
  1785. }
  1786. else {
  1787. dprintf5(( "lpstrReturn -> %d", *(LPDWORD)lpSysParms->lpstrReturn ));
  1788. }
  1789. }
  1790. }
  1791. #endif
  1792. /**********************************************************************\
  1793. * UnThunkMciStatus
  1794. *
  1795. * UnThunk the Status mci command parms.
  1796. \**********************************************************************/
  1797. VOID
  1798. UnThunkStatusCmd(
  1799. MCIDEVICEID devID,
  1800. DWORD OrigFlags,
  1801. DWORD UNALIGNED *pdwOrig16,
  1802. DWORD NewParms
  1803. )
  1804. {
  1805. #if DBG
  1806. static LPSTR f_name = "UnThunkStatusCmd: ";
  1807. #endif
  1808. MCI_GETDEVCAPS_PARMS GetDevCaps;
  1809. DWORD dwRetVal;
  1810. DWORD dwParm16;
  1811. PDWORD pdwParm32;
  1812. int iReturnType = MCI_INTEGER;
  1813. /*
  1814. ** If the MCI_STATUS_ITEM flag is not specified don't bother
  1815. ** doing any unthunking.
  1816. */
  1817. if ( !(OrigFlags & MCI_STATUS_ITEM) ) {
  1818. return;
  1819. }
  1820. /*
  1821. ** We need to determine what type of device we are
  1822. ** dealing with. We can do this by send an MCI_GETDEVCAPS
  1823. ** command to the device. (We might as well use the Unicode
  1824. ** version of mciSendCommand and avoid another thunk).
  1825. */
  1826. ZeroMemory( &GetDevCaps, sizeof(MCI_GETDEVCAPS_PARMS) );
  1827. GetDevCaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
  1828. dwRetVal = mciSendCommandW( devID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM,
  1829. (DWORD)&GetDevCaps );
  1830. /*
  1831. ** If we can't get the DevCaps then we are doomed.
  1832. */
  1833. if ( dwRetVal ) {
  1834. dprintf(("%sFailure to get devcaps", f_name));
  1835. return;
  1836. }
  1837. /*
  1838. ** Determine the dwReturn type.
  1839. */
  1840. switch ( GetDevCaps.dwReturn ) {
  1841. case MCI_DEVTYPE_ANIMATION:
  1842. switch ( ((LPDWORD)NewParms)[2] ) {
  1843. case MCI_ANIM_STATUS_HWND:
  1844. iReturnType = MCI_HWND;
  1845. break;
  1846. case MCI_ANIM_STATUS_HPAL:
  1847. iReturnType = MCI_HPAL;
  1848. break;
  1849. }
  1850. break;
  1851. case MCI_DEVTYPE_OVERLAY:
  1852. if ( ((LPDWORD)NewParms)[2] == MCI_OVLY_STATUS_HWND ) {
  1853. iReturnType = MCI_HWND;
  1854. }
  1855. break;
  1856. case MCI_DEVTYPE_DIGITAL_VIDEO:
  1857. switch ( ((LPDWORD)NewParms)[2] ) {
  1858. case MCI_DGV_STATUS_HWND:
  1859. iReturnType = MCI_HWND;
  1860. break;
  1861. case MCI_DGV_STATUS_HPAL:
  1862. iReturnType = MCI_HPAL;
  1863. break;
  1864. }
  1865. break;
  1866. }
  1867. /*
  1868. ** Thunk the dwReturn value according to the required type
  1869. */
  1870. pdwParm32 = (LPDWORD)((LPBYTE)NewParms + 4);
  1871. switch ( iReturnType ) {
  1872. case MCI_HPAL:
  1873. dprintf4(( "%sFound an HPAL return field", f_name ));
  1874. dwParm16 = MAKELONG( GETHPALETTE16( (HPALETTE)*pdwParm32 ), 0 );
  1875. STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
  1876. dprintf5(( "HDC32 -> 0x%lX", *pdwParm32 ));
  1877. dprintf5(( "HDC16 -> 0x%lX", dwParm16 ));
  1878. break;
  1879. case MCI_HWND:
  1880. dprintf4(( "%sFound an HWND return field", f_name ));
  1881. dwParm16 = MAKELONG( GETHWND16( (HWND)*pdwParm32 ), 0 );
  1882. STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
  1883. dprintf5(( "HWND32 -> 0x%lX", *pdwParm32 ));
  1884. dprintf5(( "HWND16 -> 0x%lX", dwParm16 ));
  1885. break;
  1886. case MCI_INTEGER:
  1887. dprintf4(( "%sFound an INTEGER return field", f_name ));
  1888. STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), *pdwParm32 );
  1889. dprintf5(( "INTEGER -> %ld", *pdwParm32 ));
  1890. break;
  1891. // no default: all possible cases accounted for
  1892. }
  1893. }
  1894. /**********************************************************************\
  1895. * UnThunkCommandViaTable
  1896. *
  1897. * Thunks the return field if there is one and then frees and pointers
  1898. * that were got via GETVDMPTR or GETVDMPTR.
  1899. \**********************************************************************/
  1900. int
  1901. UnThunkCommandViaTable(
  1902. LPWSTR lpCommand,
  1903. DWORD UNALIGNED *pdwOrig16,
  1904. DWORD pNewParms,
  1905. BOOL fReturnValNotThunked
  1906. )
  1907. {
  1908. #if DBG
  1909. static LPSTR f_name = "UnThunkCommandViaTable: ";
  1910. #endif
  1911. LPWSTR lpFirstParameter;
  1912. UINT wID;
  1913. DWORD dwValue;
  1914. UINT wOffset1stParm32;
  1915. DWORD dwParm16;
  1916. DWORD Size;
  1917. PDWORD pdwParm32;
  1918. DWORD dwMask = 1;
  1919. //
  1920. // Skip past command entry
  1921. //
  1922. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1923. mciEatCommandEntry( lpCommand, NULL, NULL ));
  1924. //
  1925. // Get the next entry
  1926. //
  1927. lpFirstParameter = lpCommand;
  1928. //
  1929. // Skip past the DWORD return value
  1930. //
  1931. wOffset1stParm32 = 4;
  1932. lpCommand = (LPWSTR)((LPBYTE)lpCommand +
  1933. mciEatCommandEntry( lpCommand, &dwValue, &wID ));
  1934. //
  1935. // If it is a return value, skip it
  1936. //
  1937. if ( (wID == MCI_RETURN) && (fReturnValNotThunked) ) {
  1938. pdwParm32 = (LPDWORD)((LPBYTE)pNewParms + 4);
  1939. //
  1940. // Look for a string return type, these are a special case.
  1941. //
  1942. switch ( dwValue ) {
  1943. #if DBG
  1944. case MCI_STRING:
  1945. dprintf4(( "Found a STRING return field" ));
  1946. //
  1947. // Get string pointer and length
  1948. //
  1949. Size = *(LPDWORD)((LPBYTE)pNewParms + 8);
  1950. //
  1951. // Get the 32 bit string pointer
  1952. //
  1953. if ( Size > 0 ) {
  1954. dprintf4(( "%sFreeing a return STRING pointer", f_name ));
  1955. dprintf5(( "STRING -> %s", (LPSTR)*pdwParm32 ));
  1956. }
  1957. break;
  1958. #endif
  1959. case MCI_RECT:
  1960. {
  1961. PRECT pRect32 = (PRECT)((LPBYTE)pNewParms + 4);
  1962. PRECT16 pRect16 = (PRECT16)((LPBYTE)pdwOrig16 + 4);
  1963. dprintf4(( "%sFound a RECT return field", f_name ));
  1964. pRect16->top = (SHORT)LOWORD(pRect32->top);
  1965. pRect16->bottom = (SHORT)LOWORD(pRect32->bottom);
  1966. pRect16->left = (SHORT)LOWORD(pRect32->left);
  1967. pRect16->right = (SHORT)LOWORD(pRect32->right);
  1968. }
  1969. break;
  1970. case MCI_INTEGER:
  1971. //
  1972. // Get the 32 bit return integer and store it in the
  1973. // 16 bit parameter structure.
  1974. //
  1975. dprintf4(( "%sFound an INTEGER return field", f_name ));
  1976. STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), *pdwParm32 );
  1977. dprintf5(( "INTEGER -> %ld", *pdwParm32 ));
  1978. break;
  1979. case MCI_HWND:
  1980. dprintf4(( "%sFound an HWND return field", f_name ));
  1981. dwParm16 = MAKELONG( GETHWND16( (HWND)*pdwParm32 ), 0 );
  1982. STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
  1983. dprintf5(( "HWND32 -> 0x%lX", *pdwParm32 ));
  1984. dprintf5(( "HWND16 -> 0x%lX", dwParm16 ));
  1985. break;
  1986. case MCI_HPAL:
  1987. dprintf4(( "%sFound an HPAL return field", f_name ));
  1988. dwParm16 = MAKELONG( GETHPALETTE16( (HPALETTE)*pdwParm32 ), 0 );
  1989. STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
  1990. dprintf5(( "HDC32 -> 0x%lX", *pdwParm32 ));
  1991. dprintf5(( "HDC16 -> 0x%lX", dwParm16 ));
  1992. break;
  1993. case MCI_HDC:
  1994. dprintf4(( "%sFound an HDC return field", f_name ));
  1995. dwParm16 = MAKELONG( GETHDC16( (HDC)*pdwParm32 ), 0 );
  1996. STOREDWORD( *(LPDWORD)((LPBYTE)pdwOrig16 + 4), dwParm16 );
  1997. dprintf5(( "HDC32 -> 0x%lX", *pdwParm32 ));
  1998. dprintf5(( "HDC16 -> 0x%lX", dwParm16 ));
  1999. break;
  2000. }
  2001. }
  2002. return 0;
  2003. }
  2004. #endif // _WIN64