Leaked source code of windows server 2003
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.

1950 lines
54 KiB

  1. //==========================================================================;
  2. //
  3. // mixapi.c
  4. //
  5. // Copyright (C) 1992-1993 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // Description:
  8. //
  9. //
  10. // History:
  11. // 6/27/93 cjp [curtisp]
  12. //
  13. //==========================================================================;
  14. #define _WINDLL
  15. #include <windows.h>
  16. #include <windowsx.h>
  17. #include <string.h>
  18. #include <mmsystem.h>
  19. #include <mmddk.h>
  20. #include "mmreg.h"
  21. #include "mmsysi.h"
  22. //
  23. // fix a conflict will a bad define in MMREG.H that shipped with NT
  24. // the define is bad for some Media Vision things...
  25. //
  26. // why not just build MSMIXMGR with a NEW mmreg.h??
  27. //
  28. #ifdef MIXERR_BASE
  29. #undef MIXERR_BASE
  30. #endif // MIXERR_BASE
  31. #define _INC_MMDDK
  32. #include "msmixmgr.y"
  33. #define WODM_MAPPER_STATUS (0x2000)
  34. #define WAVEOUT_MAPPER_STATUS_DEVICE 0
  35. #define WIDM_MAPPER_STATUS (0x2000)
  36. #define WAVEIN_MAPPER_STATUS_DEVICE 0
  37. #include "idrv.h"
  38. #include "mixmgri.h"
  39. #include "debug.h"
  40. UINT FAR PASCAL
  41. mmCallProc32(
  42. DWORD uId,
  43. DWORD uMsg,
  44. DWORD dwInst,
  45. DWORD dwP1,
  46. DWORD dwP2,
  47. DRIVERMSGPROC fp,
  48. DWORD dwDirChange );
  49. /* -------------------------------------------------------------------------
  50. ** thunking global variables
  51. ** -------------------------------------------------------------------------
  52. */
  53. DWORD mix32Lib;
  54. BOOL FAR PASCAL
  55. InitMixerThunks(
  56. void
  57. );
  58. DWORD CALLBACK
  59. mxdMessage(
  60. UINT uId,
  61. UINT uMsg,
  62. DWORD dwInstance,
  63. DWORD dwParam1,
  64. DWORD dwParam2
  65. );
  66. #define CHECK_AND_INIT_THUNKS( _x_ ) \
  67. if ( (_x_) == 0L ) { \
  68. if ( InitMixerThunks() == FALSE ) { \
  69. return MMSYSERR_NODRIVER; \
  70. } \
  71. }
  72. UINT guTotalMixerDevs; // total mixer devices
  73. DRIVERMSGPROC mix32Message;
  74. typedef MMDRV MIXERDRV, *PMIXERDRV;
  75. //
  76. //
  77. //
  78. typedef struct tMIXERDEV {
  79. UINT uHandleType; // for parameter validation
  80. struct tMIXERDEV *pmxdevNext; /* How quaint, a linked list... */
  81. PMIXERDRV pmxdrv;
  82. UINT wDevice;
  83. DWORD dwDrvUser;
  84. UINT uDeviceID;
  85. DWORD fdwSupport; // from the driver's mixercaps
  86. DWORD cDestinations; // from the driver's mixercaps
  87. DWORD dwCallback; // client's callback and inst data
  88. DWORD dwInstance;
  89. DWORD fdwOpen; /* The open flags the caller used */
  90. } MIXERDEV, *PMIXERDEV;
  91. PMIXERDEV gpMixerDevHeader = NULL; /* A LL of open devices */
  92. //
  93. // mixer device driver list--add one to accomodate the MIXER_MAPPER. note
  94. // that even if we are not compiling with mapper support we need to add
  95. // one because other code relies on it (for other device mappers).
  96. //
  97. MIXERDRV mixerdrv[1];
  98. //==========================================================================;
  99. //
  100. // Mixer API's
  101. //
  102. //
  103. //==========================================================================;
  104. //--------------------------------------------------------------------------;
  105. //
  106. // DWORD IMixerMapId
  107. //
  108. // Description:
  109. // This function maps a logical id to a device driver table index and
  110. // physical id.
  111. //
  112. // Arguments:
  113. // PMIXERDRV pmxdrv: The array of mixer drivers.
  114. //
  115. // UINT uTotalNumDevs: The total number of mixer devices.
  116. //
  117. // UINT uId: The logical id to be mapped.
  118. //
  119. // Return (DWORD):
  120. // The return value contains the dev[] array element id in the high word
  121. // and the driver physical device number in the low word.
  122. //
  123. // Out of range values map to FFFF:FFFF
  124. //
  125. // History:
  126. // 03/17/93 cjp [curtisp]
  127. //
  128. //--------------------------------------------------------------------------;
  129. DWORD NEAR PASCAL IMixerMapId(
  130. PMIXERDRV pmxdrv,
  131. UINT uTotalNumDevs,
  132. UINT uId
  133. )
  134. {
  135. UINT u;
  136. #ifdef MIXER_MAPPER
  137. //
  138. // the mapper is always the last element of the MIXERDEV array.
  139. //
  140. if (uId == MIXER_MAPPER)
  141. return (MAKELONG(0, MAXMIXERDRIVERS));
  142. #endif
  143. if (uId >= uTotalNumDevs)
  144. return ((DWORD)-1);
  145. #ifdef DEBUG_RETAIL
  146. if (fIdReverse)
  147. uId = uTotalNumDevs - 1 - uId;
  148. #endif
  149. for (u = 0; u < MAXMIXERDRIVERS; u++)
  150. {
  151. if (pmxdrv[u].bNumDevs > (BYTE)uId)
  152. return (MAKELONG(uId, u));
  153. uId -= pmxdrv[u].bNumDevs;
  154. }
  155. return ((DWORD)-1);
  156. } // IMixerMapId()
  157. //--------------------------------------------------------------------------;
  158. //
  159. // DWORD IMixerMessageHandle
  160. //
  161. // Description:
  162. //
  163. //
  164. // Arguments:
  165. // HMIXER hmx:
  166. //
  167. // UINT uMsg:
  168. //
  169. // DWORD dwP1:
  170. //
  171. // DWORD dwP2:
  172. //
  173. // Return (DWORD):
  174. //
  175. // History:
  176. // 03/17/93 cjp [curtisp]
  177. //
  178. //--------------------------------------------------------------------------;
  179. DWORD NEAR PASCAL IMixerMessageHandle(
  180. HMIXER hmx,
  181. UINT uMsg,
  182. DWORD dwP1,
  183. DWORD dwP2
  184. )
  185. {
  186. PMIXERDEV pmxd;
  187. DWORD dwRc;
  188. pmxd = (PMIXERDEV)hmx;
  189. dwRc = ((*(pmxd->pmxdrv->drvMessage))
  190. (pmxd->wDevice, uMsg, pmxd->dwDrvUser, dwP1, dwP2));
  191. return dwRc;
  192. } // IMixerMessageHandle()
  193. //--------------------------------------------------------------------------;
  194. //
  195. // DWORD IMixerMessageId
  196. //
  197. // Description:
  198. //
  199. //
  200. // Arguments:
  201. // PMIXERDRV pmxdrv:
  202. //
  203. // UINT uTotalNumDevs:
  204. //
  205. // UINT uDeviceID:
  206. //
  207. // UINT uMsg:
  208. //
  209. // DWORD dwParam1:
  210. //
  211. // DWORD dwParam2:
  212. //
  213. // Return (DWORD):
  214. //
  215. // History:
  216. // 03/17/93 cjp [curtisp]
  217. //
  218. //--------------------------------------------------------------------------;
  219. DWORD NEAR PASCAL IMixerMessageId(
  220. PMIXERDRV pmxdrv,
  221. UINT uTotalNumDevs,
  222. UINT uDeviceID,
  223. UINT uMsg,
  224. DWORD dwParam1,
  225. DWORD dwParam2
  226. )
  227. {
  228. DWORD dwMap;
  229. DWORD dwRc;
  230. dwMap = IMixerMapId(pmxdrv, uTotalNumDevs, uDeviceID);
  231. if (dwMap == (DWORD)-1)
  232. return (MMSYSERR_BADDEVICEID);
  233. pmxdrv = (PMIXERDRV)&pmxdrv[HIWORD(dwMap)];
  234. if (!pmxdrv->drvMessage)
  235. return (MMSYSERR_NODRIVER);
  236. dwRc = ((*(pmxdrv->drvMessage))
  237. ((UINT)dwMap, uMsg, 0L, dwParam1, dwParam2));
  238. return dwRc;
  239. } // IMixerMessageId()
  240. /******************************Public*Routine******************************\
  241. * mixerGetNumDevs
  242. *
  243. *
  244. *
  245. * History:
  246. * dd-mm-93 - StephenE - Created
  247. *
  248. \**************************************************************************/
  249. UINT MIXAPI mixerGetNumDevs(
  250. void
  251. )
  252. {
  253. CHECK_AND_INIT_THUNKS(mix32Lib);
  254. return guTotalMixerDevs;
  255. }
  256. /******************************Public*Routine******************************\
  257. * mixerGetDevCaps
  258. *
  259. *
  260. *
  261. * History:
  262. * dd-mm-93 - StephenE - Created
  263. *
  264. \**************************************************************************/
  265. MMRESULT MIXAPI mixerGetDevCaps(
  266. UINT uMxId,
  267. LPMIXERCAPS pmxcaps,
  268. UINT cbmxcaps
  269. )
  270. {
  271. MMRESULT mmr;
  272. CHECK_AND_INIT_THUNKS(mix32Lib);
  273. if (0 == cbmxcaps)
  274. return (MMSYSERR_NOERROR);
  275. V_WPOINTER(pmxcaps, cbmxcaps, MMSYSERR_INVALPARAM);
  276. if (uMxId >= MAXMIXERDRIVERS)
  277. {
  278. V_HANDLE((HMIXER)uMxId, TYPE_MIXER, MMSYSERR_INVALHANDLE);
  279. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)uMxId,
  280. MXDM_GETDEVCAPS,
  281. (DWORD)pmxcaps,
  282. (DWORD)cbmxcaps);
  283. }
  284. else
  285. {
  286. if (uMxId >= guTotalMixerDevs)
  287. {
  288. DebugErr1(DBF_ERROR, "mixerGetDevCaps: mixer device id is out of range (%u).", uMxId);
  289. return (MMSYSERR_BADDEVICEID);
  290. }
  291. mmr = (MMRESULT)IMixerMessageId(mixerdrv,
  292. guTotalMixerDevs,
  293. uMxId,
  294. MXDM_GETDEVCAPS,
  295. (DWORD)pmxcaps,
  296. (DWORD)cbmxcaps);
  297. }
  298. return mmr;
  299. }
  300. /******************************Public*Routine******************************\
  301. * mixerGetID
  302. *
  303. *
  304. *
  305. * History:
  306. * dd-mm-93 - StephenE - Created
  307. *
  308. \**************************************************************************/
  309. MMRESULT MIXAPI mixerGetID(
  310. HMIXEROBJ hmxobj,
  311. UINT FAR *puMxId,
  312. DWORD fdwId
  313. )
  314. {
  315. CHECK_AND_INIT_THUNKS(mix32Lib);
  316. return IMixerGetID( hmxobj, puMxId, NULL, fdwId );
  317. }
  318. /*****************************Private*Routine******************************\
  319. * IMixerGetID
  320. *
  321. *
  322. *
  323. * History:
  324. * dd-mm-93 - StephenE - Created
  325. *
  326. \**************************************************************************/
  327. MMRESULT FNGLOBAL IMixerGetID(
  328. HMIXEROBJ hmxobj,
  329. UINT FAR *puMxId,
  330. LPMIXERLINE pmxl,
  331. DWORD fdwId
  332. )
  333. {
  334. MMRESULT mmr;
  335. MIXERLINE mxl;
  336. UINT u;
  337. V_DFLAGS(fdwId, MIXER_GETIDF_VALID, IMixerGetID, MMSYSERR_INVALFLAG);
  338. V_WPOINTER(puMxId, sizeof(UINT), MMSYSERR_INVALPARAM);
  339. //
  340. // set to '-1' which would be the mixer mapper (if there was one)
  341. // this way we will definitely fail any calls made on this id if
  342. // this function fails and the caller doesn't check his return value.
  343. //
  344. *puMxId = (UINT)-1;
  345. //
  346. //
  347. //
  348. switch (MIXER_OBJECTF_TYPEMASK & fdwId)
  349. {
  350. case MIXER_OBJECTF_MIXER:
  351. case MIXER_OBJECTF_HMIXER:
  352. if ((UINT)hmxobj > MAXMIXERDRIVERS)
  353. {
  354. V_HANDLE(hmxobj, TYPE_MIXER, MMSYSERR_INVALHANDLE);
  355. *puMxId = ((PMIXERDEV)hmxobj)->uDeviceID;
  356. return (MMSYSERR_NOERROR);
  357. }
  358. if ((UINT)hmxobj >= guTotalMixerDevs)
  359. {
  360. DebugErr1(DBF_ERROR, "mixerGetID: mixer device id is out of range (%u).", hmxobj);
  361. return (MMSYSERR_BADDEVICEID);
  362. }
  363. *puMxId = (UINT)hmxobj;
  364. return (MMSYSERR_NOERROR);
  365. case MIXER_OBJECTF_HWAVEOUT:
  366. {
  367. UINT uId;
  368. DWORD dwId;
  369. mmr = waveOutGetID((HWAVEOUT)hmxobj, &uId);
  370. if (MMSYSERR_NOERROR != mmr)
  371. {
  372. return (MMSYSERR_INVALHANDLE);
  373. }
  374. if (WAVE_MAPPER == uId)
  375. {
  376. mmr = (MMRESULT)waveOutMessage((HWAVEOUT)hmxobj,
  377. WODM_MAPPER_STATUS,
  378. WAVEOUT_MAPPER_STATUS_DEVICE,
  379. (DWORD)(LPVOID)&dwId);
  380. if (MMSYSERR_NOERROR == mmr)
  381. {
  382. uId = (UINT)dwId;
  383. }
  384. }
  385. hmxobj = (HMIXEROBJ)uId;
  386. }
  387. case MIXER_OBJECTF_WAVEOUT:
  388. {
  389. WAVEOUTCAPS woc;
  390. mmr = waveOutGetDevCaps((UINT)hmxobj, &woc, sizeof(woc));
  391. if (MMSYSERR_NOERROR != mmr)
  392. return (MMSYSERR_BADDEVICEID);
  393. woc.szPname[SIZEOF(woc.szPname) - 1] = '\0';
  394. mxl.Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
  395. mxl.Target.dwDeviceID = (UINT)hmxobj;
  396. mxl.Target.wMid = woc.wMid;
  397. mxl.Target.wPid = woc.wPid;
  398. mxl.Target.vDriverVersion = woc.vDriverVersion;
  399. lstrcpy(mxl.Target.szPname, woc.szPname);
  400. break;
  401. }
  402. case MIXER_OBJECTF_HWAVEIN:
  403. {
  404. UINT uId;
  405. DWORD dwId;
  406. mmr = waveInGetID((HWAVEIN)hmxobj, &uId);
  407. if (MMSYSERR_NOERROR != mmr)
  408. {
  409. return (MMSYSERR_INVALHANDLE);
  410. }
  411. if (WAVE_MAPPER == uId)
  412. {
  413. mmr = (MMRESULT)waveInMessage((HWAVEIN)hmxobj,
  414. WIDM_MAPPER_STATUS,
  415. WAVEIN_MAPPER_STATUS_DEVICE,
  416. (DWORD)(LPVOID)&dwId);
  417. if (MMSYSERR_NOERROR == mmr)
  418. {
  419. uId = (UINT)dwId;
  420. }
  421. }
  422. hmxobj = (HMIXEROBJ)uId;
  423. }
  424. case MIXER_OBJECTF_WAVEIN:
  425. {
  426. WAVEINCAPS wic;
  427. mmr = waveInGetDevCaps((UINT)hmxobj, &wic, sizeof(wic));
  428. if (MMSYSERR_NOERROR != mmr)
  429. return (MMSYSERR_BADDEVICEID);
  430. wic.szPname[SIZEOF(wic.szPname) - 1] = '\0';
  431. mxl.Target.dwType = MIXERLINE_TARGETTYPE_WAVEIN;
  432. mxl.Target.dwDeviceID = (UINT)hmxobj;
  433. mxl.Target.wMid = wic.wMid;
  434. mxl.Target.wPid = wic.wPid;
  435. mxl.Target.vDriverVersion = wic.vDriverVersion;
  436. lstrcpy(mxl.Target.szPname, wic.szPname);
  437. break;
  438. }
  439. case MIXER_OBJECTF_HMIDIOUT:
  440. mmr = midiOutGetID((HMIDIOUT)hmxobj, (UINT FAR *)&hmxobj);
  441. if (MMSYSERR_NOERROR != mmr)
  442. return (MMSYSERR_INVALHANDLE);
  443. case MIXER_OBJECTF_MIDIOUT:
  444. {
  445. MIDIOUTCAPS moc;
  446. mmr = midiOutGetDevCaps((UINT)hmxobj, &moc, sizeof(moc));
  447. if (MMSYSERR_NOERROR != mmr)
  448. return (MMSYSERR_BADDEVICEID);
  449. moc.szPname[SIZEOF(moc.szPname) - 1] = '\0';
  450. mxl.Target.dwType = MIXERLINE_TARGETTYPE_MIDIOUT;
  451. mxl.Target.dwDeviceID = (UINT)hmxobj;
  452. mxl.Target.wMid = moc.wMid;
  453. mxl.Target.wPid = moc.wPid;
  454. mxl.Target.vDriverVersion = moc.vDriverVersion;
  455. lstrcpy(mxl.Target.szPname, moc.szPname);
  456. break;
  457. }
  458. case MIXER_OBJECTF_HMIDIIN:
  459. mmr = midiInGetID((HMIDIIN)hmxobj, (UINT FAR *)&hmxobj);
  460. if (MMSYSERR_NOERROR != mmr)
  461. return (MMSYSERR_INVALHANDLE);
  462. case MIXER_OBJECTF_MIDIIN:
  463. {
  464. MIDIINCAPS mic;
  465. mmr = midiInGetDevCaps((UINT)hmxobj, &mic, sizeof(mic));
  466. if (MMSYSERR_NOERROR != mmr)
  467. return (MMSYSERR_BADDEVICEID);
  468. mic.szPname[SIZEOF(mic.szPname) - 1] = '\0';
  469. mxl.Target.dwType = MIXERLINE_TARGETTYPE_MIDIIN;
  470. mxl.Target.dwDeviceID = (UINT)hmxobj;
  471. mxl.Target.wMid = mic.wMid;
  472. mxl.Target.wPid = mic.wPid;
  473. mxl.Target.vDriverVersion = mic.vDriverVersion;
  474. lstrcpy(mxl.Target.szPname, mic.szPname);
  475. break;
  476. }
  477. case MIXER_OBJECTF_AUX:
  478. {
  479. AUXCAPS ac;
  480. mmr = auxGetDevCaps((UINT)hmxobj, &ac, sizeof(ac));
  481. if (MMSYSERR_NOERROR != mmr)
  482. return (MMSYSERR_BADDEVICEID);
  483. ac.szPname[SIZEOF(ac.szPname) - 1] = '\0';
  484. mxl.Target.dwType = MIXERLINE_TARGETTYPE_AUX;
  485. mxl.Target.dwDeviceID = (UINT)hmxobj;
  486. mxl.Target.wMid = ac.wMid;
  487. mxl.Target.wPid = ac.wPid;
  488. mxl.Target.vDriverVersion = ac.vDriverVersion;
  489. lstrcpy(mxl.Target.szPname, ac.szPname);
  490. break;
  491. }
  492. default:
  493. DebugErr1(DBF_ERROR, "mixerGetID: unknown mixer object flag (%.08lXh).",
  494. MIXER_OBJECTF_TYPEMASK & fdwId);
  495. return (MMSYSERR_INVALFLAG);
  496. }
  497. //
  498. //
  499. //
  500. //
  501. mxl.cbStruct = sizeof(mxl);
  502. mxl.dwDestination = (DWORD)-1L;
  503. mxl.dwSource = (DWORD)-1L;
  504. mxl.dwLineID = (DWORD)-1L;
  505. mxl.fdwLine = 0;
  506. mxl.dwUser = 0;
  507. mxl.dwComponentType = (DWORD)-1L;
  508. mxl.cChannels = 0;
  509. mxl.cConnections = 0;
  510. mxl.cControls = 0;
  511. mxl.szShortName[0] = '\0';
  512. mxl.szName[0] = '\0';
  513. for (u = 0; u < guTotalMixerDevs; u++)
  514. {
  515. mmr = (MMRESULT)IMixerMessageId(mixerdrv,
  516. guTotalMixerDevs,
  517. u,
  518. MXDM_GETLINEINFO,
  519. (DWORD)(LPVOID)&mxl,
  520. M_GLINFOF_TARGETTYPE);
  521. if (MMSYSERR_NOERROR == mmr)
  522. {
  523. *puMxId = u;
  524. if (NULL != pmxl)
  525. {
  526. DWORD cbStruct;
  527. cbStruct = pmxl->cbStruct;
  528. _fmemcpy(pmxl, &mxl, (UINT)cbStruct);
  529. pmxl->cbStruct = cbStruct;
  530. }
  531. return (mmr);
  532. }
  533. }
  534. return (MMSYSERR_NODRIVER);
  535. } // IMixerGetID()
  536. /******************************Public*Routine******************************\
  537. * mixerOpen
  538. *
  539. *
  540. *
  541. * History:
  542. * dd-mm-93 - StephenE - Created
  543. *
  544. \**************************************************************************/
  545. MMRESULT MIXAPI mixerOpen(
  546. LPHMIXER phmx,
  547. UINT uMxId,
  548. DWORD dwCallback,
  549. DWORD dwInstance,
  550. DWORD fdwOpen
  551. )
  552. {
  553. MMRESULT mmr;
  554. DWORD dwMap;
  555. PMIXERDRV pmxdrv;
  556. PMIXERDEV pmxdev;
  557. MIXEROPENDESC mxod;
  558. DWORD dwDrvUser;
  559. MIXERCAPS mxcaps;
  560. CHECK_AND_INIT_THUNKS(mix32Lib);
  561. //
  562. //
  563. //
  564. V_WPOINTER(phmx, sizeof(HMIXER), MMSYSERR_INVALPARAM);
  565. *phmx = NULL;
  566. //
  567. // Don't allow callback functions - they're not useful and they
  568. // cause headaches. Specifically for Windows NT the only way
  569. // to cause an asynchronous callback to 16-bit land from a 32-bit DLL
  570. // is to cause an interrupt but we don't want to require mixer stuff
  571. // to be locked down to allow for this.
  572. //
  573. if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
  574. {
  575. DebugErr(DBF_ERROR, "mixerOpen: CALLBACK_FUNCTION is not supported");
  576. return MMSYSERR_INVALFLAG;
  577. }
  578. V_DCALLBACK(dwCallback, HIWORD(fdwOpen & CALLBACK_TYPEMASK), MMSYSERR_INVALPARAM);
  579. V_DFLAGS(fdwOpen, MIXER_OPENF_VALID, mixerOpen, MMSYSERR_INVALFLAG);
  580. mmr = IMixerGetID((HMIXEROBJ)uMxId, &uMxId, NULL, (MIXER_OBJECTF_TYPEMASK & fdwOpen));
  581. if (MMSYSERR_NOERROR != mmr)
  582. return (mmr);
  583. //
  584. //
  585. //
  586. //
  587. dwMap = IMixerMapId(mixerdrv, guTotalMixerDevs, uMxId);
  588. if ((DWORD)-1 == dwMap)
  589. return (MMSYSERR_BADDEVICEID);
  590. pmxdrv = &mixerdrv[HIWORD(dwMap)];
  591. #ifdef MIXER_MAPPER
  592. //
  593. // Default Mixer Mapper:
  594. //
  595. // If a mixer mapper is installed as a separate DLL then all mixer
  596. // mapper messages are routed to it. If no mixer mapper is installed,
  597. // simply loop through the mixer devices looking for a match.
  598. //
  599. if ((MIXER_MAPPER == uMxId) && (NULL == pmxdrv->drvMessage))
  600. {
  601. for (uMxId = 0; uMxId < guTotalMixerDevs; uMxId++)
  602. {
  603. // try to open it
  604. if (MMSYSERR_NOERROR == mmr)
  605. break;
  606. }
  607. return (mmr);
  608. }
  609. #endif
  610. //
  611. // Get some memory for the dev structure
  612. //
  613. pmxdev = (PMIXERDEV)NewHandle(TYPE_MIXER, sizeof(MIXERDEV));
  614. if (NULL == pmxdev)
  615. {
  616. return (MMSYSERR_NOMEM);
  617. }
  618. //
  619. // initialize our open instance struct for the client
  620. //
  621. pmxdev->uHandleType = TYPE_MIXER;
  622. pmxdev->pmxdrv = pmxdrv;
  623. pmxdev->wDevice = LOWORD(dwMap);
  624. pmxdev->uDeviceID = uMxId;
  625. //
  626. // save the client's callback info
  627. //
  628. pmxdev->dwCallback = dwCallback;
  629. pmxdev->dwInstance = dwInstance;
  630. pmxdev->fdwOpen = fdwOpen;
  631. //
  632. // this should probably be done when the driver is booted.. can change
  633. // this later..
  634. //
  635. mmr = mixerGetDevCaps(uMxId, &mxcaps, sizeof(mxcaps));
  636. if (MMSYSERR_NOERROR != mmr)
  637. {
  638. DPF((0, "!mixerOpen() failing because mixerGetDevCaps() failed!"));
  639. FreeHandle((HMIXER)pmxdev);
  640. return (mmr);
  641. }
  642. //
  643. // cache some stuff for parameter validation
  644. //
  645. pmxdev->fdwSupport = mxcaps.fdwSupport;
  646. pmxdev->cDestinations = mxcaps.cDestinations;
  647. //
  648. // If we get here, no one has the device currently open. Let's
  649. // go open it, then.
  650. //
  651. //
  652. // Load up our local MIXEROPENDESC struct
  653. //
  654. mxod.hmx = (HMIXER)pmxdev;
  655. mxod.pReserved0 = (LPVOID)(fdwOpen & ~MIXER_OBJECTF_TYPEMASK);
  656. mxod.dwCallback = dwCallback;
  657. mxod.dwInstance = dwInstance;
  658. mmr = (MMRESULT)((*(pmxdrv->drvMessage))(LOWORD(dwMap),
  659. MXDM_OPEN,
  660. (DWORD)(LPDWORD)&dwDrvUser,
  661. (DWORD)(LPVOID)&mxod,
  662. (DWORD)uMxId ));
  663. if (MMSYSERR_NOERROR != mmr)
  664. {
  665. FreeHandle((HMIXER)pmxdev);
  666. }
  667. else
  668. {
  669. pmxdrv->bUsage++;
  670. pmxdev->dwDrvUser = dwDrvUser;
  671. *phmx = (HMIXER)pmxdev;
  672. //
  673. // Put this new device into the devlist chain.
  674. //
  675. MIXMGR_ENTER;
  676. pmxdev->pmxdevNext = gpMixerDevHeader;
  677. gpMixerDevHeader = pmxdev;
  678. MIXMGR_LEAVE;
  679. }
  680. return mmr;
  681. }
  682. /******************************Public*Routine******************************\
  683. * mixerClose
  684. *
  685. *
  686. *
  687. * History:
  688. * dd-mm-93 - StephenE - Created
  689. *
  690. \**************************************************************************/
  691. MMRESULT MIXAPI mixerClose(
  692. HMIXER hmx
  693. )
  694. {
  695. MMRESULT mmr;
  696. PMIXERDEV pmxdev;
  697. PMIXERDEV pmxdevT;
  698. CHECK_AND_INIT_THUNKS(mix32Lib);
  699. V_HANDLE(hmx, TYPE_MIXER, MMSYSERR_INVALHANDLE);
  700. //
  701. // if last open instance, then close it
  702. //
  703. mmr = (MMRESULT)IMixerMessageHandle(hmx, MXDM_CLOSE, 0L, 0L);
  704. if (MMSYSERR_NOERROR != mmr)
  705. return (mmr);
  706. //
  707. // remove the mixer handle from the linked list
  708. //
  709. MIXMGR_ENTER;
  710. pmxdev = (PMIXERDEV)hmx;
  711. if (pmxdev == gpMixerDevHeader)
  712. {
  713. gpMixerDevHeader = pmxdev->pmxdevNext;
  714. }
  715. else
  716. {
  717. for (pmxdevT = gpMixerDevHeader;
  718. pmxdevT && (pmxdevT->pmxdevNext != pmxdev);
  719. pmxdevT = pmxdevT->pmxdevNext)
  720. ;
  721. if (NULL == pmxdevT)
  722. {
  723. DebugErr1(DBF_ERROR, "mixerClose: invalid mixer handle (%.04Xh).", hmx);
  724. return (MMSYSERR_INVALHANDLE);
  725. }
  726. pmxdevT->pmxdevNext = pmxdev->pmxdevNext;
  727. }
  728. MIXMGR_LEAVE;
  729. //
  730. // dec usage count
  731. //
  732. pmxdev->pmxdrv->bUsage--;
  733. //
  734. // we're done with the memory block. now free the memory and return.
  735. //
  736. FreeHandle(hmx);
  737. return mmr;
  738. }
  739. /******************************Public*Routine******************************\
  740. * mixerMessage
  741. *
  742. *
  743. *
  744. * History:
  745. * dd-mm-93 - StephenE - Created
  746. *
  747. \**************************************************************************/
  748. DWORD MIXAPI mixerMessage(
  749. HMIXER hmx,
  750. UINT uMsg,
  751. DWORD dwParam1,
  752. DWORD dwParam2
  753. )
  754. {
  755. DWORD dw;
  756. CHECK_AND_INIT_THUNKS(mix32Lib);
  757. V_HANDLE(hmx, TYPE_MIXER, MMSYSERR_INVALHANDLE);
  758. //
  759. // don't allow any non-user range messages through this API
  760. //
  761. if (MXDM_USER > uMsg)
  762. {
  763. DebugErr1(DBF_ERROR, "mixerMessage: message must be in MXDM_USER range--what's this (%u)?", uMsg);
  764. return (MMSYSERR_INVALPARAM);
  765. }
  766. dw = IMixerMessageHandle(hmx, uMsg, dwParam1, dwParam2);
  767. return dw;
  768. }
  769. //--------------------------------------------------------------------------;
  770. //
  771. // BOOL IMixerIsValidComponentType
  772. //
  773. // Description:
  774. //
  775. //
  776. // Arguments:
  777. // DWORD dwComponentType:
  778. //
  779. // UINT uSrcDst:
  780. //
  781. // Return (BOOL):
  782. //
  783. // History:
  784. // 10/06/93 cjp [curtisp]
  785. //
  786. //--------------------------------------------------------------------------;
  787. BOOL FNLOCAL IMixerIsValidComponentType(
  788. DWORD dwComponentType,
  789. DWORD fdwLine
  790. )
  791. {
  792. if (0L == (MIXERLINE_LINEF_SOURCE & fdwLine))
  793. {
  794. if (dwComponentType > MLCT_DST_LAST)
  795. return (FALSE);
  796. return (TRUE);
  797. }
  798. else
  799. {
  800. if (dwComponentType < MLCT_SRC_FIRST)
  801. return (FALSE);
  802. if (dwComponentType > MLCT_SRC_LAST)
  803. return (FALSE);
  804. return (TRUE);
  805. }
  806. return (FALSE);
  807. } // IMixerIsValidComponentType()
  808. /******************************Public*Routine******************************\
  809. * mixerGetLineInfo
  810. *
  811. *
  812. *
  813. * History:
  814. * dd-mm-93 - StephenE - Created
  815. *
  816. \**************************************************************************/
  817. MMRESULT MIXAPI mixerGetLineInfo(
  818. HMIXEROBJ hmxobj,
  819. LPMIXERLINE pmxl,
  820. DWORD fdwInfo
  821. )
  822. {
  823. DWORD fdwMxObjType;
  824. MMRESULT mmr;
  825. PMIXERDEV pmxdev;
  826. UINT uMxId;
  827. BOOL fSourceLine;
  828. CHECK_AND_INIT_THUNKS(mix32Lib);
  829. V_DFLAGS(fdwInfo, M_GLINFOF_VALID, mixerGetLineInfo, MMSYSERR_INVALFLAG);
  830. V_WPOINTER(pmxl, sizeof(DWORD), MMSYSERR_INVALPARAM);
  831. if (sizeof(MIXERLINE) > (UINT)pmxl->cbStruct)
  832. {
  833. DebugErr1(DBF_ERROR, "mixerGetLineInfo: structure size too small or cbStruct not initialized (%lu).", pmxl->cbStruct);
  834. return (MMSYSERR_INVALPARAM);
  835. }
  836. V_WPOINTER(pmxl, pmxl->cbStruct, MMSYSERR_INVALPARAM);
  837. //
  838. //
  839. //
  840. fSourceLine = FALSE;
  841. switch (fdwInfo & M_GLINFOF_QUERYMASK)
  842. {
  843. case M_GLINFOF_DESTINATION:
  844. pmxl->dwSource = (DWORD)-1L;
  845. pmxl->dwLineID = (DWORD)-1L;
  846. pmxl->dwComponentType = (DWORD)-1L;
  847. break;
  848. case M_GLINFOF_SOURCE:
  849. fSourceLine = TRUE;
  850. pmxl->dwLineID = (DWORD)-1L;
  851. pmxl->dwComponentType = (DWORD)-1L;
  852. break;
  853. case M_GLINFOF_LINEID:
  854. pmxl->dwSource = (DWORD)-1L;
  855. pmxl->dwDestination = (DWORD)-1L;
  856. pmxl->dwComponentType = (DWORD)-1L;
  857. break;
  858. case M_GLINFOF_COMPONENTTYPE:
  859. pmxl->dwSource = (DWORD)-1L;
  860. pmxl->dwDestination = (DWORD)-1L;
  861. pmxl->dwLineID = (DWORD)-1L;
  862. if (!IMixerIsValidComponentType(pmxl->dwComponentType, 0) &&
  863. !IMixerIsValidComponentType(pmxl->dwComponentType, MIXERLINE_LINEF_SOURCE))
  864. {
  865. DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid dwComponentType (%lu).", pmxl->dwComponentType);
  866. return (MMSYSERR_INVALPARAM);
  867. }
  868. break;
  869. case M_GLINFOF_TARGETTYPE:
  870. pmxl->dwSource = (DWORD)-1L;
  871. pmxl->dwDestination = (DWORD)-1L;
  872. pmxl->dwLineID = (DWORD)-1L;
  873. pmxl->dwComponentType = (DWORD)-1L;
  874. if ((DWORD)MIXERLINE_TARGETTYPE_AUX < pmxl->Target.dwType)
  875. {
  876. DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid Target.dwType (%lu).", pmxl->Target.dwType);
  877. return (MMSYSERR_INVALPARAM);
  878. }
  879. break;
  880. default:
  881. DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid query flag (%.08lXh).",
  882. fdwInfo & M_GLINFOF_QUERYMASK);
  883. return (MMSYSERR_INVALFLAG);
  884. }
  885. //
  886. //
  887. //
  888. fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwInfo);
  889. mmr = IMixerGetID(hmxobj, &uMxId, pmxl, fdwMxObjType);
  890. if (MMSYSERR_NOERROR != mmr)
  891. {
  892. DPF((0, "!IMixerGetLineInfo: IMixerGetID() failed!"));
  893. return (mmr);
  894. }
  895. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  896. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  897. {
  898. //
  899. // if a mixer device id was passed, then null hmx so we use the
  900. // correct message sender below
  901. //
  902. if ((UINT)hmxobj == uMxId)
  903. hmxobj = NULL;
  904. }
  905. else
  906. {
  907. return (MMSYSERR_NOERROR);
  908. }
  909. //
  910. // clear all fields before calling driver
  911. //
  912. if (NULL != hmxobj)
  913. {
  914. //
  915. //
  916. //
  917. pmxdev = (PMIXERDEV)hmxobj;
  918. #if 0
  919. if (pmxdev->cDestinations <= pmxl->dwDestination)
  920. {
  921. DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid destination index (%lu).", pmxl->dwDestination);
  922. return (MMSYSERR_INVALPARAM);
  923. }
  924. #endif
  925. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
  926. MXDM_GETLINEINFO,
  927. (DWORD)(LPVOID)pmxl,
  928. fdwInfo);
  929. }
  930. else
  931. {
  932. #pragma message("----IMixerGetLineInfo: dwDestination not validated for ID's!!")
  933. mmr = (MMRESULT)IMixerMessageId(mixerdrv,
  934. guTotalMixerDevs,
  935. uMxId,
  936. MXDM_GETLINEINFO,
  937. (DWORD)(LPVOID)pmxl,
  938. fdwInfo);
  939. }
  940. if (MMSYSERR_NOERROR != mmr)
  941. return (mmr);
  942. #pragma message("----IMixerGetLineInfo: should validate mixer driver didn't hose us!")
  943. //
  944. // validate the driver's returned stuff...
  945. //
  946. //
  947. if (sizeof(MIXERLINE) != (UINT)pmxl->cbStruct)
  948. {
  949. DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver returned invalid cbStruct (%lu).", pmxl->cbStruct);
  950. pmxl->cbStruct = sizeof(MIXERLINE);
  951. }
  952. if ((DWORD)-1L == pmxl->dwDestination)
  953. {
  954. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwDestination member.");
  955. }
  956. if (fSourceLine)
  957. {
  958. if (0L == (MIXERLINE_LINEF_SOURCE & pmxl->fdwLine))
  959. {
  960. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to set MIXERLINE_LINEF_SOURCE.");
  961. pmxl->fdwLine |= MIXERLINE_LINEF_SOURCE;
  962. }
  963. if ((DWORD)-1L == pmxl->dwSource)
  964. {
  965. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwSource member.");
  966. }
  967. }
  968. if ((DWORD)-1L == pmxl->dwLineID)
  969. {
  970. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwLineID member.");
  971. }
  972. if (pmxl->fdwLine & ~0x80008001L)
  973. {
  974. DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver set reserved line flags (%.08lXh)!", pmxl->fdwLine);
  975. pmxl->fdwLine &= 0x80008001L;
  976. }
  977. if (!IMixerIsValidComponentType(pmxl->dwComponentType, pmxl->fdwLine))
  978. {
  979. DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver returned invalid dwComponentType (%.08lXh).", pmxl->dwComponentType);
  980. pmxl->dwComponentType = MIXERLINE_TARGETTYPE_UNDEFINED;
  981. }
  982. if (0L == pmxl->cChannels)
  983. {
  984. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver returned zero channels?!?");
  985. pmxl->cChannels = 1;
  986. }
  987. if (fSourceLine)
  988. {
  989. if (0L != pmxl->cConnections)
  990. {
  991. DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver returned non-zero connections on source?!?");
  992. pmxl->cConnections = 0;
  993. }
  994. }
  995. pmxl->szShortName[SIZEOF(pmxl->szShortName) - 1] = '\0';
  996. pmxl->szName[SIZEOF(pmxl->szName) - 1] = '\0';
  997. //
  998. // Does this really need to be done if TARGETTYPE was requested?
  999. //
  1000. //
  1001. //
  1002. //
  1003. if ((DWORD)MIXERLINE_TARGETTYPE_UNDEFINED != pmxl->Target.dwType)
  1004. {
  1005. UINT u;
  1006. pmxl->Target.dwDeviceID = (DWORD)-1L;
  1007. //
  1008. // we have a wMid, wPid and szPname (supposedly) of type dwType
  1009. // so let's go find it...
  1010. //
  1011. switch (pmxl->Target.dwType)
  1012. {
  1013. case MIXERLINE_TARGETTYPE_WAVEOUT:
  1014. u = waveOutGetNumDevs();
  1015. while (u--)
  1016. {
  1017. WAVEOUTCAPS woc;
  1018. mmr = waveOutGetDevCaps(u, &woc, sizeof(woc));
  1019. if (MMSYSERR_NOERROR != mmr)
  1020. continue;
  1021. woc.szPname[SIZEOF(woc.szPname) - 1] = '\0';
  1022. if (woc.wMid != pmxl->Target.wMid)
  1023. continue;
  1024. if (woc.wPid != pmxl->Target.wPid)
  1025. continue;
  1026. if (woc.vDriverVersion != pmxl->Target.vDriverVersion)
  1027. continue;
  1028. if (lstrcmp(woc.szPname, pmxl->Target.szPname))
  1029. continue;
  1030. pmxl->Target.dwDeviceID = u;
  1031. break;
  1032. }
  1033. break;
  1034. case MIXERLINE_TARGETTYPE_WAVEIN:
  1035. u = waveInGetNumDevs();
  1036. while (u--)
  1037. {
  1038. WAVEINCAPS wic;
  1039. mmr = waveInGetDevCaps(u, &wic, sizeof(wic));
  1040. if (MMSYSERR_NOERROR != mmr)
  1041. continue;
  1042. wic.szPname[SIZEOF(wic.szPname) - 1] = '\0';
  1043. if (wic.wMid != pmxl->Target.wMid)
  1044. continue;
  1045. if (wic.wPid != pmxl->Target.wPid)
  1046. continue;
  1047. if (wic.vDriverVersion != pmxl->Target.vDriverVersion)
  1048. continue;
  1049. if (lstrcmp(wic.szPname, pmxl->Target.szPname))
  1050. continue;
  1051. pmxl->Target.dwDeviceID = u;
  1052. break;
  1053. }
  1054. break;
  1055. case MIXERLINE_TARGETTYPE_MIDIOUT:
  1056. u = midiOutGetNumDevs();
  1057. while (u--)
  1058. {
  1059. MIDIOUTCAPS moc;
  1060. mmr = midiOutGetDevCaps(u, &moc, sizeof(moc));
  1061. if (MMSYSERR_NOERROR != mmr)
  1062. continue;
  1063. moc.szPname[SIZEOF(moc.szPname) - 1] = '\0';
  1064. if (moc.wMid != pmxl->Target.wMid)
  1065. continue;
  1066. if (moc.wPid != pmxl->Target.wPid)
  1067. continue;
  1068. if (moc.vDriverVersion != pmxl->Target.vDriverVersion)
  1069. continue;
  1070. if (lstrcmp(moc.szPname, pmxl->Target.szPname))
  1071. continue;
  1072. pmxl->Target.dwDeviceID = u;
  1073. break;
  1074. }
  1075. break;
  1076. case MIXERLINE_TARGETTYPE_MIDIIN:
  1077. u = midiInGetNumDevs();
  1078. while (u--)
  1079. {
  1080. MIDIINCAPS mic;
  1081. mmr = midiInGetDevCaps(u, &mic, sizeof(mic));
  1082. if (MMSYSERR_NOERROR != mmr)
  1083. continue;
  1084. mic.szPname[SIZEOF(mic.szPname) - 1] = '\0';
  1085. if (mic.wMid != pmxl->Target.wMid)
  1086. continue;
  1087. if (mic.wPid != pmxl->Target.wPid)
  1088. continue;
  1089. if (mic.vDriverVersion != pmxl->Target.vDriverVersion)
  1090. continue;
  1091. if (lstrcmp(mic.szPname, pmxl->Target.szPname))
  1092. continue;
  1093. pmxl->Target.dwDeviceID = u;
  1094. break;
  1095. }
  1096. break;
  1097. case MIXERLINE_TARGETTYPE_AUX:
  1098. u = auxGetNumDevs();
  1099. while (u--)
  1100. {
  1101. AUXCAPS ac;
  1102. mmr = auxGetDevCaps(u, &ac, sizeof(ac));
  1103. if (MMSYSERR_NOERROR != mmr)
  1104. continue;
  1105. ac.szPname[SIZEOF(ac.szPname) - 1] = '\0';
  1106. if (ac.wMid != pmxl->Target.wMid)
  1107. continue;
  1108. if (ac.wPid != pmxl->Target.wPid)
  1109. continue;
  1110. if (ac.vDriverVersion != pmxl->Target.vDriverVersion)
  1111. continue;
  1112. if (lstrcmp(ac.szPname, pmxl->Target.szPname))
  1113. continue;
  1114. pmxl->Target.dwDeviceID = u;
  1115. break;
  1116. }
  1117. break;
  1118. default:
  1119. pmxl->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
  1120. break;
  1121. }
  1122. }
  1123. return mmr;
  1124. }
  1125. /******************************Public*Routine******************************\
  1126. * mixerGetLineControls
  1127. *
  1128. *
  1129. *
  1130. * History:
  1131. * dd-mm-93 - StephenE - Created
  1132. *
  1133. \**************************************************************************/
  1134. MMRESULT MIXAPI mixerGetLineControls(
  1135. HMIXEROBJ hmxobj,
  1136. LPMIXERLINECONTROLS pmxlc,
  1137. DWORD fdwControls
  1138. )
  1139. {
  1140. DWORD fdwMxObjType;
  1141. UINT uMxId;
  1142. MMRESULT mmr;
  1143. CHECK_AND_INIT_THUNKS(mix32Lib);
  1144. V_DFLAGS(fdwControls, M_GLCONTROLSF_VALID, mixerGetLineControls, MMSYSERR_INVALFLAG);
  1145. V_WPOINTER(pmxlc, sizeof(DWORD), MMSYSERR_INVALPARAM);
  1146. //
  1147. // the structure header for MIXERLINECONTROLS must be at least the
  1148. // minimum size
  1149. //
  1150. if (sizeof(MIXERLINECONTROLS) > (UINT)pmxlc->cbStruct)
  1151. {
  1152. DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbStruct not initialized (%lu).", pmxlc->cbStruct);
  1153. return (MMSYSERR_INVALPARAM);
  1154. }
  1155. V_WPOINTER(pmxlc, pmxlc->cbStruct, MMSYSERR_INVALPARAM);
  1156. if (sizeof(MIXERCONTROL) > (UINT)pmxlc->cbmxctrl)
  1157. {
  1158. DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbmxctrl not initialized (%lu).", pmxlc->cbmxctrl);
  1159. return (MMSYSERR_INVALPARAM);
  1160. }
  1161. //
  1162. //
  1163. //
  1164. switch (M_GLCONTROLSF_QUERYMASK & fdwControls)
  1165. {
  1166. case M_GLCONTROLSF_ALL:
  1167. if (0L == pmxlc->cControls)
  1168. {
  1169. DebugErr(DBF_ERROR, "mixerGetLineControls: cControls cannot be zero.");
  1170. return (MMSYSERR_INVALPARAM);
  1171. }
  1172. pmxlc->dwControlID = (DWORD)-1L;
  1173. break;
  1174. case M_GLCONTROLSF_ONEBYID:
  1175. pmxlc->dwLineID = (DWORD)-1L;
  1176. // -- fall through --
  1177. case M_GLCONTROLSF_ONEBYTYPE:
  1178. pmxlc->cControls = (DWORD)1;
  1179. break;
  1180. default:
  1181. DebugErr1(DBF_ERROR, "mixerGetLineControls: invalid query flags (%.08lXh).",
  1182. M_GLCONTROLSF_QUERYMASK & fdwControls);
  1183. return (MMSYSERR_INVALFLAG);
  1184. }
  1185. V_WPOINTER(pmxlc->pamxctrl, pmxlc->cControls * pmxlc->cbmxctrl, MMSYSERR_INVALPARAM);
  1186. //
  1187. //
  1188. //
  1189. fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwControls);
  1190. mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
  1191. if (MMSYSERR_NOERROR != mmr)
  1192. return (mmr);
  1193. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  1194. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  1195. {
  1196. //
  1197. // if a mixer device id was passed, then null hmx so we use the
  1198. // correct message sender below
  1199. //
  1200. if ((UINT)hmxobj == uMxId)
  1201. hmxobj = NULL;
  1202. }
  1203. else
  1204. {
  1205. hmxobj = NULL;
  1206. fdwControls &= ~MIXER_OBJECTF_TYPEMASK;
  1207. fdwControls |= MIXER_OBJECTF_MIXER;
  1208. }
  1209. //
  1210. //
  1211. //
  1212. //
  1213. if (NULL != hmxobj)
  1214. {
  1215. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
  1216. MXDM_GETLINECONTROLS,
  1217. (DWORD)pmxlc,
  1218. fdwControls);
  1219. }
  1220. else
  1221. {
  1222. mmr = (MMRESULT)IMixerMessageId(mixerdrv,
  1223. guTotalMixerDevs,
  1224. uMxId,
  1225. MXDM_GETLINECONTROLS,
  1226. (DWORD)pmxlc,
  1227. fdwControls);
  1228. }
  1229. return mmr;
  1230. }
  1231. /******************************Public*Routine******************************\
  1232. * mixerGetControlDetails
  1233. *
  1234. *
  1235. *
  1236. * History:
  1237. * dd-mm-93 - StephenE - Created
  1238. *
  1239. \**************************************************************************/
  1240. MMRESULT MIXAPI mixerGetControlDetails(
  1241. HMIXEROBJ hmxobj,
  1242. LPMIXERCONTROLDETAILS pmxcd,
  1243. DWORD fdwDetails
  1244. )
  1245. {
  1246. DWORD fdwMxObjType;
  1247. MMRESULT mmr;
  1248. UINT uMxId;
  1249. UINT cDetails;
  1250. CHECK_AND_INIT_THUNKS(mix32Lib);
  1251. V_DFLAGS(fdwDetails, M_GCDSF_VALID, mixerGetControlDetails, MMSYSERR_INVALFLAG);
  1252. V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM);
  1253. //
  1254. // the structure header for MIXERCONTROLDETAILS must be at least the
  1255. // minimum size
  1256. //
  1257. if (sizeof(MIXERCONTROLDETAILS) > (UINT)pmxcd->cbStruct)
  1258. {
  1259. DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct);
  1260. return (MMSYSERR_INVALPARAM);
  1261. }
  1262. V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM);
  1263. switch (M_GCDSF_QUERYMASK & fdwDetails)
  1264. {
  1265. case M_GCDSF_VALUE:
  1266. //
  1267. // if both cChannels and cMultipleItems are zero, it is a
  1268. // custom control
  1269. //
  1270. if ((0L == pmxcd->cChannels) && (0L == pmxcd->cMultipleItems))
  1271. {
  1272. if (0L == pmxcd->cbDetails)
  1273. {
  1274. DebugErr(DBF_ERROR, "mixerGetControlDetails: cbDetails cannot be zero.");
  1275. return (MMSYSERR_INVALPARAM);
  1276. }
  1277. V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  1278. }
  1279. else
  1280. {
  1281. if (0L == pmxcd->cChannels)
  1282. {
  1283. DebugErr(DBF_ERROR, "mixerGetControlDetails: cChannels for _VALUE cannot be zero.");
  1284. return (MMSYSERR_INVALPARAM);
  1285. }
  1286. if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_SIGNED))
  1287. {
  1288. DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
  1289. return (MMSYSERR_INVALPARAM);
  1290. }
  1291. //
  1292. //
  1293. //
  1294. cDetails = (UINT)pmxcd->cChannels;
  1295. if (0L != pmxcd->cMultipleItems)
  1296. {
  1297. cDetails *= (UINT)pmxcd->cMultipleItems;
  1298. }
  1299. V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  1300. }
  1301. break;
  1302. case M_GCDSF_LISTTEXT:
  1303. if (0L == pmxcd->cChannels)
  1304. {
  1305. DebugErr(DBF_ERROR, "mixerGetControlDetails: cChannels for _LISTTEXT cannot be zero.");
  1306. return (MMSYSERR_INVALPARAM);
  1307. }
  1308. if (2L > pmxcd->cMultipleItems)
  1309. {
  1310. DebugErr(DBF_ERROR, "mixerGetControlDetails: cMultipleItems for _LISTTEXT must be 2 or greater.");
  1311. return (MMSYSERR_INVALPARAM);
  1312. }
  1313. if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_LISTTEXT))
  1314. {
  1315. DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
  1316. return (MMSYSERR_INVALPARAM);
  1317. }
  1318. cDetails = (UINT)pmxcd->cChannels * (UINT)pmxcd->cMultipleItems;
  1319. V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  1320. break;
  1321. default:
  1322. DebugErr1(DBF_ERROR, "mixerGetControlDetails: invalid query flags (%.08lXh).",
  1323. M_GCDSF_QUERYMASK & fdwDetails);
  1324. return (MMSYSERR_INVALFLAG);
  1325. }
  1326. //
  1327. //
  1328. //
  1329. fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwDetails);
  1330. mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
  1331. if (MMSYSERR_NOERROR != mmr)
  1332. return (mmr);
  1333. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  1334. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  1335. {
  1336. //
  1337. // if a mixer device id was passed, then null hmx so we use the
  1338. // correct message sender below
  1339. //
  1340. if ((UINT)hmxobj == uMxId)
  1341. hmxobj = NULL;
  1342. }
  1343. else
  1344. {
  1345. hmxobj = NULL;
  1346. fdwDetails &= ~MIXER_OBJECTF_TYPEMASK;
  1347. fdwDetails |= MIXER_OBJECTF_MIXER;
  1348. }
  1349. //
  1350. //
  1351. //
  1352. //
  1353. if (NULL != hmxobj)
  1354. {
  1355. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
  1356. MXDM_GETCONTROLDETAILS,
  1357. (DWORD)pmxcd,
  1358. fdwDetails);
  1359. }
  1360. else
  1361. {
  1362. mmr = (MMRESULT)IMixerMessageId(mixerdrv,
  1363. guTotalMixerDevs,
  1364. uMxId,
  1365. MXDM_GETCONTROLDETAILS,
  1366. (DWORD)pmxcd,
  1367. fdwDetails);
  1368. }
  1369. return mmr;
  1370. }
  1371. /******************************Public*Routine******************************\
  1372. * mixerSetControlDetails
  1373. *
  1374. *
  1375. *
  1376. * History:
  1377. * dd-mm-93 - StephenE - Created
  1378. *
  1379. \**************************************************************************/
  1380. MMRESULT MIXAPI mixerSetControlDetails(
  1381. HMIXEROBJ hmxobj,
  1382. LPMIXERCONTROLDETAILS pmxcd,
  1383. DWORD fdwDetails
  1384. )
  1385. {
  1386. DWORD fdwMxObjType;
  1387. MMRESULT mmr;
  1388. UINT uMxId;
  1389. UINT cDetails;
  1390. CHECK_AND_INIT_THUNKS(mix32Lib);
  1391. V_DFLAGS(fdwDetails, M_SCDF_VALID, mixerSetControlDetails, MMSYSERR_INVALFLAG);
  1392. V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM);
  1393. //
  1394. // the structure header for MIXERCONTROLDETAILS must be at least the
  1395. // minimum size
  1396. //
  1397. if (sizeof(MIXERCONTROLDETAILS) > (UINT)pmxcd->cbStruct)
  1398. {
  1399. DebugErr1(DBF_ERROR, "mixerSetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct);
  1400. return (MMSYSERR_INVALPARAM);
  1401. }
  1402. V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM);
  1403. switch (M_SCDF_QUERYMASK & fdwDetails)
  1404. {
  1405. case M_SCDF_VALUE:
  1406. //
  1407. // cChannels is zero for custom controls
  1408. //
  1409. if (0L == pmxcd->cChannels)
  1410. {
  1411. if (0L == pmxcd->cbDetails)
  1412. {
  1413. DebugErr(DBF_ERROR, "mixerSetControlDetails: cbDetails cannot be zero.");
  1414. return (MMSYSERR_INVALPARAM);
  1415. }
  1416. V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  1417. //
  1418. //
  1419. //
  1420. if (0L != pmxcd->cMultipleItems)
  1421. {
  1422. DebugErr(DBF_ERROR, "mixerSetControlDetails: cMultipleItems must be zero for custom controls.");
  1423. return (MMSYSERR_INVALPARAM);
  1424. }
  1425. }
  1426. else
  1427. {
  1428. if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_SIGNED))
  1429. {
  1430. DebugErr1(DBF_ERROR, "mixerSetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails);
  1431. return (MMSYSERR_INVALPARAM);
  1432. }
  1433. cDetails = (UINT)pmxcd->cChannels;
  1434. //
  1435. //
  1436. //
  1437. if (0L != pmxcd->cMultipleItems)
  1438. {
  1439. cDetails *= (UINT)(pmxcd->cMultipleItems);
  1440. }
  1441. V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  1442. }
  1443. break;
  1444. case M_SCDF_CUSTOM:
  1445. if (0L == pmxcd->cbDetails)
  1446. {
  1447. DebugErr(DBF_ERROR, "mixerSetControlDetails: cbDetails cannot be zero for custom controls.");
  1448. return (MMSYSERR_INVALPARAM);
  1449. }
  1450. if (0L != pmxcd->cChannels)
  1451. {
  1452. DebugErr(DBF_ERROR, "mixerSetControlDetails: cChannels must be zero for custom controls.");
  1453. return (MMSYSERR_INVALPARAM);
  1454. }
  1455. V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM);
  1456. //
  1457. //
  1458. //
  1459. if ((NULL != pmxcd->hwndOwner) && !IsWindow(pmxcd->hwndOwner))
  1460. {
  1461. DebugErr1(DBF_ERROR, "mixerSetControlDetails: hwndOwner must be a valid window handle (%.04Xh).", pmxcd->hwndOwner);
  1462. return (MMSYSERR_INVALHANDLE);
  1463. }
  1464. break;
  1465. default:
  1466. DebugErr1(DBF_ERROR, "mixerSetControlDetails: invalid query flags (%.08lXh).",
  1467. M_SCDF_QUERYMASK & fdwDetails);
  1468. return (MMSYSERR_INVALFLAG);
  1469. }
  1470. //
  1471. //
  1472. //
  1473. fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwDetails);
  1474. mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType);
  1475. if (MMSYSERR_NOERROR != mmr)
  1476. return (mmr);
  1477. if ((MIXER_OBJECTF_MIXER == fdwMxObjType) ||
  1478. (MIXER_OBJECTF_HMIXER == fdwMxObjType))
  1479. {
  1480. //
  1481. // if a mixer device id was passed, then null hmx so we use the
  1482. // correct message sender below
  1483. //
  1484. if ((UINT)hmxobj == uMxId)
  1485. hmxobj = NULL;
  1486. }
  1487. else
  1488. {
  1489. fdwDetails &= ~MIXER_OBJECTF_TYPEMASK;
  1490. fdwDetails |= MIXER_OBJECTF_MIXER;
  1491. hmxobj = NULL;
  1492. }
  1493. //
  1494. //
  1495. //
  1496. //
  1497. if (NULL != hmxobj)
  1498. {
  1499. mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj,
  1500. MXDM_SETCONTROLDETAILS,
  1501. (DWORD)pmxcd,
  1502. fdwDetails);
  1503. }
  1504. else
  1505. {
  1506. mmr = (MMRESULT)IMixerMessageId(mixerdrv,
  1507. guTotalMixerDevs,
  1508. uMxId,
  1509. MXDM_SETCONTROLDETAILS,
  1510. (DWORD)pmxcd,
  1511. fdwDetails);
  1512. }
  1513. return mmr;
  1514. }
  1515. /*****************************Private*Routine******************************\
  1516. * InitMixerThunks
  1517. *
  1518. * Initializes the thunking system.
  1519. *
  1520. * History:
  1521. * dd-mm-93 - StephenE - Created
  1522. *
  1523. \**************************************************************************/
  1524. BOOL FAR PASCAL
  1525. InitMixerThunks(
  1526. void
  1527. )
  1528. {
  1529. /*
  1530. ** For WOW we have a fake device driver (that actually lives inside
  1531. ** this library). When an applications makes an api call to this
  1532. ** library we check to see is the WOW thunks are loaded. If they are
  1533. ** not loaded "InitWOWThunks" is called. This function loads the 32
  1534. ** bit library and determines the total number of mixer devices
  1535. ** present in the system. It then sets mixerdrv[0].bUsage
  1536. ** and guTotalMixerDevs to this value. This appears to the 16 bit code
  1537. ** that we have one 16 bit device driver that supports all the
  1538. ** 32 bit devices !!. The entry point to this fake driver is
  1539. ** mxdMessage, which just passes the message through to the 32 bit
  1540. ** side.
  1541. */
  1542. mixerdrv[0].hDriver = NULL;
  1543. mixerdrv[0].bNumDevs = (BYTE)0;
  1544. mixerdrv[0].bUsage = 0;
  1545. mixerdrv[0].drvMessage = mxdMessage;
  1546. guTotalMixerDevs = 0;
  1547. /*
  1548. ** First try winmm.dll
  1549. */
  1550. mix32Lib = LoadLibraryEx32W( "winmm.dll", NULL, 0L );
  1551. if ( mix32Lib ) {
  1552. mix32Message = (DRIVERMSGPROC)GetProcAddress32W( mix32Lib,
  1553. "mxd32Message" );
  1554. if ( mix32Message ) {
  1555. mxdMessage( 0, MXDM_INIT, 0L, 0L, 0L );
  1556. guTotalMixerDevs = (UINT)mxdMessage( 0, MXDM_GETNUMDEVS,
  1557. 0L, 0L, 0L );
  1558. mixerdrv[0].bNumDevs = (BYTE)guTotalMixerDevs;
  1559. return TRUE;
  1560. }
  1561. }
  1562. /*
  1563. ** Then try msmix32.dll
  1564. */
  1565. mix32Lib = LoadLibraryEx32W( "msmix32.dll", NULL, 0L );
  1566. if ( mix32Lib ) {
  1567. mix32Message = (DRIVERMSGPROC)GetProcAddress32W( mix32Lib,
  1568. "mxd32Message" );
  1569. if ( mix32Message ) {
  1570. mxdMessage( 0, MXDM_INIT, 0L, 0L, 0L );
  1571. guTotalMixerDevs = (UINT)mxdMessage( 0, MXDM_GETNUMDEVS,
  1572. 0L, 0L, 0L );
  1573. mixerdrv[0].bNumDevs = (BYTE)guTotalMixerDevs;
  1574. return TRUE;
  1575. }
  1576. }
  1577. /*
  1578. ** Give up !!
  1579. */
  1580. return FALSE;
  1581. }
  1582. /*****************************Private*Routine******************************\
  1583. * mxdMessage
  1584. *
  1585. * Entry point for the fake WOW device driver.
  1586. *
  1587. * History:
  1588. * dd-mm-93 - StephenE - Created
  1589. *
  1590. \**************************************************************************/
  1591. DWORD CALLBACK
  1592. mxdMessage(
  1593. UINT uId,
  1594. UINT uMsg,
  1595. DWORD dwInstance,
  1596. DWORD dwParam1,
  1597. DWORD dwParam2
  1598. )
  1599. {
  1600. return mmCallProc32( (DWORD)uId, (DWORD)uMsg, dwInstance,
  1601. dwParam1, dwParam2, mix32Message, 0L );
  1602. }