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.

2063 lines
49 KiB

  1. // File: wizard.cpp
  2. #include "precomp.h"
  3. #include <vfw.h>
  4. #include <ulsreg.h>
  5. #include "call.h"
  6. #include "ulswizrd.h"
  7. #include "ConfWnd.h"
  8. #include "ConfCpl.h"
  9. #include "mrulist.h"
  10. #include "conf.h"
  11. #include "setupdd.h"
  12. #include "vidwiz.h"
  13. #include "dstest.h"
  14. #include "splash.h"
  15. #include "nmmkcert.h"
  16. #include "confroom.h" // for GetConfRoom
  17. #include "FnObjs.h"
  18. #include "ConfPolicies.h"
  19. #include "SysPol.h"
  20. #include "confUtil.h"
  21. #include "shlWAPI.h"
  22. #include "help_ids.h"
  23. extern VOID SaveDefaultCodecSettings(UINT uBandWidth);
  24. INT_PTR CALLBACK ShortcutWizDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  25. // from ulscpl.cpp
  26. VOID FixServerDropList(HWND hdlg, int id, LPTSTR pszServer, UINT cchMax);
  27. static const TCHAR g_szRegOwner[] = WIN_REGKEY_REGOWNER; // concatenated string of first name + last name
  28. static const TCHAR g_szClientFld[] = ULS_REGISTRY TEXT ("\\") ULS_REGFLD_CLIENT;
  29. static const TCHAR g_szFirstName[] = ULS_REGKEY_FIRST_NAME;
  30. static const TCHAR g_szLastName[] = ULS_REGKEY_LAST_NAME;
  31. static const TCHAR g_szEmailName[] = ULS_REGKEY_EMAIL_NAME;
  32. static const TCHAR g_szLocation[] = ULS_REGKEY_LOCATION;
  33. static const TCHAR g_szComments[] = ULS_REGKEY_COMMENTS;
  34. static const TCHAR g_szServerName[] = ULS_REGKEY_SERVER_NAME;
  35. static const TCHAR g_szDontPublish[] = ULS_REGKEY_DONT_PUBLISH;
  36. static const TCHAR g_szResolveName[] = ULS_REGKEY_RESOLVE_NAME; // concatenated string of uls://servername/emailname
  37. static const TCHAR g_szUserName[] = ULS_REGKEY_USER_NAME; // concatenated string of first name + last name
  38. // These functions are implemented below:
  39. static INT_PTR APIENTRY IntroWiz(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  40. static INT_PTR APIENTRY AppSharingWiz(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  41. static INT_PTR APIENTRY BandwidthWiz(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  42. static BOOL NeedAudioWizard(LPLONG plSoundCaps, BOOL fForce);
  43. static BOOL CheckForNames(ULS_CONF *pConf);
  44. static void FillWizardPages ( PROPSHEETPAGE *pPage, LPARAM lParam );
  45. struct INTRO_PAGE_CONFIG
  46. {
  47. BOOL * fContinue;
  48. BOOL fAllowBack;
  49. };
  50. BOOL g_fSilentWizard = FALSE;
  51. // This holdn the user info page HWND...
  52. static HWND s_hDlgUserInfo = NULL;
  53. static HWND s_hDlgGKSettings = NULL;
  54. class IntroWiz
  55. {
  56. public:
  57. // The order of the pages
  58. // Make sure to change the order the pages are created at the same time
  59. // you change this
  60. enum
  61. {
  62. Intro,
  63. AppSharing,
  64. ULSFirst,
  65. ULSLast,
  66. Bandwidth,
  67. Video,
  68. Shortcuts,
  69. AudioFirst,
  70. Count
  71. } ;
  72. static void InitPages()
  73. {
  74. // Init to NULL before adding any pages
  75. for (int i=0; i<Count; ++i)
  76. {
  77. g_idWizOrder[i] = 0;
  78. }
  79. }
  80. static void SetPage(UINT nPage, UINT_PTR id)
  81. {
  82. g_idWizOrder[nPage] = id;
  83. }
  84. static UINT_PTR GetPrevPage(UINT nPageCur)
  85. {
  86. if (0 == nPageCur)
  87. {
  88. return(0);
  89. }
  90. for (int i=nPageCur-1; i>=1; --i)
  91. {
  92. if (0 != g_idWizOrder[i])
  93. {
  94. break;
  95. }
  96. }
  97. return(g_idWizOrder[i]);
  98. }
  99. static UINT_PTR GetNextPage(UINT nPageCur)
  100. {
  101. if (Count-1 <= nPageCur)
  102. {
  103. return(0);
  104. }
  105. for (int i=nPageCur+1; i<Count-1; ++i)
  106. {
  107. if (0 != g_idWizOrder[i])
  108. {
  109. break;
  110. }
  111. }
  112. return(g_idWizOrder[i]);
  113. }
  114. static BOOL HandleWizNotify(HWND hPage, NMHDR *pHdr, UINT nPageCur)
  115. {
  116. switch(pHdr->code)
  117. {
  118. case PSN_SETACTIVE:
  119. InitBackNext(hPage, nPageCur);
  120. if (g_fSilentWizard)
  121. {
  122. PropSheet_PressButton(GetParent(hPage), PSBTN_NEXT);
  123. }
  124. break;
  125. case PSN_WIZBACK:
  126. {
  127. UINT_PTR iPrev = GetPrevPage(nPageCur);
  128. SetWindowLongPtr(hPage, DWLP_MSGRESULT, iPrev);
  129. break;
  130. }
  131. case PSN_WIZNEXT:
  132. {
  133. UINT_PTR iPrev = GetNextPage(nPageCur);
  134. SetWindowLongPtr(hPage, DWLP_MSGRESULT, iPrev);
  135. break;
  136. }
  137. default:
  138. return(FALSE);
  139. }
  140. return(TRUE);
  141. }
  142. private:
  143. static UINT_PTR g_idWizOrder[Count];
  144. static void InitBackNext(HWND hPage, UINT nPageCur)
  145. {
  146. DWORD dwFlags = 0;
  147. if (0 != nPageCur && 0 != GetPrevPage(nPageCur))
  148. {
  149. dwFlags |= PSWIZB_BACK;
  150. }
  151. if (Count-1 != nPageCur && 0 != GetNextPage(nPageCur))
  152. {
  153. dwFlags |= PSWIZB_NEXT;
  154. }
  155. else
  156. {
  157. dwFlags |= PSWIZB_FINISH;
  158. }
  159. PropSheet_SetWizButtons(::GetParent(hPage), dwFlags);
  160. }
  161. } ;
  162. UINT_PTR IntroWiz::g_idWizOrder[Count];
  163. UINT_PTR GetPageBeforeULS()
  164. {
  165. return(IntroWiz::GetPrevPage(IntroWiz::ULSFirst));
  166. }
  167. UINT_PTR GetPageBeforeVideoWiz()
  168. {
  169. return(IntroWiz::GetPrevPage(IntroWiz::Video));
  170. }
  171. UINT_PTR GetPageBeforeAudioWiz()
  172. {
  173. return(IntroWiz::GetPrevPage(IntroWiz::AudioFirst));
  174. }
  175. UINT_PTR GetPageAfterVideo()
  176. {
  177. return(IntroWiz::GetNextPage(IntroWiz::Video));
  178. }
  179. UINT_PTR GetPageAfterULS()
  180. {
  181. return(IntroWiz::GetNextPage(IntroWiz::ULSLast));
  182. }
  183. void HideWizard(HWND hwnd)
  184. {
  185. SetWindowPos(hwnd, NULL, -1000, -1000, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
  186. }
  187. void ShowWizard(HWND hwnd)
  188. {
  189. CenterWindow(hwnd, HWND_DESKTOP);
  190. g_fSilentWizard = FALSE;
  191. PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
  192. }
  193. /* F I L L I N P R O P E R T Y P A G E */
  194. /*-------------------------------------------------------------------------
  195. %%Function: FillInPropertyPage
  196. Fill in the given PROPSHEETPAGE structure.
  197. -------------------------------------------------------------------------*/
  198. VOID FillInPropertyPage(PROPSHEETPAGE* psp, int idDlg,
  199. DLGPROC pfnDlgProc, LPARAM lParam, LPCTSTR pszProc)
  200. {
  201. // Clear and set the size of the PROPSHEETPAGE
  202. InitStruct(psp);
  203. ASSERT(0 == psp->dwFlags); // No special flags.
  204. ASSERT(NULL == psp->pszIcon); // Don't use a special icon in the caption bar.
  205. psp->hInstance = ::GetInstanceHandle();
  206. psp->pszTemplate = MAKEINTRESOURCE(idDlg); // The dialog box template to use.
  207. psp->pfnDlgProc = pfnDlgProc; // The dialog procedure that handles this page.
  208. psp->pszTitle = pszProc; // The title for this page.
  209. psp->lParam = lParam; // Special application-specific data.
  210. }
  211. static const UINT NOVALSpecified = 666;
  212. UINT GetBandwidth()
  213. {
  214. RegEntry reAudio(AUDIO_KEY, HKEY_CURRENT_USER);
  215. return(reAudio.GetNumber(REGVAL_TYPICALBANDWIDTH, NOVALSpecified ));
  216. }
  217. void SetBandwidth(UINT uBandwidth)
  218. {
  219. RegEntry reAudio(AUDIO_KEY, HKEY_CURRENT_USER);
  220. reAudio.SetValue(REGVAL_TYPICALBANDWIDTH, uBandwidth);
  221. }
  222. HRESULT StartRunOnceWizard(LPLONG plSoundCaps, BOOL fForce, BOOL fVisible)
  223. {
  224. LPPROPSHEETPAGE pAudioPages = NULL;
  225. UINT nNumAudioPages = 0;
  226. PWIZCONFIG pAudioConfig;
  227. CULSWizard* pIWizard = NULL;
  228. LPPROPSHEETPAGE pULSPages = NULL;
  229. DWORD dwNumULSPages = 0;
  230. ULS_CONF* pulsConf = NULL;
  231. UINT uOldBandwidth = 0;
  232. UINT uBandwidth = 0;
  233. int idAppSharingIntroWiz = 0;
  234. BOOL fULSWiz = FALSE;
  235. BOOL fAudioWiz = FALSE;
  236. BOOL fVideoWiz = FALSE;
  237. BOOL fVidWizInit = FALSE;
  238. HRESULT hrRet = E_FAIL;
  239. g_fSilentWizard = !fVisible;
  240. ASSERT(plSoundCaps);
  241. BOOL fNeedUlsWizard = FALSE;
  242. BOOL fNeedVideoWizard = FALSE;
  243. BOOL fNeedAudioWizard = NeedAudioWizard(plSoundCaps, fForce);
  244. if (fNeedAudioWizard)
  245. {
  246. if (GetAudioWizardPages(RUNDUE_NEVERBEFORE,
  247. WAVE_MAPPER,
  248. &pAudioPages,
  249. &pAudioConfig,
  250. &nNumAudioPages))
  251. {
  252. fAudioWiz = TRUE;
  253. }
  254. else
  255. {
  256. ERROR_OUT(("could not get AudioWiz pages"));
  257. }
  258. }
  259. fVidWizInit = InitVidWiz();
  260. if (fVidWizInit == FALSE)
  261. {
  262. fVideoWiz = FALSE;
  263. WARNING_OUT(("InitVidWiz failed"));
  264. }
  265. else
  266. {
  267. fNeedVideoWizard = NeedVideoPropPage(fForce);
  268. fVideoWiz = fNeedVideoWizard;
  269. }
  270. if (NULL != (pIWizard = new CULSWizard))
  271. {
  272. ASSERT (pIWizard);
  273. // BUGBUG: not checking return value:
  274. HRESULT hr = pIWizard->GetWizardPages (&pULSPages, &dwNumULSPages, &pulsConf);
  275. if (SUCCEEDED(hr))
  276. {
  277. ASSERT(pulsConf);
  278. TRACE_OUT(("ULS_CONF from UlsGetConfiguration:"));
  279. TRACE_OUT(("\tdwFlags: 0x%08x", pulsConf->dwFlags));
  280. TRACE_OUT(("\tszServerName: >%s<", pulsConf->szServerName));
  281. TRACE_OUT(("\tszUserName: >%s<", pulsConf->szUserName));
  282. TRACE_OUT(("\tszEmailName: >%s<", pulsConf->szEmailName));
  283. fNeedUlsWizard = ((pulsConf->dwFlags &
  284. (ULSCONF_F_EMAIL_NAME | ULSCONF_F_FIRST_NAME | ULSCONF_F_LAST_NAME)) !=
  285. (ULSCONF_F_EMAIL_NAME | ULSCONF_F_FIRST_NAME | ULSCONF_F_LAST_NAME));
  286. // Don't bother with the ULS wizard if we have all the information
  287. if ((!fForce) && !fNeedUlsWizard)
  288. {
  289. // We have all of the necessary names
  290. hrRet = S_OK;
  291. // release the pages we won't be needing them
  292. pIWizard->ReleaseWizardPages (pULSPages);
  293. delete pIWizard;
  294. pIWizard = NULL;
  295. dwNumULSPages = 0;
  296. }
  297. else
  298. {
  299. // some information is not available - we need to run the
  300. // wizard...
  301. //SS: if for some reason the user name is not set
  302. //even though the others are set??
  303. fULSWiz = TRUE;
  304. if (::GetDefaultName(pulsConf->szUserName, CCHMAX(pulsConf->szUserName)))
  305. {
  306. // We have added a default name, so mark that structure
  307. // member as valid:
  308. pulsConf->dwFlags |= ULSCONF_F_USER_NAME;
  309. }
  310. }
  311. }
  312. }
  313. else
  314. {
  315. ERROR_OUT(("CreateUlsWizardInterface() failed!"));
  316. }
  317. // Determine if we need to display the app sharing info page, and if
  318. // so which one.
  319. if (::IsWindowsNT() && !g_fNTDisplayDriverEnabled)
  320. {
  321. idAppSharingIntroWiz = ::CanInstallNTDisplayDriver()
  322. ? IDD_APPSHARINGWIZ_HAVESP
  323. : IDD_APPSHARINGWIZ_NEEDSP;
  324. }
  325. if ((fULSWiz || fAudioWiz || fVideoWiz))
  326. {
  327. UINT nNumPages = 0;
  328. // Now fill in remaining PROPSHEETHEADER structures:
  329. PROPSHEETHEADER psh;
  330. InitStruct(&psh);
  331. psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW;
  332. psh.hInstance = ::GetInstanceHandle();
  333. ASSERT(0 == psh.nStartPage);
  334. // alocate enough space for all pages
  335. DWORD nPages = dwNumULSPages + nNumAudioPages
  336. + ( (0 != idAppSharingIntroWiz) ? 1 : 0 )
  337. + (fVideoWiz ? 1 : 0)
  338. + 2 // intro page & bandwidth page
  339. + 1 // shortcuts page
  340. ;
  341. LPPROPSHEETPAGE ppsp = new PROPSHEETPAGE[ nPages ];
  342. if (NULL != ppsp)
  343. {
  344. IntroWiz::InitPages();
  345. BOOL fContinue = TRUE;
  346. INTRO_PAGE_CONFIG ipcIntro = { &fContinue, FALSE };
  347. INTRO_PAGE_CONFIG ipcAppSharing = { &fContinue, TRUE };
  348. if (fULSWiz)
  349. {
  350. // Insert the intro page:
  351. FillInPropertyPage(&ppsp[nNumPages++], IDD_INTROWIZ,
  352. IntroWiz, (LPARAM) &ipcIntro);
  353. IntroWiz::SetPage(IntroWiz::Intro, IDD_INTROWIZ);
  354. // Insert an NT application page, if necessary. It uses the
  355. // same dialog proc as the intro page.
  356. if (0 != idAppSharingIntroWiz)
  357. {
  358. FillInPropertyPage(&ppsp[nNumPages++], idAppSharingIntroWiz,
  359. AppSharingWiz, (LPARAM) &ipcAppSharing);
  360. IntroWiz::SetPage(IntroWiz::AppSharing, idAppSharingIntroWiz);
  361. }
  362. ASSERT(pulsConf);
  363. pulsConf->dwFlags |= (ULSWIZ_F_SHOW_BACK |
  364. ((fAudioWiz || fVideoWiz) ? ULSWIZ_F_NO_FINISH : 0));
  365. ::CopyMemory( &(ppsp[nNumPages]),
  366. pULSPages,
  367. dwNumULSPages * sizeof(PROPSHEETPAGE));
  368. IntroWiz::SetPage(IntroWiz::ULSFirst,
  369. reinterpret_cast<UINT_PTR>(pULSPages[0].pszTemplate));
  370. IntroWiz::SetPage(IntroWiz::ULSLast,
  371. reinterpret_cast<UINT_PTR>(pULSPages[dwNumULSPages-1].pszTemplate));
  372. nNumPages += dwNumULSPages;
  373. uBandwidth = uOldBandwidth = GetBandwidth();
  374. if( NOVALSpecified == uBandwidth )
  375. {
  376. FillInPropertyPage(&ppsp[nNumPages++], IDD_BANDWIDTHWIZ,
  377. BandwidthWiz, (LPARAM) &uBandwidth);
  378. IntroWiz::SetPage(IntroWiz::Bandwidth, IDD_BANDWIDTHWIZ);
  379. }
  380. }
  381. BOOL fShortcuts = fForce && !g_fSilentWizard;
  382. if (fVideoWiz)
  383. {
  384. LONG button_mask = 0;
  385. if (fULSWiz == TRUE)
  386. button_mask |= PSWIZB_BACK;
  387. if (fShortcuts || fAudioWiz)
  388. button_mask |= PSWIZB_NEXT;
  389. else
  390. button_mask |= PSWIZB_FINISH;
  391. FillInPropertyPage(&ppsp[nNumPages], IDD_VIDWIZ,
  392. VidWizDlg, button_mask, "NetMeeting");
  393. nNumPages++;
  394. IntroWiz::SetPage(IntroWiz::Video, IDD_VIDWIZ);
  395. }
  396. if (fShortcuts)
  397. {
  398. FillInPropertyPage(&ppsp[nNumPages], IDD_SHRTCUTWIZ,
  399. ShortcutWizDialogProc, 0);
  400. nNumPages++;
  401. IntroWiz::SetPage(IntroWiz::Shortcuts, IDD_SHRTCUTWIZ);
  402. }
  403. if (fAudioWiz)
  404. {
  405. if (fULSWiz || fVideoWiz)
  406. {
  407. pAudioConfig->uFlags |= STARTWITH_BACK;
  408. }
  409. ::CopyMemory( &(ppsp[nNumPages]),
  410. pAudioPages,
  411. nNumAudioPages * sizeof(PROPSHEETPAGE));
  412. nNumPages += nNumAudioPages;
  413. IntroWiz::SetPage(IntroWiz::AudioFirst,
  414. reinterpret_cast<UINT_PTR>(pAudioPages[0].pszTemplate));
  415. }
  416. psh.ppsp = ppsp;
  417. psh.nPages = nNumPages;
  418. if( !PropertySheet(&psh) )
  419. { // User hit CANCEL
  420. pIWizard->ReleaseWizardPages (pULSPages);
  421. delete pIWizard;
  422. delete ppsp;
  423. return S_FALSE;
  424. }
  425. delete ppsp;
  426. if ((FALSE == fContinue) && fULSWiz)
  427. {
  428. // Clear out the flags, because we don't want to store
  429. // any info in the registry (and therefore, we don't want
  430. // to run)
  431. pulsConf->dwFlags = 0;
  432. }
  433. }
  434. }
  435. if (fULSWiz)
  436. {
  437. if (!(ULSCONF_F_USER_NAME & pulsConf->dwFlags))
  438. {
  439. if (::GetDefaultName(pulsConf->szUserName, CCHMAX(pulsConf->szUserName)))
  440. {
  441. pulsConf->dwFlags |= ULSCONF_F_USER_NAME;
  442. }
  443. }
  444. if ((S_OK == pIWizard->SetConfig (pulsConf)) &&
  445. (ULSCONF_F_USER_NAME & pulsConf->dwFlags) &&
  446. (ULSCONF_F_EMAIL_NAME & pulsConf->dwFlags) &&
  447. (ULSCONF_F_FIRST_NAME & pulsConf->dwFlags) &&
  448. (ULSCONF_F_LAST_NAME & pulsConf->dwFlags))
  449. {
  450. // We have all of the necessary names
  451. hrRet = S_OK;
  452. }
  453. else
  454. {
  455. WARNING_OUT(("Unable to obtain a name!"));
  456. }
  457. TRACE_OUT(("ULS_CONF after running wizard:"));
  458. TRACE_OUT(("\tdwFlags: 0x%08x", pulsConf->dwFlags));
  459. TRACE_OUT(("\tszServerName: >%s<", pulsConf->szServerName));
  460. TRACE_OUT(("\tszUserName: >%s<", pulsConf->szUserName));
  461. TRACE_OUT(("\tszEmailName: >%s<", pulsConf->szEmailName));
  462. pIWizard->ReleaseWizardPages (pULSPages);
  463. delete pIWizard;
  464. pIWizard = NULL;
  465. }
  466. // Display the Splash screen as soon as possible
  467. if( SUCCEEDED(hrRet) && fForce && fVisible && (NULL == GetConfRoom()))
  468. {
  469. ::StartSplashScreen(NULL);
  470. }
  471. if (uOldBandwidth != uBandwidth)
  472. {
  473. SetBandwidth(uBandwidth);
  474. SaveDefaultCodecSettings(uBandwidth);
  475. }
  476. if (fAudioWiz)
  477. {
  478. AUDIOWIZOUTPUT awo;
  479. ReleaseAudioWizardPages(pAudioPages, pAudioConfig, &awo);
  480. if (awo.uValid & SOUNDCARDCAPS_CHANGED)
  481. {
  482. *plSoundCaps = awo.uSoundCardCaps;
  483. }
  484. else
  485. {
  486. // The wizard was cancelled, so we should only take the
  487. // information that tells us whether or not a sound card
  488. // is present.
  489. *plSoundCaps = (awo.uSoundCardCaps & SOUNDCARD_PRESENT);
  490. // Write this value to the registry so that the wizard will not
  491. // auto-launch the next time we run:
  492. RegEntry reSoundCaps(AUDIO_KEY, HKEY_CURRENT_USER);
  493. reSoundCaps.SetValue(REGVAL_SOUNDCARDCAPS, *plSoundCaps);
  494. }
  495. }
  496. // Even if the VidWiz page wasn't shown, we still need to call this
  497. // function (UpdateVidConfigRegistry) to fix the registry if the video
  498. // capture device configurations have changed since the last time.
  499. if (fVidWizInit)
  500. {
  501. UpdateVidConfigRegistry();
  502. UnInitVidWiz();
  503. }
  504. g_fSilentWizard = FALSE;
  505. return hrRet;
  506. }
  507. INT_PTR APIENTRY AppSharingWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  508. {
  509. switch (message)
  510. {
  511. case WM_INITDIALOG:
  512. {
  513. // Save the lParam information. in DWL_USER
  514. ::SetWindowLongPtr(hDlg, DWLP_USER, ((PROPSHEETPAGE*)lParam)->lParam);
  515. if (g_fSilentWizard)
  516. {
  517. HideWizard(GetParent(hDlg));
  518. }
  519. else
  520. {
  521. ShowWizard(GetParent(hDlg));
  522. }
  523. return TRUE;
  524. }
  525. case WM_NOTIFY:
  526. {
  527. switch (((NMHDR FAR *) lParam)->code)
  528. {
  529. case PSN_SETACTIVE:
  530. {
  531. ASSERT(lParam);
  532. INTRO_PAGE_CONFIG* pipc = (INTRO_PAGE_CONFIG*)
  533. ::GetWindowLongPtr(hDlg, DWLP_USER);
  534. ASSERT(pipc);
  535. DWORD dwFlags = pipc->fAllowBack ? PSWIZB_BACK : 0;
  536. if( IntroWiz::GetNextPage(IntroWiz::AppSharing) == 0 )
  537. {
  538. dwFlags |= PSWIZB_FINISH;
  539. }
  540. else
  541. {
  542. dwFlags |= PSWIZB_NEXT;
  543. }
  544. // Initialize the controls.
  545. PropSheet_SetWizButtons( ::GetParent(hDlg), dwFlags );
  546. if (g_fSilentWizard)
  547. {
  548. PropSheet_PressButton(
  549. GetParent(hDlg), PSBTN_NEXT);
  550. }
  551. break;
  552. }
  553. case PSN_KILLACTIVE:
  554. {
  555. ::SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
  556. return TRUE;
  557. }
  558. case PSN_WIZNEXT:
  559. {
  560. UINT_PTR iNext = IntroWiz::GetNextPage(IntroWiz::AppSharing);
  561. ASSERT( iNext );
  562. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, iNext );
  563. return TRUE;
  564. }
  565. case PSN_RESET:
  566. {
  567. ASSERT(lParam);
  568. INTRO_PAGE_CONFIG* pipc = (INTRO_PAGE_CONFIG*)
  569. ::GetWindowLongPtr(hDlg, DWLP_USER);
  570. ASSERT(pipc);
  571. *pipc->fContinue = FALSE;
  572. break;
  573. }
  574. }
  575. break;
  576. }
  577. default:
  578. break;
  579. }
  580. return FALSE;
  581. }
  582. INT_PTR APIENTRY IntroWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  583. {
  584. switch (message)
  585. {
  586. case WM_INITDIALOG:
  587. {
  588. // Save the lParam information. in DWL_USER
  589. ::SetWindowLongPtr(hDlg, DWLP_USER, ((PROPSHEETPAGE*)lParam)->lParam);
  590. if (g_fSilentWizard)
  591. {
  592. HideWizard(GetParent(hDlg));
  593. }
  594. else
  595. {
  596. ShowWizard(GetParent(hDlg));
  597. }
  598. return TRUE;
  599. }
  600. case WM_NOTIFY:
  601. {
  602. switch (((NMHDR FAR *) lParam)->code)
  603. {
  604. case PSN_SETACTIVE:
  605. {
  606. ASSERT(lParam);
  607. INTRO_PAGE_CONFIG* pipc = (INTRO_PAGE_CONFIG*)
  608. ::GetWindowLongPtr(hDlg, DWLP_USER);
  609. ASSERT(pipc);
  610. // Initialize the controls.
  611. PropSheet_SetWizButtons(
  612. ::GetParent(hDlg),
  613. PSWIZB_NEXT | (pipc->fAllowBack ? PSWIZB_BACK : 0));
  614. if (g_fSilentWizard)
  615. {
  616. PropSheet_PressButton(
  617. GetParent(hDlg), PSBTN_NEXT);
  618. }
  619. break;
  620. }
  621. case PSN_KILLACTIVE:
  622. {
  623. ::SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
  624. return TRUE;
  625. }
  626. case PSN_WIZNEXT:
  627. {
  628. break;
  629. }
  630. case PSN_RESET:
  631. {
  632. ASSERT(lParam);
  633. INTRO_PAGE_CONFIG* pipc = (INTRO_PAGE_CONFIG*)
  634. ::GetWindowLongPtr(hDlg, DWLP_USER);
  635. ASSERT(pipc);
  636. *pipc->fContinue = FALSE;
  637. break;
  638. }
  639. }
  640. break;
  641. }
  642. default:
  643. break;
  644. }
  645. return FALSE;
  646. }
  647. static void BandwidthWiz_InitDialog(HWND hDlg, UINT uOldBandwidth)
  648. {
  649. INT idChecked;
  650. //set the initial value
  651. switch (uOldBandwidth)
  652. {
  653. case BW_144KBS:
  654. idChecked = IDC_RADIO144KBS;
  655. break;
  656. case BW_ISDN:
  657. idChecked = IDC_RADIOISDN;
  658. break;
  659. case BW_MOREKBS:
  660. idChecked = IDC_RADIOMOREKBS;
  661. break;
  662. case BW_288KBS:
  663. default:
  664. idChecked = IDC_RADIO288KBS;
  665. break;
  666. }
  667. CheckRadioButton(hDlg, IDC_RADIO144KBS, IDC_RADIOISDN, idChecked);
  668. }
  669. static void BandwidthWiz_OK(HWND hDlg, UINT *puBandwidth)
  670. {
  671. //check the radio button
  672. if (IsDlgButtonChecked(hDlg,IDC_RADIO144KBS))
  673. {
  674. *puBandwidth = BW_144KBS;
  675. }
  676. else if (IsDlgButtonChecked(hDlg,IDC_RADIO288KBS))
  677. {
  678. *puBandwidth = BW_288KBS;
  679. }
  680. else if (IsDlgButtonChecked(hDlg,IDC_RADIOISDN))
  681. {
  682. *puBandwidth = BW_ISDN;
  683. }
  684. else
  685. {
  686. *puBandwidth = BW_MOREKBS;
  687. }
  688. // if (BW_MOREKBS != *puBandwidth)
  689. // {
  690. // // disable refresh of speed dials if not on a LAN
  691. // RegEntry re(UI_KEY, HKEY_CURRENT_USER);
  692. // re.SetValue(REGVAL_ENABLE_FRIENDS_AUTOREFRESH, (ULONG) 0L);
  693. // }
  694. }
  695. INT_PTR APIENTRY BandwidthWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  696. {
  697. PROPSHEETPAGE *ps;
  698. static UINT *puBandwidth;
  699. static UINT uOldBandwidth;
  700. switch (message) {
  701. case WM_INITDIALOG:
  702. {
  703. // Save the PROPSHEETPAGE information.
  704. ps = (PROPSHEETPAGE *)lParam;
  705. puBandwidth = (UINT*)ps->lParam;
  706. uOldBandwidth = *puBandwidth;
  707. BandwidthWiz_InitDialog(hDlg, uOldBandwidth);
  708. return (TRUE);
  709. }
  710. case WM_NOTIFY:
  711. switch (((NMHDR FAR *) lParam)->code) {
  712. case PSN_SETACTIVE:
  713. {
  714. // Initialize the controls.
  715. IntroWiz::HandleWizNotify(hDlg,
  716. reinterpret_cast<NMHDR*>(lParam), IntroWiz::Bandwidth);
  717. break;
  718. }
  719. case PSN_WIZBACK:
  720. return(IntroWiz::HandleWizNotify(hDlg,
  721. reinterpret_cast<NMHDR*>(lParam), IntroWiz::Bandwidth));
  722. case PSN_WIZFINISH:
  723. case PSN_WIZNEXT:
  724. {
  725. BandwidthWiz_OK(hDlg, puBandwidth);
  726. return(IntroWiz::HandleWizNotify(hDlg,
  727. reinterpret_cast<NMHDR*>(lParam), IntroWiz::Bandwidth));
  728. }
  729. case PSN_RESET:
  730. *puBandwidth = uOldBandwidth;
  731. break;
  732. default:
  733. break;
  734. }
  735. break;
  736. default:
  737. break;
  738. }
  739. return FALSE;
  740. }
  741. static void BandwidthDlg_OnCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
  742. {
  743. switch(id)
  744. {
  745. case IDOK:
  746. {
  747. UINT uBandwidth;
  748. BandwidthWiz_OK(hDlg, &uBandwidth);
  749. EndDialog(hDlg, uBandwidth);
  750. break;
  751. }
  752. // Fall through
  753. case IDCANCEL:
  754. EndDialog(hDlg, 0);
  755. break;
  756. default:
  757. break;
  758. }
  759. }
  760. INT_PTR CALLBACK BandwidthDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  761. {
  762. static const DWORD aContextHelpIds[] = {
  763. IDC_RADIO144KBS, IDH_AUDIO_CONNECTION_SPEED,
  764. IDC_RADIO288KBS, IDH_AUDIO_CONNECTION_SPEED,
  765. IDC_RADIOISDN, IDH_AUDIO_CONNECTION_SPEED,
  766. IDC_RADIOMOREKBS, IDH_AUDIO_CONNECTION_SPEED,
  767. 0, 0 // terminator
  768. };
  769. switch (message) {
  770. HANDLE_MSG(hDlg, WM_COMMAND, BandwidthDlg_OnCommand);
  771. case WM_INITDIALOG:
  772. BandwidthWiz_InitDialog(hDlg, (UINT)lParam);
  773. break;
  774. case WM_CONTEXTMENU:
  775. DoHelpWhatsThis(wParam, aContextHelpIds);
  776. break;
  777. case WM_HELP:
  778. DoHelp(lParam, aContextHelpIds);
  779. break;
  780. default:
  781. return(FALSE);
  782. }
  783. return(TRUE);
  784. }
  785. BOOL NeedAudioWizard(LPLONG plSoundCaps, BOOL fForce)
  786. {
  787. if (_Module.IsSDKCallerRTC() || SysPol::NoAudio())
  788. {
  789. WARNING_OUT(("Audio disabled through system policy switch"));
  790. return FALSE;
  791. }
  792. if (fForce)
  793. {
  794. return TRUE;
  795. }
  796. BOOL fAudioWiz = FALSE;
  797. RegEntry reSoundCaps(AUDIO_KEY, HKEY_CURRENT_USER);
  798. // a default that doesn't overlap with real values
  799. long lCapsNotPresent = 0x7FFFFFFF;
  800. *plSoundCaps = reSoundCaps.GetNumber( REGVAL_SOUNDCARDCAPS,
  801. lCapsNotPresent);
  802. if (lCapsNotPresent == *plSoundCaps)
  803. {
  804. TRACE_OUT(("Missing sound caps - starting calib wizard"));
  805. fAudioWiz = TRUE;
  806. }
  807. else
  808. {
  809. if (!ISSOUNDCARDPRESENT(*plSoundCaps))
  810. {
  811. if (waveInGetNumDevs() && waveOutGetNumDevs())
  812. fAudioWiz = TRUE;
  813. }
  814. else
  815. {
  816. WAVEINCAPS waveinCaps;
  817. WAVEOUTCAPS waveoutCaps;
  818. //if the wavein has changed since last
  819. if (waveInGetDevCaps(reSoundCaps.GetNumber(REGVAL_WAVEINDEVICEID,WAVE_MAPPER),
  820. &waveinCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
  821. {
  822. //check the name, if changed, run the wizard
  823. if (lstrcmp(reSoundCaps.GetString(REGVAL_WAVEINDEVICENAME),waveinCaps.szPname))
  824. fAudioWiz = TRUE;
  825. }
  826. else
  827. fAudioWiz = TRUE;
  828. //if the waveout has changed since last
  829. if (waveOutGetDevCaps(reSoundCaps.GetNumber(REGVAL_WAVEOUTDEVICEID,WAVE_MAPPER),
  830. &waveoutCaps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR)
  831. {
  832. //check the name, if changed, run the wizard
  833. if (lstrcmp(reSoundCaps.GetString(REGVAL_WAVEOUTDEVICENAME),waveoutCaps.szPname))
  834. fAudioWiz = TRUE;
  835. }
  836. else
  837. fAudioWiz = TRUE;
  838. }
  839. }
  840. return fAudioWiz;
  841. }
  842. ///////////////////////////////////////////////////////
  843. //
  844. // Wizard pages
  845. //
  846. DWORD SetUserPageWizButtons(HWND hDlg, DWORD dwConfFlags)
  847. {
  848. DWORD dwButtonFlags = PSWIZB_BACK;
  849. // disable the 'Next' button if not all of first name, last name and email
  850. // are filled in
  851. if (!FEmptyDlgItem(hDlg, IDEC_FIRSTNAME) &&
  852. !FEmptyDlgItem(hDlg, IDEC_LASTNAME) &&
  853. !FEmptyDlgItem(hDlg, IDC_USER_EMAIL))
  854. {
  855. dwButtonFlags |= (dwConfFlags & ULSWIZ_F_NO_FINISH) ? PSWIZB_NEXT : PSWIZB_FINISH;
  856. }
  857. PropSheet_SetWizButtons (GetParent (hDlg), dwButtonFlags);
  858. return dwButtonFlags;
  859. }
  860. void GetUserPageState(HWND hDlg, ULS_CONF *pConf)
  861. {
  862. //strip the first name/email name and last name
  863. TrimDlgItemText(hDlg, IDEC_FIRSTNAME);
  864. TrimDlgItemText(hDlg, IDEC_LASTNAME);
  865. TrimDlgItemText(hDlg, IDC_USER_EMAIL);
  866. TrimDlgItemText(hDlg, IDC_USER_LOCATION);
  867. TrimDlgItemText(hDlg, IDC_USER_INTERESTS);
  868. Edit_GetText(GetDlgItem(hDlg, IDEC_FIRSTNAME),
  869. pConf->szFirstName, MAX_FIRST_NAME_LENGTH);
  870. Edit_GetText(GetDlgItem(hDlg, IDEC_LASTNAME),
  871. pConf->szLastName, MAX_LAST_NAME_LENGTH);
  872. Edit_GetText(GetDlgItem(hDlg, IDC_USER_EMAIL),
  873. pConf->szEmailName, MAX_EMAIL_NAME_LENGTH);
  874. Edit_GetText(GetDlgItem(hDlg, IDC_USER_LOCATION),
  875. pConf->szLocation, MAX_LOCATION_NAME_LENGTH);
  876. Edit_GetText(GetDlgItem(hDlg, IDC_USER_INTERESTS),
  877. pConf->szComments, MAX_COMMENTS_LENGTH);
  878. if (pConf->szFirstName[0]) pConf->dwFlags |= ULSCONF_F_FIRST_NAME;
  879. if (pConf->szLastName[0]) pConf->dwFlags |= ULSCONF_F_LAST_NAME;
  880. if (pConf->szEmailName[0]) pConf->dwFlags |= ULSCONF_F_EMAIL_NAME;
  881. if (pConf->szLocation[0]) pConf->dwFlags |= ULSCONF_F_LOCATION;
  882. if (pConf->szComments[0]) pConf->dwFlags |= ULSCONF_F_COMMENTS;
  883. }
  884. UINT_PTR GetPageAfterUser()
  885. {
  886. UINT_PTR iNext = 0;
  887. if( SysPol::AllowDirectoryServices() )
  888. {
  889. iNext = IDD_PAGE_SERVER;
  890. }
  891. else
  892. {
  893. iNext = GetPageAfterULS();
  894. }
  895. return iNext;
  896. }
  897. INT_PTR APIENTRY PageUserDlgProc ( HWND hDlg, UINT uMsg, WPARAM uParam, LPARAM lParam )
  898. {
  899. ULS_CONF *pConf;
  900. PROPSHEETPAGE *pPage;
  901. static DWORD dwWizButtons;
  902. switch (uMsg)
  903. {
  904. case WM_DESTROY:
  905. s_hDlgUserInfo = NULL;
  906. break;
  907. case WM_INITDIALOG:
  908. s_hDlgUserInfo = hDlg;
  909. pPage = (PROPSHEETPAGE *) lParam;
  910. pConf = (ULS_CONF *) pPage->lParam;
  911. SetWindowLongPtr (hDlg, GWLP_USERDATA, lParam);
  912. // Set the font
  913. ::SendDlgItemMessage(hDlg, IDEC_FIRSTNAME, WM_SETFONT, (WPARAM) g_hfontDlg, 0);
  914. ::SendDlgItemMessage(hDlg, IDEC_LASTNAME, WM_SETFONT, (WPARAM) g_hfontDlg, 0);
  915. ::SendDlgItemMessage(hDlg, IDC_USER_LOCATION, WM_SETFONT, (WPARAM) g_hfontDlg, 0);
  916. ::SendDlgItemMessage(hDlg, IDC_USER_INTERESTS, WM_SETFONT, (WPARAM) g_hfontDlg, 0);
  917. // Limit the text
  918. Edit_LimitText(GetDlgItem(hDlg, IDEC_FIRSTNAME), MAX_FIRST_NAME_LENGTH - 1);
  919. Edit_LimitText(GetDlgItem(hDlg, IDEC_LASTNAME), MAX_LAST_NAME_LENGTH - 1);
  920. Edit_LimitText(GetDlgItem(hDlg, IDC_USER_EMAIL), MAX_EMAIL_NAME_LENGTH - 1);
  921. Edit_LimitText(GetDlgItem(hDlg, IDC_USER_LOCATION), MAX_LOCATION_NAME_LENGTH - 1);
  922. Edit_LimitText(GetDlgItem(hDlg, IDC_USER_INTERESTS), UI_COMMENTS_LENGTH - 1);
  923. if (pConf->dwFlags & ULSCONF_F_FIRST_NAME)
  924. {
  925. Edit_SetText(GetDlgItem(hDlg, IDEC_FIRSTNAME), pConf->szFirstName);
  926. }
  927. if (pConf->dwFlags & ULSCONF_F_LAST_NAME)
  928. {
  929. Edit_SetText(GetDlgItem(hDlg, IDEC_LASTNAME), pConf->szLastName);
  930. }
  931. if (pConf->dwFlags & ULSCONF_F_EMAIL_NAME)
  932. {
  933. Edit_SetText(GetDlgItem(hDlg, IDC_USER_EMAIL), pConf->szEmailName);
  934. }
  935. if (pConf->dwFlags & ULSCONF_F_LOCATION)
  936. {
  937. Edit_SetText(GetDlgItem(hDlg, IDC_USER_LOCATION), pConf->szLocation);
  938. }
  939. #ifdef DEBUG
  940. if ((0 == (pConf->dwFlags & ULSCONF_F_COMMENTS)) &&
  941. (0 == (pConf->dwFlags & ULSCONF_F_EMAIL_NAME)) )
  942. {
  943. extern VOID DbgGetComments(LPTSTR);
  944. DbgGetComments(pConf->szComments);
  945. pConf->dwFlags |= ULSCONF_F_COMMENTS;
  946. }
  947. #endif
  948. if (pConf->dwFlags & ULSCONF_F_COMMENTS)
  949. {
  950. Edit_SetText(GetDlgItem (hDlg, IDC_USER_INTERESTS), pConf->szComments);
  951. }
  952. break;
  953. case WM_COMMAND:
  954. switch (GET_WM_COMMAND_ID (uParam, lParam))
  955. {
  956. case IDEC_FIRSTNAME:
  957. case IDEC_LASTNAME:
  958. case IDC_USER_EMAIL:
  959. if (GET_WM_COMMAND_CMD(uParam,lParam) == EN_CHANGE)
  960. {
  961. pPage = (PROPSHEETPAGE *) GetWindowLongPtr (hDlg, GWLP_USERDATA);
  962. pConf = (ULS_CONF *) pPage->lParam;
  963. dwWizButtons = SetUserPageWizButtons(hDlg, pConf->dwFlags);
  964. }
  965. break;
  966. }
  967. break;
  968. case WM_NOTIFY:
  969. pPage = (PROPSHEETPAGE *) GetWindowLongPtr (hDlg, GWLP_USERDATA);
  970. pConf = (ULS_CONF *) pPage->lParam;
  971. switch (((NMHDR *) lParam)->code)
  972. {
  973. case PSN_KILLACTIVE:
  974. SetWindowLongPtr (hDlg, DWLP_MSGRESULT, FALSE);
  975. break;
  976. case PSN_RESET:
  977. ZeroMemory (pConf, sizeof (ULS_CONF));
  978. SetWindowLongPtr (hDlg, DWLP_MSGRESULT, FALSE);
  979. break;
  980. case PSN_SETACTIVE:
  981. dwWizButtons = SetUserPageWizButtons(hDlg, pConf->dwFlags);
  982. if (g_fSilentWizard)
  983. {
  984. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  985. }
  986. break;
  987. case PSN_WIZBACK:
  988. return(IntroWiz::HandleWizNotify(hDlg,
  989. reinterpret_cast<NMHDR*>(lParam), IntroWiz::ULSFirst));
  990. case PSN_WIZNEXT:
  991. case PSN_WIZFINISH:
  992. if (!(dwWizButtons & ((PSN_WIZNEXT == ((NMHDR *) lParam)->code) ?
  993. PSWIZB_NEXT : PSWIZB_FINISH)))
  994. {
  995. // Reject the next/finish button
  996. ShowWizard(GetParent(hDlg));
  997. ::SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  998. return TRUE;
  999. }
  1000. if (!FLegalEmailName(hDlg, IDC_USER_EMAIL))
  1001. {
  1002. ShowWizard(GetParent(hDlg));
  1003. ConfMsgBox(hDlg, (LPCTSTR)IDS_ILLEGALEMAILNAME);
  1004. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  1005. return TRUE;
  1006. }
  1007. GetUserPageState(hDlg, pConf);
  1008. if( PSN_WIZNEXT == (((NMHDR *) lParam)->code) )
  1009. {
  1010. UINT_PTR iNext = GetPageAfterUser();
  1011. ASSERT( iNext );
  1012. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, iNext);
  1013. return TRUE;
  1014. }
  1015. break;
  1016. default:
  1017. return FALSE;
  1018. }
  1019. default:
  1020. return FALSE;
  1021. }
  1022. return TRUE;
  1023. }
  1024. HRESULT CULSWizard::GetWizardPages ( PROPSHEETPAGE **ppPage, ULONG *pcPages, ULS_CONF **ppUlsConf )
  1025. {
  1026. const int cULS_Pages = 5;
  1027. PROPSHEETPAGE *pPage = NULL;
  1028. ULONG cPages = 0;
  1029. UINT cbSize = cULS_Pages * sizeof (PROPSHEETPAGE) + sizeof (ULS_CONF);
  1030. ULS_CONF *pConf = NULL;
  1031. HRESULT hr;
  1032. if (ppPage == NULL || pcPages == NULL || ppUlsConf == NULL)
  1033. {
  1034. return E_POINTER;
  1035. }
  1036. pPage = (PROPSHEETPAGE*) LocalAlloc(LPTR, cbSize);
  1037. if (pPage == NULL)
  1038. {
  1039. return E_OUTOFMEMORY;
  1040. }
  1041. pConf = (ULS_CONF *) (((LPBYTE) pPage) +
  1042. cULS_Pages * sizeof (PROPSHEETPAGE));
  1043. hr = GetConfig (pConf);
  1044. if (hr != S_OK)
  1045. {
  1046. // REVIEW: GetConfig will never fail, but if it did, pPage would not be released.
  1047. return hr;
  1048. }
  1049. #if USE_GAL
  1050. if( !ConfPolicies::IsGetMyInfoFromGALEnabled() ||
  1051. !ConfPolicies::GetMyInfoFromGALSucceeded() ||
  1052. ConfPolicies::InvalidMyInfo()
  1053. )
  1054. #endif // USE_GAL
  1055. {
  1056. FillInPropertyPage(&pPage[cPages], IDD_PAGE_USER, PageUserDlgProc, (LPARAM) pConf);
  1057. cPages++;
  1058. }
  1059. m_WizDirectCallingSettings.SetULS_CONF( pConf );
  1060. FillInPropertyPage( &pPage[cPages++],
  1061. IDD_PAGE_SERVER,
  1062. CWizDirectCallingSettings::StaticDlgProc,
  1063. reinterpret_cast<LPARAM>(&m_WizDirectCallingSettings)
  1064. );
  1065. *ppPage = pPage;
  1066. *pcPages = cPages;
  1067. *ppUlsConf = pConf;
  1068. return S_OK;
  1069. }
  1070. HRESULT CULSWizard::ReleaseWizardPages ( PROPSHEETPAGE *pPage)
  1071. {
  1072. LocalFree(pPage);
  1073. return S_OK;
  1074. }
  1075. HRESULT CULSWizard::GetConfig ( ULS_CONF *pConf )
  1076. {
  1077. HRESULT hr = E_POINTER;
  1078. if (NULL != pConf)
  1079. {
  1080. ::ZeroMemory (pConf, sizeof (ULS_CONF));
  1081. // always return these as valid
  1082. pConf->dwFlags = ULSCONF_F_SERVER_NAME | ULSCONF_F_PUBLISH;
  1083. RegEntry reULS(g_szClientFld, HKEY_CURRENT_USER);
  1084. // BUGBUG: ChrisPi - this was a bad idea - lstrcpyn() returns NULL on failure!
  1085. if (_T('\0') != *(lstrcpyn( pConf->szEmailName,
  1086. reULS.GetString(g_szEmailName),
  1087. CCHMAX(pConf->szEmailName))))
  1088. {
  1089. pConf->dwFlags |= ULSCONF_F_EMAIL_NAME;
  1090. }
  1091. if (_T('\0') != *(lstrcpyn( pConf->szFirstName,
  1092. reULS.GetString(g_szFirstName),
  1093. CCHMAX(pConf->szFirstName))))
  1094. {
  1095. pConf->dwFlags |= ULSCONF_F_FIRST_NAME;
  1096. }
  1097. if (_T('\0') != *(lstrcpyn( pConf->szLastName,
  1098. reULS.GetString(g_szLastName),
  1099. CCHMAX(pConf->szLastName))))
  1100. {
  1101. pConf->dwFlags |= ULSCONF_F_LAST_NAME;
  1102. }
  1103. if (_T('\0') != *(lstrcpyn( pConf->szLocation,
  1104. reULS.GetString(g_szLocation),
  1105. CCHMAX(pConf->szLocation))))
  1106. {
  1107. pConf->dwFlags |= ULSCONF_F_LOCATION;
  1108. }
  1109. if (_T('\0') != *(lstrcpyn( pConf->szUserName,
  1110. reULS.GetString(g_szUserName),
  1111. CCHMAX(pConf->szUserName))))
  1112. {
  1113. pConf->dwFlags |= ULSCONF_F_USER_NAME;
  1114. }
  1115. if (_T('\0') != *(lstrcpyn( pConf->szComments,
  1116. reULS.GetString(g_szComments),
  1117. CCHMAX(pConf->szComments))))
  1118. {
  1119. pConf->dwFlags |= ULSCONF_F_COMMENTS;
  1120. }
  1121. if (!_Module.IsSDKCallerRTC())
  1122. {
  1123. lstrcpyn( pConf->szServerName, CDirectoryManager::get_defaultServer(), CCHMAX( pConf->szServerName ) );
  1124. }
  1125. else
  1126. {
  1127. lstrcpyn( pConf->szServerName, _T(" "), CCHMAX( pConf->szServerName ) );
  1128. }
  1129. pConf->fDontPublish = reULS.GetNumber(g_szDontPublish,
  1130. REGVAL_ULS_DONT_PUBLISH_DEFAULT);
  1131. pConf->dwFlags |= ULSCONF_F_PUBLISH;
  1132. hr = S_OK;
  1133. }
  1134. return hr;
  1135. }
  1136. // FUTURE: Use CombineNames
  1137. static BOOL CheckForNames(ULS_CONF *pConf)
  1138. {
  1139. // only care if one of first name, last name, email address is missing
  1140. if ((pConf->dwFlags & ULSCONF_F_FIRST_NAME) &&
  1141. (pConf->dwFlags & ULSCONF_F_LAST_NAME) &&
  1142. (pConf->dwFlags & ULSCONF_F_EMAIL_NAME))
  1143. {
  1144. return TRUE;
  1145. }
  1146. if ((pConf->dwFlags & ULSCONF_F_FIRST_NAME) || (pConf->dwFlags & ULSCONF_F_LAST_NAME))
  1147. //set the user name too
  1148. {
  1149. TCHAR szSource[128];
  1150. TCHAR *argw[2];
  1151. argw[0] = pConf->szFirstName;
  1152. argw[1] = pConf->szLastName;
  1153. LoadString (GetInstanceHandle(), IDS_NAME_ORDER, szSource, sizeof(szSource)/sizeof(TCHAR));
  1154. FormatMessage(FORMAT_MESSAGE_ARGUMENT_ARRAY|FORMAT_MESSAGE_FROM_STRING,szSource,
  1155. 0,0,pConf->szUserName, sizeof(pConf->szUserName),(va_list *)argw );
  1156. //truncate at 47 character
  1157. pConf->szUserName[47] = TEXT('\0');
  1158. pConf->dwFlags |= ULSCONF_F_USER_NAME;
  1159. }
  1160. return TRUE;
  1161. }
  1162. /* S E T C O N F I G */
  1163. /*-------------------------------------------------------------------------
  1164. %%Function: SetConfig
  1165. -------------------------------------------------------------------------*/
  1166. HRESULT CULSWizard::SetConfig ( ULS_CONF *pConf )
  1167. {
  1168. if (pConf->dwFlags == 0)
  1169. {
  1170. // nothing to set value
  1171. return S_OK;
  1172. }
  1173. if ((pConf->dwFlags & ULSCONF_F_EMAIL_NAME) &&
  1174. (!FLegalEmailSz(pConf->szEmailName)) )
  1175. {
  1176. // email name must be legal
  1177. return E_INVALIDARG;
  1178. }
  1179. RegEntry re(g_szClientFld);
  1180. if (pConf->dwFlags & ULSCONF_F_PUBLISH)
  1181. {
  1182. re.SetValue(g_szDontPublish, (LONG) pConf->fDontPublish);
  1183. }
  1184. if (pConf->dwFlags & ULSCONF_F_EMAIL_NAME)
  1185. {
  1186. re.SetValue(g_szEmailName, pConf->szEmailName);
  1187. }
  1188. if (pConf->dwFlags & ULSCONF_F_FIRST_NAME)
  1189. {
  1190. re.SetValue(g_szFirstName, pConf->szFirstName);
  1191. }
  1192. if (pConf->dwFlags & ULSCONF_F_LAST_NAME)
  1193. {
  1194. re.SetValue(g_szLastName, pConf->szLastName);
  1195. }
  1196. if (pConf->dwFlags & ULSCONF_F_LOCATION)
  1197. {
  1198. re.SetValue(g_szLocation, pConf->szLocation);
  1199. }
  1200. if (pConf->dwFlags & ULSCONF_F_COMMENTS)
  1201. {
  1202. re.SetValue(g_szComments, pConf->szComments);
  1203. }
  1204. if (pConf->dwFlags & ULSCONF_F_SERVER_NAME)
  1205. {
  1206. CDirectoryManager::set_defaultServer( pConf->szServerName );
  1207. }
  1208. //SS:may be oprah should do this and store it as their own key
  1209. if ((pConf->dwFlags & ULSCONF_F_FIRST_NAME) || (pConf->dwFlags & ULSCONF_F_LAST_NAME))
  1210. {
  1211. ULS_CONF ulcExisting;
  1212. if ((ULSCONF_F_FIRST_NAME | ULSCONF_F_LAST_NAME) !=
  1213. (pConf->dwFlags & (ULSCONF_F_FIRST_NAME | ULSCONF_F_LAST_NAME)) )
  1214. {
  1215. // If only one of these fields is being set, load the previous config:
  1216. GetConfig(&ulcExisting);
  1217. }
  1218. CombineNames(pConf->szUserName, MAX_DCL_NAME_LEN,
  1219. (pConf->dwFlags & ULSCONF_F_FIRST_NAME) ?
  1220. pConf->szFirstName : ulcExisting.szFirstName,
  1221. (pConf->dwFlags & ULSCONF_F_LAST_NAME) ?
  1222. pConf->szLastName : ulcExisting.szLastName);
  1223. pConf->dwFlags |= ULSCONF_F_USER_NAME;
  1224. re.SetValue(g_szUserName, pConf->szUserName);
  1225. }
  1226. if ((pConf->dwFlags & ULSCONF_F_SERVER_NAME) || (pConf->dwFlags & ULSCONF_F_EMAIL_NAME))
  1227. {
  1228. TCHAR szTemp[MAX_SERVER_NAME_LENGTH + MAX_EMAIL_NAME_LENGTH + 6];
  1229. ULS_CONF ulcExisting;
  1230. if ((ULSCONF_F_SERVER_NAME | ULSCONF_F_EMAIL_NAME) !=
  1231. (pConf->dwFlags & (ULSCONF_F_SERVER_NAME | ULSCONF_F_EMAIL_NAME)))
  1232. {
  1233. // If only one of these fields is being set, load the previous config:
  1234. GetConfig(&ulcExisting);
  1235. }
  1236. FCreateIlsName(szTemp,
  1237. (pConf->dwFlags & ULSCONF_F_SERVER_NAME) ?
  1238. pConf->szServerName : ulcExisting.szServerName,
  1239. (pConf->dwFlags & ULSCONF_F_EMAIL_NAME) ?
  1240. pConf->szEmailName : ulcExisting.szEmailName,
  1241. CCHMAX(szTemp));
  1242. re.SetValue(g_szResolveName, szTemp);
  1243. }
  1244. // Generate a cert based on the entered information for secure calls
  1245. // ...make sure all fields we care about are valid first
  1246. #define ULSCONF_F_IDFIELDS (ULSCONF_F_FIRST_NAME|ULSCONF_F_LAST_NAME|\
  1247. ULSCONF_F_EMAIL_NAME)
  1248. if ((pConf->dwFlags & ULSCONF_F_IDFIELDS ) == ULSCONF_F_IDFIELDS)
  1249. {
  1250. //
  1251. // LAURABU BUGBUG:
  1252. // If we can't make a cert (France?) or have wrong SCHANNEL or
  1253. // buggy crypto or unrecognized provider, can we propagate that info
  1254. // and act like security is diabled (not available)?
  1255. //
  1256. // How/can we make a common "security not possible" setting we
  1257. // can use.
  1258. //
  1259. MakeCertWrap(pConf->szFirstName, pConf->szLastName,
  1260. pConf->szEmailName, 0);
  1261. //
  1262. // LAURABU BOGUS!
  1263. // Only do this when RDS is installed. And just ONCE.
  1264. //
  1265. // Now make a local machine cert for RDS
  1266. CHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
  1267. DWORD cbComputerName = sizeof(szComputerName);
  1268. if (GetComputerName(szComputerName, &cbComputerName))
  1269. {
  1270. MakeCertWrap(szComputerName, NULL, NULL, NMMKCERT_F_LOCAL_MACHINE);
  1271. }
  1272. else
  1273. {
  1274. ERROR_OUT(("GetComputerName failed: %x", GetLastError()));
  1275. }
  1276. }
  1277. return S_OK;
  1278. }
  1279. bool IsLegalGatewaySz(LPCTSTR szServer)
  1280. {
  1281. bool bRet = false;
  1282. if( szServer && szServer[0] )
  1283. {
  1284. bRet = true;
  1285. }
  1286. return bRet;
  1287. }
  1288. bool IsLegalGateKeeperServerSz(LPCTSTR szServer)
  1289. {
  1290. bool bRet = false;
  1291. if( szServer && szServer[0] )
  1292. {
  1293. bRet = true;
  1294. }
  1295. return bRet;
  1296. }
  1297. bool IsLegalE164Number(LPCTSTR szPhone)
  1298. {
  1299. if( (NULL == szPhone) || (0 == szPhone[0]) )
  1300. {
  1301. return false;
  1302. }
  1303. // assume a legal phone number is anything with at least 1
  1304. // digit, *,or #. Anything else will be considered the user's
  1305. // own pretty print formatting (e.g. "876-5309")
  1306. // the bad chars will get filtered out later
  1307. while (*szPhone)
  1308. {
  1309. if ( ((*szPhone >= '0') && (*szPhone <= '9')) ||
  1310. ((*szPhone == '#') || (*szPhone == '*')) )
  1311. {
  1312. return true;
  1313. }
  1314. szPhone++;
  1315. }
  1316. return false;
  1317. }
  1318. /* F L E G A L E M A I L S Z */
  1319. /*-------------------------------------------------------------------------
  1320. %%Function: FLegalEmailSz
  1321. A legal email name contains only ANSI characters.
  1322. "a-z, A-Z, numbers 0-9 and some common symbols"
  1323. It cannot include extended characters or < > ( ) /
  1324. -------------------------------------------------------------------------*/
  1325. BOOL FLegalEmailSz(PTSTR pszName)
  1326. {
  1327. if (IS_EMPTY_STRING(pszName))
  1328. return FALSE;
  1329. for ( ; ; )
  1330. {
  1331. UINT ch = (UINT) ((*pszName++) & 0x00FF);
  1332. if (0 == ch)
  1333. break;
  1334. switch (ch)
  1335. {
  1336. default:
  1337. if ((ch > (UINT) _T(' ')) && (ch <= (UINT) _T('~')) )
  1338. break;
  1339. // else fall thru to error code
  1340. case '(': case ')':
  1341. case '<': case '>':
  1342. case '[': case ']':
  1343. case '/': case '\\':
  1344. case ':': case ';':
  1345. case '+':
  1346. case '=':
  1347. case ',':
  1348. case '\"':
  1349. WARNING_OUT(("FLegalEmailSz: Invalid character '%s' (0x%02X)", &ch, ch));
  1350. return FALSE;
  1351. }
  1352. }
  1353. return TRUE;
  1354. }
  1355. /* F L E G A L E M A I L N A M E */
  1356. /*-------------------------------------------------------------------------
  1357. %%Function: FLegalEmailName
  1358. -------------------------------------------------------------------------*/
  1359. BOOL FLegalEmailName(HWND hdlg, UINT id)
  1360. {
  1361. TCHAR sz[MAX_PATH];
  1362. GetDlgItemTextTrimmed(hdlg, id, sz, CCHMAX(sz));
  1363. return FLegalEmailSz(sz);
  1364. }
  1365. /* F I L L S E R V E R C O M B O B O X */
  1366. /*-------------------------------------------------------------------------
  1367. %%Function: FillServerComboBox
  1368. -------------------------------------------------------------------------*/
  1369. VOID FillServerComboBox(HWND hwndCombo)
  1370. {
  1371. CMRUList MRUList;
  1372. MRUList.Load( DIR_MRU_KEY );
  1373. const TCHAR * const pszDomainDirectory = CDirectoryManager::get_DomainDirectory();
  1374. if( pszDomainDirectory != NULL )
  1375. {
  1376. // Make sure the configured domain server name is in the list...
  1377. MRUList.AppendEntry( pszDomainDirectory );
  1378. }
  1379. if( CDirectoryManager::isWebDirectoryEnabled() )
  1380. {
  1381. // Make sure the web directory is in the list...
  1382. MRUList.AppendEntry( CDirectoryManager::get_webDirectoryIls() );
  1383. }
  1384. const TCHAR * const defaultServer = CDirectoryManager::get_defaultServer();
  1385. if( lstrlen( defaultServer ) > 0 )
  1386. {
  1387. // Make sure the default server name is in the list and at the top...
  1388. MRUList.AddNewEntry( defaultServer );
  1389. }
  1390. ::SendMessage( hwndCombo, WM_SETREDRAW, FALSE, 0 );
  1391. ::SendMessage( hwndCombo, CB_RESETCONTENT, 0, 0 );
  1392. int nCount = MRUList.GetNumEntries();
  1393. for( int nn = MRUList.GetNumEntries() - 1; nn >= 0; nn-- )
  1394. {
  1395. ::SendMessage( hwndCombo, CB_ADDSTRING, 0, (LPARAM) CDirectoryManager::get_displayName( MRUList.GetNameEntry( nn ) ) );
  1396. }
  1397. ::SendMessage( hwndCombo, WM_SETREDRAW, TRUE, 0 );
  1398. } // End of FillServerComboBox.
  1399. //////////////////////////////////////////////////////////////////////////////
  1400. //////////////////////////////////////////////////////////////////////////////
  1401. // CWizDirectCallingSettings wizard page
  1402. //////////////////////////////////////////////////////////////////////////////
  1403. //////////////////////////////////////////////////////////////////////////////
  1404. /* static */ HWND CWizDirectCallingSettings::s_hDlg;
  1405. INT_PTR CWizDirectCallingSettings::StaticDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1406. {
  1407. INT_PTR bRet = FALSE;
  1408. if ( message == WM_INITDIALOG )
  1409. {
  1410. PROPSHEETPAGE* pPage = reinterpret_cast<PROPSHEETPAGE*>(lParam);
  1411. SetWindowLongPtr( hDlg, GWLP_USERDATA, pPage->lParam );
  1412. s_hDlg = hDlg;
  1413. CWizDirectCallingSettings* pThis = reinterpret_cast<CWizDirectCallingSettings*>(pPage->lParam);
  1414. if( pThis )
  1415. {
  1416. bRet = pThis->_OnInitDialog();
  1417. }
  1418. }
  1419. else
  1420. {
  1421. CWizDirectCallingSettings* pThis = reinterpret_cast<CWizDirectCallingSettings*>( GetWindowLongPtr( hDlg, GWLP_USERDATA ) );
  1422. if( pThis )
  1423. {
  1424. bRet = pThis->_DlgProc(hDlg, message, wParam, lParam );
  1425. }
  1426. }
  1427. return bRet;
  1428. }
  1429. /* static */ void CWizDirectCallingSettings::OnWizFinish()
  1430. {
  1431. if( s_hDlg && IsWindow( s_hDlg ) )
  1432. {
  1433. CWizDirectCallingSettings* pThis = reinterpret_cast<CWizDirectCallingSettings*>( GetWindowLongPtr( s_hDlg, GWLP_USERDATA ) );
  1434. if( pThis )
  1435. {
  1436. pThis->_OnWizFinish();
  1437. }
  1438. }
  1439. }
  1440. INT_PTR APIENTRY CWizDirectCallingSettings::_DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1441. {
  1442. BOOL bRet = FALSE;
  1443. switch( message )
  1444. {
  1445. case WM_DESTROY:
  1446. s_hDlg = NULL;
  1447. break;
  1448. case WM_NOTIFY:
  1449. {
  1450. NMHDR* pNmHdr = reinterpret_cast<NMHDR*>(lParam);
  1451. switch(pNmHdr->code)
  1452. {
  1453. case PSN_SETACTIVE: return _OnSetActive();
  1454. case PSN_KILLACTIVE: return _OnKillActive();
  1455. case PSN_WIZBACK: return _OnWizBack();
  1456. case PSN_WIZNEXT: bRet = _OnWizNext();
  1457. // We fall through from the WIZ_NEXT becaus
  1458. // we have to save the informaition when we change
  1459. // pages
  1460. case PSN_APPLY:
  1461. case PSN_WIZFINISH: _OnWizFinish();
  1462. }
  1463. break;
  1464. }
  1465. case WM_COMMAND:
  1466. return _OnCommand(wParam, lParam);
  1467. default:
  1468. break;
  1469. }
  1470. return bRet;
  1471. }
  1472. /* static */ bool CWizDirectCallingSettings::IsGatewayNameInvalid()
  1473. {
  1474. TCHAR szServer[MAX_SERVER_NAME_LENGTH];
  1475. szServer[0] = NULL;
  1476. if( s_hDlg )
  1477. {
  1478. GetDlgItemTextTrimmed(s_hDlg, IDE_CALLOPT_GW_SERVER, szServer, CCHMAX(szServer) );
  1479. }
  1480. else
  1481. {
  1482. GetDefaultGateway( szServer, CCHMAX( szServer ) );
  1483. }
  1484. return !IsLegalGatewaySz(szServer);
  1485. }
  1486. void CWizDirectCallingSettings::_SetWizButtons()
  1487. {
  1488. DWORD dwFlags = NULL;
  1489. if( ( BST_CHECKED == IsDlgButtonChecked( s_hDlg, IDC_CHECK_USE_GATEWAY ) ) && IsGatewayNameInvalid() )
  1490. {
  1491. dwFlags = PSWIZB_BACK;
  1492. }
  1493. else
  1494. {
  1495. dwFlags = PSWIZB_BACK | PSWIZB_NEXT;
  1496. }
  1497. if( 0 == GetPageAfterULS() )
  1498. {
  1499. dwFlags |= PSWIZB_FINISH;
  1500. }
  1501. else
  1502. {
  1503. dwFlags |= PSWIZB_NEXT;
  1504. }
  1505. PropSheet_SetWizButtons( GetParent( s_hDlg ), dwFlags );
  1506. }
  1507. BOOL CWizDirectCallingSettings::_OnCommand( WPARAM wParam, LPARAM lParam )
  1508. {
  1509. BOOL bRet = TRUE;
  1510. switch( LOWORD( wParam ) )
  1511. {
  1512. case IDC_CHECK_USE_GATEWAY:
  1513. {
  1514. bool bEnable = ( BST_CHECKED == IsDlgButtonChecked( s_hDlg, IDC_CHECK_USE_GATEWAY ) );
  1515. EnableWindow( GetDlgItem( s_hDlg, IDC_STATIC_GATEWAY_NAME ), bEnable );
  1516. EnableWindow( GetDlgItem( s_hDlg, IDE_CALLOPT_GW_SERVER ), bEnable );
  1517. _SetWizButtons();
  1518. }
  1519. break;
  1520. case IDE_CALLOPT_GW_SERVER:
  1521. if( HIWORD( wParam ) == EN_CHANGE )
  1522. {
  1523. _SetWizButtons();
  1524. }
  1525. break;
  1526. default:
  1527. break;
  1528. }
  1529. return bRet;
  1530. }
  1531. BOOL CWizDirectCallingSettings::_OnInitDialog()
  1532. {
  1533. BOOL bRet = TRUE;
  1534. _SetWizButtons();
  1535. InitDirectoryServicesDlgInfo( s_hDlg, m_pWiz, m_bInitialEnableGateway, m_szInitialServerName, CCHMAX(m_szInitialServerName) );
  1536. return bRet;
  1537. }
  1538. BOOL CWizDirectCallingSettings::_OnSetActive()
  1539. {
  1540. _SetWizButtons();
  1541. if (g_fSilentWizard)
  1542. {
  1543. PropSheet_PressButton(GetParent(s_hDlg), PSBTN_NEXT);
  1544. }
  1545. return FALSE;
  1546. }
  1547. BOOL CWizDirectCallingSettings::_OnKillActive()
  1548. {
  1549. return FALSE;
  1550. }
  1551. BOOL CWizDirectCallingSettings::_OnWizBack()
  1552. {
  1553. UINT iPrev = IDD_PAGE_USER;
  1554. #if USE_GAL
  1555. if( !ConfPolicies::IsGetMyInfoFromGALEnabled() )
  1556. {
  1557. iPrev = IDD_PAGE_USER;
  1558. }
  1559. else
  1560. {
  1561. iPrev = GetPageBeforeULS();
  1562. }
  1563. #endif
  1564. ASSERT( iPrev );
  1565. SetWindowLongPtr( s_hDlg, DWLP_MSGRESULT, iPrev );
  1566. return TRUE;
  1567. }
  1568. BOOL CWizDirectCallingSettings::_OnWizFinish()
  1569. {
  1570. RegEntry reConf(CONFERENCING_KEY, HKEY_CURRENT_USER);
  1571. m_pConf->dwFlags |= ULSCONF_F_PUBLISH | ULSCONF_F_SERVER_NAME;
  1572. // Get the server name
  1573. SendDlgItemMessage( s_hDlg, IDC_NAMESERVER, WM_GETTEXT, CCHMAX( m_pConf->szServerName ), (LPARAM) m_pConf->szServerName );
  1574. TrimSz( m_pConf->szServerName );
  1575. lstrcpyn( m_pConf->szServerName, CDirectoryManager::get_dnsName( m_pConf->szServerName ), CCHMAX( m_pConf->szServerName ) );
  1576. // Get the don't publish flags
  1577. m_pConf->fDontPublish = ( BST_CHECKED == IsDlgButtonChecked( s_hDlg, IDC_USER_PUBLISH ) );
  1578. reConf.SetValue(REGVAL_DONT_LOGON_ULS, BST_CHECKED != IsDlgButtonChecked( s_hDlg, IDC_USEULS ));
  1579. return FALSE;
  1580. }
  1581. BOOL CWizDirectCallingSettings::_OnWizNext()
  1582. {
  1583. UINT_PTR iNext = GetPageAfterULS();
  1584. ASSERT( iNext );
  1585. SetWindowLongPtr( s_hDlg, DWLP_MSGRESULT, iNext );
  1586. return TRUE;
  1587. }
  1588. // Taken from MSDN:
  1589. static HRESULT CreateLink(LPCSTR lpszPathObj,
  1590. LPCTSTR lpszPathLink, LPCSTR lpszDesc)
  1591. {
  1592. HRESULT hres;
  1593. IShellLink* psl;
  1594. // Get a pointer to the IShellLink interface.
  1595. hres = CoCreateInstance(CLSID_ShellLink, NULL,
  1596. CLSCTX_INPROC_SERVER, IID_IShellLink, reinterpret_cast<LPVOID *>(&psl));
  1597. if (SUCCEEDED(hres)) {
  1598. IPersistFile* ppf;
  1599. // Set the path to the shortcut target and add the
  1600. // description.
  1601. psl->SetPath(lpszPathObj);
  1602. if (NULL != lpszDesc)
  1603. {
  1604. psl->SetDescription(lpszDesc);
  1605. }
  1606. // Query IShellLink for the IPersistFile interface for saving the
  1607. // shortcut in persistent storage.
  1608. hres = psl->QueryInterface(IID_IPersistFile,
  1609. reinterpret_cast<LPVOID *>(&ppf));
  1610. if (SUCCEEDED(hres)) {
  1611. #ifndef UNICODE
  1612. WCHAR wsz[MAX_PATH];
  1613. // Ensure that the string is ANSI.
  1614. MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1,
  1615. wsz, MAX_PATH);
  1616. #else // UNICODE
  1617. LPCWSTR wsz = lpszPathLink;
  1618. #endif // UNICODE
  1619. // Save the link by calling IPersistFile::Save.
  1620. hres = ppf->Save(wsz, TRUE);
  1621. ppf->Release();
  1622. }
  1623. psl->Release();
  1624. }
  1625. return hres;
  1626. }
  1627. void DeleteShortcut(int csidl, LPCTSTR pszSubDir)
  1628. {
  1629. TCHAR szSpecial[MAX_PATH];
  1630. if (!NMGetSpecialFolderPath(NULL, szSpecial, csidl, TRUE))
  1631. {
  1632. return;
  1633. }
  1634. LPCTSTR pszNetMtg = RES2T(IDS_MEDIAPHONE_TITLE);
  1635. TCHAR szPath[MAX_PATH];
  1636. wsprintf(szPath, TEXT("%s%s\\%s.lnk"), szSpecial, pszSubDir, pszNetMtg);
  1637. DeleteFile(szPath);
  1638. }
  1639. static void CreateShortcut(HWND hDlg, int csidl, LPCTSTR pszSubDir)
  1640. {
  1641. TCHAR szSpecial[MAX_PATH];
  1642. if (!NMGetSpecialFolderPath(hDlg, szSpecial, csidl, TRUE))
  1643. {
  1644. return;
  1645. }
  1646. LPCTSTR pszNetMtg = RES2T(IDS_MEDIAPHONE_TITLE);
  1647. TCHAR szPath[MAX_PATH];
  1648. wsprintf(szPath, TEXT("%s%s\\%s.lnk"), szSpecial, pszSubDir, pszNetMtg);
  1649. char szThis[MAX_PATH];
  1650. GetModuleFileNameA(NULL, szThis, ARRAY_ELEMENTS(szThis));
  1651. CreateLink(szThis, szPath, NULL);
  1652. }
  1653. INT_PTR CALLBACK ShortcutWizDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1654. {
  1655. switch(uMsg)
  1656. {
  1657. case WM_INITDIALOG:
  1658. CheckDlgButton(hDlg, IDC_ONDESKTOP, BST_CHECKED);
  1659. CheckDlgButton(hDlg, IDC_ONQUICKLAUNCH, BST_CHECKED);
  1660. break;
  1661. case WM_DESTROY:
  1662. if (IsDlgButtonChecked(hDlg, IDC_ONDESKTOP))
  1663. {
  1664. CreateShortcut(hDlg, CSIDL_DESKTOP, g_szEmpty);
  1665. }
  1666. if (IsDlgButtonChecked(hDlg, IDC_ONQUICKLAUNCH))
  1667. {
  1668. CreateShortcut(hDlg, CSIDL_APPDATA, QUICK_LAUNCH_SUBDIR);
  1669. }
  1670. break;
  1671. case WM_NOTIFY:
  1672. {
  1673. NMHDR* pNmHdr = reinterpret_cast<NMHDR*>(lParam);
  1674. switch(pNmHdr->code)
  1675. {
  1676. case PSN_RESET:
  1677. // HACKHACK georgep: Uncheck the buttons so we will not try to
  1678. // create the shortcuts
  1679. CheckDlgButton(hDlg, IDC_ONDESKTOP, BST_UNCHECKED);
  1680. CheckDlgButton(hDlg, IDC_ONQUICKLAUNCH, BST_UNCHECKED);
  1681. // Fall through
  1682. default:
  1683. return(IntroWiz::HandleWizNotify(hDlg, pNmHdr, IntroWiz::Shortcuts));
  1684. }
  1685. break;
  1686. }
  1687. default:
  1688. return(FALSE);
  1689. }
  1690. return(TRUE);
  1691. }
  1692.