Author: fireball
Date: Mon Feb 4 13:45:55 2008
New Revision: 32113
URL:
http://svn.reactos.org/svn/reactos?rev=32113&view=rev
Log:
- Make Mm allocation strategy low->high by default.
- Clean up Mm APIs which are not needed anymore.
- Get rid of the LOADER_HIGH_ZONE definition, now the real LoaderPagesSpanned value is
calculated and used. As a result, minimum memory requirement (which was >=
LOADER_HIGH_ZONE) is gone, and a maximum amount of memory which could be allocated is also
gone (previously, not more that the LOADER_HIGH_ZONE).
- IMPORTANT: The FAT filesystem caching is disabled by default now due strange problems in
3rd boot stage, after switching the cache to use heap routines. Cache can't use
non-heap routines anymore, since the memory will overlap the contigious modules memory
space which ReactOS needs.
- More cleanup and more usage of the heap routines for temporary buffers.
- Fix a bug in MmAllocateMemoryWithType, where result of MmFindAvailablePages was checked
against -1 in error case, when in reality it's 0 (spotted by Alex). NB: 0 page is
marked as a reserved in x86 arch, so it's never going to be returned as an available.
Modified:
trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c
trunk/reactos/boot/freeldr/freeldr/cache/blocklist.c
trunk/reactos/boot/freeldr/freeldr/cache/cache.c
trunk/reactos/boot/freeldr/freeldr/fs/fat.c
trunk/reactos/boot/freeldr/freeldr/include/mm.h
trunk/reactos/boot/freeldr/freeldr/mm/meminit.c
trunk/reactos/boot/freeldr/freeldr/mm/mm.c
trunk/reactos/boot/freeldr/freeldr/windows/peloader.c
trunk/reactos/boot/freeldr/freeldr/windows/winldr.c
trunk/reactos/boot/freeldr/freeldr/windows/wlmemory.c
Modified: trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c Mon Feb 4 13:45:55 2008
@@ -582,7 +582,7 @@
FsSetFilePointer(Image, 0);
/* Allocate a temporary buffer for the read */
- ReadBuffer = MmAllocateMemory(ImageSize);
+ ReadBuffer = MmHeapAlloc(ImageSize);
/* Load the file image */
FsReadFile(Image, ImageSize, NULL, ReadBuffer);
@@ -591,7 +591,7 @@
ImageSize = FrLdrReMapImage(ReadBuffer, LoadBase);
/* Free the temporary buffer */
- MmFreeMemory(ReadBuffer);
+ MmHeapFree(ReadBuffer);
/* Calculate Difference between Real Base and Compiled Base*/
Status = LdrRelocateImageWithBias(LoadBase,
Modified: trunk/reactos/boot/freeldr/freeldr/cache/blocklist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/cache…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/cache/blocklist.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/cache/blocklist.c Mon Feb 4 13:45:55 2008
@@ -108,7 +108,7 @@
// allocate room for the block data
RtlZeroMemory(CacheBlock, sizeof(CACHE_BLOCK));
CacheBlock->BlockNumber = BlockNumber;
- CacheBlock->BlockData = MmAllocateMemory(CacheDrive->BlockSize *
CacheDrive->BytesPerSector);
+ CacheBlock->BlockData = MmHeapAlloc(CacheDrive->BlockSize *
CacheDrive->BytesPerSector);
if (CacheBlock->BlockData ==NULL)
{
MmHeapFree(CacheBlock);
@@ -118,7 +118,7 @@
// Now try to read in the block
if (!MachDiskReadLogicalSectors(CacheDrive->DriveNumber, (BlockNumber *
CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER))
{
- MmFreeMemory(CacheBlock->BlockData);
+ MmHeapFree(CacheBlock->BlockData);
MmHeapFree(CacheBlock);
return NULL;
}
@@ -161,7 +161,7 @@
RemoveEntryList(&CacheBlockToFree->ListEntry);
// Free the block memory and the block structure
- MmFreeMemory(CacheBlockToFree->BlockData);
+ MmHeapFree(CacheBlockToFree->BlockData);
MmHeapFree(CacheBlockToFree);
// Update the cache data
Modified: trunk/reactos/boot/freeldr/freeldr/cache/cache.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/cache…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/cache/cache.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/cache/cache.c Mon Feb 4 13:45:55 2008
@@ -70,7 +70,7 @@
CACHE_BLOCK,
ListEntry);
- MmFreeMemory(NextCacheBlock->BlockData);
+ MmHeapFree(NextCacheBlock->BlockData);
MmHeapFree(NextCacheBlock);
}
}
Modified: trunk/reactos/boot/freeldr/freeldr/fs/fat.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/fs/fa…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/fs/fat.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/fs/fat.c Mon Feb 4 13:45:55 2008
@@ -22,7 +22,7 @@
#define NDEBUG
#include <debug.h>
-BOOLEAN gCacheEnabled = TRUE;
+BOOLEAN gCacheEnabled = FALSE;
ULONG BytesPerSector; /* Number of bytes per sector */
ULONG SectorsPerCluster; /* Number of sectors per cluster */
Modified: trunk/reactos/boot/freeldr/freeldr/include/mm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/inclu…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/mm.h (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/mm.h Mon Feb 4 13:45:55 2008
@@ -47,10 +47,6 @@
( ((a) >> MM_PAGE_SHIFT) + ((a) & MM_PAGE_MASK ? 1 : 0) )
#endif // defined __i386__ or _PPC_ or _MIPS_
-//
-// This is the zone which is used by the OS loader
-//
-#define LOADER_HIGH_ZONE ((24*1024*1024) >> MM_PAGE_SHIFT) // 24Mb
// HEAP and STACK size
#define HEAP_PAGES 0x400
@@ -105,9 +101,6 @@
PVOID MmAllocateMemory(ULONG MemorySize);
PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType);
VOID MmFreeMemory(PVOID MemoryPointer);
-VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd);
-//PVOID MmAllocateLowMemory(ULONG MemorySize);
-//VOID MmFreeLowMemory(PVOID MemoryPointer);
PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY
MemoryType);
PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress,
TYPE_OF_MEMORY MemoryType);
Modified: trunk/reactos/boot/freeldr/freeldr/mm/meminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/mm/me…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/mm/meminit.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/mm/meminit.c Mon Feb 4 13:45:55 2008
@@ -393,8 +393,7 @@
if (FromEnd)
{
/* Allocate "high" (from end) pages */
- for (Index=/*LastFreePageHint-1*/LOADER_HIGH_ZONE-1; Index>0; Index--)
- //for (Index=LastFreePageHint-1; Index>0; Index--)
+ for (Index=LastFreePageHint-1; Index>0; Index--)
{
if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
{
Modified: trunk/reactos/boot/freeldr/freeldr/mm/mm.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/mm/mm…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/mm/mm.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/mm/mm.c Mon Feb 4 13:45:55 2008
@@ -25,12 +25,7 @@
VOID MemAllocTest(VOID);
#endif // DBG
-BOOLEAN AllocateFromEnd = TRUE;
-
-VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd)
-{
- AllocateFromEnd = PolicyAllocatePagesFromEnd;
-}
+ULONG LoaderPagesSpanned = 0;
PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
{
@@ -60,9 +55,9 @@
return NULL;
}
- FirstFreePageFromEnd = MmFindAvailablePages(PageLookupTableAddress,
TotalPagesInLookupTable, PagesNeeded, AllocateFromEnd);
-
- if (FirstFreePageFromEnd == (ULONG)-1)
+ FirstFreePageFromEnd = MmFindAvailablePages(PageLookupTableAddress,
TotalPagesInLookupTable, PagesNeeded, FALSE);
+
+ if (FirstFreePageFromEnd == 0)
{
DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not
enough free memory to allocate %d bytes.\n", MemorySize));
UiMessageBoxCritical("Memory allocation failed: out of memory.");
@@ -78,6 +73,10 @@
DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page
%d.\n", MemorySize, PagesNeeded, FirstFreePageFromEnd));
DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
#endif // DBG
+
+ // Update LoaderPagesSpanned count
+ if ((((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT) > LoaderPagesSpanned)
+ LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT);
// Now return the pointer
return MemPointer;
@@ -174,6 +173,10 @@
DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page
%d.\n", MemorySize, PagesNeeded, StartPageNumber));
DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
#endif // DBG
+
+ // Update LoaderPagesSpanned count
+ if ((((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT) > LoaderPagesSpanned)
+ LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT);
// Now return the pointer
return MemPointer;
@@ -227,6 +230,10 @@
DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page
%d.\n", MemorySize, PagesNeeded, FirstFreePageFromEnd));
DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
#endif // DBG
+
+ // Update LoaderPagesSpanned count
+ if ((((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT) > LoaderPagesSpanned)
+ LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT);
// Now return the pointer
return MemPointer;
Modified: trunk/reactos/boot/freeldr/freeldr/windows/peloader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/peloader.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/windows/peloader.c Mon Feb 4 13:45:55 2008
@@ -1,832 +1,830 @@
-/*
- * PROJECT: FreeLoader
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: freeldr/winldr/peloader.c
- * PURPOSE: Provides routines for loading PE files. To be merged with
- * arch/i386/loader.c in future
- * This article was very handy during development:
- *
http://msdn.microsoft.com/msdnmag/issues/02/03/PE2/
- * PROGRAMMERS: Aleksey Bragin (aleksey(a)reactos.org)
- * The source code in this file is based on the work of respective
- * authors of PE loading code in ReactOS and Brian Palmer and
- * Alex Ionescu's arch/i386/loader.c, and my research project
- * (creating a native EFI loader for Windows)
- */
-
-/* INCLUDES ***************************************************************/
-#include <freeldr.h>
-#include <debug.h>
-
-
-BOOLEAN
-WinLdrpCompareDllName(IN PCH DllName,
- IN PUNICODE_STRING UnicodeName);
-
-BOOLEAN
-WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
- IN PVOID DllBase,
- IN PVOID ImageBase,
- IN PIMAGE_THUNK_DATA ThunkData,
- IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
- IN ULONG ExportSize,
- IN BOOLEAN ProcessForwards);
-
-BOOLEAN
-WinLdrpLoadAndScanReferencedDll(PLOADER_PARAMETER_BLOCK WinLdrBlock,
- PCCH DirectoryPath,
- PCH ImportName,
- PLDR_DATA_TABLE_ENTRY *DataTableEntry);
-
-BOOLEAN
-WinLdrpScanImportAddressTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
- IN PVOID DllBase,
- IN PVOID ImageBase,
- IN PIMAGE_THUNK_DATA ThunkData);
-
-
-
-/* FUNCTIONS **************************************************************/
-
-/* Returns TRUE if DLL has already been loaded - looks in LoadOrderList in LPB */
-BOOLEAN
-WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
- IN PCH DllName,
- OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry)
-{
- PLDR_DATA_TABLE_ENTRY DataTableEntry;
- LIST_ENTRY *ModuleEntry;
-
- DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: DllName %X, LoadedEntry:
%X\n",
- DllName, LoadedEntry));
-
- /* Just go through each entry in the LoadOrderList and compare loaded module's
- name with a given name */
- ModuleEntry = WinLdrBlock->LoadOrderListHead.Flink;
- while (ModuleEntry != &WinLdrBlock->LoadOrderListHead)
- {
- /* Get pointer to the current DTE */
- DataTableEntry = CONTAINING_RECORD(ModuleEntry,
- LDR_DATA_TABLE_ENTRY,
- InLoadOrderLinks);
-
- DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: DTE %p, EP %p\n",
- DataTableEntry, DataTableEntry->EntryPoint));
-
- /* 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++;
- DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: LoadedEntry %X\n",
DataTableEntry));
- return TRUE;
- }
-
- /* Go to the next entry */
- ModuleEntry = ModuleEntry->Flink;
- }
-
- /* Nothing found */
- return FALSE;
-}
-
-BOOLEAN
-WinLdrScanImportDescriptorTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
- IN PCCH DirectoryPath,
- IN PLDR_DATA_TABLE_ENTRY ScanDTE)
-{
- PLDR_DATA_TABLE_ENTRY DataTableEntry;
- PIMAGE_IMPORT_DESCRIPTOR ImportTable;
- ULONG ImportTableSize;
- PCH ImportName;
- BOOLEAN Status;
-
- /* 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;
- DbgPrint((DPRINT_WINDOWS, "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));
- DbgPrint((DPRINT_WINDOWS, "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(WinLdrBlock, ImportName, &DataTableEntry))
- {
- Status = WinLdrpLoadAndScanReferencedDll(WinLdrBlock,
- DirectoryPath,
- ImportName,
- &DataTableEntry);
-
- if (!Status)
- {
- DbgPrint((DPRINT_WINDOWS, "WinLdrpLoadAndScanReferencedDll() failed\n"));
- return Status;
- }
- }
-
- /* Scan its import address table */
- Status = WinLdrpScanImportAddressTable(
- WinLdrBlock,
- DataTableEntry->DllBase,
- ScanDTE->DllBase,
- (PIMAGE_THUNK_DATA)RVA(ScanDTE->DllBase, ImportTable->FirstThunk));
-
- if (!Status)
- {
- DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable() failed\n"));
- return Status;
- }
- }
-
- return TRUE;
-}
-
-BOOLEAN
-WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
- 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;
-
- /* Allocate memory for a data table entry, zero-initialize it */
- DataTableEntry = (PLDR_DATA_TABLE_ENTRY)MmHeapAlloc(sizeof(LDR_DATA_TABLE_ENTRY));
- 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)MmHeapAlloc(Length);
- if (Buffer == NULL)
- {
- MmHeapFree(DataTableEntry);
- 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)MmHeapAlloc(Length);
- if (Buffer == NULL)
- {
- MmHeapFree(DataTableEntry);
- 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(&WinLdrBlock->LoadOrderListHead,
&DataTableEntry->InLoadOrderLinks);
-
- /* Save pointer to a newly allocated and initialized entry */
- *NewEntry = DataTableEntry;
-
- /* Return success */
- return TRUE;
-}
-
-/* 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)
-{
- PFILE FileHandle;
- PVOID PhysicalBase;
- PVOID VirtualBase = NULL;
- UCHAR HeadersBuffer[SECTOR_SIZE * 2];
- PIMAGE_NT_HEADERS NtHeaders;
- PIMAGE_SECTION_HEADER SectionHeader;
- ULONG VirtualSize, SizeOfRawData, NumberOfSections;
- BOOLEAN Status;
- ULONG i, BytesRead;
-
- CHAR ProgressString[256];
-
- /* Inform user we are loading files */
- sprintf(ProgressString, "Loading %s...", FileName);
- UiDrawProgressBarCenter(1, 100, ProgressString);
-
- /* Open the image file */
- FileHandle = FsOpenFile(FileName);
-
- if (FileHandle == NULL)
- {
- //Print(L"Can not open the file %s\n",FileName);
- UiMessageBox("Can not open the file");
- return FALSE;
- }
-
- /* Load the first 2 sectors of the image so we can read the PE header */
- Status = FsReadFile(FileHandle, SECTOR_SIZE * 2, NULL, HeadersBuffer);
- if (!Status)
- {
- //Print(L"Error reading from file %s\n", FileName);
- UiMessageBox("Error reading from file");
- FsCloseFile(FileHandle);
- 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");
- FsCloseFile(FileHandle);
- 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");
- FsCloseFile(FileHandle);
- 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 */
- //MmChangeAllocationPolicy(FALSE);
- PhysicalBase = MmAllocateMemoryWithType(NtHeaders->OptionalHeader.SizeOfImage,
MemoryType);
- //MmChangeAllocationPolicy(TRUE);
-
- if (PhysicalBase == NULL)
- {
- //Print(L"Failed to alloc pages for image %s\n", FileName);
- UiMessageBox("Failed to alloc pages for image");
- FsCloseFile(FileHandle);
- return FALSE;
- }
- }
-
- /* This is the real image base - in form of a virtual address */
- VirtualBase = PaToVa(PhysicalBase);
-
- DbgPrint((DPRINT_WINDOWS, "Base PA: 0x%X, VA: 0x%X\n", PhysicalBase,
VirtualBase));
-
- /* Set to 0 position and fully load the file image */
- FsSetFilePointer(FileHandle, 0);
-
- Status = FsReadFile(FileHandle, NtHeaders->OptionalHeader.SizeOfHeaders, NULL,
PhysicalBase);
-
- if (!Status)
- {
- //Print(L"Error reading headers %s\n", FileName);
- UiMessageBox("Error reading headers");
- FsCloseFile(FileHandle);
- 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 */
- FsSetFilePointer(FileHandle, SectionHeader->PointerToRawData);
-
- DbgPrint((DPRINT_WINDOWS, "SH->VA: 0x%X\n",
SectionHeader->VirtualAddress));
-
- /* Read this section from the file, size = SizeOfRawData */
- Status = FsReadFile(FileHandle, SizeOfRawData, &BytesRead, (PUCHAR)PhysicalBase +
SectionHeader->VirtualAddress);
-
- if (!Status && (BytesRead == 0))
- {
- DbgPrint((DPRINT_WINDOWS, "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)
- {
- DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage(): SORD %d < VS %d",
SizeOfRawData, VirtualSize));
- RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG)PhysicalBase +
SizeOfRawData), VirtualSize - SizeOfRawData);
- }
-
- SectionHeader++;
- }
-
- /* We are done with the file - close it */
- FsCloseFile(FileHandle);
-
- /* If loading failed - return right now */
- if (!Status)
- return FALSE;
-
-
- /* Relocate the image, if it needs it */
- if (NtHeaders->OptionalHeader.ImageBase != (ULONG)VirtualBase)
- {
- DbgPrint((DPRINT_WINDOWS, "Relocating %p -> %p\n",
- NtHeaders->OptionalHeader.ImageBase, VirtualBase));
- Status = (BOOLEAN)LdrRelocateImageWithBias(PhysicalBase,
- (ULONG_PTR)VirtualBase - (ULONG_PTR)PhysicalBase,
- "FreeLdr",
- TRUE,
- TRUE, /* in case of conflict still return success */
- FALSE);
- }
-
- return Status;
-}
-
-/* PRIVATE FUNCTIONS *******************************************************/
-
-/* DllName - physical, UnicodeString->Buffer - virtual */
-BOOLEAN
-WinLdrpCompareDllName(IN PCH DllName,
- IN PUNICODE_STRING UnicodeName)
-{
- PWSTR Buffer;
- UNICODE_STRING UnicodeNamePA;
- ULONG 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);
- DbgPrint((DPRINT_WINDOWS, "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;
-}
-
-BOOLEAN
-WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
- IN PVOID DllBase,
- IN PVOID ImageBase,
- IN PIMAGE_THUNK_DATA ThunkData,
- IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
- IN ULONG ExportSize,
- IN BOOLEAN ProcessForwards)
-{
- ULONG Ordinal;
- PULONG NameTable, FunctionTable;
- PUSHORT OrdinalTable;
- LONG High, Low, Middle, Result;
- ULONG Hint;
-
- //DbgPrint((DPRINT_WINDOWS, "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)
- {
- DbgPrint((DPRINT_WINDOWS, "WARNING: 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);
- //DbgPrint((DPRINT_WINDOWS, "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) */
- //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ThunkData->u1.AOD was
%p\n", ThunkData->u1.AddressOfData));
- ThunkData->u1.AddressOfData =
- (ULONG)RVA(ImageBase, ThunkData->u1.AddressOfData);
- //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ThunkData->u1.AOD became
%p\n", ThunkData->u1.AddressOfData));
- }
-
- /* Get pointers to Name and Ordinal tables (RVA -> VA) */
- NameTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames));
- OrdinalTable = (PUSHORT)VaToPa(RVA(DllBase,
ExportDirectory->AddressOfNameOrdinals));
-
- //DbgPrint((DPRINT_WINDOWS, "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;
- //DbgPrint((DPRINT_WINDOWS, "HintIndex %d\n", 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(VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Name[0]),
- (PCHAR)VaToPa( RVA(DllBase, NameTable[Hint])) ) == 0
- )
- )
- {
- Ordinal = OrdinalTable[Hint];
- //DbgPrint((DPRINT_WINDOWS, "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. */
-
- //DbgPrint((DPRINT_WINDOWS, "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) >> 1;
-
- /* Compare the names */
- Result =
strcmp(VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Name[0]),
- (PCHAR)VaToPa(RVA(DllBase, NameTable[Middle])));
-
- /*DbgPrint((DPRINT_WINDOWS, "Binary search: comparing Import '__',
Export '%s'\n",*/
- /*VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]),*/
- /*(PCHAR)VaToPa(RVA(DllBase, NameTable[Middle]))));*/
-
- /*DbgPrint((DPRINT_WINDOWS, "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");
- DbgPrint((DPRINT_WINDOWS, "Error in binary search!\n"));
- return FALSE;
- }
-
- /* Everything allright, get the ordinal */
- Ordinal = OrdinalTable[Middle];
-
- //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName() found Ordinal %d\n",
Ordinal));
- }
- }
-
- /* Check ordinal number for validity! */
- if (Ordinal >= ExportDirectory->NumberOfFunctions)
- {
- DbgPrint((DPRINT_WINDOWS, "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)RVA(DllBase, FunctionTable[Ordinal]);
-
- /* Is it a forwarder? (function pointer isn't within the export directory) */
- if (((ULONG)VaToPa((PVOID)ThunkData->u1.Function) > (ULONG)ExportDirectory)
&&
- ((ULONG)VaToPa((PVOID)ThunkData->u1.Function) < ((ULONG)ExportDirectory +
ExportSize)))
- {
- PLDR_DATA_TABLE_ENTRY DataTableEntry;
- CHAR ForwardDllName[255];
- PIMAGE_EXPORT_DIRECTORY RefExportDirectory;
- ULONG RefExportSize;
-
- /* Save the name of the forward dll */
- RtlCopyMemory(ForwardDllName, (PCHAR)VaToPa((PVOID)ThunkData->u1.Function),
sizeof(ForwardDllName));
-
- /* Strip out its extension */
- *strchr(ForwardDllName,'.') = '\0';
-
- DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ForwardDllName %s\n",
ForwardDllName));
- if (!WinLdrCheckForLoadedDll(WinLdrBlock, ForwardDllName, &DataTableEntry))
- {
- /* We can't continue if DLL couldn't be loaded, so bomb out with an error */
- //Print(L"Error loading DLL!\n");
- DbgPrint((DPRINT_WINDOWS, "Error loading DLL!\n"));
- return FALSE;
- }
-
- /* 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;
- BOOLEAN Status;
-
- /* Get pointer to the import name */
- ImportName = strchr((PCHAR)VaToPa((PVOID)ThunkData->u1.Function), '.') +
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)ImportByName;
-
- /* And recursively call ourselves */
- Status = WinLdrpBindImportName(
- WinLdrBlock,
- DataTableEntry->DllBase,
- ImageBase,
- &RefThunkData,
- RefExportDirectory,
- RefExportSize,
- TRUE);
-
- /* Fill out the ThunkData with data from RefThunkData */
- ThunkData->u1 = RefThunkData.u1;
-
- /* Return what we got from the recursive call */
- return Status;
- }
- else
- {
- /* Fail if ExportDirectory is NULL */
- return FALSE;
- }
- }
-
- /* Success! */
- return TRUE;
-}
-
-BOOLEAN
-WinLdrpLoadAndScanReferencedDll(PLOADER_PARAMETER_BLOCK WinLdrBlock,
- PCCH DirectoryPath,
- PCH ImportName,
- PLDR_DATA_TABLE_ENTRY *DataTableEntry)
-{
- CHAR FullDllName[256];
- BOOLEAN Status;
- PVOID BasePA;
-
- /* Prepare the full path to the file to be loaded */
- strcpy(FullDllName, DirectoryPath);
- strcat(FullDllName, ImportName);
-
- DbgPrint((DPRINT_WINDOWS, "Loading referenced DLL: %s\n", FullDllName));
- //Print(L"Loading referenced DLL: %s\n", FullDllName);
-
- /* Load the image */
- Status = WinLdrLoadImage(FullDllName, LoaderHalCode, &BasePA);
-
- if (!Status)
- {
- DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage() failed\n"));
- return Status;
- }
-
- /* Allocate DTE for newly loaded DLL */
- Status = WinLdrAllocateDataTableEntry(WinLdrBlock,
- ImportName,
- FullDllName,
- BasePA,
- DataTableEntry);
-
- if (!Status)
- {
- DbgPrint((DPRINT_WINDOWS,
- "WinLdrAllocateDataTableEntry() failed with Status=0x%X\n", Status));
- return Status;
- }
-
- /* Scan its dependencies too */
- DbgPrint((DPRINT_WINDOWS,
- "WinLdrScanImportDescriptorTable() calling ourselves for %S\n",
- VaToPa((*DataTableEntry)->BaseDllName.Buffer)));
- Status = WinLdrScanImportDescriptorTable(WinLdrBlock, DirectoryPath, *DataTableEntry);
-
- if (!Status)
- {
- DbgPrint((DPRINT_WINDOWS,
- "WinLdrScanImportDescriptorTable() failed with Status=0x%X\n", Status));
- return Status;
- }
-
- return TRUE;
-}
-
-BOOLEAN
-WinLdrpScanImportAddressTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
- IN PVOID DllBase,
- IN PVOID ImageBase,
- IN PIMAGE_THUNK_DATA ThunkData)
-{
- PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
- BOOLEAN Status;
- ULONG ExportSize;
-
- DbgPrint((DPRINT_WINDOWS, "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)
- {
- //Print(L"Error, DllBase == NULL!\n");
- return FALSE;
- }
- else
- {
- ExportDirectory =
- (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(VaToPa(DllBase),
- TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT,
- &ExportSize);
- }
-
- DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable(): ExportDirectory
0x%X\n", ExportDirectory));
-
- /* If pointer to Export Directory is */
- if (ExportDirectory == NULL)
- return FALSE;
-
- /* Go through each entry in the thunk table and bind it */
- while (((PIMAGE_THUNK_DATA)VaToPa(ThunkData))->u1.AddressOfData != 0)
- {
- /* Bind it */
- Status = WinLdrpBindImportName(
- WinLdrBlock,
- DllBase,
- ImageBase,
- ThunkData,
- ExportDirectory,
- ExportSize,
- FALSE);
-
- /* Move to the next entry */
- ThunkData++;
-
- /* Return error if binding was unsuccessful */
- if (!Status)
- return Status;
- }
-
- /* Return success */
- return TRUE;
-}
+/*
+ * PROJECT: FreeLoader
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: freeldr/winldr/peloader.c
+ * PURPOSE: Provides routines for loading PE files. To be merged with
+ * arch/i386/loader.c in future
+ * This article was very handy during development:
+ *
http://msdn.microsoft.com/msdnmag/issues/02/03/PE2/
+ * PROGRAMMERS: Aleksey Bragin (aleksey(a)reactos.org)
+ * The source code in this file is based on the work of respective
+ * authors of PE loading code in ReactOS and Brian Palmer and
+ * Alex Ionescu's arch/i386/loader.c, and my research project
+ * (creating a native EFI loader for Windows)
+ */
+
+/* INCLUDES ***************************************************************/
+#include <freeldr.h>
+#include <debug.h>
+
+
+BOOLEAN
+WinLdrpCompareDllName(IN PCH DllName,
+ IN PUNICODE_STRING UnicodeName);
+
+BOOLEAN
+WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ IN PVOID DllBase,
+ IN PVOID ImageBase,
+ IN PIMAGE_THUNK_DATA ThunkData,
+ IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
+ IN ULONG ExportSize,
+ IN BOOLEAN ProcessForwards);
+
+BOOLEAN
+WinLdrpLoadAndScanReferencedDll(PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ PCCH DirectoryPath,
+ PCH ImportName,
+ PLDR_DATA_TABLE_ENTRY *DataTableEntry);
+
+BOOLEAN
+WinLdrpScanImportAddressTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ IN PVOID DllBase,
+ IN PVOID ImageBase,
+ IN PIMAGE_THUNK_DATA ThunkData);
+
+
+
+/* FUNCTIONS **************************************************************/
+
+/* Returns TRUE if DLL has already been loaded - looks in LoadOrderList in LPB */
+BOOLEAN
+WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ IN PCH DllName,
+ OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry)
+{
+ PLDR_DATA_TABLE_ENTRY DataTableEntry;
+ LIST_ENTRY *ModuleEntry;
+
+ DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: DllName %X, LoadedEntry:
%X\n",
+ DllName, LoadedEntry));
+
+ /* Just go through each entry in the LoadOrderList and compare loaded module's
+ name with a given name */
+ ModuleEntry = WinLdrBlock->LoadOrderListHead.Flink;
+ while (ModuleEntry != &WinLdrBlock->LoadOrderListHead)
+ {
+ /* Get pointer to the current DTE */
+ DataTableEntry = CONTAINING_RECORD(ModuleEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: DTE %p, EP %p\n",
+ DataTableEntry, DataTableEntry->EntryPoint));
+
+ /* 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++;
+ DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: LoadedEntry %X\n",
DataTableEntry));
+ return TRUE;
+ }
+
+ /* Go to the next entry */
+ ModuleEntry = ModuleEntry->Flink;
+ }
+
+ /* Nothing found */
+ return FALSE;
+}
+
+BOOLEAN
+WinLdrScanImportDescriptorTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ IN PCCH DirectoryPath,
+ IN PLDR_DATA_TABLE_ENTRY ScanDTE)
+{
+ PLDR_DATA_TABLE_ENTRY DataTableEntry;
+ PIMAGE_IMPORT_DESCRIPTOR ImportTable;
+ ULONG ImportTableSize;
+ PCH ImportName;
+ BOOLEAN Status;
+
+ /* 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;
+ DbgPrint((DPRINT_WINDOWS, "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));
+ DbgPrint((DPRINT_WINDOWS, "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(WinLdrBlock, ImportName, &DataTableEntry))
+ {
+ Status = WinLdrpLoadAndScanReferencedDll(WinLdrBlock,
+ DirectoryPath,
+ ImportName,
+ &DataTableEntry);
+
+ if (!Status)
+ {
+ DbgPrint((DPRINT_WINDOWS, "WinLdrpLoadAndScanReferencedDll() failed\n"));
+ return Status;
+ }
+ }
+
+ /* Scan its import address table */
+ Status = WinLdrpScanImportAddressTable(
+ WinLdrBlock,
+ DataTableEntry->DllBase,
+ ScanDTE->DllBase,
+ (PIMAGE_THUNK_DATA)RVA(ScanDTE->DllBase, ImportTable->FirstThunk));
+
+ if (!Status)
+ {
+ DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable() failed\n"));
+ return Status;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ 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;
+
+ /* Allocate memory for a data table entry, zero-initialize it */
+ DataTableEntry = (PLDR_DATA_TABLE_ENTRY)MmHeapAlloc(sizeof(LDR_DATA_TABLE_ENTRY));
+ 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)MmHeapAlloc(Length);
+ if (Buffer == NULL)
+ {
+ MmHeapFree(DataTableEntry);
+ 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)MmHeapAlloc(Length);
+ if (Buffer == NULL)
+ {
+ MmHeapFree(DataTableEntry);
+ 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(&WinLdrBlock->LoadOrderListHead,
&DataTableEntry->InLoadOrderLinks);
+
+ /* Save pointer to a newly allocated and initialized entry */
+ *NewEntry = DataTableEntry;
+
+ /* Return success */
+ return TRUE;
+}
+
+/* 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)
+{
+ PFILE FileHandle;
+ PVOID PhysicalBase;
+ PVOID VirtualBase = NULL;
+ UCHAR HeadersBuffer[SECTOR_SIZE * 2];
+ PIMAGE_NT_HEADERS NtHeaders;
+ PIMAGE_SECTION_HEADER SectionHeader;
+ ULONG VirtualSize, SizeOfRawData, NumberOfSections;
+ BOOLEAN Status;
+ ULONG i, BytesRead;
+
+ CHAR ProgressString[256];
+
+ /* Inform user we are loading files */
+ sprintf(ProgressString, "Loading %s...", FileName);
+ UiDrawProgressBarCenter(1, 100, ProgressString);
+
+ /* Open the image file */
+ FileHandle = FsOpenFile(FileName);
+
+ if (FileHandle == NULL)
+ {
+ //Print(L"Can not open the file %s\n",FileName);
+ UiMessageBox("Can not open the file");
+ return FALSE;
+ }
+
+ /* Load the first 2 sectors of the image so we can read the PE header */
+ Status = FsReadFile(FileHandle, SECTOR_SIZE * 2, NULL, HeadersBuffer);
+ if (!Status)
+ {
+ //Print(L"Error reading from file %s\n", FileName);
+ UiMessageBox("Error reading from file");
+ FsCloseFile(FileHandle);
+ 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");
+ FsCloseFile(FileHandle);
+ 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");
+ FsCloseFile(FileHandle);
+ 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");
+ FsCloseFile(FileHandle);
+ return FALSE;
+ }
+ }
+
+ /* This is the real image base - in form of a virtual address */
+ VirtualBase = PaToVa(PhysicalBase);
+
+ DbgPrint((DPRINT_WINDOWS, "Base PA: 0x%X, VA: 0x%X\n", PhysicalBase,
VirtualBase));
+
+ /* Set to 0 position and fully load the file image */
+ FsSetFilePointer(FileHandle, 0);
+
+ Status = FsReadFile(FileHandle, NtHeaders->OptionalHeader.SizeOfHeaders, NULL,
PhysicalBase);
+
+ if (!Status)
+ {
+ //Print(L"Error reading headers %s\n", FileName);
+ UiMessageBox("Error reading headers");
+ FsCloseFile(FileHandle);
+ 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 */
+ FsSetFilePointer(FileHandle, SectionHeader->PointerToRawData);
+
+ DbgPrint((DPRINT_WINDOWS, "SH->VA: 0x%X\n",
SectionHeader->VirtualAddress));
+
+ /* Read this section from the file, size = SizeOfRawData */
+ Status = FsReadFile(FileHandle, SizeOfRawData, &BytesRead, (PUCHAR)PhysicalBase +
SectionHeader->VirtualAddress);
+
+ if (!Status && (BytesRead == 0))
+ {
+ DbgPrint((DPRINT_WINDOWS, "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)
+ {
+ DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage(): SORD %d < VS %d",
SizeOfRawData, VirtualSize));
+ RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG)PhysicalBase +
SizeOfRawData), VirtualSize - SizeOfRawData);
+ }
+
+ SectionHeader++;
+ }
+
+ /* We are done with the file - close it */
+ FsCloseFile(FileHandle);
+
+ /* If loading failed - return right now */
+ if (!Status)
+ return FALSE;
+
+
+ /* Relocate the image, if it needs it */
+ if (NtHeaders->OptionalHeader.ImageBase != (ULONG)VirtualBase)
+ {
+ DbgPrint((DPRINT_WINDOWS, "Relocating %p -> %p\n",
+ NtHeaders->OptionalHeader.ImageBase, VirtualBase));
+ Status = (BOOLEAN)LdrRelocateImageWithBias(PhysicalBase,
+ (ULONG_PTR)VirtualBase - (ULONG_PTR)PhysicalBase,
+ "FreeLdr",
+ TRUE,
+ TRUE, /* in case of conflict still return success */
+ FALSE);
+ }
+
+ return Status;
+}
+
+/* PRIVATE FUNCTIONS *******************************************************/
+
+/* DllName - physical, UnicodeString->Buffer - virtual */
+BOOLEAN
+WinLdrpCompareDllName(IN PCH DllName,
+ IN PUNICODE_STRING UnicodeName)
+{
+ PWSTR Buffer;
+ UNICODE_STRING UnicodeNamePA;
+ ULONG 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);
+ DbgPrint((DPRINT_WINDOWS, "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;
+}
+
+BOOLEAN
+WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ IN PVOID DllBase,
+ IN PVOID ImageBase,
+ IN PIMAGE_THUNK_DATA ThunkData,
+ IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
+ IN ULONG ExportSize,
+ IN BOOLEAN ProcessForwards)
+{
+ ULONG Ordinal;
+ PULONG NameTable, FunctionTable;
+ PUSHORT OrdinalTable;
+ LONG High, Low, Middle, Result;
+ ULONG Hint;
+
+ //DbgPrint((DPRINT_WINDOWS, "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)
+ {
+ DbgPrint((DPRINT_WINDOWS, "WARNING: 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);
+ //DbgPrint((DPRINT_WINDOWS, "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) */
+ //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ThunkData->u1.AOD was
%p\n", ThunkData->u1.AddressOfData));
+ ThunkData->u1.AddressOfData =
+ (ULONG)RVA(ImageBase, ThunkData->u1.AddressOfData);
+ //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ThunkData->u1.AOD became
%p\n", ThunkData->u1.AddressOfData));
+ }
+
+ /* Get pointers to Name and Ordinal tables (RVA -> VA) */
+ NameTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames));
+ OrdinalTable = (PUSHORT)VaToPa(RVA(DllBase,
ExportDirectory->AddressOfNameOrdinals));
+
+ //DbgPrint((DPRINT_WINDOWS, "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;
+ //DbgPrint((DPRINT_WINDOWS, "HintIndex %d\n", 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(VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Name[0]),
+ (PCHAR)VaToPa( RVA(DllBase, NameTable[Hint])) ) == 0
+ )
+ )
+ {
+ Ordinal = OrdinalTable[Hint];
+ //DbgPrint((DPRINT_WINDOWS, "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. */
+
+ //DbgPrint((DPRINT_WINDOWS, "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) >> 1;
+
+ /* Compare the names */
+ Result =
strcmp(VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Name[0]),
+ (PCHAR)VaToPa(RVA(DllBase, NameTable[Middle])));
+
+ /*DbgPrint((DPRINT_WINDOWS, "Binary search: comparing Import '__',
Export '%s'\n",*/
+ /*VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]),*/
+ /*(PCHAR)VaToPa(RVA(DllBase, NameTable[Middle]))));*/
+
+ /*DbgPrint((DPRINT_WINDOWS, "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");
+ DbgPrint((DPRINT_WINDOWS, "Error in binary search!\n"));
+ return FALSE;
+ }
+
+ /* Everything allright, get the ordinal */
+ Ordinal = OrdinalTable[Middle];
+
+ //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName() found Ordinal %d\n",
Ordinal));
+ }
+ }
+
+ /* Check ordinal number for validity! */
+ if (Ordinal >= ExportDirectory->NumberOfFunctions)
+ {
+ DbgPrint((DPRINT_WINDOWS, "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)RVA(DllBase, FunctionTable[Ordinal]);
+
+ /* Is it a forwarder? (function pointer isn't within the export directory) */
+ if (((ULONG)VaToPa((PVOID)ThunkData->u1.Function) > (ULONG)ExportDirectory)
&&
+ ((ULONG)VaToPa((PVOID)ThunkData->u1.Function) < ((ULONG)ExportDirectory +
ExportSize)))
+ {
+ PLDR_DATA_TABLE_ENTRY DataTableEntry;
+ CHAR ForwardDllName[255];
+ PIMAGE_EXPORT_DIRECTORY RefExportDirectory;
+ ULONG RefExportSize;
+
+ /* Save the name of the forward dll */
+ RtlCopyMemory(ForwardDllName, (PCHAR)VaToPa((PVOID)ThunkData->u1.Function),
sizeof(ForwardDllName));
+
+ /* Strip out its extension */
+ *strchr(ForwardDllName,'.') = '\0';
+
+ DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ForwardDllName %s\n",
ForwardDllName));
+ if (!WinLdrCheckForLoadedDll(WinLdrBlock, ForwardDllName, &DataTableEntry))
+ {
+ /* We can't continue if DLL couldn't be loaded, so bomb out with an error */
+ //Print(L"Error loading DLL!\n");
+ DbgPrint((DPRINT_WINDOWS, "Error loading DLL!\n"));
+ return FALSE;
+ }
+
+ /* 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;
+ BOOLEAN Status;
+
+ /* Get pointer to the import name */
+ ImportName = strchr((PCHAR)VaToPa((PVOID)ThunkData->u1.Function), '.') +
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)ImportByName;
+
+ /* And recursively call ourselves */
+ Status = WinLdrpBindImportName(
+ WinLdrBlock,
+ DataTableEntry->DllBase,
+ ImageBase,
+ &RefThunkData,
+ RefExportDirectory,
+ RefExportSize,
+ TRUE);
+
+ /* Fill out the ThunkData with data from RefThunkData */
+ ThunkData->u1 = RefThunkData.u1;
+
+ /* Return what we got from the recursive call */
+ return Status;
+ }
+ else
+ {
+ /* Fail if ExportDirectory is NULL */
+ return FALSE;
+ }
+ }
+
+ /* Success! */
+ return TRUE;
+}
+
+BOOLEAN
+WinLdrpLoadAndScanReferencedDll(PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ PCCH DirectoryPath,
+ PCH ImportName,
+ PLDR_DATA_TABLE_ENTRY *DataTableEntry)
+{
+ CHAR FullDllName[256];
+ BOOLEAN Status;
+ PVOID BasePA;
+
+ /* Prepare the full path to the file to be loaded */
+ strcpy(FullDllName, DirectoryPath);
+ strcat(FullDllName, ImportName);
+
+ DbgPrint((DPRINT_WINDOWS, "Loading referenced DLL: %s\n", FullDllName));
+ //Print(L"Loading referenced DLL: %s\n", FullDllName);
+
+ /* Load the image */
+ Status = WinLdrLoadImage(FullDllName, LoaderHalCode, &BasePA);
+
+ if (!Status)
+ {
+ DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage() failed\n"));
+ return Status;
+ }
+
+ /* Allocate DTE for newly loaded DLL */
+ Status = WinLdrAllocateDataTableEntry(WinLdrBlock,
+ ImportName,
+ FullDllName,
+ BasePA,
+ DataTableEntry);
+
+ if (!Status)
+ {
+ DbgPrint((DPRINT_WINDOWS,
+ "WinLdrAllocateDataTableEntry() failed with Status=0x%X\n", Status));
+ return Status;
+ }
+
+ /* Scan its dependencies too */
+ DbgPrint((DPRINT_WINDOWS,
+ "WinLdrScanImportDescriptorTable() calling ourselves for %S\n",
+ VaToPa((*DataTableEntry)->BaseDllName.Buffer)));
+ Status = WinLdrScanImportDescriptorTable(WinLdrBlock, DirectoryPath, *DataTableEntry);
+
+ if (!Status)
+ {
+ DbgPrint((DPRINT_WINDOWS,
+ "WinLdrScanImportDescriptorTable() failed with Status=0x%X\n", Status));
+ return Status;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+WinLdrpScanImportAddressTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ IN PVOID DllBase,
+ IN PVOID ImageBase,
+ IN PIMAGE_THUNK_DATA ThunkData)
+{
+ PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
+ BOOLEAN Status;
+ ULONG ExportSize;
+
+ DbgPrint((DPRINT_WINDOWS, "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)
+ {
+ //Print(L"Error, DllBase == NULL!\n");
+ return FALSE;
+ }
+ else
+ {
+ ExportDirectory =
+ (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(VaToPa(DllBase),
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportSize);
+ }
+
+ DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable(): ExportDirectory
0x%X\n", ExportDirectory));
+
+ /* If pointer to Export Directory is */
+ if (ExportDirectory == NULL)
+ return FALSE;
+
+ /* Go through each entry in the thunk table and bind it */
+ while (((PIMAGE_THUNK_DATA)VaToPa(ThunkData))->u1.AddressOfData != 0)
+ {
+ /* Bind it */
+ Status = WinLdrpBindImportName(
+ WinLdrBlock,
+ DllBase,
+ ImageBase,
+ ThunkData,
+ ExportDirectory,
+ ExportSize,
+ FALSE);
+
+ /* Move to the next entry */
+ ThunkData++;
+
+ /* Return error if binding was unsuccessful */
+ if (!Status)
+ return Status;
+ }
+
+ /* Return success */
+ return TRUE;
+}
Modified: trunk/reactos/boot/freeldr/freeldr/windows/winldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/winldr.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/windows/winldr.c Mon Feb 4 13:45:55 2008
@@ -30,6 +30,7 @@
extern char reactos_arc_strings[32][256];
extern BOOLEAN UseRealHeap;
+extern ULONG LoaderPagesSpanned;
BOOLEAN
WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
@@ -186,12 +187,11 @@
}
RtlZeroMemory(Extension, sizeof(LOADER_PARAMETER_EXTENSION));
- /* Save size and version information */
+ /* Fill LPB extension */
Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8;
Extension->MinorVersion = VersionToBoot & 0xFF;
- Extension->LoaderPagesSpanned = LOADER_HIGH_ZONE;
-
+ Extension->Profile.Status = 2;
LoaderBlock->Extension = PaToVa(Extension);
}
@@ -208,8 +208,8 @@
ULONG_PTR Tss = 0;
ULONG BlockSize, NumPages;
- LoaderBlock->u.I386.CommonDataArea = NULL;//CommonDataArea;
- //LoaderBlock->u.I386.MachineType = MachineType; //FIXME: MachineType?
+ LoaderBlock->u.I386.CommonDataArea = NULL; //CommonDataArea;
+ LoaderBlock->u.I386.MachineType = 0; // ntldr sets this to 0
/* Allocate 2 pages for PCR */
Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
@@ -483,11 +483,11 @@
Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
DbgPrint((DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status));
+ /* Alloc PCR, TSS, do magic things with the GDT/IDT */
+ WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
+
/* Initialize Phase 1 - no drivers loading anymore */
WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemPath, OperatingSystemVersion);
-
- /* Alloc PCR, TSS, do magic things with the GDT/IDT */
- WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
/* Save entry-point pointer and Loader block VAs */
KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
@@ -506,6 +506,9 @@
/* Turn on paging mode of CPU*/
WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
+ /* Save final value of LoaderPagesSpanned */
+ LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
+
DbgPrint((DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA
%p!\n",
KiSystemStartup, LoaderBlockVA));
Modified: trunk/reactos/boot/freeldr/freeldr/windows/wlmemory.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/wlmemory.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/windows/wlmemory.c Mon Feb 4 13:45:55 2008
@@ -14,6 +14,7 @@
#include <debug.h>
extern ULONG TotalNLSSize;
+extern ULONG LoaderPagesSpanned;
// This is needed because headers define wrong one for ReactOS
#undef KIP0PCRADDRESS
@@ -131,13 +132,13 @@
// PDE, HAL mapping page table, physical mapping, kernel mapping
TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;
+ // PDE+HAL+KernelPTEs == MemoryData
+ Buffer = MmAllocateMemoryWithType(
+ TotalSize - NumPageTables*MM_PAGE_SIZE, LoaderMemoryData);
+
// Physical PTEs = FirmwareTemporary
PhysicalPageTablesBuffer = MmAllocateMemoryWithType(
NumPageTables*MM_PAGE_SIZE, LoaderFirmwareTemporary);
-
- // PDE+HAL+KernelPTEs == MemoryData
- Buffer = MmAllocateMemoryWithType(
- TotalSize - NumPageTables*MM_PAGE_SIZE, LoaderMemoryData);
if (Buffer + (TotalSize - NumPageTables*MM_PAGE_SIZE) !=
PhysicalPageTablesBuffer)
@@ -290,23 +291,22 @@
if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
Mad[i].MemoryType == LoaderSpecialMemory ||
Mad[i].MemoryType == LoaderFree ||
- (Mad[i].MemoryType == LoaderFirmwareTemporary && EndPage <=
LOADER_HIGH_ZONE) ||
+ (Mad[i].MemoryType == LoaderFirmwareTemporary && EndPage <=
LoaderPagesSpanned) ||
Mad[i].MemoryType == LoaderOsloaderStack ||
Mad[i].MemoryType == LoaderLoadedProgram)
{
-
//
// But, the first megabyte of memory always stays!
// And, to tell the truth, we don't care about what's higher
- // than LOADER_HIGH_ZONE
+ // than LoaderPagesSpanned
if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
Mad[i].MemoryType == LoaderSpecialMemory)
{
if (StartPage < 0x100)
StartPage = 0x100;
- if (EndPage > LOADER_HIGH_ZONE)
- EndPage = LOADER_HIGH_ZONE;
+ if (EndPage > LoaderPagesSpanned)
+ EndPage = LoaderPagesSpanned;
}
for (Page = StartPage; Page < EndPage; Page++)
@@ -330,7 +330,6 @@
}
}
-
VOID
MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
ULONG BasePage,
@@ -361,7 +360,7 @@
// Check if it's more than the allowed for OS loader
// if yes - don't map the pages, just add as FirmwareTemporary
//
- if (BasePage + PageCount > LOADER_HIGH_ZONE)
+ if (BasePage + PageCount > LoaderPagesSpanned)
{
if (Mad[MadCount].MemoryType != LoaderSpecialMemory &&
Mad[MadCount].MemoryType != LoaderFirmwarePermanent &&