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.

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