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

422 lines
14 KiB

  1. /****************************************************************************
  2. auxout.c
  3. Level 1 kitchen sink DLL aux support module
  4. Copyright (c) 1990-2001 Microsoft Corporation
  5. Changes for NT :
  6. Change parameters for MapAuxId to return the driver index rather
  7. than a pointer
  8. change list of include files
  9. widen function parameters and return codes
  10. Change WINAPI to APIENTRY
  11. History
  12. 10/1/92 Updated for NT by Robin Speed (RobinSp)
  13. ****************************************************************************/
  14. #include "winmmi.h"
  15. /****************************************************************************
  16. * @doc INTERNAL AUX
  17. *
  18. * @func MMRESULT | auxReferenceDriverById | This function maps a logical id
  19. * to a device driver and physical id.
  20. *
  21. * @parm IN UINT | id | The logical id to be mapped.
  22. *
  23. * @parm OUT PAUXRV* OPTIONAL | ppauxdrv | Pointer to AUXDRV structure
  24. * describing the driver supporting the id.
  25. *
  26. * @parm OUT UINT* OPTIONAL | pport | The driver-relative device number. If
  27. * the caller supplies this buffer then it must also supply ppauxdrv.
  28. *
  29. * @rdesc The return value is zero if successful, MMSYSERR_BADDEVICEID if
  30. * the id is out of range.
  31. *
  32. * @comm If the caller specifies ppwavedrv then this function increments
  33. * the zuxdrv's usage before returning. The caller must ensure
  34. * the usage is eventually decremented.
  35. *
  36. ****************************************************************************/
  37. MMRESULT auxReferenceDriverById(IN UINT id, OUT PAUXDRV *ppauxdrv OPTIONAL, OUT UINT *pport OPTIONAL)
  38. {
  39. PAUXDRV pdrv;
  40. MMRESULT mmr;
  41. // Should not be called asking for port but not auxdrv
  42. WinAssert(!(pport && !ppauxdrv));
  43. EnterNumDevs("auxReferenceDriverById");
  44. if (AUX_MAPPER == id)
  45. {
  46. id = 0;
  47. for (pdrv = auxdrvZ.Next; pdrv != &auxdrvZ; pdrv = pdrv->Next)
  48. {
  49. if (pdrv->fdwDriver & MMDRV_MAPPER) break;
  50. }
  51. } else {
  52. for (pdrv = auxdrvZ.Next; pdrv != &auxdrvZ; pdrv = pdrv->Next)
  53. {
  54. if (pdrv->fdwDriver & MMDRV_MAPPER) continue;
  55. if (pdrv->NumDevs > id) break;
  56. id -= pdrv->NumDevs;
  57. }
  58. }
  59. if (pdrv != &auxdrvZ)
  60. {
  61. if (ppauxdrv)
  62. {
  63. mregIncUsagePtr(pdrv);
  64. *ppauxdrv = pdrv;
  65. if (pport) *pport = id;
  66. }
  67. mmr = MMSYSERR_NOERROR;
  68. } else {
  69. mmr = MMSYSERR_BADDEVICEID;
  70. }
  71. LeaveNumDevs("auxReferenceDriverById");
  72. return mmr;
  73. }
  74. PCWSTR auxReferenceDevInterfaceById(UINT id)
  75. {
  76. PAUXDRV pdrv;
  77. if (!auxReferenceDriverById(id, &pdrv, NULL))
  78. {
  79. PCWSTR DevInterface;
  80. DevInterface = pdrv->cookie;
  81. if (DevInterface) wdmDevInterfaceInc(DevInterface);
  82. mregDecUsagePtr(pdrv);
  83. return DevInterface;
  84. }
  85. return NULL;
  86. }
  87. /*****************************************************************************
  88. * @doc EXTERNAL AUX
  89. *
  90. * @func MMRESULT | auxOutMessage | This function sends a messages to an auxiliary
  91. * output device. It also performs error checking on the device ID passed.
  92. *
  93. * @parm UINT | uDeviceID | Identifies the auxiliary output device to be
  94. * queried. Specify a valid device ID (see the following comments
  95. * section), or use the following constant:
  96. * @flag AUX_MAPPER | Auxiliary audio mapper. The function will
  97. * return an error if no auxiliary audio mapper is installed.
  98. *
  99. * @parm UINT | uMessage | The message to send.
  100. *
  101. * @parm DWORD | dw1Param1 | Parameter 1.
  102. *
  103. * @parm DWORD | dw2Param2 | Parameter 2.
  104. *
  105. * @rdesc Returns the value returned from the driver.
  106. *
  107. ****************************************************************************/
  108. MMRESULT APIENTRY auxOutMessage(
  109. UINT uDeviceID,
  110. UINT uMessage,
  111. DWORD_PTR dwParam1,
  112. DWORD_PTR dwParam2)
  113. {
  114. PAUXDRV auxdrvr;
  115. UINT port;
  116. DWORD mmr;
  117. ClientUpdatePnpInfo();
  118. mmr = auxReferenceDriverById(uDeviceID, &auxdrvr, &port);
  119. if (mmr) return mmr;
  120. if (!auxdrvr->drvMessage)
  121. {
  122. mmr = MMSYSERR_NODRIVER;
  123. }
  124. else if (!mregHandleInternalMessages (auxdrvr, TYPE_AUX, port, uMessage, dwParam1, dwParam2, &mmr))
  125. {
  126. mmr = (MMRESULT)auxdrvr->drvMessage(port, uMessage, 0L, dwParam1, dwParam2);
  127. }
  128. mregDecUsagePtr(auxdrvr);
  129. return mmr;
  130. }
  131. /*****************************************************************************
  132. * @doc EXTERNAL AUX
  133. *
  134. * @api UINT | auxGetNumDevs | This function retrieves the number of auxiliary
  135. * output devices present in the system.
  136. *
  137. * @rdesc Returns the number of auxiliary output devices present in the system.
  138. *
  139. * @xref auxGetDevCaps
  140. ****************************************************************************/
  141. UINT APIENTRY auxGetNumDevs(void)
  142. {
  143. UINT cDevs;
  144. ClientUpdatePnpInfo();
  145. EnterNumDevs("auxGetNumDevs");
  146. cDevs = (UINT)wTotalAuxDevs;
  147. LeaveNumDevs("auxGetNumDevs");
  148. return cDevs;
  149. }
  150. /*****************************************************************************
  151. * @doc EXTERNAL AUX
  152. *
  153. * @api MMRESULT | auxGetDevCaps | This function queries a specified
  154. * auxiliary output device to determine its capabilities.
  155. *
  156. * @parm UINT | uDeviceID | Identifies the auxiliary output device to be
  157. * queried. Specify a valid device ID (see the following comments
  158. * section), or use the following constant:
  159. * @flag AUX_MAPPER | Auxiliary audio mapper. The function will
  160. * return an error if no auxiliary audio mapper is installed.
  161. *
  162. * @parm LPAUXCAPS | lpCaps | Specifies a far pointer to an AUXCAPS
  163. * structure. This structure is filled with information about the
  164. * capabilities of the device.
  165. *
  166. * @parm UINT | wSize | Specifies the size of the AUXCAPS structure.
  167. *
  168. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  169. * an error number. Possible error returns are:
  170. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  171. * @flag MMSYSERR_NODRIVER | The driver failed to install.
  172. *
  173. * @comm The device ID specified by <p uDeviceID> varies from zero
  174. * to one less than the number of devices present. AUX_MAPPER may
  175. * also be used. Use <f auxGetNumDevs> to determine the number of
  176. * auxiliary devices present in the system.
  177. *
  178. * @xref auxGetNumDevs
  179. ****************************************************************************/
  180. //
  181. // ISSUE-2001/01/08-FrankYe Silly casts to UINT in these functions,
  182. // should validate first
  183. //
  184. MMRESULT APIENTRY auxGetDevCapsW(UINT_PTR uDeviceID, LPAUXCAPSW lpCaps, UINT wSize)
  185. {
  186. DWORD_PTR dwParam1, dwParam2;
  187. MDEVICECAPSEX mdCaps;
  188. PCWSTR DevInterface;
  189. MMRESULT mmr;
  190. if (!wSize)
  191. return MMSYSERR_NOERROR;
  192. V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM);
  193. ClientUpdatePnpInfo();
  194. DevInterface = auxReferenceDevInterfaceById((UINT)uDeviceID);
  195. dwParam2 = (DWORD_PTR)DevInterface;
  196. if (0 == dwParam2)
  197. {
  198. dwParam1 = (DWORD_PTR)lpCaps;
  199. dwParam2 = (DWORD)wSize;
  200. }
  201. else
  202. {
  203. mdCaps.cbSize = (DWORD)wSize;
  204. mdCaps.pCaps = lpCaps;
  205. dwParam1 = (DWORD_PTR)&mdCaps;
  206. }
  207. mmr = (MMRESULT)auxOutMessage((UINT)uDeviceID, AUXDM_GETDEVCAPS, dwParam1, dwParam2);
  208. if (DevInterface) wdmDevInterfaceDec(DevInterface);
  209. return mmr;
  210. }
  211. MMRESULT APIENTRY auxGetDevCapsA(UINT_PTR uDeviceID, LPAUXCAPSA lpCaps, UINT wSize)
  212. {
  213. AUXCAPS2W wDevCaps2;
  214. AUXCAPS2A aDevCaps2;
  215. DWORD_PTR dwParam1, dwParam2;
  216. MDEVICECAPSEX mdCaps;
  217. PCWSTR DevInterface;
  218. MMRESULT mmRes;
  219. if (!wSize)
  220. return MMSYSERR_NOERROR;
  221. V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM);
  222. ClientUpdatePnpInfo();
  223. DevInterface = auxReferenceDevInterfaceById((UINT)uDeviceID);
  224. dwParam2 = (DWORD_PTR)DevInterface;
  225. memset(&wDevCaps2, 0, sizeof(wDevCaps2));
  226. if (0 == dwParam2)
  227. {
  228. dwParam1 = (DWORD_PTR)&wDevCaps2;
  229. dwParam2 = (DWORD)sizeof(wDevCaps2);
  230. }
  231. else
  232. {
  233. mdCaps.cbSize = (DWORD)sizeof(wDevCaps2);
  234. mdCaps.pCaps = &wDevCaps2;
  235. dwParam1 = (DWORD_PTR)&mdCaps;
  236. }
  237. mmRes = (MMRESULT)auxOutMessage( (UINT)uDeviceID, AUXDM_GETDEVCAPS,
  238. dwParam1,
  239. dwParam2);
  240. if (DevInterface) wdmDevInterfaceDec(DevInterface);
  241. //
  242. // Don't copy data back if bad return code
  243. //
  244. if (mmRes != MMSYSERR_NOERROR) {
  245. return mmRes;
  246. }
  247. aDevCaps2.wMid = wDevCaps2.wMid;
  248. aDevCaps2.wPid = wDevCaps2.wPid;
  249. aDevCaps2.vDriverVersion = wDevCaps2.vDriverVersion;
  250. aDevCaps2.wTechnology = wDevCaps2.wTechnology;
  251. aDevCaps2.dwSupport = wDevCaps2.dwSupport;
  252. aDevCaps2.ManufacturerGuid = wDevCaps2.ManufacturerGuid;
  253. aDevCaps2.ProductGuid = wDevCaps2.ProductGuid;
  254. aDevCaps2.NameGuid = wDevCaps2.NameGuid;
  255. // copy and convert lpwText to lpText here.
  256. Iwcstombs( aDevCaps2.szPname, wDevCaps2.szPname, MAXPNAMELEN);
  257. CopyMemory((PVOID)lpCaps, (PVOID)&aDevCaps2, min(sizeof(aDevCaps2), wSize));
  258. return mmRes;
  259. }
  260. /*****************************************************************************
  261. * @doc EXTERNAL AUX
  262. *
  263. * @api MMRESULT | auxGetVolume | This function returns the current volume
  264. * setting of an auxiliary output device.
  265. *
  266. * @parm UINT | uDeviceID | Identifies the auxiliary output device to be
  267. * queried.
  268. *
  269. * @parm LPDWORD | lpdwVolume | Specifies a far pointer to a location
  270. * to be filled with the current volume setting. The low-order word of
  271. * this location contains the left channel volume setting, and the high-order
  272. * word contains the right channel setting. A value of 0xFFFF represents
  273. * full volume, and a value of 0x0000 is silence.
  274. *
  275. * If a device does not support both left and right volume
  276. * control, the low-order word of the specified location contains
  277. * the volume level.
  278. *
  279. * The full 16-bit setting(s)
  280. * set with <f auxSetVolume> are returned, regardless of whether
  281. * the device supports the full 16 bits of volume level control.
  282. *
  283. * @comm Not all devices support volume control.
  284. * To determine whether the device supports volume control, use the
  285. * AUXCAPS_VOLUME flag to test the <e AUXCAPS.dwSupport> field of the
  286. * <t AUXCAPS> structure (filled by <f auxGetDevCaps>).
  287. *
  288. * To determine whether the device supports volume control on both the
  289. * left and right channels, use the AUXCAPS_LRVOLUME flag to test the
  290. * <e AUXCAPS.dwSupport> field of the <t AUXCAPS> structure (filled
  291. * by <f auxGetDevCaps>).
  292. *
  293. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  294. * an error number. Possible error returns are:
  295. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  296. * @flag MMSYSERR_NODRIVER | The driver failed to install.
  297. *
  298. * @xref auxSetVolume
  299. ****************************************************************************/
  300. MMRESULT APIENTRY auxGetVolume(UINT uDeviceID, LPDWORD lpdwVolume)
  301. {
  302. PCWSTR DevInterface;
  303. MMRESULT mmr;
  304. V_WPOINTER(lpdwVolume, sizeof(DWORD), MMSYSERR_INVALPARAM);
  305. ClientUpdatePnpInfo();
  306. DevInterface = auxReferenceDevInterfaceById(uDeviceID);
  307. mmr = (MMRESULT)auxOutMessage(uDeviceID, AUXDM_GETVOLUME, (DWORD_PTR)lpdwVolume, (DWORD_PTR)DevInterface);
  308. if (DevInterface) wdmDevInterfaceDec(DevInterface);
  309. return mmr;
  310. }
  311. /*****************************************************************************
  312. * @doc EXTERNAL AUX
  313. *
  314. * @api MMRESULT | auxSetVolume | This function sets the volume in an
  315. * auxiliary output device.
  316. *
  317. * @parm UINT | uDeviceID | Identifies the auxiliary output device to be
  318. * queried. Device IDs are determined implicitly from the number of
  319. * devices present in the system. Device ID values range from zero
  320. * to one less than the number of devices present. Use <f auxGetNumDevs>
  321. * to determine the number of auxiliary devices in the system.
  322. *
  323. * @parm DWORD | dwVolume | Specifies the new volume setting. The
  324. * low-order UINT specifies the left channel volume setting, and the
  325. * high-order word specifies the right channel setting.
  326. * A value of 0xFFFF represents full volume, and a value of 0x0000
  327. * is silence.
  328. *
  329. * If a device does not support both left and right volume
  330. * control, the low-order word of <p dwVolume> specifies the volume
  331. * level, and the high-order word is ignored.
  332. *
  333. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  334. * an error number. Possible error returns are:
  335. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  336. * @flag MMSYSERR_NODRIVER | The driver failed to install.
  337. *
  338. * @comm Not all devices support volume control.
  339. * To determine whether the device supports volume control, use the
  340. * AUXCAPS_VOLUME flag to test the <e AUXCAPS.dwSupport> field of the
  341. * <t AUXCAPS> structure (filled by <f auxGetDevCaps>).
  342. *
  343. * To determine whether the device supports volume control on both the
  344. * left and right channels, use the AUXCAPS_LRVOLUME flag to test the
  345. * <e AUXCAPS.dwSupport> field of the <t AUXCAPS> structure (filled
  346. * by <f auxGetDevCaps>).
  347. *
  348. * Most devices do not support the full 16 bits of volume level control
  349. * and will use only the high-order bits of the requested volume setting.
  350. * For example, for a device that supports 4 bits of volume control,
  351. * requested volume level values of 0x4000, 0x4fff, and 0x43be will
  352. * all produce the same physical volume setting, 0x4000. The
  353. * <f auxGetVolume> function will return the full 16-bit setting set
  354. * with <f auxSetVolume>.
  355. *
  356. * Volume settings are interpreted logarithmically. This means the
  357. * perceived volume increase is the same when increasing the
  358. * volume level from 0x5000 to 0x6000 as it is from 0x4000 to 0x5000.
  359. *
  360. * @xref auxGetVolume
  361. ****************************************************************************/
  362. MMRESULT APIENTRY auxSetVolume(UINT uDeviceID, DWORD dwVolume)
  363. {
  364. PCWSTR DevInterface;
  365. MMRESULT mmr;
  366. ClientUpdatePnpInfo();
  367. DevInterface = auxReferenceDevInterfaceById(uDeviceID);
  368. mmr = (MMRESULT)auxOutMessage(uDeviceID, AUXDM_SETVOLUME, dwVolume, (DWORD_PTR)DevInterface);
  369. if (DevInterface) wdmDevInterfaceDec(DevInterface);
  370. return mmr;
  371. }