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 List_PaToVa(LIST_ENTRY *ListEntry) { LIST_ENTRY *ListHead = ListEntry; LIST_ENTRY *Next = ListEntry->Flink; LIST_ENTRY *NextPA; //Print(L"\n\nList_Entry: %X, First Next: %X\n", ListEntry, Next); // // Walk through the whole list // if (Next != NULL) { while (Next != PaToVa(ListHead)) { NextPA = VaToPa(Next); //Print(L"Current: %X, Flink: %X, Blink: %X\n", Next, NextPA->Flink, NextPA->Blink); NextPA->Flink = PaToVa((PVOID)NextPA->Flink); NextPA->Blink = PaToVa((PVOID)NextPA->Blink); //Print(L"After converting Flink: %X, Blink: %X\n", NextPA->Flink, NextPA->Blink); Next = NextPA->Flink; } // // Finally convert first Flink/Blink // ListEntry->Flink = PaToVa((PVOID)ListEntry->Flink); if (ListEntry->Blink) ListEntry->Blink = PaToVa((PVOID)ListEntry->Blink); } }
/* DllName - physical, UnicodeString->Buffer - virtual */ static BOOLEAN WinLdrpCompareDllName(IN PCH DllName, IN PUNICODE_STRING UnicodeName) { PWSTR Buffer; UNICODE_STRING UnicodeNamePA; SIZE_T i, Length; /* First obvious check: for length of two names */ Length = strlen(DllName); UnicodeNamePA.Length = UnicodeName->Length; UnicodeNamePA.MaximumLength = UnicodeName->MaximumLength; UnicodeNamePA.Buffer = VaToPa(UnicodeName->Buffer); TRACE("WinLdrpCompareDllName: %s and %wZ, Length = %d " "UN->Length %d\n", DllName, &UnicodeNamePA, Length, UnicodeName->Length); if ((Length * sizeof(WCHAR)) > UnicodeName->Length) return FALSE; /* Store pointer to unicode string's buffer */ Buffer = VaToPa(UnicodeName->Buffer); /* Loop character by character */ for (i = 0; i < Length; i++) { /* Compare two characters, uppercasing them */ if (toupper(*DllName) != toupper((CHAR)*Buffer)) return FALSE; /* Move to the next character */ DllName++; Buffer++; } /* Check, if strings either fully match, or match till the "." (w/o extension) */ if ((UnicodeName->Length == Length * sizeof(WCHAR)) || (*Buffer == L'.')) { /* Yes they do */ return TRUE; } /* Strings don't match, return FALSE */ return FALSE; }
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; }
/* Returns TRUE if DLL has already been loaded - looks in LoadOrderList in LPB */ BOOLEAN WinLdrCheckForLoadedDll(IN OUT PLIST_ENTRY ModuleListHead, IN PCH DllName, OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry) { PLDR_DATA_TABLE_ENTRY DataTableEntry; LIST_ENTRY *ModuleEntry; TRACE("WinLdrCheckForLoadedDll: DllName %s\n", DllName); /* Just go through each entry in the LoadOrderList and compare loaded module's name with a given name */ ModuleEntry = ModuleListHead->Flink; while (ModuleEntry != ModuleListHead) { /* Get pointer to the current DTE */ DataTableEntry = CONTAINING_RECORD(ModuleEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); TRACE("WinLdrCheckForLoadedDll: DTE %p, EP %p, base %p name '%.*ws'\n", DataTableEntry, DataTableEntry->EntryPoint, DataTableEntry->DllBase, DataTableEntry->BaseDllName.Length / 2, VaToPa(DataTableEntry->BaseDllName.Buffer)); /* Compare names */ if (WinLdrpCompareDllName(DllName, &DataTableEntry->BaseDllName)) { /* Yes, found it, report pointer to the loaded module's DTE to the caller and increase load count for it */ *LoadedEntry = DataTableEntry; DataTableEntry->LoadCount++; TRACE("WinLdrCheckForLoadedDll: LoadedEntry %X\n", DataTableEntry); return TRUE; } /* Go to the next entry */ ModuleEntry = ModuleEntry->Flink; } /* Nothing found */ return FALSE; }
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; }
BOOLEAN WinLdrScanImportDescriptorTable(IN OUT PLIST_ENTRY ModuleListHead, IN PCCH DirectoryPath, IN PLDR_DATA_TABLE_ENTRY ScanDTE) { PLDR_DATA_TABLE_ENTRY DataTableEntry; PIMAGE_IMPORT_DESCRIPTOR ImportTable; ULONG ImportTableSize; PCH ImportName; BOOLEAN Success; /* Get a pointer to the import table of this image */ ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(ScanDTE->DllBase), TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize); { UNICODE_STRING BaseName; BaseName.Buffer = VaToPa(ScanDTE->BaseDllName.Buffer); BaseName.MaximumLength = ScanDTE->BaseDllName.MaximumLength; BaseName.Length = ScanDTE->BaseDllName.Length; TRACE("WinLdrScanImportDescriptorTable(): %wZ ImportTable = 0x%X\n", &BaseName, ImportTable); } /* If image doesn't have any import directory - just return success */ if (ImportTable == NULL) return TRUE; /* Loop through all entries */ for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != 0);ImportTable++) { /* Get pointer to the name */ ImportName = (PCH)VaToPa(RVA(ScanDTE->DllBase, ImportTable->Name)); TRACE("WinLdrScanImportDescriptorTable(): Looking at %s\n", ImportName); /* In case we get a reference to ourselves - just skip it */ if (WinLdrpCompareDllName(ImportName, &ScanDTE->BaseDllName)) continue; /* Load the DLL if it is not already loaded */ if (!WinLdrCheckForLoadedDll(ModuleListHead, ImportName, &DataTableEntry)) { Success = WinLdrpLoadAndScanReferencedDll(ModuleListHead, DirectoryPath, ImportName, &DataTableEntry); if (!Success) { ERR("WinLdrpLoadAndScanReferencedDll() failed\n"); return Success; } } /* Scan its import address table */ Success = WinLdrpScanImportAddressTable(ModuleListHead, DataTableEntry->DllBase, ScanDTE->DllBase, (PIMAGE_THUNK_DATA)RVA(ScanDTE->DllBase, ImportTable->FirstThunk), DirectoryPath); if (!Success) { ERR("WinLdrpScanImportAddressTable() failed: ImportName = '%s', DirectoryPath = '%s'\n", ImportName, DirectoryPath); return Success; } } return TRUE; }
static BOOLEAN WinLdrpScanImportAddressTable(IN OUT PLIST_ENTRY ModuleListHead, IN PVOID DllBase, IN PVOID ImageBase, IN PIMAGE_THUNK_DATA ThunkData, IN PCSTR DirectoryPath) { PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; BOOLEAN Success; ULONG ExportSize; TRACE("WinLdrpScanImportAddressTable(): DllBase 0x%X, " "ImageBase 0x%X, ThunkData 0x%X\n", DllBase, ImageBase, ThunkData); /* Obtain the export table from the DLL's base */ if (DllBase == NULL) { ERR("Error, DllBase == NULL!\n"); return FALSE; } else { ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(VaToPa(DllBase), TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ExportSize); } TRACE("WinLdrpScanImportAddressTable(): ExportDirectory 0x%X\n", ExportDirectory); /* If pointer to Export Directory is */ if (ExportDirectory == NULL) { ERR("DllBase=%p(%p)\n", DllBase, VaToPa(DllBase)); return FALSE; } /* Go through each entry in the thunk table and bind it */ while (((PIMAGE_THUNK_DATA)VaToPa(ThunkData))->u1.AddressOfData != 0) { /* Bind it */ Success = WinLdrpBindImportName(ModuleListHead, DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize, FALSE, DirectoryPath); /* Move to the next entry */ ThunkData++; /* Return error if binding was unsuccessful */ if (!Success) return Success; } /* Return success */ return TRUE; }
static BOOLEAN WinLdrpBindImportName(IN OUT PLIST_ENTRY ModuleListHead, IN PVOID DllBase, IN PVOID ImageBase, IN PIMAGE_THUNK_DATA ThunkData, IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, IN ULONG ExportSize, IN BOOLEAN ProcessForwards, IN PCSTR DirectoryPath) { ULONG Ordinal; PULONG NameTable, FunctionTable; PUSHORT OrdinalTable; LONG High, Low, Middle, Result; ULONG Hint; PIMAGE_IMPORT_BY_NAME ImportData; PCHAR ExportName, ForwarderName; BOOLEAN Success; //TRACE("WinLdrpBindImportName(): DllBase 0x%X, ImageBase 0x%X, ThunkData 0x%X, ExportDirectory 0x%X, ExportSize %d, ProcessForwards 0x%X\n", // DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize, ProcessForwards); /* Check passed DllBase param */ if(DllBase == NULL) { WARN("DllBase == NULL!\n"); return FALSE; } /* Convert all non-critical pointers to PA from VA */ ThunkData = VaToPa(ThunkData); /* Is the reference by ordinal? */ if (IMAGE_SNAP_BY_ORDINAL(ThunkData->u1.Ordinal) && !ProcessForwards) { /* Yes, calculate the ordinal */ Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkData->u1.Ordinal) - (UINT32)ExportDirectory->Base); //TRACE("WinLdrpBindImportName(): Ordinal %d\n", Ordinal); } else { /* It's reference by name, we have to look it up in the export directory */ if (!ProcessForwards) { /* AddressOfData in thunk entry will become a virtual address (from relative) */ //TRACE("WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData); ThunkData->u1.AddressOfData = (ULONG_PTR)RVA(ImageBase, ThunkData->u1.AddressOfData); //TRACE("WinLdrpBindImportName(): ThunkData->u1.AOD became %p\n", ThunkData->u1.AddressOfData); } /* Get the import name */ ImportData = VaToPa((PVOID)ThunkData->u1.AddressOfData); /* Get pointers to Name and Ordinal tables (RVA -> VA) */ NameTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames)); OrdinalTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNameOrdinals)); //TRACE("NameTable 0x%X, OrdinalTable 0x%X, ED->AddressOfNames 0x%X, ED->AOFO 0x%X\n", // NameTable, OrdinalTable, ExportDirectory->AddressOfNames, ExportDirectory->AddressOfNameOrdinals); /* Get the hint, convert it to a physical pointer */ Hint = ((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Hint; //TRACE("HintIndex %d\n", Hint); /* Get the export name from the hint */ ExportName = VaToPa(RVA(DllBase, NameTable[Hint])); /* If Hint is less than total number of entries in the export directory, and import name == export name, then we can just get it from the OrdinalTable */ if ((Hint < ExportDirectory->NumberOfNames) && (strcmp(ExportName, (PCHAR)ImportData->Name) == 0)) { Ordinal = OrdinalTable[Hint]; //TRACE("WinLdrpBindImportName(): Ordinal %d\n", Ordinal); } else { /* It's not the easy way, we have to lookup import name in the name table. Let's use a binary search for this task. */ //TRACE("WinLdrpBindImportName() looking up the import name using binary search...\n"); /* Low boundary is set to 0, and high boundary to the maximum index */ Low = 0; High = ExportDirectory->NumberOfNames - 1; /* Perform a binary-search loop */ while (High >= Low) { /* Divide by 2 by shifting to the right once */ Middle = (Low + High) / 2; /* Get the name from the name table */ ExportName = VaToPa(RVA(DllBase, NameTable[Middle])); /* Compare the names */ Result = strcmp(ExportName, (PCHAR)ImportData->Name); /*TRACE("Binary search: comparing Import '__', Export '%s'\n",*/ /*VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]),*/ /*(PCHAR)VaToPa(RVA(DllBase, NameTable[Middle])));*/ /*TRACE("TE->u1.AOD %p, fulladdr %p\n", ThunkData->u1.AddressOfData, ((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name );*/ /* Depending on result of strcmp, perform different actions */ if (Result > 0) { /* Adjust top boundary */ High = Middle - 1; } else if (Result < 0) { /* Adjust bottom boundary */ Low = Middle + 1; } else { /* Yay, found it! */ break; } } /* If high boundary is less than low boundary, then no result found */ if (High < Low) { //Print(L"Error in binary search\n"); ERR("Did not find export '%s'!\n", (PCHAR)ImportData->Name); return FALSE; } /* Everything alright, get the ordinal */ Ordinal = OrdinalTable[Middle]; //TRACE("WinLdrpBindImportName() found Ordinal %d\n", Ordinal); } } /* Check ordinal number for validity! */ if (Ordinal >= ExportDirectory->NumberOfFunctions) { ERR("Ordinal number is invalid!\n"); return FALSE; } /* Get a pointer to the function table */ FunctionTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfFunctions)); /* Save a pointer to the function */ ThunkData->u1.Function = (ULONG_PTR)RVA(DllBase, FunctionTable[Ordinal]); /* Is it a forwarder? (function pointer is within the export directory) */ ForwarderName = (PCHAR)VaToPa((PVOID)ThunkData->u1.Function); if (((ULONG_PTR)ForwarderName > (ULONG_PTR)ExportDirectory) && ((ULONG_PTR)ForwarderName < ((ULONG_PTR)ExportDirectory + ExportSize))) { PLDR_DATA_TABLE_ENTRY DataTableEntry; CHAR ForwardDllName[255]; PIMAGE_EXPORT_DIRECTORY RefExportDirectory; ULONG RefExportSize; TRACE("WinLdrpBindImportName(): ForwarderName %s\n", ForwarderName); /* Save the name of the forward dll */ RtlCopyMemory(ForwardDllName, ForwarderName, sizeof(ForwardDllName)); /* Strip out the symbol name */ *strrchr(ForwardDllName,'.') = '\0'; /* Check if the target image is already loaded */ if (!WinLdrCheckForLoadedDll(ModuleListHead, ForwardDllName, &DataTableEntry)) { /* Check if the forward dll name has an extension */ if (strchr(ForwardDllName, '.') == NULL) { /* Name does not have an extension, append '.dll' */ strcat(ForwardDllName, ".dll"); } /* Now let's try to load it! */ Success = WinLdrpLoadAndScanReferencedDll(ModuleListHead, DirectoryPath, ForwardDllName, &DataTableEntry); if (!Success) { ERR("WinLdrpLoadAndScanReferencedDll() failed to load forwarder dll.\n"); return Success; } } /* Get pointer to the export directory of loaded DLL */ RefExportDirectory = (PIMAGE_EXPORT_DIRECTORY) RtlImageDirectoryEntryToData(VaToPa(DataTableEntry->DllBase), TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &RefExportSize); /* Fail if it's NULL */ if (RefExportDirectory) { UCHAR Buffer[128]; IMAGE_THUNK_DATA RefThunkData; PIMAGE_IMPORT_BY_NAME ImportByName; PCHAR ImportName; /* Get pointer to the import name */ ImportName = strrchr(ForwarderName, '.') + 1; /* Create a IMAGE_IMPORT_BY_NAME structure, pointing to the local Buffer */ ImportByName = (PIMAGE_IMPORT_BY_NAME)Buffer; /* Fill the name with the import name */ RtlCopyMemory(ImportByName->Name, ImportName, strlen(ImportName)+1); /* Set Hint to 0 */ ImportByName->Hint = 0; /* And finally point ThunkData's AddressOfData to that structure */ RefThunkData.u1.AddressOfData = (ULONG_PTR)ImportByName; /* And recursively call ourselves */ Success = WinLdrpBindImportName(ModuleListHead, DataTableEntry->DllBase, ImageBase, &RefThunkData, RefExportDirectory, RefExportSize, TRUE, DirectoryPath); /* Fill out the ThunkData with data from RefThunkData */ ThunkData->u1 = RefThunkData.u1; /* Return what we got from the recursive call */ return Success; } else { /* Fail if ExportDirectory is NULL */ return FALSE; } } /* Success! */ return TRUE; }
BOOLEAN WinLdrAllocateDataTableEntry(IN OUT PLIST_ENTRY ModuleListHead, IN PCCH BaseDllName, IN PCCH FullDllName, IN PVOID BasePA, OUT PLDR_DATA_TABLE_ENTRY *NewEntry) { PVOID BaseVA = PaToVa(BasePA); PWSTR Buffer; PLDR_DATA_TABLE_ENTRY DataTableEntry; PIMAGE_NT_HEADERS NtHeaders; USHORT Length; TRACE("WinLdrAllocateDataTableEntry(, '%s', '%s', %p)\n", BaseDllName, FullDllName, BasePA); /* Allocate memory for a data table entry, zero-initialize it */ DataTableEntry = (PLDR_DATA_TABLE_ENTRY)FrLdrHeapAlloc(sizeof(LDR_DATA_TABLE_ENTRY), TAG_WLDR_DTE); if (DataTableEntry == NULL) return FALSE; RtlZeroMemory(DataTableEntry, sizeof(LDR_DATA_TABLE_ENTRY)); /* Get NT headers from the image */ NtHeaders = RtlImageNtHeader(BasePA); /* Initialize corresponding fields of DTE based on NT headers value */ DataTableEntry->DllBase = BaseVA; DataTableEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage; DataTableEntry->EntryPoint = RVA(BaseVA, NtHeaders->OptionalHeader.AddressOfEntryPoint); DataTableEntry->SectionPointer = 0; DataTableEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum; /* Initialize BaseDllName field (UNICODE_STRING) from the Ansi BaseDllName by simple conversion - copying each character */ Length = (USHORT)(strlen(BaseDllName) * sizeof(WCHAR)); Buffer = (PWSTR)FrLdrHeapAlloc(Length, TAG_WLDR_NAME); if (Buffer == NULL) { FrLdrHeapFree(DataTableEntry, TAG_WLDR_DTE); return FALSE; } RtlZeroMemory(Buffer, Length); DataTableEntry->BaseDllName.Length = Length; DataTableEntry->BaseDllName.MaximumLength = Length; DataTableEntry->BaseDllName.Buffer = PaToVa(Buffer); while (*BaseDllName != 0) { *Buffer++ = *BaseDllName++; } /* Initialize FullDllName field (UNICODE_STRING) from the Ansi FullDllName using the same method */ Length = (USHORT)(strlen(FullDllName) * sizeof(WCHAR)); Buffer = (PWSTR)FrLdrHeapAlloc(Length, TAG_WLDR_NAME); if (Buffer == NULL) { FrLdrHeapFree(DataTableEntry, TAG_WLDR_DTE); return FALSE; } RtlZeroMemory(Buffer, Length); DataTableEntry->FullDllName.Length = Length; DataTableEntry->FullDllName.MaximumLength = Length; DataTableEntry->FullDllName.Buffer = PaToVa(Buffer); while (*FullDllName != 0) { *Buffer++ = *FullDllName++; } /* Initialize what's left - LoadCount which is 1, and set Flags so that we know this entry is processed */ DataTableEntry->Flags = LDRP_ENTRY_PROCESSED; DataTableEntry->LoadCount = 1; /* Insert this DTE to a list in the LPB */ InsertTailList(ModuleListHead, &DataTableEntry->InLoadOrderLinks); TRACE("Inserting DTE %p, name='%.*S' DllBase=%p \n", DataTableEntry, DataTableEntry->BaseDllName.Length / 2, VaToPa(DataTableEntry->BaseDllName.Buffer), DataTableEntry->DllBase); /* Save pointer to a newly allocated and initialized entry */ *NewEntry = DataTableEntry; /* Return success */ return TRUE; }
PVOID HeapCreate( SIZE_T MaximumSize, TYPE_OF_MEMORY MemoryType) { PHEAP Heap; PHEAP_BLOCK Block; SIZE_T Remaining; USHORT PreviousSize; TRACE("HeapCreate(MemoryType=%ld)\n", MemoryType); /* Allocate some memory for the heap */ MaximumSize = ALIGN_UP_BY(MaximumSize, MM_PAGE_SIZE); Heap = /*MmAllocateMemoryWithType*/VaToPa(MmHeapAllocEx(MaximumSize/*, MemoryType*/)); if (!Heap) { ERR("HEAP: Failed to allocate heap of size 0x%lx, Type\n", MaximumSize, MemoryType); return NULL; } /* Initialize the heap header */ Heap->MaximumSize = MaximumSize; Heap->CurrentAllocBytes = 0; Heap->MaxAllocBytes = 0; Heap->NumAllocs = 0; Heap->NumFrees = 0; Heap->LargestAllocation = 0; /* Calculate what's left to process */ Remaining = (MaximumSize - sizeof(HEAP)) / sizeof(HEAP_BLOCK); TRACE("Remaining = %ld\n", Remaining); /* Substract 2 for the terminating entry (header + free entry) */ Remaining -= 2; Block = &Heap->Blocks; PreviousSize = 0; /* Create free blocks */ while (Remaining > 1) { /* Initialize this free block */ Block->Size = (USHORT)min(MAXUSHORT, Remaining - 1); Block->PreviousSize = PreviousSize; Block->Tag = 0; Block->Data[0].Flink = (Block - &Heap->Blocks) + Block->Size + 1; Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize; /* Substract current block size from remainder */ Remaining -= (Block->Size + 1); /* Go to next block */ PreviousSize = Block->Size; Block = Block + Block->Size + 1; TRACE("Remaining = %ld\n", Remaining); } /* Now finish with a terminating block */ Heap->TerminatingBlock = Block - &Heap->Blocks; Block->Size = 0; Block->PreviousSize = PreviousSize; Block->Tag = 'dnE#'; Block->Data[0].Flink = 0; Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize; Heap->Blocks.Data[0].Blink = Heap->TerminatingBlock; return Heap; }
// This function converts only Child->Child, and calls itself for each Sibling VOID ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) { PCONFIGURATION_COMPONENT_DATA Child; PCONFIGURATION_COMPONENT_DATA Sibling; TRACE("ConvertConfigToVA(Start 0x%X)\n", Start); Child = Start; while (Child != NULL) { if (Child->ConfigurationData) Child->ConfigurationData = PaToVa(Child->ConfigurationData); if (Child->Child) Child->Child = PaToVa(Child->Child); if (Child->Parent) Child->Parent = PaToVa(Child->Parent); if (Child->Sibling) Child->Sibling = PaToVa(Child->Sibling); if (Child->ComponentEntry.Identifier) Child->ComponentEntry.Identifier = PaToVa(Child->ComponentEntry.Identifier); TRACE("Device 0x%X class %d type %d id '%s', parent %p\n", Child, Child->ComponentEntry.Class, Child->ComponentEntry.Type, VaToPa(Child->ComponentEntry.Identifier), Child->Parent); // Go through siblings list Sibling = VaToPa(Child->Sibling); while (Sibling != NULL) { if (Sibling->ConfigurationData) Sibling->ConfigurationData = PaToVa(Sibling->ConfigurationData); if (Sibling->Child) Sibling->Child = PaToVa(Sibling->Child); if (Sibling->Parent) Sibling->Parent = PaToVa(Sibling->Parent); if (Sibling->Sibling) Sibling->Sibling = PaToVa(Sibling->Sibling); if (Sibling->ComponentEntry.Identifier) Sibling->ComponentEntry.Identifier = PaToVa(Sibling->ComponentEntry.Identifier); TRACE("Device 0x%X class %d type %d id '%s', parent %p\n", Sibling, Sibling->ComponentEntry.Class, Sibling->ComponentEntry.Type, VaToPa(Sibling->ComponentEntry.Identifier), Sibling->Parent); // Recurse into the Child tree if (VaToPa(Sibling->Child) != NULL) ConvertConfigToVA(VaToPa(Sibling->Child)); Sibling = VaToPa(Sibling->Sibling); } // Go to the next child Child = VaToPa(Child->Child); } }