Implement and use LdrProcessRelocationBlock().
authorEric Kohl <eric.kohl@reactos.org>
Sun, 27 Jun 2004 12:21:14 +0000 (12:21 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 27 Jun 2004 12:21:14 +0000 (12:21 +0000)
svn path=/trunk/; revision=9905

reactos/include/ntdll/ldr.h
reactos/lib/ntdll/def/ntdll.def
reactos/lib/ntdll/def/ntdll.edf
reactos/lib/ntdll/ldr/utils.c

index 8075d53..e4a05e1 100644 (file)
@@ -126,6 +126,12 @@ LdrLoadDll(IN PWSTR SearchPath OPTIONAL,
           IN PUNICODE_STRING Name,
           OUT PVOID *BaseAddress OPTIONAL);
 
+PIMAGE_BASE_RELOCATION STDCALL
+LdrProcessRelocationBlock(IN PVOID Address,
+                         IN USHORT Count,
+                         IN PUSHORT TypeOffset,
+                         IN ULONG_PTR Delta);
+
 NTSTATUS STDCALL
 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey,
                                   IN PCWSTR ValueName,
index 7f6b2e0..376a348 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: ntdll.def,v 1.121 2004/06/13 10:35:52 navaraf Exp $
+; $Id: ntdll.def,v 1.122 2004/06/27 12:21:14 ekohl Exp $
 ;
 ; ReactOS Operating System
 ;
@@ -51,7 +51,7 @@ LdrGetDllHandle@16
 LdrGetProcedureAddress@16
 LdrInitializeThunk@16
 LdrLoadDll@16
-;LdrProcessRelocationBlock@16
+LdrProcessRelocationBlock@16
 LdrQueryImageFileExecutionOptions@24
 LdrQueryProcessModuleInformation@12
 LdrShutdownProcess@0
index d7c771d..c21b6a8 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: ntdll.edf,v 1.111 2004/06/13 10:35:52 navaraf Exp $
+; $Id: ntdll.edf,v 1.112 2004/06/27 12:21:14 ekohl Exp $
 ;
 ; ReactOS Operating System
 ;
@@ -51,7 +51,7 @@ LdrGetDllHandle=LdrGetDllHandle@16
 LdrGetProcedureAddress=LdrGetProcedureAddress@16
 LdrInitializeThunk=LdrInitializeThunk@16
 LdrLoadDll=LdrLoadDll@16
-;LdrProcessRelocationBlock
+LdrProcessRelocationBlock=LdrProcessRelocationBlock@16
 LdrQueryImageFileExecutionOptions=LdrQueryImageFileExecutionOptions@24
 LdrQueryProcessModuleInformation=LdrQueryProcessModuleInformation@12
 LdrShutdownProcess=LdrShutdownProcess@0
index e68ef93..54fe950 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: utils.c,v 1.95 2004/06/26 15:11:14 navaraf Exp $
+/* $Id: utils.c,v 1.96 2004/06/27 12:20:33 ekohl Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -1226,10 +1226,10 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
 {
   PIMAGE_DATA_DIRECTORY RelocationDDir;
   PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
-  ULONG Count, ProtectSize, OldProtect, OldProtect2, i;
+  ULONG Count, ProtectSize, OldProtect, OldProtect2;
   PVOID Page, ProtectPage, ProtectPage2;
-  PWORD TypeOffset;
-  ULONG Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
+  PUSHORT TypeOffset;
+  ULONG_PTR Delta;
   NTSTATUS Status;
 
   if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
@@ -1244,19 +1244,21 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
     {
       return STATUS_SUCCESS;
     }
-   
+
   ProtectSize = PAGE_SIZE;
-  RelocationDir = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)ImageBase + 
+  Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
+  RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
                   RelocationDDir->VirtualAddress);
-  RelocationEnd = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)ImageBase +
+  RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
                   RelocationDDir->VirtualAddress + RelocationDDir->Size);
+
   while (RelocationDir < RelocationEnd &&
          RelocationDir->SizeOfBlock > 0)
     {
       Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
-              sizeof(WORD);
+              sizeof(USHORT);
       Page = ImageBase + RelocationDir->VirtualAddress;
-      TypeOffset = (PWORD)(RelocationDir + 1);
+      TypeOffset = (PUSHORT)(RelocationDir + 1);
 
       /* Unprotect the page(s) we're about to relocate. */
       ProtectPage = Page;
@@ -1268,7 +1270,7 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
       if (!NT_SUCCESS(Status))
         {
           DPRINT1("Failed to unprotect relocation target.\n");
-          return(Status);
+          return Status;
         }
 
       if (RelocationDir->VirtualAddress + PAGE_SIZE <
@@ -1288,36 +1290,21 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
                                      &ProtectSize,
                                      OldProtect,
                                      &OldProtect);
-              return(Status);
+              return Status;
             }
         }
-
-      /* Patch the page. */
-      for (i = 0; i < Count; i++)
+      else
         {
-          SHORT Offset = TypeOffset[i] & 0xFFF;
-          USHORT Type = TypeOffset[i] >> 12;
-
-          switch (Type)
-            {
-              case IMAGE_REL_BASED_ABSOLUTE:
-                break;
-              case IMAGE_REL_BASED_HIGH:
-                *(PUSHORT)(Page + Offset) += HIWORD(Delta);
-                break;
-              case IMAGE_REL_BASED_LOW:
-                *(PUSHORT)(Page + Offset) += LOWORD(Delta);
-                break;
-              case IMAGE_REL_BASED_HIGHLOW:
-                *(PULONG)(Page + Offset) += Delta;
-                break;
-              case IMAGE_REL_BASED_HIGHADJ:
-              default:
-                DPRINT("Unknown/unsupported fixup type %d.\n", type);
-                return STATUS_UNSUCCESSFUL;
-            }
+          ProtectPage2 = NULL;
         }
 
+      RelocationDir = LdrProcessRelocationBlock(Page,
+                                                Count,
+                                                TypeOffset,
+                                                Delta);
+      if (RelocationDir == NULL)
+        return STATUS_UNSUCCESSFUL;
+
       /* Restore old page protection. */
       NtProtectVirtualMemory(NtCurrentProcess(),
                              &ProtectPage,
@@ -1325,8 +1312,7 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
                              OldProtect,
                              &OldProtect);
 
-      if (RelocationDir->VirtualAddress + PAGE_SIZE <
-          NTHeaders->OptionalHeader.SizeOfImage)
+      if (ProtectPage2 != NULL)
         {
           NtProtectVirtualMemory(NtCurrentProcess(),
                                  &ProtectPage2,
@@ -1334,9 +1320,6 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
                                  OldProtect2,
                                  &OldProtect2);
         }
-
-      RelocationDir = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)RelocationDir +
-                      RelocationDir->SizeOfBlock);
     }
 
   return STATUS_SUCCESS;
@@ -3030,4 +3013,55 @@ LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey,
   return Status;
 }
 
+
+PIMAGE_BASE_RELOCATION STDCALL
+LdrProcessRelocationBlock(IN PVOID Address,
+                         IN USHORT Count,
+                         IN PUSHORT TypeOffset,
+                         IN ULONG_PTR Delta)
+{
+  SHORT Offset;
+  USHORT Type;
+  USHORT i;
+  PUSHORT ShortPtr;
+  PULONG LongPtr;
+
+  for (i = 0; i < Count; i++)
+    {
+      Offset = *TypeOffset & 0xFFF;
+      Type = *TypeOffset >> 12;
+
+      switch (Type)
+        {
+          case IMAGE_REL_BASED_ABSOLUTE:
+            break;
+
+          case IMAGE_REL_BASED_HIGH:
+            ShortPtr = (PUSHORT)(Address + Offset);
+            *ShortPtr += HIWORD(Delta);
+            break;
+
+          case IMAGE_REL_BASED_LOW:
+            ShortPtr = (PUSHORT)(Address + Offset);
+            *ShortPtr += LOWORD(Delta);
+            break;
+
+          case IMAGE_REL_BASED_HIGHLOW:
+            LongPtr = (PULONG)(Address + Offset);
+            *LongPtr += Delta;
+            break;
+
+          case IMAGE_REL_BASED_HIGHADJ:
+          case IMAGE_REL_BASED_MIPS_JMPADDR:
+          default:
+            DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
+            return NULL;
+        }
+
+      TypeOffset++;
+    }
+
+  return (PIMAGE_BASE_RELOCATION)TypeOffset;
+}
+
 /* EOF */