BOOLEAN WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN LPCSTR DirectoryPath) { CHAR SearchPath[1024]; BOOLEAN Success; // There is a simple logic here: try to load usual hive (system), if it // fails, then give system.alt a try, and finally try a system.sav // FIXME: For now we only try system strcpy(SearchPath, DirectoryPath); strcat(SearchPath, "SYSTEM32\\CONFIG\\"); Success = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM"); // Fail if failed... if (!Success) return FALSE; // Import what was loaded Success = RegImportBinaryHive(VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength); if (!Success) { UiMessageBox("Importing binary hive failed!"); return FALSE; } // Initialize the 'CurrentControlSet' link if (RegInitCurrentControlSet(FALSE) != ERROR_SUCCESS) { UiMessageBox("Initializing CurrentControlSet link failed!"); return FALSE; } return TRUE; }
VOID LoadAndBootDrive(IN OperatingSystemItem* OperatingSystem, IN USHORT OperatingSystemVersion) { ULONG_PTR SectionId; PCSTR SectionName = OperatingSystem->SystemPartition; CHAR SettingName[80]; CHAR SettingValue[80]; UCHAR DriveNumber; // Find all the message box settings and run them UiShowMessageBoxesInSection(SectionName); // Try to open the operating system section in the .ini file if (!IniOpenSection(SectionName, &SectionId)) { sprintf(SettingName, "Section [%s] not found in freeldr.ini.\n", SectionName); UiMessageBox(SettingName); return; } if (!IniReadSettingByName(SectionId, "BootDrive", SettingValue, sizeof(SettingValue))) { UiMessageBox("Boot drive not specified for selected OS!"); return; } DriveNumber = DriveMapGetBiosDriveNumber(SettingValue); // Now try to read the boot sector (or mbr) // If this fails then abort if (!MachDiskReadLogicalSectors(DriveNumber, 0, 1, (PVOID)0x7C00)) { UiMessageBox("Unable to read boot sector"); return; } // Check for validity if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55) { UiMessageBox("Invalid boot sector magic (0xaa55)"); return; } UiUnInitialize("Booting..."); // Don't stop the floppy drive motor when we // are just booting a bootsector, or drive, or partition. // If we were to stop the floppy motor then // the BIOS wouldn't be informed and if the // next read is to a floppy then the BIOS will // still think the motor is on and this will // result in a read error. //DiskStopFloppyMotor(); //DisableA20(); ChainLoadBiosBootSectorCode(); }
BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN LPCSTR DirectoryPath) { CHAR SearchPath[1024]; CHAR AnsiName[256], OemName[256], LangName[256]; BOOLEAN Status; // Scan registry and prepare boot drivers list WinLdrScanRegistry(LoaderBlock, DirectoryPath); // Get names of NLS files Status = WinLdrGetNLSNames(AnsiName, OemName, LangName); if (!Status) { UiMessageBox("Getting NLS names from registry failed!"); return FALSE; } TRACE("NLS data %s %s %s\n", AnsiName, OemName, LangName); // Load NLS data strcpy(SearchPath, DirectoryPath); strcat(SearchPath, "SYSTEM32\\"); Status = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName); TRACE("NLS data loaded with status %d\n", Status); /* TODO: Load OEM HAL font */ return TRUE; }
VOID OptionMenuCustomBootPartition(VOID) { ULONG_PTR SectionId; CHAR SectionName[100]; CHAR BootDriveString[20]; CHAR BootPartitionString[20]; TIMEINFO* TimeInfo; OperatingSystemItem OperatingSystem; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString)); if (!UiEditBox(BootDrivePrompt, BootDriveString, 20)) { return; } if (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20)) { return; } // Generate a unique section name TimeInfo = ArcGetTime(); sprintf(SectionName, "CustomBootPartition%u%u%u%u%u%u", TimeInfo->Year, TimeInfo->Day, TimeInfo->Month, TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second); // Add the section if (!IniAddSection(SectionName, &SectionId)) { return; } // Add the BootType if (!IniAddSettingValueToSection(SectionId, "BootType", "Partition")) { return; } // Add the BootDrive if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString)) { return; } // Add the BootPartition if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootPartitionString)) { return; } UiMessageBox(CustomBootPrompt); OperatingSystem.SystemPartition = SectionName; OperatingSystem.LoadIdentifier = NULL; OperatingSystem.OsLoadOptions = NULL; // LoadAndBootPartition(&OperatingSystem, 0); LoadOperatingSystem(&OperatingSystem); }
VOID MmInitializeHeap(PVOID PageLookupTable) { ULONG PagesNeeded; ULONG HeapStart; #ifndef _M_ARM MEMORY_TYPE Type; PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; // HACK: Make it so it doesn't overlap kernel space Type = RealPageLookupTable[0x100].PageAllocated; MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, LoaderSystemCode); #endif // Find contigious memory block for HEAP:STACK PagesNeeded = HEAP_PAGES + STACK_PAGES; HeapStart = MmFindAvailablePages(PageLookupTable, TotalPagesInLookupTable, PagesNeeded, FALSE); #ifndef _M_ARM // Unapply the hack MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, Type); #endif if (HeapStart == 0) { UiMessageBox("Critical error: Can't allocate heap!"); return; } // Initialize BGET bpool(HeapStart << MM_PAGE_SHIFT, PagesNeeded << MM_PAGE_SHIFT); // Mark those pages as used MmMarkPagesInLookupTable(PageLookupTableAddress, HeapStart, PagesNeeded, LoaderOsloaderHeap); TRACE("Heap initialized, base 0x%08x, pages %d\n", (HeapStart << MM_PAGE_SHIFT), PagesNeeded); }
// Init "phase 0" VOID AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock) { PLOADER_PARAMETER_BLOCK LoaderBlock; /* Allocate and zero-init the LPB */ WinLdrSystemBlock = MmAllocateMemoryWithType(sizeof(LOADER_SYSTEM_BLOCK), LoaderSystemBlock); if (WinLdrSystemBlock == NULL) { UiMessageBox("Failed to allocate memory for system block!"); return; } RtlZeroMemory(WinLdrSystemBlock, sizeof(LOADER_SYSTEM_BLOCK)); LoaderBlock = &WinLdrSystemBlock->LoaderBlock; LoaderBlock->NlsData = &WinLdrSystemBlock->NlsDataBlock; /* Init three critical lists, used right away */ InitializeListHead(&LoaderBlock->LoadOrderListHead); InitializeListHead(&LoaderBlock->MemoryDescriptorListHead); InitializeListHead(&LoaderBlock->BootDriverListHead); *OutLoaderBlock = LoaderBlock; }
VOID OptionMenuReboot(VOID) { UiMessageBox("The system will now reboot."); DiskStopFloppyMotor(); Reboot(); }
ULONG MsgBoxPrint(const char *Format, ...) { va_list ap; CHAR Buffer[512]; ULONG Length; va_start(ap, Format); /* Construct a string */ Length = _vsnprintf(Buffer, 512, Format, ap); /* Check if we went past the buffer */ if (Length == MAXULONG) { /* Terminate it if we went over-board */ Buffer[sizeof(Buffer) - 1] = '\n'; /* Put maximum */ Length = sizeof(Buffer); } /* Show it as a message box */ UiMessageBox(Buffer); /* Cleanup and exit */ va_end(ap); return 0; }
VOID OptionMenuReboot(VOID) { UiMessageBox("The system will now reboot."); #if defined(__i386__) || defined(_M_AMD64) DiskStopFloppyMotor(); #endif Reboot(); }
BOOLEAN WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, LPCSTR BootPath) { PLIST_ENTRY NextBd; PBOOT_DRIVER_LIST_ENTRY BootDriver; BOOLEAN Success; BOOLEAN ret = TRUE; // Walk through the boot drivers list NextBd = LoaderBlock->BootDriverListHead.Flink; while (NextBd != &LoaderBlock->BootDriverListHead) { BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link); TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, BootDriver->LdrEntry, &BootDriver->RegistryPath); // Paths are relative (FIXME: Are they always relative?) // Load it Success = WinLdrLoadDeviceDriver(&LoaderBlock->LoadOrderListHead, BootPath, &BootDriver->FilePath, 0, &BootDriver->LdrEntry); if (Success) { // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer); BootDriver->FilePath.Buffer = PaToVa(BootDriver->FilePath.Buffer); BootDriver->LdrEntry = PaToVa(BootDriver->LdrEntry); } else { // Loading failed - cry loudly ERR("Can't load boot driver '%wZ'!\n", &BootDriver->FilePath); UiMessageBox("Can't load boot driver '%wZ'!", &BootDriver->FilePath); ret = FALSE; // Remove it from the list and try to continue RemoveEntryList(NextBd); } NextBd = BootDriver->Link.Flink; } return ret; }
VOID UiShowMessageBoxesInSection(PCSTR SectionName) { ULONG Idx; CHAR SettingName[80]; CHAR SettingValue[80]; PCHAR MessageBoxText; ULONG MessageBoxTextSize; ULONG_PTR SectionId; if (!IniOpenSection(SectionName, &SectionId)) { return; } // // Find all the message box settings and run them // for (Idx=0; Idx<IniGetNumSectionItems(SectionId); Idx++) { IniReadSettingByNumber(SectionId, Idx, SettingName, sizeof(SettingName), SettingValue, sizeof(SettingValue)); if (_stricmp(SettingName, "MessageBox") == 0) { // Get the real length of the MessageBox text MessageBoxTextSize = IniGetSectionSettingValueSize(SectionId, Idx); //if (MessageBoxTextSize > 0) { // Allocate enough memory to hold the text MessageBoxText = MmHeapAlloc(MessageBoxTextSize); if (MessageBoxText) { // Get the MessageBox text IniReadSettingByNumber(SectionId, Idx, SettingName, sizeof(SettingName), MessageBoxText, MessageBoxTextSize); // Fix it up UiEscapeString(MessageBoxText); // Display it UiMessageBox(MessageBoxText); // Free the memory MmHeapFree(MessageBoxText); } } } } }
VOID LoadAndBootBootSector(IN OperatingSystemItem* OperatingSystem, IN USHORT OperatingSystemVersion) { ULONG_PTR SectionId; PCSTR SectionName = OperatingSystem->SystemPartition; CHAR FileName[260]; PFILE FilePointer; ULONG BytesRead; CHAR SettingName[80]; // Find all the message box settings and run them UiShowMessageBoxesInSection(SectionName); // Try to open the operating system section in the .ini file if (!IniOpenSection(SectionName, &SectionId)) { sprintf(SettingName, "Section [%s] not found in freeldr.ini.\n", SectionName); UiMessageBox(SettingName); return; } if (!IniReadSettingByName(SectionId, "BootSectorFile", FileName, sizeof(FileName))) { UiMessageBox("Boot sector file not specified for selected OS!"); return; } FilePointer = FsOpenFile(FileName); if (!FilePointer) { strcat(FileName, " not found."); UiMessageBox(FileName); return; } // Read boot sector if (!FsReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512)) { UiMessageBox("Unable to read boot sector."); return; } // Check for validity if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55) { UiMessageBox("Invalid boot sector magic (0xaa55)"); return; } UiUnInitialize("Booting..."); // Don't stop the floppy drive motor when we // are just booting a bootsector, or drive, or partition. // If we were to stop the floppy motor then // the BIOS wouldn't be informed and if the // next read is to a floppy then the BIOS will // still think the motor is on and this will // result in a read error. //DiskStopFloppyMotor(); //DisableA20(); ChainLoadBiosBootSectorCode(); }
/* * WinLdrLoadImage loads the specified image from the file (it doesn't * perform any additional operations on the filename, just directly * calls the file I/O routines), and relocates it so that it's ready * to be used when paging is enabled. * Addressing mode: physical */ BOOLEAN WinLdrLoadImage(IN PCHAR FileName, TYPE_OF_MEMORY MemoryType, OUT PVOID *ImageBasePA) { ULONG FileId; PVOID PhysicalBase; PVOID VirtualBase = NULL; UCHAR HeadersBuffer[SECTOR_SIZE * 2]; PIMAGE_NT_HEADERS NtHeaders; PIMAGE_SECTION_HEADER SectionHeader; ULONG VirtualSize, SizeOfRawData, NumberOfSections; ARC_STATUS Status; LARGE_INTEGER Position; ULONG i, BytesRead; TRACE("WinLdrLoadImage(%s, %ld, *)\n", FileName, MemoryType); /* Open the image file */ Status = ArcOpen(FileName, OpenReadOnly, &FileId); if (Status != ESUCCESS) { // UiMessageBox("Can not open the file."); return FALSE; } /* Load the first 2 sectors of the image so we can read the PE header */ Status = ArcRead(FileId, HeadersBuffer, SECTOR_SIZE * 2, &BytesRead); if (Status != ESUCCESS) { UiMessageBox("Error reading from file."); ArcClose(FileId); return FALSE; } /* Now read the MZ header to get the offset to the PE Header */ NtHeaders = RtlImageNtHeader(HeadersBuffer); if (!NtHeaders) { // Print(L"Error - no NT header found in %s\n", FileName); UiMessageBox("Error - no NT header found."); ArcClose(FileId); return FALSE; } /* Ensure this is executable image */ if (((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0)) { // Print(L"Not an executable image %s\n", FileName); UiMessageBox("Not an executable image."); ArcClose(FileId); return FALSE; } /* Store number of sections to read and a pointer to the first section */ NumberOfSections = NtHeaders->FileHeader.NumberOfSections; SectionHeader = IMAGE_FIRST_SECTION(NtHeaders); /* Try to allocate this memory, if fails - allocate somewhere else */ PhysicalBase = MmAllocateMemoryAtAddress(NtHeaders->OptionalHeader.SizeOfImage, (PVOID)((ULONG)NtHeaders->OptionalHeader.ImageBase & (KSEG0_BASE - 1)), MemoryType); if (PhysicalBase == NULL) { /* It's ok, we don't panic - let's allocate again at any other "low" place */ PhysicalBase = MmAllocateMemoryWithType(NtHeaders->OptionalHeader.SizeOfImage, MemoryType); if (PhysicalBase == NULL) { // Print(L"Failed to alloc pages for image %s\n", FileName); UiMessageBox("Failed to alloc pages for image."); ArcClose(FileId); return FALSE; } } /* This is the real image base - in form of a virtual address */ VirtualBase = PaToVa(PhysicalBase); TRACE("Base PA: 0x%X, VA: 0x%X\n", PhysicalBase, VirtualBase); /* Set to 0 position and fully load the file image */ Position.HighPart = Position.LowPart = 0; Status = ArcSeek(FileId, &Position, SeekAbsolute); if (Status != ESUCCESS) { UiMessageBox("Error seeking to start of file."); ArcClose(FileId); return FALSE; } Status = ArcRead(FileId, PhysicalBase, NtHeaders->OptionalHeader.SizeOfHeaders, &BytesRead); if (Status != ESUCCESS) { // Print(L"Error reading headers %s\n", FileName); UiMessageBox("Error reading headers."); ArcClose(FileId); return FALSE; } /* Reload the NT Header */ NtHeaders = RtlImageNtHeader(PhysicalBase); /* Load the first section */ SectionHeader = IMAGE_FIRST_SECTION(NtHeaders); /* Fill output parameters */ *ImageBasePA = PhysicalBase; /* Walk through each section and read it (check/fix any possible bad situations, if they arise) */ for (i = 0; i < NumberOfSections; i++) { VirtualSize = SectionHeader->Misc.VirtualSize; SizeOfRawData = SectionHeader->SizeOfRawData; /* Handle a case when VirtualSize equals 0 */ if (VirtualSize == 0) VirtualSize = SizeOfRawData; /* If PointerToRawData is 0, then force its size to be also 0 */ if (SectionHeader->PointerToRawData == 0) { SizeOfRawData = 0; } else { /* Cut the loaded size to the VirtualSize extents */ if (SizeOfRawData > VirtualSize) SizeOfRawData = VirtualSize; } /* Actually read the section (if its size is not 0) */ if (SizeOfRawData != 0) { /* Seek to the correct position */ Position.LowPart = SectionHeader->PointerToRawData; Status = ArcSeek(FileId, &Position, SeekAbsolute); TRACE("SH->VA: 0x%X\n", SectionHeader->VirtualAddress); /* Read this section from the file, size = SizeOfRawData */ Status = ArcRead(FileId, (PUCHAR)PhysicalBase + SectionHeader->VirtualAddress, SizeOfRawData, &BytesRead); if (Status != ESUCCESS) { ERR("WinLdrLoadImage(): Error reading section from file!\n"); break; } } /* Size of data is less than the virtual size - fill up the remainder with zeroes */ if (SizeOfRawData < VirtualSize) { TRACE("WinLdrLoadImage(): SORD %d < VS %d\n", SizeOfRawData, VirtualSize); RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG_PTR)PhysicalBase + SizeOfRawData), VirtualSize - SizeOfRawData); } SectionHeader++; } /* We are done with the file - close it */ ArcClose(FileId); /* If loading failed - return right now */ if (Status != ESUCCESS) return FALSE; /* Relocate the image, if it needs it */ if (NtHeaders->OptionalHeader.ImageBase != (ULONG_PTR)VirtualBase) { WARN("Relocating %p -> %p\n", NtHeaders->OptionalHeader.ImageBase, VirtualBase); return (BOOLEAN)LdrRelocateImageWithBias(PhysicalBase, (ULONG_PTR)VirtualBase - (ULONG_PTR)PhysicalBase, "FreeLdr", TRUE, TRUE, /* in case of conflict still return success */ FALSE); } TRACE("WinLdrLoadImage() done, PA = %p\n", *ImageBasePA); return TRUE; }
VOID LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem, IN USHORT OperatingSystemVersion) { ULONG_PTR SectionId; PCSTR SectionName = OperatingSystem->SystemPartition; CHAR SettingsValue[80]; BOOLEAN HasSection; CHAR BootOptions2[256]; PCHAR File; CHAR FileName[512]; CHAR BootPath[512]; LPCSTR LoadOptions; LPSTR BootOptions; BOOLEAN BootFromFloppy; ULONG i, ErrorLine; HINF InfHandle; INFCONTEXT InfContext; PLOADER_PARAMETER_BLOCK LoaderBlock; PSETUP_LOADER_BLOCK SetupBlock; LPCSTR SystemPath; LPCSTR SourcePaths[] = { "", /* Only for floppy boot */ #if defined(_M_IX86) "I386\\", #elif defined(_M_MPPC) "PPC\\", #elif defined(_M_MRX000) "MIPS\\", #endif "reactos\\", NULL }; /* Get OS setting value */ SettingsValue[0] = ANSI_NULL; IniOpenSection("Operating Systems", &SectionId); IniReadSettingByName(SectionId, SectionName, SettingsValue, sizeof(SettingsValue)); /* Open the operating system section specified in the .ini file */ HasSection = IniOpenSection(SectionName, &SectionId); UiDrawBackdrop(); UiDrawProgressBarCenter(1, 100, "Loading ReactOS Setup..."); /* Read the system path is set in the .ini file */ if (!HasSection || !IniReadSettingByName(SectionId, "SystemPath", BootPath, sizeof(BootPath))) { /* * IMPROVE: I don't want to call MachDiskGetBootPath here as a * default choice because I can call it after (see few lines below). * Also doing the strcpy call as it is done in winldr.c is not * really what we want. Instead I reset BootPath here so that * we can build the full path using the general code from below. */ // MachDiskGetBootPath(BootPath, sizeof(BootPath)); // strcpy(BootPath, SectionName); BootPath[0] = '\0'; } /* * Check whether BootPath is a full path * and if not, create a full boot path. * * See FsOpenFile for the technique used. */ if (strrchr(BootPath, ')') == NULL) { /* Temporarily save the boot path */ strcpy(FileName, BootPath); /* This is not a full path. Use the current (i.e. boot) device. */ MachDiskGetBootPath(BootPath, sizeof(BootPath)); /* Append a path separator if needed */ if (FileName[0] != '\\' && FileName[0] != '/') strcat(BootPath, "\\"); /* Append the remaining path */ strcat(BootPath, FileName); } /* Append a backslash if needed */ if ((strlen(BootPath) == 0) || BootPath[strlen(BootPath) - 1] != '\\') strcat(BootPath, "\\"); /* Read booting options */ if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions2, sizeof(BootOptions2))) { /* Get options after the title */ PCSTR p = SettingsValue; while (*p == ' ' || *p == '"') p++; while (*p != '\0' && *p != '"') p++; strcpy(BootOptions2, p); TRACE("BootOptions: '%s'\n", BootOptions2); } /* Check if a ramdisk file was given */ File = strstr(BootOptions2, "/RDPATH="); if (File) { /* Copy the file name and everything else after it */ strcpy(FileName, File + 8); /* Null-terminate */ *strstr(FileName, " ") = ANSI_NULL; /* Load the ramdisk */ if (!RamDiskLoadVirtualFile(FileName)) { UiMessageBox("Failed to load RAM disk file %s", FileName); return; } } TRACE("BootPath: '%s'\n", BootPath); /* And check if we booted from floppy */ BootFromFloppy = strstr(BootPath, "fdisk") != NULL; /* Open 'txtsetup.sif' from any of source paths */ File = BootPath + strlen(BootPath); for (i = BootFromFloppy ? 0 : 1; ; i++) { SystemPath = SourcePaths[i]; if (!SystemPath) { UiMessageBox("Failed to open txtsetup.sif"); return; } strcpy(File, SystemPath); strcpy(FileName, BootPath); strcat(FileName, "txtsetup.sif"); if (InfOpenFile(&InfHandle, FileName, &ErrorLine)) { break; } } TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath); /* Get Load options - debug and non-debug */ if (!InfFindFirstLine(InfHandle, "SetupData", "OsLoadOptions", &InfContext)) { ERR("Failed to find 'SetupData/OsLoadOptions'\n"); return; } if (!InfGetDataField(&InfContext, 1, &LoadOptions)) { ERR("Failed to get load options\n"); return; } #if DBG /* Get debug load options and use them */ if (InfFindFirstLine(InfHandle, "SetupData", "DbgOsLoadOptions", &InfContext)) { LPCSTR DbgLoadOptions; if (InfGetDataField(&InfContext, 1, &DbgLoadOptions)) LoadOptions = DbgLoadOptions; } #endif /* Copy loadoptions (original string will be freed) */ BootOptions = FrLdrTempAlloc(strlen(LoadOptions) + 1, TAG_BOOT_OPTIONS); strcpy(BootOptions, LoadOptions); TRACE("BootOptions: '%s'\n", BootOptions); UiDrawStatusText("Setup is loading..."); /* Allocate and minimalistic-initialize LPB */ AllocateAndInitLPB(&LoaderBlock); /* Allocate and initialize setup loader block */ SetupBlock = &WinLdrSystemBlock->SetupBlock; LoaderBlock->SetupLdrBlock = SetupBlock; /* Set textmode setup flag */ SetupBlock->Flags = SETUPLDR_TEXT_MODE; /* Load NLS data, they are in system32 */ strcpy(FileName, BootPath); strcat(FileName, "system32\\"); SetupLdrLoadNlsData(LoaderBlock, InfHandle, FileName); /* Get a list of boot drivers */ SetupLdrScanBootDrivers(&LoaderBlock->BootDriverListHead, InfHandle, BootPath); /* Close the inf file */ InfCloseFile(InfHandle); /* Load ReactOS Setup */ LoadAndBootWindowsCommon(_WIN32_WINNT_WS03, LoaderBlock, BootOptions, BootPath, TRUE); }
VOID LoadAndBootWindowsCommon( USHORT OperatingSystemVersion, PLOADER_PARAMETER_BLOCK LoaderBlock, LPCSTR BootOptions, LPCSTR BootPath, BOOLEAN Setup) { PLOADER_PARAMETER_BLOCK LoaderBlockVA; BOOLEAN Status; PLDR_DATA_TABLE_ENTRY KernelDTE; KERNEL_ENTRY_POINT KiSystemStartup; LPCSTR SystemRoot; TRACE("LoadAndBootWindowsCommon()\n"); /* Convert BootPath to SystemRoot */ SystemRoot = strstr(BootPath, "\\"); /* Detect hardware */ LoaderBlock->ConfigurationRoot = MachHwDetect(); if (OperatingSystemVersion == 0) OperatingSystemVersion = WinLdrDetectVersion(); /* Load the operating system core: the Kernel, the HAL and the Kernel Debugger Transport DLL */ Status = LoadWindowsCore(OperatingSystemVersion, LoaderBlock, BootOptions, BootPath, &KernelDTE); if (!Status) { UiMessageBox("Error loading NTOS core."); return; } /* Load boot drivers */ UiDrawBackdrop(); UiDrawProgressBarCenter(100, 100, "Loading boot drivers..."); Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath); TRACE("Boot drivers loaded with status %d\n", Status); /* Initialize Phase 1 - no drivers loading anymore */ WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemRoot, BootPath, OperatingSystemVersion); /* Save entry-point pointer and Loader block VAs */ KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint; LoaderBlockVA = PaToVa(LoaderBlock); /* "Stop all motors", change videomode */ MachPrepareForReactOS(Setup); /* Debugging... */ //DumpMemoryAllocMap(); /* Do the machine specific initialization */ WinLdrSetupMachineDependent(LoaderBlock); /* Map pages and create memory descriptors */ WinLdrSetupMemoryLayout(LoaderBlock); /* Set processor context */ WinLdrSetProcessorContext(); /* Save final value of LoaderPagesSpanned */ LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned; TRACE("Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n", KiSystemStartup, LoaderBlockVA); // Zero KI_USER_SHARED_DATA page memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE); WinLdrpDumpMemoryDescriptors(LoaderBlockVA); WinLdrpDumpBootDriver(LoaderBlockVA); #ifndef _M_AMD64 WinLdrpDumpArcDisks(LoaderBlockVA); #endif //FIXME: If I substitute this debugging checkpoint, GCC will "optimize away" the code below //while (1) {}; /*asm(".intel_syntax noprefix\n"); asm("test1:\n"); asm("jmp test1\n"); asm(".att_syntax\n");*/ /* Pass control */ (*KiSystemStartup)(LoaderBlockVA); }
VOID DriveMapMapDrivesInSection(PCSTR SectionName) { CHAR SettingName[80]; CHAR SettingValue[80]; CHAR Drive1[80]; CHAR Drive2[80]; ULONG_PTR SectionId; ULONG SectionItemCount; ULONG Index; ULONG Index2; DRIVE_MAP_LIST DriveMapList; RtlZeroMemory(&DriveMapList, sizeof(DRIVE_MAP_LIST)); if (!IniOpenSection(SectionName, &SectionId)) { return; } // Get the number of items in this section SectionItemCount = IniGetNumSectionItems(SectionId); // Loop through each one and check if its a DriveMap= setting for (Index=0; Index<SectionItemCount; Index++) { // Get the next setting from the .ini file section if (IniReadSettingByNumber(SectionId, Index, SettingName, sizeof(SettingName), SettingValue, sizeof(SettingValue))) { if (_stricmp(SettingName, "DriveMap") == 0) { // Make sure we haven't exceeded the drive map max count if (DriveMapList.DriveMapCount >= 4) { UiMessageBox("Max DriveMap count exceeded in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue); continue; } RtlZeroMemory(Drive1, 80); RtlZeroMemory(Drive2, 80); strcpy(Drive1, SettingValue); // Parse the setting value and separate a string "hd0,hd1" // into two strings "hd0" and "hd1" for (Index2=0; Index2<strlen(Drive1); Index2++) { // Check if this character is the separater character (comma - ',') if (Drive1[Index2] == ',') { Drive1[Index2] = '\0'; strcpy(Drive2, &Drive1[Index2+1]); break; } } // Make sure we got good values before we add them to the map if (!DriveMapIsValidDriveString(Drive1) || !DriveMapIsValidDriveString(Drive2)) { UiMessageBox("Error in DriveMap setting in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue); continue; } // Add them to the map DriveMapList.DriveMap[(DriveMapList.DriveMapCount * 2)] = DriveMapGetBiosDriveNumber(Drive1); DriveMapList.DriveMap[(DriveMapList.DriveMapCount * 2)+1] = DriveMapGetBiosDriveNumber(Drive2); DriveMapList.DriveMapCount++; TRACE("Mapping BIOS drive 0x%x to drive 0x%x\n", DriveMapGetBiosDriveNumber(Drive1), DriveMapGetBiosDriveNumber(Drive2)); } } } if (DriveMapList.DriveMapCount) { TRACE("Installing Int13 drive map for %d drives.\n", DriveMapList.DriveMapCount); DriveMapInstallInt13Handler(&DriveMapList); } else { TRACE("Removing any previously installed Int13 drive map.\n"); DriveMapRemoveInt13Handler(); } }
BOOLEAN WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN LPCSTR DirectoryPath, IN LPCSTR AnsiFileName, IN LPCSTR OemFileName, IN LPCSTR LanguageFileName) { CHAR FileName[255]; ULONG AnsiFileId; ULONG OemFileId; ULONG LanguageFileId; ULONG AnsiFileSize, OemFileSize, LanguageFileSize; ULONG TotalSize; ULONG_PTR NlsDataBase; PVOID NlsVirtual; BOOLEAN AnsiEqualsOem = FALSE; FILEINFORMATION FileInfo; ULONG BytesRead, Status; /* There may be a case, when OEM and ANSI page coincide */ if (!strcmp(AnsiFileName, OemFileName)) AnsiEqualsOem = TRUE; /* Open file with ANSI and store its size */ //Print(L"Loading %s...\n", Filename); strcpy(FileName, DirectoryPath); strcat(FileName, AnsiFileName); Status = ArcOpen(FileName, OpenReadOnly, &AnsiFileId); if (Status != ESUCCESS) goto Failure; Status = ArcGetFileInformation(AnsiFileId, &FileInfo); if (Status != ESUCCESS) goto Failure; AnsiFileSize = FileInfo.EndingAddress.LowPart; TRACE("AnsiFileSize: %d\n", AnsiFileSize); ArcClose(AnsiFileId); /* Open OEM file and store its length */ if (AnsiEqualsOem) { OemFileSize = 0; } else { //Print(L"Loading %s...\n", Filename); strcpy(FileName, DirectoryPath); strcat(FileName, OemFileName); Status = ArcOpen(FileName, OpenReadOnly, &OemFileId); if (Status != ESUCCESS) goto Failure; Status = ArcGetFileInformation(OemFileId, &FileInfo); if (Status != ESUCCESS) goto Failure; OemFileSize = FileInfo.EndingAddress.LowPart; ArcClose(OemFileId); } TRACE("OemFileSize: %d\n", OemFileSize); /* And finally open the language codepage file and store its length */ //Print(L"Loading %s...\n", Filename); strcpy(FileName, DirectoryPath); strcat(FileName, LanguageFileName); Status = ArcOpen(FileName, OpenReadOnly, &LanguageFileId); if (Status != ESUCCESS) goto Failure; Status = ArcGetFileInformation(LanguageFileId, &FileInfo); if (Status != ESUCCESS) goto Failure; LanguageFileSize = FileInfo.EndingAddress.LowPart; ArcClose(LanguageFileId); TRACE("LanguageFileSize: %d\n", LanguageFileSize); /* Sum up all three length, having in mind that every one of them must start at a page boundary => thus round up each file to a page */ TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) + MM_SIZE_TO_PAGES(OemFileSize) + MM_SIZE_TO_PAGES(LanguageFileSize); /* Store it for later marking the pages as NlsData type */ TotalNLSSize = TotalSize; NlsDataBase = (ULONG_PTR)MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData); if (NlsDataBase == 0) goto Failure; NlsVirtual = PaToVa((PVOID)NlsDataBase); LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual; LoaderBlock->NlsData->OemCodePageData = (PVOID)((PUCHAR)NlsVirtual + (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT)); LoaderBlock->NlsData->UnicodeCodePageData = (PVOID)((PUCHAR)NlsVirtual + (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) + (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT)); /* Ansi and OEM data are the same - just set pointers to the same area */ if (AnsiEqualsOem) LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData; /* Now actually read the data into memory, starting with Ansi file */ strcpy(FileName, DirectoryPath); strcat(FileName, AnsiFileName); Status = ArcOpen(FileName, OpenReadOnly, &AnsiFileId); if (Status != ESUCCESS) goto Failure; Status = ArcRead(AnsiFileId, VaToPa(LoaderBlock->NlsData->AnsiCodePageData), AnsiFileSize, &BytesRead); if (Status != ESUCCESS) goto Failure; ArcClose(AnsiFileId); /* OEM now, if it doesn't equal Ansi of course */ if (!AnsiEqualsOem) { strcpy(FileName, DirectoryPath); strcat(FileName, OemFileName); Status = ArcOpen(FileName, OpenReadOnly, &OemFileId); if (Status != ESUCCESS) goto Failure; Status = ArcRead(OemFileId, VaToPa(LoaderBlock->NlsData->OemCodePageData), OemFileSize, &BytesRead); if (Status != ESUCCESS) goto Failure; ArcClose(OemFileId); } /* finally the language file */ strcpy(FileName, DirectoryPath); strcat(FileName, LanguageFileName); Status = ArcOpen(FileName, OpenReadOnly, &LanguageFileId); if (Status != ESUCCESS) goto Failure; Status = ArcRead(LanguageFileId, VaToPa(LoaderBlock->NlsData->UnicodeCodePageData), LanguageFileSize, &BytesRead); if (Status != ESUCCESS) goto Failure; ArcClose(LanguageFileId); // // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK // Should go to WinLdrLoadOemHalFont(), when it will be implemented // LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData); /* Convert NlsTables address to VA */ LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData); return TRUE; Failure: //UiMessageBox("Error reading NLS file %s\n", Filename); UiMessageBox("Error reading NLS file!"); return FALSE; }
VOID OptionMenuCustomBootReactOS(VOID) { ULONG_PTR SectionId; CHAR SectionName[100]; CHAR BootDriveString[20]; CHAR BootPartitionString[20]; CHAR ReactOSSystemPath[200]; CHAR ReactOSARCPath[200]; CHAR ReactOSOptions[200]; TIMEINFO* TimeInfo; OperatingSystemItem OperatingSystem; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString)); RtlZeroMemory(ReactOSSystemPath, sizeof(ReactOSSystemPath)); RtlZeroMemory(ReactOSOptions, sizeof(ReactOSOptions)); if (!UiEditBox(BootDrivePrompt, BootDriveString, 20)) return; if (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20)) return; if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSSystemPath, 200)) return; if (!UiEditBox(ReactOSOptionsPrompt, ReactOSOptions, 200)) return; /* Generate a unique section name */ TimeInfo = ArcGetTime(); sprintf(SectionName, "CustomReactOS%u%u%u%u%u%u", TimeInfo->Year, TimeInfo->Day, TimeInfo->Month, TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second); /* Add the section */ if (!IniAddSection(SectionName, &SectionId)) return; /* Add the BootType */ if (!IniAddSettingValueToSection(SectionId, "BootType", "Windows2003")) return; /* Construct the ReactOS ARC system path */ ConstructArcPath(ReactOSARCPath, ReactOSSystemPath, DriveMapGetBiosDriveNumber(BootDriveString), atoi(BootPartitionString)); /* Add the system path */ if (!IniAddSettingValueToSection(SectionId, "SystemPath", ReactOSARCPath)) return; /* Add the CommandLine */ if (!IniAddSettingValueToSection(SectionId, "Options", ReactOSOptions)) return; UiMessageBox(CustomBootPrompt); OperatingSystem.SystemPartition = SectionName; OperatingSystem.LoadIdentifier = NULL; OperatingSystem.OsLoadOptions = NULL; // ReactOSOptions // LoadAndBootWindows(&OperatingSystem, _WIN32_WINNT_WS03); LoadOperatingSystem(&OperatingSystem); }
VOID OptionMenuCustomBootLinux(VOID) { ULONG_PTR SectionId; CHAR SectionName[100]; CHAR BootDriveString[20]; CHAR BootPartitionString[20]; CHAR LinuxKernelString[200]; CHAR LinuxInitrdString[200]; CHAR LinuxCommandLineString[200]; TIMEINFO* TimeInfo; OperatingSystemItem OperatingSystem; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString)); RtlZeroMemory(LinuxKernelString, sizeof(LinuxKernelString)); RtlZeroMemory(LinuxInitrdString, sizeof(LinuxInitrdString)); RtlZeroMemory(LinuxCommandLineString, sizeof(LinuxCommandLineString)); if (!UiEditBox(BootDrivePrompt, BootDriveString, 20)) return; if (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20)) return; if (!UiEditBox(LinuxKernelPrompt, LinuxKernelString, 200)) return; if (!UiEditBox(LinuxInitrdPrompt, LinuxInitrdString, 200)) return; if (!UiEditBox(LinuxCommandLinePrompt, LinuxCommandLineString, 200)) return; /* Generate a unique section name */ TimeInfo = ArcGetTime(); sprintf(SectionName, "CustomLinux%u%u%u%u%u%u", TimeInfo->Year, TimeInfo->Day, TimeInfo->Month, TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second); /* Add the section */ if (!IniAddSection(SectionName, &SectionId)) return; /* Add the BootType */ if (!IniAddSettingValueToSection(SectionId, "BootType", "Linux")) return; /* Add the BootDrive */ if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString)) return; /* Add the BootPartition */ if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootPartitionString)) return; /* Add the Kernel */ if (!IniAddSettingValueToSection(SectionId, "Kernel", LinuxKernelString)) return; /* Add the Initrd */ if (strlen(LinuxInitrdString) > 0) { if (!IniAddSettingValueToSection(SectionId, "Initrd", LinuxInitrdString)) return; } /* Add the CommandLine */ if (!IniAddSettingValueToSection(SectionId, "CommandLine", LinuxCommandLineString)) return; UiMessageBox(CustomBootPrompt); OperatingSystem.SystemPartition = SectionName; OperatingSystem.LoadIdentifier = "Custom Linux Setup"; OperatingSystem.OsLoadOptions = NULL; // LoadAndBootLinux(&OperatingSystem, 0); LoadOperatingSystem(&OperatingSystem); }
VOID LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem, IN USHORT OperatingSystemVersion) { ULONG_PTR SectionId; PCSTR SectionName = OperatingSystem->SystemPartition; CHAR SettingsValue[80]; BOOLEAN HasSection; CHAR BootPath[MAX_PATH]; CHAR FileName[MAX_PATH]; CHAR BootOptions[256]; PCHAR File; BOOLEAN Success; PLOADER_PARAMETER_BLOCK LoaderBlock; /* Get OS setting value */ SettingsValue[0] = ANSI_NULL; IniOpenSection("Operating Systems", &SectionId); IniReadSettingByName(SectionId, SectionName, SettingsValue, sizeof(SettingsValue)); /* Open the operating system section specified in the .ini file */ HasSection = IniOpenSection(SectionName, &SectionId); UiDrawBackdrop(); UiDrawProgressBarCenter(1, 100, "Loading NT..."); /* Read the system path is set in the .ini file */ if (!HasSection || !IniReadSettingByName(SectionId, "SystemPath", BootPath, sizeof(BootPath))) { strcpy(BootPath, SectionName); } /* * Check whether BootPath is a full path * and if not, create a full boot path. * * See FsOpenFile for the technique used. */ if (strrchr(BootPath, ')') == NULL) { /* Temporarily save the boot path */ strcpy(FileName, BootPath); /* This is not a full path. Use the current (i.e. boot) device. */ MachDiskGetBootPath(BootPath, sizeof(BootPath)); /* Append a path separator if needed */ if (FileName[0] != '\\' && FileName[0] != '/') strcat(BootPath, "\\"); /* Append the remaining path */ strcat(BootPath, FileName); } /* Append a backslash if needed */ if ((strlen(BootPath) == 0) || BootPath[strlen(BootPath) - 1] != '\\') strcat(BootPath, "\\"); /* Read booting options */ if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions))) { /* Get options after the title */ PCSTR p = SettingsValue; while (*p == ' ' || *p == '"') p++; while (*p != '\0' && *p != '"') p++; strcpy(BootOptions, p); TRACE("BootOptions: '%s'\n", BootOptions); } /* Append boot-time options */ AppendBootTimeOptions(BootOptions); /* Check if a ramdisk file was given */ File = strstr(BootOptions, "/RDPATH="); if (File) { /* Copy the file name and everything else after it */ strcpy(FileName, File + 8); /* Null-terminate */ *strstr(FileName, " ") = ANSI_NULL; /* Load the ramdisk */ if (!RamDiskLoadVirtualFile(FileName)) { UiMessageBox("Failed to load RAM disk file %s", FileName); return; } } /* Let user know we started loading */ //UiDrawStatusText("Loading..."); TRACE("BootPath: '%s'\n", BootPath); /* Allocate and minimalistic-initialize LPB */ AllocateAndInitLPB(&LoaderBlock); /* Load Hive */ UiDrawBackdrop(); UiDrawProgressBarCenter(15, 100, "Loading system hive..."); Success = WinLdrInitSystemHive(LoaderBlock, BootPath); TRACE("SYSTEM hive %s\n", (Success ? "loaded" : "not loaded")); /* Load NLS data, OEM font, and prepare boot drivers list */ Success = WinLdrScanSystemHive(LoaderBlock, BootPath); TRACE("SYSTEM hive %s\n", (Success ? "scanned" : "not scanned")); /* Finish loading */ LoadAndBootWindowsCommon(OperatingSystemVersion, LoaderBlock, BootOptions, BootPath, FALSE); }
BOOLEAN WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN LPCSTR DirectoryPath, IN LPCSTR HiveName) { ULONG FileId; CHAR FullHiveName[256]; LONG Status; FILEINFORMATION FileInfo; ULONG HiveFileSize; ULONG_PTR HiveDataPhysical; PVOID HiveDataVirtual; ULONG BytesRead; LPCWSTR FsService; /* Concatenate path and filename to get the full name */ strcpy(FullHiveName, DirectoryPath); strcat(FullHiveName, HiveName); //Print(L"Loading %s...\n", FullHiveName); Status = ArcOpen(FullHiveName, OpenReadOnly, &FileId); if (Status != ESUCCESS) { UiMessageBox("Opening hive file failed!"); return FALSE; } /* Get the file length */ Status = ArcGetFileInformation(FileId, &FileInfo); if (Status != ESUCCESS) { ArcClose(FileId); UiMessageBox("Hive file has 0 size!"); return FALSE; } HiveFileSize = FileInfo.EndingAddress.LowPart; /* Round up the size to page boundary and alloc memory */ HiveDataPhysical = (ULONG_PTR)MmAllocateMemoryWithType( MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT, LoaderRegistryData); if (HiveDataPhysical == 0) { ArcClose(FileId); UiMessageBox("Unable to alloc memory for a hive!"); return FALSE; } /* Convert address to virtual */ HiveDataVirtual = PaToVa((PVOID)HiveDataPhysical); /* Fill LoaderBlock's entries */ LoaderBlock->RegistryLength = HiveFileSize; LoaderBlock->RegistryBase = HiveDataVirtual; /* Finally read from file to the memory */ Status = ArcRead(FileId, (PVOID)HiveDataPhysical, HiveFileSize, &BytesRead); if (Status != ESUCCESS) { ArcClose(FileId); UiMessageBox("Unable to read from hive file!"); return FALSE; } // Add boot filesystem driver to the list FsService = FsGetServiceName(FileId); if (FsService) { TRACE(" Adding filesystem service %S\n", FsService); Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\", NULL, (LPWSTR)FsService); if (!Status) TRACE(" Failed to add filesystem service\n"); } else { TRACE(" No required filesystem service\n"); } ArcClose(FileId); return TRUE; }
VOID RunLoader(VOID) { ULONG_PTR SectionId; ULONG OperatingSystemCount; OperatingSystemItem* OperatingSystemList; PCSTR* OperatingSystemDisplayNames; ULONG DefaultOperatingSystem; LONG TimeOut; ULONG SelectedOperatingSystem; ULONG i; if (!MachInitializeBootDevices()) { UiMessageBoxCritical("Error when detecting hardware."); return; } #ifdef _M_IX86 /* Load additional SCSI driver (if any) */ if (LoadBootDeviceDriver() != ESUCCESS) { UiMessageBoxCritical("Unable to load additional boot device drivers."); } #endif if (!IniFileInitialize()) { UiMessageBoxCritical("Error initializing .ini file."); return; } /* Debugger main initialization */ DebugInit(TRUE); if (!IniOpenSection("FreeLoader", &SectionId)) { UiMessageBoxCritical("Section [FreeLoader] not found in freeldr.ini."); return; } TimeOut = GetTimeOut(); /* UI main initialization */ if (!UiInitialize(TRUE)) { UiMessageBoxCritical("Unable to initialize UI."); return; } OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount); if (!OperatingSystemList) { UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot."); goto Reboot; } if (OperatingSystemCount == 0) { UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot."); goto Reboot; } DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemList, OperatingSystemCount); /* Create list of display names */ OperatingSystemDisplayNames = FrLdrTempAlloc(sizeof(PCSTR) * OperatingSystemCount, 'mNSO'); if (!OperatingSystemDisplayNames) goto Reboot; for (i = 0; i < OperatingSystemCount; i++) { OperatingSystemDisplayNames[i] = OperatingSystemList[i].LoadIdentifier; } /* Find all the message box settings and run them */ UiShowMessageBoxesInSection("FreeLoader"); for (;;) { /* Redraw the backdrop */ UiDrawBackdrop(); /* Show the operating system list menu */ if (!UiDisplayMenu("Please select the operating system to start:", "For troubleshooting and advanced startup options for " "ReactOS, press F8.", TRUE, OperatingSystemDisplayNames, OperatingSystemCount, DefaultOperatingSystem, TimeOut, &SelectedOperatingSystem, FALSE, MainBootMenuKeyPressFilter)) { UiMessageBox("Press ENTER to reboot."); goto Reboot; } TimeOut = -1; /* Load the chosen operating system */ LoadOperatingSystem(&OperatingSystemList[SelectedOperatingSystem]); } Reboot: UiUnInitialize("Rebooting..."); return; }