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.

3113 lines
88 KiB

  1. /*++
  2. Copyright (c) 1989-1998 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. Main source file of the NTOS system initialization subcomponent.
  7. Author:
  8. Steve Wood (stevewo) 31-Mar-1989
  9. Revision History:
  10. --*/
  11. #include "ntos.h"
  12. #include "ntimage.h"
  13. #include <zwapi.h>
  14. #include <ntdddisk.h>
  15. #include <kddll.h>
  16. #include <setupblk.h>
  17. #include <fsrtl.h>
  18. #include <ntverp.h>
  19. #include "stdlib.h"
  20. #include "stdio.h"
  21. #include <string.h>
  22. #include <safeboot.h>
  23. #include <inbv.h>
  24. #include <hdlsblk.h>
  25. #include <hdlsterm.h>
  26. #include "anim.h"
  27. #include "xip.h"
  28. UNICODE_STRING NtSystemRoot;
  29. PVOID ExPageLockHandle;
  30. VOID
  31. ExpInitializeExecutive(
  32. IN ULONG Number,
  33. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  34. );
  35. NTKERNELAPI
  36. BOOLEAN
  37. ExpRefreshTimeZoneInformation(
  38. IN PLARGE_INTEGER CurrentUniversalTime
  39. );
  40. NTSTATUS
  41. CreateSystemRootLink(
  42. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  43. );
  44. static USHORT
  45. NameToOrdinal (
  46. IN PSZ NameOfEntryPoint,
  47. IN ULONG_PTR DllBase,
  48. IN ULONG NumberOfNames,
  49. IN PULONG NameTableBase,
  50. IN PUSHORT NameOrdinalTableBase
  51. );
  52. NTSTATUS
  53. LookupEntryPoint (
  54. IN PVOID DllBase,
  55. IN PSZ NameOfEntryPoint,
  56. OUT PVOID *AddressOfEntryPoint
  57. );
  58. #if defined(_X86_)
  59. VOID
  60. KiLogMcaErrors (
  61. VOID
  62. );
  63. #endif
  64. PFN_COUNT
  65. ExBurnMemory(
  66. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  67. IN PFN_COUNT NumberOfPagesToBurn,
  68. IN TYPE_OF_MEMORY MemoryTypeForRemovedPages,
  69. IN PMEMORY_ALLOCATION_DESCRIPTOR NewMemoryDescriptor OPTIONAL
  70. );
  71. VOID
  72. DisplayFilter(
  73. PUCHAR *String
  74. );
  75. #ifdef ALLOC_PRAGMA
  76. //
  77. // The INIT section is not pageable during initialization, so these
  78. // functions can be in INIT rather than in .text.
  79. //
  80. #pragma alloc_text(INIT,ExBurnMemory)
  81. #pragma alloc_text(INIT,ExpInitializeExecutive)
  82. #pragma alloc_text(INIT,Phase1Initialization)
  83. #pragma alloc_text(INIT,CreateSystemRootLink)
  84. #pragma alloc_text(INIT,LookupEntryPoint)
  85. #pragma alloc_text(INIT,NameToOrdinal)
  86. #endif
  87. //
  88. // Define global static data used during initialization.
  89. //
  90. ULONG NtGlobalFlag;
  91. extern PMESSAGE_RESOURCE_BLOCK KiBugCheckMessages;
  92. extern UCHAR CmProcessorMismatch;
  93. ULONG NtMajorVersion;
  94. ULONG NtMinorVersion;
  95. #if DBG
  96. ULONG NtBuildNumber = VER_PRODUCTBUILD | 0xC0000000;
  97. #else
  98. ULONG NtBuildNumber = VER_PRODUCTBUILD | 0xF0000000;
  99. #endif
  100. #if defined(__BUILDMACHINE__)
  101. #if defined(__BUILDDATE__)
  102. #define B2(w,x,y) "" #w "." #x "." #y
  103. #define B1(w,x,y) B2(w, x, y)
  104. #define BUILD_MACHINE_TAG B1(VER_PRODUCTBUILD, __BUILDMACHINE__, __BUILDDATE__)
  105. #else
  106. #define B2(w,x) "" #w "." #x
  107. #define B1(w,x) B2(w,x)
  108. #define BUILD_MACHINE_TAG B1(VER_PRODUCTBUILD, __BUILDMACHINE__)
  109. #endif
  110. #else
  111. #define BUILD_MACHINE_TAG ""
  112. #endif
  113. const CHAR NtBuildLab[] = BUILD_MACHINE_TAG;
  114. ULONG InitializationPhase;
  115. extern BOOLEAN ShowProgressBar;
  116. extern KiServiceLimit;
  117. extern PMESSAGE_RESOURCE_DATA KiBugCodeMessages;
  118. extern ULONG KdpTimeSlipPending;
  119. extern BOOLEAN KdBreakAfterSymbolLoad;
  120. extern CM_SYSTEM_CONTROL_VECTOR CmControlVector[];
  121. ULONG CmNtCSDVersion;
  122. ULONG CmNtCSDReleaseType;
  123. #define SP_RELEASE_TYPE_NONE 0 // No SP string appendage
  124. #define SP_RELEASE_TYPE_INTERNAL 1 // Uses VER_PRODUCTBUILD_QFE in ntverp.h for build value
  125. #define SP_RELEASE_TYPE_RC 2 // Uses VER_PRODUCTRCVERSION in ntverp.h for RC x.x value
  126. #define SP_RELEASE_TYPE_BETA 3 // Uses VER_PRODUCTBETAVERSION in ntverp.h for B' x.x value
  127. ULONG CmBrand;
  128. UNICODE_STRING CmVersionString;
  129. UNICODE_STRING CmCSDVersionString;
  130. ULONG InitSafeBootMode;
  131. BOOLEAN InitIsWinPEMode = FALSE;
  132. ULONG InitWinPEModeType = INIT_WINPEMODE_NONE;
  133. WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe";
  134. ULONG NtInitialUserProcessBufferLength =
  135. sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR);
  136. ULONG NtInitialUserProcessBufferType = REG_SZ;
  137. #if defined(_X86_)
  138. extern ULONG KeNumprocSpecified;
  139. #endif
  140. typedef struct _EXLOCK {
  141. KSPIN_LOCK SpinLock;
  142. KIRQL Irql;
  143. } EXLOCK, *PEXLOCK;
  144. #ifdef ALLOC_PRAGMA
  145. NTSTATUS
  146. ExpInitializeLockRoutine(
  147. PEXLOCK Lock
  148. );
  149. #pragma alloc_text(INIT,ExpInitializeLockRoutine)
  150. #endif
  151. BOOLEAN
  152. ExpOkayToLockRoutine(
  153. IN PEXLOCK Lock
  154. )
  155. {
  156. return TRUE;
  157. }
  158. NTSTATUS
  159. ExpInitializeLockRoutine(
  160. PEXLOCK Lock
  161. )
  162. {
  163. KeInitializeSpinLock(&Lock->SpinLock);
  164. return STATUS_SUCCESS;
  165. }
  166. NTSTATUS
  167. ExpAcquireLockRoutine(
  168. PEXLOCK Lock
  169. )
  170. {
  171. ExAcquireSpinLock(&Lock->SpinLock,&Lock->Irql);
  172. return STATUS_SUCCESS;
  173. }
  174. NTSTATUS
  175. ExpReleaseLockRoutine(
  176. PEXLOCK Lock
  177. )
  178. {
  179. ExReleaseSpinLock(&Lock->SpinLock,Lock->Irql);
  180. return STATUS_SUCCESS;
  181. }
  182. #if 0
  183. NTSTATUS
  184. ExpDeleteLockRoutine(
  185. PEXLOCK Lock
  186. )
  187. {
  188. return STATUS_SUCCESS;
  189. }
  190. #endif //0
  191. #ifdef ALLOC_DATA_PRAGMA
  192. #pragma data_seg("INITDATA")
  193. #endif
  194. ULONG CmNtGlobalFlag = 0;
  195. NLSTABLEINFO InitTableInfo;
  196. ULONG InitNlsTableSize;
  197. PVOID InitNlsTableBase;
  198. PFN_COUNT BBTPagesToReserve;
  199. #ifdef ALLOC_DATA_PRAGMA
  200. #pragma data_seg("PAGEDATA")
  201. #endif
  202. PVOID InitNlsSectionPointer = NULL;
  203. ULONG InitAnsiCodePageDataOffset = 0;
  204. ULONG InitOemCodePageDataOffset = 0;
  205. ULONG InitUnicodeCaseTableDataOffset = 0;
  206. #ifdef ALLOC_DATA_PRAGMA
  207. #pragma data_seg()
  208. #endif
  209. PVOID BBTBuffer;
  210. MEMORY_ALLOCATION_DESCRIPTOR BBTMemoryDescriptor;
  211. #define COLOR_BLACK 0
  212. #define COLOR_BLUE 2
  213. #define COLOR_DARKGRAY 4
  214. #define COLOR_GRAY 9
  215. #define COLOR_WHITE 15
  216. extern BOOLEAN InbvBootDriverInstalled;
  217. VOID
  218. DisplayBootBitmap (
  219. IN BOOLEAN DisplayOnScreen
  220. )
  221. /*++
  222. Routine Description:
  223. Draws the gui boot screen.
  224. Arguments:
  225. DisplayOnScreen - TRUE to dump text to the screen, FALSE otherwise.
  226. Return Value:
  227. None.
  228. Environment:
  229. This routine may be called more than once, and should not be marked INIT.
  230. --*/
  231. {
  232. LARGE_INTEGER DueTime;
  233. static BOOLEAN FirstCall = TRUE;
  234. ROT_BAR_TYPE TempRotBarSelection = RB_UNSPECIFIED;
  235. if (FirstCall == FALSE) {
  236. //
  237. // Disable current animation
  238. //
  239. InbvAcquireLock();
  240. RotBarSelection = RB_UNSPECIFIED;
  241. InbvReleaseLock();
  242. }
  243. ShowProgressBar = FALSE;
  244. if (DisplayOnScreen) {
  245. PUCHAR BitmapTop, BitmapBottom;
  246. if (SharedUserData->NtProductType == NtProductWinNt) {
  247. InbvSetTextColor(COLOR_WHITE);
  248. InbvSolidColorFill(0, 0, 639, 479, 7); // background
  249. InbvSolidColorFill(0, 421, 639, 479, 1); // bottom
  250. BitmapTop = InbvGetResourceAddress(6);
  251. BitmapBottom = InbvGetResourceAddress(7);
  252. } else { // srv
  253. InbvSetTextColor(14);
  254. InbvSolidColorFill(0, 0, 639, 479, 6); // background
  255. InbvSolidColorFill(0, 421, 639, 479, 1); // bottom
  256. BitmapTop = InbvGetResourceAddress(14);
  257. BitmapBottom = InbvGetResourceAddress(15);
  258. }
  259. TempRotBarSelection = RB_UNSPECIFIED;
  260. InbvSetScrollRegion(32, 80, 631, 400);
  261. if (BitmapTop && BitmapBottom) {
  262. InbvBitBlt(BitmapBottom, 0, 419);
  263. InbvBitBlt(BitmapTop, 0, 0);
  264. }
  265. } else {
  266. PUCHAR BarBitmap = NULL;
  267. PUCHAR TextBitmap = NULL;
  268. PUCHAR Bitmap = NULL;
  269. InbvInstallDisplayStringFilter(DisplayFilter);
  270. if (!InbvBootDriverInstalled) {
  271. return;
  272. }
  273. Bitmap = InbvGetResourceAddress(1); // workstation bitmap
  274. if (ExVerifySuite(EmbeddedNT)) { // embd and pro have the same bar, but different text
  275. TextBitmap = InbvGetResourceAddress(12); // embedded edition title text
  276. BarBitmap = InbvGetResourceAddress(8); // pro and embedded editions progress bar
  277. }
  278. else if (SharedUserData->NtProductType == NtProductWinNt) { // home or pro
  279. if (ExVerifySuite(Personal)) { // home
  280. BarBitmap = InbvGetResourceAddress(9); // home edition progress bar
  281. TextBitmap = InbvGetResourceAddress(11); // home edition title text
  282. }
  283. else { // pro
  284. BarBitmap = InbvGetResourceAddress(8); // pro and embedded editions progress bar
  285. switch (CmBrand) {
  286. case 1: // TabletPc
  287. TextBitmap = InbvGetResourceAddress(17);
  288. break;
  289. case 2: // eHome Freestyle
  290. TextBitmap = InbvGetResourceAddress(18);
  291. break;
  292. default: // Professional title text
  293. TextBitmap = InbvGetResourceAddress(10);
  294. }
  295. }
  296. }
  297. else { // srv
  298. BarBitmap = InbvGetResourceAddress(4); // srv edition progress bar
  299. TextBitmap = InbvGetResourceAddress(13); // srv edition title text
  300. }
  301. if (Bitmap) {
  302. TempRotBarSelection = RB_SQUARE_CELLS;
  303. }
  304. //
  305. // Set positions for scrolling bar.
  306. //
  307. if (Bitmap) {
  308. InbvBitBlt(Bitmap, 0, 0);
  309. //if (SharedUserData->NtProductType == NtProductServer) {
  310. if (SharedUserData->NtProductType != NtProductWinNt) {
  311. // make some fixes for server bitmap: remove "XP"
  312. UCHAR sav_copyright[64];
  313. InbvScreenToBufferBlt(sav_copyright, 413, 237, 7, 7, 8);
  314. InbvSolidColorFill(418,230,454,256,0);
  315. InbvBufferToScreenBlt(sav_copyright, 413, 237, 7, 7, 8);
  316. // HACK: in case of "text mode setup" (ExpInTextModeSetup == TRUE)
  317. // we can't determine the SKU so we displaying neutral butmap
  318. // without specific SKU title (e.g. just Windows) and server's progress bar
  319. {
  320. extern BOOLEAN ExpInTextModeSetup; // defined at base\ntos\ex\exinit.c
  321. if (ExpInTextModeSetup) {
  322. TextBitmap = NULL;
  323. }
  324. else {
  325. PUCHAR DotBitmap = InbvGetResourceAddress(16); // srv edition progress bar
  326. InbvBitBlt(DotBitmap, 423, 233);
  327. }
  328. }
  329. }
  330. }
  331. if (TextBitmap) {
  332. InbvBitBlt(TextBitmap, 220, 272);
  333. }
  334. if (BarBitmap) {
  335. InbvBitBlt(BarBitmap, 0, 0);
  336. }
  337. }
  338. InbvAcquireLock();
  339. RotBarSelection = TempRotBarSelection;
  340. InbvRotBarInit();
  341. InbvReleaseLock();
  342. if (FirstCall) {
  343. //
  344. // If we got here, we are showing the boot bitmap.
  345. // Start a timer to support animation.
  346. //
  347. HANDLE ThreadHandle;
  348. PsCreateSystemThread(&ThreadHandle,
  349. 0L,
  350. NULL,
  351. NULL,
  352. NULL,
  353. InbvRotateGuiBootDisplay,
  354. NULL);
  355. }
  356. FirstCall = FALSE;
  357. }
  358. VOID
  359. DisplayFilter(
  360. IN OUT PUCHAR *String
  361. )
  362. /*++
  363. Routine Description:
  364. This routine monitors InbvDisplayString output. If it sees something
  365. which needs to be displayed on the screen, it triggers the output screen.
  366. Arguments:
  367. String - Pointer to a string pointer.
  368. Returns:
  369. None.
  370. Notes:
  371. This routine will be called anytime a string is displayed via the
  372. Inbv routines. It cannot be paged!
  373. --*/
  374. {
  375. static const UCHAR EmptyString = 0;
  376. static BOOLEAN NonDotHit = FALSE;
  377. if ((NonDotHit == FALSE) && (strcmp(*String, ".") == 0)) {
  378. *String = (PUCHAR)&EmptyString;
  379. } else {
  380. NonDotHit = TRUE;
  381. InbvInstallDisplayStringFilter((INBV_DISPLAY_STRING_FILTER)NULL);
  382. DisplayBootBitmap(TRUE);
  383. }
  384. }
  385. PFN_COUNT
  386. ExBurnMemory (
  387. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  388. IN PFN_COUNT NumberOfPagesToBurn,
  389. IN TYPE_OF_MEMORY MemoryTypeForRemovedPages,
  390. IN PMEMORY_ALLOCATION_DESCRIPTOR NewMemoryDescriptor OPTIONAL
  391. )
  392. /*++
  393. Routine Description:
  394. This routine removes memory from the system loader block thus simulating
  395. a machine with less physical memory without having to physically remove it.
  396. Arguments:
  397. LoaderBlock - Supplies a pointer to the loader parameter block.
  398. NumberOfPagesToBurn - Supplies the number of pages to burn.
  399. MemoryTypeForRemovedPages - Supplies the type to mark into the loader block
  400. for the burned pages.
  401. NewMemoryDescriptor - If non-NULL, this supplies a pointer to a memory
  402. block to be used if a split is needed.
  403. Return Value:
  404. Number of pages actually burned.
  405. Environment:
  406. Kernel mode.
  407. --*/
  408. {
  409. PLIST_ENTRY ListHead;
  410. PLIST_ENTRY NextEntry;
  411. PFN_COUNT PagesRemaining;
  412. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  413. PagesRemaining = NumberOfPagesToBurn;
  414. //
  415. // Look backwards through physical memory to leave it like
  416. // it otherwise would be. ie: that's the way most people add memory
  417. // modules to their systems.
  418. //
  419. ListHead = &LoaderBlock->MemoryDescriptorListHead;
  420. NextEntry = ListHead->Blink;
  421. do {
  422. MemoryDescriptor = CONTAINING_RECORD(NextEntry,
  423. MEMORY_ALLOCATION_DESCRIPTOR,
  424. ListEntry);
  425. if ((MemoryDescriptor->MemoryType == LoaderFree ||
  426. MemoryDescriptor->MemoryType == LoaderFirmwareTemporary) &&
  427. MemoryDescriptor->PageCount != 0) {
  428. if (MemoryDescriptor->PageCount > PagesRemaining) {
  429. //
  430. // This block has enough pages.
  431. // Split it into two and mark it as requested.
  432. //
  433. MemoryDescriptor->PageCount = MemoryDescriptor->PageCount -
  434. PagesRemaining;
  435. if (ARGUMENT_PRESENT (NewMemoryDescriptor)) {
  436. NewMemoryDescriptor->BasePage = MemoryDescriptor->BasePage +
  437. MemoryDescriptor->PageCount;
  438. NewMemoryDescriptor->PageCount = PagesRemaining;
  439. NewMemoryDescriptor->MemoryType = MemoryTypeForRemovedPages;
  440. InsertTailList (MemoryDescriptor->ListEntry.Blink,
  441. &NewMemoryDescriptor->ListEntry);
  442. }
  443. PagesRemaining = 0;
  444. break;
  445. }
  446. PagesRemaining -= MemoryDescriptor->PageCount;
  447. MemoryDescriptor->MemoryType = MemoryTypeForRemovedPages;
  448. }
  449. NextEntry = NextEntry->Blink;
  450. } while (NextEntry != ListHead);
  451. return NumberOfPagesToBurn - PagesRemaining;
  452. }
  453. extern BOOLEAN ExpInTextModeSetup;
  454. VOID
  455. ExpInitializeExecutive(
  456. IN ULONG Number,
  457. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  458. )
  459. /*++
  460. Routine Description:
  461. This routine is called from the kernel initialization routine during
  462. bootstrap to initialize the executive and all of its subcomponents.
  463. Each subcomponent is potentially called twice to perform Phase 0, and
  464. then Phase 1 initialization. During Phase 0 initialization, the only
  465. activity that may be performed is the initialization of subcomponent
  466. specific data. Phase 0 initialization is performed in the context of
  467. the kernel start up routine with interrupts disabled. During Phase 1
  468. initialization, the system is fully operational and subcomponents may
  469. do any initialization that is necessary.
  470. Arguments:
  471. Number - Supplies the processor number currently initializing.
  472. LoaderBlock - Supplies a pointer to a loader parameter block.
  473. Return Value:
  474. None.
  475. --*/
  476. {
  477. PFN_COUNT PagesToBurn;
  478. PCHAR Options;
  479. PCHAR MemoryOption;
  480. NTSTATUS Status;
  481. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  482. PMESSAGE_RESOURCE_ENTRY MessageEntry;
  483. PLIST_ENTRY NextEntry;
  484. ANSI_STRING AnsiString;
  485. STRING NameString;
  486. CHAR Buffer[ 256 ];
  487. ULONG ImageCount;
  488. ULONG i;
  489. ULONG_PTR ResourceIdPath[3];
  490. PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
  491. PMESSAGE_RESOURCE_DATA MessageData;
  492. CHAR VersionBuffer[ 64 ];
  493. PCHAR s;
  494. PCHAR sMajor;
  495. PCHAR sMinor;
  496. PIMAGE_NT_HEADERS NtHeaders;
  497. PLIST_ENTRY NextMd;
  498. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  499. //
  500. // Initialize PRCB pool lookaside pointers.
  501. //
  502. ExInitPoolLookasidePointers ();
  503. if (Number == 0) {
  504. //
  505. // Determine whether this is textmode setup and whether this is a
  506. // remote boot client.
  507. //
  508. ExpInTextModeSetup = FALSE;
  509. IoRemoteBootClient = FALSE;
  510. if (LoaderBlock->SetupLoaderBlock != NULL) {
  511. if ((LoaderBlock->SetupLoaderBlock->Flags & SETUPBLK_FLAGS_IS_TEXTMODE) != 0) {
  512. ExpInTextModeSetup = TRUE;
  513. }
  514. if ((LoaderBlock->SetupLoaderBlock->Flags & SETUPBLK_FLAGS_IS_REMOTE_BOOT) != 0) {
  515. IoRemoteBootClient = TRUE;
  516. ASSERT( _memicmp( LoaderBlock->ArcBootDeviceName, "net(0)", 6 ) == 0 );
  517. }
  518. }
  519. #if defined(REMOTE_BOOT)
  520. SharedUserData->SystemFlags = 0;
  521. if (IoRemoteBootClient) {
  522. SharedUserData->SystemFlags |= SYSTEM_FLAG_REMOTE_BOOT_CLIENT;
  523. }
  524. #endif // defined(REMOTE_BOOT)
  525. //
  526. // Indicate that we are in phase 0.
  527. //
  528. InitializationPhase = 0L;
  529. Options = LoaderBlock->LoadOptions;
  530. if (Options != NULL) {
  531. //
  532. // If in BBT mode, remove the requested amount of memory from the
  533. // loader block and use it for BBT purposes instead.
  534. //
  535. _strupr(Options);
  536. MemoryOption = strstr(Options, "PERFMEM");
  537. if (MemoryOption != NULL) {
  538. MemoryOption = strstr (MemoryOption,"=");
  539. if (MemoryOption != NULL) {
  540. PagesToBurn = (PFN_COUNT) atol (MemoryOption + 1);
  541. //
  542. // Convert MB to pages.
  543. //
  544. PagesToBurn *= ((1024 * 1024) / PAGE_SIZE);
  545. if (PagesToBurn != 0) {
  546. PERFINFO_INIT_TRACEFLAGS(Options, MemoryOption);
  547. BBTPagesToReserve = ExBurnMemory (LoaderBlock,
  548. PagesToBurn,
  549. LoaderBBTMemory,
  550. &BBTMemoryDescriptor);
  551. }
  552. }
  553. }
  554. //
  555. // Burn memory - consume the amount of memory
  556. // specified in the OS Load Options. This is used
  557. // for testing reduced memory configurations.
  558. //
  559. MemoryOption = strstr(Options, "BURNMEMORY");
  560. if (MemoryOption != NULL) {
  561. MemoryOption = strstr(MemoryOption,"=");
  562. if (MemoryOption != NULL ) {
  563. PagesToBurn = (PFN_COUNT) atol (MemoryOption + 1);
  564. //
  565. // Convert MB to pages.
  566. //
  567. PagesToBurn *= ((1024 * 1024) / PAGE_SIZE);
  568. if (PagesToBurn != 0) {
  569. ExBurnMemory (LoaderBlock,
  570. PagesToBurn,
  571. LoaderBad,
  572. NULL);
  573. }
  574. }
  575. }
  576. }
  577. //
  578. // Initialize the translation tables using the loader
  579. // loaded tables.
  580. //
  581. InitNlsTableBase = LoaderBlock->NlsData->AnsiCodePageData;
  582. InitAnsiCodePageDataOffset = 0;
  583. InitOemCodePageDataOffset = (ULONG)((PUCHAR)LoaderBlock->NlsData->OemCodePageData - (PUCHAR)LoaderBlock->NlsData->AnsiCodePageData);
  584. InitUnicodeCaseTableDataOffset = (ULONG)((PUCHAR)LoaderBlock->NlsData->UnicodeCaseTableData - (PUCHAR)LoaderBlock->NlsData->AnsiCodePageData);
  585. RtlInitNlsTables(
  586. (PVOID)((PUCHAR)InitNlsTableBase+InitAnsiCodePageDataOffset),
  587. (PVOID)((PUCHAR)InitNlsTableBase+InitOemCodePageDataOffset),
  588. (PVOID)((PUCHAR)InitNlsTableBase+InitUnicodeCaseTableDataOffset),
  589. &InitTableInfo
  590. );
  591. RtlResetRtlTranslations(&InitTableInfo);
  592. //
  593. // Initialize the Hardware Architecture Layer (HAL).
  594. //
  595. if (HalInitSystem(InitializationPhase, LoaderBlock) == FALSE) {
  596. KeBugCheck(HAL_INITIALIZATION_FAILED);
  597. }
  598. //
  599. // Enable interrupts now that the HAL has initialized.
  600. //
  601. #if defined(_X86_)
  602. _enable();
  603. #endif
  604. //
  605. // Initialize the crypto exponent... Set to 0 when systems leave ms!
  606. //
  607. #ifdef TEST_BUILD_EXPONENT
  608. #pragma message("WARNING: building kernel with TESTKEY enabled!")
  609. #else
  610. #define TEST_BUILD_EXPONENT 0
  611. #endif
  612. SharedUserData->CryptoExponent = TEST_BUILD_EXPONENT;
  613. #if DBG
  614. NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
  615. FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
  616. #endif
  617. sprintf( Buffer, "C:%s", LoaderBlock->NtBootPathName );
  618. RtlInitString( &AnsiString, Buffer );
  619. Buffer[ --AnsiString.Length ] = '\0';
  620. NtSystemRoot.Buffer = SharedUserData->NtSystemRoot;
  621. NtSystemRoot.MaximumLength = sizeof( SharedUserData->NtSystemRoot ) / sizeof( WCHAR );
  622. NtSystemRoot.Length = 0;
  623. Status = RtlAnsiStringToUnicodeString( &NtSystemRoot,
  624. &AnsiString,
  625. FALSE
  626. );
  627. if (!NT_SUCCESS( Status )) {
  628. KeBugCheck(SESSION3_INITIALIZATION_FAILED);
  629. }
  630. //
  631. // Find the address of BugCheck message block resource and put it
  632. // in KiBugCodeMessages.
  633. //
  634. // WARNING: This code assumes that the KLDR_DATA_TABLE_ENTRY for
  635. // ntoskrnl.exe is always the first in the loaded module list.
  636. //
  637. DataTableEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
  638. KLDR_DATA_TABLE_ENTRY,
  639. InLoadOrderLinks);
  640. ResourceIdPath[0] = 11;
  641. ResourceIdPath[1] = 1;
  642. ResourceIdPath[2] = 0;
  643. Status = LdrFindResource_U (DataTableEntry->DllBase,
  644. ResourceIdPath,
  645. 3,
  646. (VOID *) &ResourceDataEntry);
  647. if (NT_SUCCESS(Status)) {
  648. Status = LdrAccessResource (DataTableEntry->DllBase,
  649. ResourceDataEntry,
  650. &MessageData,
  651. NULL);
  652. if (NT_SUCCESS(Status)) {
  653. KiBugCodeMessages = MessageData;
  654. }
  655. }
  656. #if !defined(NT_UP)
  657. //
  658. // Verify that the kernel and HAL images are suitable for MP systems.
  659. //
  660. // N.B. Loading of kernel and HAL symbols now occurs in kdinit.
  661. //
  662. ImageCount = 0;
  663. NextEntry = LoaderBlock->LoadOrderListHead.Flink;
  664. while ((NextEntry != &LoaderBlock->LoadOrderListHead) && (ImageCount < 2)) {
  665. DataTableEntry = CONTAINING_RECORD(NextEntry,
  666. KLDR_DATA_TABLE_ENTRY,
  667. InLoadOrderLinks);
  668. ImageCount += 1;
  669. if ( !MmVerifyImageIsOkForMpUse(DataTableEntry->DllBase) ) {
  670. KeBugCheckEx(UP_DRIVER_ON_MP_SYSTEM,
  671. (ULONG_PTR)DataTableEntry->DllBase,
  672. 0,
  673. 0,
  674. 0);
  675. }
  676. NextEntry = NextEntry->Flink;
  677. }
  678. #endif // !defined(NT_UP)
  679. //
  680. // Get system control values out of the registry.
  681. //
  682. CmGetSystemControlValues(LoaderBlock->RegistryBase, &CmControlVector[0]);
  683. CmNtGlobalFlag &= FLG_VALID_BITS; // Toss bogus bits.
  684. if (((CmNtCSDVersion & 0xFFFF0000) == 0) &&
  685. ( CmNtCSDReleaseType )) {
  686. switch ( CmNtCSDReleaseType ) {
  687. case SP_RELEASE_TYPE_INTERNAL:
  688. CmNtCSDVersion |= VER_PRODUCTBUILD_QFE << 16;
  689. break;
  690. #ifdef VER_PRODUCTBETAVERSION
  691. case SP_RELEASE_TYPE_BETA:
  692. CmNtCSDVersion |= VER_PRODUCTBETAVERSION << 16;
  693. break;
  694. #endif
  695. #ifdef VER_PRODUCTRCVERSION
  696. case SP_RELEASE_TYPE_RC:
  697. CmNtCSDVersion |= VER_PRODUCTRCVERSION << 16;
  698. break;
  699. #endif
  700. default:
  701. break;
  702. }
  703. }
  704. NtGlobalFlag |= CmNtGlobalFlag;
  705. #if !DBG
  706. if (!(CmNtGlobalFlag & FLG_ENABLE_KDEBUG_SYMBOL_LOAD)) {
  707. NtGlobalFlag &= ~FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
  708. }
  709. #endif
  710. //
  711. // Initialize the ExResource package.
  712. //
  713. if (!ExInitSystem()) {
  714. KeBugCheck(PHASE0_INITIALIZATION_FAILED);
  715. }
  716. //
  717. // Get multinode configuration (if any).
  718. //
  719. KeNumaInitialize();
  720. //
  721. // Initialize memory management and the memory allocation pools.
  722. //
  723. MmInitSystem (0, LoaderBlock);
  724. //
  725. // Scan the loaded module list and load the driver image symbols.
  726. //
  727. ImageCount = 0;
  728. NextEntry = LoaderBlock->LoadOrderListHead.Flink;
  729. while (NextEntry != &LoaderBlock->LoadOrderListHead) {
  730. if (ImageCount >= 2) {
  731. ULONG Count;
  732. WCHAR *Filename;
  733. ULONG Length;
  734. //
  735. // Get the address of the data table entry for the next component.
  736. //
  737. DataTableEntry = CONTAINING_RECORD(NextEntry,
  738. KLDR_DATA_TABLE_ENTRY,
  739. InLoadOrderLinks);
  740. //
  741. // Load the symbols via the kernel debugger
  742. // for the next component.
  743. //
  744. if (DataTableEntry->FullDllName.Buffer[0] == L'\\') {
  745. //
  746. // Correct fullname already available
  747. //
  748. Filename = DataTableEntry->FullDllName.Buffer;
  749. Length = DataTableEntry->FullDllName.Length / sizeof(WCHAR);
  750. Count = 0;
  751. do {
  752. Buffer[Count++] = (CHAR)*Filename++;
  753. } while (Count < Length);
  754. Buffer[Count] = 0;
  755. } else {
  756. //
  757. // Assume drivers
  758. //
  759. sprintf (Buffer, "%ws\\System32\\Drivers\\%wZ",
  760. &SharedUserData->NtSystemRoot[2],
  761. &DataTableEntry->BaseDllName);
  762. }
  763. RtlInitString (&NameString, Buffer );
  764. DbgLoadImageSymbols (&NameString,
  765. DataTableEntry->DllBase,
  766. (ULONG)-1);
  767. #if !defined(NT_UP)
  768. if (!MmVerifyImageIsOkForMpUse(DataTableEntry->DllBase)) {
  769. KeBugCheckEx(UP_DRIVER_ON_MP_SYSTEM,(ULONG_PTR)DataTableEntry->DllBase,0,0,0);
  770. }
  771. #endif // NT_UP
  772. }
  773. ImageCount += 1;
  774. NextEntry = NextEntry->Flink;
  775. }
  776. //
  777. // If break after symbol load is specified, then break into the
  778. // debugger.
  779. //
  780. if (KdBreakAfterSymbolLoad != FALSE) {
  781. DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
  782. }
  783. //
  784. // Turn on the headless terminal now, if we are of a sufficiently
  785. // new vintage of loader
  786. //
  787. if (LoaderBlock->Extension->Size >= sizeof (LOADER_PARAMETER_EXTENSION)) {
  788. HeadlessInit(LoaderBlock);
  789. }
  790. //
  791. // These fields are supported for legacy 3rd party 32-bit software
  792. // only. New code should call NtQueryInformationSystem() to get them.
  793. //
  794. #if defined(_WIN64)
  795. SharedUserData->Reserved1 = 0x7ffeffff; // 2gb HighestUserAddress
  796. SharedUserData->Reserved3 = 0x80000000; // 2gb SystemRangeStart
  797. #else
  798. //
  799. // Set the highest user address and the start of the system range in
  800. // the shared memory block.
  801. //
  802. // N.B. This is not a constant value if the target system is an x86
  803. // with 3gb of user virtual address space.
  804. //
  805. SharedUserData->Reserved1 = (ULONG)MM_HIGHEST_USER_ADDRESS;
  806. SharedUserData->Reserved3 = (ULONG)MmSystemRangeStart;
  807. #endif
  808. //
  809. // Snapshot the NLS tables into paged pool and then
  810. // reset the translation tables.
  811. //
  812. // Walk through the memory descriptors and size the NLS data.
  813. //
  814. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  815. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  816. MemoryDescriptor = CONTAINING_RECORD(NextMd,
  817. MEMORY_ALLOCATION_DESCRIPTOR,
  818. ListEntry);
  819. if (MemoryDescriptor->MemoryType == LoaderNlsData) {
  820. InitNlsTableSize += MemoryDescriptor->PageCount*PAGE_SIZE;
  821. }
  822. NextMd = MemoryDescriptor->ListEntry.Flink;
  823. }
  824. InitNlsTableBase = ExAllocatePoolWithTag (NonPagedPool,
  825. InitNlsTableSize,
  826. ' slN');
  827. if (InitNlsTableBase == NULL) {
  828. KeBugCheck(PHASE0_INITIALIZATION_FAILED);
  829. }
  830. //
  831. // Copy the NLS data into the dynamic buffer so that we can
  832. // free the buffers allocated by the loader. The loader guarantees
  833. // contiguous buffers and the base of all the tables is the ANSI
  834. // code page data.
  835. //
  836. RtlCopyMemory (InitNlsTableBase,
  837. LoaderBlock->NlsData->AnsiCodePageData,
  838. InitNlsTableSize);
  839. RtlInitNlsTables ((PVOID)((PUCHAR)InitNlsTableBase+InitAnsiCodePageDataOffset),
  840. (PVOID)((PUCHAR)InitNlsTableBase+InitOemCodePageDataOffset),
  841. (PVOID)((PUCHAR)InitNlsTableBase+InitUnicodeCaseTableDataOffset),
  842. &InitTableInfo);
  843. RtlResetRtlTranslations (&InitTableInfo);
  844. //
  845. // Determine System version information.
  846. //
  847. DataTableEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
  848. KLDR_DATA_TABLE_ENTRY,
  849. InLoadOrderLinks);
  850. if (CmNtCSDVersion & 0xFFFF) {
  851. Status = RtlFindMessage (DataTableEntry->DllBase, 11, 0,
  852. WINDOWS_NT_CSD_STRING, &MessageEntry);
  853. if (NT_SUCCESS( Status )) {
  854. RtlInitAnsiString( &AnsiString, MessageEntry->Text );
  855. AnsiString.Length -= 2;
  856. sprintf( Buffer,
  857. "%Z %u%c",
  858. &AnsiString,
  859. (CmNtCSDVersion & 0xFF00) >> 8,
  860. (CmNtCSDVersion & 0xFF) ? 'A' + (CmNtCSDVersion & 0xFF) - 1 : '\0');
  861. }
  862. else {
  863. sprintf( Buffer, "CSD %04x", CmNtCSDVersion );
  864. }
  865. }
  866. else {
  867. CmCSDVersionString.MaximumLength = (USHORT) sprintf( Buffer, VER_PRODUCTBETA_STR );
  868. }
  869. //
  870. // High-order 16-bits of CSDVersion contain RC number or build number. If non-zero
  871. // display it after the Service Pack number.
  872. //
  873. if (CmNtCSDVersion & 0xFFFF0000) {
  874. switch ( CmNtCSDReleaseType ) {
  875. case SP_RELEASE_TYPE_INTERNAL:
  876. s = Buffer + strlen( Buffer );
  877. if (s != Buffer) {
  878. *s++ = ',';
  879. *s++ = ' ';
  880. }
  881. s += sprintf( s,
  882. "v.%u",
  883. (CmNtCSDVersion & 0xFFFF0000) >> 16
  884. );
  885. *s++ = '\0';
  886. break;
  887. #ifdef VER_PRODUCTRCVERSION
  888. case SP_RELEASE_TYPE_RC:
  889. s = Buffer + strlen( Buffer );
  890. if (s != Buffer) {
  891. *s++ = ',';
  892. *s++ = ' ';
  893. }
  894. Status = RtlFindMessage (DataTableEntry->DllBase, 11, 0,
  895. WINDOWS_NT_RC_STRING, &MessageEntry);
  896. if (NT_SUCCESS(Status)) {
  897. RtlInitAnsiString( &AnsiString, MessageEntry->Text );
  898. AnsiString.Length -= 2;
  899. }
  900. else {
  901. RtlInitAnsiString( &AnsiString, "RC" );
  902. }
  903. s += sprintf( s,
  904. "%Z %u",
  905. &AnsiString,
  906. (CmNtCSDVersion & 0xFF000000) >> 24
  907. );
  908. if (CmNtCSDVersion & 0x00FF0000) {
  909. s += sprintf( s, ".%u", (CmNtCSDVersion & 0x00FF0000) >> 16 );
  910. }
  911. *s++ = '\0';
  912. break;
  913. #endif
  914. #ifdef VER_PRODUCTBETAVERSION
  915. case SP_RELEASE_TYPE_BETA:
  916. s = Buffer + strlen( Buffer );
  917. if (s != Buffer) {
  918. *s++ = ',';
  919. *s++ = ' ';
  920. }
  921. RtlInitAnsiString( &AnsiString, "\xDF" );
  922. s += sprintf( s,
  923. "%Z %u",
  924. &AnsiString,
  925. (CmNtCSDVersion & 0xFF000000) >> 24
  926. );
  927. if (CmNtCSDVersion & 0x00FF0000) {
  928. s += sprintf( s, ".%u", (CmNtCSDVersion & 0x00FF0000) >> 16 );
  929. }
  930. *s++ = '\0';
  931. break;
  932. #endif
  933. default:
  934. break;
  935. }
  936. }
  937. RtlInitAnsiString( &AnsiString, Buffer );
  938. RtlAnsiStringToUnicodeString( &CmCSDVersionString, &AnsiString, TRUE );
  939. sMajor = strcpy( VersionBuffer, VER_PRODUCTVERSION_STR );
  940. sMinor = strchr( sMajor, '.' );
  941. *sMinor++ = '\0';
  942. NtMajorVersion = atoi( sMajor );
  943. NtMinorVersion = atoi( sMinor );
  944. *--sMinor = '.';
  945. NtHeaders = RtlImageNtHeader (DataTableEntry->DllBase);
  946. if (NtHeaders->OptionalHeader.MajorSubsystemVersion != NtMajorVersion ||
  947. NtHeaders->OptionalHeader.MinorSubsystemVersion != NtMinorVersion) {
  948. NtMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion;
  949. NtMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion;
  950. }
  951. sprintf( VersionBuffer, "%u.%u", NtMajorVersion, NtMinorVersion );
  952. RtlCreateUnicodeStringFromAsciiz( &CmVersionString, VersionBuffer );
  953. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  954. PVOID StackTraceDataBase;
  955. ULONG StackTraceDataBaseLength;
  956. NTSTATUS Status;
  957. StackTraceDataBaseLength = 512 * 1024;
  958. switch ( MmQuerySystemSize() ) {
  959. case MmMediumSystem :
  960. StackTraceDataBaseLength = 1024 * 1024;
  961. break;
  962. case MmLargeSystem :
  963. StackTraceDataBaseLength = 2048 * 1024;
  964. break;
  965. }
  966. StackTraceDataBase = ExAllocatePoolWithTag( NonPagedPool,
  967. StackTraceDataBaseLength,
  968. 'catS');
  969. if (StackTraceDataBase != NULL) {
  970. KdPrint(( "INIT: Kernel mode stack back trace enabled with %u KB buffer.\n", StackTraceDataBaseLength / 1024 ));
  971. Status = RtlInitStackTraceDataBaseEx( StackTraceDataBase,
  972. StackTraceDataBaseLength,
  973. StackTraceDataBaseLength,
  974. (PRTL_INITIALIZE_LOCK_ROUTINE) ExpInitializeLockRoutine,
  975. (PRTL_ACQUIRE_LOCK_ROUTINE) ExpAcquireLockRoutine,
  976. (PRTL_RELEASE_LOCK_ROUTINE) ExpReleaseLockRoutine,
  977. (PRTL_OKAY_TO_LOCK_ROUTINE) ExpOkayToLockRoutine
  978. );
  979. } else {
  980. Status = STATUS_NO_MEMORY;
  981. }
  982. if (!NT_SUCCESS( Status )) {
  983. KdPrint(( "INIT: Unable to initialize stack trace data base - Status == %lx\n", Status ));
  984. }
  985. }
  986. if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
  987. RtlInitializeExceptionLog(MAX_EXCEPTION_LOG);
  988. }
  989. ExInitializeHandleTablePackage();
  990. #if DBG
  991. //
  992. // Allocate and zero the system service count table.
  993. //
  994. KeServiceDescriptorTable[0].Count =
  995. (PULONG)ExAllocatePoolWithTag(NonPagedPool,
  996. KiServiceLimit * sizeof(ULONG),
  997. 'llac');
  998. KeServiceDescriptorTableShadow[0].Count = KeServiceDescriptorTable[0].Count;
  999. if (KeServiceDescriptorTable[0].Count != NULL ) {
  1000. RtlZeroMemory((PVOID)KeServiceDescriptorTable[0].Count,
  1001. KiServiceLimit * sizeof(ULONG));
  1002. }
  1003. #endif
  1004. if (!ObInitSystem()) {
  1005. KeBugCheck(OBJECT_INITIALIZATION_FAILED);
  1006. }
  1007. if (!SeInitSystem()) {
  1008. KeBugCheck(SECURITY_INITIALIZATION_FAILED);
  1009. }
  1010. if (PsInitSystem(0, LoaderBlock) == FALSE) {
  1011. KeBugCheck(PROCESS_INITIALIZATION_FAILED);
  1012. }
  1013. if (!PpInitSystem()) {
  1014. KeBugCheck(PP0_INITIALIZATION_FAILED);
  1015. }
  1016. //
  1017. // Initialize debug system.
  1018. //
  1019. DbgkInitialize ();
  1020. //
  1021. // Compute the tick count multiplier that is used for computing the
  1022. // windows millisecond tick count and copy the resultant value to
  1023. // the memory that is shared between user and kernel mode.
  1024. //
  1025. ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement);
  1026. SharedUserData->TickCountMultiplier = ExpTickCountMultiplier;
  1027. //
  1028. // Set the base os version into shared memory
  1029. //
  1030. SharedUserData->NtMajorVersion = NtMajorVersion;
  1031. SharedUserData->NtMinorVersion = NtMinorVersion;
  1032. //
  1033. // Set the supported image number range used to determine by the
  1034. // loader if a particular image can be executed on the host system.
  1035. // Eventually this will need to be dynamically computed. Also set
  1036. // the architecture specific feature bits.
  1037. //
  1038. #if defined(_AMD64_)
  1039. SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_AMD64;
  1040. SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_AMD64;
  1041. #elif defined(_X86_)
  1042. SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_I386;
  1043. SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_I386;
  1044. #elif defined(_IA64_)
  1045. SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_IA64;
  1046. SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_IA64;
  1047. #else
  1048. #error "no target architecture"
  1049. #endif
  1050. }
  1051. else {
  1052. //
  1053. // Initialize the Hardware Architecture Layer (HAL).
  1054. //
  1055. if (HalInitSystem(InitializationPhase, LoaderBlock) == FALSE) {
  1056. KeBugCheck(HAL_INITIALIZATION_FAILED);
  1057. }
  1058. }
  1059. return;
  1060. }
  1061. VOID
  1062. xcpt4 (
  1063. VOID
  1064. );
  1065. VOID
  1066. Phase1Initialization(
  1067. IN PVOID Context
  1068. )
  1069. {
  1070. PCHAR s;
  1071. PLOADER_PARAMETER_BLOCK LoaderBlock;
  1072. PETHREAD Thread;
  1073. PKPRCB Prcb;
  1074. KPRIORITY Priority;
  1075. NTSTATUS Status;
  1076. UNICODE_STRING SessionManager;
  1077. PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
  1078. PVOID Address;
  1079. PFN_COUNT MemorySize;
  1080. SIZE_T Size;
  1081. ULONG Index;
  1082. RTL_USER_PROCESS_INFORMATION ProcessInformation;
  1083. LARGE_INTEGER UniversalTime;
  1084. LARGE_INTEGER CmosTime;
  1085. LARGE_INTEGER OldTime;
  1086. TIME_FIELDS TimeFields;
  1087. UNICODE_STRING UnicodeDebugString;
  1088. ANSI_STRING AnsiDebugString;
  1089. UNICODE_STRING EnvString, NullString, UnicodeSystemDriveString;
  1090. CHAR DebugBuffer[256];
  1091. CHAR BootLogBuffer[256]; // must be the same size as DebugBuffer
  1092. PWSTR Src, Dst;
  1093. BOOLEAN ResetActiveTimeBias;
  1094. HANDLE NlsSection;
  1095. LARGE_INTEGER SectionSize;
  1096. LARGE_INTEGER SectionOffset;
  1097. PVOID SectionBase;
  1098. PVOID ViewBase;
  1099. ULONG CacheViewSize;
  1100. SIZE_T CapturedViewSize;
  1101. ULONG SavedViewSize;
  1102. LONG BootTimeZoneBias;
  1103. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  1104. CHAR VersionBuffer[24];
  1105. PMESSAGE_RESOURCE_ENTRY MessageEntry;
  1106. #ifndef NT_UP
  1107. PMESSAGE_RESOURCE_ENTRY MessageEntry1;
  1108. #endif
  1109. PCHAR MPKernelString;
  1110. PCHAR Options;
  1111. PCHAR YearOverrideOption, SafeModeOption, BootLogOption;
  1112. LONG CurrentYear = 0;
  1113. PSTR SafeBoot;
  1114. BOOLEAN UseAlternateShell = FALSE;
  1115. #if defined(REMOTE_BOOT)
  1116. BOOLEAN NetBootRequiresFormat = FALSE;
  1117. BOOLEAN NetBootDisconnected = FALSE;
  1118. CHAR NetBootHalName[MAX_HAL_NAME_LENGTH + 1];
  1119. UNICODE_STRING TmpUnicodeString;
  1120. #endif // defined(REMOTE_BOOT)
  1121. BOOLEAN NOGUIBOOT;
  1122. PVOID Environment;
  1123. //
  1124. // Initialize the handle for the PAGELK section.
  1125. //
  1126. ExPageLockHandle = MmLockPagableCodeSection ((PVOID)MmShutdownSystem);
  1127. MmUnlockPagableImageSection(ExPageLockHandle);
  1128. //
  1129. // Set the phase number and raise the priority of current thread to
  1130. // a high priority so it will not be preempted during initialization.
  1131. //
  1132. ResetActiveTimeBias = FALSE;
  1133. InitializationPhase = 1;
  1134. Thread = PsGetCurrentThread();
  1135. Priority = KeSetPriorityThread( &Thread->Tcb,MAXIMUM_PRIORITY - 1 );
  1136. LoaderBlock = (PLOADER_PARAMETER_BLOCK)Context;
  1137. //
  1138. // Put Phase 1 initialization calls here.
  1139. //
  1140. if (HalInitSystem(InitializationPhase, LoaderBlock) == FALSE) {
  1141. KeBugCheck(HAL1_INITIALIZATION_FAILED);
  1142. }
  1143. //
  1144. // Allow the boot video driver to behave differently based on the
  1145. // OsLoadOptions.
  1146. //
  1147. Options = LoaderBlock->LoadOptions ? _strupr(LoaderBlock->LoadOptions) : NULL;
  1148. if (Options) {
  1149. NOGUIBOOT = (BOOLEAN)(strstr(Options, "NOGUIBOOT") != NULL);
  1150. } else {
  1151. NOGUIBOOT = FALSE;
  1152. }
  1153. InbvEnableBootDriver((BOOLEAN)!NOGUIBOOT);
  1154. //
  1155. // There is now enough functionality for the system Boot Video
  1156. // Driver to run.
  1157. //
  1158. if (InbvDriverInitialize(LoaderBlock, 18)) {
  1159. BOOLEAN SOS;
  1160. if (NOGUIBOOT) {
  1161. //
  1162. // If the user specified the noguiboot switch we don't want to
  1163. // use the bootvid driver, so release display ownership.
  1164. //
  1165. InbvNotifyDisplayOwnershipLost(NULL);
  1166. }
  1167. if (Options) {
  1168. SOS = (BOOLEAN)(strstr(Options, "SOS") != NULL);
  1169. } else {
  1170. SOS = FALSE;
  1171. }
  1172. if (NOGUIBOOT) {
  1173. InbvEnableDisplayString(FALSE);
  1174. } else {
  1175. InbvEnableDisplayString(SOS);
  1176. DisplayBootBitmap(SOS);
  1177. }
  1178. }
  1179. //
  1180. // Check whether we are booting into WinPE
  1181. //
  1182. if (Options) {
  1183. if (strstr(Options, "MININT") != NULL) {
  1184. InitIsWinPEMode = TRUE;
  1185. if (strstr(Options, "INRAM") != NULL) {
  1186. InitWinPEModeType |= INIT_WINPEMODE_INRAM;
  1187. } else {
  1188. InitWinPEModeType |= INIT_WINPEMODE_REGULAR;
  1189. }
  1190. }
  1191. }
  1192. //
  1193. // Now that the HAL is available and memory management has sized
  1194. // memory, display the initial system banner containing the version number.
  1195. // Under normal circumstances, this is the first message displayed
  1196. // to the user by the OS.
  1197. //
  1198. DataTableEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
  1199. KLDR_DATA_TABLE_ENTRY,
  1200. InLoadOrderLinks);
  1201. Status = RtlFindMessage (DataTableEntry->DllBase,
  1202. 11,
  1203. 0,
  1204. WINDOWS_NT_BANNER,
  1205. &MessageEntry);
  1206. s = DebugBuffer;
  1207. if (CmCSDVersionString.Length != 0) {
  1208. s += sprintf( s, ": %wZ", &CmCSDVersionString );
  1209. }
  1210. *s++ = '\0';
  1211. sprintf( VersionBuffer, "%u.%u", NtMajorVersion, NtMinorVersion );
  1212. sprintf (s,
  1213. NT_SUCCESS(Status) ? MessageEntry->Text :
  1214. "MICROSOFT (R) WINDOWS 2000 (TM)\n",
  1215. VersionBuffer,
  1216. NtBuildNumber & 0xFFFF,
  1217. DebugBuffer);
  1218. InbvDisplayString(s);
  1219. RtlCopyMemory (BootLogBuffer, DebugBuffer, sizeof(DebugBuffer));
  1220. //
  1221. // Initialize the Power subsystem.
  1222. //
  1223. if (!PoInitSystem(0)) {
  1224. KeBugCheck(INTERNAL_POWER_ERROR);
  1225. }
  1226. //
  1227. // The user may have put a /YEAR=2000 switch on
  1228. // the OSLOADOPTIONS line. This allows us to
  1229. // enforce a particular year on hardware that
  1230. // has a broken clock.
  1231. //
  1232. if (Options) {
  1233. YearOverrideOption = strstr(Options, "YEAR");
  1234. if (YearOverrideOption != NULL) {
  1235. YearOverrideOption = strstr(YearOverrideOption,"=");
  1236. }
  1237. if (YearOverrideOption != NULL) {
  1238. CurrentYear = atol(YearOverrideOption + 1);
  1239. }
  1240. }
  1241. //
  1242. // Initialize the system time and set the time the system was booted.
  1243. //
  1244. // N.B. This cannot be done until after the phase one initialization
  1245. // of the HAL Layer.
  1246. //
  1247. if (ExCmosClockIsSane
  1248. && HalQueryRealTimeClock(&TimeFields)) {
  1249. //
  1250. // If appropriate, override the year.
  1251. //
  1252. if (YearOverrideOption) {
  1253. TimeFields.Year = (SHORT)CurrentYear;
  1254. }
  1255. RtlTimeFieldsToTime(&TimeFields, &CmosTime);
  1256. UniversalTime = CmosTime;
  1257. if ( !ExpRealTimeIsUniversal ) {
  1258. //
  1259. // If the system stores time in local time. This is converted to
  1260. // universal time before going any further
  1261. //
  1262. // If we have previously set the time through NT, then
  1263. // ExpLastTimeZoneBias should contain the timezone bias in effect
  1264. // when the clock was set. Otherwise, we will have to resort to
  1265. // our next best guess which would be the programmed bias stored in
  1266. // the registry
  1267. //
  1268. if ( ExpLastTimeZoneBias == -1 ) {
  1269. ResetActiveTimeBias = TRUE;
  1270. ExpLastTimeZoneBias = ExpAltTimeZoneBias;
  1271. }
  1272. ExpTimeZoneBias.QuadPart = Int32x32To64(
  1273. ExpLastTimeZoneBias*60, // Bias in seconds
  1274. 10000000
  1275. );
  1276. SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
  1277. SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
  1278. SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
  1279. UniversalTime.QuadPart = CmosTime.QuadPart + ExpTimeZoneBias.QuadPart;
  1280. }
  1281. KeSetSystemTime(&UniversalTime, &OldTime, FALSE, NULL);
  1282. //
  1283. // Notify other components that the system time has been set
  1284. //
  1285. PoNotifySystemTimeSet();
  1286. KeBootTime = UniversalTime;
  1287. KeBootTimeBias = 0;
  1288. }
  1289. MPKernelString = "";
  1290. #ifndef NT_UP
  1291. //
  1292. // Enforce processor licensing.
  1293. //
  1294. if (KeLicensedProcessors) {
  1295. if (KeRegisteredProcessors > KeLicensedProcessors) {
  1296. KeRegisteredProcessors = KeLicensedProcessors;
  1297. }
  1298. }
  1299. if (Options) {
  1300. ULONG NewRegisteredProcessors;
  1301. PCHAR NumProcOption;
  1302. NumProcOption = strstr(Options, "NUMPROC");
  1303. if (NumProcOption != NULL) {
  1304. NumProcOption = strstr(NumProcOption,"=");
  1305. }
  1306. if (NumProcOption != NULL) {
  1307. NewRegisteredProcessors = atol(NumProcOption+1);
  1308. if (NewRegisteredProcessors < KeRegisteredProcessors) {
  1309. KeRegisteredProcessors = NewRegisteredProcessors;
  1310. }
  1311. #if defined(_X86_)
  1312. KeNumprocSpecified = NewRegisteredProcessors;
  1313. #endif
  1314. }
  1315. }
  1316. //
  1317. // If this is an MP build of the kernel start any other processors now
  1318. //
  1319. KeStartAllProcessors();
  1320. //
  1321. // Since starting processors has thrown off the system time, get it again
  1322. // from the RTC and set the system time again.
  1323. //
  1324. if (ExCmosClockIsSane
  1325. && HalQueryRealTimeClock(&TimeFields)) {
  1326. if (YearOverrideOption) {
  1327. TimeFields.Year = (SHORT)CurrentYear;
  1328. }
  1329. RtlTimeFieldsToTime(&TimeFields, &CmosTime);
  1330. if ( !ExpRealTimeIsUniversal ) {
  1331. UniversalTime.QuadPart = CmosTime.QuadPart + ExpTimeZoneBias.QuadPart;
  1332. }
  1333. KeSetSystemTime(&UniversalTime, &OldTime, TRUE, NULL);
  1334. }
  1335. //
  1336. // Set the affinity of the system process and all of its threads to
  1337. // all processors in the host configuration.
  1338. //
  1339. KeSetAffinityProcess(KeGetCurrentThread()->ApcState.Process,
  1340. KeActiveProcessors);
  1341. Status = RtlFindMessage (DataTableEntry->DllBase, 11, 0,
  1342. WINDOWS_NT_MP_STRING, &MessageEntry1);
  1343. if (NT_SUCCESS( Status )) {
  1344. MPKernelString = MessageEntry1->Text;
  1345. }
  1346. else {
  1347. MPKernelString = "MultiProcessor Kernel\r\n";
  1348. }
  1349. #endif
  1350. //
  1351. // Signify to the HAL that all processors have been started and any
  1352. // post initialization should be performed.
  1353. //
  1354. if (!HalAllProcessorsStarted()) {
  1355. KeBugCheck(HAL1_INITIALIZATION_FAILED);
  1356. }
  1357. RtlInitAnsiString( &AnsiDebugString, MPKernelString );
  1358. if (AnsiDebugString.Length >= 2) {
  1359. AnsiDebugString.Length -= 2;
  1360. }
  1361. //
  1362. // Now that the processors have started, display number of processors
  1363. // and size of memory.
  1364. //
  1365. Status = RtlFindMessage( DataTableEntry->DllBase,
  1366. 11,
  1367. 0,
  1368. KeNumberProcessors > 1 ? WINDOWS_NT_INFO_STRING_PLURAL
  1369. : WINDOWS_NT_INFO_STRING,
  1370. &MessageEntry
  1371. );
  1372. MemorySize = 0;
  1373. for (Index=0; Index < MmPhysicalMemoryBlock->NumberOfRuns; Index++) {
  1374. MemorySize += (PFN_COUNT)MmPhysicalMemoryBlock->Run[Index].PageCount;
  1375. }
  1376. sprintf (DebugBuffer,
  1377. NT_SUCCESS(Status) ? MessageEntry->Text : "%u System Processor [%u MB Memory] %Z\n",
  1378. KeNumberProcessors,
  1379. (MemorySize + (1 << (20 - PAGE_SHIFT)) - 1) >> (20 - PAGE_SHIFT),
  1380. &AnsiDebugString);
  1381. InbvDisplayString(DebugBuffer);
  1382. InbvUpdateProgressBar(5);
  1383. #if defined(REMOTE_BOOT)
  1384. //
  1385. // Save any information from NetBoot for later.
  1386. //
  1387. if (IoRemoteBootClient) {
  1388. ULONG Flags;
  1389. ASSERT(LoaderBlock->SetupLoaderBlock != NULL);
  1390. Flags = LoaderBlock->SetupLoaderBlock->Flags;
  1391. NetBootDisconnected = (BOOLEAN)((Flags & SETUPBLK_FLAGS_DISCONNECTED) != 0);
  1392. NetBootRequiresFormat = (BOOLEAN)((Flags & SETUPBLK_FLAGS_FORMAT_NEEDED) != 0);
  1393. memcpy(NetBootHalName,
  1394. LoaderBlock->SetupLoaderBlock->NetBootHalName,
  1395. sizeof(NetBootHalName));
  1396. }
  1397. #endif // defined(REMOTE_BOOT)
  1398. //
  1399. // Initialize OB, EX, KE, and KD.
  1400. //
  1401. if (!ObInitSystem()) {
  1402. KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
  1403. }
  1404. if (!ExInitSystem()) {
  1405. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,STATUS_UNSUCCESSFUL,0,1,0);
  1406. }
  1407. if (!KeInitSystem()) {
  1408. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,STATUS_UNSUCCESSFUL,0,2,0);
  1409. }
  1410. if (!KdInitSystem(InitializationPhase, NULL)) {
  1411. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,STATUS_UNSUCCESSFUL,0,3,0);
  1412. }
  1413. //
  1414. // SE expects directory and executive objects to be available, but
  1415. // must be before device drivers are initialized.
  1416. //
  1417. if (!SeInitSystem()) {
  1418. KeBugCheck(SECURITY1_INITIALIZATION_FAILED);
  1419. }
  1420. InbvUpdateProgressBar(10);
  1421. //
  1422. // Create the symbolic link to \SystemRoot.
  1423. //
  1424. Status = CreateSystemRootLink(LoaderBlock);
  1425. if ( !NT_SUCCESS(Status) ) {
  1426. KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED,Status,0,0,0);
  1427. }
  1428. if (MmInitSystem(1, LoaderBlock) == FALSE) {
  1429. KeBugCheck(MEMORY1_INITIALIZATION_FAILED);
  1430. }
  1431. //
  1432. // Snapshot the NLS tables into a page file backed section, and then
  1433. // reset the translation tables.
  1434. //
  1435. SectionSize.HighPart = 0;
  1436. SectionSize.LowPart = InitNlsTableSize;
  1437. Status = ZwCreateSection(
  1438. &NlsSection,
  1439. SECTION_ALL_ACCESS,
  1440. NULL,
  1441. &SectionSize,
  1442. PAGE_READWRITE,
  1443. SEC_COMMIT,
  1444. NULL
  1445. );
  1446. if (!NT_SUCCESS(Status)) {
  1447. KdPrint(("INIT: Nls Section Creation Failed %x\n",Status));
  1448. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,Status,1,0,0);
  1449. }
  1450. Status = ObReferenceObjectByHandle(
  1451. NlsSection,
  1452. SECTION_ALL_ACCESS,
  1453. MmSectionObjectType,
  1454. KernelMode,
  1455. &InitNlsSectionPointer,
  1456. NULL
  1457. );
  1458. ZwClose(NlsSection);
  1459. if ( !NT_SUCCESS(Status) ) {
  1460. KdPrint(("INIT: Nls Section Reference Failed %x\n",Status));
  1461. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,Status,2,0,0);
  1462. }
  1463. SectionBase = NULL;
  1464. CacheViewSize = SectionSize.LowPart;
  1465. SavedViewSize = CacheViewSize;
  1466. SectionSize.LowPart = 0;
  1467. Status = MmMapViewInSystemCache (InitNlsSectionPointer,
  1468. &SectionBase,
  1469. &SectionSize,
  1470. &CacheViewSize);
  1471. if (!NT_SUCCESS(Status)) {
  1472. KdPrint(("INIT: Map In System Cache Failed %x\n",Status));
  1473. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,Status,3,0,0);
  1474. }
  1475. //
  1476. // Copy the NLS data into the dynamic buffer so that we can
  1477. // free the buffers allocated by the loader. The loader guarantees
  1478. // contiguous buffers and the base of all the tables is the ANSI
  1479. // code page data.
  1480. //
  1481. RtlCopyMemory (SectionBase, InitNlsTableBase, InitNlsTableSize);
  1482. //
  1483. // Unmap the view to remove all pages from memory. This prevents
  1484. // these tables from consuming memory in the system cache while
  1485. // the system cache is underutilized during bootup.
  1486. //
  1487. MmUnmapViewInSystemCache (SectionBase, InitNlsSectionPointer, FALSE);
  1488. SectionBase = NULL;
  1489. //
  1490. // Map it back into the system cache, but now the pages will no
  1491. // longer be valid.
  1492. //
  1493. Status = MmMapViewInSystemCache(
  1494. InitNlsSectionPointer,
  1495. &SectionBase,
  1496. &SectionSize,
  1497. &SavedViewSize
  1498. );
  1499. if ( !NT_SUCCESS(Status) ) {
  1500. KdPrint(("INIT: Map In System Cache Failed %x\n",Status));
  1501. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,Status,4,0,0);
  1502. }
  1503. ExFreePool(InitNlsTableBase);
  1504. InitNlsTableBase = SectionBase;
  1505. RtlInitNlsTables(
  1506. (PVOID)((PUCHAR)InitNlsTableBase+InitAnsiCodePageDataOffset),
  1507. (PVOID)((PUCHAR)InitNlsTableBase+InitOemCodePageDataOffset),
  1508. (PVOID)((PUCHAR)InitNlsTableBase+InitUnicodeCaseTableDataOffset),
  1509. &InitTableInfo
  1510. );
  1511. RtlResetRtlTranslations(&InitTableInfo);
  1512. ViewBase = NULL;
  1513. SectionOffset.LowPart = 0;
  1514. SectionOffset.HighPart = 0;
  1515. CapturedViewSize = 0;
  1516. //
  1517. // Map the system dll into the user part of the address space
  1518. //
  1519. Status = MmMapViewOfSection (InitNlsSectionPointer,
  1520. PsGetCurrentProcess(),
  1521. &ViewBase,
  1522. 0L,
  1523. 0L,
  1524. &SectionOffset,
  1525. &CapturedViewSize,
  1526. ViewShare,
  1527. 0L,
  1528. PAGE_READWRITE);
  1529. if (!NT_SUCCESS(Status)) {
  1530. KdPrint(("INIT: Map In User Portion Failed %x\n",Status));
  1531. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,Status,5,0,0);
  1532. }
  1533. RtlCopyMemory (ViewBase, InitNlsTableBase, InitNlsTableSize);
  1534. InitNlsTableBase = ViewBase;
  1535. //
  1536. // Initialize the cache manager.
  1537. //
  1538. if (!CcInitializeCacheManager()) {
  1539. KeBugCheck(CACHE_INITIALIZATION_FAILED);
  1540. }
  1541. //
  1542. // Config management (particularly the registry) gets initialized in
  1543. // two parts. Part 1 makes \REGISTRY\MACHINE\SYSTEM and
  1544. // \REGISTRY\MACHINE\HARDWARE available. These are needed to
  1545. // complete IO init.
  1546. //
  1547. if (!CmInitSystem1(LoaderBlock)) {
  1548. KeBugCheck(CONFIG_INITIALIZATION_FAILED);
  1549. }
  1550. //
  1551. // Initialize the prefetcher after registry is initialized so we can
  1552. // query the prefetching parameters.
  1553. //
  1554. CcPfInitializePrefetcher();
  1555. InbvUpdateProgressBar(15);
  1556. //
  1557. // Compute timezone bias and next cutover date.
  1558. //
  1559. BootTimeZoneBias = ExpLastTimeZoneBias;
  1560. ExpRefreshTimeZoneInformation(&CmosTime);
  1561. if (ResetActiveTimeBias) {
  1562. ExLocalTimeToSystemTime(&CmosTime,&UniversalTime);
  1563. KeBootTime = UniversalTime;
  1564. KeBootTimeBias = 0;
  1565. KeSetSystemTime(&UniversalTime, &OldTime, FALSE, NULL);
  1566. }
  1567. else {
  1568. //
  1569. // Check to see if a timezone switch occurred prior to boot...
  1570. //
  1571. if (BootTimeZoneBias != ExpLastTimeZoneBias) {
  1572. ZwSetSystemTime(NULL,NULL);
  1573. }
  1574. }
  1575. if (!FsRtlInitSystem()) {
  1576. KeBugCheck(FILE_INITIALIZATION_FAILED);
  1577. }
  1578. //
  1579. // Initialize the range list package - this must be before PNP
  1580. // initialization as PNP uses range lists.
  1581. //
  1582. RtlInitializeRangeListPackage();
  1583. HalReportResourceUsage();
  1584. KdDebuggerInitialize1(LoaderBlock);
  1585. //
  1586. // Perform phase1 initialization of the Plug and Play manager. This
  1587. // must be done before the I/O system initializes.
  1588. //
  1589. if (!PpInitSystem()) {
  1590. KeBugCheck(PP1_INITIALIZATION_FAILED);
  1591. }
  1592. InbvUpdateProgressBar(20);
  1593. //
  1594. // LPC needs to be initialized before the I/O system, since
  1595. // some drivers may create system threads that will terminate
  1596. // and cause LPC to be called.
  1597. //
  1598. if (!LpcInitSystem()) {
  1599. KeBugCheck(LPC_INITIALIZATION_FAILED);
  1600. }
  1601. //
  1602. // Check for the existence of the safeboot option.
  1603. //
  1604. if (Options) {
  1605. SafeBoot = strstr(Options,SAFEBOOT_LOAD_OPTION_A);
  1606. } else {
  1607. SafeBoot = FALSE;
  1608. }
  1609. if (SafeBoot) {
  1610. //
  1611. // Isolate the safeboot option.
  1612. //
  1613. SafeBoot += strlen(SAFEBOOT_LOAD_OPTION_A);
  1614. //
  1615. // Set the safeboot mode.
  1616. //
  1617. if (strncmp(SafeBoot,SAFEBOOT_MINIMAL_STR_A,strlen(SAFEBOOT_MINIMAL_STR_A))==0) {
  1618. InitSafeBootMode = SAFEBOOT_MINIMAL;
  1619. SafeBoot += strlen(SAFEBOOT_MINIMAL_STR_A);
  1620. } else if (strncmp(SafeBoot,SAFEBOOT_NETWORK_STR_A,strlen(SAFEBOOT_NETWORK_STR_A))==0) {
  1621. InitSafeBootMode = SAFEBOOT_NETWORK;
  1622. SafeBoot += strlen(SAFEBOOT_NETWORK_STR_A);
  1623. } else if (strncmp(SafeBoot,SAFEBOOT_DSREPAIR_STR_A,strlen(SAFEBOOT_DSREPAIR_STR_A))==0) {
  1624. InitSafeBootMode = SAFEBOOT_DSREPAIR;
  1625. SafeBoot += strlen(SAFEBOOT_DSREPAIR_STR_A);
  1626. } else {
  1627. InitSafeBootMode = 0;
  1628. }
  1629. if (*SafeBoot && strncmp(SafeBoot,SAFEBOOT_ALTERNATESHELL_STR_A,strlen(SAFEBOOT_ALTERNATESHELL_STR_A))==0) {
  1630. UseAlternateShell = TRUE;
  1631. }
  1632. if (InitSafeBootMode) {
  1633. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  1634. PMESSAGE_RESOURCE_ENTRY MessageEntry;
  1635. ULONG MsgId = 0;
  1636. DataTableEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
  1637. KLDR_DATA_TABLE_ENTRY,
  1638. InLoadOrderLinks);
  1639. switch (InitSafeBootMode) {
  1640. case SAFEBOOT_MINIMAL:
  1641. MsgId = BOOTING_IN_SAFEMODE_MINIMAL;
  1642. break;
  1643. case SAFEBOOT_NETWORK:
  1644. MsgId = BOOTING_IN_SAFEMODE_NETWORK;
  1645. break;
  1646. case SAFEBOOT_DSREPAIR:
  1647. MsgId = BOOTING_IN_SAFEMODE_DSREPAIR;
  1648. break;
  1649. }
  1650. Status = RtlFindMessage (DataTableEntry->DllBase, 11, 0, MsgId, &MessageEntry);
  1651. if (NT_SUCCESS( Status )) {
  1652. InbvDisplayString(MessageEntry->Text);
  1653. }
  1654. }
  1655. }
  1656. //
  1657. // Check for the existence of the bootlog option.
  1658. //
  1659. if (Options) {
  1660. BootLogOption = strstr(Options, "BOOTLOG");
  1661. } else {
  1662. BootLogOption = FALSE;
  1663. }
  1664. if (BootLogOption) {
  1665. Status = RtlFindMessage (DataTableEntry->DllBase, 11, 0, BOOTLOG_ENABLED, &MessageEntry);
  1666. if (NT_SUCCESS( Status )) {
  1667. InbvDisplayString(MessageEntry->Text);
  1668. }
  1669. IopInitializeBootLogging(LoaderBlock, BootLogBuffer);
  1670. }
  1671. //
  1672. // Now that system time is running, initialize more of the Executive.
  1673. //
  1674. ExInitSystemPhase2();
  1675. InbvUpdateProgressBar(25);
  1676. //
  1677. // Allow time slip notification changes.
  1678. //
  1679. KdpTimeSlipPending = 0;
  1680. //
  1681. // If we are running XIP, we have to initialize XIP before the I/O system calls xipdisk.sys
  1682. // This is defined to be nothing on platforms that do not support XIP.
  1683. //
  1684. XIPInit(LoaderBlock);
  1685. //
  1686. // Initialize the Io system.
  1687. //
  1688. // IoInitSystem updates progress bar updates from 25 to 75 %.
  1689. //
  1690. InbvSetProgressBarSubset(25, 75);
  1691. if (!IoInitSystem(LoaderBlock)) {
  1692. KeBugCheck(IO1_INITIALIZATION_FAILED);
  1693. }
  1694. //
  1695. // Clear progress bar subset, goes back to absolute mode.
  1696. //
  1697. InbvSetProgressBarSubset(0, 100);
  1698. //
  1699. // Set the registry value that indicates we've booted in safeboot mode.
  1700. //
  1701. if (InitSafeBootMode) {
  1702. HANDLE hSafeBoot,hOption;
  1703. UNICODE_STRING string;
  1704. OBJECT_ATTRIBUTES objectAttributes;
  1705. ULONG disposition;
  1706. UCHAR Buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + 32];
  1707. ULONG length;
  1708. PKEY_VALUE_PARTIAL_INFORMATION keyValue;
  1709. InitializeObjectAttributes(
  1710. &objectAttributes,
  1711. &CmRegistryMachineSystemCurrentControlSetControlSafeBoot,
  1712. OBJ_CASE_INSENSITIVE,
  1713. NULL,
  1714. NULL
  1715. );
  1716. Status = ZwOpenKey(
  1717. &hSafeBoot,
  1718. KEY_ALL_ACCESS,
  1719. &objectAttributes
  1720. );
  1721. if (NT_SUCCESS(Status)) {
  1722. if (UseAlternateShell) {
  1723. RtlInitUnicodeString( &string, L"AlternateShell" );
  1724. keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
  1725. RtlZeroMemory(Buffer, sizeof(Buffer));
  1726. Status = NtQueryValueKey(
  1727. hSafeBoot,
  1728. &string,
  1729. KeyValuePartialInformation,
  1730. keyValue,
  1731. sizeof(Buffer),
  1732. &length
  1733. );
  1734. if (!NT_SUCCESS(Status)) {
  1735. UseAlternateShell = FALSE;
  1736. }
  1737. }
  1738. RtlInitUnicodeString( &string, L"Option" );
  1739. InitializeObjectAttributes(
  1740. &objectAttributes,
  1741. &string,
  1742. OBJ_CASE_INSENSITIVE,
  1743. hSafeBoot,
  1744. NULL
  1745. );
  1746. Status = ZwCreateKey(
  1747. &hOption,
  1748. KEY_ALL_ACCESS,
  1749. &objectAttributes,
  1750. 0,
  1751. NULL,
  1752. REG_OPTION_VOLATILE,
  1753. &disposition
  1754. );
  1755. NtClose(hSafeBoot);
  1756. if (NT_SUCCESS(Status)) {
  1757. RtlInitUnicodeString( &string, L"OptionValue" );
  1758. Status = NtSetValueKey(
  1759. hOption,
  1760. &string,
  1761. 0,
  1762. REG_DWORD,
  1763. &InitSafeBootMode,
  1764. sizeof(ULONG)
  1765. );
  1766. if (UseAlternateShell) {
  1767. RtlInitUnicodeString( &string, L"UseAlternateShell" );
  1768. Index = 1;
  1769. Status = NtSetValueKey(
  1770. hOption,
  1771. &string,
  1772. 0,
  1773. REG_DWORD,
  1774. &Index,
  1775. sizeof(ULONG)
  1776. );
  1777. }
  1778. NtClose(hOption);
  1779. }
  1780. }
  1781. }
  1782. //
  1783. // Create the Mini NT boot key, to indicate to the user mode
  1784. // programs that we are in Mini NT environment.
  1785. //
  1786. if (InitIsWinPEMode) {
  1787. WCHAR KeyName[256] = {0};
  1788. HANDLE hControl;
  1789. UNICODE_STRING String;
  1790. OBJECT_ATTRIBUTES ObjAttrs;
  1791. ULONG Disposition;
  1792. wcsncpy(KeyName, CmRegistryMachineSystemCurrentControlSet.Buffer,
  1793. CmRegistryMachineSystemCurrentControlSet.Length);
  1794. wcscat(KeyName, L"\\Control");
  1795. RtlInitUnicodeString(&String, KeyName);
  1796. InitializeObjectAttributes(
  1797. &ObjAttrs,
  1798. &String,
  1799. OBJ_CASE_INSENSITIVE,
  1800. NULL,
  1801. NULL
  1802. );
  1803. Status = ZwOpenKey(
  1804. &hControl,
  1805. KEY_ALL_ACCESS,
  1806. &ObjAttrs
  1807. );
  1808. if (NT_SUCCESS(Status)) {
  1809. HANDLE hMiniNT;
  1810. RtlInitUnicodeString(&String, L"MiniNT");
  1811. InitializeObjectAttributes(
  1812. &ObjAttrs,
  1813. &String,
  1814. OBJ_CASE_INSENSITIVE,
  1815. hControl,
  1816. NULL
  1817. );
  1818. Status = ZwCreateKey(
  1819. &hMiniNT,
  1820. KEY_ALL_ACCESS,
  1821. &ObjAttrs,
  1822. 0,
  1823. NULL,
  1824. REG_OPTION_VOLATILE,
  1825. &Disposition
  1826. );
  1827. if (NT_SUCCESS(Status)) {
  1828. ZwClose(hMiniNT);
  1829. }
  1830. ZwClose(hControl);
  1831. }
  1832. //
  1833. // If we could not create the key, then bug check
  1834. // since we can't boot into mini NT anyway.
  1835. //
  1836. if (!NT_SUCCESS(Status)) {
  1837. KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,Status,6,0,0);
  1838. }
  1839. }
  1840. //
  1841. // Begin paging the executive if desired.
  1842. //
  1843. MmInitSystem(2, LoaderBlock);
  1844. InbvUpdateProgressBar(80);
  1845. #if defined(_X86_)
  1846. //
  1847. // Initialize Vdm specific stuff
  1848. //
  1849. // Note: If this fails, Vdms may not be able to run, but it isn't
  1850. // necessary to bugcheck the system because of this.
  1851. //
  1852. KeI386VdmInitialize();
  1853. #if !defined(NT_UP)
  1854. //
  1855. // Now that the error log interface has been initialized, write
  1856. // an informational message if it was determined that the
  1857. // processors in the system are at differing revision levels.
  1858. //
  1859. if (CmProcessorMismatch != 0) {
  1860. PIO_ERROR_LOG_PACKET ErrLog;
  1861. ErrLog = IoAllocateGenericErrorLogEntry(ERROR_LOG_MAXIMUM_SIZE);
  1862. if (ErrLog) {
  1863. //
  1864. // Fill it in and write it out.
  1865. //
  1866. ErrLog->FinalStatus = STATUS_MP_PROCESSOR_MISMATCH;
  1867. ErrLog->ErrorCode = STATUS_MP_PROCESSOR_MISMATCH;
  1868. ErrLog->UniqueErrorValue = CmProcessorMismatch;
  1869. IoWriteErrorLogEntry(ErrLog);
  1870. }
  1871. }
  1872. #endif // !NT_UP
  1873. //
  1874. // Also log remembered machine checks, if any.
  1875. //
  1876. KiLogMcaErrors();
  1877. #endif // _X86_
  1878. if (!PoInitSystem(1)) {
  1879. KeBugCheck(INTERNAL_POWER_ERROR);
  1880. }
  1881. //
  1882. // Okay to call PsInitSystem now that \SystemRoot is defined so it can
  1883. // locate NTDLL.DLL and SMSS.EXE.
  1884. //
  1885. if (PsInitSystem(1, LoaderBlock) == FALSE) {
  1886. KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
  1887. }
  1888. InbvUpdateProgressBar(85);
  1889. //
  1890. // Force KeBugCheck to look at PsLoadedModuleList now that it is setup.
  1891. //
  1892. if (LoaderBlock == KeLoaderBlock) {
  1893. KeLoaderBlock = NULL;
  1894. }
  1895. //
  1896. // Free loader block.
  1897. //
  1898. MmFreeLoaderBlock (LoaderBlock);
  1899. LoaderBlock = NULL;
  1900. Context = NULL;
  1901. //
  1902. // Perform Phase 1 Reference Monitor Initialization. This includes
  1903. // creating the Reference Monitor Command Server Thread, a permanent
  1904. // thread of the System Init process. That thread will create an LPC
  1905. // port called the Reference Monitor Command Port through which
  1906. // commands sent by the Local Security Authority Subsystem will be
  1907. // received. These commands (e.g. Enable Auditing) change the Reference
  1908. // Monitor State.
  1909. //
  1910. if (!SeRmInitPhase1()) {
  1911. KeBugCheck(REFMON_INITIALIZATION_FAILED);
  1912. }
  1913. InbvUpdateProgressBar(90);
  1914. //
  1915. // Set up process parameters for the Session Manager Subsystem.
  1916. //
  1917. // NOTE: Remote boot allocates an extra DOS_MAX_PATH_LENGTH number of
  1918. // WCHARs in order to hold command line arguments to smss.exe.
  1919. //
  1920. Size = sizeof( *ProcessParameters ) +
  1921. ((DOS_MAX_PATH_LENGTH * 6) * sizeof( WCHAR ));
  1922. ProcessParameters = NULL;
  1923. Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
  1924. (PVOID *)&ProcessParameters,
  1925. 0,
  1926. &Size,
  1927. MEM_COMMIT,
  1928. PAGE_READWRITE
  1929. );
  1930. if (!NT_SUCCESS( Status )) {
  1931. #if DBG
  1932. sprintf(DebugBuffer,
  1933. "INIT: Unable to allocate Process Parameters. 0x%lx\n",
  1934. Status);
  1935. RtlInitAnsiString(&AnsiDebugString, DebugBuffer);
  1936. if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDebugString,
  1937. &AnsiDebugString,
  1938. TRUE)) == FALSE) {
  1939. KeBugCheck(SESSION1_INITIALIZATION_FAILED);
  1940. }
  1941. ZwDisplayString(&UnicodeDebugString);
  1942. #endif // DBG
  1943. KeBugCheckEx(SESSION1_INITIALIZATION_FAILED,Status,0,0,0);
  1944. }
  1945. ProcessParameters->Length = (ULONG)Size;
  1946. ProcessParameters->MaximumLength = (ULONG)Size;
  1947. //
  1948. // Reserve the low 1 MB of address space in the session manager.
  1949. // Setup gets started using a replacement for the session manager
  1950. // and that process needs to be able to use the vga driver on x86,
  1951. // which uses int10 and thus requires the low 1 meg to be reserved
  1952. // in the process. The cost is so low that we just do this all the
  1953. // time, even when setup isn't running.
  1954. //
  1955. ProcessParameters->Flags = RTL_USER_PROC_PARAMS_NORMALIZED | RTL_USER_PROC_RESERVE_1MB;
  1956. Size = PAGE_SIZE;
  1957. Environment = NULL;
  1958. Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
  1959. &Environment,
  1960. 0,
  1961. &Size,
  1962. MEM_COMMIT,
  1963. PAGE_READWRITE
  1964. );
  1965. if (!NT_SUCCESS( Status )) {
  1966. #if DBG
  1967. sprintf(DebugBuffer,
  1968. "INIT: Unable to allocate Process Environment 0x%lx\n",
  1969. Status);
  1970. RtlInitAnsiString(&AnsiDebugString, DebugBuffer);
  1971. if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDebugString,
  1972. &AnsiDebugString,
  1973. TRUE)) == FALSE) {
  1974. KeBugCheck(SESSION2_INITIALIZATION_FAILED);
  1975. }
  1976. ZwDisplayString(&UnicodeDebugString);
  1977. #endif // DBG
  1978. KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,Status,0,0,0);
  1979. }
  1980. ProcessParameters->Environment = Environment;
  1981. Dst = (PWSTR)(ProcessParameters + 1);
  1982. ProcessParameters->CurrentDirectory.DosPath.Buffer = Dst;
  1983. ProcessParameters->CurrentDirectory.DosPath.MaximumLength = DOS_MAX_PATH_LENGTH * sizeof( WCHAR );
  1984. RtlCopyUnicodeString( &ProcessParameters->CurrentDirectory.DosPath,
  1985. &NtSystemRoot
  1986. );
  1987. Dst = (PWSTR)((PCHAR)ProcessParameters->CurrentDirectory.DosPath.Buffer +
  1988. ProcessParameters->CurrentDirectory.DosPath.MaximumLength
  1989. );
  1990. ProcessParameters->DllPath.Buffer = Dst;
  1991. ProcessParameters->DllPath.MaximumLength = DOS_MAX_PATH_LENGTH * sizeof( WCHAR );
  1992. RtlCopyUnicodeString( &ProcessParameters->DllPath,
  1993. &ProcessParameters->CurrentDirectory.DosPath
  1994. );
  1995. RtlAppendUnicodeToString( &ProcessParameters->DllPath, L"\\System32" );
  1996. Dst = (PWSTR)((PCHAR)ProcessParameters->DllPath.Buffer +
  1997. ProcessParameters->DllPath.MaximumLength
  1998. );
  1999. ProcessParameters->ImagePathName.Buffer = Dst;
  2000. ProcessParameters->ImagePathName.MaximumLength = DOS_MAX_PATH_LENGTH * sizeof( WCHAR );
  2001. if (NtInitialUserProcessBufferType != REG_SZ ||
  2002. (NtInitialUserProcessBufferLength != (ULONG)-1 &&
  2003. (NtInitialUserProcessBufferLength < sizeof(WCHAR) ||
  2004. NtInitialUserProcessBufferLength >
  2005. sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR)))) {
  2006. KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,
  2007. STATUS_INVALID_PARAMETER,
  2008. NtInitialUserProcessBufferType,
  2009. NtInitialUserProcessBufferLength,
  2010. sizeof(NtInitialUserProcessBuffer));
  2011. }
  2012. // Executable names with spaces don't need to
  2013. // be supported so just find the first space and
  2014. // assume it terminates the process image name.
  2015. Src = NtInitialUserProcessBuffer;
  2016. while (*Src && *Src != L' ') {
  2017. Src++;
  2018. }
  2019. ProcessParameters->ImagePathName.Length =
  2020. (USHORT)((PUCHAR)Src - (PUCHAR)NtInitialUserProcessBuffer);
  2021. RtlCopyMemory(ProcessParameters->ImagePathName.Buffer,
  2022. NtInitialUserProcessBuffer,
  2023. ProcessParameters->ImagePathName.Length);
  2024. ProcessParameters->ImagePathName.Buffer[ProcessParameters->ImagePathName.Length / sizeof(WCHAR)] = UNICODE_NULL;
  2025. Dst = (PWSTR)((PCHAR)ProcessParameters->ImagePathName.Buffer +
  2026. ProcessParameters->ImagePathName.MaximumLength
  2027. );
  2028. ProcessParameters->CommandLine.Buffer = Dst;
  2029. ProcessParameters->CommandLine.MaximumLength = DOS_MAX_PATH_LENGTH * sizeof( WCHAR );
  2030. RtlAppendUnicodeToString(&ProcessParameters->CommandLine,
  2031. NtInitialUserProcessBuffer);
  2032. #if defined(REMOTE_BOOT)
  2033. //
  2034. // Pass additional parameters for remote boot clients.
  2035. //
  2036. if (IoRemoteBootClient && !ExpInTextModeSetup) {
  2037. RtlAppendUnicodeToString(&ProcessParameters->CommandLine, L" NETBOOT");
  2038. RtlAppendUnicodeToString(&ProcessParameters->CommandLine, L" NETBOOTHAL ");
  2039. AnsiDebugString.Length = strlen(NetBootHalName);
  2040. AnsiDebugString.MaximumLength = sizeof(NetBootHalName);
  2041. AnsiDebugString.Buffer = NetBootHalName;
  2042. RtlAnsiStringToUnicodeString(&TmpUnicodeString, &AnsiDebugString, TRUE);
  2043. RtlAppendUnicodeStringToString(&ProcessParameters->CommandLine, &TmpUnicodeString);
  2044. (RtlFreeStringRoutine)(TmpUnicodeString.Buffer);
  2045. if (NetBootDisconnected) {
  2046. RtlAppendUnicodeToString(&ProcessParameters->CommandLine, L" NETBOOTDISCONNECTED");
  2047. }
  2048. if (NetBootRequiresFormat) {
  2049. RtlAppendUnicodeToString(&ProcessParameters->CommandLine, L" NETBOOTFORMAT");
  2050. }
  2051. }
  2052. #endif // defined(REMOTE_BOOT)
  2053. NullString.Buffer = L"";
  2054. NullString.Length = sizeof(WCHAR);
  2055. NullString.MaximumLength = sizeof(WCHAR);
  2056. EnvString.Buffer = ProcessParameters->Environment;
  2057. EnvString.Length = 0;
  2058. EnvString.MaximumLength = (USHORT)Size;
  2059. RtlAppendUnicodeToString( &EnvString, L"Path=" );
  2060. RtlAppendUnicodeStringToString( &EnvString, &ProcessParameters->DllPath );
  2061. RtlAppendUnicodeStringToString( &EnvString, &NullString );
  2062. UnicodeSystemDriveString = NtSystemRoot;
  2063. UnicodeSystemDriveString.Length = 2 * sizeof( WCHAR );
  2064. RtlAppendUnicodeToString( &EnvString, L"SystemDrive=" );
  2065. RtlAppendUnicodeStringToString( &EnvString, &UnicodeSystemDriveString );
  2066. RtlAppendUnicodeStringToString( &EnvString, &NullString );
  2067. RtlAppendUnicodeToString( &EnvString, L"SystemRoot=" );
  2068. RtlAppendUnicodeStringToString( &EnvString, &NtSystemRoot );
  2069. RtlAppendUnicodeStringToString( &EnvString, &NullString );
  2070. #if 0
  2071. KdPrint(( "ProcessParameters at %lx\n", ProcessParameters ));
  2072. KdPrint(( " CurDir: %wZ\n", &ProcessParameters->CurrentDirectory.DosPath ));
  2073. KdPrint(( " DllPath: %wZ\n", &ProcessParameters->DllPath ));
  2074. KdPrint(( " ImageFile: %wZ\n", &ProcessParameters->ImagePathName ));
  2075. KdPrint(( " Environ: %lx\n", ProcessParameters->Environment ));
  2076. Src = ProcessParameters->Environment;
  2077. while (*Src) {
  2078. KdPrint(( " %ws\n", Src ));
  2079. while (*Src++) {
  2080. ;
  2081. }
  2082. }
  2083. #endif
  2084. //
  2085. // Notify boot prefetcher of boot progress.
  2086. //
  2087. CcPfBeginBootPhase(PfSessionManagerInitPhase);
  2088. SessionManager = ProcessParameters->ImagePathName;
  2089. Status = RtlCreateUserProcess(
  2090. &SessionManager,
  2091. OBJ_CASE_INSENSITIVE,
  2092. RtlDeNormalizeProcessParams( ProcessParameters ),
  2093. NULL,
  2094. NULL,
  2095. NULL,
  2096. FALSE,
  2097. NULL,
  2098. NULL,
  2099. &ProcessInformation);
  2100. if (InbvBootDriverInstalled)
  2101. {
  2102. FinalizeBootLogo();
  2103. }
  2104. if (!NT_SUCCESS(Status)) {
  2105. #if DBG
  2106. sprintf(DebugBuffer,
  2107. "INIT: Unable to create Session Manager. 0x%lx\n",
  2108. Status);
  2109. RtlInitAnsiString(&AnsiDebugString, DebugBuffer);
  2110. if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDebugString,
  2111. &AnsiDebugString,
  2112. TRUE)) == FALSE) {
  2113. KeBugCheck(SESSION3_INITIALIZATION_FAILED);
  2114. }
  2115. ZwDisplayString(&UnicodeDebugString);
  2116. #endif // DBG
  2117. KeBugCheckEx(SESSION3_INITIALIZATION_FAILED,Status,0,0,0);
  2118. }
  2119. Status = ZwResumeThread(ProcessInformation.Thread,NULL);
  2120. if ( !NT_SUCCESS(Status) ) {
  2121. #if DBG
  2122. sprintf(DebugBuffer,
  2123. "INIT: Unable to resume Session Manager. 0x%lx\n",
  2124. Status);
  2125. RtlInitAnsiString(&AnsiDebugString, DebugBuffer);
  2126. if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDebugString,
  2127. &AnsiDebugString,
  2128. TRUE)) == FALSE) {
  2129. KeBugCheck(SESSION4_INITIALIZATION_FAILED);
  2130. }
  2131. ZwDisplayString(&UnicodeDebugString);
  2132. #endif // DBG
  2133. KeBugCheckEx(SESSION4_INITIALIZATION_FAILED,Status,0,0,0);
  2134. }
  2135. InbvUpdateProgressBar(100);
  2136. //
  2137. // Turn on debug output so that we can see chkdsk run.
  2138. //
  2139. InbvEnableDisplayString(TRUE);
  2140. //
  2141. // Wait five seconds for the session manager to get started or
  2142. // terminate. If the wait times out, then the session manager
  2143. // is assumed to be healthy and the zero page thread is called.
  2144. //
  2145. OldTime.QuadPart = Int32x32To64(5, -(10 * 1000 * 1000));
  2146. Status = ZwWaitForSingleObject(
  2147. ProcessInformation.Process,
  2148. FALSE,
  2149. &OldTime
  2150. );
  2151. if (Status == STATUS_SUCCESS) {
  2152. #if DBG
  2153. sprintf(DebugBuffer, "INIT: Session Manager terminated.\n");
  2154. RtlInitAnsiString(&AnsiDebugString, DebugBuffer);
  2155. RtlAnsiStringToUnicodeString(&UnicodeDebugString,
  2156. &AnsiDebugString,
  2157. TRUE);
  2158. ZwDisplayString(&UnicodeDebugString);
  2159. #endif // DBG
  2160. KeBugCheck(SESSION5_INITIALIZATION_FAILED);
  2161. }
  2162. //
  2163. // Don't need these handles anymore.
  2164. //
  2165. ZwClose( ProcessInformation.Thread );
  2166. ZwClose( ProcessInformation.Process );
  2167. //
  2168. // Free up memory used to pass arguments to session manager.
  2169. //
  2170. Size = 0;
  2171. Address = Environment;
  2172. ZwFreeVirtualMemory( NtCurrentProcess(),
  2173. (PVOID *)&Address,
  2174. &Size,
  2175. MEM_RELEASE
  2176. );
  2177. Size = 0;
  2178. Address = ProcessParameters;
  2179. ZwFreeVirtualMemory( NtCurrentProcess(),
  2180. (PVOID *)&Address,
  2181. &Size,
  2182. MEM_RELEASE
  2183. );
  2184. InitializationPhase += 1;
  2185. MmZeroPageThread();
  2186. }
  2187. NTSTATUS
  2188. CreateSystemRootLink(
  2189. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  2190. )
  2191. {
  2192. HANDLE handle;
  2193. UNICODE_STRING nameString;
  2194. OBJECT_ATTRIBUTES objectAttributes;
  2195. STRING linkString;
  2196. UNICODE_STRING linkUnicodeString;
  2197. NTSTATUS status;
  2198. UCHAR deviceNameBuffer[256];
  2199. STRING deviceNameString;
  2200. UNICODE_STRING deviceNameUnicodeString;
  2201. HANDLE linkHandle;
  2202. #if DBG
  2203. UCHAR debugBuffer[256];
  2204. STRING debugString;
  2205. UNICODE_STRING debugUnicodeString;
  2206. #endif
  2207. //
  2208. // Create the root directory object for the \ArcName directory.
  2209. //
  2210. RtlInitUnicodeString( &nameString, L"\\ArcName" );
  2211. InitializeObjectAttributes( &objectAttributes,
  2212. &nameString,
  2213. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  2214. NULL,
  2215. SePublicDefaultUnrestrictedSd );
  2216. status = NtCreateDirectoryObject( &handle,
  2217. DIRECTORY_ALL_ACCESS,
  2218. &objectAttributes );
  2219. if (!NT_SUCCESS( status )) {
  2220. KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED,status,1,0,0);
  2221. return status;
  2222. } else {
  2223. (VOID) NtClose( handle );
  2224. }
  2225. //
  2226. // Create the root directory object for the \Device directory.
  2227. //
  2228. RtlInitUnicodeString( &nameString, L"\\Device" );
  2229. InitializeObjectAttributes( &objectAttributes,
  2230. &nameString,
  2231. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  2232. NULL,
  2233. SePublicDefaultUnrestrictedSd );
  2234. status = NtCreateDirectoryObject( &handle,
  2235. DIRECTORY_ALL_ACCESS,
  2236. &objectAttributes );
  2237. if (!NT_SUCCESS( status )) {
  2238. KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED,status,2,0,0);
  2239. return status;
  2240. } else {
  2241. (VOID) NtClose( handle );
  2242. }
  2243. //
  2244. // Create the symbolic link to the root of the system directory.
  2245. //
  2246. RtlInitAnsiString( &linkString, INIT_SYSTEMROOT_LINKNAME );
  2247. status = RtlAnsiStringToUnicodeString( &linkUnicodeString,
  2248. &linkString,
  2249. TRUE);
  2250. if (!NT_SUCCESS( status )) {
  2251. KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED,status,3,0,0);
  2252. return status;
  2253. }
  2254. InitializeObjectAttributes( &objectAttributes,
  2255. &linkUnicodeString,
  2256. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  2257. NULL,
  2258. SePublicDefaultUnrestrictedSd );
  2259. //
  2260. // Use ARC device name and system path from loader.
  2261. //
  2262. sprintf( deviceNameBuffer,
  2263. "\\ArcName\\%s%s",
  2264. LoaderBlock->ArcBootDeviceName,
  2265. LoaderBlock->NtBootPathName);
  2266. deviceNameBuffer[strlen(deviceNameBuffer)-1] = '\0';
  2267. RtlInitString( &deviceNameString, deviceNameBuffer );
  2268. status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
  2269. &deviceNameString,
  2270. TRUE );
  2271. if (!NT_SUCCESS(status)) {
  2272. RtlFreeUnicodeString( &linkUnicodeString );
  2273. KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED,status,4,0,0);
  2274. return status;
  2275. }
  2276. status = NtCreateSymbolicLinkObject( &linkHandle,
  2277. SYMBOLIC_LINK_ALL_ACCESS,
  2278. &objectAttributes,
  2279. &deviceNameUnicodeString );
  2280. RtlFreeUnicodeString( &linkUnicodeString );
  2281. RtlFreeUnicodeString( &deviceNameUnicodeString );
  2282. if (!NT_SUCCESS(status)) {
  2283. KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED,status,5,0,0);
  2284. return status;
  2285. }
  2286. #if DBG
  2287. sprintf( debugBuffer, "INIT: %s => %s\n",
  2288. INIT_SYSTEMROOT_LINKNAME,
  2289. deviceNameBuffer );
  2290. RtlInitAnsiString( &debugString, debugBuffer );
  2291. status = RtlAnsiStringToUnicodeString( &debugUnicodeString,
  2292. &debugString,
  2293. TRUE );
  2294. if (NT_SUCCESS(status)) {
  2295. ZwDisplayString( &debugUnicodeString );
  2296. RtlFreeUnicodeString( &debugUnicodeString );
  2297. }
  2298. #endif // DBG
  2299. NtClose( linkHandle );
  2300. return STATUS_SUCCESS;
  2301. }
  2302. #if 0
  2303. PVOID
  2304. LookupImageBaseByName (
  2305. IN PLIST_ENTRY ListHead,
  2306. IN PSZ Name
  2307. )
  2308. /*++
  2309. Lookups BaseAddress of ImageName - returned value can be used
  2310. to find entry points via LookupEntryPoint
  2311. --*/
  2312. {
  2313. PKLDR_DATA_TABLE_ENTRY Entry;
  2314. PLIST_ENTRY Next;
  2315. PVOID Base;
  2316. ANSI_STRING ansiString;
  2317. UNICODE_STRING unicodeString;
  2318. NTSTATUS status;
  2319. Next = ListHead->Flink;
  2320. if (!Next) {
  2321. return NULL;
  2322. }
  2323. RtlInitAnsiString(&ansiString, Name);
  2324. status = RtlAnsiStringToUnicodeString( &unicodeString, &ansiString, TRUE );
  2325. if (!NT_SUCCESS (status)) {
  2326. return NULL;
  2327. }
  2328. Base = NULL;
  2329. while (Next != ListHead) {
  2330. Entry = CONTAINING_RECORD(Next, KLDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  2331. Next = Next->Flink;
  2332. if (RtlEqualUnicodeString (&unicodeString, &Entry->BaseDllName, TRUE)) {
  2333. Base = Entry->DllBase;
  2334. break;
  2335. }
  2336. }
  2337. RtlFreeUnicodeString( &unicodeString );
  2338. return Base;
  2339. }
  2340. #endif
  2341. NTSTATUS
  2342. LookupEntryPoint (
  2343. IN PVOID DllBase,
  2344. IN PSZ NameOfEntryPoint,
  2345. OUT PVOID *AddressOfEntryPoint
  2346. )
  2347. /*++
  2348. Routine Description:
  2349. Returns the address of an entry point given the DllBase and PSZ
  2350. name of the entry point in question
  2351. --*/
  2352. {
  2353. PIMAGE_EXPORT_DIRECTORY ExportDirectory;
  2354. ULONG ExportSize;
  2355. USHORT Ordinal;
  2356. PULONG Addr;
  2357. CHAR NameBuffer[64];
  2358. ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
  2359. RtlImageDirectoryEntryToData(
  2360. DllBase,
  2361. TRUE,
  2362. IMAGE_DIRECTORY_ENTRY_EXPORT,
  2363. &ExportSize);
  2364. #if DBG
  2365. if (!ExportDirectory) {
  2366. DbgPrint("LookupENtryPoint: Can't locate system Export Directory\n");
  2367. }
  2368. #endif
  2369. if ( strlen(NameOfEntryPoint) > sizeof(NameBuffer)-2 ) {
  2370. return STATUS_INVALID_PARAMETER;
  2371. }
  2372. strcpy(NameBuffer,NameOfEntryPoint);
  2373. Ordinal = NameToOrdinal(
  2374. NameBuffer,
  2375. (ULONG_PTR)DllBase,
  2376. ExportDirectory->NumberOfNames,
  2377. (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfNames),
  2378. (PUSHORT)((ULONG_PTR)DllBase + ExportDirectory->AddressOfNameOrdinals)
  2379. );
  2380. //
  2381. // If Ordinal is not within the Export Address Table,
  2382. // then DLL does not implement function.
  2383. //
  2384. if ( (ULONG)Ordinal >= ExportDirectory->NumberOfFunctions ) {
  2385. return STATUS_PROCEDURE_NOT_FOUND;
  2386. }
  2387. Addr = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfFunctions);
  2388. *AddressOfEntryPoint = (PVOID)((ULONG_PTR)DllBase + Addr[Ordinal]);
  2389. return STATUS_SUCCESS;
  2390. }
  2391. static USHORT
  2392. NameToOrdinal (
  2393. IN PSZ NameOfEntryPoint,
  2394. IN ULONG_PTR DllBase,
  2395. IN ULONG NumberOfNames,
  2396. IN PULONG NameTableBase,
  2397. IN PUSHORT NameOrdinalTableBase
  2398. )
  2399. {
  2400. ULONG SplitIndex;
  2401. LONG CompareResult;
  2402. if ( NumberOfNames == 0 ) {
  2403. return (USHORT)-1;
  2404. }
  2405. SplitIndex = NumberOfNames >> 1;
  2406. CompareResult = strcmp(NameOfEntryPoint, (PSZ)(DllBase + NameTableBase[SplitIndex]));
  2407. if ( CompareResult == 0 ) {
  2408. return NameOrdinalTableBase[SplitIndex];
  2409. }
  2410. if ( NumberOfNames == 1 ) {
  2411. return (USHORT)-1;
  2412. }
  2413. if ( CompareResult < 0 ) {
  2414. NumberOfNames = SplitIndex;
  2415. } else {
  2416. NameTableBase = &NameTableBase[SplitIndex+1];
  2417. NameOrdinalTableBase = &NameOrdinalTableBase[SplitIndex+1];
  2418. NumberOfNames = NumberOfNames - SplitIndex - 1;
  2419. }
  2420. return NameToOrdinal(NameOfEntryPoint,DllBase,NumberOfNames,NameTableBase,NameOrdinalTableBase);
  2421. }