[ros-diffs] [fireball] 32113: - 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.

fireball at svn.reactos.org fireball at svn.reactos.org
Mon Feb 4 11:45:55 CET 2008


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/i386/loader.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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/blocklist.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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/cache.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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/fat.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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/include/mm.h?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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/meminit.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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/windows/peloader.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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 at 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 at 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/windows/winldr.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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/windows/wlmemory.c?rev=32113&r1=32112&r2=32113&view=diff
==============================================================================
--- 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 &&




More information about the Ros-diffs mailing list