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 &&