IN PVOID BasePA,\r
OUT PLDR_DATA_TABLE_ENTRY *NewEntry)\r
{\r
- return FALSE;\r
+ PVOID BaseVA = PaToVa(BasePA);\r
+ PWSTR Buffer;\r
+ PLDR_DATA_TABLE_ENTRY DataTableEntry;\r
+ PIMAGE_NT_HEADERS NtHeaders;\r
+ USHORT Length;\r
+\r
+ /* Allocate memory for a data table entry, zero-initialize it */\r
+ DataTableEntry = (PLDR_DATA_TABLE_ENTRY)MmAllocateMemory(sizeof(LDR_DATA_TABLE_ENTRY));\r
+ if (DataTableEntry == NULL)\r
+ return FALSE;\r
+ RtlZeroMemory(DataTableEntry, sizeof(LDR_DATA_TABLE_ENTRY));\r
+\r
+ /* Get NT headers from the image */\r
+ NtHeaders = RtlImageNtHeader(BasePA);\r
+\r
+ /* Initialize corresponding fields of DTE based on NT headers value */\r
+ DataTableEntry->DllBase = BaseVA;\r
+ DataTableEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;\r
+ DataTableEntry->EntryPoint = (PVOID)((ULONG)BaseVA +\r
+ NtHeaders->OptionalHeader.AddressOfEntryPoint);\r
+ DataTableEntry->SectionPointer = 0;\r
+ DataTableEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;\r
+\r
+ /* Initialize BaseDllName field (UNICODE_STRING) from the Ansi BaseDllName\r
+ by simple conversion - copying each character */\r
+ Length = (USHORT)(strlen(BaseDllName) * sizeof(WCHAR));\r
+ Buffer = (PWSTR)MmAllocateMemory(Length);\r
+ if (Buffer == NULL)\r
+ return FALSE;\r
+ RtlZeroMemory(Buffer, Length);\r
+\r
+ DataTableEntry->BaseDllName.Length = Length;\r
+ DataTableEntry->BaseDllName.MaximumLength = Length;\r
+ DataTableEntry->BaseDllName.Buffer = PaToVa(Buffer);\r
+ while (*BaseDllName != 0)\r
+ {\r
+ *Buffer++ = *BaseDllName++;\r
+ }\r
+\r
+ /* Initialize FullDllName field (UNICODE_STRING) from the Ansi FullDllName\r
+ using the same method */\r
+ Length = (USHORT)(strlen(FullDllName) * sizeof(WCHAR));\r
+ Buffer = (PWSTR)MmAllocateMemory(Length);\r
+ if (Buffer == NULL)\r
+ return FALSE;\r
+ RtlZeroMemory(Buffer, Length);\r
+\r
+ DataTableEntry->FullDllName.Length = Length;\r
+ DataTableEntry->FullDllName.MaximumLength = Length;\r
+ DataTableEntry->FullDllName.Buffer = PaToVa(Buffer);\r
+ while (*FullDllName != 0)\r
+ {\r
+ *Buffer++ = *FullDllName++;\r
+ }\r
+\r
+ /* Initialize what's left - LoadCount which is 1, and set Flags so that\r
+ we know this entry is processed */\r
+ DataTableEntry->Flags = LDRP_ENTRY_PROCESSED;\r
+ DataTableEntry->LoadCount = 1;\r
+\r
+ /* Insert this DTE to a list in the LPB */\r
+ InsertTailList(&WinLdrBlock->LoadOrderListHead, &DataTableEntry->InLoadOrderLinks);\r
+\r
+ /* Save pointer to a newly allocated and initialized entry */\r
+ *NewEntry = DataTableEntry;\r
+\r
+ /* Return success */\r
+ return TRUE;\r
}\r
\r
/* WinLdrLoadImage loads the specified image from the file (it doesn't\r
WinLdrLoadImage(IN PCHAR FileName,\r
OUT PVOID *ImageBasePA)\r
{\r
- return FALSE;\r
+ PFILE FileHandle;\r
+ PVOID PhysicalBase;\r
+ PVOID VirtualBase = NULL;\r
+ UCHAR HeadersBuffer[SECTOR_SIZE * 2];\r
+ PIMAGE_NT_HEADERS NtHeaders;\r
+ PIMAGE_SECTION_HEADER SectionHeader;\r
+ ULONG VirtualSize, SizeOfRawData, NumberOfSections;\r
+ BOOLEAN Status;\r
+ ULONG i, BytesRead;\r
+\r
+ //Print(L"Loading %s... ", FileName);\r
+\r
+ /* Open the image file */\r
+ FileHandle = FsOpenFile(FileName);\r
+\r
+ if (FileHandle == NULL)\r
+ {\r
+ //Print(L"Can not open the file %s\n",FileName);\r
+ UiMessageBox("Can not open the file");\r
+ return FALSE;\r
+ }\r
+\r
+ /* Load the first 2 sectors of the image so we can read the PE header */\r
+ Status = FsReadFile(FileHandle, SECTOR_SIZE * 2, NULL, HeadersBuffer);\r
+ if (!Status)\r
+ {\r
+ //Print(L"Error reading from file %s\n", FileName);\r
+ UiMessageBox("Error reading from file");\r
+ FsCloseFile(FileHandle);\r
+ return FALSE;\r
+ }\r
+\r
+ /* Now read the MZ header to get the offset to the PE Header */\r
+ NtHeaders = RtlImageNtHeader(HeadersBuffer);\r
+\r
+ if (!NtHeaders)\r
+ {\r
+ //Print(L"Error - no NT header found in %s\n", FileName);\r
+ UiMessageBox("Error - no NT header found");\r
+ FsCloseFile(FileHandle);\r
+ return FALSE;\r
+ }\r
+\r
+ /* Ensure this is executable image */\r
+ if (((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0))\r
+ {\r
+ //Print(L"Not an executable image %s\n", FileName);\r
+ UiMessageBox("Not an executable image");\r
+ FsCloseFile(FileHandle);\r
+ return FALSE;\r
+ }\r
+\r
+ /* Store number of sections to read and a pointer to the first section */\r
+ NumberOfSections = NtHeaders->FileHeader.NumberOfSections;\r
+ SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);\r
+\r
+ /* Try to allocate this memory, if fails - allocate somewhere else */\r
+ PhysicalBase = MmAllocateMemoryAtAddress(NtHeaders->OptionalHeader.SizeOfImage,\r
+ (PVOID)NtHeaders->OptionalHeader.ImageBase);\r
+\r
+ if (PhysicalBase == NULL)\r
+ {\r
+ /* It's ok, we don't panic - let's allocate again at any other "low" place */\r
+ MmChangeAllocationPolicy(FALSE);\r
+ PhysicalBase = MmAllocateMemory(NtHeaders->OptionalHeader.SizeOfImage);\r
+ MmChangeAllocationPolicy(TRUE);\r
+\r
+ if (PhysicalBase == NULL)\r
+ {\r
+ //Print(L"Failed to alloc pages for image %s\n", FileName);\r
+ UiMessageBox("Failed to alloc pages for image");\r
+ FsCloseFile(FileHandle);\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ /* This is the real image base - in form of a virtual address */\r
+ VirtualBase = PaToVa(PhysicalBase);\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "Base PA: 0x%X, VA: 0x%X\n", PhysicalBase, VirtualBase));\r
+\r
+ /* Set to 0 position and fully load the file image */\r
+ FsSetFilePointer(FileHandle, 0);\r
+\r
+ Status = FsReadFile(FileHandle, NtHeaders->OptionalHeader.SizeOfHeaders, NULL, PhysicalBase);\r
+\r
+ if (!Status)\r
+ {\r
+ //Print(L"Error reading headers %s\n", FileName);\r
+ UiMessageBox("Error reading headers");\r
+ FsCloseFile(FileHandle);\r
+ return FALSE;\r
+ }\r
+\r
+ /* Reload the NT Header */\r
+ NtHeaders = RtlImageNtHeader(PhysicalBase);\r
+\r
+ /* Load the first section */\r
+ SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);\r
+\r
+ /* Fill output parameters */\r
+ *ImageBasePA = PhysicalBase;\r
+\r
+ /* Walk through each section and read it (check/fix any possible\r
+ bad situations, if they arise) */\r
+ for (i = 0; i < NumberOfSections; i++)\r
+ {\r
+ VirtualSize = SectionHeader->Misc.VirtualSize;\r
+ SizeOfRawData = SectionHeader->SizeOfRawData;\r
+\r
+ /* Handle a case when VirtualSize equals 0 */\r
+ if (VirtualSize == 0)\r
+ VirtualSize = SizeOfRawData;\r
+\r
+ /* If PointerToRawData is 0, then force its size to be also 0 */\r
+ if (SectionHeader->PointerToRawData == 0)\r
+ {\r
+ SizeOfRawData = 0;\r
+ }\r
+ else\r
+ {\r
+ /* Cut the loaded size to the VirtualSize extents */\r
+ if (SizeOfRawData > VirtualSize)\r
+ SizeOfRawData = VirtualSize;\r
+ }\r
+\r
+ /* Actually read the section (if its size is not 0) */\r
+ if (SizeOfRawData != 0)\r
+ {\r
+ /* Seek to the correct position */\r
+ FsSetFilePointer(FileHandle, SectionHeader->PointerToRawData);\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "SH->VA: 0x%X\n", SectionHeader->VirtualAddress));\r
+\r
+ /* Read this section from the file, size = SizeOfRawData */\r
+ Status = FsReadFile(FileHandle, SizeOfRawData, &BytesRead, (PUCHAR)PhysicalBase + SectionHeader->VirtualAddress);\r
+\r
+ if (!Status && (BytesRead == 0))\r
+ break;\r
+ }\r
+\r
+ /* Size of data is less than the virtual size - fill up the remainder with zeroes */\r
+ if (SizeOfRawData < VirtualSize)\r
+ RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG)PhysicalBase + SizeOfRawData), VirtualSize - SizeOfRawData);\r
+\r
+ SectionHeader++;\r
+ }\r
+\r
+ /* We are done with the file - close it */\r
+ FsCloseFile(FileHandle);\r
+\r
+ /* If loading failed - return right now */\r
+ if (!Status)\r
+ return FALSE;\r
+\r
+\r
+ /* Relocate the image, if it needs it */\r
+ if (NtHeaders->OptionalHeader.ImageBase != (ULONG)VirtualBase)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Relocating %p -> %p\n",\r
+ NtHeaders->OptionalHeader.ImageBase, VirtualBase));\r
+ Status = (BOOLEAN)LdrRelocateImageWithBias(PhysicalBase,\r
+ 0,\r
+ "FLx86",\r
+ TRUE,\r
+ 3,\r
+ FALSE);\r
+ }\r
+\r
+ return Status;\r
}\r
\r
/* PRIVATE FUNCTIONS *******************************************************/\r