static BOOLEAN WinLdrpLoadAndScanReferencedDll(PLIST_ENTRY ModuleListHead, PCCH DirectoryPath, PCH ImportName, PLDR_DATA_TABLE_ENTRY *DataTableEntry) { CHAR FullDllName[256]; BOOLEAN Success; PVOID BasePA = NULL; /* Prepare the full path to the file to be loaded */ strcpy(FullDllName, DirectoryPath); strcat(FullDllName, ImportName); TRACE("Loading referenced DLL: %s\n", FullDllName); //Print(L"Loading referenced DLL: %s\n", FullDllName); /* Load the image */ Success = WinLdrLoadImage(FullDllName, LoaderBootDriver, &BasePA); if (!Success) { ERR("WinLdrLoadImage() failed\n"); return Success; } /* Allocate DTE for newly loaded DLL */ Success = WinLdrAllocateDataTableEntry(ModuleListHead, ImportName, FullDllName, BasePA, DataTableEntry); if (!Success) { ERR("WinLdrAllocateDataTableEntry() failed\n"); return Success; } /* Scan its dependencies too */ TRACE("WinLdrScanImportDescriptorTable() calling ourselves for %S\n", VaToPa((*DataTableEntry)->BaseDllName.Buffer)); Success = WinLdrScanImportDescriptorTable(ModuleListHead, DirectoryPath, *DataTableEntry); if (!Success) { ERR("WinLdrScanImportDescriptorTable() failed\n"); return Success; } return TRUE; }
static BOOLEAN LoadWindowsCore(IN USHORT OperatingSystemVersion, IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN LPCSTR BootOptions, IN LPCSTR BootPath, IN OUT PLDR_DATA_TABLE_ENTRY* KernelDTE) { BOOLEAN Status; CHAR DirPath[MAX_PATH]; CHAR KdTransportDllName[MAX_PATH]; PLDR_DATA_TABLE_ENTRY HalDTE, KdComDTE = NULL; if (!KernelDTE) return FALSE; /* Load the Kernel */ LoadModule(LoaderBlock, BootPath, "NTOSKRNL.EXE", LoaderSystemCode, KernelDTE, FALSE, 30); /* Load the HAL */ LoadModule(LoaderBlock, BootPath, "HAL.DLL", LoaderHalCode, &HalDTE, FALSE, 45); /* Load the Kernel Debugger Transport DLL */ if (OperatingSystemVersion > _WIN32_WINNT_WIN2K) { /* * According to http://www.nynaeve.net/?p=173 : * "[...] Another enhancement that could be done Microsoft-side would be * a better interface for replacing KD transport modules. Right now, due * to the fact that ntoskrnl is static linked to KDCOM.DLL, the OS loader * has a hardcoded hack that interprets the KD type in the OS loader options, * loads one of the (hardcoded filenames) "kdcom.dll", "kd1394.dll", or * "kdusb2.dll" modules, and inserts them into the loaded module list under * the name "kdcom.dll". [...]" */ /* * This loop replaces a dumb call to strstr(..., "DEBUGPORT="). * Indeed I want it to be case-insensitive to allow "debugport=" * or "DeBuGpOrT=" or... , and I don't want it to match malformed * command-line options, such as: * * "...foo DEBUGPORT=xxx bar..." * "...foo/DEBUGPORT=xxx bar..." * "...foo/DEBUGPORT=bar..." * * i.e. the "DEBUGPORT=" switch must start with a slash and be separated * from the rest by whitespace, unless it begins the command-line, e.g.: * * "/DEBUGPORT=COM1 foo...bar..." * "...foo /DEBUGPORT=USB bar..." * or: * "...foo /DEBUGPORT= bar..." * (in that case, we default the port to COM). */ while (BootOptions) { /* Skip possible initial whitespace */ BootOptions += strspn(BootOptions, " \t"); /* Check whether a new commutator starts and it is the DEBUGPORT one */ if (*BootOptions != '/' || _strnicmp(++BootOptions, "DEBUGPORT=", 10) != 0) { /* Search for another whitespace */ BootOptions = strpbrk(BootOptions, " \t"); continue; } else { /* We found the DEBUGPORT commutator. Move to the port name. */ BootOptions += 10; break; } } if (BootOptions) { /* * We have found the DEBUGPORT commutator. Parse the port name. * Format: /DEBUGPORT=COM1 or /DEBUGPORT=FILE:\Device\HarddiskX\PartitionY\debug.log or /DEBUGPORT=FOO * If we only have /DEBUGPORT= (i.e. without any port name), defaults it to "COM". */ strcpy(KdTransportDllName, "KD"); if (_strnicmp(BootOptions, "COM", 3) == 0 && '0' <= BootOptions[3] && BootOptions[3] <= '9') { strncat(KdTransportDllName, BootOptions, 3); } else { size_t i = strcspn(BootOptions, " \t:"); /* Skip valid separators: whitespace or colon */ if (i == 0) strcat(KdTransportDllName, "COM"); else strncat(KdTransportDllName, BootOptions, i); } strcat(KdTransportDllName, ".DLL"); _strupr(KdTransportDllName); /* * Load the transport DLL. Specify it to LoadModule so that it can * change the base DLL name of the loaded transport DLL to the default * "KDCOM.DLL" name, to make the PE loader happy. */ LoadModule(LoaderBlock, BootPath, KdTransportDllName, LoaderSystemCode, &KdComDTE, TRUE, 60); } } /* Load all referenced DLLs for Kernel, HAL and Kernel Debugger Transport DLL */ strcpy(DirPath, BootPath); strcat(DirPath, "system32\\"); Status = WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, *KernelDTE); Status &= WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, HalDTE); if (KdComDTE) { Status &= WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, KdComDTE); } return Status; }
static BOOLEAN WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead, LPCSTR BootPath, PUNICODE_STRING FilePath, ULONG Flags, PLDR_DATA_TABLE_ENTRY *DriverDTE) { CHAR FullPath[1024]; CHAR DriverPath[1024]; CHAR DllName[1024]; PCHAR DriverNamePos; BOOLEAN Status; PVOID DriverBase = NULL; // Separate the path to file name and directory path _snprintf(DriverPath, sizeof(DriverPath), "%wZ", FilePath); DriverNamePos = strrchr(DriverPath, '\\'); if (DriverNamePos != NULL) { // Copy the name strcpy(DllName, DriverNamePos+1); // Cut out the name from the path *(DriverNamePos+1) = 0; } else { // There is no directory in the path strcpy(DllName, DriverPath); DriverPath[0] = 0; } TRACE("DriverPath: %s, DllName: %s, LPB\n", DriverPath, DllName); // Check if driver is already loaded Status = WinLdrCheckForLoadedDll(LoadOrderListHead, DllName, DriverDTE); if (Status) { // We've got the pointer to its DTE, just return success return TRUE; } // It's not loaded, we have to load it _snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath); Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase); if (!Status) return FALSE; // Allocate a DTE for it Status = WinLdrAllocateDataTableEntry(LoadOrderListHead, DllName, DllName, DriverBase, DriverDTE); if (!Status) { ERR("WinLdrAllocateDataTableEntry() failed\n"); return FALSE; } // Modify any flags, if needed (*DriverDTE)->Flags |= Flags; // Look for any dependencies it may have, and load them too sprintf(FullPath,"%s%s", BootPath, DriverPath); Status = WinLdrScanImportDescriptorTable(LoadOrderListHead, FullPath, *DriverDTE); if (!Status) { ERR("WinLdrScanImportDescriptorTable() failed for %s\n", FullPath); return FALSE; } return TRUE; }