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.

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