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.

1201 lines
27 KiB

  1. /*++
  2. Copyright (c) 1991-1994 Microsoft Corporation
  3. Module Name:
  4. ftreg.c
  5. Abstract:
  6. This module contains the routines for Disk Administrator that deal
  7. with registry manipulation
  8. Author:
  9. Edward (Ted) Miller (TedM) 11/15/91
  10. Environment:
  11. User process.
  12. Notes:
  13. Revision History:
  14. 1-Feb-94 (bobri) Clean up and handle missing floppy disk on registry
  15. save/restore.
  16. --*/
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include "fdisk.h"
  22. #include "ftregres.h"
  23. // attempt to avoid conflict
  24. #define TEMP_KEY_NAME TEXT("xzss3___$$Temp$Hive$$___")
  25. #define DISK_KEY_NAME TEXT("DISK")
  26. #define DISK_VALUE_NAME TEXT("Information")
  27. LONG
  28. FdpLoadHiveIntoRegistry(
  29. IN LPTSTR HiveFilename
  30. )
  31. /*++
  32. Routine Description:
  33. This routine writes the contents of a given hive file into the registry,
  34. rooted at a temporary key in HKEY_LOCAL_MACHINE.
  35. Arguments:
  36. HiveFilename - supplies filename of the hive to be loaded into
  37. the registry
  38. Return Value:
  39. Windows error code.
  40. --*/
  41. {
  42. NTSTATUS Status;
  43. BOOLEAN OldPrivState;
  44. LONG Err;
  45. // Attempt to get restore privilege
  46. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
  47. TRUE,
  48. FALSE,
  49. &OldPrivState);
  50. if (!NT_SUCCESS(Status)) {
  51. return RtlNtStatusToDosError(Status);
  52. }
  53. // Load the hive into our registry
  54. Err = RegLoadKey(HKEY_LOCAL_MACHINE,TEMP_KEY_NAME,HiveFilename);
  55. // Restore old privilege if necessary
  56. if (!OldPrivState) {
  57. RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
  58. FALSE,
  59. FALSE,
  60. &OldPrivState);
  61. }
  62. return Err;
  63. }
  64. LONG
  65. FdpUnloadHiveFromRegistry(
  66. VOID
  67. )
  68. /*++
  69. Routine Description:
  70. This routine removes a tree (previously loaded with
  71. FdpLoadHiveIntoRegistry) from the temporary key in HKEY_LOCAL_MACHINE.
  72. Arguments:
  73. None.
  74. Return Value:
  75. Windows error code.
  76. --*/
  77. {
  78. NTSTATUS Status;
  79. BOOLEAN OldPrivState;
  80. LONG Err;
  81. // Attempt to get restore privilege
  82. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
  83. TRUE,
  84. FALSE,
  85. &OldPrivState);
  86. if (!NT_SUCCESS(Status)) {
  87. return RtlNtStatusToDosError(Status);
  88. }
  89. // Unload the hive from our registry
  90. Err = RegUnLoadKey(HKEY_LOCAL_MACHINE,TEMP_KEY_NAME);
  91. // Restore old privilege if necessary
  92. if (!OldPrivState) {
  93. RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
  94. FALSE,
  95. FALSE,
  96. &OldPrivState);
  97. }
  98. return Err;
  99. }
  100. LONG
  101. FdpGetDiskInfoFromKey(
  102. IN LPTSTR RootKeyName,
  103. OUT PVOID *DiskInfo,
  104. OUT PULONG DiskInfoSize
  105. )
  106. /*++
  107. Routine Description:
  108. This routine pulls the binary blob containing disk ft, drive letter,
  109. and layout information out of a given registry key.
  110. The info is found in HKEY_LOCAL_MACHINE,<RootKeyName>\DISK:Information.
  111. Arguments:
  112. RootKeyName - name of the subkey of HKEY_LOCAL_MACHINE that is to
  113. contain the DISK key.
  114. DiskInfo - receives a pointer to a buffer containing the disk info.
  115. DiskInfoSize - receives size of the disk buffer.
  116. Return Value:
  117. Windows error code. If NO_ERROR, DiskInfo and DiskInfoSize are
  118. filled in, and it is the caller's responsibility to free the buffer
  119. when it is finished (via LocalFree()).
  120. --*/
  121. {
  122. LONG Err;
  123. HKEY hkeyDisk;
  124. ULONG BufferSize;
  125. ULONG ValueType;
  126. PVOID Buffer;
  127. LPTSTR DiskKeyName;
  128. // Form the name of the DISK key
  129. DiskKeyName = (LPTSTR)LocalAlloc( LMEM_FIXED,
  130. ( lstrlen(RootKeyName)
  131. + lstrlen(DISK_KEY_NAME)
  132. + 2 // the \ and nul
  133. )
  134. * sizeof(TCHAR)
  135. );
  136. if (DiskKeyName == NULL) {
  137. return ERROR_NOT_ENOUGH_MEMORY;
  138. }
  139. lstrcpy(DiskKeyName,RootKeyName);
  140. lstrcat(DiskKeyName,TEXT("\\"));
  141. lstrcat(DiskKeyName,DISK_KEY_NAME);
  142. // Open the DISK key.
  143. Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  144. DiskKeyName,
  145. REG_OPTION_RESERVED,
  146. KEY_READ,
  147. &hkeyDisk);
  148. if (Err != NO_ERROR) {
  149. goto CleanUp2;
  150. }
  151. // Determine how large we need the buffer to be
  152. Err = RegQueryValueEx(hkeyDisk,
  153. DISK_VALUE_NAME,
  154. NULL,
  155. &ValueType,
  156. NULL,
  157. &BufferSize);
  158. if ((Err != NO_ERROR) && (Err != ERROR_MORE_DATA)) {
  159. goto CleanUp1;
  160. }
  161. // Allocate a buffer of appropriate size
  162. Buffer = (PVOID)LocalAlloc(LMEM_FIXED,BufferSize);
  163. if (Buffer == NULL) {
  164. Err = ERROR_NOT_ENOUGH_MEMORY;
  165. goto CleanUp1;
  166. }
  167. // Query the data
  168. Err = RegQueryValueEx(hkeyDisk,
  169. DISK_VALUE_NAME,
  170. NULL,
  171. &ValueType,
  172. Buffer,
  173. &BufferSize);
  174. if (Err != NO_ERROR) {
  175. LocalFree(Buffer);
  176. goto CleanUp1;
  177. }
  178. *DiskInfo = Buffer;
  179. *DiskInfoSize = BufferSize;
  180. CleanUp1:
  181. RegCloseKey(hkeyDisk);
  182. CleanUp2:
  183. LocalFree(DiskKeyName);
  184. return Err;
  185. }
  186. LONG
  187. FdpGetDiskInfoFromHive(
  188. IN PCHAR HiveFilename,
  189. OUT PVOID *DiskInfo,
  190. OUT PULONG DiskInfoSize
  191. )
  192. /*++
  193. Routine Description:
  194. This routine pulls the binary blob containing disk ft, drive letter,
  195. and layout information out of a given registry hive, which must be
  196. a file in an alternate NT tree (ie, can't be an active hive).
  197. The info is found in \DISK:Information within the hive.
  198. Arguments:
  199. HiveFilename - supplies filename of hive
  200. DiskInfo - receives a pointer to a buffer containing the disk info.
  201. DiskInfoSize - receives size of the disk buffer.
  202. Return Value:
  203. Windows error code. If NO_ERROR, DiskInfo and DiskInfoSize are
  204. filled in, and it is the caller's responsibility to free the buffer
  205. when it is finished (via LocalFree()).
  206. --*/
  207. {
  208. ULONG windowsError;
  209. windowsError = FdpLoadHiveIntoRegistry(HiveFilename);
  210. if (windowsError == NO_ERROR) {
  211. windowsError = FdpGetDiskInfoFromKey(TEMP_KEY_NAME,DiskInfo,DiskInfoSize);
  212. FdpUnloadHiveFromRegistry();
  213. }
  214. return windowsError;
  215. }
  216. LONG
  217. FdTransferOldDiskInfoToRegistry(
  218. IN PCHAR HiveFilename
  219. )
  220. /*++
  221. Routine Description:
  222. This routine transfers disk configuration from a given hive file
  223. (which should be an inactive system hive) to the current registry.
  224. Arguments:
  225. HiveFilename - supplies filename of source hive
  226. Return Value:
  227. Windows error code.
  228. --*/
  229. {
  230. LONG windowsError;
  231. PVOID diskInfo;
  232. ULONG diskInfoSize;
  233. HKEY hkeyDisk;
  234. // Load up the hive and pull the disk info from it.
  235. windowsError = FdpGetDiskInfoFromHive(HiveFilename,&diskInfo,&diskInfoSize);
  236. if (windowsError != NO_ERROR) {
  237. return windowsError;
  238. }
  239. // Propogate the disk info into the current registry.
  240. //
  241. // Start by opening HKEY_LOCAL_MACHINE,System\DISK
  242. windowsError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  243. TEXT("System\\") DISK_KEY_NAME,
  244. REG_OPTION_RESERVED,
  245. KEY_WRITE,
  246. &hkeyDisk);
  247. if (windowsError != NO_ERROR) {
  248. LocalFree(diskInfo);
  249. return windowsError;
  250. }
  251. // Set the Information value in the DISK key.
  252. windowsError = RegSetValueEx(hkeyDisk,
  253. DISK_VALUE_NAME,
  254. 0,
  255. REG_BINARY,
  256. diskInfo,
  257. diskInfoSize);
  258. RegCloseKey(hkeyDisk);
  259. LocalFree(diskInfo);
  260. return windowsError;
  261. }
  262. typedef struct _STRING_LIST_NODE {
  263. struct _STRING_LIST_NODE *Next;
  264. LPTSTR String;
  265. } STRING_LIST_NODE, *PSTRING_LIST_NODE;
  266. PSTRING_LIST_NODE FoundDirectoryList;
  267. ULONG FoundDirectoryCount;
  268. TCHAR Pattern[MAX_PATH+1];
  269. WIN32_FIND_DATA FindData;
  270. OFSTRUCT OfStruct;
  271. HWND hwndStatus;
  272. BOOLEAN ScanDrive[26];
  273. BOOLEAN UserCancelled;
  274. typedef
  275. BOOL
  276. (*PFOUND_HIVE_ROUTINE)(
  277. IN LPTSTR Directory
  278. );
  279. VOID
  280. ProcessPendingMessages(
  281. VOID
  282. )
  283. /*++
  284. Routine Description:
  285. Preprocess messages.
  286. Arguments:
  287. None
  288. Return Value:
  289. None
  290. --*/
  291. {
  292. MSG msg;
  293. while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  294. DispatchMessage(&msg);
  295. }
  296. }
  297. PUCHAR ConfigRegistryPath = "\\system32\\config\\system";
  298. BOOL
  299. FdpSearchTreeForSystemHives(
  300. IN LPTSTR CurrentDirectory,
  301. IN PFOUND_HIVE_ROUTINE FoundHiveRoutine,
  302. IN HWND hdlg
  303. )
  304. /*++
  305. Routine Description:
  306. Search an entire directory tree for system and system.alt hive files.
  307. When found, call a callback function with the directory in which
  308. system32\config\system[.alt] was found, and the full path of the hive
  309. file.
  310. The root directory is not included in the search.
  311. The top-level call to this function should have a current directory
  312. like "C:." (ie, no slash for the root directory).
  313. Arguments:
  314. CurrentDirectory - supplies current directory search path
  315. Return Value:
  316. FALSE if error (callback function returned FALSE when we found an entry).
  317. --*/
  318. {
  319. HANDLE findHandle;
  320. TCHAR newDirectory[MAX_PATH+1];
  321. BOOL found = FALSE;
  322. // Iterate through the current directory, looking for subdirectories.
  323. lstrcpy(Pattern, CurrentDirectory);
  324. lstrcat(Pattern, "\\*");
  325. findHandle = FindFirstFile(Pattern, &FindData);
  326. if (findHandle != INVALID_HANDLE_VALUE) {
  327. do {
  328. ProcessPendingMessages();
  329. if (UserCancelled) {
  330. return FALSE;
  331. }
  332. // If the current match is not a directory then skip it.
  333. if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  334. || !lstrcmp(FindData.cFileName,TEXT("."))
  335. || !lstrcmp(FindData.cFileName,TEXT(".."))) {
  336. continue;
  337. }
  338. found = FALSE;
  339. // Form the name of the file we are looking for
  340. // [<currentdirectory>\<match>\system32\config\system]
  341. lstrcpy(Pattern, CurrentDirectory);
  342. lstrcat(Pattern, "\\");
  343. lstrcat(Pattern, FindData. cFileName);
  344. lstrcpy(newDirectory, Pattern);
  345. // Don't decend into the directory unless the path to the
  346. // hive.alt name is within MAX_PATH length.
  347. if ((ULONG)(lstrlen(newDirectory) / sizeof(TCHAR)) < (MAX_PATH - strlen(ConfigRegistryPath) - 4)) {
  348. SetDlgItemText(hdlg, IDC_SIMPLE_TEXT_LINE, newDirectory);
  349. lstrcat(Pattern, TEXT(ConfigRegistryPath));
  350. if (OpenFile(Pattern, &OfStruct, OF_EXIST) != (HFILE)(-1)) {
  351. found = TRUE;
  352. }
  353. // Also check for a system.alt file there
  354. lstrcat(Pattern,TEXT(".alt"));
  355. if (OpenFile(Pattern, &OfStruct, OF_EXIST) != (HFILE)(-1)) {
  356. found = TRUE;
  357. }
  358. if (found) {
  359. if (!FoundHiveRoutine(newDirectory)) {
  360. return FALSE;
  361. }
  362. }
  363. // Descend into the directory we just found
  364. if (!FdpSearchTreeForSystemHives(newDirectory, FoundHiveRoutine, hdlg)) {
  365. return FALSE;
  366. }
  367. }
  368. } while (FindNextFile(findHandle,&FindData));
  369. FindClose(findHandle);
  370. }
  371. return TRUE;
  372. }
  373. BOOL
  374. FdpFoundHiveCallback(
  375. IN PCHAR Directory
  376. )
  377. /*++
  378. Routine Description:
  379. This routine is called when a directory containing a system hive
  380. has been located. If all goes well (allocate memory and the like)
  381. this routine will save the directory name in a list for later use.
  382. NOTE: No checks are made on the directory name being greater in
  383. length than MAX_PATH. It is the responsibility of the caller to
  384. insure that this is true.
  385. Arguments:
  386. Directory - the pointer to the character string for the directory
  387. where a hive has been located.
  388. Return Value:
  389. TRUE - did something with it.
  390. FALSE - did not save the directory.
  391. --*/
  392. {
  393. TCHAR windowsDir[MAX_PATH+1];
  394. PSTRING_LIST_NODE dirItem;
  395. LPTSTR p;
  396. // If this is the current windows directory, skip it.
  397. GetWindowsDirectory(windowsDir, sizeof(windowsDir)/sizeof(TCHAR));
  398. if (!lstrcmpi(Directory, windowsDir)) {
  399. return TRUE;
  400. }
  401. // Save the directory information away
  402. dirItem = (PSTRING_LIST_NODE)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(STRING_LIST_NODE));
  403. if (dirItem == NULL) {
  404. return FALSE;
  405. }
  406. p = (LPTSTR)LocalAlloc(LMEM_FIXED,(lstrlen(Directory)+1) * sizeof(TCHAR));
  407. if (p == NULL) {
  408. LocalFree(dirItem);
  409. return FALSE;
  410. }
  411. dirItem->String = p;
  412. lstrcpy(p, Directory);
  413. // Update the global chain of found directories.
  414. dirItem->Next = FoundDirectoryList;
  415. FoundDirectoryList = dirItem;
  416. FoundDirectoryCount++;
  417. return TRUE;
  418. }
  419. VOID
  420. FdpFreeDirectoryList(
  421. VOID
  422. )
  423. /*++
  424. Routine Description:
  425. Go through the list of directories containing system hives and
  426. free the entries.
  427. Arguments:
  428. None
  429. Return Value:
  430. None
  431. --*/
  432. {
  433. PSTRING_LIST_NODE n,
  434. p = FoundDirectoryList;
  435. while (p) {
  436. n = p->Next;
  437. if (p->String) {
  438. LocalFree(p->String);
  439. }
  440. LocalFree(p);
  441. p = n;
  442. }
  443. FoundDirectoryCount = 0;
  444. FoundDirectoryList = NULL;
  445. }
  446. BOOL CALLBACK
  447. FdpScanningDirsDlgProc(
  448. IN HWND hwnd,
  449. IN UINT msg,
  450. IN WPARAM wParam,
  451. IN LPARAM lParam
  452. )
  453. /*++
  454. Routine Description:
  455. Display the "scanning" dialog, then when the IDLE message arrives
  456. process all drive letters and search for system hives.
  457. Arguments:
  458. Windows dialog proc
  459. Return Value:
  460. Windows dialog proc
  461. --*/
  462. {
  463. TCHAR LetterColon[3];
  464. TCHAR Letter;
  465. switch (msg) {
  466. case WM_INITDIALOG:
  467. CenterDialog(hwnd);
  468. break;
  469. case WM_ENTERIDLE:
  470. // Sent to us by the main window after the dialog is displayed.
  471. // Perform the search here.
  472. ConfigurationSearchIdleTrigger = FALSE;
  473. UserCancelled = FALSE;
  474. lstrcpy(LetterColon,TEXT("?:"));
  475. for (Letter = TEXT('A'); Letter <= TEXT('Z'); Letter++) {
  476. if (!ScanDrive[Letter-TEXT('A')]) {
  477. continue;
  478. }
  479. LetterColon[0] = Letter;
  480. if (!FdpSearchTreeForSystemHives(LetterColon, FdpFoundHiveCallback, hwnd)) {
  481. EndDialog(hwnd,IDCANCEL);
  482. return TRUE;
  483. }
  484. }
  485. EndDialog(hwnd,IDOK);
  486. break;
  487. case WM_COMMAND:
  488. switch (LOWORD(wParam)) {
  489. case IDCANCEL:
  490. UserCancelled = TRUE;
  491. break;
  492. default:
  493. return FALSE;
  494. }
  495. break;
  496. default:
  497. return FALSE;
  498. }
  499. return TRUE;
  500. }
  501. BOOL CALLBACK
  502. FdpSelectDirDlgProc(
  503. IN HWND hwnd,
  504. IN UINT msg,
  505. IN WPARAM wParam,
  506. IN LPARAM lParam
  507. )
  508. /*++
  509. Routine Description:
  510. Using the list of directories containing system hives, display the
  511. selections to the user and save the selected item if the user so
  512. chooses.
  513. Arguments:
  514. Windows dialog proc.
  515. Return Value:
  516. Windows dialog proc.
  517. --*/
  518. {
  519. PSTRING_LIST_NODE Str;
  520. LONG i;
  521. static HANDLE ListBoxHandle;
  522. switch (msg) {
  523. case WM_INITDIALOG:
  524. CenterDialog(hwnd);
  525. // Add each item in the directory list to the listbox
  526. ListBoxHandle = GetDlgItem(hwnd,IDC_LISTBOX);
  527. for (Str = FoundDirectoryList; Str; Str = Str->Next) {
  528. i = SendMessage(ListBoxHandle,LB_ADDSTRING ,0,(LONG)Str->String);
  529. SendMessage(ListBoxHandle,LB_SETITEMDATA,i,(LONG)Str );
  530. }
  531. // select the zeroth item
  532. SendMessage(ListBoxHandle,LB_SETCURSEL,0,0);
  533. break;
  534. case WM_COMMAND:
  535. switch (LOWORD(wParam)) {
  536. case IDOK:
  537. // Get the index of the current list box selection and the
  538. // pointer to the string node associated with it.
  539. i = SendMessage(ListBoxHandle,LB_GETCURSEL,0,0);
  540. EndDialog(hwnd,SendMessage(ListBoxHandle,LB_GETITEMDATA,i,0));
  541. break;
  542. case IDCANCEL:
  543. EndDialog(hwnd,(int)NULL);
  544. break;
  545. default:
  546. return FALSE;
  547. }
  548. break;
  549. default:
  550. return FALSE;
  551. }
  552. return TRUE;
  553. }
  554. BOOL
  555. DoMigratePreviousFtConfig(
  556. VOID
  557. )
  558. /*++
  559. Routine Description:
  560. Allow the user to move the disk config info from a different Windows NT
  561. installation into the current registry.
  562. For each fixed disk volume, scan it for system hives and present the
  563. results to the user so he can select the installation to migrate.
  564. Then load the system hive from that instllation (system.alt if the system
  565. hive is corrupt, etc) and transfer the DISK:Information binary blob.
  566. Arguments:
  567. None.
  568. Return Value:
  569. FALSE if error or user cancelled, TRUE if info was migrated and reboot
  570. is required.
  571. --*/
  572. {
  573. LONG windowsError;
  574. TCHAR letter;
  575. TCHAR letterColon[4];
  576. PSTRING_LIST_NODE stringNode;
  577. // Tell the user what this will do and prompt for confirmation
  578. if (ConfirmationDialog(MSG_CONFIRM_MIGRATE_CONFIG, MB_ICONEXCLAMATION | MB_YESNO) != IDYES) {
  579. return FALSE;
  580. }
  581. ProcessPendingMessages();
  582. // Figure out which drives are relevent
  583. SetCursor(hcurWait);
  584. RtlZeroMemory(ScanDrive,sizeof(ScanDrive));
  585. lstrcpy(letterColon,TEXT("?:\\"));
  586. for (letter=TEXT('A'); letter<=TEXT('Z'); letter++) {
  587. letterColon[0] = letter;
  588. if (GetDriveType(letterColon) == DRIVE_FIXED) {
  589. ScanDrive[letter-TEXT('A')] = TRUE;
  590. }
  591. }
  592. SetCursor(hcurNormal);
  593. // Create a window that will list the directories being scanned, to
  594. // keep the user entertained.
  595. ConfigurationSearchIdleTrigger = TRUE;
  596. windowsError = DialogBox(hModule,
  597. MAKEINTRESOURCE(IDD_SIMPLETEXT),
  598. hwndFrame,
  599. FdpScanningDirsDlgProc);
  600. if (windowsError == IDCANCEL) {
  601. FdpFreeDirectoryList();
  602. return FALSE;
  603. }
  604. ProcessPendingMessages();
  605. if (!FoundDirectoryCount) {
  606. InfoDialog(MSG_NO_OTHER_NTS);
  607. return FALSE;
  608. }
  609. // Display a dialog box that allows the user to select one of the
  610. // directories we found.
  611. stringNode = (PSTRING_LIST_NODE)DialogBox(hModule,
  612. MAKEINTRESOURCE(IDD_SELDIR),
  613. hwndFrame,
  614. FdpSelectDirDlgProc);
  615. if (stringNode == NULL) {
  616. FdpFreeDirectoryList();
  617. return FALSE;
  618. }
  619. // User made a selection. One last confirmation.
  620. if (ConfirmationDialog(MSG_ABSOLUTELY_SURE,MB_ICONEXCLAMATION | MB_YESNO) != IDYES) {
  621. FdpFreeDirectoryList();
  622. return FALSE;
  623. }
  624. ProcessPendingMessages();
  625. SetCursor(hcurWait);
  626. lstrcpy(Pattern,stringNode->String);
  627. lstrcat(Pattern,TEXT(ConfigRegistryPath));
  628. windowsError = FdTransferOldDiskInfoToRegistry(Pattern);
  629. if (windowsError != NO_ERROR) {
  630. lstrcat(Pattern,TEXT(".alt"));
  631. windowsError = FdTransferOldDiskInfoToRegistry(Pattern);
  632. }
  633. FdpFreeDirectoryList();
  634. SetCursor(hcurNormal);
  635. if (windowsError != NO_ERROR) {
  636. if (windowsError == ERROR_FILE_NOT_FOUND) {
  637. ErrorDialog(MSG_NO_DISK_INFO);
  638. } else if (windowsError == ERROR_SHARING_VIOLATION) {
  639. ErrorDialog(MSG_DISK_INFO_BUSY);
  640. } else {
  641. ErrorDialog(windowsError);
  642. }
  643. return FALSE;
  644. }
  645. return TRUE;
  646. }
  647. BOOL
  648. DoRestoreFtConfig(
  649. VOID
  650. )
  651. /*++
  652. Routine Description:
  653. Restore previously saved disk configuration information into the
  654. active registry.
  655. The saved config info will come from a floppy that the user is
  656. prompted to insert.
  657. Arguments:
  658. None.
  659. Return Value:
  660. FALSE if error or user cancelled, TRUE if info was restored and reboot
  661. is required.
  662. --*/
  663. {
  664. LONG Err;
  665. TCHAR caption[256];
  666. UINT errorMode;
  667. va_list arglist =
  668. #ifdef _ALPHA_ // Alpha defines va_list as a struct. Init as such
  669. {0};
  670. #else
  671. NULL;
  672. #endif
  673. // Get confirmation
  674. if (ConfirmationDialog(MSG_CONFIRM_RESTORE_CONFIG, MB_ICONEXCLAMATION | MB_YESNO) != IDYES) {
  675. return FALSE;
  676. }
  677. // Get the diskette into A:.
  678. errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  679. LoadString(hModule,IDS_INSERT_DISK,caption,sizeof(caption)/sizeof(TCHAR));
  680. if (CommonDialog(MSG_INSERT_REGSAVEDISK,caption,MB_OKCANCEL | MB_TASKMODAL, arglist) != IDOK) {
  681. return FALSE;
  682. }
  683. ProcessPendingMessages();
  684. SetCursor(hcurWait);
  685. // If there is no file called SYSTEM on a:\, it appears that the registry
  686. // creates one and then keeps it open. To avoid this, check to see
  687. // whether there is one first.
  688. if (OpenFile(TEXT("A:\\SYSTEM"),&OfStruct,OF_EXIST) == (HFILE)(-1)) {
  689. Err = ERROR_FILE_NOT_FOUND;
  690. } else {
  691. Err = FdTransferOldDiskInfoToRegistry(TEXT("A:\\SYSTEM"));
  692. }
  693. SetErrorMode(errorMode);
  694. SetCursor(hcurNormal);
  695. if (Err != NO_ERROR) {
  696. ErrorDialog(Err);
  697. return FALSE;
  698. }
  699. return TRUE;
  700. }
  701. VOID
  702. DoSaveFtConfig(
  703. VOID
  704. )
  705. /*++
  706. Routine Description:
  707. Allow the user to update the registry save diskette with the currently
  708. defined disk configuration. The saved info excludes any changes made
  709. during this session of disk manager.
  710. Arguments:
  711. None.
  712. Return Value:
  713. None.
  714. --*/
  715. {
  716. LONG Err,
  717. ErrAlt;
  718. LPTSTR SystemHiveName = TEXT("a:\\system");
  719. HKEY hkey;
  720. TCHAR caption[256];
  721. DWORD disposition;
  722. UINT errorMode;
  723. va_list arglist =
  724. #ifdef _ALPHA_
  725. {0}; // Alpha defines va_list as a struct. Init as such.
  726. #else
  727. NULL;
  728. #endif
  729. // Get a diskette into A:.
  730. LoadString(hModule,
  731. IDS_INSERT_DISK,
  732. caption,
  733. sizeof(caption)/sizeof(TCHAR));
  734. if (CommonDialog(MSG_INSERT_REGSAVEDISK2,caption,MB_OKCANCEL | MB_TASKMODAL, arglist) != IDOK) {
  735. return;
  736. }
  737. // Decide what to do based on the presence of a a:\system. If that file
  738. // is present, just update the DISK entry in it. If it is not present,
  739. // then blast out the entire system hive.
  740. errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  741. ProcessPendingMessages();
  742. SetCursor(hcurWait);
  743. if (OpenFile(SystemHiveName,&OfStruct,OF_EXIST) == (HFILE)(-1)) {
  744. BOOLEAN OldPrivState;
  745. NTSTATUS Status;
  746. // Blast the entire system hive out to the floppy.
  747. // Start by attempting to get backup privilege.
  748. Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
  749. TRUE,
  750. FALSE,
  751. &OldPrivState);
  752. Err = RtlNtStatusToDosError(Status);
  753. if (Err == NO_ERROR) {
  754. Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  755. TEXT("system"),
  756. REG_OPTION_RESERVED,
  757. KEY_READ,
  758. &hkey);
  759. if (Err == NO_ERROR) {
  760. Err = RegSaveKey(hkey,SystemHiveName,NULL);
  761. RegCloseKey(hkey);
  762. }
  763. if (!OldPrivState) {
  764. RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,FALSE,FALSE,&OldPrivState);
  765. }
  766. }
  767. } else {
  768. PVOID DiskInfo;
  769. ULONG DiskInfoSize;
  770. // Load up the saved system hive
  771. Err = FdpLoadHiveIntoRegistry(SystemHiveName);
  772. if (Err == NO_ERROR) {
  773. // Get the current DISK information
  774. Err = FdpGetDiskInfoFromKey(TEXT("system"),&DiskInfo,&DiskInfoSize);
  775. if (Err == NO_ERROR) {
  776. // Place the current disk information into the saved hive
  777. Err = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  778. TEMP_KEY_NAME TEXT("\\") DISK_KEY_NAME,
  779. 0,
  780. "Disk and fault tolerance information.",
  781. REG_OPTION_NON_VOLATILE,
  782. KEY_WRITE,
  783. NULL,
  784. &hkey,
  785. &disposition );
  786. if (Err == NO_ERROR) {
  787. Err = RegSetValueEx(hkey,
  788. DISK_VALUE_NAME,
  789. REG_OPTION_RESERVED,
  790. REG_BINARY,
  791. DiskInfo,
  792. DiskInfoSize);
  793. RegFlushKey(hkey);
  794. RegCloseKey(hkey);
  795. }
  796. LocalFree(DiskInfo);
  797. }
  798. ErrAlt = FdpUnloadHiveFromRegistry();
  799. if (Err == NO_ERROR && ErrAlt != NO_ERROR) {
  800. Err = ErrAlt;
  801. }
  802. }
  803. }
  804. SetCursor(hcurNormal);
  805. SetErrorMode(errorMode);
  806. if (Err == NO_ERROR) {
  807. InfoDialog(MSG_CONFIG_SAVED_OK);
  808. } else {
  809. ErrorDialog(Err);
  810. }
  811. return;
  812. }