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.

591 lines
16 KiB

  1. /*******************************Module*Header*********************************\
  2. * Module Name: cddrvr.c
  3. *
  4. * Installalble driver stuff for the
  5. *
  6. * Media Control Architecture Redbook Audio Device Driver
  7. *
  8. * Created: 10/7/90
  9. * Author: DLL (DavidLe)
  10. *
  11. * History:
  12. *
  13. * Copyright (c) 1990-1999 Microsoft Corporation
  14. *
  15. \******************************************************************************/
  16. #include <stdlib.h>
  17. #include <windows.h>
  18. #include <mmsystem.h>
  19. #include <mmddk.h>
  20. #include <winreg.h>
  21. #include "mcicda.h"
  22. #include "cda.h"
  23. #include "cdio.h"
  24. HANDLE InitCritSection = NULL;
  25. #define MYREGSTR_PATH_MEDIA TEXT("SYSTEM\\CurrentControlSet\\Control\\MediaResources")
  26. static TCHAR gszRegstrCDAPath[] = MYREGSTR_PATH_MEDIA TEXT("\\mci\\cdaudio");
  27. static TCHAR gszUnitEnum[] = TEXT("%s\\unit %d");
  28. static TCHAR gszSettingsKey[] = TEXT("Volume Settings");
  29. static TCHAR gszDefaultCDA[] = TEXT("Default Drive");
  30. int PASCAL FAR CDAConfig (HWND hwndParent);
  31. DWORD NEAR PASCAL drvOpen (LPMCI_OPEN_DRIVER_PARMS lpDrvOpen);
  32. UINT CDAudio_GetDefDrive();
  33. typedef BOOL (WINAPI *SHOWMMCPLPROPSHEETW)(HWND hwndParent,
  34. LPCWSTR szPropSheetID,
  35. LPWSTR szTabName,
  36. LPWSTR szCaption);
  37. #define _MAX_PATH 260
  38. /*****************************************************************************
  39. @doc INTERNAL MCICDA
  40. @api DWORD NEAR PASCAL | drvOpen |
  41. @parm LPMCI_OPEN_DRIVER_PARMS | lpDrvOpen |
  42. @rdesc
  43. @comm
  44. *****************************************************************************/
  45. #define CONFIG_ID 10000L // Use the hiword of dwDriverID to identify
  46. // config. opens
  47. DWORD NEAR PASCAL drvOpen (LPMCI_OPEN_DRIVER_PARMS lpDrvOpen)
  48. {
  49. DWORD dwRes;
  50. if (lpDrvOpen == NULL)
  51. {
  52. dwRes = CONFIG_ID;
  53. }
  54. else
  55. {
  56. long lSupportInfo;
  57. int numdrives;
  58. LPCTSTR lpstrBuf;
  59. DID didDrive;
  60. PINSTDATA pInst;
  61. /*
  62. Sent to the driver when it is opened.
  63. dwDriverID is 0L.
  64. lParam1 is a far pointer to a zero-terminated string
  65. containing the name used to open the driver.
  66. lParam2 is passed through from the drvOpen call.
  67. Return 0L to FAIL the open.
  68. */
  69. lpDrvOpen->wType = MCI_DEVTYPE_CD_AUDIO;
  70. lpDrvOpen->wCustomCommandTable = MCI_TABLE_NOT_PRESENT;
  71. EnterCrit (InitCritSection);
  72. numdrives = CDA_init_audio ();
  73. LeaveCrit (InitCritSection);
  74. dprintf2(("Number of CD drives found = %d", numdrives));
  75. if (numdrives <= 0)
  76. {
  77. return 0;
  78. }
  79. if (numdrives > 1)
  80. {
  81. lpstrBuf = lpDrvOpen->lpstrParams;
  82. while (*lpstrBuf == ' ')
  83. {
  84. ++lpstrBuf;
  85. }
  86. if (*lpstrBuf == '\0')
  87. {
  88. didDrive = CDAudio_GetDefDrive();
  89. }
  90. else
  91. {
  92. didDrive = *lpstrBuf - '0';
  93. }
  94. if (didDrive >= MCIRBOOK_MAX_DRIVES)
  95. {
  96. return 0;
  97. }
  98. }
  99. else
  100. {
  101. didDrive = 0;
  102. }
  103. // get the next drive with audio support
  104. lSupportInfo = 0; // in case the loop never executes, or open fails
  105. for (;didDrive < numdrives;didDrive++)
  106. {
  107. EnterCrit (CdInfo[didDrive].DeviceCritSec);
  108. if (!CDA_open (didDrive))
  109. {
  110. LeaveCrit (CdInfo[didDrive].DeviceCritSec);
  111. continue;
  112. }
  113. lSupportInfo = CDA_get_support_info(didDrive);
  114. if (lSupportInfo & SUPPORTS_REDBOOKAUDIO)
  115. {
  116. break;
  117. }
  118. CDA_close (didDrive);
  119. LeaveCrit (CdInfo[didDrive].DeviceCritSec);
  120. }
  121. // no drives with audio
  122. if (! (lSupportInfo & SUPPORTS_REDBOOKAUDIO))
  123. {
  124. CDA_close (didDrive);
  125. LeaveCrit (CdInfo[didDrive].DeviceCritSec);
  126. return 0;
  127. }
  128. // Future domain driver will not fail previous checks if no data cable
  129. if ((lSupportInfo & DISC_IN_DRIVE) &&
  130. CDA_time_info (didDrive, NULL, NULL) != COMMAND_SUCCESSFUL)
  131. {
  132. CDA_close (didDrive);
  133. LeaveCrit (CdInfo[didDrive].DeviceCritSec);
  134. return 0;
  135. }
  136. CDA_close (didDrive);
  137. LeaveCrit (CdInfo[didDrive].DeviceCritSec);
  138. pInst = (PINSTDATA)LocalAlloc(LPTR, sizeof(INSTDATA));
  139. if (pInst == NULL)
  140. {
  141. return 0;
  142. }
  143. pInst->uMCIDeviceID = lpDrvOpen->wDeviceID;
  144. pInst->uDevice = didDrive;
  145. mciSetDriverData (lpDrvOpen->wDeviceID, (DWORD_PTR)pInst);
  146. dwRes = lpDrvOpen->wDeviceID;
  147. }
  148. return dwRes;
  149. }
  150. UINT CDAudio_GetDefDrive()
  151. {
  152. HKEY hkTmp;
  153. DWORD uDrive = 0;
  154. if (RegOpenKey(HKEY_LOCAL_MACHINE
  155. , gszRegstrCDAPath
  156. , &hkTmp ) == ERROR_SUCCESS)
  157. {
  158. DWORD cb = sizeof(DWORD);
  159. RegQueryValueEx(hkTmp
  160. , gszDefaultCDA
  161. , NULL
  162. , NULL
  163. , (LPBYTE)&uDrive
  164. , &cb);
  165. RegCloseKey(hkTmp);
  166. }
  167. return (UINT)uDrive;
  168. }
  169. typedef struct {
  170. DWORD unit;
  171. DWORD dwVol;
  172. } CDAREG, *PCDAREG;
  173. DWORD CDAudio_GetUnitVolume(
  174. UINT uDrive)
  175. {
  176. HKEY hkTmp;
  177. CDAREG cda;
  178. TCHAR szRegstrCDAudio[_MAX_PATH];
  179. wsprintf (szRegstrCDAudio, gszUnitEnum, gszRegstrCDAPath, uDrive);
  180. cda.dwVol = 0xff;
  181. if (RegOpenKey(HKEY_LOCAL_MACHINE,szRegstrCDAudio,&hkTmp) == ERROR_SUCCESS)
  182. {
  183. DWORD cbCDA = sizeof(CDAREG);
  184. RegQueryValueEx(hkTmp
  185. , gszSettingsKey
  186. , NULL
  187. , NULL
  188. , (LPBYTE)&cda
  189. , &cbCDA);
  190. RegCloseKey(hkTmp);
  191. }
  192. return cda.dwVol;
  193. }
  194. /***************************************************************************
  195. *
  196. * @doc INTERNAL
  197. *
  198. * @func DWORD | DriverProc | The entry point for an installable driver.
  199. *
  200. * @parm DWORD | dwDriverId | For most messages, dwDriverId is the DWORD
  201. * value that the driver returns in response to a DRV_OPEN message.
  202. * Each time that the driver is opened, through the DrvOpen API,
  203. * the driver receives a DRV_OPEN message and can return an
  204. * arbitrary, non-zero, value. The installable driver interface
  205. * saves this value and returns a unique driver handle to the
  206. * application. Whenever the application sends a message to the
  207. * driver using the driver handle, the interface routes the message
  208. * to this entry point and passes the corresponding dwDriverId.
  209. *
  210. * This mechanism allows the driver to use the same or different
  211. * identifiers for multiple opens but ensures that driver handles
  212. * are unique at the application interface layer.
  213. *
  214. * The following messages are not related to a particular open
  215. * instance of the driver.
  216. *
  217. * DRV_LOAD, DRV_FREE, DRV_ENABLE, DRV_DISABLE, DRV_OPEN
  218. *
  219. * @parm HANDLE | hDriver | This is the handle returned to the
  220. * application by the driver interface.
  221. *
  222. * @parm UINT | message | The requested action to be performed. Message
  223. * values below DRV_RESERVED are used for globally defined messages.
  224. * Message values from DRV_RESERVED to DRV_USER are used for
  225. * defined driver portocols. Messages above DRV_USER are used
  226. * for driver specific messages.
  227. *
  228. * @parm DWORD | dwParam1 | Data for this message. Defined separately for
  229. * each message
  230. *
  231. * @parm DWORD | dwParam2 | Data for this message. Defined separately for
  232. * each message
  233. *
  234. * @rdesc Defined separately for each message.
  235. *
  236. ***************************************************************************/
  237. LRESULT DriverProc (DWORD_PTR dwDriverID, HANDLE hDriver, UINT message,
  238. LPARAM lParam1, LPARAM lParam2)
  239. {
  240. LRESULT dwRes;
  241. PINSTDATA pInst;
  242. TCHAR szMutex[32];
  243. switch (message)
  244. {
  245. // Standard, globally used messages.
  246. case DRV_LOAD:
  247. {
  248. int i;
  249. InitCritSection = CreateMutex (NULL, FALSE, TEXT ("MCICDA_InitCritSection"));
  250. for ( i = 0; i < MCIRBOOK_MAX_DRIVES; i++ ) {
  251. CdInfo[i].DeviceCritSec = NULL;
  252. wsprintf (szMutex, TEXT ("%s%ld"), TEXT ("MCICDA_DeviceCritSec_"), i);
  253. CdInfo[i].DeviceCritSec = CreateMutex (NULL, FALSE, szMutex);
  254. }
  255. #if DBG
  256. DebugLevel = GetProfileIntW(L"mmdebug", L"mcicda", 0);
  257. #endif
  258. dprintf2(("DRV_LOAD"));
  259. /*
  260. Sent to the driver when it is loaded. Always the first
  261. message received by a driver.
  262. dwDriverID is 0L.
  263. lParam1 is 0L.
  264. lParam2 is 0L.
  265. Return 0L to FAIL the load.
  266. */
  267. hInstance = GetModuleHandleW( L"mcicda");
  268. dwRes = 1L;
  269. }
  270. break;
  271. case DRV_FREE:
  272. {
  273. int i;
  274. dprintf2(("DRV_FREE"));
  275. /*
  276. Sent to the driver when it is about to be discarded. This
  277. will always be the last message received by a driver before
  278. it is freed.
  279. dwDriverID is 0L.
  280. lParam1 is 0L.
  281. lParam2 is 0L.
  282. Return value is IGNORED.
  283. */
  284. dwRes = 1L;
  285. if (InitCritSection) {
  286. CloseHandle (InitCritSection);
  287. InitCritSection = NULL;
  288. }
  289. for ( i = 0; i < MCIRBOOK_MAX_DRIVES; i++ ) {
  290. if (CdInfo[i].DeviceCritSec) {
  291. CloseHandle (CdInfo[i].DeviceCritSec);
  292. CdInfo[i].DeviceCritSec = NULL;
  293. }
  294. }
  295. }
  296. break;
  297. case DRV_OPEN:
  298. dprintf2(("DRV_OPEN"));
  299. dwRes = drvOpen((LPMCI_OPEN_DRIVER_PARMS)lParam2);
  300. break;
  301. case DRV_CLOSE:
  302. dprintf2(("DRV_CLOSE"));
  303. /*
  304. Sent to the driver when it is closed. Drivers are unloaded
  305. when the close count reaches zero.
  306. dwDriverID is the driver identifier returned from the
  307. corresponding DRV_OPEN.
  308. lParam1 is passed through from the drvOpen call.
  309. lParam2 is passed through from the drvOpen call.
  310. Return 0L to FAIL the close.
  311. */
  312. dwRes = 1L;
  313. break;
  314. case DRV_ENABLE:
  315. dprintf2(("DRV_ENABLE"));
  316. /*
  317. Sent to the driver when the driver is loaded or reloaded
  318. and whenever windows is enabled. Drivers should only
  319. hook interrupts or expect ANY part of the driver to be in
  320. memory between enable and disable messages
  321. dwDriverID is 0L.
  322. lParam1 is 0L.
  323. lParam2 is 0L.
  324. Return value is ignored.
  325. */
  326. dwRes = 1L;
  327. break;
  328. case DRV_DISABLE:
  329. dprintf2(("DRV_DISABLE"));
  330. /*
  331. Sent to the driver before the driver is freed.
  332. and whenever windows is disabled
  333. dwDriverID is 0L.
  334. lParam1 is 0L.
  335. lParam2 is 0L.
  336. Return value is ignored.
  337. */
  338. dwRes = 1L;
  339. break;
  340. case DRV_QUERYCONFIGURE:
  341. dprintf2(("DRV_QUERYCONFIGURE"));
  342. /*
  343. Sent to the driver so that applications can
  344. determine whether the driver supports custom
  345. configuration. The driver should return a
  346. non-zero value to indicate that configuration
  347. is supported.
  348. dwDriverID is the value returned from the DRV_OPEN
  349. call that must have succeeded before this message
  350. was sent.
  351. lParam1 is passed from the app and is undefined.
  352. lParam2 is passed from the app and is undefined.
  353. return 0L to indicate configuration NOT supported.
  354. */
  355. dwRes = 1L;
  356. break;
  357. case DRV_CONFIGURE:
  358. dprintf2(("DRV_CONFIGURE"));
  359. /*
  360. Sent to the driver so that it can display a custom
  361. configuration dialog box.
  362. lParam1 is passed from the app. and should contain
  363. the parent window handle in the loword.
  364. lParam2 is passed from the app and is undefined.
  365. return value is undefined.
  366. Drivers should create their own section in
  367. system.ini. The section name should be the driver
  368. name.
  369. */
  370. if (lParam1)
  371. {
  372. dwRes = CDAConfig((HWND)LOWORD (lParam1));
  373. } else {
  374. dwRes = DRVCNF_CANCEL;
  375. }
  376. break;
  377. default:
  378. if (dwDriverID != CONFIG_ID &&
  379. message >= DRV_MCI_FIRST && message <= DRV_MCI_LAST) {
  380. dwRes = CD_MCI_Handler ((MCIDEVICEID)dwDriverID, message,
  381. lParam1, lParam2);
  382. } else {
  383. dwRes = DefDriverProc(dwDriverID, hDriver, message,
  384. lParam1, lParam2);
  385. }
  386. break;
  387. }
  388. return (LRESULT)dwRes;
  389. }
  390. /*****************************Private*Routine******************************\
  391. * EnterCrit
  392. *
  393. *
  394. *
  395. * History:
  396. * dd-mm-94 - StephenE - Created
  397. *
  398. \**************************************************************************/
  399. void
  400. EnterCrit(
  401. HANDLE hMutex
  402. )
  403. {
  404. dprintf4(( "Entering Crit Sect 0x%X", hMutex ));
  405. if (hMutex)
  406. {
  407. WaitForSingleObject (hMutex, INFINITE);
  408. }
  409. }
  410. /*****************************Private*Routine******************************\
  411. * LeaveCrit
  412. *
  413. *
  414. *
  415. * History:
  416. * dd-mm-94 - StephenE - Created
  417. *
  418. \**************************************************************************/
  419. void
  420. LeaveCrit(
  421. HANDLE hMutex
  422. )
  423. {
  424. dprintf4(( "Leaving Crit Sect 0x%X", hMutex ));
  425. if (hMutex)
  426. {
  427. ReleaseMutex (hMutex);
  428. }
  429. }
  430. /*****************************************************************************
  431. @doc INTERNAL MCICDA
  432. @api int | CDAConfig |
  433. @parm HWND | hwndParent |
  434. @rdesc
  435. @comm
  436. *****************************************************************************/
  437. int CDAConfig (HWND hwndParent)
  438. {
  439. static HWND hwndPrevParent = NULL;
  440. WCHAR szCaptionW[ 128 ];
  441. // We need only a unicode version of the caption (for FindWindow()
  442. // and ShowMMCPLPropertySheetW(), which are unicode-enabled).
  443. //
  444. LoadStringW(hInstance,IDS_CDMUSICCAPTION,szCaptionW,cchLENGTH(szCaptionW));
  445. if (hwndPrevParent)
  446. {
  447. BringWindowToTop(FindWindowW(NULL, szCaptionW));
  448. }
  449. else
  450. {
  451. HINSTANCE h;
  452. SHOWMMCPLPROPSHEETW fn;
  453. static TCHAR aszMMSystemW[] = TEXT("MMSYS.CPL");
  454. static char aszShowPropSheetA[] = "ShowMMCPLPropertySheetW";
  455. static WCHAR aszCDAudioW[] = L"CDAUDIO";
  456. WCHAR szCDMusicW[64];
  457. LoadStringW(hInstance, IDS_CDMUSIC, szCDMusicW, cchLENGTH(szCDMusicW));
  458. h = LoadLibrary (aszMMSystemW);
  459. if (h)
  460. {
  461. fn = (SHOWMMCPLPROPSHEETW)GetProcAddress(h, aszShowPropSheetA);
  462. if (fn)
  463. {
  464. BOOL f;
  465. hwndPrevParent = hwndParent;
  466. CDA_init_audio ();
  467. f = fn(hwndParent, aszCDAudioW, szCDMusicW, szCaptionW);
  468. CDA_terminate_audio ();
  469. hwndPrevParent = NULL;
  470. }
  471. FreeLibrary(h);
  472. }
  473. }
  474. return DRVCNF_OK;
  475. }