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.

3244 lines
91 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: mmwow32.c
  3. *
  4. * This file thunks for the Multi-Media functions.
  5. *
  6. * Created: 1-Jul-1993
  7. * Author: Stephen Estrop [StephenE]
  8. *
  9. * Copyright (c) 1993-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #define NO_GDI
  12. #ifndef WIN32
  13. #define WIN32
  14. #endif
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include "winmmi.h"
  19. #define _INC_ALL_WOWSTUFF
  20. #include "mmwow32.h"
  21. #include "mmwowcb.h"
  22. // #define TELL_THE_TRUTH
  23. #define MIN_TIME_PERIOD_WE_RETURN 1
  24. #if DBG
  25. /*
  26. ** ----------------------------------------------------------------
  27. ** Debugging, Profiling and Tracing variables.
  28. ** ----------------------------------------------------------------
  29. */
  30. int TraceAux = 0;
  31. int TraceJoy = 0;
  32. int TraceTime = 0;
  33. int TraceMix = 0;
  34. int TraceWaveOut = 0;
  35. int TraceWaveIn = 0;
  36. int TraceMidiOut = 0;
  37. int TraceMidiIn = 0;
  38. int DebugLevel = 0;
  39. int AllocWaveCount;
  40. int AllocMidiCount;
  41. #endif
  42. #ifndef _WIN64
  43. PCALLBACK_DATA pCallBackData; // A 32 bit ptr to the 16 bit callback data
  44. CRITICAL_SECTION mmCriticalSection;
  45. TIMECAPS g_TimeCaps32;
  46. LPCALL_ICA_HW_INTERRUPT GenerateInterrupt;
  47. LPGETVDMPOINTER GetVDMPointer;
  48. LPWOWHANDLE32 lpWOWHandle32;
  49. LPWOWHANDLE16 lpWOWHandle16;
  50. DWORD
  51. NotifyCallbackData(
  52. UINT uDevID,
  53. UINT uMsg,
  54. DWORD dwInstance,
  55. DWORD dwParam1,
  56. VPCALLBACK_DATA parg16
  57. );
  58. BOOL APIENTRY
  59. WOW32ResolveMultiMediaHandle(
  60. UINT uHandleType,
  61. UINT uMappingDirection,
  62. WORD wHandle16_In,
  63. LPWORD lpwHandle16_Out,
  64. DWORD dwHandle32_In,
  65. LPDWORD lpdwHandle32_Out
  66. );
  67. /*
  68. ** Constants for use with WOW32ResolveMultiMediaHandle
  69. */
  70. #define WOW32_DIR_16IN_32OUT 0x0001
  71. #define WOW32_DIR_32IN_16OUT 0x0002
  72. #define WOW32_WAVEIN_HANDLE 0x0003
  73. #define WOW32_WAVEOUT_HANDLE 0x0004
  74. #define WOW32_MIDIOUT_HANDLE 0x0005
  75. #define WOW32_MIDIIN_HANDLE 0x0006
  76. /*
  77. ** Constans for auxOutMessage, waveInMessage, waveOutMessage, midiInMessage
  78. ** and midiOutMessage.
  79. */
  80. #define DRV_BUFFER_LOW (DRV_USER - 0x1000) // 0x3000
  81. #define DRV_BUFFER_USER (DRV_USER - 0x0800) // 0x3800
  82. #define DRV_BUFFER_HIGH (DRV_USER - 0x0001) // 0x3FFF
  83. /******************************Public*Routine******************************\
  84. * NotifyCallbackData
  85. *
  86. * This function is called by the 16 bit mmsystem.dll to notify us of the
  87. * address of the callback data structure. The callback data structure
  88. * has been paged locked so that it can be accessed at interrupt time, this
  89. * also means that we can safely keep a 32 bit pointer to the data.
  90. *
  91. * History:
  92. * 22-11-93 - StephenE - Created
  93. *
  94. \**************************************************************************/
  95. DWORD
  96. NotifyCallbackData(
  97. UINT uDevID,
  98. UINT uMsg,
  99. DWORD dwInstance,
  100. DWORD dwParam1,
  101. VPCALLBACK_DATA parg16
  102. )
  103. {
  104. HMODULE hModNTVDM;
  105. if ( parg16 ) {
  106. InitializeCriticalSection( &mmCriticalSection );
  107. hModNTVDM = GetModuleHandleW( (LPCWSTR)L"NTVDM.EXE" );
  108. if ( hModNTVDM ) {
  109. *(FARPROC *)&GenerateInterrupt =
  110. GetProcAddress( hModNTVDM, "call_ica_hw_interrupt" );
  111. }
  112. timeGetDevCaps( &g_TimeCaps32, sizeof(g_TimeCaps32) );
  113. #if !defined(i386)
  114. /*
  115. ** Although the Risc PC's support a uPeriodMin of 1ms, WOW does not
  116. ** seem capable of delivering interrupts at that rate on non
  117. ** intel platforms.
  118. */
  119. g_TimeCaps32.wPeriodMin = 10;
  120. #endif
  121. }
  122. else {
  123. DeleteCriticalSection( &mmCriticalSection );
  124. }
  125. dprintf1(( "Notified of callback address %X", parg16 ));
  126. pCallBackData = GETVDMPTR( parg16 );
  127. return 0L;
  128. }
  129. /******************************Public*Routine******************************\
  130. * wod32Message
  131. *
  132. * Thunks WODM_Xxxx messages
  133. *
  134. * The dwInstance field is used to save the 32 bit version of the decives
  135. * handle. So for example a WODM_PAUSE message can be thunked thus.
  136. * case WODM_PAUSE:
  137. * return waveOutPause( (HWAVEOUT)dwInstance );
  138. *
  139. *
  140. *
  141. * History:
  142. * 22-11-93 - StephenE - Created
  143. *
  144. \**************************************************************************/
  145. DWORD WINAPI
  146. wod32Message(
  147. UINT uDeviceID,
  148. UINT uMessage,
  149. DWORD dwInstance,
  150. DWORD dwParam1,
  151. DWORD dwParam2
  152. )
  153. {
  154. #if DBG
  155. static MSG_NAME name_map[] = {
  156. WODM_GETNUMDEVS, "WODM_GETNUMDEVS",
  157. WODM_GETDEVCAPS, "WODM_GETDEVCAPS",
  158. WODM_OPEN, "WODM_OPEN",
  159. WODM_CLOSE, "WODM_CLOSE",
  160. WODM_PREPARE, "WODM_PREPARE",
  161. WODM_UNPREPARE, "WODM_UNPREPARE",
  162. WODM_WRITE, "WODM_WRITE",
  163. WODM_PAUSE, "WODM_PAUSE",
  164. WODM_RESTART, "WODM_RESTART",
  165. WODM_RESET, "WODM_RESET",
  166. WODM_GETPOS, "WODM_GETPOS",
  167. WODM_GETPITCH, "WODM_GETPITCH",
  168. WODM_SETPITCH, "WODM_SETPITCH",
  169. WODM_GETVOLUME, "WODM_GETVOLUME",
  170. WODM_SETVOLUME, "WODM_SETVOLUME",
  171. WODM_GETPLAYBACKRATE, "WODM_GETPLAYBACKRATE",
  172. WODM_SETPLAYBACKRATE, "WODM_SETPLAYBACKRATE",
  173. WODM_BREAKLOOP, "WODM_BREAKLOOP",
  174. WODM_BUSY, "WODM_BUSY",
  175. WODM_MAPPER_STATUS, "WODM_MAPPER_STATUS"
  176. };
  177. int i;
  178. int n;
  179. #endif
  180. static DWORD dwNumWaveOutDevs;
  181. DWORD dwRet = MMSYSERR_NOTSUPPORTED;
  182. DWORD dwTmp;
  183. DWORD UNALIGNED *lpdwTmp;
  184. WAVEOUTCAPSA woCaps;
  185. MMTIME mmTime32;
  186. #if DBG
  187. for( i = 0, n = sizeof(name_map) / sizeof(name_map[0]); i < n; i++ ) {
  188. if ( name_map[i].uMsg == uMessage ) {
  189. break;
  190. }
  191. }
  192. if ( i != n ) {
  193. trace_waveout(( "wod32Message( 0x%X, %s, 0x%X, 0x%X, 0x%X)",
  194. uDeviceID, name_map[i].lpstrName, dwInstance,
  195. dwParam1, dwParam2 ));
  196. }
  197. else {
  198. trace_waveout(( "wod32Message( 0x%X, 0x%X, 0x%X, 0x%X, 0x%X)",
  199. uDeviceID, uMessage, dwInstance,
  200. dwParam1, dwParam2 ));
  201. }
  202. #endif
  203. /*
  204. ** Make sure that we are consistent with the WAVE_MAPPER
  205. */
  206. if ( LOWORD(uDeviceID) == 0xFFFF ) {
  207. uDeviceID = (UINT)-1;
  208. }
  209. switch ( uMessage ) {
  210. case WODM_GETNUMDEVS:
  211. dwRet = waveOutGetNumDevs();
  212. break;
  213. case WODM_OPEN:
  214. dwRet = ThunkCommonWaveOpen( WAVE_OUT_DEVICE, uDeviceID, dwParam1,
  215. dwParam2, dwInstance );
  216. break;
  217. case WODM_CLOSE:
  218. dwRet = waveOutClose( (HWAVEOUT)dwInstance );
  219. break;
  220. case WODM_BREAKLOOP:
  221. case WODM_PAUSE:
  222. case WODM_RESET:
  223. case WODM_RESTART:
  224. dwRet = waveOutMessage( (HWAVEOUT)dwInstance, uMessage, 0L, 0L );
  225. break;
  226. case WODM_GETDEVCAPS:
  227. // Handle
  228. // Vadimb
  229. if ( 0 == dwInstance ) {
  230. dwRet = waveOutGetDevCapsA(uDeviceID, &woCaps, sizeof(woCaps));
  231. }
  232. else {
  233. dwRet = waveOutMessage((HWAVEOUT)dwInstance,
  234. uMessage,
  235. (DWORD)&woCaps,
  236. sizeof(woCaps));
  237. }
  238. if ( dwRet == MMSYSERR_NOERROR ) {
  239. CopyWaveOutCaps( (LPWAVEOUTCAPS16)GETVDMPTR( dwParam1 ),
  240. &woCaps, dwParam2 );
  241. }
  242. break;
  243. case WODM_GETVOLUME:
  244. /*
  245. ** An application might try to get the volume using either
  246. ** the device ID (waveOutGetVolume) or a handle to the device
  247. ** waveOutMessage( WODM_GETVOLUME...), if the later is the case
  248. ** we must also call waveOutMessage as the device ID will not
  249. ** necessarily be valid. Same applies for waveOutSetVolume below.
  250. */
  251. if ( dwInstance == 0 ) {
  252. dwRet = waveOutGetVolume( (HWAVEOUT)uDeviceID, &dwTmp );
  253. }
  254. else {
  255. dwRet = waveOutMessage( (HWAVEOUT)dwInstance, uMessage,
  256. (DWORD)&dwTmp, 0L );
  257. }
  258. lpdwTmp = GETVDMPTR( dwParam1 );
  259. *lpdwTmp = dwTmp;
  260. break;
  261. case WODM_GETPITCH:
  262. case WODM_GETPLAYBACKRATE:
  263. dwRet = waveOutMessage( (HWAVEOUT)dwInstance, uMessage,
  264. (DWORD)&dwTmp, 0L );
  265. lpdwTmp = GETVDMPTR( dwParam1 );
  266. *lpdwTmp = dwTmp;
  267. break;
  268. case WODM_GETPOS:
  269. GetMMTime( (LPMMTIME16)GETVDMPTR( dwParam1 ), &mmTime32 );
  270. dwRet = waveOutGetPosition( (HWAVEOUT)dwInstance, &mmTime32,
  271. sizeof(mmTime32) );
  272. if ( dwRet == MMSYSERR_NOERROR ) {
  273. PutMMTime( (LPMMTIME16)GETVDMPTR( dwParam1 ), &mmTime32 );
  274. }
  275. break;
  276. case WODM_UNPREPARE:
  277. dwRet = ThunkCommonWaveUnprepareHeader( (HWAVE)dwInstance, dwParam1,
  278. WAVE_OUT_DEVICE );
  279. break;
  280. case WODM_PREPARE:
  281. dwRet = ThunkCommonWavePrepareHeader( (HWAVE)dwInstance, dwParam1,
  282. WAVE_OUT_DEVICE );
  283. break;
  284. case WODM_SETVOLUME:
  285. /*
  286. ** An application might try to set the volume using either
  287. ** the device ID (waveOutSetVolume) or a handle to the device
  288. ** waveOutMessage( WODM_SETVOLUME...), if the later is the case
  289. ** we must also call waveOutMessage as the device ID will not
  290. ** necessarily be valid. Same applies for waveOutGetVolume above.
  291. */
  292. if ( dwInstance == 0 ) {
  293. dwRet = waveOutSetVolume( (HWAVEOUT)uDeviceID, dwParam1 );
  294. }
  295. else {
  296. dwRet = waveOutMessage( (HWAVEOUT)dwInstance, uMessage,
  297. dwParam1, dwParam2 );
  298. }
  299. break;
  300. case WODM_SETPITCH:
  301. case WODM_SETPLAYBACKRATE:
  302. dwRet = waveOutMessage( (HWAVEOUT)dwInstance, uMessage, dwParam1, 0L );
  303. break;
  304. case WODM_WRITE:
  305. dwRet = ThunkCommonWaveReadWrite( WAVE_OUT_DEVICE, dwParam1,
  306. dwParam2, dwInstance );
  307. break;
  308. case WODM_MAPPER_STATUS:
  309. {
  310. WAVEFORMATEX waveFmtEx;
  311. switch ( dwParam1 ) {
  312. case WAVEOUT_MAPPER_STATUS_DEVICE:
  313. case WAVEOUT_MAPPER_STATUS_MAPPED:
  314. dwRet = waveOutMessage( (HWAVEOUT)dwInstance, uMessage,
  315. dwParam1, (DWORD)&dwTmp );
  316. lpdwTmp = GETVDMPTR( dwParam2 );
  317. *lpdwTmp = dwTmp;
  318. break;
  319. case WAVEOUT_MAPPER_STATUS_FORMAT:
  320. dwRet = waveOutMessage( (HWAVEOUT)dwInstance, uMessage,
  321. dwParam1, (DWORD)&waveFmtEx );
  322. CopyMemory( (LPVOID)GETVDMPTR( dwParam2 ),
  323. (LPVOID)&waveFmtEx, sizeof(WAVEFORMATEX) );
  324. break;
  325. default:
  326. dwRet = MMSYSERR_NOTSUPPORTED;
  327. }
  328. }
  329. break;
  330. default:
  331. if ( uMessage >= DRV_BUFFER_LOW && uMessage <= DRV_BUFFER_HIGH ) {
  332. lpdwTmp = GETVDMPTR( dwParam1 );
  333. }
  334. else {
  335. lpdwTmp = (LPDWORD)dwParam1;
  336. }
  337. dwRet = waveOutMessage( (HWAVEOUT)dwInstance, uMessage,
  338. (DWORD)lpdwTmp, dwParam2 );
  339. break;
  340. }
  341. trace_waveout(( "-> 0x%X", dwRet ));
  342. return dwRet;
  343. }
  344. /******************************Public*Routine******************************\
  345. * wid32Message
  346. *
  347. * Thunks WIDM_Xxxx messages
  348. *
  349. *
  350. * History:
  351. * 22-11-93 - StephenE - Created
  352. *
  353. \**************************************************************************/
  354. DWORD WINAPI
  355. wid32Message(
  356. UINT uDeviceID,
  357. UINT uMessage,
  358. DWORD dwInstance,
  359. DWORD dwParam1,
  360. DWORD dwParam2
  361. )
  362. {
  363. #if DBG
  364. static MSG_NAME name_map[] = {
  365. WIDM_GETNUMDEVS, "WIDM_GETNUMDEVS",
  366. WIDM_GETDEVCAPS, "WIDM_GETDEVCAPS",
  367. WIDM_OPEN, "WIDM_OPEN",
  368. WIDM_CLOSE, "WIDM_CLOSE",
  369. WIDM_PREPARE, "WIDM_PREPARE",
  370. WIDM_UNPREPARE, "WIDM_UNPREPARE",
  371. WIDM_ADDBUFFER, "WIDM_ADDBUFFER",
  372. WIDM_START, "WIDM_START",
  373. WIDM_STOP, "WIDM_STOP",
  374. WIDM_RESET, "WIDM_RESET",
  375. WIDM_GETPOS, "WIDM_GETPOS",
  376. WIDM_MAPPER_STATUS, "WIDM_MAPPER_STATUS"
  377. };
  378. int i;
  379. int n;
  380. #endif
  381. static DWORD dwNumWaveInDevs;
  382. DWORD dwRet = MMSYSERR_NOTSUPPORTED;
  383. WAVEINCAPSA wiCaps;
  384. MMTIME mmTime32;
  385. DWORD dwTmp;
  386. DWORD UNALIGNED *lpdwTmp;
  387. #if DBG
  388. for( i = 0, n = sizeof(name_map) / sizeof(name_map[0]); i < n; i++ ) {
  389. if ( name_map[i].uMsg == uMessage ) {
  390. break;
  391. }
  392. }
  393. if ( i != n ) {
  394. trace_wavein(( "wid32Message( 0x%X, %s, 0x%X, 0x%X, 0x%X)",
  395. uDeviceID, name_map[i].lpstrName, dwInstance,
  396. dwParam1, dwParam2 ));
  397. }
  398. else {
  399. trace_wavein(( "wid32Message( 0x%X, 0x%X, 0x%X, 0x%X, 0x%X)",
  400. uDeviceID, uMessage, dwInstance,
  401. dwParam1, dwParam2 ));
  402. }
  403. #endif
  404. /*
  405. ** Make sure that we are consistent with the WAVE_MAPPER
  406. */
  407. if ( LOWORD(uDeviceID) == 0xFFFF ) {
  408. uDeviceID = (UINT)-1;
  409. }
  410. switch ( uMessage ) {
  411. case WIDM_GETNUMDEVS:
  412. dwRet = waveInGetNumDevs();
  413. break;
  414. case WIDM_GETDEVCAPS:
  415. // Handle
  416. // VadimB
  417. if (0 == dwInstance) {
  418. dwRet = waveInGetDevCapsA(uDeviceID, &wiCaps, sizeof(wiCaps));
  419. }
  420. else {
  421. dwRet = waveInMessage((HWAVEIN)dwInstance,
  422. uMessage,
  423. (DWORD)&wiCaps,
  424. sizeof(wiCaps));
  425. }
  426. if ( dwRet == MMSYSERR_NOERROR ) {
  427. CopyWaveInCaps( (LPWAVEINCAPS16)GETVDMPTR( dwParam1 ),
  428. &wiCaps, dwParam2 );
  429. }
  430. break;
  431. case WIDM_OPEN:
  432. dwRet = ThunkCommonWaveOpen( WAVE_IN_DEVICE, uDeviceID, dwParam1,
  433. dwParam2, dwInstance );
  434. break;
  435. case WIDM_UNPREPARE:
  436. dwRet = ThunkCommonWaveUnprepareHeader( (HWAVE)dwInstance, dwParam1,
  437. WAVE_IN_DEVICE );
  438. break;
  439. case WIDM_PREPARE:
  440. dwRet = ThunkCommonWavePrepareHeader( (HWAVE)dwInstance, dwParam1,
  441. WAVE_IN_DEVICE );
  442. break;
  443. case WIDM_ADDBUFFER:
  444. dwRet = ThunkCommonWaveReadWrite( WAVE_IN_DEVICE, dwParam1,
  445. dwParam2, dwInstance );
  446. break;
  447. case WIDM_CLOSE:
  448. dwRet = waveInClose( (HWAVEIN)dwInstance );
  449. break;
  450. case WIDM_START:
  451. case WIDM_STOP:
  452. case WIDM_RESET:
  453. dwRet = waveInMessage( (HWAVEIN)dwInstance, uMessage, 0L, 0L );
  454. break;
  455. case WIDM_GETPOS:
  456. GetMMTime( (LPMMTIME16)GETVDMPTR( dwParam1 ), &mmTime32 );
  457. dwRet = waveInGetPosition( (HWAVEIN)dwInstance, &mmTime32,
  458. sizeof(mmTime32) );
  459. if ( dwRet == MMSYSERR_NOERROR ) {
  460. PutMMTime( (LPMMTIME16)GETVDMPTR( dwParam1 ), &mmTime32 );
  461. }
  462. break;
  463. case WIDM_MAPPER_STATUS:
  464. {
  465. WAVEFORMATEX waveFmtEx;
  466. switch ( dwParam1 ) {
  467. case WAVEIN_MAPPER_STATUS_DEVICE:
  468. case WAVEIN_MAPPER_STATUS_MAPPED:
  469. dwRet = waveInMessage( (HWAVEIN)dwInstance, uMessage,
  470. dwParam1, (DWORD)&dwTmp );
  471. lpdwTmp = GETVDMPTR( dwParam2 );
  472. *lpdwTmp = dwTmp;
  473. break;
  474. case WAVEIN_MAPPER_STATUS_FORMAT:
  475. dwRet = waveInMessage( (HWAVEIN)dwInstance, uMessage,
  476. dwParam1, (DWORD)&waveFmtEx );
  477. CopyMemory( (LPVOID)GETVDMPTR( dwParam2 ),
  478. (LPVOID)&waveFmtEx, sizeof(WAVEFORMATEX) );
  479. break;
  480. default:
  481. dwRet = MMSYSERR_NOTSUPPORTED;
  482. }
  483. }
  484. break;
  485. default:
  486. if ( uMessage >= DRV_BUFFER_LOW && uMessage <= DRV_BUFFER_HIGH ) {
  487. lpdwTmp = GETVDMPTR( dwParam1 );
  488. }
  489. else {
  490. lpdwTmp = (LPDWORD)dwParam1;
  491. }
  492. dwRet = waveInMessage( (HWAVEIN)dwInstance, uMessage,
  493. (DWORD)lpdwTmp, dwParam2 );
  494. }
  495. trace_wavein(( "-> 0x%X", dwRet ));
  496. return dwRet;
  497. }
  498. /*****************************Private*Routine******************************\
  499. * ThunkCommonWaveOpen
  500. *
  501. * Thunks all wave device opens
  502. *
  503. * History:
  504. * 22-11-93 - StephenE - Created
  505. *
  506. \**************************************************************************/
  507. DWORD
  508. ThunkCommonWaveOpen(
  509. int iWhich,
  510. UINT uDeviceID,
  511. DWORD dwParam1,
  512. DWORD dwParam2,
  513. DWORD dwInstance
  514. )
  515. {
  516. /*
  517. ** dwParam1 is a 16:16 pointer to a WAVEOPENDESC16 structure.
  518. ** dwParam2 specifies any option flags used when opening the device.
  519. */
  520. LPWAVEOPENDESC16 lpOpenDesc16;
  521. WAVEFORMATEX UNALIGNED *lpFormat16;
  522. DWORD dwRet;
  523. WAVEFORMAT wf[4];
  524. WAVEFORMATEX *lpFormat32;
  525. lpOpenDesc16 = GETVDMPTR( dwParam1 );
  526. lpFormat16 = GETVDMPTR( lpOpenDesc16->lpFormat );
  527. /*
  528. ** Thunk the wave format structure. If the wave format tag is PCM
  529. ** we just copy the structure as is. If the wave format size
  530. ** is less than or equal to sizeof(wf) again just copy the
  531. ** structure as is, otherwise we allocate a new structure and then
  532. ** copy 16 bit wave format into it.
  533. */
  534. switch ( lpFormat16->wFormatTag ) {
  535. case WAVE_FORMAT_PCM:
  536. CopyMemory( (LPVOID)&wf[0], (LPVOID)lpFormat16, sizeof(PCMWAVEFORMAT) );
  537. lpFormat32 = (WAVEFORMATEX *)&wf[0];
  538. break;
  539. default:
  540. if ( sizeof(WAVEFORMATEX) + lpFormat16->cbSize > sizeof(wf) ) {
  541. lpFormat32 = winmmAlloc( sizeof(WAVEFORMATEX) + lpFormat16->cbSize );
  542. if (lpFormat32 == NULL) {
  543. return MMSYSERR_NOMEM;
  544. }
  545. }
  546. else {
  547. lpFormat32 = (WAVEFORMATEX *)&wf[0];
  548. }
  549. CopyMemory( (LPVOID)lpFormat32, (LPVOID)lpFormat16,
  550. sizeof(WAVEFORMATEX) + lpFormat16->cbSize );
  551. break;
  552. }
  553. /*
  554. ** If the app is only querying the device we don't have to do very
  555. ** much, just pass the mapped format to waveOutOpen.
  556. */
  557. if ( dwParam2 & WAVE_FORMAT_QUERY ) {
  558. if ( iWhich == WAVE_OUT_DEVICE ) {
  559. dwRet = waveOutOpen( NULL, uDeviceID, lpFormat32,
  560. lpOpenDesc16->dwCallback,
  561. lpOpenDesc16->dwInstance, dwParam2 );
  562. }
  563. else {
  564. dwRet = waveInOpen( NULL, uDeviceID, lpFormat32,
  565. lpOpenDesc16->dwCallback,
  566. lpOpenDesc16->dwInstance, dwParam2 );
  567. }
  568. }
  569. else {
  570. HWAVE Hand32;
  571. PINSTANCEDATA pInstanceData;
  572. /*
  573. ** Create InstanceData block to be used by our callback routine.
  574. **
  575. ** NOTE: Although we malloc it here we don't free it.
  576. ** This is not a mistake - it must not be freed before the
  577. ** callback routine has used it - so it does the freeing.
  578. **
  579. ** If the malloc fails we bomb down to the bottom,
  580. ** set dwRet to MMSYSERR_NOMEM and exit gracefully.
  581. **
  582. ** We always have a callback functions. This is to ensure that
  583. ** the WAVEHDR structure keeps getting copied back from
  584. ** 32 bit space to 16 bit, as it contains flags which
  585. ** applications are liable to keep checking.
  586. */
  587. pInstanceData = winmmAlloc(sizeof(INSTANCEDATA) );
  588. if ( pInstanceData != NULL ) {
  589. DWORD dwNewFlags = CALLBACK_FUNCTION;
  590. dprintf2(( "WaveCommonOpen: Allocated instance buffer at 0x%8X",
  591. pInstanceData ));
  592. dprintf2(( "16 bit callback = 0x%X", lpOpenDesc16->dwCallback ));
  593. pInstanceData->Hand16 = lpOpenDesc16->hWave;
  594. pInstanceData->dwCallback = lpOpenDesc16->dwCallback;
  595. pInstanceData->dwCallbackInstance = lpOpenDesc16->dwInstance;
  596. pInstanceData->dwFlags = dwParam2;
  597. dwNewFlags |= (dwParam2 & WAVE_ALLOWSYNC);
  598. if ( iWhich == WAVE_OUT_DEVICE ) {
  599. dwRet = waveOutOpen( (LPHWAVEOUT)&Hand32, uDeviceID, lpFormat32,
  600. (DWORD)W32CommonDeviceCB,
  601. (DWORD)pInstanceData, dwNewFlags );
  602. }
  603. else {
  604. dwRet = waveInOpen( (LPHWAVEIN)&Hand32, uDeviceID, lpFormat32,
  605. (DWORD)W32CommonDeviceCB,
  606. (DWORD)pInstanceData, dwNewFlags );
  607. }
  608. /*
  609. ** If the call returns success save a copy of the 32 bit handle
  610. ** otherwise free the memory we malloc'd earlier, as the
  611. ** callback that would have freed it will never get callled.
  612. */
  613. if ( dwRet == MMSYSERR_NOERROR ) {
  614. DWORD UNALIGNED *lpDw;
  615. lpDw = GETVDMPTR( dwInstance );
  616. *lpDw = (DWORD)Hand32;
  617. SetWOWHandle( Hand32, lpOpenDesc16->hWave );
  618. trace_waveout(( "Handle -> %x", Hand32 ));
  619. }
  620. else {
  621. dprintf2(( "WaveCommonOpen: Freeing instance buffer at %8X "
  622. "because open failed", pInstanceData ));
  623. winmmFree( pInstanceData );
  624. }
  625. }
  626. else {
  627. dwRet = MMSYSERR_NOMEM;
  628. }
  629. }
  630. /*
  631. ** Free the wave format structure if one was allocated.
  632. */
  633. if (lpFormat32 != (WAVEFORMATEX *)&wf[0] ) {
  634. winmmFree( lpFormat32 );
  635. }
  636. return dwRet;
  637. }
  638. /*****************************Private*Routine******************************\
  639. * ThunkCommonWaveReadWrite
  640. *
  641. * Thunks all wave reads and writes.
  642. *
  643. * History:
  644. * 22-11-93 - StephenE - Created
  645. *
  646. \**************************************************************************/
  647. DWORD
  648. ThunkCommonWaveReadWrite(
  649. int iWhich,
  650. DWORD dwParam1,
  651. DWORD dwParam2,
  652. DWORD dwInstance
  653. )
  654. {
  655. UINT ul;
  656. PWAVEHDR32 p32WaveHdr;
  657. WAVEHDR16 UNALIGNED *lp16;
  658. /*
  659. ** Get a pointer to the shadow WAVEHDR buffer.
  660. */
  661. lp16 = GETVDMPTR( dwParam1 );
  662. p32WaveHdr = (PWAVEHDR32)lp16->reserved;
  663. /*
  664. ** Make sure that the wave headers are consistent.
  665. */
  666. p32WaveHdr->Wavehdr.lpData = GETVDMPTR( (PWAVEHDR32)lp16->lpData );
  667. p32WaveHdr->pWavehdr32 = lp16;
  668. CopyMemory( (LPVOID)&p32WaveHdr->Wavehdr.dwBufferLength,
  669. (LPVOID)&lp16->dwBufferLength,
  670. (sizeof(WAVEHDR) - sizeof(LPSTR) - sizeof(DWORD)) );
  671. /*
  672. ** Call either waveInAddBuffer or waveOutWrite as determined by
  673. ** iWhich.
  674. */
  675. if ( iWhich == WAVE_OUT_DEVICE ) {
  676. ul = waveOutWrite( (HWAVEOUT)dwInstance,
  677. &p32WaveHdr->Wavehdr, sizeof(WAVEHDR) );
  678. }
  679. else {
  680. ul = waveInAddBuffer( (HWAVEIN)dwInstance,
  681. &p32WaveHdr->Wavehdr, sizeof(WAVEHDR) );
  682. }
  683. /*
  684. ** If the call worked reflect any change in the wave header back into
  685. ** the header that the application gave use.
  686. */
  687. if ( ul == MMSYSERR_NOERROR ) {
  688. PutWaveHdr16( lp16, &p32WaveHdr->Wavehdr );
  689. }
  690. return ul;
  691. }
  692. /*****************************Private*Routine******************************\
  693. * ThunkCommonWavePrepareHeader
  694. *
  695. * This function sets up the following structure...
  696. *
  697. *
  698. * +-------------+ +-------------+
  699. * 0:32 | pWavehdr32 |------>| Original |
  700. * +-------------+ | header |
  701. * 16:16 | pWavehdr16 |------>| passed by |
  702. * +-------------+<--+ | the 16 bit |
  703. * | New 32 bit | | | |
  704. * | header thats| | | |
  705. * | used instead| | | |
  706. * | of the one | | +-------------+
  707. * | passed to by| +---| reserved |
  708. * | application.| +-------------+
  709. * | |
  710. * +-------------+
  711. *
  712. * ... and then calls waveXxxPrepareHeader as determioned by iWhich.
  713. *
  714. * Used by:
  715. * waveOutPrepareHdr
  716. * waveInPrepareHdr
  717. *
  718. *
  719. * History:
  720. * dd-mm-94 - StephenE - Created
  721. *
  722. \**************************************************************************/
  723. DWORD
  724. ThunkCommonWavePrepareHeader(
  725. HWAVE hWave,
  726. DWORD dwParam1,
  727. int iWhich
  728. )
  729. {
  730. PWAVEHDR32 p32WaveHdr;
  731. DWORD ul;
  732. WAVEHDR16 UNALIGNED *lp16;
  733. lp16 = GETVDMPTR( dwParam1 );
  734. /*
  735. ** Allocate some storage for the new wave header structure.
  736. ** On debug builds we keep track of the number of wave headers allocated
  737. ** and freed.
  738. */
  739. p32WaveHdr = (PWAVEHDR32)winmmAlloc( sizeof(WAVEHDR32) );
  740. if ( p32WaveHdr != NULL ) {
  741. #if DBG
  742. AllocWaveCount++;
  743. dprintf2(( "WH>> 0x%X (%d)", p32WaveHdr, AllocWaveCount ));
  744. #endif
  745. /*
  746. ** Copy the header given to us by the application into the newly
  747. ** allocated header. Note that GetWaveHdr returns a 0:32 pointer
  748. ** to the applications 16 bit header, which we save for later use.
  749. */
  750. p32WaveHdr->pWavehdr16 = (PWAVEHDR16)dwParam1;
  751. p32WaveHdr->pWavehdr32 = GetWaveHdr16( dwParam1,
  752. &p32WaveHdr->Wavehdr );
  753. /*
  754. ** Prepare the real header
  755. */
  756. if ( iWhich == WAVE_OUT_DEVICE ) {
  757. ul = waveOutPrepareHeader( (HWAVEOUT)hWave,
  758. &p32WaveHdr->Wavehdr,
  759. sizeof(WAVEHDR) );
  760. }
  761. else {
  762. ul = waveInPrepareHeader( (HWAVEIN)hWave,
  763. &p32WaveHdr->Wavehdr,
  764. sizeof(WAVEHDR) );
  765. }
  766. if ( ul == MMSYSERR_NOERROR ) {
  767. /*
  768. ** Copy back the prepared header so that any changed fields are
  769. ** updated.
  770. */
  771. PutWaveHdr16( lp16, &p32WaveHdr->Wavehdr );
  772. /*
  773. ** Save a back pointer to the newly allocated header in the
  774. ** reserved field.
  775. */
  776. lp16->reserved = (DWORD)p32WaveHdr;
  777. }
  778. else {
  779. /*
  780. ** Some error happened, anyway the wave header is now trash so
  781. ** free the allocated storage etc.
  782. */
  783. winmmFree( p32WaveHdr );
  784. #if DBG
  785. AllocWaveCount--;
  786. dprintf2(( "WH<< 0x%X (%d)", p32WaveHdr, AllocWaveCount ));
  787. #endif
  788. }
  789. }
  790. else {
  791. dprintf2(( "Could not allocate shadow wave header!!" ));
  792. ul = MMSYSERR_NOMEM;
  793. }
  794. return ul;
  795. }
  796. /*****************************Private*Routine******************************\
  797. * ThunkCommonWaveUnprepareHeader
  798. *
  799. *
  800. *
  801. * History:
  802. * dd-mm-94 - StephenE - Created
  803. *
  804. \**************************************************************************/
  805. DWORD
  806. ThunkCommonWaveUnprepareHeader(
  807. HWAVE hWave,
  808. DWORD dwParam1,
  809. int iWhich
  810. )
  811. {
  812. DWORD ul;
  813. PWAVEHDR32 p32WaveHdr;
  814. WAVEHDR16 UNALIGNED *lp16;
  815. BOOL fDoneBitSet;
  816. lp16 = (WAVEHDR16 UNALIGNED *)GETVDMPTR( dwParam1 );
  817. p32WaveHdr = (PWAVEHDR32)lp16->reserved;
  818. /*
  819. ** The DK Stowaway app clears the done bit before calling
  820. ** waveOutUnprepareHeader and depends on the done bit being cleared when
  821. ** this api returns.
  822. **
  823. ** So when we copy the 32 bit flags back we make sure that the done
  824. ** is left in the same state that we found it
  825. */
  826. fDoneBitSet = (lp16->dwFlags & WHDR_DONE);
  827. /*
  828. ** Now call waveXxxUnprepare header with the shadow buffer as determined
  829. ** by iWhich.
  830. */
  831. if ( iWhich == WAVE_OUT_DEVICE ) {
  832. ul = waveOutUnprepareHeader( (HWAVEOUT)hWave,
  833. &p32WaveHdr->Wavehdr, sizeof(WAVEHDR) );
  834. }
  835. else {
  836. ul = waveInUnprepareHeader( (HWAVEIN)hWave,
  837. &p32WaveHdr->Wavehdr, sizeof(WAVEHDR) );
  838. }
  839. /*
  840. ** Reflect any changes made by waveOutUnprepareHeader back into the
  841. ** the buffer that the application gave us.
  842. */
  843. if ( ul == MMSYSERR_NOERROR ) {
  844. PutWaveHdr16( lp16, &p32WaveHdr->Wavehdr );
  845. /*
  846. ** Make sure that we leave the done bit in the same state that we
  847. ** found it.
  848. */
  849. if (fDoneBitSet) {
  850. lp16->dwFlags |= WHDR_DONE;
  851. }
  852. else {
  853. lp16->dwFlags &= ~WHDR_DONE;
  854. }
  855. /*
  856. ** If everything worked OK we should free the shadow wave header
  857. ** here.
  858. */
  859. #if DBG
  860. AllocWaveCount--;
  861. dprintf2(( "WH<< 0x%X (%d)", p32WaveHdr, AllocWaveCount ));
  862. #endif
  863. winmmFree( p32WaveHdr );
  864. }
  865. return ul;
  866. }
  867. /*****************************Private*Routine******************************\
  868. * CopyWaveOutCaps
  869. *
  870. * Copies 32 bit wave out caps info into the passed 16bit storage.
  871. *
  872. * History:
  873. * 22-11-93 - StephenE - Created
  874. *
  875. \**************************************************************************/
  876. void
  877. CopyWaveOutCaps(
  878. LPWAVEOUTCAPS16 lpCaps16,
  879. LPWAVEOUTCAPSA lpCaps32,
  880. DWORD dwSize
  881. )
  882. {
  883. WAVEOUTCAPS16 Caps16;
  884. Caps16.wMid = lpCaps32->wMid;
  885. Caps16.wPid = lpCaps32->wPid;
  886. Caps16.vDriverVersion = LOWORD( lpCaps32->vDriverVersion );
  887. CopyMemory( Caps16.szPname, lpCaps32->szPname, MAXPNAMELEN );
  888. Caps16.dwFormats = lpCaps32->dwFormats;
  889. Caps16.wChannels = lpCaps32->wChannels;
  890. Caps16.dwSupport = lpCaps32->dwSupport;
  891. CopyMemory( (LPVOID)lpCaps16, (LPVOID)&Caps16, (UINT)dwSize );
  892. }
  893. /*****************************Private*Routine******************************\
  894. * CopyWaveInCaps
  895. *
  896. * Copies 32 bit wave in caps info into the passed 16bit storage.
  897. *
  898. * History:
  899. * 22-11-93 - StephenE - Created
  900. *
  901. \**************************************************************************/
  902. void
  903. CopyWaveInCaps(
  904. LPWAVEINCAPS16 lpCaps16,
  905. LPWAVEINCAPSA lpCaps32,
  906. DWORD dwSize
  907. )
  908. {
  909. WAVEINCAPS16 Caps16;
  910. Caps16.wMid = lpCaps32->wMid;
  911. Caps16.wPid = lpCaps32->wPid;
  912. Caps16.vDriverVersion = LOWORD( lpCaps32->vDriverVersion );
  913. CopyMemory( Caps16.szPname, lpCaps32->szPname, MAXPNAMELEN );
  914. Caps16.dwFormats = lpCaps32->dwFormats;
  915. Caps16.wChannels = lpCaps32->wChannels;
  916. CopyMemory( (LPVOID)lpCaps16, (LPVOID)&Caps16, (UINT)dwSize );
  917. }
  918. /******************************Public*Routine******************************\
  919. * GetWaveHdr16
  920. *
  921. * Thunks a WAVEHDR structure from 16 bit to 32 bit space.
  922. *
  923. * Used by:
  924. * waveOutWrite
  925. * waveInAddBuffer
  926. *
  927. * Returns a 32 bit pointer to the 16 bit wave header. This wave header
  928. * should have been locked down by wave(In|Out)PrepareHeader. Therefore,
  929. * it is to store this pointer for use during the WOM_DONE callback message.
  930. *
  931. * With the WAVEHDR and MIDIHDR structs I am assured by Robin that the ->lpNext
  932. * field is only used by the driver, and is therefore in 32 bit space. It
  933. * therefore doesn't matter what gets passed back and forth (I hope !).
  934. *
  935. * History:
  936. * 22-11-93 - StephenE - Created
  937. *
  938. \**************************************************************************/
  939. PWAVEHDR16
  940. GetWaveHdr16(
  941. DWORD vpwhdr,
  942. LPWAVEHDR lpwhdr
  943. )
  944. {
  945. register PWAVEHDR16 pwhdr16;
  946. pwhdr16 = GETVDMPTR(vpwhdr);
  947. if ( pwhdr16 == NULL ) {
  948. dprintf1(( "getwavehdr16 GETVDMPTR returned an invalid pointer" ));
  949. return NULL;
  950. }
  951. CopyMemory( (LPVOID)lpwhdr, (LPVOID)pwhdr16, sizeof(*lpwhdr) );
  952. lpwhdr->lpData = GETVDMPTR( pwhdr16->lpData );
  953. return pwhdr16;
  954. }
  955. /******************************Public*Routine******************************\
  956. * PutWaveHdr16
  957. *
  958. * Thunks a WAVEHDR structure from 32 bit back to 16 bit space.
  959. *
  960. * Used by:
  961. * waveOutPrepareHeader
  962. * waveOutUnprepareHeader
  963. * waveOutWrite
  964. * waveInPrepareHeader
  965. * waveInUnprepareHeader
  966. * waveInAddBuffer
  967. *
  968. * History:
  969. * 22-11-93 - StephenE - Created
  970. *
  971. \**************************************************************************/
  972. void
  973. PutWaveHdr16(
  974. WAVEHDR16 UNALIGNED *pwhdr16,
  975. LPWAVEHDR lpwhdr
  976. )
  977. {
  978. LPSTR lpDataSave = pwhdr16->lpData;
  979. DWORD dwReservedSave = pwhdr16->reserved;
  980. CopyMemory( (LPVOID)pwhdr16, (LPVOID)lpwhdr, sizeof(WAVEHDR) );
  981. pwhdr16->lpData = lpDataSave;
  982. pwhdr16->reserved = dwReservedSave;
  983. }
  984. /******************************Public*Routine******************************\
  985. * mod32Message
  986. *
  987. * Thunks all midi out apis.
  988. *
  989. * History:
  990. * 22-11-93 - StephenE - Created
  991. *
  992. \**************************************************************************/
  993. DWORD WINAPI
  994. mod32Message(
  995. UINT uDeviceID,
  996. UINT uMessage,
  997. DWORD dwInstance,
  998. DWORD dwParam1,
  999. DWORD dwParam2
  1000. )
  1001. {
  1002. #if DBG
  1003. static MSG_NAME name_map[] = {
  1004. MODM_GETNUMDEVS, "MODM_GETNUMDEVS",
  1005. MODM_GETDEVCAPS, "MODM_GETDEVCAPS",
  1006. MODM_OPEN, "MODM_OPEN",
  1007. MODM_CLOSE, "MODM_CLOSE",
  1008. MODM_PREPARE, "MODM_PREPARE",
  1009. MODM_UNPREPARE, "MODM_UNPREPARE",
  1010. MODM_DATA, "MODM_DATA",
  1011. MODM_RESET, "MODM_RESET",
  1012. MODM_LONGDATA, "MODM_LONGDATA",
  1013. MODM_GETVOLUME, "MODM_GETVOLUME",
  1014. MODM_SETVOLUME, "MODM_SETVOLUME" ,
  1015. MODM_CACHEDRUMPATCHES, "MODM_CACHEDRUMPATCHES",
  1016. MODM_CACHEPATCHES, "MODM_CACHEPATCHES"
  1017. };
  1018. int i;
  1019. int n;
  1020. #endif
  1021. static DWORD dwNumMidiOutDevs;
  1022. DWORD dwRet = MMSYSERR_NOTSUPPORTED;
  1023. DWORD dwTmp = 0;
  1024. DWORD UNALIGNED *lpdwTmp;
  1025. MIDIOUTCAPSA moCaps;
  1026. #if DBG
  1027. for( i = 0, n = sizeof(name_map) / sizeof(name_map[0]); i < n; i++ ) {
  1028. if ( name_map[i].uMsg == uMessage ) {
  1029. break;
  1030. }
  1031. }
  1032. if ( i != n ) {
  1033. trace_midiout(( "mod32Message( 0x%X, %s, 0x%X, 0x%X, 0x%X)",
  1034. uDeviceID, name_map[i].lpstrName, dwInstance,
  1035. dwParam1, dwParam2 ));
  1036. }
  1037. else {
  1038. trace_midiout(( "mod32Message( 0x%X, 0x%X, 0x%X, 0x%X, 0x%X)",
  1039. uDeviceID, uMessage, dwInstance,
  1040. dwParam1, dwParam2 ));
  1041. }
  1042. #endif
  1043. if ( LOWORD(uDeviceID) == 0xFFFF ) {
  1044. uDeviceID = (UINT)-1;
  1045. }
  1046. switch ( uMessage ) {
  1047. case MODM_GETNUMDEVS:
  1048. dwRet = midiOutGetNumDevs();
  1049. break;
  1050. case MODM_GETDEVCAPS:
  1051. //
  1052. // this api also might take a valid handle in uDeviceID
  1053. // per Win95 behavior
  1054. // VadimB
  1055. if (0 == dwInstance) {
  1056. dwRet = midiOutGetDevCapsA( uDeviceID, &moCaps, sizeof(moCaps));
  1057. }
  1058. else {
  1059. dwRet = midiOutMessage((HMIDIOUT)dwInstance,
  1060. uMessage,
  1061. (DWORD)&moCaps,
  1062. sizeof(moCaps));
  1063. }
  1064. if ( dwRet == MMSYSERR_NOERROR ) {
  1065. CopyMidiOutCaps( (LPMIDIOUTCAPS16)GETVDMPTR( dwParam1 ),
  1066. &moCaps, dwParam2 );
  1067. }
  1068. break;
  1069. case MODM_OPEN:
  1070. dwRet = ThunkCommonMidiOpen( MIDI_OUT_DEVICE, uDeviceID, dwParam1,
  1071. dwParam2, dwInstance );
  1072. break;
  1073. case MODM_LONGDATA:
  1074. dwRet = ThunkCommonMidiReadWrite( MIDI_OUT_DEVICE, dwParam1,
  1075. dwParam2, dwInstance );
  1076. break;
  1077. case MODM_PREPARE:
  1078. dwRet = ThunkCommonMidiPrepareHeader( (HMIDI)dwInstance, dwParam1,
  1079. MIDI_OUT_DEVICE );
  1080. break;
  1081. case MODM_UNPREPARE:
  1082. dwRet = ThunkCommonMidiUnprepareHeader( (HMIDI)dwInstance, dwParam1,
  1083. MIDI_OUT_DEVICE );
  1084. break;
  1085. case MODM_DATA:
  1086. dwRet = midiOutShortMsg( (HMIDIOUT)dwInstance, dwParam1 );
  1087. break;
  1088. case MODM_CLOSE:
  1089. dwRet = midiOutClose( (HMIDIOUT)dwInstance );
  1090. break;
  1091. case MODM_RESET:
  1092. dwRet = midiOutMessage( (HMIDIOUT)dwInstance, uMessage,
  1093. dwParam1, dwParam2 );
  1094. break;
  1095. case MODM_SETVOLUME:
  1096. /*
  1097. ** An application might try to set the volume using either
  1098. ** the device ID (midiOutSetVolume) or a handle to the device
  1099. ** midiOutMessage( MODM_SETVOLUME...), if the later is the case
  1100. ** we must also call midiOutMessage as the device ID will not
  1101. ** necessarily be valid. Same applies for midiOutGetVolume below.
  1102. */
  1103. if ( dwInstance == 0 ) {
  1104. dwRet = midiOutSetVolume( (HMIDIOUT)uDeviceID, dwParam1 );
  1105. }
  1106. else {
  1107. dwRet = midiOutMessage( (HMIDIOUT)dwInstance, uMessage,
  1108. dwParam1, dwParam2 );
  1109. }
  1110. break;
  1111. case MODM_GETVOLUME:
  1112. if ( dwInstance == 0 ) {
  1113. dwRet = midiOutGetVolume( (HMIDIOUT)uDeviceID, &dwTmp );
  1114. }
  1115. else {
  1116. dwRet = midiOutMessage( (HMIDIOUT)dwInstance, uMessage,
  1117. (DWORD)&dwTmp, dwParam2 );
  1118. }
  1119. lpdwTmp = GETVDMPTR( dwParam1 );
  1120. *lpdwTmp = dwTmp;
  1121. break;
  1122. case MODM_CACHEPATCHES:
  1123. case MODM_CACHEDRUMPATCHES:
  1124. {
  1125. LPWORD lpCache;
  1126. lpCache = winmmAlloc( MIDIPATCHSIZE * sizeof(WORD) );
  1127. if ( lpCache != NULL ) {
  1128. lpdwTmp = GETVDMPTR( dwParam1 );
  1129. CopyMemory( (LPVOID)lpCache, (LPVOID)lpdwTmp,
  1130. MIDIPATCHSIZE * sizeof(WORD) );
  1131. dwRet = midiOutMessage( (HMIDIOUT)dwInstance, uMessage,
  1132. (DWORD)lpCache, dwParam2 );
  1133. winmmFree( lpCache );
  1134. }
  1135. else {
  1136. dwRet = MMSYSERR_NOMEM;
  1137. }
  1138. }
  1139. break;
  1140. default:
  1141. if ( uMessage >= DRV_BUFFER_LOW && uMessage <= DRV_BUFFER_HIGH ) {
  1142. lpdwTmp = GETVDMPTR( dwParam1 );
  1143. }
  1144. else {
  1145. lpdwTmp = (LPDWORD)dwParam1;
  1146. }
  1147. dwRet = midiOutMessage( (HMIDIOUT)dwInstance, uMessage,
  1148. (DWORD)lpdwTmp, dwParam2 );
  1149. }
  1150. trace_midiout(( "-> 0x%X", dwRet ));
  1151. return dwRet;
  1152. }
  1153. /******************************Public*Routine******************************\
  1154. * mid32Message
  1155. *
  1156. * Thunks all midi in apis.
  1157. *
  1158. * History:
  1159. * 22-11-93 - StephenE - Created
  1160. *
  1161. \**************************************************************************/
  1162. DWORD WINAPI
  1163. mid32Message(
  1164. UINT uDeviceID,
  1165. UINT uMessage,
  1166. DWORD dwInstance,
  1167. DWORD dwParam1,
  1168. DWORD dwParam2
  1169. )
  1170. {
  1171. #if DBG
  1172. static MSG_NAME name_map[] = {
  1173. MIDM_GETNUMDEVS, "MIDM_GETNUMDEVS",
  1174. MIDM_GETDEVCAPS, "MIDM_GETDEVCAPS",
  1175. MIDM_OPEN, "MIDM_OPEN",
  1176. MIDM_ADDBUFFER, "MIDM_ADDBUFFER",
  1177. MIDM_CLOSE, "MIDM_CLOSE",
  1178. MIDM_PREPARE, "MIDM_PREPARE",
  1179. MIDM_UNPREPARE, "MIDM_UNPREPARE",
  1180. MIDM_RESET, "MIDM_RESET",
  1181. MIDM_START, "MIDM_START",
  1182. MIDM_STOP, "MIDM_STOP",
  1183. };
  1184. int i;
  1185. int n;
  1186. #endif
  1187. static DWORD dwNumMidiInDevs;
  1188. DWORD dwRet = MMSYSERR_NOTSUPPORTED;
  1189. MIDIINCAPSA miCaps;
  1190. DWORD UNALIGNED *lpdwTmp;
  1191. #if DBG
  1192. for( i = 0, n = sizeof(name_map) / sizeof(name_map[0]); i < n; i++ ) {
  1193. if ( name_map[i].uMsg == uMessage ) {
  1194. break;
  1195. }
  1196. }
  1197. if ( i != n ) {
  1198. trace_midiin(( "mid32Message( 0x%X, %s, 0x%X, 0x%X, 0x%X)",
  1199. uDeviceID, name_map[i].lpstrName, dwInstance,
  1200. dwParam1, dwParam2 ));
  1201. }
  1202. else {
  1203. trace_midiin(( "mid32Message( 0x%X, 0x%X, 0x%X, 0x%X, 0x%X)",
  1204. uDeviceID, uMessage, dwInstance,
  1205. dwParam1, dwParam2 ));
  1206. }
  1207. #endif
  1208. if ( LOWORD(uDeviceID) == 0xFFFF ) {
  1209. uDeviceID = (UINT)-1;
  1210. }
  1211. switch ( uMessage ) {
  1212. case MIDM_GETNUMDEVS:
  1213. dwRet = midiInGetNumDevs();
  1214. break;
  1215. case MIDM_GETDEVCAPS:
  1216. // Handle
  1217. // VadimB
  1218. if (0 == dwInstance) {
  1219. dwRet = midiInGetDevCapsA( uDeviceID, &miCaps, sizeof(miCaps));
  1220. }
  1221. else {
  1222. dwRet = midiInMessage((HMIDIIN)dwInstance,
  1223. uMessage,
  1224. (DWORD)&miCaps,
  1225. sizeof(miCaps));
  1226. }
  1227. if ( dwRet == MMSYSERR_NOERROR ) {
  1228. CopyMidiInCaps( (LPMIDIINCAPS16)GETVDMPTR( dwParam1 ),
  1229. &miCaps, dwParam2 );
  1230. }
  1231. break;
  1232. case MIDM_OPEN:
  1233. dwRet = ThunkCommonMidiOpen( MIDI_IN_DEVICE, uDeviceID, dwParam1,
  1234. dwParam2, dwInstance );
  1235. break;
  1236. case MIDM_ADDBUFFER:
  1237. dwRet = ThunkCommonMidiReadWrite( MIDI_IN_DEVICE, dwParam1,
  1238. dwParam2, dwInstance );
  1239. break;
  1240. case MIDM_PREPARE:
  1241. dwRet = ThunkCommonMidiPrepareHeader( (HMIDI)dwInstance, dwParam1,
  1242. MIDI_IN_DEVICE );
  1243. break;
  1244. case MIDM_UNPREPARE:
  1245. dwRet = ThunkCommonMidiUnprepareHeader( (HMIDI)dwInstance, dwParam1,
  1246. MIDI_IN_DEVICE );
  1247. break;
  1248. case MIDM_CLOSE:
  1249. dwRet = midiInClose( (HMIDIIN)dwInstance );
  1250. break;
  1251. case MIDM_START:
  1252. case MIDM_STOP:
  1253. case MIDM_RESET:
  1254. dwRet = midiInMessage( (HMIDIIN)dwInstance, uMessage,
  1255. dwParam1, dwParam2 );
  1256. break;
  1257. default:
  1258. if ( uMessage >= DRV_BUFFER_LOW && uMessage <= DRV_BUFFER_HIGH ) {
  1259. lpdwTmp = GETVDMPTR( dwParam1 );
  1260. }
  1261. else {
  1262. lpdwTmp = (LPDWORD)dwParam1;
  1263. }
  1264. dwRet = midiInMessage( (HMIDIIN)dwInstance, uMessage,
  1265. (DWORD)lpdwTmp, dwParam2 );
  1266. }
  1267. trace_midiin(( "-> 0x%X", dwRet ));
  1268. return dwRet;
  1269. }
  1270. /*****************************Private*Routine******************************\
  1271. * ThunkCommonMidiOpen
  1272. *
  1273. * Thunks all midi open requests.
  1274. *
  1275. * History:
  1276. * 22-11-93 - StephenE - Created
  1277. *
  1278. \**************************************************************************/
  1279. DWORD
  1280. ThunkCommonMidiOpen(
  1281. int iWhich,
  1282. UINT uDeviceID,
  1283. DWORD dwParam1,
  1284. DWORD dwParam2,
  1285. DWORD dwInstance
  1286. )
  1287. {
  1288. /*
  1289. ** dwParam1 is a 16:16 pointer to a MIDIOPENDESC16 structure.
  1290. ** dwParam2 specifies any option flags used when opening the device.
  1291. */
  1292. LPMIDIOPENDESC16 lpOpenDesc16;
  1293. DWORD dwRet;
  1294. HMIDI Hand32;
  1295. PINSTANCEDATA pInstanceData;
  1296. lpOpenDesc16 = GETVDMPTR( dwParam1 );
  1297. /*
  1298. ** Create InstanceData block to be used by our callback routine.
  1299. **
  1300. ** NOTE: Although we malloc it here we don't free it.
  1301. ** This is not a mistake - it must not be freed before the
  1302. ** callback routine has used it - so it does the freeing.
  1303. **
  1304. ** If the malloc fails we bomb down to the bottom,
  1305. ** set dwRet to MMSYSERR_NOMEM and exit gracefully.
  1306. **
  1307. ** We always have a callback functions. This is to ensure that
  1308. ** the MIDIHDR structure keeps getting copied back from
  1309. ** 32 bit space to 16 bit, as it contains flags which
  1310. ** applications are liable to keep checking.
  1311. */
  1312. pInstanceData = winmmAlloc(sizeof(INSTANCEDATA) );
  1313. if ( pInstanceData != NULL ) {
  1314. DWORD dwNewFlags = CALLBACK_FUNCTION;
  1315. dprintf2(( "MidiCommonOpen: Allocated instance buffer at 0x%8X",
  1316. pInstanceData ));
  1317. dprintf2(( "16 bit callback = 0x%X", lpOpenDesc16->dwCallback ));
  1318. pInstanceData->Hand16 = lpOpenDesc16->hMidi;
  1319. pInstanceData->dwCallback = lpOpenDesc16->dwCallback;
  1320. pInstanceData->dwCallbackInstance = lpOpenDesc16->dwInstance;
  1321. pInstanceData->dwFlags = dwParam2;
  1322. if ( iWhich == MIDI_OUT_DEVICE ) {
  1323. dwRet = midiOutOpen( (LPHMIDIOUT)&Hand32, uDeviceID,
  1324. (DWORD)W32CommonDeviceCB,
  1325. (DWORD)pInstanceData, dwNewFlags );
  1326. }
  1327. else {
  1328. dwRet = midiInOpen( (LPHMIDIIN)&Hand32, uDeviceID,
  1329. (DWORD)W32CommonDeviceCB,
  1330. (DWORD)pInstanceData, dwNewFlags );
  1331. }
  1332. /*
  1333. ** If the call returns success save a copy of the 32 bit handle
  1334. ** otherwise free the memory we malloc'd earlier, as the
  1335. ** callback that would have freed it will never get callled.
  1336. */
  1337. if ( dwRet == MMSYSERR_NOERROR ) {
  1338. DWORD UNALIGNED *lpDw;
  1339. lpDw = GETVDMPTR( dwInstance );
  1340. *lpDw = (DWORD)Hand32;
  1341. SetWOWHandle( Hand32, lpOpenDesc16->hMidi );
  1342. #if DBG
  1343. if ( iWhich == MIDI_OUT_DEVICE ) {
  1344. trace_midiout(( "Handle -> %x", Hand32 ));
  1345. }
  1346. else {
  1347. trace_midiout(( "Handle -> %x", Hand32 ));
  1348. }
  1349. #endif
  1350. }
  1351. else {
  1352. dprintf2(( "MidiCommonOpen: Freeing instance buffer at %8X "
  1353. "because open failed", pInstanceData ));
  1354. winmmFree( pInstanceData );
  1355. }
  1356. }
  1357. else {
  1358. dwRet = MMSYSERR_NOMEM;
  1359. }
  1360. return dwRet;
  1361. }
  1362. /*****************************Private*Routine******************************\
  1363. * ThunkCommonMidiReadWrite
  1364. *
  1365. * Thunks all midi read/write requests.
  1366. *
  1367. * History:
  1368. * 22-11-93 - StephenE - Created
  1369. *
  1370. \**************************************************************************/
  1371. DWORD
  1372. ThunkCommonMidiReadWrite(
  1373. int iWhich,
  1374. DWORD dwParam1,
  1375. DWORD dwParam2,
  1376. DWORD dwInstance
  1377. )
  1378. {
  1379. UINT ul;
  1380. PMIDIHDR32 p32MidiHdr;
  1381. MIDIHDR UNALIGNED *lp16;
  1382. /*
  1383. ** Get a pointer to the shadow MIDIHDR buffer.
  1384. */
  1385. lp16 = GETVDMPTR( dwParam1 );
  1386. p32MidiHdr = (PMIDIHDR32)lp16->reserved;
  1387. /*
  1388. ** Make sure that the midi headers are consistent.
  1389. */
  1390. CopyMemory( (LPVOID)&p32MidiHdr->Midihdr.dwBufferLength,
  1391. (LPVOID)&lp16->dwBufferLength,
  1392. (sizeof(MIDIHDR) - sizeof(LPSTR) - sizeof(DWORD)) );
  1393. p32MidiHdr->Midihdr.reserved = p32MidiHdr->reserved;
  1394. /*
  1395. ** Call either midiInAddBuffer or midiOutWrite as determined by
  1396. ** iWhich.
  1397. */
  1398. if ( iWhich == MIDI_OUT_DEVICE ) {
  1399. ul = midiOutLongMsg( (HMIDIOUT)dwInstance,
  1400. &p32MidiHdr->Midihdr, sizeof(MIDIHDR) );
  1401. }
  1402. else {
  1403. ul = midiInAddBuffer( (HMIDIIN)dwInstance,
  1404. &p32MidiHdr->Midihdr, sizeof(MIDIHDR) );
  1405. }
  1406. /*
  1407. ** If the call worked reflect any change in the midi header back into
  1408. ** the header that the application gave use.
  1409. */
  1410. if ( ul == MMSYSERR_NOERROR ) {
  1411. PutMidiHdr16( lp16, &p32MidiHdr->Midihdr );
  1412. }
  1413. return ul;
  1414. }
  1415. /*****************************Private*Routine******************************\
  1416. * ThunkCommonMidiPrepareHeader
  1417. *
  1418. * This function sets up the following structure...
  1419. *
  1420. *
  1421. * +-------------+ +-------------+
  1422. * 0:32 | pMidihdr32 |------>| Original |
  1423. * +-------------+ | header |
  1424. * 16:16 | pMidihdr16 |------>| passed by |
  1425. * +-------------+<--+ | the 16 bit |
  1426. * | New 32 bit | | | |
  1427. * | header thats| | | |
  1428. * | used instead| | | |
  1429. * | of the one | | +-------------+
  1430. * | passed to by| +---| reserved |
  1431. * | application.| +-------------+
  1432. * | |
  1433. * +-------------+
  1434. *
  1435. * ... and then calls midiXxxPrepareHeader as determioned by iWhich.
  1436. *
  1437. * Used by:
  1438. * midiOutPrepareHdr
  1439. * midiInPrepareHdr
  1440. *
  1441. *
  1442. * History:
  1443. * dd-mm-94 - StephenE - Created
  1444. *
  1445. \**************************************************************************/
  1446. DWORD
  1447. ThunkCommonMidiPrepareHeader(
  1448. HMIDI hMidi,
  1449. DWORD dwParam1,
  1450. int iWhich
  1451. )
  1452. {
  1453. PMIDIHDR32 p32MidiHdr;
  1454. DWORD ul;
  1455. MIDIHDR UNALIGNED *lp16;
  1456. lp16 = GETVDMPTR( dwParam1 );
  1457. /*
  1458. ** Allocate some storage for the new midi header structure.
  1459. ** On debug builds we keep track of the number of midi headers allocated
  1460. ** and freed.
  1461. */
  1462. p32MidiHdr = (PMIDIHDR32)winmmAlloc( sizeof(MIDIHDR32) );
  1463. if ( p32MidiHdr != NULL ) {
  1464. #if DBG
  1465. AllocMidiCount++;
  1466. dprintf2(( "MH>> 0x%X (%d)", p32MidiHdr, AllocMidiCount ));
  1467. #endif
  1468. /*
  1469. ** Copy the header given to us by the application into the newly
  1470. ** allocated header. Note that GetMidiHdr returns a 0:32 pointer
  1471. ** to the applications 16 bit header, which we save for later use.
  1472. */
  1473. p32MidiHdr->pMidihdr16 = (PMIDIHDR16)dwParam1;
  1474. p32MidiHdr->pMidihdr32 = GetMidiHdr16( dwParam1,
  1475. &p32MidiHdr->Midihdr );
  1476. /*
  1477. ** Prepare the real header
  1478. */
  1479. if ( iWhich == MIDI_OUT_DEVICE ) {
  1480. ul = midiOutPrepareHeader( (HMIDIOUT)hMidi,
  1481. &p32MidiHdr->Midihdr,
  1482. sizeof(MIDIHDR) );
  1483. }
  1484. else {
  1485. ul = midiInPrepareHeader( (HMIDIIN)hMidi,
  1486. &p32MidiHdr->Midihdr,
  1487. sizeof(MIDIHDR) );
  1488. }
  1489. if ( ul == MMSYSERR_NOERROR ) {
  1490. /*
  1491. ** Save a copy of the reserved field, MidiMap uses it.
  1492. */
  1493. p32MidiHdr->reserved = p32MidiHdr->Midihdr.reserved;
  1494. /*
  1495. ** Copy back the prepared header so that any changed fields are
  1496. ** updated.
  1497. */
  1498. PutMidiHdr16( lp16, &p32MidiHdr->Midihdr );
  1499. /*
  1500. ** Save a back pointer to the newly allocated header in the
  1501. ** reserved field.
  1502. */
  1503. lp16->reserved = (DWORD)p32MidiHdr;
  1504. }
  1505. else {
  1506. /*
  1507. ** Some error happened, anyway the midi header is now trash so
  1508. ** free the allocated storage etc.
  1509. */
  1510. winmmFree( p32MidiHdr );
  1511. #if DBG
  1512. AllocMidiCount--;
  1513. dprintf2(( "MH<< 0x%X (%d)", p32MidiHdr, AllocMidiCount ));
  1514. #endif
  1515. }
  1516. }
  1517. else {
  1518. dprintf2(( "Could not allocate shadow midi header!!" ));
  1519. ul = MMSYSERR_NOMEM;
  1520. }
  1521. return ul;
  1522. }
  1523. /*****************************Private*Routine******************************\
  1524. * ThunkCommonMidiUnprepareHeader
  1525. *
  1526. *
  1527. *
  1528. * History:
  1529. * dd-mm-94 - StephenE - Created
  1530. *
  1531. \**************************************************************************/
  1532. DWORD
  1533. ThunkCommonMidiUnprepareHeader(
  1534. HMIDI hMidi,
  1535. DWORD dwParam1,
  1536. int iWhich
  1537. )
  1538. {
  1539. DWORD ul;
  1540. PMIDIHDR32 p32MidiHdr;
  1541. MIDIHDR UNALIGNED *lp16;
  1542. lp16 = (MIDIHDR UNALIGNED *)GETVDMPTR( dwParam1 );
  1543. p32MidiHdr = (PMIDIHDR32)lp16->reserved;
  1544. p32MidiHdr->Midihdr.reserved = p32MidiHdr->reserved;
  1545. /*
  1546. ** Now call midiXxxUnprepare header with the shadow buffer as determined
  1547. ** by iWhich.
  1548. */
  1549. if ( iWhich == MIDI_OUT_DEVICE ) {
  1550. ul = midiOutUnprepareHeader( (HMIDIOUT)hMidi,
  1551. &p32MidiHdr->Midihdr, sizeof(MIDIHDR) );
  1552. }
  1553. else {
  1554. ul = midiInUnprepareHeader( (HMIDIIN)hMidi,
  1555. &p32MidiHdr->Midihdr, sizeof(MIDIHDR) );
  1556. }
  1557. /*
  1558. ** Reflect any changes made by midiOutUnprepareHeader back into the
  1559. ** the buffer that the application gave us.
  1560. */
  1561. if ( ul == MMSYSERR_NOERROR ) {
  1562. PutMidiHdr16( lp16, &p32MidiHdr->Midihdr );
  1563. /*
  1564. ** If everything worked OK we should free the shadow midi header
  1565. ** here.
  1566. */
  1567. #if DBG
  1568. AllocMidiCount--;
  1569. dprintf2(( "MH<< 0x%X (%d)", p32MidiHdr, AllocMidiCount ));
  1570. #endif
  1571. winmmFree( p32MidiHdr );
  1572. }
  1573. return ul;
  1574. }
  1575. /*****************************Private*Routine******************************\
  1576. * CopyMidiOutCaps
  1577. *
  1578. * Copies 32 bit midi out caps info into the passed 16bit storage.
  1579. *
  1580. * History:
  1581. * 22-11-93 - StephenE - Created
  1582. *
  1583. \**************************************************************************/
  1584. void
  1585. CopyMidiOutCaps(
  1586. LPMIDIOUTCAPS16 lpCaps16,
  1587. LPMIDIOUTCAPSA lpCaps32,
  1588. DWORD dwSize
  1589. )
  1590. {
  1591. MIDIOUTCAPS16 Caps16;
  1592. Caps16.wMid = lpCaps32->wMid;
  1593. Caps16.wPid = lpCaps32->wPid;
  1594. CopyMemory( Caps16.szPname, lpCaps32->szPname, MAXPNAMELEN );
  1595. Caps16.vDriverVersion = LOWORD( lpCaps32->vDriverVersion );
  1596. Caps16.wTechnology = lpCaps32->wTechnology;
  1597. Caps16.wVoices = lpCaps32->wVoices;
  1598. Caps16.wNotes = lpCaps32->wNotes;
  1599. Caps16.wChannelMask = lpCaps32->wChannelMask;
  1600. Caps16.dwSupport = lpCaps32->dwSupport;
  1601. CopyMemory( (LPVOID)lpCaps16, (LPVOID)&Caps16, (UINT)dwSize );
  1602. }
  1603. /*****************************Private*Routine******************************\
  1604. * CopyMidiInCaps
  1605. *
  1606. * Copies 32 bit midi in caps info into the passed 16bit storage.
  1607. *
  1608. * History:
  1609. * 22-11-93 - StephenE - Created
  1610. *
  1611. \**************************************************************************/
  1612. void
  1613. CopyMidiInCaps(
  1614. LPMIDIINCAPS16 lpCaps16,
  1615. LPMIDIINCAPSA lpCaps32,
  1616. DWORD dwSize
  1617. )
  1618. {
  1619. MIDIINCAPS16 Caps16;
  1620. Caps16.wMid = lpCaps32->wMid;
  1621. Caps16.wPid = lpCaps32->wPid;
  1622. Caps16.vDriverVersion = LOWORD( lpCaps32->vDriverVersion );
  1623. CopyMemory( Caps16.szPname, lpCaps32->szPname, MAXPNAMELEN );
  1624. CopyMemory( (LPVOID)lpCaps16, (LPVOID)&Caps16, (UINT)dwSize );
  1625. }
  1626. /******************************Public*Routine******************************\
  1627. * GetMidiHdr16
  1628. *
  1629. * Thunks a MIDIHDR structure from 16 bit to 32 bit space.
  1630. *
  1631. * Used by:
  1632. * midiOutLongMsg
  1633. * midiInAddBuffer
  1634. *
  1635. * Returns a 32 bit pointer to the 16 bit midi header. This midi header
  1636. * should have been locked down by midi(In|Out)PrepareHeader. Therefore,
  1637. * it is to store this pointer for use during the WOM_DONE callback message.
  1638. *
  1639. * With the MIDIHDR and MIDIHDR structs I am assured by Robin that the ->lpNext
  1640. * field is only used by the driver, and is therefore in 32 bit space. It
  1641. * therefore doesn't matter what gets passed back and forth (I hope !).
  1642. *
  1643. * History:
  1644. * 22-11-93 - StephenE - Created
  1645. *
  1646. \**************************************************************************/
  1647. PMIDIHDR16
  1648. GetMidiHdr16(
  1649. DWORD vpmhdr,
  1650. LPMIDIHDR lpmhdr
  1651. )
  1652. {
  1653. register PMIDIHDR16 pmhdr16;
  1654. pmhdr16 = GETVDMPTR(vpmhdr);
  1655. if ( pmhdr16 == NULL ) {
  1656. dprintf1(( "getmidihdr16 GETVDMPTR returned an invalid pointer" ));
  1657. return NULL;
  1658. }
  1659. CopyMemory( (LPVOID)lpmhdr, (LPVOID)pmhdr16, sizeof(*lpmhdr) );
  1660. lpmhdr->lpData = GETVDMPTR( pmhdr16->lpData );
  1661. return pmhdr16;
  1662. }
  1663. /******************************Public*Routine******************************\
  1664. * PutMidiHdr16
  1665. *
  1666. * Thunks a MIDIHDR structure from 32 bit back to 16 bit space.
  1667. *
  1668. * Used by:
  1669. * midiOutPrepareHeader
  1670. * midiOutUnprepareHeader
  1671. * midiOutLongMsg
  1672. * midiInPrepareHeader
  1673. * midiInUnprepareHeader
  1674. * midiInAddBuffer
  1675. *
  1676. * History:
  1677. * 22-11-93 - StephenE - Created
  1678. *
  1679. \**************************************************************************/
  1680. void
  1681. PutMidiHdr16(
  1682. MIDIHDR UNALIGNED *pmhdr16,
  1683. LPMIDIHDR lpmhdr
  1684. )
  1685. {
  1686. LPSTR lpDataSave = pmhdr16->lpData;
  1687. DWORD dwReservedSave = pmhdr16->reserved;
  1688. CopyMemory( (LPVOID)pmhdr16, (LPVOID)lpmhdr, sizeof(MIDIHDR) );
  1689. pmhdr16->lpData = lpDataSave;
  1690. pmhdr16->reserved = dwReservedSave;
  1691. }
  1692. /*****************************Private*Routine******************************\
  1693. * PutMMTime
  1694. *
  1695. * Puts an MMTIME structure from 32 bit storage into 16 bit storage
  1696. *
  1697. * History:
  1698. * 22-11-93 - StephenE - Created
  1699. *
  1700. \**************************************************************************/
  1701. void
  1702. PutMMTime(
  1703. LPMMTIME16 lpTime16,
  1704. LPMMTIME lpTime32
  1705. )
  1706. {
  1707. lpTime16->wType = LOWORD(lpTime32->wType);
  1708. switch ( lpTime32->wType ) {
  1709. case TIME_MS:
  1710. lpTime16->u.ms = lpTime32->u.ms;
  1711. break;
  1712. case TIME_SAMPLES:
  1713. lpTime16->u.sample = lpTime32->u.sample;
  1714. break;
  1715. case TIME_BYTES:
  1716. lpTime16->u.cb = lpTime32->u.cb;
  1717. break;
  1718. case TIME_SMPTE:
  1719. lpTime16->u.smpte.hour = lpTime32->u.smpte.hour;
  1720. lpTime16->u.smpte.min = lpTime32->u.smpte.min;
  1721. lpTime16->u.smpte.sec = lpTime32->u.smpte.sec;
  1722. lpTime16->u.smpte.frame = lpTime32->u.smpte.frame;
  1723. lpTime16->u.smpte.fps = lpTime32->u.smpte.fps;
  1724. lpTime16->u.smpte.dummy = lpTime32->u.smpte.dummy;
  1725. break;
  1726. case TIME_MIDI:
  1727. lpTime16->u.midi.songptrpos = lpTime32->u.midi.songptrpos;
  1728. break;
  1729. }
  1730. }
  1731. /*****************************Private*Routine******************************\
  1732. * GetMMTime
  1733. *
  1734. * Gets an MMTIME structure from 16 bit storage into 32 bit storage
  1735. *
  1736. * History:
  1737. * 22-11-93 - StephenE - Created
  1738. *
  1739. \**************************************************************************/
  1740. void
  1741. GetMMTime(
  1742. LPMMTIME16 lpTime16,
  1743. LPMMTIME lpTime32
  1744. )
  1745. {
  1746. lpTime32->wType = lpTime16->wType;
  1747. switch ( lpTime32->wType ) {
  1748. case TIME_MS:
  1749. lpTime32->u.ms = lpTime16->u.ms;
  1750. break;
  1751. case TIME_SAMPLES:
  1752. lpTime32->u.sample = lpTime16->u.sample;
  1753. break;
  1754. case TIME_BYTES:
  1755. lpTime32->u.cb = lpTime16->u.cb;
  1756. break;
  1757. case TIME_SMPTE:
  1758. lpTime32->u.smpte.hour = lpTime16->u.smpte.hour;
  1759. lpTime32->u.smpte.min = lpTime16->u.smpte.min;
  1760. lpTime32->u.smpte.sec = lpTime16->u.smpte.sec;
  1761. lpTime32->u.smpte.frame = lpTime16->u.smpte.frame;
  1762. lpTime32->u.smpte.fps = lpTime16->u.smpte.fps;
  1763. lpTime32->u.smpte.dummy = lpTime16->u.smpte.dummy;
  1764. break;
  1765. case TIME_MIDI:
  1766. lpTime32->u.midi.songptrpos = lpTime16->u.midi.songptrpos;
  1767. break;
  1768. }
  1769. }
  1770. /******************************Public*Routine******************************\
  1771. * W32CommonDeviceCB
  1772. *
  1773. * This routine is the callback which is ALWAYS called by wave and midi
  1774. * functions. This is done to ensure that the XXXXHDR structure keeps
  1775. * getting copied back from 32 bit space to 16 bit, as it contains flags
  1776. * which the application is liable to keep checking.
  1777. *
  1778. * The way this whole business works is that the wave/midi data stays in 16
  1779. * bit space, but the XXXXHDR is copied to the 32 bit side, with the
  1780. * address of the data thunked accordingly so that Robin's device driver
  1781. * can still get at the data but we don't have the performance penalty of
  1782. * copying it back and forth all the time, not least because it is liable
  1783. * to be rather large...
  1784. *
  1785. * It also handles the tidying up of memory which is reserved to store
  1786. * the XXXXHDR, and the instance data (HWND/Callback address; instance
  1787. * data; flags) which the xxxxOpen calls pass to this routine, enabling
  1788. * it to forward messages or call callback as required.
  1789. *
  1790. * This routine handles all the messages that get sent from Robin's
  1791. * driver, and in fact thunks them back to the correct 16 bit form. In
  1792. * theory there should be no MM_ format messages from the 16 bit side, so
  1793. * I can zap 'em out of WMSG16. However the 32 bit side should thunk the
  1794. * mesages correctly and forward them to the 16 bit side and thence to
  1795. * the app.
  1796. *
  1797. * For the MM_WIM_DATA and MM_WOM_DONE message dwParam1 points to the
  1798. * following data struture.
  1799. *
  1800. * P32HDR is a 32 bit pointer to the original 16 bit header
  1801. * P16HDR is a 16 bit far pointer to the original 16 bit header
  1802. *
  1803. * If we need to refernece the original header we must do via the
  1804. * P32HDR pointer.
  1805. *
  1806. * +---------+
  1807. * | P32HDR +----->+---------+
  1808. * +---------+ | 16 bit |
  1809. * | P16HDR +----->| | This is the original
  1810. * dwParam1 ----->+---------+ | Wave | wave header passed to
  1811. * | 32 bit | | Header | us by the Win 16 app.
  1812. * This is the 32 | | | |
  1813. * bit wave | Wave | +---------+
  1814. * header that we | Header |
  1815. * thunked at | |
  1816. * earlier. +---------+
  1817. *
  1818. *
  1819. * We must ensure that the 32 bit structure is completely hidden from the
  1820. * 16 bit application, ie. the 16 bit app only see's the wave header that it
  1821. * passed to us earlier.
  1822. *
  1823. *
  1824. * NOTE: dwParam2 is junk
  1825. *
  1826. *
  1827. *
  1828. * History:
  1829. * 22-11-93 - StephenE - Created
  1830. *
  1831. \**************************************************************************/
  1832. VOID
  1833. W32CommonDeviceCB(
  1834. HANDLE handle,
  1835. UINT uMsg,
  1836. DWORD dwInstance,
  1837. DWORD dwParam1,
  1838. DWORD dwParam2
  1839. )
  1840. {
  1841. PWAVEHDR32 pWavehdr32;
  1842. PMIDIHDR32 pMidiThunkHdr;
  1843. PINSTANCEDATA pInstanceData;
  1844. HANDLE16 Hand16;
  1845. pInstanceData = (PINSTANCEDATA)dwInstance;
  1846. WinAssert( pInstanceData );
  1847. switch (uMsg) {
  1848. /* ------------------------------------------------------------
  1849. ** MIDI INPUT MESSAGES
  1850. ** ------------------------------------------------------------
  1851. */
  1852. case MM_MIM_LONGDATA:
  1853. /*
  1854. ** This message is sent to a window when an input buffer has been
  1855. ** filled with MIDI system-exclusive data and is being returned to
  1856. ** the application.
  1857. */
  1858. case MM_MIM_LONGERROR:
  1859. /*
  1860. ** This message is sent to a window when an invalid MIDI
  1861. ** system-exclusive message is received.
  1862. */
  1863. pMidiThunkHdr = CONTAINING_RECORD(dwParam1, MIDIHDR32, Midihdr);
  1864. WinAssert( pMidiThunkHdr );
  1865. COPY_MIDIINHDR16_FLAGS( pMidiThunkHdr->pMidihdr32, pMidiThunkHdr->Midihdr );
  1866. dwParam1 = (DWORD)pMidiThunkHdr->pMidihdr16;
  1867. case MM_MIM_DATA:
  1868. /*
  1869. ** This message is sent to a window when a MIDI message is
  1870. ** received by a MIDI input device.
  1871. */
  1872. case MM_MIM_ERROR:
  1873. /*
  1874. ** This message is sent to a window when an invalid MIDI message
  1875. ** is received.
  1876. */
  1877. case MM_MIM_OPEN:
  1878. /*
  1879. ** This message is sent to a window when a MIDI input device is opened.
  1880. ** We process this message the same way as MM_MIM_CLOSE (see below)
  1881. */
  1882. case MM_MIM_CLOSE:
  1883. /*
  1884. ** This message is sent to a window when a MIDI input device is
  1885. ** closed. The device handle is no longer valid once this message
  1886. ** has been sent.
  1887. */
  1888. Hand16 = pInstanceData->Hand16;
  1889. break;
  1890. /* ------------------------------------------------------------
  1891. ** MIDI OUTPUT MESSAGES
  1892. ** ------------------------------------------------------------
  1893. */
  1894. case MM_MOM_DONE:
  1895. /*
  1896. ** This message is sent to a window when the specified
  1897. ** system-exclusive buffer has been played and is being returned to
  1898. ** the application.
  1899. */
  1900. pMidiThunkHdr = CONTAINING_RECORD(dwParam1, MIDIHDR32, Midihdr);
  1901. WinAssert( pMidiThunkHdr );
  1902. COPY_MIDIOUTHDR16_FLAGS( pMidiThunkHdr->pMidihdr32, pMidiThunkHdr->Midihdr );
  1903. dwParam1 = (DWORD)pMidiThunkHdr->pMidihdr16;
  1904. case MM_MOM_OPEN:
  1905. /*
  1906. ** This message is sent to a window when a MIDI output device is opened.
  1907. ** We process this message the same way as MM_MOM_CLOSE (see below)
  1908. */
  1909. case MM_MOM_CLOSE:
  1910. /*
  1911. ** This message is sent to a window when a MIDI output device is
  1912. ** closed. The device handle is no longer valid once this message
  1913. ** has been sent.
  1914. */
  1915. Hand16 = pInstanceData->Hand16;
  1916. break;
  1917. /* ------------------------------------------------------------
  1918. ** WAVE INPUT MESSAGES
  1919. ** ------------------------------------------------------------
  1920. */
  1921. case MM_WIM_DATA:
  1922. /*
  1923. ** This message is sent to a window when waveform data is present
  1924. ** in the input buffer and the buffer is being returned to the
  1925. ** application. The message can be sent either when the buffer
  1926. ** is full, or after the waveInReset function is called.
  1927. */
  1928. pWavehdr32 = (PWAVEHDR32)( (PBYTE)dwParam1 - (sizeof(PWAVEHDR16) * 2));
  1929. WinAssert( pWavehdr32 );
  1930. COPY_WAVEINHDR16_FLAGS( pWavehdr32->pWavehdr32, pWavehdr32->Wavehdr );
  1931. dwParam1 = (DWORD)pWavehdr32->pWavehdr16;
  1932. case MM_WIM_OPEN:
  1933. /*
  1934. ** This message is sent to a window when a waveform input
  1935. ** device is opened.
  1936. **
  1937. ** We process this message the same way as MM_WIM_CLOSE (see below)
  1938. */
  1939. case MM_WIM_CLOSE:
  1940. /*
  1941. ** This message is sent to a window when a waveform input device is
  1942. ** closed. The device handle is no longer valid once the message has
  1943. ** been sent.
  1944. */
  1945. Hand16 = pInstanceData->Hand16;
  1946. break;
  1947. /* ------------------------------------------------------------
  1948. ** WAVE OUTPUT MESSAGES
  1949. ** ------------------------------------------------------------
  1950. */
  1951. case MM_WOM_DONE:
  1952. /*
  1953. ** This message is sent to a window when the specified output
  1954. ** buffer is being returned to the application. Buffers are returned
  1955. ** to the application when they have been played, or as the result of
  1956. ** a call to waveOutReset.
  1957. */
  1958. pWavehdr32 = (PWAVEHDR32)( (PBYTE)dwParam1 - (sizeof(PWAVEHDR16) * 2));
  1959. WinAssert( pWavehdr32 );
  1960. COPY_WAVEOUTHDR16_FLAGS( pWavehdr32->pWavehdr32, pWavehdr32->Wavehdr );
  1961. dwParam1 = (DWORD)pWavehdr32->pWavehdr16;
  1962. case MM_WOM_OPEN:
  1963. /*
  1964. ** This message is sent to a window when a waveform output device
  1965. ** is opened.
  1966. **
  1967. ** We process this message the same way as MM_WOM_CLOSE (see below)
  1968. */
  1969. case MM_WOM_CLOSE:
  1970. /*
  1971. ** This message is sent to a window when a waveform output device
  1972. ** is closed. The device handle is no longer valid once the
  1973. ** message has been sent.
  1974. */
  1975. Hand16 = pInstanceData->Hand16;
  1976. break;
  1977. #if DBG
  1978. default:
  1979. dprintf(( "Unknown message received in CallBack function " ));
  1980. return;
  1981. #endif
  1982. }
  1983. /*
  1984. ** Now make the CallBack, or PostMessage call depending
  1985. ** on the flags passed to original (wave|midi)(In|Out)Open call.
  1986. */
  1987. pInstanceData = (PINSTANCEDATA)dwInstance;
  1988. WinAssert( pInstanceData );
  1989. switch (pInstanceData->dwFlags & CALLBACK_TYPEMASK) {
  1990. case CALLBACK_WINDOW:
  1991. dprintf3(( "WINDOW callback identified" ));
  1992. PostMessage( HWND32( LOWORD(pInstanceData->dwCallback) ),
  1993. uMsg, Hand16, dwParam1 );
  1994. break;
  1995. case CALLBACK_TASK:
  1996. case CALLBACK_FUNCTION: {
  1997. DWORD dwFlags;
  1998. if ( (pInstanceData->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_TASK ) {
  1999. dprintf3(( "TASK callback identified" ));
  2000. dwFlags = DCB_TASK;
  2001. }
  2002. else {
  2003. dprintf3(( "FUNCTION callback identified" ));
  2004. dwFlags = DCB_FUNCTION;
  2005. }
  2006. WOW32DriverCallback( pInstanceData->dwCallback,
  2007. dwFlags,
  2008. Hand16,
  2009. LOWORD( uMsg ),
  2010. pInstanceData->dwCallbackInstance,
  2011. dwParam1,
  2012. dwParam2 );
  2013. }
  2014. break;
  2015. }
  2016. /*
  2017. ** Now, free up any storage that was allocated during the waveOutOpen
  2018. ** and waveInOpen. This should only be freed during the MM_WOM_CLOSE or
  2019. ** MM_WIM_CLOSE message.
  2020. */
  2021. switch (uMsg) {
  2022. case MM_MIM_CLOSE:
  2023. case MM_MOM_CLOSE:
  2024. case MM_WIM_CLOSE:
  2025. case MM_WOM_CLOSE:
  2026. dprintf2(( "W32CommonDeviceOpen: Freeing device open buffer at %X",
  2027. pInstanceData ));
  2028. dprintf2(( "Alloc Midi count = %d", AllocMidiCount ));
  2029. dprintf2(( "Alloc Wave count = %d", AllocWaveCount ));
  2030. winmmFree( pInstanceData );
  2031. break;
  2032. }
  2033. }
  2034. /******************************Public*Routine******************************\
  2035. * WOW32DriverCallback
  2036. *
  2037. * Callback stub, which invokes the "real" 16 bit callback.
  2038. * The parameters to this function must be in the format that the 16 bit
  2039. * code expects, i.e. all handles must be 16 bit handles, all addresses must
  2040. * be 16:16 ones.
  2041. *
  2042. *
  2043. * It is possible that this function will have been called with the
  2044. * DCB_WINDOW set in which case the 16 bit interrupt handler will call
  2045. * PostMessage. Howver, it is much more efficient if PostMessage is called
  2046. * from the 32 bit side.
  2047. *
  2048. * History:
  2049. * 22-11-93 - StephenE - Created
  2050. *
  2051. \**************************************************************************/
  2052. BOOL WOW32DriverCallback( DWORD dwCallback, DWORD dwFlags, WORD wID, WORD wMsg,
  2053. DWORD dwUser, DWORD dw1, DWORD dw2 )
  2054. {
  2055. PCALLBACK_ARGS pArgs;
  2056. WORD tempSendCount;
  2057. /*
  2058. ** If this is window callback post the message here and let WOW
  2059. ** take care of it.
  2060. */
  2061. if ( (dwFlags & DCB_TYPEMASK) == DCB_WINDOW ) {
  2062. return PostMessage( HWND32( LOWORD(dwCallback) ), wMsg, wID, dw1 );
  2063. }
  2064. /*
  2065. ** Now we put the parameters into the global callback data array
  2066. ** and increment the wSendCount field. Then we simulate
  2067. ** an interrupt to the 16 bit code.
  2068. **
  2069. ** If tempSendCount == wRecvCount then we have filled the callback buffer.
  2070. ** We throw this interrupt away, but still simulate an interrupt to the
  2071. ** 16 bit side in an attempt to get it procesing the interrupt still in
  2072. ** the buffer.
  2073. */
  2074. EnterCriticalSection( &mmCriticalSection );
  2075. tempSendCount = ((pCallBackData->wSendCount + 1) % CALLBACK_ARGS_SIZE);
  2076. if (tempSendCount != pCallBackData->wRecvCount) {
  2077. pArgs = &pCallBackData->args[ pCallBackData->wSendCount ];
  2078. pArgs->dwFlags = dwFlags;
  2079. pArgs->dwFunctionAddr = dwCallback;
  2080. pArgs->wHandle = wID;
  2081. pArgs->wMessage = wMsg;
  2082. pArgs->dwInstance = dwUser;
  2083. pArgs->dwParam1 = dw1;
  2084. pArgs->dwParam2 = dw2;
  2085. /*
  2086. ** Increment the send count. Use of the % operator above makes
  2087. ** sure that we wrap around to the begining of the array correctly.
  2088. */
  2089. pCallBackData->wSendCount = tempSendCount;
  2090. }
  2091. dprintf4(( "Send count = %d, Receive count = %d",
  2092. pCallBackData->wSendCount, pCallBackData->wRecvCount ));
  2093. LeaveCriticalSection( &mmCriticalSection );
  2094. /*
  2095. ** Dispatch the interrupt to the 16 bit code.
  2096. */
  2097. dprintf4(( "Dispatching HW interrupt callback" ));
  2098. if (!IsNEC_98) {
  2099. GenerateInterrupt( MULTIMEDIA_ICA, MULTIMEDIA_LINE, 1 );
  2100. } else {
  2101. GenerateInterrupt( MULTIMEDIA_ICA, MULTIMEDIA_LINE_98, 1 );
  2102. }
  2103. /*
  2104. ** Dummy return code, used to keep api consistent with Win31 and Win NT.
  2105. */
  2106. return TRUE;
  2107. }
  2108. /******************************Public*Routine******************************\
  2109. * aux32Message
  2110. *
  2111. * Thunk the aux apis.
  2112. *
  2113. * History:
  2114. * 22-11-93 - StephenE - Created
  2115. *
  2116. \**************************************************************************/
  2117. DWORD WINAPI
  2118. aux32Message(
  2119. UINT uDeviceID,
  2120. UINT uMessage,
  2121. DWORD dwInstance,
  2122. DWORD dwParam1,
  2123. DWORD dwParam2
  2124. )
  2125. {
  2126. #if DBG
  2127. static MSG_NAME name_map[] = {
  2128. AUXDM_GETNUMDEVS, "AUXDM_GETNUMDEVS",
  2129. AUXDM_GETDEVCAPS, "AUXDM_GETDEVCAPS",
  2130. AUXDM_GETVOLUME, "AUXDM_GETVOLUME",
  2131. AUXDM_SETVOLUME, "AUXDM_SETVOLUME",
  2132. };
  2133. int i;
  2134. int n;
  2135. #endif
  2136. static DWORD dwNumAuxDevs;
  2137. DWORD dwRet = MMSYSERR_NOTSUPPORTED;
  2138. DWORD dwTmp;
  2139. DWORD UNALIGNED *lpdwTmp;
  2140. AUXCAPSA aoCaps;
  2141. #if DBG
  2142. for( i = 0, n = sizeof(name_map) / sizeof(name_map[0]); i < n; i++ ) {
  2143. if ( name_map[i].uMsg == uMessage ) {
  2144. break;
  2145. }
  2146. }
  2147. if ( i != n ) {
  2148. trace_aux(( "aux32Message( 0x%X, %s, 0x%X, 0x%X, 0x%X)",
  2149. uDeviceID, name_map[i].lpstrName, dwInstance,
  2150. dwParam1, dwParam2 ));
  2151. }
  2152. else {
  2153. trace_aux(( "aux32Message( 0x%X, 0x%X, 0x%X, 0x%X, 0x%X)",
  2154. uDeviceID, uMessage, dwInstance,
  2155. dwParam1, dwParam2 ));
  2156. }
  2157. #endif
  2158. if ( LOWORD(uDeviceID) == 0xFFFF ) {
  2159. uDeviceID = (UINT)-1;
  2160. }
  2161. dprintf2(( "aux32Message (0x%x)", uMessage ));
  2162. switch ( uMessage ) {
  2163. case AUXDM_GETNUMDEVS:
  2164. dwRet = auxGetNumDevs();
  2165. break;
  2166. case AUXDM_GETDEVCAPS:
  2167. dwRet = auxGetDevCapsA( uDeviceID, &aoCaps, sizeof(aoCaps) );
  2168. if ( dwRet == MMSYSERR_NOERROR ) {
  2169. CopyAuxCaps( (LPAUXCAPS16)GETVDMPTR( dwParam1 ),
  2170. &aoCaps, dwParam2 );
  2171. }
  2172. break;
  2173. case AUXDM_GETVOLUME:
  2174. dwRet = auxGetVolume( uDeviceID, &dwTmp );
  2175. lpdwTmp = GETVDMPTR( dwParam1 );
  2176. *lpdwTmp = dwTmp;
  2177. break;
  2178. case AUXDM_SETVOLUME:
  2179. dwRet = auxSetVolume( uDeviceID, dwParam1 );
  2180. break;
  2181. default:
  2182. if ( uMessage >= DRV_BUFFER_LOW && uMessage <= DRV_BUFFER_HIGH ) {
  2183. lpdwTmp = GETVDMPTR( dwParam1 );
  2184. }
  2185. else {
  2186. lpdwTmp = (LPDWORD)dwParam1;
  2187. }
  2188. dwRet = auxOutMessage( uDeviceID, uMessage,
  2189. (DWORD)lpdwTmp, dwParam2 );
  2190. }
  2191. trace_aux(( "-> 0x%X", dwRet ));
  2192. return dwRet;
  2193. }
  2194. /*****************************Private*Routine******************************\
  2195. * CopyAuxCaps
  2196. *
  2197. * Copies 32 bit aux out caps info into the passed 16bit storage.
  2198. *
  2199. * History:
  2200. * 22-11-93 - StephenE - Created
  2201. *
  2202. \**************************************************************************/
  2203. void
  2204. CopyAuxCaps(
  2205. LPAUXCAPS16 lpCaps16,
  2206. LPAUXCAPSA lpCaps32,
  2207. DWORD dwSize
  2208. )
  2209. {
  2210. AUXCAPS16 Caps16;
  2211. Caps16.wMid = lpCaps32->wMid;
  2212. Caps16.wPid = lpCaps32->wPid;
  2213. Caps16.vDriverVersion = LOWORD( lpCaps32->vDriverVersion );
  2214. CopyMemory( Caps16.szPname, lpCaps32->szPname, MAXPNAMELEN );
  2215. Caps16.wTechnology = lpCaps32->wTechnology;
  2216. Caps16.dwSupport = lpCaps32->dwSupport;
  2217. CopyMemory( (LPVOID)lpCaps16, (LPVOID)&Caps16, (UINT)dwSize );
  2218. }
  2219. /******************************Public*Routine******************************\
  2220. * tid32Message
  2221. *
  2222. * Thunk the timer apis
  2223. *
  2224. * History:
  2225. * 22-11-93 - StephenE - Created
  2226. *
  2227. \**************************************************************************/
  2228. DWORD WINAPI
  2229. tid32Message(
  2230. UINT uDevId,
  2231. UINT uMessage,
  2232. DWORD dwInstance,
  2233. DWORD dwParam1,
  2234. DWORD dwParam2
  2235. )
  2236. {
  2237. #if DBG
  2238. static MSG_NAME name_map[] = {
  2239. TDD_SETTIMEREVENT, "timeSetEvent",
  2240. TDD_KILLTIMEREVENT, "timeKillEvent",
  2241. TDD_GETSYSTEMTIME, "timeGetTime",
  2242. TDD_GETDEVCAPS, "timeGetDevCaps",
  2243. TDD_BEGINMINPERIOD, "timeBeginPeriod",
  2244. TDD_ENDMINPERIOD, "timeEndPeriod",
  2245. };
  2246. int i;
  2247. int n;
  2248. #endif
  2249. DWORD dwRet = TIMERR_NOCANDO;
  2250. LPTIMECAPS16 lp16TimeCaps;
  2251. LPTIMEREVENT16 lp16TimeEvent;
  2252. #if DBG
  2253. for( i = 0, n = sizeof(name_map) / sizeof(name_map[0]); i < n; i++ ) {
  2254. if ( name_map[i].uMsg == uMessage ) {
  2255. break;
  2256. }
  2257. }
  2258. if ( i != n ) {
  2259. trace_time(( "tid32Message( %s, 0x%X, 0x%X)",
  2260. name_map[i].lpstrName, dwParam1, dwParam2 ));
  2261. }
  2262. else {
  2263. trace_time(( "tid32Message( 0x%X, 0x%X, 0x%X)",
  2264. uMessage, dwParam1, dwParam2 ));
  2265. }
  2266. #endif
  2267. switch (uMessage) {
  2268. case TDD_SETTIMEREVENT:
  2269. lp16TimeEvent = (LPTIMEREVENT16)GETVDMPTR( dwParam1);
  2270. trace_time(( "tid32Message: timeSetEvent(%#X, %#X, %#X, %#X)",
  2271. lp16TimeEvent->wDelay, lp16TimeEvent->wResolution,
  2272. lp16TimeEvent->lpFunction, lp16TimeEvent->wFlags ));
  2273. /*
  2274. ** The only difference for WOW is that WOW32DriverCallback is
  2275. ** called for the callback rather than DriverCallback. The
  2276. ** last parameter to timeSetEventInternal makes this happen.
  2277. */
  2278. dwRet = timeSetEventInternal( max( lp16TimeEvent->wDelay,
  2279. g_TimeCaps32.wPeriodMin ),
  2280. lp16TimeEvent->wResolution,
  2281. (LPTIMECALLBACK)lp16TimeEvent->lpFunction,
  2282. (DWORD)lp16TimeEvent->dwUser,
  2283. lp16TimeEvent->wFlags & TIME_PERIODIC,
  2284. TRUE);
  2285. dprintf4(( "timeSetEvent: 32 bit time ID %8X", dwRet ));
  2286. break;
  2287. case TDD_KILLTIMEREVENT:
  2288. dwRet = timeKillEvent( dwParam1 );
  2289. {
  2290. /*
  2291. ** Purge the callback queue of any messages were
  2292. ** generated with this timer id.
  2293. */
  2294. int nIndex;
  2295. EnterCriticalSection( &mmCriticalSection );
  2296. for ( nIndex = 0; nIndex < CALLBACK_ARGS_SIZE; nIndex++ ) {
  2297. if ( pCallBackData->args[ nIndex ].wHandle == LOWORD(dwParam1) &&
  2298. pCallBackData->args[ nIndex ].wMessage == 0 ) {
  2299. pCallBackData->args[ nIndex ].dwFunctionAddr = 0L;
  2300. }
  2301. }
  2302. LeaveCriticalSection( &mmCriticalSection );
  2303. }
  2304. break;
  2305. case TDD_GETSYSTEMTIME:
  2306. dwRet = timeGetTime();
  2307. break;
  2308. case TDD_GETDEVCAPS:
  2309. dwRet = 0;
  2310. lp16TimeCaps = GETVDMPTR( dwParam1 );
  2311. /*
  2312. ** Under NT, the minimum time period is about 15ms.
  2313. ** But Win3.1 on a 386 always returns 1ms. Encarta doesn't even
  2314. ** bother testing the CD-ROM's speed if the minimum period
  2315. ** is > 2ms, it just assumes it is too slow. So here we lie
  2316. ** to WOW apps and always tell them 1ms just like Win3.1.
  2317. ** John Vert (jvert) 17-Jun-1993
  2318. */
  2319. #ifdef TELL_THE_TRUTH
  2320. lp16TimeCaps->wPeriodMin = g_TimeCaps32.wPeriodMin;
  2321. #else
  2322. lp16TimeCaps->wPeriodMin = MIN_TIME_PERIOD_WE_RETURN;
  2323. #endif
  2324. /*
  2325. ** In windows 3.1 the wPeriodMax value is 0xFFFF which is the
  2326. ** max value you can store in a word. In windows NT the
  2327. ** wPeriodMax is 0xF4240 (1000 seconds).
  2328. **
  2329. ** If we just cast the 32 bit value down to a 16bit value we
  2330. ** end up with 0x4240 which very small compared to real 32 bit
  2331. ** value.
  2332. **
  2333. ** Therefore I will take the minimum of wPeriodMax and 0xFFFF
  2334. ** that way will should remain consistent with Win 3.1 if
  2335. ** wPeriodMax is greater than 0xFFFF.
  2336. */
  2337. lp16TimeCaps->wPeriodMax = (WORD)min(0xFFFF, g_TimeCaps32.wPeriodMax);
  2338. break;
  2339. case TDD_ENDMINPERIOD:
  2340. dwParam1 = max(dwParam1, g_TimeCaps32.wPeriodMin);
  2341. dwRet = timeEndPeriod( dwParam1 );
  2342. break;
  2343. case TDD_BEGINMINPERIOD:
  2344. dwParam1 = max(dwParam1, g_TimeCaps32.wPeriodMin);
  2345. dwRet = timeBeginPeriod( dwParam1 );
  2346. break;
  2347. }
  2348. trace_time(( "-> 0x%X", dwRet ));
  2349. return dwRet;
  2350. }
  2351. /******************************Public*Routine******************************\
  2352. * joy32Message
  2353. *
  2354. * Thunk the joystick apis
  2355. *
  2356. * History:
  2357. * 22-11-93 - StephenE - Created
  2358. *
  2359. \**************************************************************************/
  2360. DWORD WINAPI
  2361. joy32Message(
  2362. UINT uID,
  2363. UINT uMessage,
  2364. DWORD dwInstance,
  2365. DWORD dwParam1,
  2366. DWORD dwParam2
  2367. )
  2368. {
  2369. #if DBG
  2370. static MSG_NAME name_map[] = {
  2371. JDD_GETDEVCAPS, "joyGetDevCaps",
  2372. JDD_GETPOS, "joyGetPos",
  2373. // JDD_SETCALIBRATION, "joySetCalibration",
  2374. JDD_GETNUMDEVS, "joyGetNumDevs"
  2375. };
  2376. int i;
  2377. int n;
  2378. #endif
  2379. UINT wXbase;
  2380. UINT wXdelta;
  2381. UINT wYbase;
  2382. UINT wYdelta;
  2383. UINT wZbase;
  2384. UINT wZdelta;
  2385. WORD UNALIGNED *lpw;
  2386. DWORD dwRet = TIMERR_NOCANDO;
  2387. JOYCAPSA JoyCaps32;
  2388. JOYINFO JoyInfo32;
  2389. LPJOYCAPS16 lp16JoyCaps;
  2390. LPJOYINFO16 lp16JoyInfo;
  2391. #if DBG
  2392. for( i = 0, n = sizeof(name_map) / sizeof(name_map[0]); i < n; i++ ) {
  2393. if ( name_map[i].uMsg == uMessage ) {
  2394. break;
  2395. }
  2396. }
  2397. if ( i != n ) {
  2398. trace_joy(( "joy32Message( %s, 0x%X, 0x%X)",
  2399. name_map[i].lpstrName, dwParam1, dwParam2 ));
  2400. }
  2401. else {
  2402. trace_joy(( "joy32Message( 0x%X, 0x%X, 0x%X)",
  2403. uMessage, dwParam1, dwParam2 ));
  2404. }
  2405. #endif
  2406. switch (uMessage) {
  2407. case JDD_GETDEVCAPS:
  2408. dwRet = joyGetDevCapsA( uID, &JoyCaps32, sizeof(JoyCaps32) );
  2409. if ( dwRet == 0 ) {
  2410. JOYCAPS16 JoyCaps16;
  2411. lp16JoyCaps = GETVDMPTR( dwParam1 );
  2412. JoyCaps16.wMid = JoyCaps32.wMid;
  2413. JoyCaps16.wPid = JoyCaps32.wPid;
  2414. CopyMemory( JoyCaps16.szPname, JoyCaps32.szPname, MAXPNAMELEN );
  2415. JoyCaps16.wXmin = LOWORD( JoyCaps32.wXmin );
  2416. JoyCaps16.wXmax = LOWORD( JoyCaps32.wXmax );
  2417. JoyCaps16.wYmin = LOWORD( JoyCaps32.wYmin );
  2418. JoyCaps16.wYmax = LOWORD( JoyCaps32.wYmax );
  2419. JoyCaps16.wZmin = LOWORD( JoyCaps32.wZmin );
  2420. JoyCaps16.wZmax = LOWORD( JoyCaps32.wZmax );
  2421. JoyCaps16.wNumButtons = LOWORD( JoyCaps32.wNumButtons );
  2422. JoyCaps16.wPeriodMin = LOWORD( JoyCaps32.wPeriodMin );
  2423. JoyCaps16.wPeriodMax = LOWORD( JoyCaps32.wPeriodMax );
  2424. CopyMemory( (LPVOID)lp16JoyCaps, (LPVOID)&JoyCaps16, (UINT)dwParam2 );
  2425. }
  2426. break;
  2427. case JDD_GETNUMDEVS:
  2428. dwRet = joyGetNumDevs();
  2429. break;
  2430. case JDD_GETPOS:
  2431. dwRet = joyGetPos( uID, &JoyInfo32 );
  2432. if ( dwRet == MMSYSERR_NOERROR ) {
  2433. lp16JoyInfo = GETVDMPTR( dwParam1 );
  2434. lp16JoyInfo->wXpos = LOWORD( JoyInfo32.wXpos );
  2435. lp16JoyInfo->wYpos = LOWORD( JoyInfo32.wYpos );
  2436. lp16JoyInfo->wZpos = LOWORD( JoyInfo32.wZpos );
  2437. lp16JoyInfo->wButtons = LOWORD( JoyInfo32.wButtons );
  2438. }
  2439. break;
  2440. }
  2441. trace_joy(( "-> 0x%X", dwRet ));
  2442. return dwRet;
  2443. }
  2444. /******************************Public*Routine******************************\
  2445. * mxd32Message
  2446. *
  2447. * 32 bit thunk function. On NT all the 16 bit mixer apis get routed to
  2448. * here.
  2449. *
  2450. * History:
  2451. * 22-11-93 - StephenE - Created
  2452. *
  2453. \**************************************************************************/
  2454. DWORD CALLBACK
  2455. mxd32Message(
  2456. UINT uId,
  2457. UINT uMsg,
  2458. DWORD dwInstance,
  2459. DWORD dwParam1,
  2460. DWORD dwParam2
  2461. )
  2462. {
  2463. #if DBG
  2464. static MSG_NAME name_map[] = {
  2465. MXDM_INIT, "mixerInit",
  2466. MXDM_GETNUMDEVS, "mixerGetNumDevs",
  2467. MXDM_GETDEVCAPS, "mixerGetDevCaps",
  2468. MXDM_OPEN, "mixerOpen",
  2469. MXDM_GETLINEINFO, "mixerGetLineInfo",
  2470. MXDM_GETLINECONTROLS, "mixerGetLineControls",
  2471. MXDM_GETCONTROLDETAILS, "mixerGetControlsDetails",
  2472. MXDM_SETCONTROLDETAILS, "mixerSetControlsDetails"
  2473. };
  2474. int i;
  2475. int n;
  2476. #endif
  2477. DWORD dwRet = MMSYSERR_NOTSUPPORTED;
  2478. DWORD fdwOpen;
  2479. LPVOID lpOldAddress;
  2480. LPMIXERCONTROLDETAILS pmxcd;
  2481. LPMIXERLINECONTROLSA pmxlc;
  2482. MIXERCONTROLDETAILS mxcdA;
  2483. HMIXEROBJ hmixobj;
  2484. MIXERCAPSA caps32;
  2485. MIXERCAPS16 caps16;
  2486. LPMIXERCAPS16 lpcaps16;
  2487. MIXERLINEA line32;
  2488. LPMIXERLINE16 lpline16;
  2489. LPMIXEROPENDESC16 lpmxod16;
  2490. HMIXER UNALIGNED *phmx;
  2491. HMIXER hmx;
  2492. #if DBG
  2493. for( i = 0, n = sizeof(name_map) / sizeof(name_map[0]); i < n; i++ ) {
  2494. if ( name_map[i].uMsg == uMsg ) {
  2495. break;
  2496. }
  2497. }
  2498. if ( i != n ) {
  2499. trace_mix(( "mxd32Message( %s, 0x%X, 0x%X, 0x%X)",
  2500. name_map[i].lpstrName, dwInstance, dwParam1, dwParam2 ));
  2501. }
  2502. else {
  2503. trace_mix(( "mxd32Message( 0x%X, 0x%X, 0x%X, 0x%X)",
  2504. uMsg, dwInstance, dwParam1, dwParam2 ));
  2505. }
  2506. #endif
  2507. if ( dwInstance == 0L ) {
  2508. hmixobj = (HMIXEROBJ)uId;
  2509. }
  2510. else {
  2511. hmixobj = (HMIXEROBJ)dwInstance;
  2512. }
  2513. switch ( uMsg ) {
  2514. case MXDM_INIT:
  2515. dwRet = 0;
  2516. break;
  2517. case MXDM_GETNUMDEVS:
  2518. dwRet = mixerGetNumDevs();
  2519. break;
  2520. case MXDM_CLOSE:
  2521. dwRet = mixerClose( (HMIXER)dwInstance );
  2522. break;
  2523. case MXDM_GETDEVCAPS:
  2524. dwRet = mixerGetDevCapsA( uId, &caps32, sizeof(caps32) );
  2525. if ( dwRet == MMSYSERR_NOERROR ) {
  2526. lpcaps16 = GETVDMPTR( dwParam1 );
  2527. caps16.wMid = caps32.wMid;
  2528. caps16.wPid = caps32.wPid;
  2529. caps16.vDriverVersion = LOWORD( caps32.vDriverVersion );
  2530. CopyMemory( caps16.szPname, caps32.szPname, MAXPNAMELEN );
  2531. caps16.fdwSupport = caps32.fdwSupport;
  2532. caps16.cDestinations = caps32.cDestinations;
  2533. CopyMemory( (LPVOID)lpcaps16, (LPVOID)&caps16, (UINT)dwParam2 );
  2534. }
  2535. break;
  2536. case MXDM_OPEN:
  2537. lpmxod16 = GETVDMPTR( dwParam1 );
  2538. /*
  2539. ** fdwOpen has already mapped all device handles into device ID's on
  2540. ** the 16 bit side. Therefore mangle the flags to reflect this.
  2541. */
  2542. fdwOpen = (DWORD)lpmxod16->pReserved0;
  2543. if ( ( fdwOpen & CALLBACK_TYPEMASK ) == CALLBACK_WINDOW ) {
  2544. lpmxod16->dwCallback = (DWORD)HWND32(LOWORD(lpmxod16->dwCallback));
  2545. }
  2546. else if ( ( fdwOpen & CALLBACK_TYPEMASK ) == CALLBACK_TASK ) {
  2547. lpmxod16->dwCallback = GetCurrentThreadId();
  2548. }
  2549. dwRet = mixerOpen( &hmx, dwParam2, lpmxod16->dwCallback,
  2550. lpmxod16->dwInstance, fdwOpen );
  2551. if ( dwRet == MMSYSERR_NOERROR ) {
  2552. SetWOWHandle( hmx, lpmxod16->hmx );
  2553. phmx = GETVDMPTR( dwInstance );
  2554. *phmx = hmx;
  2555. }
  2556. break;
  2557. case MXDM_GETLINEINFO:
  2558. lpline16 = GETVDMPTR( dwParam1 );
  2559. GetLineInfo( lpline16, &line32 );
  2560. dwRet = mixerGetLineInfoA( hmixobj, &line32, dwParam2 );
  2561. if ( dwRet == MMSYSERR_NOERROR ) {
  2562. PutLineInfo( lpline16, &line32 );
  2563. }
  2564. break;
  2565. case MXDM_GETLINECONTROLS:
  2566. pmxlc = (LPMIXERLINECONTROLSA)GETVDMPTR( dwParam1 );
  2567. lpOldAddress = pmxlc->pamxctrl;
  2568. pmxlc->pamxctrl = GETVDMPTR( lpOldAddress );
  2569. dwRet = mixerGetLineControlsA(hmixobj, pmxlc, dwParam2);
  2570. pmxlc->pamxctrl = lpOldAddress;
  2571. break;
  2572. /*
  2573. ** CAREFUL !!!
  2574. **
  2575. ** The ONLY reason we don't copy the details themselves is because
  2576. ** somewhere down the line (usually in the IO subsystem) they're
  2577. ** copied anyway
  2578. */
  2579. case MXDM_GETCONTROLDETAILS:
  2580. pmxcd = (LPMIXERCONTROLDETAILS)GETVDMPTR( dwParam1 );
  2581. CopyMemory(&mxcdA, pmxcd, sizeof(mxcdA));
  2582. mxcdA.paDetails = GETVDMPTR( pmxcd->paDetails );
  2583. dwRet = mixerGetControlDetailsA(hmixobj, &mxcdA, dwParam2);
  2584. break;
  2585. case MXDM_SETCONTROLDETAILS:
  2586. pmxcd = (LPMIXERCONTROLDETAILS)GETVDMPTR( dwParam1 );
  2587. CopyMemory(&mxcdA, pmxcd, sizeof(mxcdA));
  2588. mxcdA.paDetails = GETVDMPTR( pmxcd->paDetails );
  2589. dwRet = mixerSetControlDetails( hmixobj, &mxcdA, dwParam2 );
  2590. break;
  2591. default:
  2592. dprintf3(( "Unkown mixer message 0x%X", uMsg ));
  2593. dwRet = mixerMessage( (HMIXER)hmixobj, uMsg, dwParam1, dwParam2 );
  2594. break;
  2595. }
  2596. dprintf3(( "-> 0x%X", dwRet ));
  2597. return dwRet;
  2598. }
  2599. /*****************************Private*Routine******************************\
  2600. * GetLineInfo
  2601. *
  2602. * Copies fields from the 16 bit line info structure to the 32 bit line info
  2603. * structure.
  2604. *
  2605. * History:
  2606. * 22-11-93 - StephenE - Created
  2607. *
  2608. \**************************************************************************/
  2609. void
  2610. GetLineInfo(
  2611. LPMIXERLINE16 lpline16,
  2612. LPMIXERLINEA lpline32
  2613. )
  2614. {
  2615. CopyMemory( lpline32, (LPVOID)lpline16, FIELD_OFFSET(MIXERLINEA, Target.vDriverVersion ) );
  2616. lpline32->Target.vDriverVersion = (DWORD)lpline16->Target.vDriverVersion;
  2617. CopyMemory( lpline32->Target.szPname, lpline16->Target.szPname, MAXPNAMELEN );
  2618. lpline32->cbStruct += sizeof(UINT) - sizeof(WORD);
  2619. }
  2620. /*****************************Private*Routine******************************\
  2621. * PutLineInfo
  2622. *
  2623. * Copies fields from the 32 bit line info structure to the 16 bit line info
  2624. * structure.
  2625. *
  2626. * History:
  2627. * 22-11-93 - StephenE - Created
  2628. *
  2629. \**************************************************************************/
  2630. void
  2631. PutLineInfo(
  2632. LPMIXERLINE16 lpline16,
  2633. LPMIXERLINEA lpline32
  2634. )
  2635. {
  2636. CopyMemory( (LPVOID)lpline16, lpline32, FIELD_OFFSET(MIXERLINEA, Target.vDriverVersion ) );
  2637. lpline16->Target.vDriverVersion = (WORD)lpline32->Target.vDriverVersion;
  2638. CopyMemory( lpline16->Target.szPname, lpline32->Target.szPname, MAXPNAMELEN );
  2639. lpline16->cbStruct -= sizeof(UINT) - sizeof(WORD);
  2640. }
  2641. /******************************Public*Routine******************************\
  2642. * WOW32ResolveMultiMediaHandle
  2643. *
  2644. *
  2645. *
  2646. * History:
  2647. * dd-mm-93 - StephenE - Created
  2648. *
  2649. \**************************************************************************/
  2650. BOOL APIENTRY
  2651. WOW32ResolveMultiMediaHandle(
  2652. UINT uHandleType,
  2653. UINT uMappingDirection,
  2654. WORD wHandle16_In,
  2655. LPWORD lpwHandle16_Out,
  2656. DWORD dwHandle32_In,
  2657. LPDWORD lpdwHandle32_Out
  2658. )
  2659. {
  2660. BOOL fReturn = FALSE;
  2661. DWORD dwHandle32;
  2662. WORD wHandle16;
  2663. HANDLE h;
  2664. /*
  2665. ** Protect ourself from being given a duff pointer.
  2666. */
  2667. try {
  2668. if ( uMappingDirection == WOW32_DIR_16IN_32OUT ) {
  2669. dwHandle32 = 0L;
  2670. if ( wHandle16_In != 0 ) {
  2671. switch ( uHandleType ) {
  2672. case WOW32_WAVEIN_HANDLE:
  2673. case WOW32_WAVEOUT_HANDLE:
  2674. case WOW32_MIDIOUT_HANDLE:
  2675. case WOW32_MIDIIN_HANDLE:
  2676. EnterCriticalSection(&HandleListCritSec);
  2677. h = GetHandleFirst();
  2678. while ( h ) {
  2679. if ( GetWOWHandle(h) == wHandle16_In ) {
  2680. dwHandle32 = (DWORD)h;
  2681. break;
  2682. }
  2683. h = GetHandleNext(h);
  2684. }
  2685. LeaveCriticalSection(&HandleListCritSec);
  2686. break;
  2687. }
  2688. *lpdwHandle32_Out = dwHandle32;
  2689. if ( dwHandle32 ) {
  2690. fReturn = TRUE;
  2691. }
  2692. }
  2693. }
  2694. else if ( uMappingDirection == WOW32_DIR_32IN_16OUT ) {
  2695. switch ( uHandleType ) {
  2696. case WOW32_WAVEIN_HANDLE:
  2697. case WOW32_WAVEOUT_HANDLE:
  2698. case WOW32_MIDIOUT_HANDLE:
  2699. case WOW32_MIDIIN_HANDLE:
  2700. wHandle16 = (WORD)GetWOWHandle(dwHandle32_In);
  2701. break;
  2702. }
  2703. *lpwHandle16_Out = wHandle16;
  2704. if ( wHandle16 ) {
  2705. fReturn = TRUE;
  2706. }
  2707. }
  2708. }
  2709. except( EXCEPTION_EXECUTE_HANDLER ) {
  2710. fReturn = FALSE;
  2711. }
  2712. return fReturn;
  2713. }
  2714. #endif // _WIN64