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.

1656 lines
47 KiB

  1. #include "cmdcons.h"
  2. #pragma hdrstop
  3. #include <crypt.h>
  4. #include <recovery.h>
  5. #include <ntsamp.h>
  6. #include <spkbd.h>
  7. static BOOL firstTime = TRUE;
  8. static CONST PWSTR gszSoftwareHiveName = L"software";
  9. static CONST PWSTR gszSoftwareHiveKey= L"\\registry\\machine\\xSOFTWARE";
  10. static CONST PWSTR gszSAMHiveName = L"sam";
  11. static CONST PWSTR gszSAMHiveKey = L"\\registry\\machine\\security";
  12. static CONST PWSTR gszSystemHiveName = L"system";
  13. static CONST PWSTR gszSystemHiveKey = L"\\registry\\machine\\xSYSTEM";
  14. static CONST PWSTR gszSecurityHiveName = L"security";
  15. static CONST PWSTR gszSecurityHiveKey = L"\\registry\\machine\\xSECURITY";
  16. LIST_ENTRY NtInstalls;
  17. ULONG InstallCount;
  18. LIST_ENTRY NtInstallsFullScan;
  19. ULONG InstallCountFullScan;
  20. PNT_INSTALLATION SelectedInstall;
  21. LARGE_INTEGER glBias;
  22. #define IS_VALID_INSTALL(x) (((x) > 0) && ((x) <= InstallCount))
  23. typedef struct _KEY_CHECK_STRUCT {
  24. WCHAR *szKeyName;
  25. BOOLEAN bControlSet;
  26. } KEY_CHECK_STRUCT;
  27. //
  28. // forward declarations
  29. //
  30. BOOLEAN
  31. LoginRequired(
  32. VOID
  33. );
  34. BOOLEAN
  35. RcOpenHive(
  36. PWSTR szHiveName,
  37. PWSTR szHiveKey
  38. );
  39. BOOLEAN
  40. RcCloseHive(
  41. PWSTR szHiveKey
  42. );
  43. BOOLEAN
  44. RcIsValidSystemHive(
  45. VOID
  46. );
  47. BOOLEAN
  48. IsSetCommandEnabled(
  49. VOID
  50. );
  51. BOOLEAN
  52. RcDetermineCorrectControlKey(
  53. OUT PULONG pCorrectKey
  54. );
  55. LARGE_INTEGER
  56. RcGetTimeZoneBias(
  57. VOID
  58. );
  59. VOID
  60. RcDestroyList(
  61. PLIST_ENTRY ListHead
  62. )
  63. {
  64. PLIST_ENTRY Entry = ListHead->Flink;
  65. if(Entry != NULL) {
  66. while(Entry != ListHead) {
  67. PLIST_ENTRY Next = Entry->Flink;
  68. SpMemFree(Entry);
  69. Entry = Next;
  70. }
  71. }
  72. InitializeListHead(ListHead);
  73. }
  74. BOOL
  75. RcLogonDiskRegionEnum(
  76. IN PPARTITIONED_DISK Disk,
  77. IN PDISK_REGION Region,
  78. IN ULONG_PTR UseArcNames
  79. )
  80. {
  81. WCHAR buf[MAX_PATH];
  82. OBJECT_ATTRIBUTES Obja;
  83. HANDLE DirectoryHandle;
  84. NTSTATUS Status;
  85. UNICODE_STRING UnicodeString;
  86. IO_STATUS_BLOCK IoStatusBlock;
  87. PFILE_BOTH_DIR_INFORMATION DirectoryInfo;
  88. struct SEARCH_BUFFER {
  89. FILE_BOTH_DIR_INFORMATION DirInfo;
  90. WCHAR Names[MAX_PATH];
  91. } Buffer;
  92. UNICODE_STRING FileName;
  93. LPWSTR s;
  94. PNT_INSTALLATION NtInstall;
  95. swprintf( buf, L"\\??\\%c:\\", Region->DriveLetter );
  96. INIT_OBJA( &Obja, &UnicodeString, buf );
  97. Status = ZwOpenFile(
  98. &DirectoryHandle,
  99. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  100. &Obja,
  101. &IoStatusBlock,
  102. FILE_SHARE_READ | FILE_SHARE_WRITE,
  103. FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
  104. );
  105. if (!NT_SUCCESS(Status)) {
  106. return TRUE;
  107. }
  108. DirectoryInfo = &Buffer.DirInfo;
  109. RtlInitUnicodeString( &FileName, L"*" );
  110. while (NT_SUCCESS(Status)) {
  111. Status = ZwQueryDirectoryFile(
  112. DirectoryHandle,
  113. NULL,
  114. NULL,
  115. NULL,
  116. &IoStatusBlock,
  117. DirectoryInfo,
  118. sizeof(Buffer),
  119. FileBothDirectoryInformation,
  120. TRUE,
  121. &FileName,
  122. FALSE
  123. );
  124. if (NT_SUCCESS(Status) && DirectoryInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  125. swprintf( buf, L"\\??\\%c:\\", Region->DriveLetter );
  126. wcsncat( buf, DirectoryInfo->FileName, DirectoryInfo->FileNameLength/sizeof(WCHAR) );
  127. wcscat( buf, L"\\system32\\config" );
  128. if (SpFileExists(buf, TRUE)) {
  129. swprintf( buf, L"\\??\\%c:\\", Region->DriveLetter );
  130. wcsncat( buf, DirectoryInfo->FileName, DirectoryInfo->FileNameLength/sizeof(WCHAR) );
  131. wcscat( buf, L"\\system32\\drivers" );
  132. if (SpFileExists(buf, TRUE)) {
  133. NtInstall = (PNT_INSTALLATION) SpMemAlloc( sizeof(NT_INSTALLATION) );
  134. if (NtInstall) {
  135. RtlZeroMemory( NtInstall, sizeof(NT_INSTALLATION) );
  136. NtInstall->InstallNumber = ++InstallCount;
  137. NtInstall->DriveLetter = Region->DriveLetter;
  138. NtInstall->Region = Region;
  139. wcsncpy( NtInstall->Path, DirectoryInfo->FileName,
  140. DirectoryInfo->FileNameLength/sizeof(WCHAR) );
  141. InsertTailList( &NtInstalls, &NtInstall->ListEntry );
  142. }
  143. }
  144. }
  145. }
  146. }
  147. ZwClose( DirectoryHandle );
  148. return TRUE;
  149. }
  150. BOOLEAN
  151. RcScanForNTInstallEnum(
  152. IN PCWSTR DirName,
  153. IN PFILE_BOTH_DIR_INFORMATION FileInfo,
  154. OUT PULONG ret,
  155. IN PVOID Pointer
  156. )
  157. /*++
  158. Routine Description:
  159. NOTE: this routine os of type: ENUMFILESPROC (spmisc.h)
  160. This routine determines if the directory which is currently being
  161. enumerated is an NT install directory
  162. Arguments:
  163. DirName - IN: the directory in which the file to enumerate exists
  164. FileInfo - IN: file attributes for the file to enumerate
  165. ret - OUT: return status of this procedure
  166. Pointer - IN: contains persistent recursion data
  167. Return Value:
  168. A linked list of SP_DISCOVERED_NT_INSTALLS, where each structure
  169. refers to a discovered installation of Windows
  170. --*/
  171. {
  172. PWSTR FileName;
  173. PWSTR FullPath;
  174. PWSTR PartialPathName;
  175. BOOLEAN IsNtInstall;
  176. PRC_SCAN_RECURSION_DATA RecursionData;
  177. //
  178. // Ignore non-directories
  179. //
  180. if(! (FileInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  181. return TRUE; // continue processing
  182. }
  183. //
  184. // Build the full file or dir path
  185. //
  186. //
  187. // We have to make a copy of the directory name, because the info struct
  188. // we get isn't NULL-terminated.
  189. //
  190. wcsncpy(
  191. TemporaryBuffer,
  192. FileInfo->FileName,
  193. FileInfo->FileNameLength
  194. );
  195. (TemporaryBuffer)[FileInfo->FileNameLength / sizeof(WCHAR)] = UNICODE_NULL;
  196. FileName = SpDupStringW(TemporaryBuffer);
  197. wcscpy(TemporaryBuffer,DirName);
  198. SpConcatenatePaths(TemporaryBuffer,FileName);
  199. FullPath = SpDupStringW(TemporaryBuffer);
  200. SpMemFree(FileName);
  201. //
  202. // Get the recursion data
  203. //
  204. RecursionData = (PRC_SCAN_RECURSION_DATA)Pointer;
  205. //
  206. // get the directory component beyond the root directory
  207. //
  208. PartialPathName = FullPath + RecursionData->RootDirLength;
  209. ASSERT(PartialPathName < (FullPath + wcslen(FullPath)));
  210. //
  211. // Test if the directory is an NT install
  212. //
  213. IsNtInstall = SpIsNtInDirectory(RecursionData->NtPartitionRegion,
  214. PartialPathName
  215. );
  216. //
  217. // if we found an NT install, then add it to our linked list
  218. //
  219. if(IsNtInstall) {
  220. PNT_INSTALLATION NtInstall;
  221. NtInstall = (PNT_INSTALLATION) SpMemAlloc( sizeof(NT_INSTALLATION) );
  222. if (NtInstall) {
  223. RtlZeroMemory( NtInstall, sizeof(NT_INSTALLATION) );
  224. NtInstall->InstallNumber = ++InstallCountFullScan;
  225. NtInstall->DriveLetter = RecursionData->NtPartitionRegion->DriveLetter;
  226. NtInstall->Region = RecursionData->NtPartitionRegion;
  227. //
  228. // Note: this PartialPathName contains the '\' at the beginning of the
  229. // Path, while the FileName used in RcLogonDiskRegionEnum
  230. // does not
  231. //
  232. wcsncpy( NtInstall->Path, PartialPathName, sizeof(NtInstall->Path)/sizeof(WCHAR));
  233. InsertTailList( &NtInstallsFullScan, &NtInstall->ListEntry );
  234. }
  235. }
  236. SpMemFree(FullPath);
  237. return TRUE; // continue processing
  238. }
  239. BOOL
  240. RcScanDisksForNTInstallsEnum(
  241. IN PPARTITIONED_DISK Disk,
  242. IN PDISK_REGION NtPartitionRegion,
  243. IN ULONG_PTR Context
  244. )
  245. /*++
  246. Routine Description:
  247. This routine launches the directory level scan for NT installs.
  248. Arguments:
  249. Disk - the disk we are scanning
  250. NtPartitionRegion - the partition we are scanning
  251. Context - the persistent recursion data
  252. Return Value:
  253. TRUE - continue scanning
  254. FALSE - stop scanning
  255. --*/
  256. {
  257. ULONG EnumReturnData;
  258. ENUMFILESRESULT EnumFilesResult;
  259. PWSTR NtPartition;
  260. PWSTR DirName;
  261. PRC_SCAN_RECURSION_DATA RecursionData;
  262. //
  263. // make sure this is valid partition:
  264. //
  265. // not reserved
  266. // filesystem is ntfs || fat
  267. //
  268. if (((NtPartitionRegion->Filesystem != FilesystemFat) &&
  269. (NtPartitionRegion->Filesystem != FilesystemFat32) &&
  270. (NtPartitionRegion->Filesystem != FilesystemNtfs)
  271. ) ||
  272. (NtPartitionRegion->IsReserved == 1)
  273. ) {
  274. KdPrintEx((DPFLTR_SETUP_ID,
  275. DPFLTR_INFO_LEVEL,
  276. "SPCMDCON: RcScanDisksForNTInstallsEnum: skipping filesystem type %x\r\n",
  277. NtPartitionRegion->Filesystem
  278. ));
  279. return TRUE;
  280. }
  281. //
  282. // Get our context
  283. //
  284. RecursionData = (PRC_SCAN_RECURSION_DATA)Context;
  285. //
  286. // Keep track of which partition region we are dealing with
  287. // so that the file enumeration routine can pass this info
  288. // on to SpIsNtInDirectory.
  289. //
  290. RecursionData->NtPartitionRegion = NtPartitionRegion;
  291. //
  292. // Get the device path of the nt partition.
  293. //
  294. SpNtNameFromRegion(
  295. NtPartitionRegion,
  296. TemporaryBuffer,
  297. sizeof(TemporaryBuffer),
  298. PartitionOrdinalCurrent
  299. );
  300. NtPartition = SpDupStringW(TemporaryBuffer);
  301. //
  302. // Begin searching at the root directory
  303. //
  304. wcscpy(TemporaryBuffer, NtPartition);
  305. SpConcatenatePaths(TemporaryBuffer, L"\\");
  306. DirName = SpDupStringW(TemporaryBuffer);
  307. //
  308. // get the length of the root directory string less the
  309. // directory separator. This will be used to remove
  310. // the root dir component of the pathname when we pass
  311. // the dir name into SpIsNtInDirectory. We need to do this
  312. // because SpIsNtInDirectory adds the root dir back in.
  313. //
  314. RecursionData->RootDirLength = wcslen(DirName) - 1;
  315. KdPrintEx((DPFLTR_SETUP_ID,
  316. DPFLTR_INFO_LEVEL,
  317. "SPCMDCON: SpScanDisksForNTInstalls: Scanning: %s\n",
  318. DirName
  319. ));
  320. //
  321. // Enumerate all the directories on the current partition
  322. //
  323. // Note: if the enumeration does not return with a status of NormalReturn,
  324. // we do not stop the scanning process, rather we will contine on
  325. // scanning any remaining disks/partitions.
  326. //
  327. EnumFilesResult = SpEnumFilesRecursiveLimited(
  328. DirName,
  329. RcScanForNTInstallEnum,
  330. MAX_FULL_SCAN_RECURSION_DEPTH,
  331. 0,
  332. &EnumReturnData,
  333. RecursionData
  334. );
  335. if (EnumFilesResult != NormalReturn) {
  336. KdPrintEx((DPFLTR_SETUP_ID,
  337. DPFLTR_INFO_LEVEL,
  338. "SPCMDCON: SpScanDisksForNTInstalls: Enum Files returned non-normal result: %x\n",
  339. EnumFilesResult
  340. ));
  341. }
  342. //
  343. // we are done with instance of DirName
  344. //
  345. SpMemFree(DirName);
  346. return TRUE;
  347. }
  348. NTSTATUS
  349. RcAuthorizePasswordLogon(
  350. IN PWSTR UserName,
  351. IN PWSTR UserPassword,
  352. IN PNT_INSTALLATION NtInstall
  353. )
  354. {
  355. #define BUFFERSIZE (sizeof(KEY_VALUE_PARTIAL_INFORMATION)+256)
  356. OBJECT_ATTRIBUTES Obja;
  357. UNICODE_STRING UnicodeString;
  358. NTSTATUS Status;
  359. NTSTATUS TmpStatus;
  360. WCHAR KeyName[128];
  361. PWSTR Hive = NULL;
  362. PWSTR HiveKey = NULL;
  363. PUCHAR buffer = NULL;
  364. PWSTR PartitionPath = NULL;
  365. HANDLE hKeySamRoot = NULL;
  366. HANDLE hKeyNames = NULL;
  367. HANDLE hKeyUser = NULL;
  368. HANDLE hKeySystemRoot = NULL;
  369. HANDLE hKeySecurityRoot = NULL;
  370. ULONG ResultLength;
  371. ULONG Number;
  372. ULONG Rid;
  373. NT_OWF_PASSWORD NtOwfPassword;
  374. NT_OWF_PASSWORD UserOwfPassword;
  375. ULONG i;
  376. BOOLEAN NtPasswordPresent;
  377. BOOLEAN NtPasswordNonNull;
  378. WCHAR PasswordBuffer[128];
  379. UNICODE_STRING BootKeyPassword;
  380. PUNICODE_STRING pBootKeyPassword = NULL;
  381. USHORT BootKeyType = 0;
  382. PWCHAR MessageText = NULL;
  383. UNICODE_STRING SysKeyFileName;
  384. HANDLE SysKeyHandle;
  385. IO_STATUS_BLOCK IoStatusBlock;
  386. PWCHAR FloppyPath = NULL;
  387. BOOLEAN bSecurityHiveLoaded = FALSE;
  388. BOOLEAN bSysHiveLoaded = FALSE;
  389. BOOLEAN bSamHiveLoaded = FALSE;
  390. BOOLEAN bClearScreen = FALSE;
  391. //
  392. // Allocate buffers.
  393. //
  394. Hive = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  395. HiveKey = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  396. buffer = SpMemAlloc(BUFFERSIZE);
  397. //
  398. // Get the name of the target patition.
  399. //
  400. SpNtNameFromRegion(
  401. NtInstall->Region,
  402. _CmdConsBlock->TemporaryBuffer,
  403. _CmdConsBlock->TemporaryBufferSize,
  404. PartitionOrdinalCurrent
  405. );
  406. PartitionPath = SpDupStringW(_CmdConsBlock->TemporaryBuffer);
  407. //
  408. // Load the SYSTEM hive
  409. //
  410. bSysHiveLoaded = RcOpenSystemHive();
  411. if (!bSysHiveLoaded){
  412. //
  413. // Note : System hive seems to be corrupted so go ahead
  414. // and let the user log in so that he/she can fix
  415. // the problem
  416. //
  417. Status = STATUS_SUCCESS;
  418. //RcSetSETCommandStatus(TRUE); // enable the set command also
  419. goto exit;
  420. }
  421. //
  422. // Now get a key to the root of the hive we just loaded.
  423. //
  424. wcscpy(HiveKey,L"\\registry\\machine\\xSYSTEM");
  425. INIT_OBJA(&Obja,&UnicodeString,HiveKey);
  426. Status = ZwOpenKey(&hKeySystemRoot,KEY_ALL_ACCESS,&Obja);
  427. if(!NT_SUCCESS(Status)) {
  428. KdPrint(("SETUP: Unable to open %ws (%lx)\n",HiveKey,Status));
  429. goto exit;
  430. }
  431. //
  432. // Load the SAM hive
  433. //
  434. wcscpy(Hive,PartitionPath);
  435. SpConcatenatePaths(Hive,NtInstall->Path);
  436. SpConcatenatePaths(Hive,L"system32\\config");
  437. SpConcatenatePaths(Hive,L"sam");
  438. //
  439. // Form the path of the key into which we will
  440. // load the hive. We'll use the convention that
  441. // a hive will be loaded into \registry\machine\security.
  442. //
  443. wcscpy(HiveKey,L"\\registry\\machine\\security");
  444. //
  445. // Attempt to load the key.
  446. //
  447. Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
  448. if(!NT_SUCCESS(Status)) {
  449. KdPrint(("SETUP: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
  450. //
  451. // Note : SAM hive seems to be corrupted so go ahead
  452. // and let the user log in so that he/she can fix
  453. // the problem
  454. //
  455. Status = STATUS_SUCCESS;
  456. //RcSetSETCommandStatus(TRUE); // enable the set command also
  457. goto exit;
  458. }
  459. bSamHiveLoaded = TRUE;
  460. //
  461. // Now get a key to the root of the hive we just loaded.
  462. //
  463. INIT_OBJA(&Obja,&UnicodeString,HiveKey);
  464. Status = ZwOpenKey(&hKeySamRoot,KEY_ALL_ACCESS,&Obja);
  465. if(!NT_SUCCESS(Status)) {
  466. KdPrint(("SETUP: Unable to open %ws (%lx)\n",HiveKey,Status));
  467. goto exit;
  468. }
  469. //
  470. // load the "security" hive
  471. //
  472. bSecurityHiveLoaded = RcOpenHive(gszSecurityHiveName, gszSecurityHiveKey);
  473. if (!bSecurityHiveLoaded) {
  474. KdPrint(("SETUP: Unable to load hive %ws to key %ws\n",
  475. gszSecurityHiveName, gszSecurityHiveKey));
  476. //
  477. // Note : securityy hive seems to be corrupted so go ahead
  478. // and let the user log in so that he/she can fix
  479. // the problem
  480. //
  481. Status = STATUS_SUCCESS;
  482. //RcSetSETCommandStatus(TRUE); // enable the set command also
  483. goto exit;
  484. }
  485. //
  486. // Now get a key to the root of the security hive we just loaded.
  487. //
  488. INIT_OBJA(&Obja,&UnicodeString,gszSecurityHiveKey);
  489. Status = ZwOpenKey(&hKeySecurityRoot,KEY_ALL_ACCESS,&Obja);
  490. if(!NT_SUCCESS(Status)) {
  491. KdPrint(("SETUP: Unable to open %ws (%lx)\n",gszSecurityHiveName,Status));
  492. goto exit;
  493. }
  494. if (_wcsicmp(UserName,L"administrator")==0) {
  495. Rid = DOMAIN_USER_RID_ADMIN;
  496. } else {
  497. //
  498. // Get the key to the account data base
  499. //
  500. wcscpy(KeyName,L"SAM\\Domains\\Account\\Users\\Names\\");
  501. wcscat(KeyName,UserName);
  502. INIT_OBJA(&Obja,&UnicodeString,KeyName);
  503. Obja.RootDirectory = hKeySamRoot;
  504. Status = ZwOpenKey(&hKeyNames,KEY_READ,&Obja);
  505. if(!NT_SUCCESS(Status)) {
  506. goto exit;
  507. }
  508. //
  509. // Get the RID of the user
  510. //
  511. UnicodeString.Length = 0;
  512. UnicodeString.MaximumLength = 0;
  513. UnicodeString.Buffer = _CmdConsBlock->TemporaryBuffer;
  514. Status = ZwQueryValueKey(
  515. hKeyNames,
  516. &UnicodeString,
  517. KeyValuePartialInformation,
  518. _CmdConsBlock->TemporaryBuffer,
  519. _CmdConsBlock->TemporaryBufferSize,
  520. &ResultLength
  521. );
  522. if(!NT_SUCCESS(Status)) {
  523. goto exit;
  524. }
  525. Rid = ((PKEY_VALUE_PARTIAL_INFORMATION)_CmdConsBlock->TemporaryBuffer)->Type;
  526. }
  527. while(TRUE){
  528. Status = SamRetrieveOwfPasswordUser(
  529. Rid,
  530. hKeySecurityRoot,
  531. hKeySamRoot,
  532. hKeySystemRoot,
  533. pBootKeyPassword,
  534. BootKeyType,
  535. &NtOwfPassword,
  536. &NtPasswordPresent,
  537. &NtPasswordNonNull
  538. );
  539. if (NT_SUCCESS(Status)) {
  540. break;
  541. }
  542. if (Status == STATUS_SAM_NEED_BOOTKEY_PASSWORD) {
  543. RcMessageOut( MSG_LOGON_PROMPT_SYSKEY_PASSWORD );
  544. RtlZeroMemory( PasswordBuffer, sizeof(PasswordBuffer) );
  545. RcPasswordIn( PasswordBuffer, sizeof(PasswordBuffer) / sizeof(WCHAR) );
  546. RtlInitUnicodeString( &BootKeyPassword, PasswordBuffer );
  547. pBootKeyPassword = &BootKeyPassword;
  548. BootKeyType = SamBootKeyPassword;
  549. }
  550. if (Status == STATUS_SAM_NEED_BOOTKEY_FLOPPY){
  551. FloppyPath = SpDupStringW(L"\\Device\\Floppy0");
  552. MessageText = SpRetreiveMessageText(ImageBase,MSG_LOGON_PROMPT_SYSKEY_FLOPPY,NULL,0);
  553. bClearScreen = TRUE;
  554. if (!SpPromptForDisk(
  555. MessageText,
  556. FloppyPath,
  557. L"StartKey.Key",
  558. TRUE,
  559. FALSE,
  560. FALSE,
  561. NULL
  562. )){
  563. Status = STATUS_WRONG_PASSWORD;
  564. goto exit;
  565. }
  566. INIT_OBJA( &Obja, &SysKeyFileName, L"\\Device\\Floppy0\\StartKey.Key" );
  567. Status = ZwCreateFile(&SysKeyHandle,
  568. FILE_GENERIC_READ,
  569. &Obja,
  570. &IoStatusBlock,
  571. NULL,
  572. FILE_ATTRIBUTE_NORMAL,
  573. FILE_SHARE_READ,
  574. FILE_OPEN,
  575. FILE_SYNCHRONOUS_IO_NONALERT,
  576. NULL,
  577. 0
  578. );
  579. if (NT_SUCCESS(Status))
  580. {
  581. Status = ZwReadFile(
  582. SysKeyHandle,
  583. NULL,
  584. NULL,
  585. NULL,
  586. &IoStatusBlock,
  587. (PVOID) &PasswordBuffer[0],
  588. sizeof(PasswordBuffer),
  589. 0,
  590. NULL
  591. );
  592. ZwClose( SysKeyHandle );
  593. if (NT_SUCCESS(Status)) {
  594. BootKeyPassword.Buffer = PasswordBuffer;
  595. BootKeyPassword.Length = BootKeyPassword.MaximumLength =
  596. (USHORT) IoStatusBlock.Information;
  597. pBootKeyPassword = &BootKeyPassword;
  598. BootKeyType = SamBootKeyDisk;
  599. } else {
  600. goto exit;
  601. }
  602. } else {
  603. goto exit;
  604. }
  605. }
  606. if (!NT_SUCCESS(Status) && Status != STATUS_SAM_NEED_BOOTKEY_PASSWORD && Status != STATUS_SAM_NEED_BOOTKEY_FLOPPY) {
  607. goto exit;
  608. }
  609. }
  610. if (NtPasswordPresent && !NtPasswordNonNull && *UserPassword == 0) {
  611. Status = STATUS_SUCCESS;
  612. goto exit;
  613. }
  614. if (!NtPasswordPresent && *UserPassword == 0) {
  615. Status = STATUS_SUCCESS;
  616. goto exit;
  617. }
  618. RtlInitUnicodeString( &UnicodeString, UserPassword );
  619. Status = RtlCalculateNtOwfPassword( &UnicodeString, &UserOwfPassword );
  620. if(!NT_SUCCESS(Status)) {
  621. goto exit;
  622. }
  623. if (!RtlEqualNtOwfPassword( &NtOwfPassword, &UserOwfPassword )) {
  624. Status = STATUS_WRONG_PASSWORD;
  625. }
  626. //
  627. // now check to see if this user has admin rights
  628. //
  629. exit:
  630. RtlSecureZeroMemory(PasswordBuffer, sizeof(PasswordBuffer));
  631. if(bClearScreen)
  632. pRcCls();
  633. //
  634. // close handles
  635. //
  636. if (hKeySamRoot)
  637. ZwClose(hKeySamRoot);
  638. if (hKeySecurityRoot)
  639. ZwClose(hKeySecurityRoot);
  640. if (hKeyNames) {
  641. ZwClose( hKeyNames );
  642. }
  643. if (hKeyUser) {
  644. ZwClose( hKeyUser );
  645. }
  646. if (hKeySystemRoot)
  647. ZwClose(hKeySystemRoot);
  648. //
  649. // Unload the SAM hive
  650. //
  651. if (bSamHiveLoaded) {
  652. TmpStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
  653. if(!NT_SUCCESS(TmpStatus)) {
  654. KdPrint(("SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TmpStatus));
  655. }
  656. }
  657. //
  658. // unload the security hive
  659. //
  660. if (bSecurityHiveLoaded) {
  661. if (!RcCloseHive(gszSecurityHiveKey))
  662. KdPrint(("SETUP: warning: unable to unload key %ws\n",gszSecurityHiveKey));
  663. }
  664. //
  665. // unload system hive
  666. //
  667. if (bSysHiveLoaded)
  668. RcCloseSystemHive();
  669. //
  670. // free memory
  671. //
  672. if (Hive) {
  673. SpMemFree( Hive );
  674. }
  675. if (HiveKey) {
  676. SpMemFree( HiveKey );
  677. }
  678. if (buffer) {
  679. SpMemFree( buffer );
  680. }
  681. if (PartitionPath) {
  682. SpMemFree( PartitionPath );
  683. }
  684. if (MessageText) {
  685. SpMemFree( MessageText );
  686. }
  687. if (FloppyPath) {
  688. SpMemFree( FloppyPath );
  689. }
  690. return Status;
  691. }
  692. ULONG
  693. RcCmdLogon(
  694. IN PTOKENIZED_LINE TokenizedLine
  695. )
  696. {
  697. #define MAX_FAILURES 3
  698. NTSTATUS Status;
  699. PLIST_ENTRY Next;
  700. PNT_INSTALLATION NtInstall;
  701. PNT_INSTALLATION OldSelectedNtInstall = SelectedInstall;
  702. ULONG InstallNumber;
  703. WCHAR Buffer[128];
  704. WCHAR UserNameBuffer[128];
  705. WCHAR PasswordBuffer[128];
  706. UNICODE_STRING UnicodeString;
  707. ULONG FailureCount = 0;
  708. ULONG u;
  709. BOOLEAN bRegCorrupted = FALSE;
  710. if (RcCmdParseHelp( TokenizedLine, MSG_LOGON_HELP )) {
  711. return 1;
  712. }
  713. //
  714. // Initialize list referring to the depth first search results
  715. // (These will be used via RcCmdBootCfg)
  716. //
  717. RcDestroyList(&NtInstallsFullScan);
  718. InstallCountFullScan = 0;
  719. //
  720. // Do a SHALLOW search for NT installs by default (at cmdcons boot)
  721. //
  722. RcDestroyList(&NtInstalls);
  723. InstallCount = 0;
  724. SpEnumerateDiskRegions( (PSPENUMERATEDISKREGIONS)RcLogonDiskRegionEnum, 0 );
  725. if (InstallCount == 0) {
  726. //
  727. // no nt installations on the machine so let the
  728. // user logon anyway
  729. //
  730. SelectedInstall = NULL;
  731. firstTime = FALSE;
  732. return 1;
  733. }
  734. retry:
  735. RcTextOut( L"\r\n" );
  736. Next = NtInstalls.Flink;
  737. while ((UINT_PTR)Next != (UINT_PTR)&NtInstalls) {
  738. NtInstall = CONTAINING_RECORD( Next, NT_INSTALLATION, ListEntry );
  739. Next = NtInstall->ListEntry.Flink;
  740. swprintf( Buffer, L"%d: %c:\\", NtInstall->InstallNumber, NtInstall->DriveLetter );
  741. wcsncat(Buffer, NtInstall->Path, MAX_APPEND_SIZE(Buffer));
  742. Buffer[MAX_COPY_SIZE(Buffer)] = L'\0';
  743. wcsncat( Buffer, L"\r\n", MAX_APPEND_SIZE(Buffer));
  744. Buffer[MAX_COPY_SIZE(Buffer)] = L'\0';
  745. RcTextOut( Buffer );
  746. }
  747. RcTextOut( L"\r\n" );
  748. if (InBatchMode) {
  749. if (TokenizedLine && TokenizedLine->TokenCount >= 2) {
  750. RtlInitUnicodeString( &UnicodeString, TokenizedLine->Tokens->Next->String );
  751. RtlUnicodeStringToInteger( &UnicodeString, 10, &InstallNumber );
  752. } else {
  753. InstallNumber = 1;
  754. }
  755. if(!IS_VALID_INSTALL(InstallNumber)/* InstallNumber > InstallCount*/){
  756. RcMessageOut( MSG_INSTALL_SELECT_ERROR );
  757. return 1; // will err out
  758. }
  759. } else {
  760. if (TokenizedLine && TokenizedLine->TokenCount == 2) {
  761. // Note : this could have been invoked only by executing a logon command
  762. // at the prompt
  763. RtlInitUnicodeString( &UnicodeString, TokenizedLine->Tokens->Next->String );
  764. Status = RtlUnicodeStringToInteger( &UnicodeString, 10, &InstallNumber );
  765. KdPrint(("SPCMDCON:Loging into %lx (%ws)\n", InstallNumber,
  766. TokenizedLine->Tokens->Next->String));
  767. if (*TokenizedLine->Tokens->Next->String < L'0' ||
  768. *TokenizedLine->Tokens->Next->String > L'9' ||
  769. !NT_SUCCESS(Status) || !IS_VALID_INSTALL(InstallNumber)) {
  770. RcMessageOut( MSG_INSTALL_SELECT_ERROR );
  771. return 1; // just err out for the command
  772. }
  773. } else {
  774. RtlZeroMemory( Buffer, sizeof(Buffer) );
  775. RcMessageOut( MSG_INSTALL_SELECT );
  776. if (!RcLineIn( Buffer, 2 )) {
  777. if( firstTime == TRUE ) {
  778. return 0;
  779. } else {
  780. return 1;
  781. }
  782. }
  783. if (*Buffer < L'0' || *Buffer > L'9') {
  784. RcMessageOut( MSG_INSTALL_SELECT_ERROR );
  785. goto retry;
  786. }
  787. RtlInitUnicodeString( &UnicodeString, Buffer );
  788. Status = RtlUnicodeStringToInteger( &UnicodeString, 10, &InstallNumber );
  789. if(!NT_SUCCESS(Status) || !IS_VALID_INSTALL(InstallNumber)){
  790. RcMessageOut( MSG_INSTALL_SELECT_ERROR );
  791. goto retry;
  792. }
  793. }
  794. }
  795. Next = NtInstalls.Flink;
  796. while ((UINT_PTR)Next != (UINT_PTR)&NtInstalls) {
  797. NtInstall = CONTAINING_RECORD( Next, NT_INSTALLATION, ListEntry );
  798. Next = NtInstall->ListEntry.Flink;
  799. if (NtInstall->InstallNumber == InstallNumber) {
  800. OldSelectedNtInstall = SelectedInstall;
  801. SelectedInstall = NtInstall;
  802. break;
  803. }
  804. }
  805. if (SelectedInstall == NULL) {
  806. if( firstTime == TRUE ) {
  807. return 0;
  808. } else {
  809. RcMessageOut( MSG_INSTALL_SELECT_ERROR );
  810. goto retry;
  811. }
  812. }
  813. //
  814. // Save the NT name of the region we selected to logon.
  815. //
  816. SpNtNameFromRegion( SelectedInstall->Region,
  817. SelectedInstall->NtNameSelectedInstall,
  818. sizeof(SelectedInstall->NtNameSelectedInstall),
  819. PartitionOrdinalCurrent);
  820. //
  821. // Note : check the SYSTEM, SAM, SECURITY hives and if corrupted then
  822. // allow the user to log in without asking for password
  823. // so that he/she may be able correct the problem
  824. //
  825. if (RcIsValidSystemHive()) {
  826. if (RcOpenHive( gszSAMHiveName, gszSAMHiveKey )) {
  827. RcCloseHive( gszSAMHiveKey );
  828. if (!RcOpenHive(gszSecurityHiveName, gszSecurityHiveKey)){
  829. bRegCorrupted = TRUE;
  830. goto success_exit;
  831. }
  832. RcCloseHive(gszSecurityHiveKey);
  833. } else{
  834. bRegCorrupted = TRUE;
  835. goto success_exit;
  836. }
  837. }
  838. else{
  839. bRegCorrupted = TRUE;
  840. goto success_exit;
  841. }
  842. //
  843. // Get the bias information for displaying the file times properly
  844. //
  845. glBias = RcGetTimeZoneBias();
  846. KdPrint(("SPCMDCON: RcGetTimeZoneBias returned : %lx-%lx\n",
  847. glBias.HighPart, glBias.LowPart));
  848. if (InBatchMode) {
  849. if (TokenizedLine && TokenizedLine->TokenCount == 3) {
  850. Status = RcAuthorizePasswordLogon( L"Administrator", TokenizedLine->Tokens->Next->Next->String, NtInstall );
  851. if(NT_SUCCESS(Status)) {
  852. goto success_exit;
  853. }
  854. } else {
  855. Status = RcAuthorizePasswordLogon( L"Administrator", L"", NtInstall );
  856. if(NT_SUCCESS(Status)) {
  857. goto success_exit;
  858. }
  859. }
  860. } else {
  861. // Login only if required
  862. if (!LoginRequired())
  863. goto success_exit;
  864. wcscpy(UserNameBuffer,L"Administrator");
  865. RtlZeroMemory( PasswordBuffer, sizeof(PasswordBuffer) );
  866. while (FailureCount < MAX_FAILURES) {
  867. //
  868. // get the password
  869. //
  870. RcMessageOut( MSG_LOGON_PROMPT_PASSWORD );
  871. RtlZeroMemory( PasswordBuffer, sizeof(PasswordBuffer) );
  872. RcPasswordIn(PasswordBuffer, sizeof(PasswordBuffer)/sizeof(WCHAR));
  873. //
  874. // authorize the logon attempt
  875. //
  876. Status = RcAuthorizePasswordLogon( UserNameBuffer, PasswordBuffer, NtInstall );
  877. RtlSecureZeroMemory(PasswordBuffer, sizeof(PasswordBuffer));
  878. if(NT_SUCCESS(Status)) {
  879. goto success_exit;
  880. }
  881. RcMessageOut( MSG_LOGON_FAILURE );
  882. FailureCount += 1;
  883. }
  884. }
  885. RcMessageOut( MSG_LOGON_FAILUE_BAD );
  886. RcMessageOut( MSG_REBOOT_NOW );
  887. RcTextOut(L"\r\n");
  888. //
  889. // wait for the use to press ENTER
  890. //
  891. while (SpInputGetKeypress() != ASCI_CR);
  892. return 0;
  893. success_exit:
  894. //
  895. // Enable the set command if specified and not already
  896. // enabled (would be enabled if registries are corrupted)
  897. //
  898. if (bRegCorrupted) {
  899. //AllowAllPaths = TRUE;
  900. //RcSetSETCommandStatus(TRUE);
  901. } else {
  902. RcSetSETCommandStatus(IsSetCommandEnabled());
  903. }
  904. //
  905. // set the current drive to the selected install.
  906. //
  907. _CurDrive = SelectedInstall->DriveLetter;
  908. //
  909. // set the current dir to the correct one.
  910. //
  911. RtlZeroMemory( Buffer, sizeof(Buffer) );
  912. wcscat( Buffer, L"\\" );
  913. wcsncat(Buffer,
  914. SelectedInstall->Path,
  915. MAX_APPEND_SIZE(Buffer));
  916. Buffer[MAX_COPY_SIZE(Buffer)] = L'\0';
  917. wcscat( Buffer, L"\\" );
  918. u = RcToUpper(SelectedInstall->DriveLetter) - L'A';
  919. if(_CurDirs[u]) {
  920. SpMemFree(_CurDirs[u]);
  921. }
  922. _CurDirs[u] = SpDupStringW( Buffer );
  923. firstTime = FALSE;
  924. RcPurgeHistoryBuffer();
  925. return 1;
  926. }
  927. /*++
  928. Routine Description:
  929. Checks the "SecurityLevel" value under
  930. HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Setup\RecoveryConsole to see
  931. if login is needed or not
  932. Arguments:
  933. None
  934. Return Value:
  935. TRUE if Login is required or FALSE otherwise
  936. --*/
  937. BOOLEAN
  938. LoginRequired(
  939. VOID
  940. )
  941. {
  942. BOOLEAN bLogin = TRUE;
  943. PWSTR szValueName = L"SecurityLevel";
  944. HANDLE hKey = NULL;
  945. UNICODE_STRING unicodeStr;
  946. NTSTATUS status;
  947. BYTE buffer[ sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  948. MAX_PATH * sizeof(WCHAR) ];
  949. ULONG ulResultLen = 0;
  950. PKEY_VALUE_PARTIAL_INFORMATION pKeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
  951. OBJECT_ATTRIBUTES stObjAttr;
  952. PWSTR szWinLogonKey =
  953. L"\\registry\\machine\\xSOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Setup\\RecoveryConsole";
  954. RtlZeroMemory(buffer, sizeof(buffer));
  955. //
  956. // Load the SOFTWARE hive
  957. //
  958. if (RcOpenHive( gszSoftwareHiveName, gszSoftwareHiveKey )) {
  959. //
  960. // Open the key
  961. //
  962. INIT_OBJA( &stObjAttr, &unicodeStr, szWinLogonKey );
  963. status = ZwOpenKey( &hKey, KEY_ALL_ACCESS, &stObjAttr );
  964. if (NT_SUCCESS(status)) {
  965. RtlInitUnicodeString( &unicodeStr, szValueName );
  966. //
  967. // read the value
  968. //
  969. status = ZwQueryValueKey( hKey,
  970. &unicodeStr,
  971. KeyValuePartialInformation,
  972. pKeyValueInfo,
  973. sizeof(buffer),
  974. &ulResultLen );
  975. if (NT_SUCCESS(status) && (pKeyValueInfo->Type == REG_DWORD)) {
  976. bLogin = !(*((PDWORD)(pKeyValueInfo->Data)) == 1);
  977. }
  978. }
  979. if (hKey)
  980. ZwClose(hKey);
  981. // close the hive
  982. RcCloseHive( gszSoftwareHiveKey );
  983. }
  984. return bLogin;
  985. }
  986. /*++
  987. Routine Description:
  988. Checks the "SetCommand" value under
  989. HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Setup\RecoveryConsole to see
  990. if SET command needs to be enabled or disabled
  991. Arguments:
  992. None
  993. Return Value:
  994. TRUE if Login is required or FALSE otherwise
  995. --*/
  996. BOOLEAN
  997. IsSetCommandEnabled(
  998. VOID
  999. )
  1000. {
  1001. BOOLEAN bSetEnabled = FALSE;
  1002. PWSTR szValueName = L"SetCommand";
  1003. HANDLE hKey = NULL;
  1004. UNICODE_STRING unicodeStr;
  1005. NTSTATUS status;
  1006. BYTE buffer[ sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  1007. MAX_PATH * sizeof(WCHAR) ];
  1008. ULONG ulResultLen = 0;
  1009. PKEY_VALUE_PARTIAL_INFORMATION pKeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
  1010. OBJECT_ATTRIBUTES stObjAttr;
  1011. PWSTR szWinLogonKey =
  1012. L"\\registry\\machine\\xSOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Setup\\RecoveryConsole";
  1013. RtlZeroMemory(buffer, sizeof(buffer));
  1014. //
  1015. // Load the SOFTWARE hive
  1016. //
  1017. if (RcOpenHive( gszSoftwareHiveName, gszSoftwareHiveKey )) {
  1018. //
  1019. // Open the key
  1020. //
  1021. INIT_OBJA( &stObjAttr, &unicodeStr, szWinLogonKey );
  1022. status = ZwOpenKey( &hKey, KEY_ALL_ACCESS, &stObjAttr );
  1023. if (NT_SUCCESS(status)) {
  1024. RtlInitUnicodeString( &unicodeStr, szValueName );
  1025. //
  1026. // read the value
  1027. //
  1028. status = ZwQueryValueKey( hKey,
  1029. &unicodeStr,
  1030. KeyValuePartialInformation,
  1031. pKeyValueInfo,
  1032. sizeof(buffer),
  1033. &ulResultLen );
  1034. if (NT_SUCCESS(status) && (pKeyValueInfo->Type == REG_DWORD)) {
  1035. bSetEnabled = (*((PDWORD)(pKeyValueInfo->Data)) == 1);
  1036. }
  1037. }
  1038. if (hKey)
  1039. ZwClose(hKey);
  1040. // close the hive
  1041. RcCloseHive( gszSoftwareHiveKey );
  1042. }
  1043. return bSetEnabled;
  1044. }
  1045. LARGE_INTEGER
  1046. RcGetTimeZoneBias(
  1047. VOID
  1048. )
  1049. /*++
  1050. Routine Description:
  1051. Reads the bias information from
  1052. "\\HKLM\\System\\CurrentControlSet\\Control\\TimeZoneInformation"
  1053. key's "Bias" value. We use our own conversion routine because
  1054. RtlSetTimeZoneInformation() updates the system time (which we
  1055. don't want to change).
  1056. Arguments:
  1057. none
  1058. Return Value:
  1059. 0 if error, otherwise value stored in the registry
  1060. for the key (could be zero).
  1061. --*/
  1062. {
  1063. LARGE_INTEGER lBias;
  1064. OBJECT_ATTRIBUTES stObjAttr;
  1065. HANDLE hKey = NULL;
  1066. NTSTATUS status;
  1067. UNICODE_STRING unicodeStr;
  1068. unsigned uIndex;
  1069. ULONG uControl = -1;
  1070. WCHAR szKeyName[MAX_PATH];
  1071. BYTE dataBuff[MAX_PATH +
  1072. sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
  1073. KEY_VALUE_PARTIAL_INFORMATION *pKeyData =
  1074. (KEY_VALUE_PARTIAL_INFORMATION*)dataBuff;
  1075. ULONG ulResultLen = 0;
  1076. UNICODE_STRING szValueName;
  1077. DWORD dwDaylightBias = 0;
  1078. DWORD dwStandardBias = 0;
  1079. BOOLEAN bSysHiveOpened;
  1080. lBias.QuadPart = 0;
  1081. //
  1082. // open the system hive & determine correct control set to use
  1083. //
  1084. bSysHiveOpened = RcOpenHive(gszSystemHiveName, gszSystemHiveKey);
  1085. if (bSysHiveOpened && RcDetermineCorrectControlKey(&uControl)) {
  1086. //
  1087. // open the key and read the
  1088. //
  1089. RtlZeroMemory(pKeyData, sizeof(dataBuff));
  1090. swprintf(szKeyName,
  1091. L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Control\\TimeZoneInformation",
  1092. uControl);
  1093. INIT_OBJA(&stObjAttr, &unicodeStr, szKeyName);
  1094. RtlInitUnicodeString(&szValueName, L"Bias");
  1095. status = ZwOpenKey(&hKey, KEY_READ, &stObjAttr);
  1096. if (!NT_SUCCESS(status)) {
  1097. KdPrint(("SPCMDCON: RcGetTimeZoneBias - Couldnot open hive key: %ws(%lx)\n",
  1098. szKeyName, status));
  1099. } else {
  1100. //
  1101. // Query the "Bias" value under the key
  1102. //
  1103. status = ZwQueryValueKey( hKey,
  1104. &szValueName,
  1105. KeyValuePartialInformation,
  1106. pKeyData,
  1107. sizeof(dataBuff),
  1108. &ulResultLen );
  1109. if (NT_SUCCESS(status) && (pKeyData->Type == REG_DWORD)) {
  1110. lBias.QuadPart = Int32x32To64(*(DWORD*)(pKeyData->Data) * 60,
  1111. 10000000);
  1112. RtlZeroMemory(pKeyData, sizeof(dataBuff));
  1113. RtlInitUnicodeString(&szValueName, L"DaylightBias");
  1114. //
  1115. // Query the "DaylightBias" value under the key
  1116. //
  1117. status = ZwQueryValueKey( hKey,
  1118. &szValueName,
  1119. KeyValuePartialInformation,
  1120. pKeyData,
  1121. sizeof(dataBuff),
  1122. &ulResultLen );
  1123. if (NT_SUCCESS(status) && (pKeyData->Type == REG_DWORD)) {
  1124. dwDaylightBias = *(DWORD*)(pKeyData->Data);
  1125. if (dwDaylightBias == 0 ) {
  1126. //
  1127. // there could be a standard bias
  1128. //
  1129. RtlZeroMemory(pKeyData, sizeof(dataBuff));
  1130. RtlInitUnicodeString(&szValueName, L"StandardBias");
  1131. //
  1132. // Query the "StandardBias" value under the key
  1133. //
  1134. status = ZwQueryValueKey( hKey,
  1135. &szValueName,
  1136. KeyValuePartialInformation,
  1137. pKeyData,
  1138. sizeof(dataBuff),
  1139. &ulResultLen );
  1140. if (NT_SUCCESS(status) &&
  1141. (pKeyData->Type == REG_DWORD)) {
  1142. dwStandardBias = *(DWORD*)(pKeyData->Data);
  1143. }
  1144. }
  1145. lBias.QuadPart += Int32x32To64((dwDaylightBias + dwStandardBias) * 60,
  1146. 10000000);
  1147. } else {
  1148. lBias.QuadPart = 0; //
  1149. }
  1150. }
  1151. if (!NT_SUCCESS(status))
  1152. KdPrint(("SPCMDCON: RcGetTimeZoneBias Error:(%lx)", status));
  1153. }
  1154. if (hKey)
  1155. ZwClose(hKey);
  1156. }
  1157. if (bSysHiveOpened)
  1158. RcCloseHive(gszSystemHiveKey);
  1159. return lBias;
  1160. }
  1161. BOOLEAN
  1162. RcIsValidSystemHive(
  1163. VOID
  1164. )
  1165. /*++
  1166. Routine Description:
  1167. Verifies whether the system hive of the selected NT install
  1168. is fine. Checks for the presence of "Control\Lsa" and
  1169. "Control\SessionManager" currently under ControlSet.
  1170. Arguments:
  1171. none
  1172. Return Value:
  1173. TRUE - indicates system hive is fine
  1174. FALSE - indicates system hive is corrupted
  1175. --*/
  1176. {
  1177. BOOLEAN bResult = FALSE;
  1178. OBJECT_ATTRIBUTES stObjAttr;
  1179. HANDLE hKey = NULL;
  1180. NTSTATUS status;
  1181. UNICODE_STRING unicodeStr;
  1182. unsigned uIndex;
  1183. ULONG uControl = -1;
  1184. WCHAR szKeyName[MAX_PATH];
  1185. BOOLEAN bSysHiveOpened;
  1186. KEY_CHECK_STRUCT aKeysToCheck[] = {
  1187. { L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Control\\Lsa", TRUE },
  1188. { L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Control\\Session Manager", TRUE } };
  1189. //
  1190. // open the system hive & determine correct control set to use
  1191. //
  1192. bSysHiveOpened = RcOpenHive(gszSystemHiveName, gszSystemHiveKey);
  1193. if ( bSysHiveOpened && RcDetermineCorrectControlKey(&uControl)) {
  1194. bResult = TRUE;
  1195. //
  1196. // open each of the key and then close it to verify its presence
  1197. //
  1198. for (uIndex = 0;
  1199. uIndex < (sizeof(aKeysToCheck) / sizeof(KEY_CHECK_STRUCT));
  1200. uIndex++) {
  1201. if (aKeysToCheck[uIndex].bControlSet)
  1202. swprintf(szKeyName, aKeysToCheck[uIndex].szKeyName, uControl);
  1203. else
  1204. wcscpy(szKeyName, aKeysToCheck[uIndex].szKeyName);
  1205. INIT_OBJA(&stObjAttr, &unicodeStr, szKeyName);
  1206. status = ZwOpenKey(&hKey, KEY_READ, &stObjAttr);
  1207. if (!NT_SUCCESS(status)) {
  1208. KdPrint(("SPCMDCON: RcIsValidSystemHive - Couldnot open hive key: %ws(%lx)\n",
  1209. szKeyName, status));
  1210. bResult = FALSE;
  1211. break;
  1212. }
  1213. if (hKey)
  1214. ZwClose(hKey);
  1215. }
  1216. }
  1217. if (bSysHiveOpened)
  1218. RcCloseHive(gszSystemHiveKey);
  1219. return bResult;
  1220. }
  1221. BOOLEAN
  1222. RcOpenHive(
  1223. PWSTR szHiveName,
  1224. PWSTR szHiveKey
  1225. )
  1226. /*++
  1227. Routine Description:
  1228. Opens the requested hive of the selected NT install.
  1229. Arguments:
  1230. szHiveName - hive file name (just file name alone)
  1231. szHiveKey - the key into which the hive needs to be loaded
  1232. Return Value:
  1233. TRUE - indicates sucess
  1234. FALSE - indicates failure
  1235. --*/
  1236. {
  1237. PWSTR Hive = NULL;
  1238. PWSTR HiveKey = NULL;
  1239. PUCHAR buffer = NULL;
  1240. PWSTR PartitionPath = NULL;
  1241. NTSTATUS Status;
  1242. BOOLEAN bResult = FALSE;
  1243. if ((SelectedInstall == NULL) || (szHiveName == NULL) || (szHiveKey == NULL)) {
  1244. return FALSE;
  1245. }
  1246. //
  1247. // Allocate buffers.
  1248. //
  1249. Hive = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  1250. HiveKey = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  1251. buffer = SpMemAlloc(BUFFERSIZE);
  1252. //
  1253. // Get the name of the target patition.
  1254. //
  1255. SpNtNameFromRegion(
  1256. SelectedInstall->Region, // SelectedInstall is a global defined in cmdcons.h
  1257. _CmdConsBlock->TemporaryBuffer,
  1258. _CmdConsBlock->TemporaryBufferSize,
  1259. PartitionOrdinalCurrent
  1260. );
  1261. PartitionPath = SpDupStringW(_CmdConsBlock->TemporaryBuffer);
  1262. //
  1263. // Load the hive
  1264. //
  1265. wcscpy(Hive,PartitionPath);
  1266. SpConcatenatePaths(Hive,SelectedInstall->Path);
  1267. SpConcatenatePaths(Hive,L"system32\\config");
  1268. SpConcatenatePaths(Hive,szHiveName);
  1269. //
  1270. // Form the path of the key into which we will
  1271. // load the hive. We'll use the convention that
  1272. // a hive will be loaded into \registry\machine\x<hivename>.
  1273. //
  1274. wcscpy(HiveKey, szHiveKey);
  1275. //
  1276. // Attempt to load the key.
  1277. //
  1278. Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
  1279. if (NT_SUCCESS(Status))
  1280. bResult = TRUE;
  1281. else
  1282. DEBUG_PRINTF(("CMDCONS: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
  1283. if (Hive != NULL)
  1284. SpMemFree( Hive );
  1285. if (HiveKey != NULL)
  1286. SpMemFree( HiveKey );
  1287. if (buffer != NULL)
  1288. SpMemFree( buffer );
  1289. return bResult;
  1290. }
  1291. BOOLEAN
  1292. RcCloseHive(
  1293. PWSTR szHiveKey
  1294. )
  1295. /*++
  1296. Routine Description:
  1297. Closes the specified hive of the selected NT install.
  1298. Arguments:
  1299. szHiveKey - specifies the key of the hive to be unloaded
  1300. Return Value:
  1301. TRUE - indicates sucess
  1302. FALSE - indicates failure
  1303. --*/
  1304. {
  1305. NTSTATUS TmpStatus;
  1306. BOOLEAN bResult = FALSE;
  1307. if (szHiveKey != NULL) {
  1308. //
  1309. // Unload the hive
  1310. //
  1311. TmpStatus = SpLoadUnloadKey( NULL, NULL, szHiveKey, NULL );
  1312. if (NT_SUCCESS(TmpStatus)) {
  1313. bResult = TRUE;
  1314. } else {
  1315. KdPrint(("CMDCONS: warning: unable to unload key %ws (%lx)\n", szHiveKey, TmpStatus));
  1316. }
  1317. }
  1318. return bResult;
  1319. }