/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ex/init.c
- * PURPOSE: Executive initalization
- *
- * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
- * and optimized/cleaned it.
- * Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ * PURPOSE: Executive Initialization Code
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Eric Kohl (ekohl@rz-online.de)
*/
+/* INCLUDES ******************************************************************/
+
#include <ntoskrnl.h>
-#include <ntos/bootvid.h>
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
+//#include <ntoskrnl/cm/newcm.h>
+#include "ntoskrnl/cm/cm.h"
+#include <ntverp.h>
/* DATA **********************************************************************/
-extern ULONG MmCoreDumpType;
-extern CHAR KiTimerSystemAuditing;
-extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
-extern ADDRESS_RANGE KeMemoryMap[64];
-extern ULONG KeMemoryMapRangeCount;
-extern ULONG_PTR FirstKrnlPhysAddr;
-extern ULONG_PTR LastKrnlPhysAddr;
-extern ULONG_PTR LastKernelAddress;
-extern LOADER_MODULE KeLoaderModules[64];
-extern PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
-extern LIST_ENTRY KiProfileListHead;
-extern LIST_ENTRY KiProfileSourceListHead;
-extern KSPIN_LOCK KiProfileLock;
-BOOLEAN SetupMode = TRUE;
-
-VOID PspPostInitSystemProcess(VOID);
+/* NT Version Info */
+ULONG NtMajorVersion = VER_PRODUCTMAJORVERSION;
+ULONG NtMinorVersion = VER_PRODUCTMINORVERSION;
+#if DBG
+ULONG NtBuildNumber = VER_PRODUCTBUILD | 0xC0000000;
+#else
+ULONG NtBuildNumber = VER_PRODUCTBUILD;
+#endif
+
+/* NT System Info */
+ULONG NtGlobalFlag;
+ULONG ExSuiteMask;
+
+/* Cm Version Info */
+ULONG CmNtSpBuildNumber;
+ULONG CmNtCSDVersion;
+ULONG CmNtCSDReleaseType;
+UNICODE_STRING CmVersionString;
+UNICODE_STRING CmCSDVersionString;
+CHAR NtBuildLab[] = KERNEL_VERSION_BUILD_STR;
+
+/* Init flags and settings */
+ULONG ExpInitializationPhase;
+BOOLEAN ExpInTextModeSetup;
+BOOLEAN IoRemoteBootClient;
+ULONG InitSafeBootMode;
+BOOLEAN InitIsWinPEMode, InitWinPEModeType;
+
+/* NT Boot Path */
+UNICODE_STRING NtSystemRoot;
+
+/* NT Initial User Application */
+WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe";
+ULONG NtInitialUserProcessBufferLength = sizeof(NtInitialUserProcessBuffer) -
+ sizeof(WCHAR);
+ULONG NtInitialUserProcessBufferType = REG_SZ;
+
+/* Boot NLS information */
+PVOID ExpNlsTableBase;
+ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
+ULONG ExpUnicodeCaseTableDataOffset;
+NLSTABLEINFO ExpNlsTableInfo;
+ULONG ExpNlsTableSize;
+PVOID ExpNlsSectionPointer;
+
+/* CMOS Timer Sanity */
+BOOLEAN ExCmosClockIsSane = TRUE;
/* FUNCTIONS ****************************************************************/
-static
-VOID
-INIT_FUNCTION
-InitSystemSharedUserPage (PCSZ ParameterLine)
+NTSTATUS
+NTAPI
+ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
- UNICODE_STRING ArcDeviceName;
- UNICODE_STRING ArcName;
- UNICODE_STRING BootPath;
- UNICODE_STRING DriveDeviceName;
- UNICODE_STRING DriveName;
- WCHAR DriveNameBuffer[20];
- PCHAR ParamBuffer;
- PWCHAR ArcNameBuffer;
- PCHAR p;
- NTSTATUS Status;
- ULONG Length;
+ UNICODE_STRING LinkName;
OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE Handle;
- ULONG i;
- BOOLEAN BootDriveFound = FALSE;
-
- /*
- * NOTE:
- * The shared user page has been zeroed-out right after creation.
- * There is NO need to do this again.
- */
- Ki386SetProcessorFeatures();
-
- /* Set the Version Data */
- SharedUserData->NtProductType = NtProductWinNt;
- SharedUserData->ProductTypeIsValid = TRUE;
- SharedUserData->NtMajorVersion = 5;
- SharedUserData->NtMinorVersion = 0;
-
- /*
- * Retrieve the current dos system path
- * (e.g.: C:\reactos) from the given arc path
- * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
- * Format: "<arc_name>\<path> [options...]"
- */
-
- /* Create local parameter line copy */
- ParamBuffer = ExAllocatePool(PagedPool, 256);
- strcpy (ParamBuffer, (char *)ParameterLine);
- DPRINT("%s\n", ParamBuffer);
-
- /* Cut options off */
- p = strchr (ParamBuffer, ' ');
- if (p) *p = 0;
- DPRINT("%s\n", ParamBuffer);
-
- /* Extract path */
- p = strchr (ParamBuffer, '\\');
- if (p) {
-
- DPRINT("Boot path: %s\n", p);
- RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
- *p = 0;
-
- } else {
-
- DPRINT("Boot path: %s\n", "\\");
- RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
- }
- DPRINT("Arc name: %s\n", ParamBuffer);
-
- /* Only ARC Name left - Build full ARC Name */
- ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
- swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
- RtlInitUnicodeString (&ArcName, ArcNameBuffer);
- DPRINT("Arc name: %wZ\n", &ArcName);
-
- /* Free ParamBuffer */
- ExFreePool (ParamBuffer);
-
- /* Allocate ARC Device Name string */
- ArcDeviceName.Length = 0;
- ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
- ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-
- /* Open the Symbolic Link */
+ HANDLE LinkHandle;
+ NTSTATUS Status;
+ ANSI_STRING AnsiName;
+ CHAR Buffer[256];
+ ANSI_STRING TargetString;
+ UNICODE_STRING TargetName;
+
+ /* Initialize the ArcName tree */
+ RtlInitUnicodeString(&LinkName, L"\\ArcName");
InitializeObjectAttributes(&ObjectAttributes,
- &ArcName,
- OBJ_OPENLINK,
+ &LinkName,
+ OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL,
- NULL);
- Status = NtOpenSymbolicLinkObject(&Handle,
- SYMBOLIC_LINK_ALL_ACCESS,
- &ObjectAttributes);
-
- /* Free the String */
- ExFreePool(ArcName.Buffer);
-
- /* Check for Success */
- if (!NT_SUCCESS(Status)) {
-
- /* Free the Strings */
- RtlFreeUnicodeString(&BootPath);
- ExFreePool(ArcDeviceName.Buffer);
- CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
- KEBUGCHECK(0);
- }
-
- /* Query the Link */
- Status = NtQuerySymbolicLinkObject(Handle,
- &ArcDeviceName,
- &Length);
- NtClose (Handle);
-
- /* Check for Success */
- if (!NT_SUCCESS(Status)) {
-
- /* Free the Strings */
- RtlFreeUnicodeString(&BootPath);
- ExFreePool(ArcDeviceName.Buffer);
- CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
- KEBUGCHECK(0);
- }
- DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
-
- /* Allocate Device Name string */
- DriveDeviceName.Length = 0;
- DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
- DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-
- /* Loop Drives */
- for (i = 0; i < 26; i++) {
-
- /* Setup the String */
- swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
- RtlInitUnicodeString(&DriveName,
- DriveNameBuffer);
-
- /* Open the Symbolic Link */
- InitializeObjectAttributes(&ObjectAttributes,
- &DriveName,
- OBJ_OPENLINK,
- NULL,
- NULL);
- Status = NtOpenSymbolicLinkObject(&Handle,
- SYMBOLIC_LINK_ALL_ACCESS,
- &ObjectAttributes);
-
- /* If it failed, skip to the next drive */
- if (!NT_SUCCESS(Status)) {
- DPRINT("Failed to open link %wZ\n", &DriveName);
- continue;
- }
+ SePublicDefaultUnrestrictedSd);
+
+ /* Create it */
+ Status = NtCreateDirectoryObject(&LinkHandle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 1, 0, 0);
+ }
- /* Query it */
- Status = NtQuerySymbolicLinkObject(Handle,
- &DriveDeviceName,
- &Length);
+ /* Close the LinkHandle */
+ NtClose(LinkHandle);
- /* If it failed, skip to the next drive */
- if (!NT_SUCCESS(Status)) {
- DPRINT("Failed to query link %wZ\n", &DriveName);
- continue;
- }
- DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
+ /* Initialize the Device tree */
+ RtlInitUnicodeString(&LinkName, L"\\Device");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &LinkName,
+ OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+ NULL,
+ SePublicDefaultUnrestrictedSd);
+
+ /* Create it */
+ Status = NtCreateDirectoryObject(&LinkHandle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 2, 0, 0);
+ }
- /* See if we've found the boot drive */
- if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
+ /* Close the LinkHandle */
+ ObCloseHandle(LinkHandle, KernelMode);
- DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
- swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
- BootDriveFound = TRUE;
- }
+ /* Create the system root symlink name */
+ RtlInitAnsiString(&AnsiName, "\\SystemRoot");
+ Status = RtlAnsiStringToUnicodeString(&LinkName, &AnsiName, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 3, 0, 0);
+ }
- /* Close this Link */
- NtClose (Handle);
+ /* Initialize the attributes for the link */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &LinkName,
+ OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+ NULL,
+ SePublicDefaultUnrestrictedSd);
+
+ /* Build the ARC name */
+ sprintf(Buffer,
+ "\\ArcName\\%s%s",
+ LoaderBlock->ArcBootDeviceName,
+ LoaderBlock->NtBootPathName);
+ Buffer[strlen(Buffer) - 1] = ANSI_NULL;
+
+ /* Convert it to Unicode */
+ RtlInitString(&TargetString, Buffer);
+ Status = RtlAnsiStringToUnicodeString(&TargetName,
+ &TargetString,
+ TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We failed, bugcheck */
+ KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 4, 0, 0);
}
- /* Free all the Strings we have in memory */
- RtlFreeUnicodeString (&BootPath);
- ExFreePool(DriveDeviceName.Buffer);
- ExFreePool(ArcDeviceName.Buffer);
+ /* Create it */
+ Status = NtCreateSymbolicLinkObject(&LinkHandle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttributes,
+ &TargetName);
- /* Make sure we found the Boot Drive */
- if (BootDriveFound == FALSE) {
+ /* Free the strings */
+ RtlFreeUnicodeString(&LinkName);
+ RtlFreeUnicodeString(&TargetName);
- DbgPrint("No system drive found!\n");
- KEBUGCHECK (NO_BOOT_DEVICE);
+ /* Check if creating the link failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 5, 0, 0);
}
-}
-inline
-VOID
-STDCALL
-ExecuteRuntimeAsserts(VOID)
-{
- /*
- * Fail at runtime if someone has changed various structures without
- * updating the offsets used for the assembler code.
- */
- ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
- ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
- ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
- ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
- ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
- ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
- ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
- ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
- ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
- ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
- ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
- ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
- ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
- ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
- ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
- ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
- ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
- ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
- ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
- ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
- ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
- ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
- ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
- ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
+ /* Close the handle and return success */
+ ObCloseHandle(LinkHandle, KernelMode);
+ return STATUS_SUCCESS;
}
-inline
VOID
-STDCALL
-ParseAndCacheLoadedModules(VOID)
+NTAPI
+ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
- ULONG i;
- PCHAR Name;
+ LARGE_INTEGER SectionSize;
+ NTSTATUS Status;
+ HANDLE NlsSection;
+ PVOID SectionBase = NULL;
+ ULONG ViewSize = 0;
+ LARGE_INTEGER SectionOffset = {{0}};
+ PLIST_ENTRY ListHead, NextEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
+
+ /* Check if this is boot-time phase 0 initialization */
+ if (!ExpInitializationPhase)
+ {
+ /* Loop the memory descriptors */
+ ListHead = &LoaderBlock->MemoryDescriptorListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current block */
+ MdBlock = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Check if this is an NLS block */
+ if (MdBlock->MemoryType == LoaderNlsData)
+ {
+ /* Increase the table size */
+ ExpNlsTableSize += MdBlock->PageCount * PAGE_SIZE;
+ }
- /* Loop the Module List and get the modules we want */
- for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
+ /* Go to the next block */
+ NextEntry = MdBlock->ListEntry.Flink;
+ }
+
+ /*
+ * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
+ * so unless someone fixes FreeLdr, we'll have to use this icky hack.
+ */
+ ExpNlsTableSize += 2 * PAGE_SIZE; // BIAS FOR FREELDR. HACK!
+
+ /* Allocate the a new buffer since loader memory will be freed */
+ ExpNlsTableBase = ExAllocatePoolWithTag(NonPagedPool,
+ ExpNlsTableSize,
+ TAG('R', 't', 'l', 'i'));
+ if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
+
+ /* Copy the codepage data in its new location. */
+ RtlCopyMemory(ExpNlsTableBase,
+ LoaderBlock->NlsData->AnsiCodePageData,
+ ExpNlsTableSize);
+
+ /* Initialize and reset the NLS TAbles */
+ RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpAnsiCodePageDataOffset),
+ (PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpOemCodePageDataOffset),
+ (PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpUnicodeCaseTableDataOffset),
+ &ExpNlsTableInfo);
+ RtlResetRtlTranslations(&ExpNlsTableInfo);
+ return;
+ }
- /* Get the Name of this Module */
- if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\'))) {
+ /* Set the section size */
+ SectionSize.QuadPart = ExpNlsTableSize;
+
+ /* Create the NLS Section */
+ Status = ZwCreateSection(&NlsSection,
+ SECTION_ALL_ACCESS,
+ NULL,
+ &SectionSize,
+ PAGE_READWRITE,
+ SEC_COMMIT,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 1, 0, 0);
+ }
- /* Save the name */
- Name = (PCHAR)KeLoaderModules[i].String;
+ /* Get a pointer to the section */
+ Status = ObReferenceObjectByHandle(NlsSection,
+ SECTION_ALL_ACCESS,
+ MmSectionObjectType,
+ KernelMode,
+ &ExpNlsSectionPointer,
+ NULL);
+ ZwClose(NlsSection);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 2, 0, 0);
+ }
- } else {
+ /* Map the NLS Section in system space */
+ Status = MmMapViewInSystemSpace(ExpNlsSectionPointer,
+ &SectionBase,
+ &ExpNlsTableSize);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 3, 0, 0);
+ }
- /* No name, skip */
- Name++;
- }
+ /* Copy the codepage data in its new location. */
+ RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
+
+ /* Free the previously allocated buffer and set the new location */
+ ExFreePool(ExpNlsTableBase);
+ ExpNlsTableBase = SectionBase;
+
+ /* Initialize the NLS Tables */
+ RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpAnsiCodePageDataOffset),
+ (PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpOemCodePageDataOffset),
+ (PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpUnicodeCaseTableDataOffset),
+ &ExpNlsTableInfo);
+ RtlResetRtlTranslations(&ExpNlsTableInfo);
+
+ /* Reset the base to 0 */
+ SectionBase = NULL;
+
+ /* Map the section in the system process */
+ Status = MmMapViewOfSection(ExpNlsSectionPointer,
+ PsGetCurrentProcess(),
+ &SectionBase,
+ 0L,
+ 0L,
+ &SectionOffset,
+ &ViewSize,
+ ViewShare,
+ 0L,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 5, 0, 0);
+ }
- /* Now check for any of the modules we will need later */
- if (!_stricmp(Name, "ansi.nls")) {
+ /* Copy the table into the system process and set this as the base */
+ RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
+ ExpNlsTableBase = SectionBase;
+}
- CachedModules[AnsiCodepage] = &KeLoaderModules[i];
+NTSTATUS
+NTAPI
+ExpLoadInitialProcess(IN OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation)
+{
+ PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
+ NTSTATUS Status;
+ ULONG Size;
+ PWSTR p;
+ UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
+ UNICODE_STRING SmssName, Environment, SystemDriveString;
+ PVOID EnvironmentPtr = NULL;
+
+ /* Allocate memory for the process parameters */
+ Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
+ ((MAX_PATH * 6) * sizeof(WCHAR));
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+ (PVOID)&ProcessParameters,
+ 0,
+ &Size,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(SESSION1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
- } else if (!_stricmp(Name, "oem.nls")) {
+ /* Setup the basic header, and give the process the low 1MB to itself */
+ ProcessParameters->Length = Size;
+ ProcessParameters->MaximumLength = Size;
+ ProcessParameters->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED |
+ RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
+
+ /* Allocate a page for the environment */
+ Size = PAGE_SIZE;
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+ &EnvironmentPtr,
+ 0,
+ &Size,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
- CachedModules[OemCodepage] = &KeLoaderModules[i];
+ /* Write the pointer */
+ ProcessParameters->Environment = EnvironmentPtr;
+
+ /* Make a buffer for the DOS path */
+ p = (PWSTR)(ProcessParameters + 1);
+ ProcessParameters->CurrentDirectory.DosPath.Buffer = p;
+ ProcessParameters->
+ CurrentDirectory.DosPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+ /* Copy the DOS path */
+ RtlCopyUnicodeString(&ProcessParameters->CurrentDirectory.DosPath,
+ &NtSystemRoot);
+
+ /* Make a buffer for the DLL Path */
+ p = (PWSTR)((PCHAR)ProcessParameters->CurrentDirectory.DosPath.Buffer +
+ ProcessParameters->CurrentDirectory.DosPath.MaximumLength);
+ ProcessParameters->DllPath.Buffer = p;
+ ProcessParameters->DllPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+ /* Copy the DLL path and append the system32 directory */
+ RtlCopyUnicodeString(&ProcessParameters->DllPath,
+ &ProcessParameters->CurrentDirectory.DosPath);
+ RtlAppendUnicodeToString(&ProcessParameters->DllPath, L"\\System32");
+
+ /* Make a buffer for the image name */
+ p = (PWSTR)((PCHAR)ProcessParameters->DllPath.Buffer +
+ ProcessParameters->DllPath.MaximumLength);
+ ProcessParameters->ImagePathName.Buffer = p;
+ ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+ /* Make sure the buffer is a valid string which within the given length */
+ if ((NtInitialUserProcessBufferType != REG_SZ) ||
+ ((NtInitialUserProcessBufferLength != -1) &&
+ ((NtInitialUserProcessBufferLength < sizeof(WCHAR)) ||
+ (NtInitialUserProcessBufferLength >
+ sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR)))))
+ {
+ /* Invalid initial process string, bugcheck */
+ KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,
+ (ULONG_PTR)STATUS_INVALID_PARAMETER,
+ NtInitialUserProcessBufferType,
+ NtInitialUserProcessBufferLength,
+ sizeof(NtInitialUserProcessBuffer));
+ }
- } else if (!_stricmp(Name, "casemap.nls")) {
+ /* Cut out anything after a space */
+ p = NtInitialUserProcessBuffer;
+ while (*p && *p != L' ') p++;
+
+ /* Set the image path length */
+ ProcessParameters->ImagePathName.Length =
+ (USHORT)((PCHAR)p - (PCHAR)NtInitialUserProcessBuffer);
+
+ /* Copy the actual buffer */
+ RtlCopyMemory(ProcessParameters->ImagePathName.Buffer,
+ NtInitialUserProcessBuffer,
+ ProcessParameters->ImagePathName.Length);
+
+ /* Null-terminate it */
+ ProcessParameters->
+ ImagePathName.Buffer[ProcessParameters->ImagePathName.Length /
+ sizeof(WCHAR)] = UNICODE_NULL;
+
+ /* Make a buffer for the command line */
+ p = (PWSTR)((PCHAR)ProcessParameters->ImagePathName.Buffer +
+ ProcessParameters->ImagePathName.MaximumLength);
+ ProcessParameters->CommandLine.Buffer = p;
+ ProcessParameters->CommandLine.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+ /* Add the image name to the command line */
+ RtlAppendUnicodeToString(&ProcessParameters->CommandLine,
+ NtInitialUserProcessBuffer);
+
+ /* Create the environment string */
+ RtlInitEmptyUnicodeString(&Environment,
+ ProcessParameters->Environment,
+ (USHORT)Size);
+
+ /* Append the DLL path to it */
+ RtlAppendUnicodeToString(&Environment, L"Path=" );
+ RtlAppendUnicodeStringToString(&Environment, &ProcessParameters->DllPath);
+ RtlAppendUnicodeStringToString(&Environment, &NullString );
+
+ /* Create the system drive string */
+ SystemDriveString = NtSystemRoot;
+ SystemDriveString.Length = 2 * sizeof(WCHAR);
+
+ /* Append it to the environment */
+ RtlAppendUnicodeToString(&Environment, L"SystemDrive=");
+ RtlAppendUnicodeStringToString(&Environment, &SystemDriveString);
+ RtlAppendUnicodeStringToString(&Environment, &NullString);
+
+ /* Append the system root to the environment */
+ RtlAppendUnicodeToString(&Environment, L"SystemRoot=");
+ RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
+ RtlAppendUnicodeStringToString(&Environment, &NullString);
+
+ /* Create SMSS process */
+ SmssName = ProcessParameters->ImagePathName;
+ Status = RtlCreateUserProcess(&SmssName,
+ OBJ_CASE_INSENSITIVE,
+ RtlDeNormalizeProcessParams(
+ ProcessParameters),
+ NULL,
+ NULL,
+ NULL,
+ FALSE,
+ NULL,
+ NULL,
+ ProcessInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(SESSION3_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
- CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
+ /* Resume the thread */
+ Status = ZwResumeThread(ProcessInformation->ThreadHandle, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed */
+ KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
- } else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv")) {
+ /* Return success */
+ return STATUS_SUCCESS;
+}
- CachedModules[SystemRegistry] = &KeLoaderModules[i];
- SetupMode = FALSE;
+ULONG
+NTAPI
+ExComputeTickCountMultiplier(IN ULONG ClockIncrement)
+{
+ ULONG MsRemainder = 0, MsIncrement;
+ ULONG IncrementRemainder;
+ ULONG i;
- } else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
+ /* Count the number of milliseconds for each clock interrupt */
+ MsIncrement = ClockIncrement / (10 * 1000);
- CachedModules[HardwareRegistry] = &KeLoaderModules[i];
+ /* Count the remainder from the division above, with 24-bit precision */
+ IncrementRemainder = ClockIncrement - (MsIncrement * (10 * 1000));
+ for (i= 0; i < 24; i++)
+ {
+ /* Shift the remainders */
+ MsRemainder <<= 1;
+ IncrementRemainder <<= 1;
+
+ /* Check if we've went past 1 ms */
+ if (IncrementRemainder >= (10 * 1000))
+ {
+ /* Increase the remainder by one, and substract from increment */
+ IncrementRemainder -= (10 * 1000);
+ MsRemainder |= 1;
}
}
+
+ /* Return the increment */
+ return (MsIncrement << 24) | MsRemainder;
}
-inline
-VOID
-STDCALL
-ParseCommandLine(PULONG MaxMem,
- PBOOLEAN NoGuiBoot,
- PBOOLEAN BootLog,
- PBOOLEAN ForceAcpiDisable)
+BOOLEAN
+NTAPI
+ExpInitSystemPhase0(VOID)
{
- PCHAR p1, p2;
+ /* Initialize EXRESOURCE Support */
+ ExpResourceInitialization();
- p1 = (PCHAR)KeLoaderBlock.CommandLine;
- while(*p1 && (p2 = strchr(p1, '/'))) {
+ /* Initialize the environment lock */
+ ExInitializeFastMutex(&ExpEnvironmentLock);
- p2++;
- if (!_strnicmp(p2, "MAXMEM", 6)) {
+ /* Initialize the lookaside lists and locks */
+ ExpInitLookasideLists();
- p2 += 6;
- while (isspace(*p2)) p2++;
+ /* Initialize the Firmware Table resource and listhead */
+ InitializeListHead(&ExpFirmwareTableProviderListHead);
+ ExInitializeResourceLite(&ExpFirmwareTableResource);
- if (*p2 == '=') {
+ /* Set the suite mask to maximum and return */
+ ExSuiteMask = 0xFFFFFFFF;
+ return TRUE;
+}
- p2++;
+BOOLEAN
+NTAPI
+ExpInitSystemPhase1(VOID)
+{
+ /* Initialize worker threads */
+ ExpInitializeWorkerThreads();
- while(isspace(*p2)) p2++;
+ /* Initialize pushlocks */
+ ExpInitializePushLocks();
- if (isdigit(*p2)) {
- while (isdigit(*p2)) {
- *MaxMem = *MaxMem * 10 + *p2 - '0';
- p2++;
- }
- break;
- }
- }
- } else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
+ /* Initialize events and event pairs */
+ ExpInitializeEventImplementation();
+ ExpInitializeEventPairImplementation();
- p2 += 9;
- *NoGuiBoot = TRUE;
+ /* Initialize callbacks */
+ ExpInitializeCallbacks();
- } else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
+ /* Initialize mutants */
+ ExpInitializeMutantImplementation();
- p2 += 9;
- if (*p2 == ':') {
+ /* Initialize semaphores */
+ ExpInitializeSemaphoreImplementation();
- p2++;
- if (!_strnicmp(p2, "FULL", 4)) {
+ /* Initialize timers */
+ ExpInitializeTimerImplementation();
- MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
+ /* Initialize profiling */
+ ExpInitializeProfileImplementation();
- } else {
+ /* Initialize UUIDs */
+ ExpInitUuids();
- MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
- }
- }
- } else if (!_strnicmp(p2, "BOOTLOG", 7)) {
+ /* Initialize Win32K */
+ ExpWin32kInit();
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+ExInitSystem(VOID)
+{
+ /* Check the initialization phase */
+ switch (ExpInitializationPhase)
+ {
+ case 0:
- p2 += 7;
- *BootLog = TRUE;
- } else if (!_strnicmp(p2, "NOACPI", 6)) {
+ /* Do Phase 0 */
+ return ExpInitSystemPhase0();
- p2 += 6;
- *ForceAcpiDisable = TRUE;
- }
+ case 1:
- p1 = p2;
+ /* Do Phase 1 */
+ return ExpInitSystemPhase1();
+
+ default:
+
+ /* Don't know any other phase! Bugcheck! */
+ KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
+ return FALSE;
}
}
-
+
+BOOLEAN
+NTAPI
+ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLOADER_PARAMETER_EXTENSION Extension;
+
+ /* Get the loader extension */
+ Extension = LoaderBlock->Extension;
+
+ /* Validate the size (larger structures are OK, we'll just ignore them) */
+ if (Extension->Size < sizeof(LOADER_PARAMETER_EXTENSION)) return FALSE;
+
+ /* Don't validate upper versions */
+ if (Extension->MajorVersion > 5) return TRUE;
+
+ /* Fail if this is NT 4 */
+ if (Extension->MajorVersion < 5) return FALSE;
+
+ /* Fail if this is XP */
+ if (Extension->MinorVersion < 2) return FALSE;
+
+ /* This is 2003 or newer, approve it */
+ return TRUE;
+}
+
VOID
-INIT_FUNCTION
-ExpDisplayNotice(VOID)
+NTAPI
+ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
- CHAR str[50];
-
- if (SetupMode)
- {
- HalDisplayString(
- "\n\n\n ReactOS " KERNEL_VERSION_STR " Setup \n");
- HalDisplayString(
- " \xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD");
- HalDisplayString(
- "\xCD\xCD\n");
- return;
+ ULONG i = 0;
+ PLIST_ENTRY NextEntry;
+ ULONG Count, Length;
+ PWCHAR Name;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ BOOLEAN OverFlow = FALSE;
+ CHAR NameBuffer[256];
+ ANSI_STRING SymbolString;
+
+ /* Loop the driver list */
+ NextEntry = LoaderBlock->LoadOrderListHead.Flink;
+ while (NextEntry != &LoaderBlock->LoadOrderListHead)
+ {
+ /* Skip the first two images */
+ if (i >= 2)
+ {
+ /* Get the entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+ if (LdrEntry->FullDllName.Buffer[0] == L'\\')
+ {
+ /* We have a name, read its data */
+ Name = LdrEntry->FullDllName.Buffer;
+ Length = LdrEntry->FullDllName.Length / sizeof(WCHAR);
+
+ /* Check if our buffer can hold it */
+ if (sizeof(NameBuffer) < Length + sizeof(ANSI_NULL))
+ {
+ /* It's too long */
+ OverFlow = TRUE;
+ }
+ else
+ {
+ /* Copy the name */
+ Count = 0;
+ do
+ {
+ /* Copy the character */
+ NameBuffer[Count++] = (CHAR)*Name++;
+ } while (Count < Length);
+
+ /* Null-terminate */
+ NameBuffer[Count] = ANSI_NULL;
+ }
+ }
+ else
+ {
+ /* This should be a driver, check if it fits */
+ if (sizeof(NameBuffer) <
+ (sizeof("\\System32\\Drivers\\") +
+ NtSystemRoot.Length / sizeof(WCHAR) - sizeof(UNICODE_NULL) +
+ LdrEntry->BaseDllName.Length / sizeof(WCHAR) +
+ sizeof(ANSI_NULL)))
+ {
+ /* Buffer too small */
+ OverFlow = TRUE;
+ while (TRUE);
+ }
+ else
+ {
+ /* Otherwise build the name. HACKED for GCC :( */
+ sprintf(NameBuffer,
+ "%S\\System32\\Drivers\\%S",
+ &SharedUserData->NtSystemRoot[2],
+ LdrEntry->BaseDllName.Buffer);
+ }
+ }
+
+ /* Check if the buffer was ok */
+ if (!OverFlow)
+ {
+ /* Initialize the ANSI_STRING for the debugger */
+ RtlInitString(&SymbolString, NameBuffer);
+
+ /* Load the symbols */
+ DbgLoadImageSymbols(&SymbolString,
+ LdrEntry->DllBase,
+ 0xFFFFFFFF);
+ }
+ }
+
+ /* Go to the next entry */
+ i++;
+ NextEntry = NextEntry->Flink;
}
-
- HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
- KERNEL_VERSION_BUILD_STR")\n");
- HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
- HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
- "Public License, and you\n");
- HalDisplayString("are welcome to change it and/or distribute copies of it "
- "under certain\n");
- HalDisplayString("conditions. There is absolutely no warranty for "
- "ReactOS.\n\n");
-
- /* Display number of Processors */
- sprintf(str,
- "Found %x system processor(s). [%lu MB Memory]\n",
- (int)KeNumberProcessors,
- (KeLoaderBlock.MemHigher + 1088)/ 1024);
- HalDisplayString(str);
-
+
+ /* Check if we should break after symbol load */
+ if (KdBreakAfterSymbolLoad) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
}
-
+
VOID
-INIT_FUNCTION
-STDCALL
-ExpInitializeExecutive(VOID)
+NTAPI
+ExpInitializeExecutive(IN ULONG Cpu,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
- UNICODE_STRING EventName;
- HANDLE InitDoneEventHandle;
- OBJECT_ATTRIBUTES ObjectAttributes;
- BOOLEAN NoGuiBoot = FALSE;
- BOOLEAN BootLog = FALSE;
- ULONG MaxMem = 0;
- BOOLEAN ForceAcpiDisable = FALSE;
- LARGE_INTEGER Timeout;
- HANDLE ProcessHandle;
- HANDLE ThreadHandle;
+ PNLS_DATA_BLOCK NlsData;
+ CHAR Buffer[256];
+ ANSI_STRING AnsiPath;
NTSTATUS Status;
+ PCHAR CommandLine, PerfMem;
+ ULONG PerfMemUsed;
+
+ /* Validate Loader */
+ if (!ExpIsLoaderValid(LoaderBlock))
+ {
+ /* Invalid loader version */
+ KeBugCheckEx(MISMATCHED_HAL,
+ 3,
+ LoaderBlock->Extension->Size,
+ LoaderBlock->Extension->MajorVersion,
+ LoaderBlock->Extension->MinorVersion);
+ }
+
+ /* Initialize PRCB pool lookaside pointers */
+ ExInitPoolLookasidePointers();
- /* Check if the structures match the ASM offset constants */
- ExecuteRuntimeAsserts();
+ /* Check if this is an application CPU */
+ if (Cpu)
+ {
+ /* Then simply initialize it with HAL */
+ if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
+ {
+ /* Initialization failed */
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ /* We're done */
+ return;
+ }
+
+ /* Assume no text-mode or remote boot */
+ ExpInTextModeSetup = FALSE;
+ IoRemoteBootClient = FALSE;
- /* Sets up the Text Sections of the Kernel and HAL for debugging */
- LdrInit1();
+ /* Check if we have a setup loader block */
+ if (LoaderBlock->SetupLdrBlock)
+ {
+ /* Check if this is text-mode setup */
+ if (LoaderBlock->SetupLdrBlock->Flags & 1) ExpInTextModeSetup = TRUE;
+
+ /* Check if this is network boot */
+ if (LoaderBlock->SetupLdrBlock->Flags & 2)
+ {
+ /* Set variable */
+ IoRemoteBootClient = TRUE;
+
+ /* Make sure we're actually booting off the network */
+ ASSERT(!_memicmp(LoaderBlock->ArcBootDeviceName, "net(0)", 6));
+ }
+ }
- /* Lower the IRQL to Dispatch Level */
- KeLowerIrql(DISPATCH_LEVEL);
+ /* Set phase to 0 */
+ ExpInitializationPhase = 0;
- /* Sets up the VDM Data */
- NtEarlyInitVdm();
+ /* Get boot command line */
+ CommandLine = LoaderBlock->LoadOptions;
+ if (CommandLine)
+ {
+ /* Upcase it for comparison and check if we're in performance mode */
+ _strupr(CommandLine);
+ PerfMem = strstr(CommandLine, "PERFMEM");
+ if (PerfMem)
+ {
+ /* Check if the user gave a number of bytes to use */
+ PerfMem = strstr(PerfMem, "=");
+ if (PerfMem)
+ {
+ /* Read the number of pages we'll use */
+ PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
+ if (PerfMem)
+ {
+ /* FIXME: TODO */
+ DPRINT1("BBT performance mode not yet supported."
+ "/PERFMEM option ignored.\n");
+ }
+ }
+ }
- /* Parse Command Line Settings */
- ParseCommandLine(&MaxMem, &NoGuiBoot, &BootLog, &ForceAcpiDisable);
+ /* Check if we're burning memory */
+ PerfMem = strstr(CommandLine, "BURNMEMORY");
+ if (PerfMem)
+ {
+ /* Check if the user gave a number of bytes to use */
+ PerfMem = strstr(PerfMem, "=");
+ if (PerfMem)
+ {
+ /* Read the number of pages we'll use */
+ PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
+ if (PerfMem)
+ {
+ /* FIXME: TODO */
+ DPRINT1("Burnable memory support not yet present."
+ "/BURNMEM option ignored.\n");
+ }
+ }
+ }
+ }
- /* Initialize Kernel Memory Address Space */
- MmInit1(FirstKrnlPhysAddr,
- LastKrnlPhysAddr,
- LastKernelAddress,
- (PADDRESS_RANGE)&KeMemoryMap,
- KeMemoryMapRangeCount,
- MaxMem > 8 ? MaxMem : 4096);
+ /* Setup NLS Base and offsets */
+ NlsData = LoaderBlock->NlsData;
+ ExpNlsTableBase = NlsData->AnsiCodePageData;
+ ExpAnsiCodePageDataOffset = 0;
+ ExpOemCodePageDataOffset = ((ULONG_PTR)NlsData->OemCodePageData -
+ (ULONG_PTR)NlsData->AnsiCodePageData);
+ ExpUnicodeCaseTableDataOffset = ((ULONG_PTR)NlsData->UnicodeCodePageData -
+ (ULONG_PTR)NlsData->AnsiCodePageData);
+
+ /* Initialize the NLS Tables */
+ RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpAnsiCodePageDataOffset),
+ (PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpOemCodePageDataOffset),
+ (PVOID)((ULONG_PTR)ExpNlsTableBase +
+ ExpUnicodeCaseTableDataOffset),
+ &ExpNlsTableInfo);
+ RtlResetRtlTranslations(&ExpNlsTableInfo);
+
+ /* Now initialize the HAL */
+ if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
+ {
+ /* HAL failed to initialize, bugcheck */
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
- /* Parse the Loaded Modules (by FreeLoader) and cache the ones we'll need */
- ParseAndCacheLoadedModules();
+ /* Make sure interrupts are active now */
+ _enable();
+ /* Clear the crypto exponent */
+ SharedUserData->CryptoExponent = 0;
- /* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
- KeInit2();
+ /* Set global flags for the checked build */
+#if DBG
+ NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
+ FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
+#endif
- /* Bring back the IRQL to Passive */
- KeLowerIrql(PASSIVE_LEVEL);
+ /* Setup NT System Root Path */
+ sprintf(Buffer, "C:%s", LoaderBlock->NtBootPathName);
- /* Initialize Profiling */
- InitializeListHead(&KiProfileListHead);
- InitializeListHead(&KiProfileSourceListHead);
- KeInitializeSpinLock(&KiProfileLock);
+ /* Convert to ANSI_STRING and null-terminate it */
+ RtlInitString(&AnsiPath, Buffer );
+ Buffer[--AnsiPath.Length] = ANSI_NULL;
- /* Load basic Security for other Managers */
- if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
+ /* Get the string from KUSER_SHARED_DATA's buffer */
+ RtlInitEmptyUnicodeString(&NtSystemRoot,
+ SharedUserData->NtSystemRoot,
+ sizeof(SharedUserData->NtSystemRoot));
- /* Create the Basic Object Manager Types to allow new Object Types */
- ObInit();
+ /* Now fill it in */
+ Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
+ if (!NT_SUCCESS(Status)) KEBUGCHECK(SESSION3_INITIALIZATION_FAILED);
- /* Initialize Lookaside Lists */
- ExInit2();
+ /* Setup bugcheck messages */
+ KiInitializeBugCheck();
- /* Set up Region Maps, Sections and the Paging File */
- MmInit2();
+ /* Setup initial system settings (FIXME: Needs Cm Rewrite) */
+ CmGetSystemControlValues(LoaderBlock->RegistryBase, CmControlVector);
- /* Initialize Tokens now that the Object Manager is ready */
- if (!SeInit2()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
+ /* Initialize the executive at phase 0 */
+ if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED);
- /* Set 1 CPU for now, we'll increment this later */
- KeNumberProcessors = 1;
-
- /* Initalize the Process Manager */
- PiInitProcessManager();
-
- /* Break into the Debugger if requested */
- if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
+ /* Initialize the memory manager at phase 0 */
+ if (!MmInitSystem(0, LoaderBlock)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED);
- /* Initialize all processors */
- while (!HalAllProcessorsStarted()) {
+ /* Load boot symbols */
+ ExpLoadBootSymbols(LoaderBlock);
- PVOID ProcessorStack;
+ /* Set system ranges */
+ SharedUserData->Reserved1 = (ULONG_PTR)MmHighestUserAddress;
+ SharedUserData->Reserved3 = (ULONG_PTR)MmSystemRangeStart;
- /* Set up the Kernel and Process Manager for this CPU */
- KePrepareForApplicationProcessorInit(KeNumberProcessors);
- KeCreateApplicationProcessorIdleThread(KeNumberProcessors);
+ /* Make a copy of the NLS Tables */
+ ExpInitNls(LoaderBlock);
- /* Allocate a stack for use when booting the processor */
- ProcessorStack = RVA(Ki386InitialStackArray[((int)KeNumberProcessors)], MM_STACK_SIZE);
+ /* Check if the user wants a kernel stack trace database */
+ if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB)
+ {
+ /* FIXME: TODO */
+ DPRINT1("Kernel-mode stack trace support not yet present."
+ "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
+ }
- /* Tell HAL a new CPU is being started */
- HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
- KeNumberProcessors++;
+ /* Check if he wanted exception logging */
+ if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING)
+ {
+ /* FIXME: TODO */
+ DPRINT1("Kernel-mode exception logging support not yet present."
+ "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
}
- /* Do Phase 1 HAL Initalization */
- HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+ /* Initialize the Handle Table */
+ ExpInitializeHandleTables();
- /* Initialize Basic System Objects and Worker Threads */
- ExInit3();
+#if DBG
+ /* On checked builds, allocate the system call count table */
+ KeServiceDescriptorTable[0].Count =
+ ExAllocatePoolWithTag(NonPagedPool,
+ KiServiceLimit * sizeof(ULONG),
+ TAG('C', 'a', 'l', 'l'));
- /* Create the system handle table, assign it to the system process, create
- the client id table and assign a PID for the system process. This needs
- to be done before the worker threads are initialized so the system
- process gets the first PID (4) */
- PspPostInitSystemProcess();
+ /* Use it for the shadow table too */
+ KeServiceDescriptorTableShadow[0].Count = KeServiceDescriptorTable[0].Count;
- /* initialize the worker threads */
- ExpInitializeWorkerThreads();
+ /* Make sure allocation succeeded */
+ if (KeServiceDescriptorTable[0].Count)
+ {
+ /* Zero the call counts to 0 */
+ RtlZeroMemory(KeServiceDescriptorTable[0].Count,
+ KiServiceLimit * sizeof(ULONG));
+ }
+#endif
- /* initialize callbacks */
- ExpInitializeCallbacks();
+ /* Create the Basic Object Manager Types to allow new Object Types */
+ if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED);
- /* Call KD Providers at Phase 1 */
- KdInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+ /* Load basic Security for other Managers */
+ if (!SeInit()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
+
+ /* Initialize the Process Manager */
+ if (!PsInitSystem(LoaderBlock)) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED);
+
+ /* Initialize the PnP Manager */
+ if (!PpInitSystem()) KEBUGCHECK(PP0_INITIALIZATION_FAILED);
+
+ /* Initialize the User-Mode Debugging Subsystem */
+ DbgkInitialize();
+
+ /* Calculate the tick count multiplier */
+ ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement);
+ SharedUserData->TickCountMultiplier = ExpTickCountMultiplier;
+
+ /* Set the OS Version */
+ SharedUserData->NtMajorVersion = NtMajorVersion;
+ SharedUserData->NtMinorVersion = NtMinorVersion;
+
+ /* Set the machine type */
+#if defined(_X86_)
+ SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_I386;
+ SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_I386;
+#elif defined(_PPC_) // <3 Arty
+ SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_POWERPC;
+ SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_POWERPC;
+#elif
+#error "Unsupported ReactOS Target"
+#endif
+}
- /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
- IoInit();
+VOID
+NTAPI
+Phase1InitializationDiscard(PVOID Context)
+{
+ PLOADER_PARAMETER_BLOCK LoaderBlock = Context;
+ PCHAR CommandLine, Y2KHackRequired;
+ LARGE_INTEGER Timeout;
+ NTSTATUS Status;
+ TIME_FIELDS TimeFields;
+ LARGE_INTEGER SystemBootTime, UniversalBootTime, OldTime;
+ PRTL_USER_PROCESS_INFORMATION ProcessInfo;
+ BOOLEAN SosEnabled, NoGuiBoot;
+ ULONG YearHack = 0;
+
+ /* Allocate initial process information */
+ ProcessInfo = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(RTL_USER_PROCESS_INFORMATION),
+ TAG('I', 'n', 'i', 't'));
+ if (!ProcessInfo)
+ {
+ /* Bugcheck */
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 8, 0, 0);
+ }
- /* TBD */
- PoInit((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock, ForceAcpiDisable);
+ /* Set to phase 1 */
+ ExpInitializationPhase = 1;
- /* Initialize the Registry (Hives are NOT yet loaded!) */
- CmInitializeRegistry();
+ /* Set us at maximum priority */
+ KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY);
- /* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
- MmInit3();
+ /* Do Phase 1 HAL Initialization */
+ if (!HalInitSystem(1, LoaderBlock)) KeBugCheck(HAL1_INITIALIZATION_FAILED);
- /* Initialize Cache Views */
- CcInit();
+ /* Get the command line and upcase it */
+ CommandLine = _strupr(LoaderBlock->LoadOptions);
- /* Initialize File Locking */
- FsRtlpInitFileLockingImplementation();
+ /* Check if GUI Boot is enabled */
+ NoGuiBoot = (strstr(CommandLine, "NOGUIBOOT")) ? TRUE: FALSE;
- /* Report all resources used by hal */
- HalReportResourceUsage();
-
- /* Clear the screen to blue */
- HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+ /* Get the SOS setting */
+ SosEnabled = strstr(CommandLine, "SOS") ? TRUE: FALSE;
- /* Display version number and copyright/warranty message */
- ExpDisplayNotice();
+ /* Setup the boot driver */
+ InbvEnableBootDriver(!NoGuiBoot);
+ InbvDriverInitialize(LoaderBlock, 18);
- /* Call KD Providers at Phase 2 */
- KdInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+ /* Check if GUI boot is enabled */
+ if (!NoGuiBoot)
+ {
+ /* It is, display the boot logo and enable printing strings */
+ InbvEnableDisplayString(SosEnabled);
+ DisplayBootBitmap(SosEnabled);
+ }
+ else
+ {
+ /* Release display ownership if not using GUI boot */
+ InbvNotifyDisplayOwnershipLost(NULL);
- /* Import and create NLS Data and Sections */
- RtlpInitNls();
+ /* Don't allow boot-time strings */
+ InbvEnableDisplayString(FALSE);
+ }
- /* Import and Load Registry Hives */
- CmInitHives(SetupMode);
+ /* Check if this is LiveCD (WinPE) mode */
+ if (strstr(CommandLine, "MININT"))
+ {
+ /* Setup WinPE Settings */
+ InitIsWinPEMode = TRUE;
+ InitWinPEModeType |= (strstr(CommandLine, "INRAM")) ? 0x80000000 : 1;
+ }
- /* Initialize the time zone information from the registry */
- ExpInitTimeZoneInfo();
+ /* FIXME: Print product name, version, and build */
- /* Enter the kernel debugger before starting up the boot drivers */
- if (KdDebuggerEnabled) KdbEnter();
+ /* Initialize Power Subsystem in Phase 0 */
+ if (!PoInitSystem(0, AcpiTableDetected)) KeBugCheck(INTERNAL_POWER_ERROR);
- /* Setup Drivers and Root Device Node */
- IoInit2(BootLog);
+ /* Check for Y2K hack */
+ Y2KHackRequired = strstr(CommandLine, "YEAR");
+ if (Y2KHackRequired) Y2KHackRequired = strstr(Y2KHackRequired, "=");
+ if (Y2KHackRequired) YearHack = atol(Y2KHackRequired + 1);
- /* Display the boot screen image if not disabled */
- if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
+ /* Query the clock */
+ if ((ExCmosClockIsSane) && (HalQueryRealTimeClock(&TimeFields)))
+ {
+ /* Check if we're using the Y2K hack */
+ if (Y2KHackRequired) TimeFields.Year = (CSHORT)YearHack;
+
+ /* Convert to time fields */
+ RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
+ UniversalBootTime = SystemBootTime;
+
+#if 0 // FIXME: Won't work until we can read registry data here
+ /* FIXME: This assumes that the RTC is not already in GMT */
+ ExpTimeZoneBias.QuadPart = Int32x32To64(ExpLastTimeZoneBias * 60,
+ 10000000);
+
+ /* Set the boot time-zone bias */
+ SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
+ SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
+ SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
+
+ /* Convert the boot time to local time, and set it */
+ UniversalBootTime.QuadPart = SystemBootTime.QuadPart +
+ ExpTimeZoneBias.QuadPart;
+#endif
+
+ /* Update the system time */
+ KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
+
+ /* Remember this as the boot time */
+ KeBootTime = UniversalBootTime;
+ KeBootTimeBias = 0;
+ }
- /* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
- IoInit3();
+ /* Initialize all processors */
+ if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED);
- /* Load the System DLL and its Entrypoints */
- LdrpInitializeSystemDll();
+ /* FIXME: Print CPU and Memory */
- /* Initialize the Default Locale */
- PiInitDefaultLocale();
+ /* Update the progress bar */
+ InbvUpdateProgressBar(5);
- /* Initialize shared user page. Set dos system path, dos device map, etc. */
- InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
+ /* Call OB initialization again */
+ if (!ObInit()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
- /* Create 'ReactOSInitDone' event */
- RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
- InitializeObjectAttributes(&ObjectAttributes,
- &EventName,
- 0,
- NULL,
- NULL);
- Status = ZwCreateEvent(&InitDoneEventHandle,
- EVENT_ALL_ACCESS,
- &ObjectAttributes,
- SynchronizationEvent,
- FALSE);
+ /* Initialize Basic System Objects and Worker Threads */
+ if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 1, 0);
- /* Check for Success */
- if (!NT_SUCCESS(Status)) {
+ /* Initialize the later stages of the kernel */
+ if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 2, 0);
- DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
- InitDoneEventHandle = INVALID_HANDLE_VALUE;
+ /* Call KD Providers at Phase 1 */
+ if (!KdInitSystem(ExpInitializationPhase, KeLoaderBlock))
+ {
+ /* Failed, bugcheck */
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 3, 0);
}
- /* Launch initial process */
- Status = LdrLoadInitialProcess(&ProcessHandle,
- &ThreadHandle);
+ /* Initialize the SRM in Phase 1 */
+ if (!SeInit()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
- /* Check for success, Bugcheck if we failed */
- if (!NT_SUCCESS(Status)) {
+ /* Update the progress bar */
+ InbvUpdateProgressBar(10);
- KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ /* Create SystemRoot Link */
+ Status = ExpCreateSystemRootLink(LoaderBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to create the system root link */
+ KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0);
}
- /* Wait on the Completion Event */
- if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
+ /* Set up Region Maps, Sections and the Paging File */
+ if (!MmInitSystem(1, LoaderBlock)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED);
+
+ /* Create NLS section */
+ ExpInitNls(KeLoaderBlock);
- HANDLE Handles[2]; /* Init event, Initial process */
+ /* Initialize Cache Views */
+ if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED);
- /* Setup the Handles to wait on */
- Handles[0] = InitDoneEventHandle;
- Handles[1] = ProcessHandle;
+ /* Initialize the Registry */
+ if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED);
- /* Wait for the system to be initialized */
- Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
- Status = ZwWaitForMultipleObjects(2,
- Handles,
- WaitAny,
- FALSE,
- &Timeout);
- if (!NT_SUCCESS(Status)) {
+ /* Update progress bar */
+ InbvUpdateProgressBar(15);
- DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
+ /* Update timezone information */
+ ExRefreshTimeZoneInformation(&SystemBootTime);
- } else if (Status == STATUS_TIMEOUT) {
+ /* Initialize the File System Runtime Library */
+ if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED);
- DPRINT1("WARNING: System not initialized after 120 seconds.\n");
+ /* Report all resources used by HAL */
+ HalReportResourceUsage();
- } else if (Status == STATUS_WAIT_0 + 1) {
+ /* Call the debugger DLL once we have KD64 6.0 support */
+ //KdDebuggerInitialize1(LoaderBlock);
- /* Crash the system if the initial process was terminated. */
- KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
- }
+ /* Setup PnP Manager in phase 1 */
+ if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED);
+
+ /* Update progress bar */
+ InbvUpdateProgressBar(20);
+
+ /* Initialize LPC */
+ if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED);
+
+ /* Initialize the I/O Subsystem */
+ if (!IoInitSystem(KeLoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);
+
+ /* Unmap Low memory, and initialize the MPW and Balancer Thread */
+ MmInitSystem(2, LoaderBlock);
+
+ /* Update progress bar */
+ InbvUpdateProgressBar(80);
+
+ /* Initialize VDM support */
+ KeI386VdmInitialize();
- /* Disable the Boot Logo */
- if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
+ /* Initialize Power Subsystem in Phase 1*/
+ if (!PoInitSystem(1, AcpiTableDetected)) KeBugCheck(INTERNAL_POWER_ERROR);
- /* Signal the Event and close the handle */
- ZwSetEvent(InitDoneEventHandle, NULL);
- ZwClose(InitDoneEventHandle);
+ /* Initialize the Process Manager at Phase 1 */
+ if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
- } else {
+ /* Update progress bar */
+ InbvUpdateProgressBar(85);
- /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
- if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
+ /* Make sure nobody touches the loader block again */
+ if (LoaderBlock == KeLoaderBlock) KeLoaderBlock = NULL;
+ LoaderBlock = Context = NULL;
- /* Crash the system if the initial process terminates within 5 seconds. */
- Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
- Status = ZwWaitForSingleObject(ProcessHandle,
- FALSE,
- &Timeout);
+ /* Update progress bar */
+ InbvUpdateProgressBar(90);
- /* Check for timeout, crash if the initial process didn't initalize */
- if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
+ /* Launch initial process */
+ Status = ExpLoadInitialProcess(ProcessInfo);
+
+ /* Update progress bar */
+ InbvUpdateProgressBar(100);
+
+ /* Allow strings to be displayed */
+ InbvEnableDisplayString(TRUE);
+
+ /* Wait 5 seconds for it to initialize */
+ Timeout.QuadPart = Int32x32To64(5, -10000000);
+ Status = ZwWaitForSingleObject(ProcessInfo->ProcessHandle, FALSE, &Timeout);
+ if (InbvBootDriverInstalled) FinalizeBootLogo();
+
+ if (Status == STATUS_SUCCESS)
+ {
+ /* Bugcheck the system if SMSS couldn't initialize */
+ KeBugCheck(SESSION5_INITIALIZATION_FAILED);
}
- /* Enable the Clock, close remaining handles */
- KiTimerSystemAuditing = 1;
- ZwClose(ThreadHandle);
- ZwClose(ProcessHandle);
-}
+ /* Close process handles */
+ ZwClose(ProcessInfo->ThreadHandle);
+ ZwClose(ProcessInfo->ProcessHandle);
-VOID INIT_FUNCTION
-ExInit2(VOID)
-{
- ExpInitLookasideLists();
+ /* FIXME: We should free the initial process' memory!*/
+
+ /* Increase init phase */
+ ExpInitializationPhase += 1;
+
+ /* Free the process information */
+ ExFreePool(ProcessInfo);
}
-VOID INIT_FUNCTION
-ExInit3 (VOID)
+VOID
+NTAPI
+Phase1Initialization(IN PVOID Context)
{
- ExpInitializeEventImplementation();
- ExpInitializeEventPairImplementation();
- ExpInitializeMutantImplementation();
- ExpInitializeSemaphoreImplementation();
- ExpInitializeTimerImplementation();
- LpcpInitSystem();
- ExpInitializeProfileImplementation();
- ExpWin32kInit();
- ExpInitUuids();
- ExpInitializeHandleTables();
+ /* Do the .INIT part of Phase 1 which we can free later */
+ Phase1InitializationDiscard(Context);
+
+ /* Jump into zero page thread */
+ MmZeroPageThreadMain(NULL);
}
-/* EOF */