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.

1494 lines
44 KiB

  1. /*==========================================================================*/
  2. //
  3. // mmcpl.c
  4. //
  5. // Copyright (C) 1993-1994 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // 06/94 -Created- VijR
  8. //
  9. /*==========================================================================*/
  10. #pragma warning( disable: 4103)
  11. #include "mmcpl.h"
  12. #include <cpl.h>
  13. #define NOSTATUSBAR
  14. #include <commctrl.h>
  15. #include <prsht.h>
  16. #include <regstr.h>
  17. #include <infstr.h>
  18. #include <devguid.h>
  19. #include "draw.h"
  20. #include "utils.h"
  21. #include "drivers.h"
  22. #include "sulib.h"
  23. #include <tchar.h>
  24. #include <hwtab.h>
  25. #include "debug.h"
  26. #ifndef cchRESOURCE
  27. #define cchRESOURCE 256
  28. #endif
  29. /*
  30. ***************************************************************
  31. * Globals
  32. ***************************************************************
  33. */
  34. HINSTANCE ghInstance = NULL;
  35. BOOL gfNukeExt = -1;
  36. HWND ghwndMsgBox = NULL;
  37. HWND ghwndAdvProp = NULL;
  38. BOOL gfVoiceTab = FALSE;
  39. #ifdef FIX_BUG_15451
  40. static TCHAR cszFORKLINE[] = TEXT("RUNDLL32.EXE MMSYS.CPL,ShowDriverSettingsAfterFork %s");
  41. #endif // FIX_BUG_15451
  42. SZCODE cszAUDIO[] = AUDIO;
  43. SZCODE cszVIDEO[] = VIDEO;
  44. SZCODE cszCDAUDIO[] = CDAUDIO;
  45. SZCODE cszMIDI[] = MIDI;
  46. SZCODE cszVOICE[] = VOICE;
  47. SZCODE cszVOLUME[] = VOLUME;
  48. /*
  49. ***************************************************************
  50. * Typedefs
  51. ***************************************************************
  52. */
  53. typedef struct _ExtPropSheetCBParam //Callback Parameter
  54. {
  55. HTREEITEM hti;
  56. LPPROPSHEETHEADER ppsh;
  57. LPARAM lParam1; //PIRESOURCE/PINSTRUMENT etc. depending on node. (OR) Simple propsheet class
  58. LPARAM lParam2; //hwndTree (OR) Simple propsheet name
  59. } EXTPROPSHEETCBPARAM, *PEXTPROPSHEETCBPARAM;
  60. typedef struct _MBInfo
  61. {
  62. LPTSTR szTitle;
  63. LPTSTR szMsg;
  64. UINT uStyle;
  65. } MBINFO, *PMBINFO;
  66. /*
  67. ***************************************************************
  68. * Defines
  69. ***************************************************************
  70. */
  71. #define MAXPAGES 8 // MAX number of sheets allowed
  72. #define MAXMODULES 32 // MAX number of external modules allowed
  73. #define MAXCLASSSIZE 64
  74. #define cComma TEXT(',')
  75. #define PROPTABSIZE 13
  76. #define GetString(_str,_id,_hi) LoadString (_hi, _id, _str, sizeof(_str)/sizeof(TCHAR))
  77. /*
  78. ***************************************************************
  79. * File Globals
  80. ***************************************************************
  81. */
  82. static SZCODE aszSimpleProperties[] = REGSTR_PATH_MEDIARESOURCES TEXT("\\MediaExtensions\\shellx\\SimpleProperties\\");
  83. static SZCODE aszShellName[] = TEXT("ShellName");
  84. static UINT g_cRefCnt; // keeps track of the ref count
  85. static int g_cProcesses = 0;
  86. static int g_nStartPage = 0;
  87. /*
  88. ***************************************************************
  89. * Prototypes
  90. ***************************************************************
  91. */
  92. INT_PTR CALLBACK AudioDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  93. INT_PTR CALLBACK VideoDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  94. INT_PTR CALLBACK CDDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  95. INT_PTR CALLBACK ACMDlg(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
  96. INT_PTR CALLBACK SoundDlg(HWND, UINT, WPARAM, LPARAM);
  97. INT_PTR CALLBACK VolumeDlg(HWND, UINT, WPARAM, LPARAM);
  98. INT_PTR CALLBACK AddDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  99. INT_PTR CALLBACK AdvDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  100. INT_PTR CALLBACK HardwareDlgProc(HWND hdlg, UINT uMsg, WPARAM wp, LPARAM lp);
  101. INT_PTR CALLBACK VoiceDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  102. //INT_PTR CALLBACK EffectDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  103. //
  104. // This is the dialog procedure for the "Hardware" page.
  105. //
  106. INT_PTR CALLBACK HardwareDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
  107. {
  108. static HWND s_hwndHW = NULL;
  109. switch (uMessage)
  110. {
  111. case WM_NOTIFY:
  112. {
  113. NMHDR * pnmhdr = (NMHDR *) lParam;
  114. int code = pnmhdr->code;
  115. switch (code)
  116. {
  117. case HWN_FILTERITEM:
  118. {
  119. NMHWTAB *pnmht = (NMHWTAB *) lParam;
  120. BOOL fFilter = FALSE;
  121. if (!pnmht->fHidden) // Let's not bother looking at devices already hidden
  122. {
  123. fFilter = FALSE;
  124. }
  125. return(TRUE);
  126. }
  127. break;
  128. case HWN_SELECTIONCHANGED:
  129. {
  130. NMHWTAB *pnmht = (NMHWTAB *) lParam;
  131. if (pnmht)
  132. {
  133. if (pnmht->pdinf)
  134. {
  135. if (IsEqualGUID(&(pnmht->pdinf->ClassGuid),&GUID_DEVCLASS_CDROM))
  136. {
  137. SetWindowText(s_hwndHW, TEXT("hh.exe ms-its:tshoot.chm::/hdw_drives.htm"));
  138. }
  139. else
  140. {
  141. SetWindowText(s_hwndHW, TEXT("hh.exe ms-its:tshoot.chm::/tssound.htm"));
  142. }
  143. }
  144. }
  145. }
  146. break;
  147. }
  148. }
  149. break;
  150. case WM_INITDIALOG:
  151. {
  152. GUID guidClass[2];
  153. guidClass[0] = GUID_DEVCLASS_CDROM;
  154. guidClass[1] = GUID_DEVCLASS_MEDIA;
  155. s_hwndHW = DeviceCreateHardwarePageEx(hDlg, (const GUID *) &guidClass, 2, HWTAB_LARGELIST );
  156. if (s_hwndHW)
  157. {
  158. SetWindowText(s_hwndHW, TEXT("hh.exe ms-its:tshoot.chm::/tssound.htm"));
  159. }
  160. else
  161. {
  162. DestroyWindow(hDlg); // catastrophic failure
  163. }
  164. }
  165. return FALSE;
  166. }
  167. return FALSE;
  168. }
  169. INT_PTR CALLBACK CD_HardwareDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
  170. {
  171. switch (uMessage)
  172. {
  173. case WM_INITDIALOG:
  174. {
  175. HWND hwndHW;
  176. hwndHW = DeviceCreateHardwarePageEx(hDlg, &GUID_DEVCLASS_CDROM, 1, HWTAB_SMALLLIST);
  177. if (hwndHW)
  178. {
  179. SetWindowText(hwndHW, TEXT("hh.exe ms-its:tshoot.chm::/hdw_multi.htm"));
  180. }
  181. else
  182. {
  183. DestroyWindow(hDlg); // catastrophic failure
  184. }
  185. }
  186. return FALSE;
  187. }
  188. return FALSE;
  189. }
  190. /*
  191. ***************************************************************
  192. ***************************************************************
  193. */
  194. INT_PTR FAR PASCAL mmse_MessageBoxProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  195. {
  196. switch (wMsg)
  197. {
  198. case WM_INITDIALOG:
  199. {
  200. PMBINFO pmbInfo = (PMBINFO)lParam;
  201. UINT uStyle = pmbInfo->uStyle;
  202. SetWindowText(hDlg, pmbInfo->szTitle);
  203. SetWindowText(GetDlgItem(hDlg, MMSE_TEXT), pmbInfo->szMsg);
  204. if (IsFlagClear(uStyle, MMSE_OK))
  205. DestroyWindow(GetDlgItem(hDlg, MMSE_OK));
  206. if (IsFlagClear(uStyle, MMSE_YES))
  207. DestroyWindow(GetDlgItem(hDlg, MMSE_YES));
  208. if (IsFlagClear(uStyle, MMSE_NO))
  209. DestroyWindow(GetDlgItem(hDlg, MMSE_NO));
  210. ghwndMsgBox = hDlg;
  211. break;
  212. }
  213. case WM_DESTROY:
  214. ghwndMsgBox = NULL;
  215. break;
  216. case WM_COMMAND:
  217. {
  218. switch (GET_WM_COMMAND_ID(wParam, lParam))
  219. {
  220. case MMSE_YES:
  221. EndDialog(hDlg, MMSE_YES);
  222. break;
  223. case MMSE_NO:
  224. EndDialog(hDlg, MMSE_NO);
  225. break;
  226. case MMSE_OK:
  227. EndDialog(hDlg, MMSE_OK);
  228. break;
  229. }
  230. break;
  231. }
  232. default:
  233. return FALSE;
  234. }
  235. return TRUE;
  236. }
  237. INT_PTR mmse_MessageBox(HWND hwndP, LPTSTR szMsg, LPTSTR szTitle, UINT uStyle)
  238. {
  239. MBINFO mbInfo;
  240. mbInfo.szMsg = szMsg;
  241. mbInfo.szTitle = szTitle;
  242. mbInfo.uStyle = uStyle;
  243. return DialogBoxParam(ghInstance, MAKEINTRESOURCE(DLG_MESSAGE_BOX), hwndP, mmse_MessageBoxProc, (LPARAM)&mbInfo);
  244. }
  245. /*==========================================================================*/
  246. int FAR PASCAL lstrncmpi(
  247. LPCTSTR lszKey,
  248. LPCTSTR lszClass,
  249. int iSize)
  250. {
  251. TCHAR aszKey[64];
  252. lstrcpyn(aszKey, lszKey, iSize);
  253. return lstrcmpi(aszKey, lszClass);
  254. }
  255. int StrByteLen(LPTSTR sz)
  256. {
  257. LPTSTR psz;
  258. if (!sz)
  259. return 0;
  260. for (psz = sz; *psz; psz = CharNext(psz))
  261. ;
  262. return (int)(psz - sz);
  263. }
  264. static void NukeExt(LPTSTR sz)
  265. {
  266. int len;
  267. len = StrByteLen(sz);
  268. if (len > 4 && sz[len-4] == TEXT('.'))
  269. sz[len-4] = 0;
  270. }
  271. static LPTSTR NukePath(LPTSTR sz)
  272. {
  273. LPTSTR pTmp, pSlash;
  274. for (pSlash = pTmp = sz; *pTmp; pTmp = CharNext(pTmp))
  275. {
  276. if (*pTmp == TEXT('\\'))
  277. pSlash = pTmp;
  278. }
  279. return (pSlash == sz ? pSlash : pSlash+1);
  280. }
  281. void CheckNukeExtOption(LPTSTR sz)
  282. {
  283. SHFILEINFO sfi;
  284. SHGetFileInfo(sz, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME);
  285. if (lstrcmpi((LPTSTR)(sfi.szDisplayName+lstrlen(sfi.szDisplayName)-4), cszWavExt))
  286. gfNukeExt = TRUE;
  287. else
  288. gfNukeExt = FALSE;
  289. }
  290. LPTSTR PASCAL NiceName(LPTSTR sz, BOOL fNukePath)
  291. {
  292. SHFILEINFO sfi;
  293. if (gfNukeExt == -1)
  294. CheckNukeExtOption(sz);
  295. if (!SHGetFileInfo(sz, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME))
  296. return sz;
  297. if (fNukePath)
  298. {
  299. lstrcpy(sz, sfi.szDisplayName);
  300. }
  301. else
  302. {
  303. LPTSTR lpszFileName;
  304. lpszFileName = NukePath(sz);
  305. lstrcpy(lpszFileName, sfi.szDisplayName);
  306. if (lpszFileName != sz)
  307. CharUpperBuff(sz, 1);
  308. }
  309. return sz;
  310. }
  311. /*
  312. ***************************************************************
  313. * ErrorBox
  314. *
  315. * Description:
  316. * Brings up error Dialog displaying error
  317. *
  318. * Parameters:
  319. * HWND hDlg - Window handle
  320. * int iResource - id of the resource to be loaded
  321. * LPTSTR lpszDesc - The string to be inserted in the resource string
  322. *
  323. * Returns: BOOL
  324. *
  325. ***************************************************************
  326. */
  327. BOOL PASCAL ErrorBox(HWND hDlg, int iResource, LPTSTR lpszDesc)
  328. {
  329. TCHAR szBuf[MAXMSGLEN];
  330. TCHAR szTitle[MAXSTR];
  331. TCHAR szResource[MAXMSGLEN];
  332. LoadString(ghInstance, iResource, szResource, MAXSTR);
  333. LoadString(ghInstance, IDS_ERROR, szTitle, MAXSTR);
  334. wsprintf(szBuf, szResource, lpszDesc);
  335. MessageBox(hDlg, szBuf, szTitle, MB_APPLMODAL | MB_OK |MB_ICONSTOP);
  336. return TRUE;
  337. }
  338. int PASCAL DisplayMessage(HWND hDlg, int iResTitle, int iResMsg, UINT uStyle)
  339. {
  340. TCHAR szBuf[MAXMSGLEN];
  341. TCHAR szTitle[MAXSTR];
  342. UINT uAddStyle = MB_APPLMODAL;
  343. if (!LoadString(ghInstance, iResTitle, szTitle, MAXSTR))
  344. return FALSE;
  345. if (!LoadString(ghInstance, iResMsg, szBuf, MAXSTR))
  346. return FALSE;
  347. if (uStyle & MB_OK)
  348. uAddStyle |= MB_ICONASTERISK;
  349. else
  350. uAddStyle |= MB_ICONQUESTION;
  351. return MessageBox(hDlg, szBuf, szTitle, uStyle | uAddStyle);
  352. }
  353. //Adds spaces around Tab Names to make them all approx. same size.
  354. STATIC void PadWithSpaces(LPTSTR szName, LPTSTR szPaddedName)
  355. {
  356. static SZCODE cszFmt[] = TEXT("%s%s%s");
  357. TCHAR szPad[8];
  358. int i;
  359. i = PROPTABSIZE - lstrlen(szName);
  360. i = (i <= 0) ? 0 : i/2;
  361. for (szPad[i] = TEXT('\0');i; i--)
  362. szPad[i-1] = TEXT(' ');
  363. wsprintf(szPaddedName, cszFmt, szPad, szName, szPad);
  364. }
  365. /*==========================================================================*/
  366. UINT CALLBACK CallbackPage(
  367. HWND hwnd,
  368. UINT uMsg,
  369. LPPROPSHEETPAGE ppsp)
  370. {
  371. if (uMsg == PSPCB_RELEASE)
  372. {
  373. DPF_T("* RelasePage %s *", (LPTSTR)ppsp->pszTitle);
  374. }
  375. return 1;
  376. }
  377. /*==========================================================================*/
  378. static BOOL PASCAL NEAR AddPage(
  379. LPPROPSHEETHEADER ppsh,
  380. LPCTSTR pszTitle,
  381. DLGPROC pfnDialog,
  382. UINT idTemplate,
  383. LPARAM lParam)
  384. {
  385. if (ppsh->nPages < MAXPAGES)
  386. {
  387. if (pfnDialog)
  388. {
  389. PROPSHEETPAGE psp;
  390. psp.dwSize = sizeof(PROPSHEETPAGE);
  391. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USECALLBACK;
  392. psp.hInstance = ghInstance;
  393. psp.pszTemplate = MAKEINTRESOURCE(idTemplate);
  394. psp.pszIcon = NULL;
  395. psp.pszTitle = pszTitle;
  396. psp.pfnDlgProc = pfnDialog;
  397. psp.lParam = (LPARAM)lParam;
  398. psp.pfnCallback = CallbackPage;
  399. psp.pcRefParent = NULL;
  400. if (ppsh->phpage[ppsh->nPages] = CreatePropertySheetPage(&psp))
  401. {
  402. ppsh->nPages++;
  403. return TRUE;
  404. }
  405. }
  406. }
  407. return FALSE;
  408. }
  409. /*==========================================================================*/
  410. BOOL CALLBACK MMExtPropSheetCallback(DWORD dwFunc, DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD_PTR dwInstance)
  411. {
  412. PEXTPROPSHEETCBPARAM pcbp = (PEXTPROPSHEETCBPARAM)dwInstance;
  413. if (!pcbp && dwFunc != MM_EPS_BLIND_TREECHANGE)
  414. return FALSE;
  415. switch (dwFunc)
  416. {
  417. case MM_EPS_GETNODEDESC:
  418. {
  419. if (!dwParam1)
  420. return FALSE;
  421. if (pcbp->hti == NULL)
  422. lstrcpy((LPTSTR)dwParam1, (LPTSTR)pcbp->lParam2);
  423. else
  424. {
  425. GetTreeItemNodeDesc ((LPTSTR)dwParam1,
  426. (PIRESOURCE)pcbp->lParam1);
  427. }
  428. break;
  429. }
  430. case MM_EPS_GETNODEID:
  431. {
  432. if (!dwParam1)
  433. return FALSE;
  434. if (pcbp->hti == NULL)
  435. lstrcpy((LPTSTR)dwParam1, (LPTSTR)pcbp->lParam2);
  436. else
  437. {
  438. GetTreeItemNodeID ((LPTSTR)dwParam1,
  439. (PIRESOURCE)pcbp->lParam1);
  440. }
  441. break;
  442. }
  443. case MM_EPS_ADDSHEET:
  444. {
  445. HPROPSHEETPAGE hpsp = (HPROPSHEETPAGE)dwParam1;
  446. if (hpsp && (pcbp->ppsh->nPages < MAXPAGES))
  447. {
  448. pcbp->ppsh->phpage[pcbp->ppsh->nPages++] = hpsp;
  449. return TRUE;
  450. }
  451. return FALSE;
  452. }
  453. case MM_EPS_TREECHANGE:
  454. {
  455. RefreshAdvDlgTree ();
  456. break;
  457. }
  458. case MM_EPS_BLIND_TREECHANGE:
  459. {
  460. RefreshAdvDlgTree ();
  461. break;
  462. }
  463. default:
  464. return FALSE;
  465. }
  466. return TRUE;
  467. }
  468. INT_PTR CALLBACK SpeechDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  469. /*==========================================================================*/
  470. static BOOL PASCAL NEAR AddSpeechPage(LPPROPSHEETHEADER ppsh)
  471. {
  472. TCHAR aszTitleRes[128];
  473. TCHAR szTmp[32];
  474. LoadString(ghInstance, IDS_SPEECH_NAME, aszTitleRes, sizeof(aszTitleRes)/sizeof(TCHAR));
  475. PadWithSpaces((LPTSTR)aszTitleRes, (LPTSTR)szTmp);
  476. return AddPage(ppsh, szTmp, SpeechDlgProc, IDD_SPEECH, (LPARAM)NULL);
  477. }
  478. /*==========================================================================*/
  479. static BOOL PASCAL NEAR AddAdvancedPage(
  480. LPPROPSHEETHEADER ppsh)
  481. {
  482. TCHAR aszTitleRes[128];
  483. TCHAR szTmp[32];
  484. LoadString(ghInstance, IDS_ADVANCED, aszTitleRes, sizeof(aszTitleRes)/sizeof(TCHAR));
  485. PadWithSpaces((LPTSTR)aszTitleRes, (LPTSTR)szTmp);
  486. return AddPage(ppsh, szTmp, AdvDlg, ADVDLG, (LPARAM)NULL);
  487. }
  488. /*==========================================================================*/
  489. static BOOL PASCAL NEAR AddHardwarePage(
  490. LPPROPSHEETHEADER ppsh)
  491. {
  492. TCHAR aszTitleRes[128];
  493. TCHAR szTmp[32];
  494. // Don't add a hardware tab if the admin restricted it
  495. if (SHRestricted(REST_NOHARDWARETAB))
  496. return FALSE;
  497. LoadString(ghInstance, IDS_HARDWARE, aszTitleRes, sizeof(aszTitleRes)/sizeof(TCHAR));
  498. PadWithSpaces((LPTSTR)aszTitleRes, (LPTSTR)szTmp);
  499. return AddPage(ppsh, szTmp, HardwareDlgProc, HWDLG, (LPARAM)NULL);
  500. }
  501. /*==========================================================================*/
  502. static BOOL PASCAL NEAR AddSchemesPage(
  503. LPPROPSHEETHEADER ppsh)
  504. {
  505. TCHAR aszTitleRes[128];
  506. LoadString(ghInstance, IDS_EVENTSNAME, aszTitleRes, sizeof(aszTitleRes)/sizeof(TCHAR));
  507. return AddPage(ppsh, aszTitleRes, SoundDlg, SOUNDDIALOG, (LPARAM)NULL);
  508. }
  509. /*==========================================================================*/
  510. static void PASCAL NEAR AddInternalPages (LPPROPSHEETHEADER ppsh)
  511. {
  512. static EXTPROPSHEETCBPARAM cbp;
  513. TCHAR szText[ cchRESOURCE ];
  514. TCHAR szPadded[ cchRESOURCE ];
  515. // Add the Volume page
  516. //
  517. GetString (szText, IDS_VOLUMENAME, ghInstance);
  518. PadWithSpaces (szText, szPadded);
  519. AddPage (ppsh, szPadded, VolumeDlg, IDD_VOLUME, (LPARAM)NULL);
  520. // Add the Sound Scheme page
  521. //
  522. GetString (szText, IDS_EVENTSNAME, ghInstance);
  523. PadWithSpaces (szText, szPadded);
  524. AddPage (ppsh, szPadded, SoundDlg, SOUNDDIALOG, (LPARAM)NULL);
  525. // Add the Audio page
  526. //
  527. GetString (szText, IDS_AUDIO_TAB, ghInstance);
  528. PadWithSpaces (szText, szPadded);
  529. AddPage (ppsh, szPadded, AudioDlg, AUDIODLG, (LPARAM)NULL);
  530. // Add the Voice page
  531. //
  532. GetString (szText, IDS_VOICE, ghInstance);
  533. PadWithSpaces (szText, szPadded);
  534. AddPage (ppsh, szPadded, VoiceDlg, VOICEDLG, (LPARAM)NULL);
  535. // Add the Video page
  536. //
  537. /* GetString (szText, IDS_VIDEO_TAB, ghInstance);
  538. PadWithSpaces (szText, szPadded);
  539. AddPage (ppsh, szPadded, VideoDlg, VIDEODLG, (LPARAM)NULL); */
  540. // Add the MIDI page
  541. //
  542. /* GetString (szText, IDS_MIDI_TAB, ghInstance);
  543. PadWithSpaces (szText, szPadded);
  544. cbp.ppsh = ppsh;
  545. cbp.hti = NULL;
  546. cbp.lParam1 = (LPARAM)cszMIDI;
  547. cbp.lParam2 = (LPARAM)szPadded;
  548. AddSimpleMidiPages ((LPVOID)szPadded, MMExtPropSheetCallback, (LPARAM)&cbp);
  549. */
  550. // Add the CD Audio page
  551. //
  552. /* GetString (szText, IDS_CDAUDIO_TAB, ghInstance);
  553. PadWithSpaces (szText, szPadded);
  554. AddPage (ppsh, szPadded, CDDlg, CDDLG, (LPARAM)NULL);
  555. */
  556. }
  557. static void InitPSH(LPPROPSHEETHEADER ppsh, HWND hwndParent, LPTSTR pszCaption, HPROPSHEETPAGE FAR * phpsp)
  558. {
  559. ppsh->dwSize = sizeof(PROPSHEETHEADER);
  560. ppsh->dwFlags = PSH_PROPTITLE;
  561. ppsh->hwndParent = hwndParent;
  562. ppsh->hInstance = ghInstance;
  563. ppsh->pszCaption = pszCaption;
  564. ppsh->nPages = 0;
  565. ppsh->nStartPage = 0;
  566. ppsh->phpage = phpsp;
  567. }
  568. /*==========================================================================*/
  569. #ifdef FIX_BUG_15451
  570. static void PASCAL cplMMDoubleClick (HWND hCPlWnd, int nStartPage)
  571. #else // FIX_BUG_15451
  572. static void PASCAL cplMMDoubleClick (HWND hCPlWnd)
  573. #endif // FIX_BUG_15451
  574. {
  575. PROPSHEETHEADER psh;
  576. HPROPSHEETPAGE hpsp[MAXPAGES];
  577. TCHAR strOldDir[MAX_PATH], strSysDir[MAX_PATH];
  578. strOldDir[0] = TEXT('\0');
  579. strSysDir[0] = TEXT('\0');
  580. GetSystemDirectory(strSysDir, MAX_PATH);
  581. GetCurrentDirectory(MAX_PATH, strOldDir);
  582. SetCurrentDirectory(strSysDir);
  583. wsInfParseInit();
  584. InitCommonControls();
  585. OleInitialize(NULL);
  586. RegSndCntrlClass((LPCTSTR)DISPFRAMCLASS);
  587. InitPSH(&psh,hCPlWnd,(LPTSTR)MAKEINTRESOURCE(IDS_MMNAME),hpsp);
  588. #ifdef FIX_BUG_15451
  589. psh.nStartPage = nStartPage;
  590. #else // FIX_BUG_15451
  591. psh.nStartPage = g_nStartPage;
  592. #endif // FIX_BUG_15451
  593. g_nStartPage = 0;
  594. AddInternalPages(&psh);
  595. //AddSpeechPage(&psh);
  596. //AddAdvancedPage(&psh);
  597. AddHardwarePage(&psh);
  598. PropertySheet(&psh);
  599. OleUninitialize();
  600. infClose(NULL);
  601. SetCurrentDirectory(strOldDir);
  602. }
  603. /*==========================================================================*/
  604. static void PASCAL cplEventsDoubleClick (HWND hCPlWnd)
  605. {
  606. PROPSHEETHEADER psh;
  607. HPROPSHEETPAGE hpsp[MAXPAGES];
  608. InitCommonControls();
  609. RegSndCntrlClass((LPCTSTR)DISPFRAMCLASS);
  610. InitPSH(&psh,hCPlWnd,(LPTSTR)MAKEINTRESOURCE(IDS_EVENTSNAME),hpsp);
  611. AddSchemesPage(&psh);
  612. PropertySheet(&psh);
  613. }
  614. #ifdef FIX_BUG_15451
  615. /*==========================================================================*/
  616. /*
  617. * ShowDriverSettings
  618. * ShowDriverSettingsAfterFork
  619. *
  620. * When the user selects DevicesTab.<anydevice>.Properties.Settings, a
  621. * DRV_CONFIGURE message is sent to the selected user-mode driver, to cause
  622. * it to display its configuration dialog. The sound drivers shipped with
  623. * NT (SNDBLST,MVAUDIO,SNDSYS) exhibit a bug in this condition: when the
  624. * configuration dialog is complete (regardless of whether OK or CANCEL was
  625. * selected), these drivers attempt to unload-and-reload their kernel-mode
  626. * component in order to begin using the new (or restore the original)
  627. * driver settings. The unload request fails, because both the Audio tab
  628. * and SNDVOL.EXE have open mixer handles and pending IRPs within the kernel
  629. * driver (the latter are used to provide notifications of volume changes).
  630. * Worse, when the unload fails, it leaves the driver useless: its state
  631. * remains STOP_PENDING, and it cannot be resurrected without logging off
  632. * and back on.
  633. *
  634. * These routines have been provided as a temporary workaround for bug 15451,
  635. * which describes the problem mentioned above. The theory behind this
  636. * solution is two-fold:
  637. * 1- close SNDVOL.EXE as soon as a driver's configuration dialog is
  638. * to be displayed, and restart it directly thereafter. This prevents
  639. * it from maintaining any open handles to and/or pending IRPs within the
  640. * kernel driver.
  641. * 2- if the Audio tab has ever been displayed, it will have open mixers
  642. * which must be closed. Because a bug/design flaw within these sound
  643. * drivers prevents the mixers from being closed without killing this
  644. * process (the sound drivers each cache open mixer handles), the
  645. * routine ShowDriverSettings forks a new MMSYS.CPL process, which is
  646. * then used to display the driver's settings dialog.
  647. *
  648. * The flow of this solution follows:
  649. *
  650. * 1- MMSYS.CPL starts on Audio tab, setting fHaveStartedAudioDialog to TRUE.
  651. * 2- User selects Devices tab.
  652. * 3- User selects a device driver.
  653. * 4- User selects Properties+Settings; control reaches ShowDriverSettings().
  654. * 5- ShowDriverSettings() determines if there is a need to fork a new process:
  655. * this will be the case if the Audio tab has been displayed, and the
  656. * device for which it is to display settings contains mixers. If either
  657. * of these conditions is false, ShowDriverSettings displays the driver's
  658. * settings dialog directly (via ConfigureDriver()).
  659. * 6- ShowDriverSettings() uses WinExec() to fork a new process, using
  660. * the routine ShowDriverSettingsAfterFork() as an entry point. If the
  661. * exec fails, ShowDriverSettings() displays the driver's settings dialog
  662. * directly (via ConfigureDriver()).
  663. * PROCESS 1: PROCESS 2:
  664. * 7- Enters WaitForNewCPLWindow(), 1- ShowDriverSettingsAfterFork() will
  665. * which will wait up to 5 seconds receive on its command-line the
  666. * for the new MMSYS.CPL process name of the driver for which
  667. * to open a driver Properties settings have been requested. It
  668. * dialog which matches its own: opens the primary dialog, using the
  669. * if it finds such a dialog, Devices tab as the initial tab--
  670. * WaitForNewCPLWindow() will post so that the Advanced tab is never
  671. * IDCANCEL messages to both the displayed, and because the Devices
  672. * current driver Properties dialog, tab is the active tab on the other
  673. * and to this process's main process.
  674. * dialog, terminating this process. 2- During WM_INITDIALOG of the Devices
  675. * dialog, this process searches for
  676. * the previous process' MMSYS.CPL dialog.
  677. * If successful, it moves this MMSYS.CPL
  678. * dialog directly behind the previous dialog.
  679. * 3- During ID_INIT of the Devices dialog, this
  680. * process searches the TreeView for the driver
  681. * which was named on the comand-line: if found,
  682. * it highlights the TreeItem and simulates a press
  683. * of the Properties button
  684. * 4- During WM_INITDIALOG of the device's Properties dialog,
  685. * this process searches for the previous process' device's
  686. * properties dialog. If successful, it moves this dialog
  687. * directly behind its counterpart.
  688. * 5- During ID_INIT of the device's Properties dialog, this process
  689. * simulates a press of the Settings button
  690. * 6- When the Settings button is pressed, this process recognizes that
  691. * it has been forked and skips the call to ShowDriverSettings(),
  692. * instead simply displaying the driver's settings dialog (via
  693. * ConfigureDriver()).
  694. *
  695. * Let it be known that this is a hack, and should be removed post-beta.
  696. *
  697. */
  698. extern BOOL fHaveStartedAudioDialog; // in MSACMCPL.C
  699. void ShowDriverSettings (HWND hDlg, LPTSTR pszName)
  700. {
  701. if (fHaveStartedAudioDialog && fDeviceHasMixers (pszName))
  702. {
  703. TCHAR szForkLine[ cchRESOURCE *2 ];
  704. STARTUPINFO si;
  705. PROCESS_INFORMATION pi;
  706. memset(&si, 0, sizeof(si));
  707. si.cb = sizeof(si);
  708. si.wShowWindow = SW_SHOW;
  709. si.dwFlags = STARTF_USESHOWWINDOW;
  710. wsprintf (szForkLine, cszFORKLINE, pszName);
  711. if (CreateProcess(NULL,szForkLine,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
  712. {
  713. (void)WaitForNewCPLWindow (hDlg);
  714. }
  715. else
  716. {
  717. ConfigureDriver (hDlg, pszName);
  718. }
  719. }
  720. else
  721. {
  722. ConfigureDriver (hDlg, pszName);
  723. }
  724. }
  725. void WINAPI ShowDriverSettingsAfterFork (
  726. HWND hwndStub,
  727. HINSTANCE hAppInstance,
  728. LPTSTR lpszCmdLine,
  729. int nCmdShow)
  730. {
  731. #ifdef UNICODE
  732. WCHAR szCmdLine[ cchRESOURCE ];
  733. #else
  734. #define szCmdLine lpszCmdLine
  735. #endif
  736. lstrcpy (szDriverWhichNeedsSettings, szCmdLine);
  737. cplMMDoubleClick (NULL, 4); // 4==Start on Advanced ("Devices") tab
  738. }
  739. void WINAPI ShowDriverSettingsAfterForkW (
  740. HWND hwndStub,
  741. HINSTANCE hAppInstance,
  742. LPWSTR lpwszCmdLine,
  743. int nCmdShow)
  744. {
  745. #ifdef UNICODE
  746. #define szCmdLine lpwszCmdLine
  747. #else
  748. CHAR szCmdLine[ cchRESOURCE ];
  749. wcstombs(szCmdLine, lpwszCmdLine, cchRESOURCE);
  750. #endif
  751. lstrcpy (szDriverWhichNeedsSettings, szCmdLine);
  752. cplMMDoubleClick (NULL, 4); // 4==Start on Advanced ("Devices") tab
  753. }
  754. #endif // FIX_BUG_15451
  755. // Globals to support sound event command line parameters.
  756. #define MAX_SND_EVNT_CMD_LINE 32
  757. TCHAR gszCmdLineApp[MAX_SND_EVNT_CMD_LINE];
  758. TCHAR gszCmdLineEvent[MAX_SND_EVNT_CMD_LINE];
  759. /*==========================================================================*/
  760. LONG CPlApplet(
  761. HWND hCPlWnd,
  762. UINT Msg,
  763. LPARAM lParam1,
  764. LPARAM lParam2)
  765. {
  766. switch (Msg)
  767. {
  768. case CPL_INIT:
  769. wHelpMessage = RegisterWindowMessage(TEXT("ShellHelp"));
  770. DPF_T("*CPL_INIT*");
  771. g_cRefCnt++;
  772. return (LRESULT)TRUE;
  773. case CPL_GETCOUNT:
  774. return (LRESULT)1;
  775. case CPL_INQUIRE:
  776. DPF_T("*CPL_INQUIRE*");
  777. switch (lParam1)
  778. {
  779. case 0:
  780. ((LPCPLINFO)lParam2)->idIcon = IDI_MMICON;
  781. ((LPCPLINFO)lParam2)->idName = IDS_MMNAME;
  782. ((LPCPLINFO)lParam2)->idInfo = IDS_MMINFO;
  783. break;
  784. default:
  785. return FALSE;
  786. }
  787. ((LPCPLINFO)lParam2)->lData = 0L;
  788. return TRUE;
  789. case CPL_NEWINQUIRE:
  790. switch (lParam1)
  791. {
  792. case 0:
  793. ((LPNEWCPLINFO)lParam2)->hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_MMICON));
  794. LoadString(ghInstance, IDS_MMNAME, ((LPNEWCPLINFO)lParam2)->szName, sizeof(((LPNEWCPLINFO)lParam2)->szName)/sizeof(TCHAR));
  795. LoadString(ghInstance, IDS_MMINFO, ((LPNEWCPLINFO)lParam2)->szInfo, sizeof(((LPNEWCPLINFO)lParam2)->szInfo)/sizeof(TCHAR));
  796. break;
  797. default:
  798. return FALSE;
  799. }
  800. ((LPNEWCPLINFO)lParam2)->dwHelpContext = 0;
  801. ((LPNEWCPLINFO)lParam2)->dwSize = sizeof(NEWCPLINFO);
  802. ((LPNEWCPLINFO)lParam2)->lData = 0L;
  803. ((LPNEWCPLINFO)lParam2)->szHelpFile[0] = 0;
  804. return TRUE;
  805. case CPL_DBLCLK:
  806. DPF_T("* CPL_DBLCLICK*");
  807. // Do the applet thing.
  808. switch (lParam1)
  809. {
  810. case 0:
  811. // Check for obsolete command line (see comments
  812. // under CPL_STARTWPARAMS)
  813. if ((-1) == g_nStartPage) break;
  814. #ifdef FIX_BUG_15451
  815. lstrcpy (szDriverWhichNeedsSettings, TEXT(""));
  816. cplMMDoubleClick(hCPlWnd, g_nStartPage);
  817. #else // FIX_BUG_15451
  818. cplMMDoubleClick(hCPlWnd);
  819. #endif // FIX_BUG_15451
  820. break;
  821. }
  822. break;
  823. case CPL_STARTWPARMS:
  824. switch (lParam1)
  825. {
  826. case 0:
  827. if (lParam2 && *((LPTSTR)lParam2))
  828. {
  829. TCHAR c;
  830. c = *((LPTSTR)lParam2);
  831. if (c > TEXT('0') && c < TEXT('5'))
  832. {
  833. g_nStartPage = c - TEXT('0');
  834. break;
  835. }
  836. // The "S" command line was used on Windows 98 and Windows 98
  837. // SE. The command line was written to the Active Setup
  838. // registry to run logic to setup preferred devices on a
  839. // specific PnP device instance. It is obsolete and handled in
  840. // winmm.dll itself. This cpl should do nothing for this
  841. // command line.
  842. if ((c == TEXT('S')) || (c == TEXT('s'))) {
  843. g_nStartPage = (-1);
  844. break;
  845. }
  846. }
  847. g_nStartPage = 0;
  848. break;
  849. // For sound events, the passed in parameter indicates a module
  850. // name and event. If a name is passed only show it's sound events.
  851. // If a name and event are passed only show the event.
  852. /* case 1:
  853. if (lParam2 && *((LPTSTR)lParam2))
  854. {
  855. TCHAR *psz;
  856. if ((psz = wcschr((LPTSTR)lParam2, TEXT(','))) != NULL)
  857. {
  858. *psz++ = TEXT('\0');
  859. wcsncpy(gszCmdLineEvent, psz, MAX_SND_EVNT_CMD_LINE/sizeof(TCHAR));
  860. gszCmdLineEvent[MAX_SND_EVNT_CMD_LINE-sizeof(TCHAR)] = TEXT('\0');
  861. }
  862. wcsncpy(gszCmdLineApp, (LPTSTR)lParam2,
  863. MAX_SND_EVNT_CMD_LINE/sizeof(TCHAR));
  864. gszCmdLineApp[MAX_SND_EVNT_CMD_LINE-sizeof(TCHAR)] = TEXT('\0');
  865. }
  866. break; */
  867. }
  868. break;
  869. case CPL_EXIT:
  870. DPF_T("* CPL_EXIT*");
  871. g_cRefCnt--;
  872. break;
  873. }
  874. return 0;
  875. }
  876. void PASCAL ShowPropSheet(LPCTSTR pszTitle,
  877. DLGPROC pfnDialog,
  878. UINT idTemplate,
  879. HWND hWndParent,
  880. LPTSTR pszCaption,
  881. LPARAM lParam)
  882. {
  883. PROPSHEETHEADER psh;
  884. HPROPSHEETPAGE hpsp[MAXPAGES];
  885. InitPSH(&psh,hWndParent,pszCaption,hpsp);
  886. AddPage(&psh, pszTitle, pfnDialog, idTemplate, lParam);
  887. PropertySheet(&psh);
  888. }
  889. void PASCAL ShowMidiPropSheet(LPPROPSHEETHEADER ppshExt,
  890. LPCTSTR pszTitle,
  891. HWND hWndParent,
  892. short iMidiPropType,
  893. LPTSTR pszCaption,
  894. HTREEITEM hti,
  895. LPARAM lParam1,
  896. LPARAM lParam2)
  897. {
  898. PROPSHEETHEADER psh;
  899. LPPROPSHEETHEADER ppsh;
  900. HPROPSHEETPAGE hpsp[MAXPAGES];
  901. static EXTPROPSHEETCBPARAM cbp;
  902. if (!ppshExt)
  903. {
  904. ppsh = &psh;
  905. InitPSH(ppsh,hWndParent,pszCaption,hpsp);
  906. }
  907. else
  908. ppsh = ppshExt;
  909. cbp.lParam1 = lParam1;
  910. cbp.lParam2 = lParam2;
  911. cbp.hti = hti;
  912. cbp.ppsh = ppsh;
  913. if (iMidiPropType == MIDI_CLASS_PROP)
  914. {
  915. if (AddMidiPages((LPVOID)pszTitle, MMExtPropSheetCallback, (LPARAM)&cbp))
  916. {
  917. PropertySheet(ppsh);
  918. }
  919. }
  920. else if (iMidiPropType == MIDI_INSTRUMENT_PROP)
  921. {
  922. if (AddInstrumentPages((LPVOID)pszTitle, MMExtPropSheetCallback, (LPARAM)&cbp))
  923. {
  924. PropertySheet(ppsh);
  925. }
  926. }
  927. else
  928. {
  929. if (AddDevicePages((LPVOID)pszTitle, MMExtPropSheetCallback, (LPARAM)&cbp))
  930. {
  931. PropertySheet(ppsh);
  932. }
  933. }
  934. }
  935. void PASCAL ShowWithMidiDevPropSheet(LPCTSTR pszTitle,
  936. DLGPROC pfnDialog,
  937. UINT idTemplate,
  938. HWND hWndParent,
  939. LPTSTR pszCaption,
  940. HTREEITEM hti,
  941. LPARAM lParam, LPARAM lParamExt1, LPARAM lParamExt2)
  942. {
  943. PROPSHEETHEADER psh;
  944. HPROPSHEETPAGE hpsp[MAXPAGES];
  945. InitPSH(&psh,hWndParent,pszCaption,hpsp);
  946. AddPage(&psh, pszTitle, pfnDialog, idTemplate, lParam);
  947. PropertySheet(&psh);
  948. // Disabling the details sheet - obsolete 01/10/2001
  949. //ShowMidiPropSheet(&psh, pszCaption, hWndParent,MIDI_DEVICE_PROP,pszCaption,hti,lParamExt1,lParamExt2);
  950. }
  951. BOOL WINAPI ShowMMCPLPropertySheetW(HWND hwndParent, LPCTSTR pszPropSheetID, LPTSTR pszTabName, LPTSTR pszCaption)
  952. {
  953. DLGPROC pfnDlgProc;
  954. UINT idTemplate;
  955. HWND hwndP;
  956. PROPSHEETHEADER psh;
  957. HPROPSHEETPAGE hpsp[MAXPAGES];
  958. if (GetWindowLongPtr(hwndParent, GWL_EXSTYLE) & WS_EX_TOPMOST)
  959. hwndP = NULL;
  960. else
  961. hwndP = hwndParent;
  962. InitPSH(&psh,hwndP,pszCaption,hpsp);
  963. psh.dwFlags = 0;
  964. if (!lstrcmpi(pszPropSheetID, cszAUDIO))
  965. {
  966. pfnDlgProc = AudioDlg;
  967. idTemplate = AUDIODLG;
  968. goto ShowSheet;
  969. }
  970. if (!lstrcmpi(pszPropSheetID, cszVOICE))
  971. {
  972. pfnDlgProc = VoiceDlg;
  973. idTemplate = VOICEDLG;
  974. goto ShowSheet;
  975. }
  976. if (!lstrcmpi(pszPropSheetID, cszVOLUME))
  977. {
  978. pfnDlgProc = VolumeDlg;
  979. idTemplate = IDD_VOLUME;
  980. goto ShowSheet;
  981. }
  982. if (!lstrcmpi(pszPropSheetID, cszVIDEO))
  983. {
  984. pfnDlgProc = VideoDlg;
  985. idTemplate = VIDEODLG;
  986. goto ShowSheet;
  987. }
  988. if (!lstrcmpi(pszPropSheetID, cszCDAUDIO))
  989. {
  990. pfnDlgProc = CD_HardwareDlgProc;
  991. idTemplate = HWDLG;
  992. goto ShowSheet;
  993. }
  994. if (!lstrcmpi(pszPropSheetID, cszMIDI))
  995. {
  996. /*
  997. static EXTPROPSHEETCBPARAM cbpMIDI;
  998. cbpMIDI.ppsh = &psh;
  999. cbpMIDI.hti = NULL;
  1000. cbpMIDI.lParam1 = (LPARAM)pszPropSheetID;
  1001. cbpMIDI.lParam2 = (LPARAM)pszTabName;
  1002. AddSimpleMidiPages((LPVOID)pszTabName, MMExtPropSheetCallback, (LPARAM)&cbpMIDI);
  1003. PropertySheet(&psh);
  1004. return TRUE;
  1005. */
  1006. pfnDlgProc = AudioDlg;
  1007. idTemplate = AUDIODLG;
  1008. goto ShowSheet;
  1009. }
  1010. return FALSE;
  1011. ShowSheet:
  1012. AddPage(&psh, pszTabName, pfnDlgProc, idTemplate, (LPARAM)NULL);
  1013. PropertySheet(&psh);
  1014. return TRUE;
  1015. }
  1016. BOOL WINAPI ShowMMCPLPropertySheet(HWND hwndParent, LPCSTR pszPropSheetID, LPSTR pszTabName, LPSTR pszCaption)
  1017. {
  1018. DLGPROC pfnDlgProc;
  1019. UINT idTemplate;
  1020. HWND hwndP;
  1021. PROPSHEETHEADER psh;
  1022. HPROPSHEETPAGE hpsp[MAXPAGES];
  1023. TCHAR szPropSheetID[MAX_PATH];
  1024. TCHAR szTabName[MAX_PATH];
  1025. TCHAR szCaption[MAX_PATH];
  1026. //convert three params into UNICODE strings
  1027. MultiByteToWideChar( GetACP(), 0, pszPropSheetID, -1, szPropSheetID, sizeof(szPropSheetID) / sizeof(TCHAR) );
  1028. MultiByteToWideChar( GetACP(), 0, pszTabName, -1, szTabName, sizeof(szTabName) / sizeof(TCHAR) );
  1029. MultiByteToWideChar( GetACP(), 0, pszCaption, -1, szCaption, sizeof(szCaption) / sizeof(TCHAR) );
  1030. return (ShowMMCPLPropertySheetW(hwndParent,szPropSheetID,szTabName,szCaption));
  1031. }
  1032. //allows you to show control panel from RUNDLL32
  1033. DWORD WINAPI ShowFullControlPanel(HWND hwndP, HINSTANCE hInst, LPTSTR szCmd, int nShow)
  1034. {
  1035. cplMMDoubleClick(hwndP, 0);
  1036. return 0;
  1037. }
  1038. DWORD WINAPI ShowAudioPropertySheet(HWND hwndP, HINSTANCE hInst, LPTSTR szCmd, int nShow)
  1039. {
  1040. TCHAR szAudio[MAXLNAME];
  1041. TCHAR szAudioProperties[MAXLNAME];
  1042. char mbcszAUDIO[MAXLNAME];
  1043. char mbszAudio[MAXLNAME];
  1044. char mbszAudioProperties[MAXLNAME];
  1045. HWND hwndPrev;
  1046. LoadString(ghInstance, IDS_AUDIOPROPERTIES, szAudioProperties, sizeof(szAudioProperties)/sizeof(TCHAR));
  1047. hwndPrev = FindWindow(NULL,szAudioProperties);
  1048. if (hwndPrev)
  1049. {
  1050. SetForegroundWindow(hwndPrev);
  1051. }
  1052. else
  1053. {
  1054. LoadString(ghInstance, IDS_WAVE_HEADER, szAudio, sizeof(szAudio)/sizeof(TCHAR));
  1055. ShowMMCPLPropertySheetW(hwndP, cszAUDIO, szAudio, szAudioProperties);
  1056. }
  1057. return 0;
  1058. }
  1059. DWORD WINAPI mmseRunOnce(HWND hwnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nShow)
  1060. {
  1061. // This is an obsolete function formerly used to migrate
  1062. // registry and driver information. We leave the export
  1063. // in place in case an old installation has left a RunOnce
  1064. // command in place to execute this function.
  1065. return 0;
  1066. }
  1067. DWORD WINAPI mmseRunOnceW(HWND hwnd, HINSTANCE hInst, LPWSTR lpwszCmdLine, int nShow)
  1068. {
  1069. // This is an obsolete function formerly used to migrate
  1070. // registry and driver information. We leave the export
  1071. // in place in case an old installation has left a RunOnce
  1072. // command in place to execute this function.
  1073. return 0;
  1074. }
  1075. extern BOOL DriversDllInitialize (IN PVOID, IN DWORD, IN PCONTEXT OPTIONAL);
  1076. BOOL DllInitialize (IN PVOID hInstance,
  1077. IN DWORD ulReason,
  1078. IN PCONTEXT pctx OPTIONAL)
  1079. {
  1080. // patch in the old DRIVERS.DLL code (see DRIVERS.C)
  1081. //
  1082. DriversDllInitialize (hInstance, ulReason, pctx);
  1083. if (ulReason == DLL_PROCESS_ATTACH)
  1084. {
  1085. ++g_cProcesses;
  1086. ghInstance = hInstance;
  1087. DisableThreadLibraryCalls(hInstance);
  1088. return TRUE;
  1089. }
  1090. if (ulReason == DLL_PROCESS_DETACH)
  1091. {
  1092. --g_cProcesses;
  1093. return TRUE;
  1094. }
  1095. return TRUE;
  1096. }
  1097. DWORD
  1098. WINAPI
  1099. MediaClassInstaller(
  1100. IN DI_FUNCTION InstallFunction,
  1101. IN HDEVINFO DeviceInfoSet,
  1102. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. This routine acts as the class installer for Media devices.
  1107. Arguments:
  1108. InstallFunction - Specifies the device installer function code indicating
  1109. the action being performed.
  1110. DeviceInfoSet - Supplies a handle to the device information set being
  1111. acted upon by this install action.
  1112. DeviceInfoData - Optionally, supplies the address of a device information
  1113. element being acted upon by this install action.
  1114. Return Value:
  1115. If this function successfully completed the requested action, the return
  1116. value is NO_ERROR.
  1117. If the default behavior is to be performed for the requested action, the
  1118. return value is ERROR_DI_DO_DEFAULT.
  1119. If an error occurred while attempting to perform the requested action, a
  1120. Win32 error code is returned.
  1121. --*/
  1122. {
  1123. DWORD dwRet=ERROR_DI_DO_DEFAULT;
  1124. switch (InstallFunction)
  1125. {
  1126. case DIF_SELECTBESTCOMPATDRV:
  1127. dwRet = Media_SelectBestCompatDrv(DeviceInfoSet,DeviceInfoData);
  1128. break;
  1129. case DIF_ALLOW_INSTALL:
  1130. dwRet = Media_AllowInstall(DeviceInfoSet,DeviceInfoData);
  1131. break;
  1132. case DIF_INSTALLDEVICE :
  1133. dwRet = Media_InstallDevice(DeviceInfoSet, DeviceInfoData);
  1134. break;
  1135. case DIF_REMOVE:
  1136. dwRet = Media_RemoveDevice(DeviceInfoSet,DeviceInfoData);
  1137. break;
  1138. case DIF_SELECTDEVICE:
  1139. dwRet = Media_SelectDevice(DeviceInfoSet,DeviceInfoData);
  1140. break;
  1141. case DIF_FIRSTTIMESETUP:
  1142. // Fall through
  1143. case DIF_DETECT:
  1144. dwRet = Media_MigrateLegacy(DeviceInfoSet,DeviceInfoData);
  1145. break;
  1146. }
  1147. return dwRet;
  1148. }
  1149. DWORD WINAPI mmWOW64MediaInstallDevice(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData)
  1150. {
  1151. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  1152. HWND hWnd;
  1153. //
  1154. // Get the device install parameters, so we'll know what parent window to use for any
  1155. // UI that occurs during configuration of this device.
  1156. //
  1157. DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  1158. if (SetupDiGetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams))
  1159. {
  1160. hWnd = DeviceInstallParams.hwndParent;
  1161. }
  1162. else
  1163. {
  1164. hWnd = NULL;
  1165. }
  1166. //
  1167. // The INF will have created a "Drivers" subkey under the device's software key.
  1168. // This tree, in turn, contains subtrees for each type of driver (aux, midi, etc.)
  1169. // applicable for this device. We must now traverse this tree, and create entries
  1170. // in Drivers32 for each function alias.
  1171. //
  1172. return InstallDriversForPnPDevice(hWnd, DeviceInfoSet, DeviceInfoData);
  1173. }
  1174. DWORD WINAPI mmWOW64MediaRemoveDevice(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData)
  1175. {
  1176. if( RemoveDriver(DeviceInfoSet, DeviceInfoData) )
  1177. {
  1178. return NO_ERROR;
  1179. }
  1180. else
  1181. {
  1182. return ERROR_BAD_DRIVER;
  1183. }
  1184. }
  1185. DWORD WINAPI mmWOW64MediaClassInstallerA(HWND hwnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nShow)
  1186. /*++
  1187. Routine Description:
  1188. This routine acts as a thunking layer for calling the 32-bit
  1189. installation functions from the 64-bit setup via RunDLL32.exe.
  1190. Arguments:
  1191. hwnd - not used
  1192. hInst - not used
  1193. lpwszCmdLine - command line arguments: "Instance ID (string)" DI_FUNCTION (as an integer)
  1194. nShow - not used
  1195. Return Value:
  1196. If this function successfully completed the requested action, the return
  1197. value is NO_ERROR.
  1198. If an error occurred while attempting to perform the requested action, a
  1199. Win32 error code is returned.
  1200. --*/
  1201. {
  1202. LPSTR strInstanceID = NULL;
  1203. LPSTR strInstallIndex = NULL;
  1204. DWORD dwInstallIndex = 0;
  1205. LPSTR strTemp = NULL;
  1206. HDEVINFO DeviceInfoSet = NULL;
  1207. SP_DEVINFO_DATA DeviceInfoData;
  1208. DWORD dwResult = NO_ERROR;
  1209. // Find first quote
  1210. strTemp = strchr( lpszCmdLine, '\"' );
  1211. if( !strTemp )
  1212. {
  1213. return ERROR_INVALID_PARAMETER;
  1214. }
  1215. // Instance ID
  1216. // Skip first quote
  1217. strInstanceID = ++strTemp;
  1218. // Find second quote
  1219. strTemp = strchr( strTemp, '\"' );
  1220. if( !strTemp )
  1221. {
  1222. return ERROR_INVALID_PARAMETER;
  1223. }
  1224. // NULL-terminate the InstanceID
  1225. *strTemp = 0;
  1226. // Install Index
  1227. // Skip the NULL
  1228. strInstallIndex = ++strTemp;
  1229. // Convert the installation index
  1230. dwInstallIndex = atoi( strInstallIndex );
  1231. // Create a device handle
  1232. DeviceInfoSet = SetupDiCreateDeviceInfoList( NULL, NULL );
  1233. if( INVALID_HANDLE_VALUE == DeviceInfoSet )
  1234. {
  1235. return ERROR_NOT_ENOUGH_MEMORY;
  1236. }
  1237. // Create the device info structure
  1238. ZeroMemory( &DeviceInfoData, sizeof(SP_DEVINFO_DATA) );
  1239. DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  1240. if( 0 == SetupDiOpenDeviceInfoA( DeviceInfoSet, strInstanceID, NULL, 0, &DeviceInfoData ) )
  1241. {
  1242. dwResult = GetLastError();
  1243. }
  1244. // Do the installation task
  1245. if( NO_ERROR == dwResult )
  1246. {
  1247. switch( dwInstallIndex )
  1248. {
  1249. case DIF_INSTALLDEVICE:
  1250. dwResult = mmWOW64MediaInstallDevice(DeviceInfoSet, &DeviceInfoData);
  1251. break;
  1252. case DIF_REMOVE:
  1253. dwResult = mmWOW64MediaRemoveDevice(DeviceInfoSet, &DeviceInfoData);
  1254. break;
  1255. default:
  1256. dwResult = ERROR_INVALID_PARAMETER;
  1257. break;
  1258. }
  1259. }
  1260. SetupDiDestroyDeviceInfoList( DeviceInfoSet );
  1261. return dwResult;
  1262. }