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.

2209 lines
68 KiB

  1. //
  2. // prwizard.cpp
  3. //
  4. // Copyright (c) Microsoft Corp, 2000
  5. //
  6. // This file contains source code for presenting UI wizards to guide the user
  7. // in creating a password recovery key disk/file, and using such a file to
  8. // reset the password on an account.
  9. //
  10. // History:
  11. //
  12. // georgema 8/17/2000 Created
  13. //
  14. //
  15. // Exports: PRShowSaveWizard
  16. // PRShowRestoreWizard
  17. //
  18. // Dependencies: shellapi.h, shell32.lib for SHGetFileInfo()
  19. #pragma comment(user, "Compiled on " __DATE__ " at " __TIME__)
  20. #pragma comment(compiler)
  21. #include <nt.h>
  22. #include <ntrtl.h>
  23. #include <nturtl.h>
  24. #include <ntstatus.h> // STATUS_... error values
  25. #include <windows.h>
  26. #include <shellapi.h>
  27. #include <ole2.h>
  28. #include <security.h>
  29. #include <tchar.h>
  30. #include <io.h> // _waccess
  31. #include <stdlib.h>
  32. #include <commdlg.h>
  33. #include <passrec.h>
  34. #include <lm.h>
  35. #include <prsht.h> // includes the property sheet functionality
  36. #include <netlib.h>
  37. #include <commctrl.h>
  38. #include <comctrlp.h>
  39. #include <shfusion.h>
  40. #include "switches.h"
  41. #include "wizres.h" // includes the definitions for the resources
  42. #include "keymgr.h"
  43. #include "diskio.h"
  44. #include "testaudit.h"
  45. // All of these definitions are for updating the password hint for the user
  46. // DirectUser and DirectUI
  47. #ifdef PASSWORDHINT
  48. #include <shgina.h>
  49. #endif
  50. // Symbols and variables of global significance
  51. #define FILESPACENEEDED 8192 // how much must be on disk - conservative
  52. #define LERROR_NO_ACCOUNT (0x80008888)
  53. #define NUMSAVEPAGES 5 // how many pages of save wizard
  54. #define NUMRESTOREPAGES 4 // how many pages of restore wizard
  55. #define TEMPSTRINGBUFSIZE 500
  56. //#define PSWBUFSIZE 20
  57. #define TIMERPERIOD 1000 // 1 second tick timer for progress
  58. #define TIMERID 1001
  59. // Error values from SaveThread
  60. #define ERRNOFILE 2
  61. #define ERRSAVEERROR 1
  62. #define ERRSUCCESS 0
  63. // Variables defined in other files
  64. extern HINSTANCE g_hInstance; // shared with keymgr
  65. extern HANDLE g_hFile;
  66. extern INT g_iFileSize;
  67. // Global vars shared with disk subsystem
  68. TCHAR pszFileName[] = TEXT("A:\\userkey.psw");
  69. HWND c_hDlg;
  70. // File scope (locally global)
  71. static WCHAR Buf[TEMPSTRINGBUFSIZE]; // gen purpose scratch string
  72. static WCHAR rgszDrives[200]; // drive strings cache
  73. static INT c_ArrayCount = 0;
  74. static INT c_DriveCount = 0;
  75. static INT c_fDrivesCounted = FALSE;
  76. static WCHAR c_rgcFileName[MAX_PATH];
  77. static WCHAR c_rgcPsw[PWLEN + 1];
  78. static WCHAR c_rgcOldPsw[PWLEN + 1];
  79. static WCHAR c_rgcUser[UNLEN + 1] = {0};
  80. static WCHAR c_rgcDomain[UNLEN + 1];
  81. static HCURSOR c_hCursor;
  82. static UINT_PTR c_iTimer;
  83. static HWND c_hProgress;
  84. static INT c_iProg = 0;
  85. static HWND c_TimerAssociatedWindow;
  86. static BOOL c_bSaveComplete = FALSE;
  87. // Recovery data
  88. static BYTE *c_pPrivate = NULL;
  89. static INT c_cbPrivate = 0;
  90. // Page control handles
  91. static HWND c_hwndSWelcome1;
  92. static HWND c_hwndSWelcome2;
  93. static HWND c_hwndSInstructions;
  94. static HWND c_hwndSP1E1;
  95. static HWND c_hwndSP1E2;
  96. static HWND c_hwndSFinish1;
  97. static HWND c_hwndSFinish2;
  98. static HWND c_hwndSCancel;
  99. static HWND c_hwndDriveInstructions;
  100. static HWND c_hwndDrivePrompt;
  101. static HWND c_hwndCBDriveList;
  102. static HWND c_hwndRWelcome1;
  103. static HWND c_hwndRWelcome2;
  104. static HWND c_hwndRInstructions;
  105. static HWND c_hwndRP1E1;
  106. static HWND c_hwndRP1E2;
  107. static HWND c_hwndRP1E3;
  108. static HWND c_hwndRBackup;
  109. static HWND c_hwndRFinish1;
  110. static HWND c_hwndRFinish2;
  111. static HWND c_hwndRCancel;
  112. static HFONT c_hTitleFont;
  113. static BOOL c_fIsBackup;
  114. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  115. //
  116. // Common utility functions
  117. //
  118. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  119. WCHAR *RString(INT iResID)
  120. {
  121. ASSERT(iResID);
  122. Buf[0] = 0;
  123. if (NULL != g_hInstance)
  124. {
  125. LoadString(g_hInstance,iResID,Buf,TEMPSTRINGBUFSIZE);
  126. }
  127. return Buf;
  128. }
  129. /**********************************************************************
  130. RMessageBox() - Wrapper for MessageBox(), allowing text elements to be
  131. specified either by resource ID or by a pointer to a string. Text
  132. ID greater and 0x1000 (4096) is taken to be a pointer.
  133. **********************************************************************/
  134. int RMessageBox(HWND hw,UINT_PTR uiResIDTitle, UINT_PTR uiResIDText, UINT uiType)
  135. {
  136. WCHAR tBuf[TEMPSTRINGBUFSIZE];
  137. WCHAR mBuf[TEMPSTRINGBUFSIZE];
  138. INT_PTR iCount = 0;
  139. tBuf[0] = 0;
  140. mBuf[0] = 0;
  141. ASSERT(g_hInstance);
  142. if (NULL != g_hInstance)
  143. {
  144. if (uiResIDTitle < 4096)
  145. {
  146. iCount = LoadString(g_hInstance,(UINT)uiResIDTitle,tBuf,TEMPSTRINGBUFSIZE);
  147. }
  148. else
  149. {
  150. wcsncpy(tBuf,(WCHAR *)uiResIDTitle,TEMPSTRINGBUFSIZE);
  151. tBuf[TEMPSTRINGBUFSIZE - 1] = 0;
  152. }
  153. if (uiResIDTitle < 4096)
  154. {
  155. iCount = LoadString(g_hInstance,(UINT)uiResIDText,mBuf,TEMPSTRINGBUFSIZE);
  156. }
  157. else
  158. {
  159. wcsncpy(mBuf,(WCHAR *)uiResIDText,TEMPSTRINGBUFSIZE);
  160. mBuf[TEMPSTRINGBUFSIZE - 1] = 0;
  161. }
  162. if (0 != iCount)
  163. {
  164. return MessageBox(hw,mBuf,tBuf,uiType);
  165. }
  166. }
  167. // 0 is error return value from MessageBox()
  168. return 0;
  169. }
  170. /**********************************************************************
  171. RSetControlText() - Set text of dialog control by ID to string by ID.
  172. String ID of zero clears the control.
  173. **********************************************************************/
  174. void RSetControlText(UINT uiControlID, UINT uiTextID)
  175. {
  176. WCHAR tBuf[TEMPSTRINGBUFSIZE];
  177. INT iCount;
  178. ASSERT(g_hInstance);
  179. ASSERT(uiControlID);
  180. if ((NULL != g_hInstance) && (0 != uiControlID))
  181. {
  182. if (0 != uiTextID)
  183. {
  184. iCount = LoadString(g_hInstance,uiTextID,tBuf,TEMPSTRINGBUFSIZE);
  185. if (iCount)
  186. {
  187. SetDlgItemText(c_hDlg,uiControlID,tBuf);
  188. }
  189. else
  190. {
  191. SetDlgItemText(c_hDlg,uiControlID,L"");
  192. }
  193. }
  194. else
  195. {
  196. SetDlgItemText(c_hDlg,uiControlID,L"");
  197. }
  198. }
  199. return;
  200. }
  201. /**********************************************************************
  202. CreateFontY() - Create the fond to use in the wizard.
  203. **********************************************************************/
  204. HFONT CreateFontY(LPCTSTR pszFontName,LONG lWeight,LONG lHeight)
  205. {
  206. NONCLIENTMETRICS ncm = {0};
  207. if (NULL == pszFontName)
  208. {
  209. return NULL;
  210. }
  211. if (0 == lHeight)
  212. {
  213. return NULL;
  214. }
  215. ncm.cbSize = sizeof(ncm);
  216. if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS,0,&ncm,0))
  217. {
  218. return NULL;
  219. }
  220. LOGFONT TitleLogFont = ncm.lfMessageFont;
  221. TitleLogFont.lfWeight = lWeight;
  222. lstrcpyn(TitleLogFont.lfFaceName,pszFontName,LF_FACESIZE);
  223. HDC hdc = GetDC(NULL);
  224. if (NULL == hdc)
  225. {
  226. return NULL;
  227. }
  228. INT FontSize = lHeight;
  229. TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72;
  230. HFONT h = CreateFontIndirect(&TitleLogFont);
  231. ReleaseDC(NULL,hdc);
  232. return h;
  233. }
  234. /**********************************************************************
  235. CenterPage() - Center the passed window on the screen.
  236. **********************************************************************/
  237. void CenterPage(HWND hwndIn)
  238. {
  239. RECT rectWorkArea;
  240. RECT rectWindow;
  241. DWORD FreeWidth, Width, FreeHeight, Height;
  242. if (!SystemParametersInfo(SPI_GETWORKAREA,0,&rectWorkArea,0))
  243. {
  244. return;
  245. }
  246. GetWindowRect(hwndIn,&rectWindow);
  247. Height = (rectWorkArea.bottom - rectWorkArea.top);
  248. Width = (rectWorkArea.right - rectWorkArea.left);
  249. FreeHeight = Height - (rectWindow.bottom - rectWindow.top);
  250. FreeWidth = Width - (rectWindow.right - rectWindow.left);
  251. MoveWindow(hwndIn,
  252. FreeWidth / 2,
  253. FreeHeight / 2,
  254. (rectWindow.right - rectWindow.left),
  255. (rectWindow.bottom - rectWindow.top),
  256. TRUE);
  257. return;
  258. }
  259. /**********************************************************************
  260. FetchPsw() - Fetch password from two password windows. Return TRUE on
  261. success, else show message box for user error and return false. User
  262. errors include:
  263. 1. two passwords do not match
  264. 2. either password is blank
  265. Copies user entered password to global string c_rgcPsw.
  266. **********************************************************************/
  267. BOOL FetchPsw(HWND hE1,HWND hE2)
  268. {
  269. TCHAR rgcE1[PWLEN + 1];
  270. TCHAR rgcE2[PWLEN + 1];
  271. INT_PTR iCount;
  272. rgcE1[0] = 0;
  273. rgcE2[0] = 0;
  274. if ((NULL == hE2) || (NULL == hE1))
  275. {
  276. return FALSE;
  277. }
  278. iCount = SendMessage(hE1,WM_GETTEXT,PWLEN + 1,(LPARAM) rgcE1);
  279. iCount = SendMessage(hE2,WM_GETTEXT,PWLEN + 1,(LPARAM) rgcE2);
  280. if (0 != _tcsncmp(rgcE1,rgcE2,PWLEN))
  281. {
  282. RMessageBox(c_hDlg,IDS_MBTINVALIDPSW ,IDS_BADPSW ,MB_ICONHAND);
  283. return FALSE;
  284. }
  285. #ifdef NOBLANKPASSWORD
  286. if (rgcE1[0] == 0)
  287. {
  288. RMessageBox(c_hDlg,IDS_MBTMISSINGPSW ,IDS_NOPSW ,MB_ICONHAND);
  289. return FALSE;
  290. }
  291. #endif
  292. #if TESTAUDIT
  293. if (wcslen(rgcE1) > 25)
  294. {
  295. CHECKPOINT(65,"Wizard: Password length > 25 chars");
  296. }
  297. #endif
  298. _tcsncpy(c_rgcPsw,rgcE1,PWLEN);
  299. c_rgcPsw[PWLEN] = 0;
  300. return TRUE;
  301. }
  302. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  303. //
  304. // File and Disk manipulation functions
  305. //
  306. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  307. #define FILENAMESIZE 255;
  308. /**********************************************************************
  309. FileMediumIsRemoveable() - Accept pathname of file to create, return
  310. TRUE if pathname is to a removeable medium like a floppy or zipdisk.
  311. **********************************************************************/
  312. BOOL FileMediumIsRemoveable(TCHAR *pszPath)
  313. {
  314. return (DRIVE_REMOVABLE == GetDriveType(pszPath));
  315. }
  316. /**********************************************************************
  317. FileMediumIsEncrypted
  318. Accepts an input file path which may be a filename, and returns TRUE if the file
  319. is/would be encrypted.
  320. Note that this function touches the drive. Attempting to call FileMediumIsEncrypted()
  321. on a floppy drive path with no floppy in the drive produces a pop-up error box.
  322. **********************************************************************/
  323. BOOL FileMediumIsEncrypted(TCHAR *pszPath)
  324. {
  325. TCHAR rgcPath[MAX_PATH];
  326. TCHAR *pOldHack = NULL;
  327. TCHAR *pHack;
  328. DWORD dwAttr;
  329. #ifdef GMDEBUG
  330. OutputDebugString(L"File path = ");
  331. OutputDebugString(pszPath);
  332. OutputDebugString(L"\n");
  333. #endif
  334. _tcsncpy(rgcPath,pszPath,MAX_PATH-1);
  335. pHack = rgcPath;
  336. do
  337. {
  338. pOldHack = pHack;
  339. pHack = _tcschr(++pHack,TCHAR('\\'));
  340. } while (pHack);
  341. if (pOldHack == NULL)
  342. {
  343. return FALSE;
  344. }
  345. *pOldHack = 0;
  346. #ifdef GMDEBUG
  347. OutputDebugString(L"Trimmed path =");
  348. OutputDebugString(pszPath);
  349. OutputDebugString(L"\n");
  350. #endif
  351. dwAttr = GetFileAttributes(rgcPath);
  352. if (-1 == dwAttr)
  353. {
  354. return FALSE;
  355. }
  356. if (dwAttr & FILE_ATTRIBUTE_ENCRYPTED)
  357. {
  358. #ifdef GMDEBUG
  359. OutputDebugString(L"File is encrypted\n");
  360. #endif
  361. return TRUE;
  362. }
  363. else return FALSE;
  364. }
  365. /**********************************************************************
  366. CountRemoveableDrives
  367. Called to determine whether it is appropriate to display the drive selection page.
  368. The return value is the number of such drives available.
  369. If 0, a message box announces that a backup cannot be made and why
  370. If 1, the drive select page should be skipped
  371. If more than one, the user chooses the drive
  372. **********************************************************************/
  373. INT CountRemoveableDrives(void) {
  374. //TCHAR rgszDrives[100];
  375. DWORD dwcc;
  376. TCHAR *pc;
  377. INT iCount = 0;
  378. WCHAR wcDriveLetter = L'A';
  379. if (c_fDrivesCounted)
  380. {
  381. return c_DriveCount;
  382. }
  383. dwcc = GetLogicalDriveStrings(200,rgszDrives);
  384. if (0 == dwcc)
  385. {
  386. return 0;
  387. }
  388. pc = rgszDrives;
  389. while (*pc != 0)
  390. {
  391. if (FileMediumIsRemoveable(pc))
  392. {
  393. if (DRIVE_CDROM != GetDriveType(pc))
  394. {
  395. #ifdef LOUDLY
  396. OutputDebugString(L"Removeable drive: ");
  397. OutputDebugString(pc);
  398. OutputDebugString(L"\n");
  399. //MessageBox(NULL,pc,pc,MB_OK);
  400. #endif
  401. iCount++;
  402. wcDriveLetter = *pc;
  403. }
  404. }
  405. while(*pc != 0)
  406. {
  407. pc++;
  408. }
  409. pc++;
  410. }
  411. c_DriveCount = iCount;
  412. c_fDrivesCounted = TRUE;
  413. // If only 1 drive, go ahead and stamp the filename
  414. if (1 == iCount)
  415. {
  416. CHECKPOINT(54,"Wizard: Both - Exactly one removeable drive");
  417. pszFileName[0] = wcDriveLetter;
  418. }
  419. return iCount;
  420. }
  421. /**********************************************************************
  422. Get the UI string for the named drive
  423. **********************************************************************/
  424. BOOL GetDriveUIString(WCHAR *pszFilePath,WCHAR *pszUIString,INT icbSize,HANDLE *phImageList,INT *piIconIndex)
  425. {
  426. WCHAR rgcModel[] = {L"A:\\"};
  427. SHFILEINFO sfi = {0};
  428. if ((NULL == pszUIString) || (NULL == pszFilePath))
  429. {
  430. return FALSE;
  431. }
  432. rgcModel[0] = *pszFilePath;
  433. DWORD_PTR dwRet = SHGetFileInfo(rgcModel,FILE_ATTRIBUTE_DIRECTORY,&sfi,sizeof(sfi),
  434. 0 |
  435. SHGFI_SYSICONINDEX |
  436. SHGFI_SMALLICON |
  437. SHGFI_DISPLAYNAME);
  438. if ( 0 == dwRet)
  439. {
  440. return FALSE; // failed to get the string
  441. }
  442. wcsncpy(pszUIString,sfi.szDisplayName,(icbSize / sizeof(WCHAR)) -sizeof(WCHAR));
  443. *piIconIndex = sfi.iIcon;
  444. *phImageList = (HANDLE) dwRet;
  445. return TRUE;
  446. }
  447. /**********************************************************************
  448. ShowRemoveableDrives
  449. Called from within SPageProcX, the page procedure for the drive selection page, this
  450. function gets the available logical drives on the system, filters them one by one
  451. keeping only removeable and unencrypted volumes.
  452. These are assigned to up to six radio button text labels on IDD_SPAGEX
  453. The return value is the number of such drives available.
  454. If 0, a message box announces the failure condition, and the wizard exits
  455. If 1, this page is skipped, and that drive letter is inserted in the file name string
  456. If more than one, the user chooses the drive
  457. **********************************************************************/
  458. INT ShowRemoveableDrives(void)
  459. {
  460. //TCHAR rgszDrives[200];
  461. DWORD dwcc;
  462. TCHAR *pc;
  463. WCHAR rgcszUI[80];
  464. HANDLE hIcons;
  465. INT iIcons;
  466. BOOL fSetImageList = TRUE;
  467. COMBOBOXEXITEM stItem = {0};
  468. INT iDrive = 0;
  469. ASSERT(c_hwndCBDriveList);
  470. // test and show
  471. dwcc = GetLogicalDriveStrings(200,rgszDrives);
  472. if (0 == dwcc)
  473. {
  474. goto fail;
  475. }
  476. pc = rgszDrives;
  477. while (*pc != 0)
  478. {
  479. rgcszUI[0] = 0;
  480. if (!GetDriveUIString(pc,rgcszUI,80,&hIcons,&iIcons))
  481. {
  482. goto fail;
  483. }
  484. if ((fSetImageList) && (hIcons != NULL))
  485. {
  486. // set image list for the edit control to the system image list
  487. // returned from GetDriveUIString
  488. SendMessage(c_hwndCBDriveList,CBEM_SETIMAGELIST,
  489. 0,(LPARAM)(HIMAGELIST) hIcons);
  490. fSetImageList = FALSE;
  491. }
  492. #ifdef LOUDLY
  493. {
  494. OutputDebugString(L"Drive ");
  495. OutputDebugString(pc);
  496. OutputDebugString(L"=");
  497. OutputDebugString(rgcszUI);
  498. OutputDebugString(L"\n");
  499. }
  500. #endif
  501. if (FileMediumIsRemoveable(pc))
  502. {
  503. if (DRIVE_CDROM != GetDriveType(pc))
  504. {
  505. #ifdef LOUDLY
  506. {
  507. WCHAR sz[100];
  508. _stprintf(sz,L"Drive %s added as removeable drive index %d\n",pc,iDrive);
  509. OutputDebugString(sz);
  510. }
  511. #endif
  512. // add string to combo box
  513. stItem.mask = CBEIF_SELECTEDIMAGE |CBEIF_IMAGE | CBEIF_TEXT | CBEIF_LPARAM;
  514. stItem.pszText = rgcszUI;
  515. stItem.iImage = iIcons;
  516. stItem.iSelectedImage = iIcons;
  517. stItem.lParam = iDrive;
  518. stItem.iItem = -1;
  519. SendMessage(c_hwndCBDriveList,CBEM_INSERTITEM,0,(LPARAM) &stItem);
  520. }
  521. }
  522. iDrive++;
  523. #if TESTAUDIT
  524. if (iDrive == 0) CHECKPOINT(53,"Wizard: Both - no removeable drives");
  525. if (iDrive > 1) CHECKPOINT(52,"Wizard: Both - more than 1 removeable drive");
  526. #endif
  527. while(*pc != 0)
  528. {
  529. pc++;
  530. }
  531. pc++;
  532. }
  533. c_ArrayCount = iDrive;
  534. SendMessage(c_hwndCBDriveList,CB_SETCURSEL,0,0);
  535. return 1;
  536. fail:
  537. // show message box
  538. return 0;
  539. }
  540. /**********************************************************************
  541. Get drive letter for zero-based drive number from the drive name strings in rgszDrives.
  542. Note that c_ArrayCount is 1-based.
  543. **********************************************************************/
  544. WCHAR GetDriveLetter(INT iDrive)
  545. {
  546. WCHAR *pc;
  547. pc = rgszDrives;
  548. // return default driveletter if input invalid
  549. if ((iDrive == 0) || (iDrive < 0) || (iDrive >= c_ArrayCount))
  550. {
  551. return *pc;
  552. }
  553. for (INT i=0;i<iDrive;i++)
  554. {
  555. while(*pc != 0) pc++; // skip non-nulls
  556. while(*pc == 0) pc++; // skip nulls
  557. }
  558. return *pc;
  559. }
  560. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  561. //
  562. // Password restore/recover functionality routines called within the UI
  563. //
  564. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  565. /****************************************************************************\
  566. ExistsOldKey
  567. Inputs: TCHAR pszUser
  568. Returns: TRUE if user has an existing password backup, FALSE otherwise.
  569. The username string is an account name on the local machine, not prefixed by the
  570. machine name.
  571. \****************************************************************************/
  572. BOOL ExistsOldKey(TCHAR *pszUser)
  573. {
  574. DWORD BUStatus;
  575. if (0 == PRQueryStatus(NULL, pszUser,&BUStatus))
  576. {
  577. if (0 == BUStatus)
  578. {
  579. return TRUE;
  580. }
  581. }
  582. return FALSE;
  583. }
  584. /****************************************************************************\
  585. GetNames()
  586. Gets local machine domain name and the username for later use by LogonUser() to
  587. test the password entered by the user. A username may be passed in via psz. If
  588. psz is NULL, the currently logged in username will be used. Retrieved strings are
  589. placed in global strings c_rgcDomain and c_rgcUser.
  590. Inputs: WCHAR username string
  591. Call with NULL psz to use currently logged on username
  592. Returns: void
  593. If function fails, the affected global string is set to empty string.
  594. \****************************************************************************/
  595. void GetNames(WCHAR *psz)
  596. {
  597. OSVERSIONINFOEXW versionInfo;
  598. BOOL fIsDC = FALSE;
  599. WCHAR *pName = NULL;
  600. DWORD dwStatus;
  601. DWORD dwcb;
  602. versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
  603. if (GetVersionEx((OSVERSIONINFO *)&versionInfo))
  604. {
  605. fIsDC = (versionInfo.wProductType == VER_NT_DOMAIN_CONTROLLER);
  606. }
  607. if (fIsDC)
  608. {
  609. dwStatus = NetpGetDomainName(&pName);
  610. if (dwStatus == NO_ERROR)
  611. {
  612. wcsncpy(c_rgcDomain,pName,UNLEN);
  613. c_rgcDomain[UNLEN] = 0;
  614. NetApiBufferFree(pName);
  615. }
  616. else c_rgcDomain[0] = 0;
  617. }
  618. else
  619. {
  620. dwStatus = NetpGetComputerName(&pName);
  621. if (dwStatus == NO_ERROR)
  622. {
  623. wcsncpy(c_rgcDomain,pName,UNLEN);
  624. c_rgcDomain[UNLEN] = 0;
  625. NetApiBufferFree(pName);
  626. }
  627. else c_rgcDomain[0] = 0;
  628. }
  629. if (psz)
  630. {
  631. wcsncpy(c_rgcUser,psz,UNLEN);
  632. c_rgcUser[UNLEN] = 0;
  633. }
  634. else
  635. {
  636. dwcb = UNLEN + 1;
  637. GetUserNameW(c_rgcUser,&dwcb);
  638. }
  639. #ifdef LOUDLY
  640. OutputDebugString(L"GetNames: ");
  641. OutputDebugString(c_rgcDomain);
  642. OutputDebugString(L" ");
  643. OutputDebugString(c_rgcUser);
  644. OutputDebugString(L"\n");
  645. OutputDebugString(L"Passed Username = ");
  646. if (psz)OutputDebugString(psz);
  647. OutputDebugString(L"\n");
  648. #endif
  649. }
  650. #ifdef PASSWORDHINT
  651. /**********************************************************************
  652. SetUserHint() - Set the password hint on a local account by reference
  653. to the username, to a string passed by WCHAR *
  654. **********************************************************************/
  655. HRESULT
  656. SetUserHint(LPCWSTR pszAccountName,LPCWSTR pszNewHint)
  657. {
  658. HRESULT hr;
  659. ILogonEnumUsers *pUsers = NULL;
  660. VARIANT var;
  661. hr = CoCreateInstance(CLSID_ShellLogonEnumUsers,
  662. NULL,
  663. CLSCTX_INPROC_SERVER,
  664. IID_ILogonEnumUsers,
  665. (void **) &pUsers);
  666. if (SUCCEEDED(hr))
  667. {
  668. ILogonUser *pUser = NULL;
  669. var.vt = VT_BSTR;
  670. var.bstrVal = SysAllocString(pszAccountName);
  671. hr = pUsers->item(var,&pUser);
  672. if (SUCCEEDED(hr))
  673. {
  674. BSTR bstrHint = SysAllocString(L"Hint");
  675. VariantClear(&var); // free embedded bstr
  676. var.vt = VT_BSTR;
  677. var.bstrVal = SysAllocString(pszNewHint);
  678. hr = pUser->put_setting(bstrHint,var);
  679. // There is no fallback for failure to set the hint. Just proceed.
  680. SysFreeString(bstrHint);
  681. pUser->Release();
  682. }
  683. VariantClear(&var); // free embedded bstr
  684. pUsers->Release();
  685. }
  686. return hr;
  687. }
  688. #endif
  689. /**********************************************************************
  690. SetAccountPassword() - Call the DPAPI password change function, passing
  691. the password blob from the reset disk by means of global variables.
  692. **********************************************************************/
  693. DWORD
  694. SetAccountPassword(void)
  695. {
  696. DWORD dwErr = ERROR_FUNCTION_FAILED;
  697. CHECKPOINT(58,"Wizard: Restore - Set account password");
  698. c_pPrivate = 0;
  699. if (!ReadPrivateData(&c_pPrivate,&c_cbPrivate))
  700. {
  701. dwErr = GetLastError();
  702. goto cleanup;
  703. }
  704. if( (c_rgcUser[0] == 0))
  705. {
  706. dwErr = LERROR_NO_ACCOUNT;
  707. goto cleanup;
  708. }
  709. dwErr = PRRecoverPassword(c_rgcUser,
  710. c_pPrivate,
  711. c_cbPrivate,
  712. c_rgcPsw);
  713. #ifdef PASSWORDHINT
  714. if (0 == dwErr)
  715. {
  716. INT_PTR icb = 0;
  717. WCHAR szHint[256];
  718. szHint[0] = 0;
  719. icb = SendMessage(c_hwndRP1E3,WM_GETTEXT,255,(LPARAM)szHint);
  720. SetUserHint(c_rgcUser,szHint);
  721. }
  722. #endif
  723. cleanup:
  724. // ensure that buffers are cleaned and released
  725. SecureZeroMemory(c_rgcPsw,sizeof(c_rgcPsw));
  726. if (NULL != c_pPrivate)
  727. {
  728. ReleaseFileBuffer((LPVOID) c_pPrivate);
  729. }
  730. c_pPrivate = NULL;
  731. return dwErr;
  732. }
  733. /****************************************************************************\
  734. SaveInfo
  735. Inputs: void, uses globals c_rgcUser, c_rgcPsw
  736. Returns: INT, returns nonzero if a password backup has been generated on the host
  737. machine, and a valid private blob has been generated and written to the
  738. target disk
  739. \****************************************************************************/
  740. INT
  741. SaveInfo(void)
  742. {
  743. BOOL fError = TRUE;
  744. DWORD dwRet;
  745. BOOL fStatus = FALSE;
  746. BYTE *pPrivate = NULL;
  747. DWORD cbPrivate = 0;
  748. CHECKPOINT(50,"Wizard: Save - generating recovery data");
  749. c_hCursor = LoadCursor(g_hInstance,IDC_WAIT);
  750. c_hCursor = SetCursor(c_hCursor);
  751. #ifdef LOUDLY
  752. OutputDebugString(L"SaveInfo: Username = ");
  753. OutputDebugString(c_rgcUser);
  754. OutputDebugString(L"\n");
  755. #endif
  756. #ifdef LOUDLY
  757. OutputDebugString(c_rgcUser);
  758. OutputDebugString(L" \\ ");
  759. OutputDebugString(c_rgcPsw);
  760. OutputDebugString(L"\n");
  761. #endif
  762. dwRet = PRGenerateRecoveryKey(c_rgcUser,
  763. c_rgcPsw,
  764. &pPrivate,
  765. &cbPrivate);
  766. #ifdef LOUDLY
  767. OutputDebugString(L"PRGenerateRecoveryKey returns\n");
  768. #endif
  769. if (ERROR_SUCCESS != dwRet)
  770. {
  771. #ifdef LOUDLY
  772. OutputDebugString(L"GenerateRecoveryKey failed\n");
  773. #endif
  774. goto cleanup;
  775. }
  776. if (!WritePrivateData(pPrivate,cbPrivate))
  777. {
  778. #ifdef LOUDLY
  779. OutputDebugString(L"WriteOutputFile failed\n");
  780. #endif
  781. CHECKPOINT(51,"Wizard: Save - write failed (disk full?)");
  782. // delete output file if created
  783. DeleteFile(pszFileName);
  784. goto cleanup;
  785. }
  786. #if TESTAUDIT
  787. else
  788. {
  789. CHECKPOINT(55,"Wizard: Save - write to disk OK");
  790. }
  791. #endif
  792. SetFileAttributes(pszFileName,FILE_ATTRIBUTE_READONLY);
  793. if (0 == cbPrivate)
  794. {
  795. goto cleanup;
  796. }
  797. fStatus = TRUE;
  798. fError = FALSE;
  799. cleanup:
  800. // zero buffer of c_usPassword (our local psw buffer)
  801. SecureZeroMemory(c_rgcPsw,sizeof(c_rgcPsw));
  802. SecureZeroMemory(pPrivate,cbPrivate);
  803. if (fError)
  804. {
  805. KillTimer(c_TimerAssociatedWindow,TIMERID);
  806. RMessageBox(c_hDlg,IDS_MBTERROR ,IDS_SERROR ,MB_ICONHAND);
  807. c_iTimer = SetTimer(c_TimerAssociatedWindow,TIMERID,TIMERPERIOD,NULL);
  808. }
  809. //cleanupnomsg:
  810. if (fError)
  811. {
  812. // delete output file
  813. if (g_hFile)
  814. {
  815. CloseHandle(g_hFile);
  816. g_hFile = NULL;
  817. DeleteFile(pszFileName);
  818. }
  819. }
  820. if (NULL != g_hFile)
  821. {
  822. CloseHandle(g_hFile);
  823. g_hFile = NULL;
  824. }
  825. LocalFree(pPrivate);
  826. return fStatus;
  827. }
  828. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  829. //
  830. // WELCOME page proc doesn't have to do much
  831. //
  832. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  833. INT_PTR CALLBACK SPageProc0(
  834. HWND hDlg,
  835. UINT message,
  836. WPARAM wParam,
  837. LPARAM lParam)
  838. {
  839. switch (message)
  840. {
  841. case WM_INITDIALOG:
  842. {
  843. TCHAR SBuf[TEMPSTRINGBUFSIZE];
  844. c_hDlg = hDlg;
  845. c_hwndSWelcome1 = GetDlgItem(hDlg,IDC_SWELCOME1);
  846. if (NULL != c_hTitleFont)
  847. {
  848. SendMessage(c_hwndSWelcome1,WM_SETFONT,(WPARAM) c_hTitleFont,(LPARAM) TRUE);
  849. }
  850. LoadString(g_hInstance,IDS_SWELCOME1,SBuf,TEMPSTRINGBUFSIZE);
  851. SendMessage(c_hwndSWelcome1,WM_SETTEXT,0,(LPARAM)SBuf);
  852. c_hwndSWelcome2 = GetDlgItem(hDlg,IDC_SWELCOME2);
  853. LoadString(g_hInstance,IDS_SWELCOME2,SBuf,TEMPSTRINGBUFSIZE);
  854. SendMessage(c_hwndSWelcome2,WM_SETTEXT,0,(LPARAM)SBuf);
  855. break;
  856. }
  857. case WM_COMMAND:
  858. //if (HIWORD(wParam) == BN_CLICKED)
  859. //{
  860. // // crack the incoming command messages
  861. // INT NotifyId = HIWORD(wParam);
  862. // INT ControlId = LOWORD(wParam);
  863. //}
  864. break;
  865. case WM_NOTIFY:
  866. switch (((NMHDR FAR *) lParam)->code)
  867. {
  868. case PSN_KILLACTIVE:
  869. SetWindowLong(hDlg,DWLP_MSGRESULT, FALSE);
  870. return 1;
  871. break;
  872. case PSN_SETACTIVE:
  873. // state following a BACK from the next page
  874. CenterPage(GetParent(hDlg));
  875. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_NEXT);
  876. break;
  877. case PSN_RESET:
  878. if (c_hTitleFont) DeleteObject(c_hTitleFont);
  879. break;
  880. case PSN_WIZNEXT:
  881. break;
  882. default:
  883. return FALSE;
  884. }
  885. break;
  886. default:
  887. return FALSE;
  888. }
  889. return TRUE;
  890. }
  891. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  892. //
  893. // PAGE1 page proc, where the real work is done
  894. //
  895. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  896. DWORD c_iThread;
  897. DWORD dwThreadReturn;
  898. DWORD WINAPI SaveThread(LPVOID lpv)
  899. {
  900. c_bSaveComplete = FALSE;
  901. if (g_hFile == NULL)
  902. {
  903. c_bSaveComplete = TRUE;
  904. dwThreadReturn = ERRNOFILE;
  905. return 2;
  906. }
  907. if (FALSE == SaveInfo())
  908. {
  909. if (g_hFile)
  910. {
  911. CloseHandle(g_hFile);
  912. }
  913. g_hFile = NULL;
  914. c_bSaveComplete = TRUE;
  915. dwThreadReturn = ERRSAVEERROR;
  916. return 1;
  917. }
  918. if (g_hFile)
  919. {
  920. CloseHandle(g_hFile);
  921. }
  922. g_hFile = NULL;
  923. c_bSaveComplete = TRUE;
  924. dwThreadReturn = ERRSUCCESS;
  925. return 0;
  926. }
  927. // Dialog procedure for the drive selection page. This page is common to both the backup and
  928. // restore wizards, with the instruction text being selected on the basis of which mode is being
  929. // exercised.
  930. INT_PTR CALLBACK SPageProcX(
  931. HWND hDlg,
  932. UINT message,
  933. WPARAM wParam,
  934. LPARAM lParam)
  935. {
  936. INT i;
  937. switch (message)
  938. {
  939. case WM_INITDIALOG:
  940. {
  941. c_hwndDriveInstructions = GetDlgItem(hDlg,IDC_DRIVEINSTRUCTIONS);
  942. c_hwndDrivePrompt = GetDlgItem(hDlg,IDC_DRIVEPROMPT);
  943. c_hwndCBDriveList = GetDlgItem(hDlg,IDC_COMBO);
  944. if (1 == CountRemoveableDrives())
  945. {
  946. if (c_fIsBackup)
  947. {
  948. WCHAR temp[TEMPSTRINGBUFSIZE];
  949. WCHAR *pc = RString(IDS_SONLYONEDRIVE);
  950. swprintf(temp,pc,pszFileName[0]);
  951. SendMessage(c_hwndDriveInstructions,WM_SETTEXT,0,(LPARAM)temp);
  952. }
  953. else
  954. {
  955. WCHAR temp[TEMPSTRINGBUFSIZE];
  956. WCHAR *pc = RString(IDS_RONLYONEDRIVE);
  957. swprintf(temp,pc,pszFileName[0]);
  958. SendMessage(c_hwndDriveInstructions,WM_SETTEXT,0,(LPARAM)temp);
  959. }
  960. ShowWindow(c_hwndDrivePrompt,SW_HIDE);
  961. ShowWindow(c_hwndCBDriveList,SW_HIDE);
  962. }
  963. else
  964. {
  965. ShowRemoveableDrives();
  966. }
  967. break;
  968. }
  969. case WM_COMMAND:
  970. if (HIWORD(wParam) == BN_CLICKED)
  971. {
  972. i = LOWORD(wParam);
  973. }
  974. break;
  975. case WM_NOTIFY:
  976. switch (((NMHDR FAR *) lParam)->code)
  977. {
  978. case PSN_KILLACTIVE:
  979. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  980. return 1;
  981. break;
  982. case PSN_RESET:
  983. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  984. if (c_hTitleFont)
  985. {
  986. DeleteObject(c_hTitleFont);
  987. }
  988. break;
  989. case PSN_SETACTIVE:
  990. // Set data in the UI, Set up sequence buttons
  991. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK | PSWIZB_NEXT);
  992. break;
  993. case PSN_WIZNEXT:
  994. // take first character (drive letter) of the text associated with the
  995. // selected radio button and copy it to the filename in the drive
  996. // letter position.
  997. {
  998. LRESULT lr;
  999. INT iDrive = 0;
  1000. COMBOBOXEXITEM stCBItem = {0};
  1001. lr = SendMessage(c_hwndCBDriveList,CB_GETCURSEL,0,0);
  1002. // If combobox sel error, first drive
  1003. if (CB_ERR == lr)
  1004. {
  1005. iDrive = 0;
  1006. }
  1007. else
  1008. {
  1009. stCBItem.mask = CBEIF_LPARAM;
  1010. stCBItem.iItem = lr;
  1011. lr = SendMessage(c_hwndCBDriveList,CBEM_GETITEM,0,(LPARAM)&stCBItem);
  1012. if (CB_ERR != lr)
  1013. {
  1014. iDrive = (INT) stCBItem.lParam;
  1015. }
  1016. }
  1017. pszFileName[0] = GetDriveLetter(iDrive);
  1018. }
  1019. CHECKPOINT(59,"Wizard: Both - Drive select page");
  1020. if (!c_fIsBackup)
  1021. {
  1022. CHECKPOINT(60,"Wizard: Restore - drive select");
  1023. if (NULL == GetInputFile())
  1024. {
  1025. // failed to open file
  1026. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_SPAGEXS);
  1027. return TRUE;
  1028. }
  1029. }
  1030. return FALSE;
  1031. break;
  1032. default:
  1033. return FALSE;
  1034. }
  1035. break;
  1036. default:
  1037. return FALSE;
  1038. }
  1039. return TRUE;
  1040. }
  1041. INT_PTR CALLBACK SPageProc1(
  1042. HWND hDlg,
  1043. UINT message,
  1044. WPARAM wParam,
  1045. LPARAM lParam)
  1046. {
  1047. INT i;
  1048. switch (message)
  1049. {
  1050. case WM_INITDIALOG:
  1051. {
  1052. HWND hC = GetDlgItem(hDlg,PSBTN_CANCEL);
  1053. if (NULL != hC)
  1054. {
  1055. ShowWindow(hC,SW_HIDE);
  1056. }
  1057. c_hwndSInstructions = GetDlgItem(hDlg,IDC_SINSTRUCTIONS);
  1058. c_hwndSP1E1 = GetDlgItem(hDlg,IDC_SP1E1);
  1059. LoadString(g_hInstance,IDS_SP1INSTRUCTIONS,Buf,TEMPSTRINGBUFSIZE);
  1060. SendMessage(c_hwndSInstructions,WM_SETTEXT,0,(LPARAM)Buf);
  1061. break;
  1062. }
  1063. case WM_COMMAND:
  1064. if (HIWORD(wParam) == BN_CLICKED)
  1065. {
  1066. i = LOWORD(wParam);
  1067. }
  1068. break;
  1069. case WM_NOTIFY:
  1070. switch (((NMHDR FAR *) lParam)->code)
  1071. {
  1072. case PSN_KILLACTIVE:
  1073. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1074. return 1;
  1075. break;
  1076. case PSN_RESET:
  1077. // reset data to the original values
  1078. SendMessage(c_hwndSP1E1,WM_SETTEXT,0,0);
  1079. //SendMessage(c_hwndSP1E2,WM_SETTEXT,0,0);
  1080. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1081. if (c_hTitleFont)
  1082. {
  1083. DeleteObject(c_hTitleFont);
  1084. }
  1085. break;
  1086. case PSN_SETACTIVE:
  1087. // Set data in the UI, Set up sequence buttons
  1088. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK | PSWIZB_NEXT);
  1089. break;
  1090. case PSN_WIZBACK:
  1091. CHECKPOINT(61,"Wizard: Save - back from enter old psw page");
  1092. break;
  1093. case PSN_WIZNEXT:
  1094. {
  1095. //Fetch the data and process it - if FALSE, stay on this page
  1096. // allow null password
  1097. HANDLE hToken = NULL;
  1098. BOOL fPswOK = FALSE;
  1099. SendMessage(c_hwndSP1E1,WM_GETTEXT,PWLEN + 1,(LPARAM)c_rgcPsw);
  1100. fPswOK = LogonUser(c_rgcUser,c_rgcDomain,c_rgcPsw,
  1101. LOGON32_LOGON_INTERACTIVE,
  1102. LOGON32_PROVIDER_DEFAULT,
  1103. &hToken);
  1104. if (hToken)
  1105. {
  1106. CloseHandle(hToken);
  1107. }
  1108. // Handle failure to verify the entered old password
  1109. if (!fPswOK)
  1110. {
  1111. // If the error was account restriction, and the user password
  1112. // is blank, that may account for the fail. Skip informing the
  1113. // user and attempt the write anyway.
  1114. DWORD dwErr = GetLastError();
  1115. if ((ERROR_ACCOUNT_RESTRICTION != dwErr) || (wcslen(c_rgcPsw) != 0))
  1116. {
  1117. RMessageBox(c_hDlg,IDS_MBTWRONGPSW,IDS_WRONGPSW,MB_ICONHAND);
  1118. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_SPAGE1);
  1119. return TRUE;
  1120. }
  1121. }
  1122. // Handle key file already present - overwrite?
  1123. if ( ExistsOldKey(c_rgcUser))
  1124. {
  1125. int k = RMessageBox(c_hDlg,IDS_MBTREPLACE ,IDS_OLDEXISTS ,MB_YESNO);
  1126. if (k != IDYES)
  1127. {
  1128. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_SPAGE1);
  1129. return TRUE;
  1130. }
  1131. }
  1132. // Handle can't create the output file
  1133. if (NULL == GetOutputFile())
  1134. {
  1135. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_SPAGE1);
  1136. return TRUE;
  1137. }
  1138. // Handle not enough space
  1139. if (FILESPACENEEDED > GetDriveFreeSpace(pszFileName))
  1140. {
  1141. // if still not enough space, let go of the attempt to create an output file,
  1142. // or successive attempts will fail for a sharing violation
  1143. if (g_hFile)
  1144. {
  1145. CloseHandle(g_hFile);
  1146. g_hFile = NULL;
  1147. }
  1148. RMessageBox(c_hDlg,IDS_MBTNOSPACE ,IDS_MBMNOSPACE ,MB_OK);
  1149. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_SPAGE1);
  1150. return TRUE;
  1151. }
  1152. // Conditions OK - create a thread to do the operation
  1153. // and generate timer events which march the progress bar
  1154. // SaveInfo() will zero the psw buffer
  1155. HANDLE hT = CreateThread(NULL,0,SaveThread,(LPVOID)NULL,0,&c_iThread);
  1156. if (NULL == hT)
  1157. {
  1158. // failed to launch the timer thread.
  1159. // Announce a nonspecific error
  1160. if (g_hFile)
  1161. {
  1162. CloseHandle(g_hFile);
  1163. g_hFile = NULL;
  1164. }
  1165. RMessageBox(c_hDlg,IDS_MBTERROR ,IDS_SERROR ,MB_OK);
  1166. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_SPAGE1);
  1167. return TRUE;
  1168. }
  1169. return FALSE;
  1170. }
  1171. break;
  1172. default:
  1173. return FALSE;
  1174. }
  1175. break;
  1176. default:
  1177. return FALSE;
  1178. }
  1179. return TRUE;
  1180. }
  1181. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1182. //
  1183. // FINISH page proc - reach this page only on success?
  1184. //
  1185. // This page receives timer interrupts, advancing the progress bar at each one. When c_bSaveComplete indicates
  1186. // that the operation is complete, it shuts off the timer and waits for the user to advance to the next page.
  1187. //
  1188. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1189. INT_PTR CALLBACK SPageProc2(
  1190. HWND hDlg,
  1191. UINT message,
  1192. WPARAM wParam,
  1193. LPARAM lParam)
  1194. {
  1195. WCHAR Msg[200];
  1196. WCHAR Tpl[200];
  1197. Tpl[0] = 0;
  1198. Msg[0] = 0;
  1199. LoadString(g_hInstance,IDS_SPROGRESS,Tpl,200 -1);
  1200. HWND hP = GetDlgItem(hDlg,IDC_SPROGRESS);
  1201. switch (message)
  1202. {
  1203. case WM_TIMER:
  1204. // advance the progress bar
  1205. SendMessage(c_hProgress,PBM_STEPIT,0,0);
  1206. c_iProg += 5;
  1207. if (100 <= c_iProg)
  1208. {
  1209. c_iProg = 95;
  1210. }
  1211. // Stop advancing when c_bSaveComplete is nonzero, and
  1212. if (c_bSaveComplete)
  1213. {
  1214. KillTimer(hDlg,TIMERID);
  1215. c_iTimer =0;
  1216. SecureZeroMemory(c_rgcPsw,sizeof(c_rgcPsw));
  1217. if (dwThreadReturn == ERRSUCCESS)
  1218. {
  1219. // set text to indicate complete
  1220. SendMessage(c_hProgress,PBM_SETPOS,100,0);
  1221. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_NEXT);
  1222. c_iProg = 100;
  1223. }
  1224. else
  1225. {
  1226. SendMessage(c_hProgress,PBM_SETPOS,0,0);
  1227. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK);
  1228. c_iProg = 0;
  1229. }
  1230. }
  1231. swprintf(Msg,Tpl,c_iProg);
  1232. if (hP)
  1233. {
  1234. SendMessage(hP,WM_SETTEXT,0,(LPARAM)Msg);
  1235. }
  1236. break;
  1237. case WM_INITDIALOG:
  1238. {
  1239. // instead of starting the timer here, do it on the set active
  1240. // notification, since the init is not redone if you rearrive at
  1241. // this page after an error.
  1242. c_hProgress = GetDlgItem(hDlg,IDC_PROGRESS1);
  1243. break;
  1244. }
  1245. case WM_COMMAND:
  1246. break;
  1247. case WM_NOTIFY:
  1248. switch (((NMHDR FAR *) lParam)->code)
  1249. {
  1250. case PSN_KILLACTIVE:
  1251. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1252. return 1;
  1253. break;
  1254. case PSN_RESET:
  1255. SecureZeroMemory(c_rgcPsw,sizeof(c_rgcPsw));
  1256. // rest to the original values
  1257. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1258. if (c_hTitleFont)
  1259. {
  1260. DeleteObject(c_hTitleFont);
  1261. }
  1262. break;
  1263. case PSN_SETACTIVE:
  1264. PropSheet_SetWizButtons(GetParent(hDlg),0);
  1265. PropSheet_CancelToClose(GetParent(hDlg));
  1266. SendMessage(c_hProgress,PBM_SETSTEP,5,0);
  1267. SendMessage(c_hProgress,PBM_SETPOS,0,0);
  1268. // Start a timer
  1269. c_iTimer = 0;
  1270. c_iProg = 0;
  1271. c_iTimer = SetTimer(hDlg,TIMERID,TIMERPERIOD,NULL);
  1272. c_TimerAssociatedWindow = hDlg;
  1273. // Set controls to state indicated by data
  1274. // Set BACK/FINISH instead of BACK/NEXT
  1275. break;
  1276. case PSN_WIZBACK:
  1277. break;
  1278. case PSN_WIZNEXT:
  1279. // Done
  1280. SecureZeroMemory(c_rgcPsw,sizeof(c_rgcPsw));
  1281. if (c_iTimer)
  1282. {
  1283. KillTimer(hDlg,TIMERID);
  1284. }
  1285. c_iTimer = 0;
  1286. break;
  1287. default:
  1288. return FALSE;
  1289. }
  1290. break;
  1291. default:
  1292. return FALSE;
  1293. }
  1294. return TRUE;
  1295. }
  1296. INT_PTR CALLBACK SPageProc3(
  1297. HWND hDlg,
  1298. UINT message,
  1299. WPARAM wParam,
  1300. LPARAM lParam)
  1301. {
  1302. switch (message)
  1303. {
  1304. case WM_INITDIALOG:
  1305. {
  1306. // instead of starting the timer here, do it on the set active
  1307. // notification, since the init is not redone if you rearrive at
  1308. // this page after an error.
  1309. c_hwndSFinish1 = GetDlgItem(hDlg,IDC_SFINISH1);
  1310. c_hwndSFinish2 = GetDlgItem(hDlg,IDC_SFINISH2);
  1311. if (NULL != c_hTitleFont)
  1312. {
  1313. SendMessage(c_hwndSFinish1,WM_SETFONT,(WPARAM) c_hTitleFont,(LPARAM) TRUE);
  1314. }
  1315. LoadString(g_hInstance,IDS_SFINISH1,Buf,TEMPSTRINGBUFSIZE);
  1316. SendMessage(c_hwndSFinish1,WM_SETTEXT,0,(LPARAM)Buf);
  1317. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_FINISH);
  1318. LoadString(g_hInstance,IDS_SFINISH2,Buf,TEMPSTRINGBUFSIZE);
  1319. SendMessage(c_hwndSFinish2,WM_SETTEXT,0,(LPARAM)Buf);
  1320. break;
  1321. }
  1322. case WM_COMMAND:
  1323. break;
  1324. case WM_NOTIFY:
  1325. switch (((NMHDR FAR *) lParam)->code)
  1326. {
  1327. case PSN_KILLACTIVE:
  1328. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1329. return 1;
  1330. break;
  1331. case PSN_RESET:
  1332. // reset to the original values
  1333. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1334. if (c_hTitleFont)
  1335. {
  1336. DeleteObject(c_hTitleFont);
  1337. }
  1338. break;
  1339. case PSN_SETACTIVE:
  1340. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_FINISH);
  1341. PropSheet_CancelToClose(GetParent(hDlg));
  1342. break;
  1343. case PSN_WIZBACK:
  1344. break;
  1345. case PSN_WIZFINISH:
  1346. // Done
  1347. SecureZeroMemory(c_rgcPsw,sizeof(c_rgcPsw));
  1348. if (c_hTitleFont)
  1349. {
  1350. DeleteObject(c_hTitleFont);
  1351. }
  1352. break;
  1353. default:
  1354. return FALSE;
  1355. }
  1356. break;
  1357. default:
  1358. return FALSE;
  1359. }
  1360. return TRUE;
  1361. }
  1362. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1363. //
  1364. // WELCOME page proc doesn't have to do much
  1365. //
  1366. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1367. INT_PTR CALLBACK RPageProc0(
  1368. HWND hDlg,
  1369. UINT message,
  1370. WPARAM wParam,
  1371. LPARAM lParam)
  1372. {
  1373. switch (message)
  1374. {
  1375. case WM_INITDIALOG:
  1376. {
  1377. c_hDlg = hDlg;
  1378. c_hwndRWelcome1 = GetDlgItem(hDlg,IDC_RWELCOME1);
  1379. if (NULL != c_hTitleFont)
  1380. {
  1381. SendMessage(c_hwndRWelcome1,WM_SETFONT,(WPARAM) c_hTitleFont,(LPARAM) TRUE);
  1382. }
  1383. LoadString(g_hInstance,IDS_RWELCOME1,Buf,TEMPSTRINGBUFSIZE);
  1384. SendMessage(c_hwndRWelcome1,WM_SETTEXT,0,(LPARAM)Buf);
  1385. c_hwndRWelcome2 = GetDlgItem(hDlg,IDC_RWELCOME2);
  1386. LoadString(g_hInstance,IDS_RWELCOME2,Buf,TEMPSTRINGBUFSIZE);
  1387. SendMessage(c_hwndRWelcome2,WM_SETTEXT,0,(LPARAM)Buf);
  1388. break;
  1389. }
  1390. case WM_COMMAND:
  1391. //if (HIWORD(wParam) == BN_CLICKED)
  1392. //{
  1393. // // crack the incoming command messages
  1394. // INT NotifyId = HIWORD(wParam);
  1395. // INT ControlId = LOWORD(wParam);
  1396. //}
  1397. break;
  1398. case WM_NOTIFY:
  1399. switch (((NMHDR FAR *) lParam)->code)
  1400. {
  1401. case PSN_KILLACTIVE:
  1402. SetWindowLong(hDlg,DWLP_MSGRESULT, FALSE);
  1403. return 1;
  1404. break;
  1405. case PSN_SETACTIVE:
  1406. // state following a BACK from the next page
  1407. CenterPage(GetParent(hDlg));
  1408. CloseInputFile();
  1409. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_NEXT);
  1410. break;
  1411. case PSN_WIZNEXT:
  1412. break;
  1413. case PSN_RESET:
  1414. if (c_hTitleFont) DeleteObject(c_hTitleFont);
  1415. break;
  1416. default:
  1417. return FALSE;
  1418. }
  1419. break;
  1420. default:
  1421. return FALSE;
  1422. }
  1423. return TRUE;
  1424. }
  1425. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1426. //
  1427. // PAGE1 page proc, where the real work is done
  1428. //
  1429. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1430. INT_PTR CALLBACK RPageProc1(
  1431. HWND hDlg,
  1432. UINT message,
  1433. WPARAM wParam,
  1434. LPARAM lParam)
  1435. {
  1436. INT i;
  1437. switch (message)
  1438. {
  1439. case WM_INITDIALOG:
  1440. {
  1441. Buf[0] = 0;
  1442. c_hwndRInstructions = GetDlgItem(hDlg,IDC_RINSTRUCTIONS);
  1443. c_hwndRP1E1 = GetDlgItem(hDlg,IDC_RP1E1);
  1444. c_hwndRP1E2 = GetDlgItem(hDlg,IDC_RP1E2);
  1445. c_hwndRP1E3 = GetDlgItem(hDlg,IDC_RP1E3);
  1446. LoadString(g_hInstance,IDS_RP1INSTR,Buf,TEMPSTRINGBUFSIZE);
  1447. SendMessage(c_hwndRInstructions,WM_SETTEXT,0,(LPARAM)Buf);
  1448. break;
  1449. }
  1450. case WM_COMMAND:
  1451. if (HIWORD(wParam) == BN_CLICKED)
  1452. {
  1453. i = LOWORD(wParam);
  1454. }
  1455. break;
  1456. case WM_NOTIFY:
  1457. switch (((NMHDR FAR *) lParam)->code)
  1458. {
  1459. DWORD dwRet;
  1460. case PSN_KILLACTIVE:
  1461. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1462. return 1;
  1463. break;
  1464. case PSN_RESET:
  1465. // reset data to the original values
  1466. free(c_pPrivate);
  1467. c_pPrivate = NULL;
  1468. SecureZeroMemory(c_rgcPsw,sizeof(c_rgcPsw));
  1469. SendMessage(c_hwndRP1E1,WM_SETTEXT,0,0);
  1470. SendMessage(c_hwndRP1E2,WM_SETTEXT,0,0);
  1471. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1472. if (c_hTitleFont)
  1473. {
  1474. DeleteObject(c_hTitleFont);
  1475. }
  1476. CloseInputFile();
  1477. g_hFile = NULL;
  1478. break;
  1479. case PSN_SETACTIVE:
  1480. // Set data in the UI, Set up sequence buttons
  1481. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK | PSWIZB_NEXT);
  1482. break;
  1483. case PSN_WIZBACK:
  1484. CHECKPOINT(62,"Wizard: Restore - BACK from enter new psw data page");
  1485. CloseInputFile();
  1486. return FALSE;
  1487. break;
  1488. case PSN_WIZNEXT:
  1489. //Fetch the data and process it
  1490. if (!FetchPsw(c_hwndRP1E1,c_hwndRP1E2))
  1491. {
  1492. // psw buffers empty if you get here - FetchPsw will have told
  1493. // the user what to do
  1494. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_RPAGE1);
  1495. return TRUE;
  1496. }
  1497. // SetAccountPassword will clean the psw buffers
  1498. dwRet = SetAccountPassword();
  1499. if (ERROR_SUCCESS == dwRet)
  1500. {
  1501. return FALSE;
  1502. }
  1503. //else if (NERR_PasswordTooShort == dwRet) {
  1504. else if (
  1505. (STATUS_ILL_FORMED_PASSWORD == dwRet) ||
  1506. (STATUS_PASSWORD_RESTRICTION == dwRet))
  1507. {
  1508. // Password doesn't conform - try again
  1509. RMessageBox(hDlg,IDS_MBTINVALIDPSW,IDS_RPSWTOOSHORT,MB_ICONHAND);
  1510. SendMessage(c_hwndRP1E1,WM_SETTEXT,0,(LPARAM)0);
  1511. SendMessage(c_hwndRP1E2,WM_SETTEXT,0,(LPARAM)0);
  1512. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_RPAGE1);
  1513. return TRUE;
  1514. }
  1515. else if (NTE_BAD_DATA == dwRet)
  1516. {
  1517. // ya might get this using an obsolete disk?
  1518. free(c_pPrivate);
  1519. c_pPrivate = NULL;
  1520. RMessageBox(hDlg,IDS_MBTINVALIDDISK ,IDS_RPSWERROR ,MB_ICONHAND);
  1521. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_RWELCOME);
  1522. return TRUE;
  1523. }
  1524. else
  1525. {
  1526. RMessageBox(hDlg,IDS_MBTERROR,IDS_RPSWUNSPEC,MB_ICONHAND);
  1527. SetWindowLong(hDlg,DWLP_MSGRESULT,IDD_RWELCOME);
  1528. return TRUE;
  1529. }
  1530. return FALSE;
  1531. break;
  1532. default:
  1533. return FALSE;
  1534. }
  1535. break;
  1536. default:
  1537. return FALSE;
  1538. }
  1539. return TRUE;
  1540. }
  1541. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1542. //
  1543. // FINISH page proc - reach this page only on success?
  1544. //
  1545. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1546. INT_PTR CALLBACK RPageProc2(
  1547. HWND hDlg,
  1548. UINT message,
  1549. WPARAM wParam,
  1550. LPARAM lParam)
  1551. {
  1552. INT i;
  1553. switch (message)
  1554. {
  1555. case WM_INITDIALOG:
  1556. CloseInputFile();
  1557. c_hwndRFinish1 = GetDlgItem(hDlg,IDC_RFINISH1);
  1558. if (NULL != c_hTitleFont)
  1559. {
  1560. SendMessage(c_hwndRFinish1,WM_SETFONT,(WPARAM) c_hTitleFont,(LPARAM) TRUE);
  1561. }
  1562. LoadString(g_hInstance,IDS_RFINISH1,Buf,TEMPSTRINGBUFSIZE);
  1563. SendMessage(c_hwndRFinish1,WM_SETTEXT,0,(LPARAM)Buf);
  1564. c_hwndRFinish2 = GetDlgItem(hDlg,IDC_RFINISH2);
  1565. LoadString(g_hInstance,IDS_RFINISH2,Buf,TEMPSTRINGBUFSIZE);
  1566. SendMessage(c_hwndRFinish2,WM_SETTEXT,0,(LPARAM)Buf);
  1567. break;
  1568. case WM_COMMAND:
  1569. if (HIWORD(wParam) == BN_CLICKED)
  1570. {
  1571. i = LOWORD(wParam);
  1572. }
  1573. break;
  1574. case WM_NOTIFY:
  1575. switch (((NMHDR FAR *) lParam)->code)
  1576. {
  1577. case PSN_KILLACTIVE:
  1578. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1579. return 1;
  1580. break;
  1581. case PSN_RESET:
  1582. // rest to the original values
  1583. SetWindowLong(hDlg, DWLP_MSGRESULT, FALSE);
  1584. if (c_hTitleFont)
  1585. {
  1586. DeleteObject(c_hTitleFont);
  1587. }
  1588. break;
  1589. case PSN_SETACTIVE:
  1590. CloseInputFile();
  1591. // Set controls to state indicated by data
  1592. // Set BACK/FINISH instead of BACK/NEXT
  1593. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_FINISH);
  1594. PropSheet_CancelToClose(GetParent(hDlg));
  1595. break;
  1596. case PSN_WIZBACK:
  1597. break;
  1598. case PSN_WIZFINISH:
  1599. // Done
  1600. if (c_hTitleFont)
  1601. {
  1602. DeleteObject(c_hTitleFont);
  1603. }
  1604. break;
  1605. default:
  1606. return FALSE;
  1607. }
  1608. break;
  1609. default:
  1610. return FALSE;
  1611. }
  1612. return TRUE;
  1613. }
  1614. /////////////////////////////////////////////////////////////////////////
  1615. //
  1616. // Common Routines for all pages
  1617. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1618. //
  1619. //
  1620. //
  1621. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1622. void InitPropertyPage( PROPSHEETPAGE* psp,
  1623. INT idDlg,
  1624. DLGPROC pfnDlgProc,
  1625. DWORD dwFlags,
  1626. LPARAM lParam)
  1627. {
  1628. memset((LPVOID)psp,0,sizeof(PROPSHEETPAGE));
  1629. psp->dwFlags = dwFlags;
  1630. psp->pszTemplate = MAKEINTRESOURCE(idDlg);
  1631. psp->pfnDlgProc = pfnDlgProc;
  1632. psp->dwSize = sizeof(PROPSHEETPAGE);
  1633. psp->hInstance = g_hInstance;
  1634. }
  1635. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1636. //
  1637. // Set the text for title and subtitle for Wizard97 style pages
  1638. //
  1639. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1640. void SetPageHeaderText(PROPSHEETPAGE *psp,
  1641. INT iTitle,
  1642. INT iSubTitle)
  1643. {
  1644. if (0 != (psp->dwFlags & PSP_HIDEHEADER))
  1645. {
  1646. return;
  1647. }
  1648. if (0 != iTitle)
  1649. {
  1650. psp->pszHeaderTitle = MAKEINTRESOURCE(iTitle);
  1651. psp->dwFlags |= PSP_USEHEADERTITLE;
  1652. }
  1653. if (0 != iSubTitle)
  1654. {
  1655. psp->pszHeaderSubTitle = MAKEINTRESOURCE(iSubTitle);
  1656. psp->dwFlags |= PSP_USEHEADERSUBTITLE;
  1657. }
  1658. }
  1659. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1660. //
  1661. // Set the page's title bar caption
  1662. //
  1663. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1664. void SetPageCaption(PROPSHEETPAGE *psp,
  1665. INT iTitle)
  1666. {
  1667. if (0 != iTitle)
  1668. {
  1669. psp->pszTitle = MAKEINTRESOURCE(iTitle);
  1670. psp->dwFlags |= PSP_USETITLE;
  1671. }
  1672. }
  1673. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1674. //
  1675. // PRShow[Save|Restore]Wizard()
  1676. //
  1677. // Pass the HWND of the owning window, and pass the instance handle of
  1678. // the enclosing binary, for the purpose of locating resources
  1679. //
  1680. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1681. void APIENTRY PRShowSaveWizardW(HWND hwndOwner,HINSTANCE hInstance,LPWSTR pszCmdLine,int nCmdShow)
  1682. {
  1683. PROPSHEETPAGE psp[NUMSAVEPAGES];
  1684. HPROPSHEETPAGE hpsp[NUMSAVEPAGES];
  1685. PROPSHEETHEADER psh;
  1686. INT_PTR iRet;
  1687. CHECKPOINT(63,"Wizard: Save - Show from nusrmgr.cpl");
  1688. // do not allow this operation if no drives available
  1689. if (0 == CountRemoveableDrives())
  1690. {
  1691. RMessageBox(hwndOwner,IDS_MBTNODRIVE,IDS_MBMNODRIVE,MB_ICONHAND);
  1692. return;
  1693. }
  1694. if (NULL == hwndOwner)
  1695. {
  1696. hwndOwner = GetForegroundWindow();
  1697. }
  1698. HANDLE hMutex = CreateMutex(NULL,TRUE,TEXT("PRWIZARDMUTEX"));
  1699. if (NULL == hMutex)
  1700. {
  1701. return;
  1702. }
  1703. if (ERROR_ALREADY_EXISTS == GetLastError())
  1704. {
  1705. CloseHandle(hMutex);
  1706. return;
  1707. }
  1708. c_fIsBackup = TRUE;
  1709. c_hTitleFont = CreateFontY(TEXT("MS Shell Dlg"),FW_BOLD,12);
  1710. #ifdef LOUDLY
  1711. if (NULL == c_hTitleFont) OutputDebugString(L"Title font missing\n");
  1712. if (NULL == hwndOwner) OutputDebugString(L"Owner window handle missing\n");
  1713. #endif
  1714. InitPropertyPage( &psp[0], IDD_SWELCOME, SPageProc0, PSP_HIDEHEADER,0);
  1715. InitPropertyPage( &psp[1], IDD_SPAGEXS , SPageProcX, PSP_DEFAULT ,0);
  1716. InitPropertyPage( &psp[2], IDD_SPAGE1 , SPageProc1, PSP_DEFAULT ,0);
  1717. InitPropertyPage( &psp[3], IDD_SPAGE2 , SPageProc2, PSP_DEFAULT, 0);
  1718. InitPropertyPage( &psp[4], IDD_SFINISH , SPageProc3, PSP_HIDEHEADER,0);
  1719. SetPageHeaderText(&psp[1], IDS_SPXTITLE,IDS_SPXSUBTITLE);
  1720. SetPageHeaderText(&psp[2], IDS_SP1TITLE,IDS_SP1SUBTITLE);
  1721. SetPageHeaderText(&psp[3], IDS_SP2TITLE,IDS_SP2SUBTITLE);
  1722. for (INT j=0;j<NUMSAVEPAGES;j++)
  1723. {
  1724. hpsp[j] = CreatePropertySheetPage((LPCPROPSHEETPAGE) &psp[j]);
  1725. }
  1726. psh.dwSize = sizeof(PROPSHEETHEADER);
  1727. psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
  1728. psh.hwndParent = hwndOwner;
  1729. psh.pszCaption = RString(IDS_BACKUPCAPTION);
  1730. psh.nPages = NUMSAVEPAGES;
  1731. psh.nStartPage = 0;
  1732. psh.phpage = (HPROPSHEETPAGE *) hpsp;
  1733. psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
  1734. psh.pszbmHeader = MAKEINTRESOURCE(IDB_TITLE);
  1735. psh.hInstance = g_hInstance;
  1736. // modal property sheet
  1737. SetErrorMode(0);
  1738. iRet = PropertySheet(&psh);
  1739. #ifdef LOUDLY
  1740. if (iRet < 0)
  1741. {
  1742. WCHAR sz[200];
  1743. DWORD dwErr = GetLastError();
  1744. swprintf(sz,L"PropertySheet() failed : GetLastError() returns: %d\n",dwErr);
  1745. OutputDebugString(sz);
  1746. }
  1747. #endif
  1748. if (c_hTitleFont)
  1749. {
  1750. DeleteObject (c_hTitleFont);
  1751. }
  1752. if (hMutex)
  1753. {
  1754. CloseHandle(hMutex);
  1755. }
  1756. return;
  1757. }
  1758. void APIENTRY PRShowRestoreWizardW(HWND hwndOwner,HINSTANCE hInstance,LPWSTR pszCmdLine,int nCmdShow)
  1759. {
  1760. PROPSHEETPAGE psp[NUMRESTOREPAGES];
  1761. HPROPSHEETPAGE hpsp[NUMRESTOREPAGES];
  1762. PROPSHEETHEADER psh;
  1763. INT_PTR iRet;
  1764. BOOL fICC;
  1765. CHECKPOINT(64,"Wizard: Restore - show restore wizard from nusrmgr.cpl");
  1766. if (NULL == hwndOwner)
  1767. {
  1768. hwndOwner = GetActiveWindow();
  1769. }
  1770. if (0 == CountRemoveableDrives())
  1771. {
  1772. RMessageBox(hwndOwner,IDS_MBTNODRIVE,IDS_MBMNODRIVE,MB_ICONHAND);
  1773. return;
  1774. }
  1775. INITCOMMONCONTROLSEX stICC;
  1776. OleInitialize(NULL);
  1777. // Initialize common controls in two steps
  1778. stICC.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1779. stICC.dwICC = ICC_WIN95_CLASSES | ICC_DATE_CLASSES | ICC_USEREX_CLASSES;
  1780. fICC = InitCommonControlsEx(&stICC);
  1781. #ifdef LOUDLY
  1782. if (fICC) OutputDebugString(L"Common control init 2 OK\n");
  1783. else OutputDebugString(L"Common control init 2 FAILED\n");
  1784. #endif
  1785. stICC.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1786. stICC.dwICC = ICC_WINLOGON_REINIT;
  1787. fICC = InitCommonControlsEx(&stICC);
  1788. #ifdef LOUDLY
  1789. if (fICC) OutputDebugString(L"Common control init 1 OK\n");
  1790. else OutputDebugString(L"Common control init 1 FAILED\n");
  1791. #endif
  1792. c_fIsBackup = FALSE;
  1793. GetNames(pszCmdLine); // If name is null, get current user (debug/test use)
  1794. c_hTitleFont = CreateFontY(TEXT("MS Shell Dlg"),FW_BOLD,12);
  1795. #ifdef LOUDLY
  1796. if (NULL == c_hTitleFont) OutputDebugString(L"Title font missing\n");
  1797. if (NULL == hwndOwner) OutputDebugString(L"Owner window handle missing\n");
  1798. #endif
  1799. InitPropertyPage( &psp[0], IDD_RWELCOME, RPageProc0,PSP_HIDEHEADER,0);
  1800. InitPropertyPage( &psp[1], IDD_SPAGEXR , SPageProcX,PSP_DEFAULT ,0);
  1801. InitPropertyPage( &psp[2], IDD_RPAGE1 , RPageProc1,PSP_DEFAULT ,0);
  1802. InitPropertyPage( &psp[3], IDD_RFINISH , RPageProc2,PSP_HIDEHEADER,0);
  1803. SetPageHeaderText(&psp[1], IDS_RPXTITLE,IDS_RPXSUBTITLE);
  1804. SetPageHeaderText(&psp[2], IDS_RP1TITLE,IDS_RP1SUBTITLE);
  1805. for (INT j=0;j<NUMRESTOREPAGES;j++)
  1806. {
  1807. hpsp[j] = CreatePropertySheetPage((LPCPROPSHEETPAGE) &psp[j]);
  1808. }
  1809. psh.dwSize = sizeof(PROPSHEETHEADER);
  1810. psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
  1811. psh.hwndParent = hwndOwner;
  1812. psh.pszCaption = RString(IDS_RESTORECAPTION);
  1813. psh.nPages = NUMRESTOREPAGES;
  1814. psh.nStartPage = 0;
  1815. psh.phpage = (HPROPSHEETPAGE *) hpsp;
  1816. psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
  1817. psh.pszbmHeader = MAKEINTRESOURCE(IDB_TITLE);
  1818. psh.hInstance = g_hInstance;
  1819. iRet = PropertySheet(&psh);
  1820. #ifdef LOUDLY
  1821. if (iRet < 0)
  1822. {
  1823. WCHAR sz[200];
  1824. DWORD dwErr = GetLastError();
  1825. swprintf(sz,L"PropertySheet() returns %x: GetLastError() returns: %d\n", iRet, dwErr);
  1826. OutputDebugString(sz);
  1827. }
  1828. #endif
  1829. if (c_hTitleFont)
  1830. {
  1831. DeleteObject (c_hTitleFont);
  1832. }
  1833. OleUninitialize();
  1834. return;
  1835. }
  1836. // ==================================
  1837. //
  1838. // These are the real exports from KEYMGR:
  1839. // PRShowSaveWizardExW - call from cpl applet, passing window title as pszCmdLine
  1840. // PRShowSaveFromMsginaW - call from MSGINA, passing username as pszCmdLine
  1841. // PRShowRestoreWizardExW - call from cpl applet, passing username as pszCmdLine
  1842. // PRShowRestoreFromMsginaW - call from MSGINA, passing username as pszCmdLine
  1843. // This export was added so that the backup wizard could be called from the system context
  1844. // (in which msgina runs). The username is taken from the UI and passed into the wizard,
  1845. // which uses it to create the backup key for that account.
  1846. //
  1847. // The global username string, c_rgcUser, is normally a null string until it is set by either
  1848. // getting the current logged user, or matching the SID found in a backup key. This api
  1849. // prestuffs that value. When it is found non-null, then GetUsernameW() is not called in
  1850. // SaveInfo() where the backup is made.
  1851. void APIENTRY PRShowSaveWizardExW(HWND hwndOwner,HINSTANCE hInstance,LPWSTR pszCmdLine,int nCmdShow)
  1852. {
  1853. #ifdef LOUDLY
  1854. OutputDebugString(L"\n\n\n");
  1855. #endif
  1856. BOOL fICC;
  1857. if (0 == CountRemoveableDrives())
  1858. {
  1859. RMessageBox(hwndOwner,IDS_MBTNODRIVE,IDS_MBMNODRIVE,MB_ICONHAND);
  1860. return;
  1861. }
  1862. INITCOMMONCONTROLSEX stICC;
  1863. stICC.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1864. stICC.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES;
  1865. OleInitialize(NULL);
  1866. fICC = InitCommonControlsEx(&stICC);
  1867. #ifdef LOUDLY
  1868. if (fICC) OutputDebugString(L"Common control init OK\n");
  1869. else OutputDebugString(L"Common control init FAILED\n");
  1870. #endif
  1871. // String passed in for this function is the window title for the user mgr.
  1872. // To get current logged user, call GetNames with NULL arg.
  1873. GetNames(NULL);
  1874. if (pszCmdLine != NULL)
  1875. {
  1876. #ifdef LOUDLY
  1877. OutputDebugString(L"*********");
  1878. OutputDebugString(pszCmdLine);
  1879. OutputDebugString(L"\n");
  1880. #endif
  1881. hwndOwner = FindWindow(L"HTML Application Host Window Class",pszCmdLine);
  1882. }
  1883. #ifdef LOUDLY
  1884. else OutputDebugString(L"NULL passed in pszCmdLine\n");
  1885. #endif
  1886. PRShowSaveWizardW(hwndOwner,NULL,NULL,NULL);
  1887. OleUninitialize();
  1888. return;
  1889. }
  1890. void APIENTRY PRShowSaveFromMsginaW(HWND hwndOwner,HINSTANCE hInstance,LPWSTR pszCmdLine,int nCmdShow)
  1891. {
  1892. BOOL fICC;
  1893. INITCOMMONCONTROLSEX stICC;
  1894. CHECKPOINT(56,"Wizard: Save - show from msgina");
  1895. stICC.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1896. stICC.dwICC = ICC_WINLOGON_REINIT;
  1897. OleInitialize(NULL);
  1898. fICC = InitCommonControlsEx(&stICC);
  1899. #ifdef LOUDLY
  1900. if (fICC) OutputDebugString(L"Common control init OK\n");
  1901. else OutputDebugString(L"Common control init FAILED\n");
  1902. #endif
  1903. GetNames(pszCmdLine);
  1904. PRShowSaveWizardW(hwndOwner,g_hInstance,NULL,NULL);
  1905. OleUninitialize();
  1906. return;
  1907. }
  1908. //These wrapper functions are supposed to rationalize the arguments coming in from two different calling
  1909. // environments. As it turns out, this is not necessary on the restore case, and these turn out to be
  1910. // identical. In fact, the friendly logon ui calls PRShowRestoreWizardW directly. PRShowRestoreWizardExW
  1911. // is left in so as not to change an existing interface.
  1912. void APIENTRY PRShowRestoreWizardExW(HWND hwndOwner,HINSTANCE hInstance,LPWSTR pszCmdLine,int nCmdShow)
  1913. {
  1914. if (NULL == hwndOwner) hwndOwner = GetActiveWindow();
  1915. PRShowRestoreWizardW(hwndOwner,NULL,pszCmdLine,NULL);
  1916. return;
  1917. }
  1918. void APIENTRY PRShowRestoreFromMsginaW(HWND hwndOwner,HINSTANCE hInstance,LPWSTR pszCmdLine,int nCmdShow)
  1919. {
  1920. CHECKPOINT(57,"Wizard: Restore - Show from msgina");
  1921. if (NULL == hwndOwner) hwndOwner = GetActiveWindow();
  1922. PRShowRestoreWizardW(hwndOwner,NULL,pszCmdLine,NULL);
  1923. return;
  1924. }