Windows NT 4.0 source code leak
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.

3212 lines
90 KiB

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