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.

400 lines
11 KiB

  1. /************************************************************************/
  2. /*
  3. ** Copyright (c) 1985-1999 Microsoft Corporation
  4. **
  5. ** Title: drvproc.c - Multimedia Systems Media Control Interface
  6. ** waveform audio driver for RIFF wave files.
  7. **
  8. ** Version: 1.00
  9. **
  10. ** Date: 18-Apr-1990
  11. **
  12. ** Author: ROBWI
  13. */
  14. /************************************************************************/
  15. /*
  16. ** Change log:
  17. **
  18. ** DATE REV DESCRIPTION
  19. ** ----------- ----- ------------------------------------------
  20. ** 10-Jan-1992 MikeTri Ported to NT
  21. ** @@@ need to change slash slash comments to slash star
  22. */
  23. /************************************************************************/
  24. // #define DEBUGLEVELVAR mciwaveDebugLevel
  25. #define UNICODE
  26. #define NOGDICAPMASKS
  27. #define NOVIRTUALKEYCODES
  28. #define NOWINSTYLES
  29. #define NOSYSMETRICS
  30. #define NOMENUS
  31. #define NOICONS
  32. #define NOKEYSTATES
  33. #define NOSYSCOMMANDS
  34. #define NORASTEROPS
  35. #define NOSHOWWINDOW
  36. #define OEMRESOURCE
  37. #define NOATOM
  38. #define NOCLIPBOARD
  39. #define NOCOLOR
  40. #define NOCTLMGR
  41. #define NODRAWTEXT
  42. #define NOGDI
  43. #define NOKERNEL
  44. #define NONLS
  45. #define NOMB
  46. #define NOMEMMGR
  47. #define NOMETAFILE
  48. #define NOMINMAX
  49. #define NOOPENFILE
  50. #define NOSCROLL
  51. #define NOTEXTMETRIC
  52. #define NOWH
  53. #define NOWINOFFSETS
  54. #define NOCOMM
  55. #define NOKANJI
  56. #define NOHELP
  57. #define NOPROFILER
  58. #define NODEFERWINDOWPOS
  59. #define MMNOMMIO
  60. #define MMNOJOY
  61. #define MMNOTIMER
  62. #define MMNOAUX
  63. #define MMNOMIDI
  64. #include <windows.h>
  65. #include "mciwave.h"
  66. #include <mmddk.h>
  67. /************************************************************************/
  68. /*
  69. ** This constant is used for a return value when opening the MCI
  70. ** driver for configuration. Setting the high-order word of the
  71. ** dwDriverID identifies configuration opens.
  72. */
  73. #define CONFIG_ID 10000L
  74. #define MAXINISTRING 32
  75. /************************************************************************/
  76. /*
  77. ** wTableEntry Contains the wave command table identifier.
  78. */
  79. #ifndef MCI_NO_COMMAND_TABLE
  80. #define MCI_NO_COMMAND_TABLE -1
  81. #endif
  82. PRIVATE UINT wTableEntry = MCI_NO_COMMAND_TABLE;
  83. /************************************************************************/
  84. /*
  85. @doc INTERNAL MCIWAVE
  86. @func UINT | GetAudioSeconds |
  87. This converts the given string to a UINT which represents the
  88. number of seconds of audio buffers that should be available. The
  89. number is bounded by the minimum and maximum number of seconds as
  90. defined by MinAudioSeconds and MaxAudioSeconds.
  91. @parm LPCSTR | lszNumber |
  92. Points to the string containing the string representation of the
  93. number to convert.
  94. @rdesc Returns the int representation of the number passed. If the number
  95. is out of range, the default number of audio seconds is returned.
  96. */
  97. PUBLIC UINT PASCAL FAR GetAudioSeconds(
  98. LPCWSTR lszNumber)
  99. {
  100. UINT wSeconds;
  101. for (wSeconds = 0;
  102. (wSeconds < MaxAudioSeconds) && (*lszNumber >= TEXT('0')) && (*lszNumber <= TEXT('9'));
  103. lszNumber++)
  104. wSeconds = wSeconds * 10 + (*lszNumber - '0');
  105. if ((wSeconds > MaxAudioSeconds) || (wSeconds < MinAudioSeconds))
  106. wSeconds = AudioSecondsDefault;
  107. return wSeconds;
  108. }
  109. /************************************************************************/
  110. /*
  111. @doc INTERNAL MCIWAVE
  112. @api BOOL | mwLoadDriver |
  113. This function is called in response to a <m>DRV_LOAD<d> message, and
  114. performs driver initialization. It determines the total number of
  115. input and output devices for use in trying to open any device.
  116. The function then tries to register the extended wave command table.
  117. @rdesc Returns TRUE on success, else FALSE.
  118. */
  119. PRIVATE BOOL PASCAL NEAR mwLoadDriver(
  120. VOID)
  121. {
  122. WCHAR aszResource[MAXINISTRING];
  123. dprintf3(("mwLoadDriver called"));
  124. cWaveOutMax = waveOutGetNumDevs();
  125. cWaveInMax = waveInGetNumDevs();
  126. #if DBG
  127. if (cWaveOutMax + cWaveInMax) {
  128. dprintf4(("Number of Wave Out devices = %d, Wave In devices = %d", cWaveOutMax, cWaveInMax));
  129. } else {
  130. dprintf1(("NO wave input or output devices detected"));
  131. }
  132. #endif
  133. if (LoadString( hModuleInstance,
  134. IDS_COMMANDS,
  135. aszResource,
  136. sizeof(aszResource) / sizeof(WCHAR) ))
  137. {
  138. wTableEntry = mciLoadCommandResource(hModuleInstance, aszResource, 0);
  139. if (wTableEntry != MCI_NO_COMMAND_TABLE) {
  140. dprintf4(("Loaded MCIWAVE command table, table number %d", wTableEntry));
  141. return TRUE;
  142. }
  143. #if DBG
  144. else
  145. dprintf1(("mwLoadDriver: mciLoadCommandResource failed"));
  146. }
  147. else
  148. {
  149. dprintf1(("mwLoadDriver: LoadString of command table identifier failed"));
  150. #endif
  151. }
  152. dprintf1(("mwLoadDriver returning FALSE"));
  153. return FALSE;
  154. }
  155. /************************************************************************/
  156. /*
  157. @doc INTERNAL MCIWAVE
  158. @api BOOL | mwFreeDriver |
  159. Perform driver cleanup in response to DRV_FREE message. This is only
  160. called at driver unload time if a previous DRV_LOAD message succeeded.
  161. @rdesc Returns TRUE always.
  162. */
  163. PRIVATE BOOL PASCAL NEAR mwFreeDriver(
  164. VOID)
  165. {
  166. if (wTableEntry != MCI_NO_COMMAND_TABLE) {
  167. mciFreeCommandResource(wTableEntry);
  168. wTableEntry = MCI_NO_COMMAND_TABLE;
  169. }
  170. return TRUE;
  171. }
  172. /************************************************************************/
  173. /*
  174. @doc INTERNAL MCIWAVE
  175. @api LRESULT | DriverProc |
  176. The entry point for an installable driver.
  177. @parm DWORD | dDriverId |
  178. For most messages, <p>dDriverId<d> is the DWORD value that the driver
  179. returns in response to a <m>DRV_OPEN<d> message. Each time that the
  180. driver is opened, through the DrvOpen API, the driver receives a
  181. <m>DRV_OPEN<d> message and can return an arbitrary, non-zero, value.
  182. The installable driver interface saves this value and returns a unique
  183. driver handle to the application. Whenever the application sends a
  184. message to the driver using the driver handle, the interface routes the
  185. message to this entry point and passes the corresponding
  186. <p>dDriverId<d>.
  187. This mechanism allows the driver to use the same or different
  188. identifiers for multiple opens but ensures that driver handles are
  189. unique at the application interface layer.
  190. The following messages are not related to a particular open instance
  191. of the driver. For these messages, the <p>dDriverId<d> will always
  192. be ZERO: <m>DRV_LOAD<d>, <m>DRV_FREE<d>, <m>DRV_ENABLE<d>,
  193. <m>DRV_DISABLE<d>, <m>DRV_OPEN<d>.
  194. @parm HANDLE | hDriver |
  195. This is the handle returned to the application by the driver interface.
  196. @parm UINT | wMessage |
  197. The requested action to be performed. Message values below
  198. <m>DRV_RESERVED<d> are used for globally defined messages. Message
  199. values from <m>DRV_RESERVED<d> to <m>DRV_USER<d> are used for defined
  200. driver portocols. Messages above <m>DRV_USER<d> are used for driver
  201. specific messages.
  202. @flag DRV_LOAD |
  203. Load the driver.
  204. @flag DRV_FREE |
  205. Free the driver.
  206. @flag DRV_OPEN |
  207. Open the driver. If <p>dParam2<d> is NULL, the driver is being
  208. opened for configuration, else the parameter points to an open
  209. parameters block. The command line in the open parameters optionally
  210. contains a replacement for the default audio seconds parameter. If so,
  211. the current default is replaced with this new number.
  212. The rest of the open parameters block is filled in with the driver's
  213. extended command table and device type. The device ID is then
  214. returned.
  215. @flag DRV_CLOSE |
  216. Close the driver. Returns TRUE.
  217. @flag DRV_QUERYCONFIGURE |
  218. Query as to whether the driver can be configured. Returns TRUE.
  219. @flag DRV_CONFIGURE |
  220. After verifying <p>dParam1<d> and <p>dParam2<d>, configure the
  221. driver. Opens the driver configuration dialog.
  222. @flag DRV_ENABLE |
  223. Enable the driver. Use DefDriverProc.
  224. @flag DRV_DISABLE |
  225. Disable the driver. Use DefDriverProc.
  226. @parm LPARAM | lParam1 |
  227. Data for this message. Defined separately for each message.
  228. @parm LPARAM | lParam2 |
  229. Data for this message. Defined separately for each message.
  230. @rdesc Defined separately for each message.
  231. */
  232. #if 0
  233. PUBLIC LRESULT PASCAL DefDriverProc(
  234. DWORD dDriverID,
  235. HANDLE hDriver,
  236. UINT wMessage,
  237. LONG lParam1,
  238. LONG lParam2);
  239. #endif
  240. PUBLIC LRESULT PASCAL DriverProc(
  241. DWORD dDriverID,
  242. HANDLE hDriver,
  243. UINT wMessage,
  244. DWORD_PTR lParam1,
  245. DWORD_PTR lParam2)
  246. {
  247. LPMCI_OPEN_DRIVER_PARMS lpOpen;
  248. switch (wMessage) {
  249. case DRV_LOAD:
  250. return (LRESULT)(LONG)mwLoadDriver();
  251. case DRV_FREE:
  252. return (LRESULT)(LONG)mwFreeDriver();
  253. case DRV_OPEN:
  254. if (!(LONG)lParam2)
  255. return (LRESULT)CONFIG_ID;
  256. lpOpen = (LPMCI_OPEN_DRIVER_PARMS)lParam2;
  257. if (lpOpen->lpstrParams != NULL)
  258. wAudioSeconds = GetAudioSeconds(lpOpen->lpstrParams);
  259. else
  260. wAudioSeconds = AudioSecondsDefault;
  261. lpOpen->wCustomCommandTable = wTableEntry;
  262. lpOpen->wType = MCI_DEVTYPE_WAVEFORM_AUDIO;
  263. return (LRESULT)(LONG)lpOpen->wDeviceID;
  264. case DRV_CLOSE:
  265. case DRV_QUERYCONFIGURE:
  266. return (LRESULT)1;
  267. case DRV_INSTALL:
  268. case DRV_REMOVE:
  269. return (LRESULT)DRVCNF_OK;
  270. case DRV_CONFIGURE:
  271. if ((LONG)lParam2 && (LONG)lParam1 && (((LPDRVCONFIGINFO)lParam2)->dwDCISize == sizeof(DRVCONFIGINFO)))
  272. return (LRESULT)(LONG)Config((HWND)lParam1, (LPDRVCONFIGINFO)lParam2, hModuleInstance);
  273. return (LRESULT)DRVCNF_CANCEL;
  274. default:
  275. if (!HIWORD(dDriverID) && wMessage >= DRV_MCI_FIRST && wMessage <= DRV_MCI_LAST)
  276. return mciDriverEntry((WORD)dDriverID, wMessage, (DWORD)lParam1, (LPMCI_GENERIC_PARMS)lParam2);
  277. else
  278. return DefDriverProc(dDriverID, hDriver, wMessage, lParam1, lParam2);
  279. }
  280. }
  281. /**************************************************************************
  282. @doc EXTERNAL
  283. @api BOOL | DllInstanceInit | This procedure is called whenever a
  284. process attaches or detaches from the DLL.
  285. @parm PVOID | hModule | Handle of the DLL.
  286. @parm ULONG | Reason | What the reason for the call is.
  287. @parm PCONTEXT | pContext | Some random other information.
  288. @rdesc The return value is TRUE if the initialisation completed ok,
  289. FALSE if not.
  290. **************************************************************************/
  291. BOOL DllInstanceInit(PVOID hModule, ULONG Reason, PCONTEXT pContext)
  292. {
  293. UNREFERENCED_PARAMETER(pContext);
  294. if (Reason == DLL_PROCESS_ATTACH) {
  295. #if DBG
  296. WCHAR strname[50];
  297. #endif
  298. DisableThreadLibraryCalls(hModule);
  299. mciwaveInitDebugLevel ();
  300. InitCrit();
  301. hModuleInstance = hModule;
  302. #if DBG
  303. GetModuleFileName(NULL, strname, sizeof(strname) / sizeof(WCHAR) );
  304. dprintf2(("Process attaching, exe=%ls (Pid %x Tid %x)", strname, GetCurrentProcessId(), GetCurrentThreadId()));
  305. dprintf2((" starting debug level=%d", mciwaveDebugLevel));
  306. #endif
  307. } else if (Reason == DLL_PROCESS_DETACH) {
  308. dprintf2(("Process ending (Pid %x Tid %x)", GetCurrentProcessId(), GetCurrentThreadId()));
  309. DeleteCrit(); // Something nasty happens if we don't do this
  310. } else {
  311. dprintf2(("DllInstanceInit - reason %d", Reason));
  312. }
  313. return TRUE;
  314. }
  315. /************************************************************************/