- Revert 24020 (good code, but buggy) and 24041 (bad code/revision).
authorAlex Ionescu <aionescu@gmail.com>
Tue, 12 Sep 2006 05:21:27 +0000 (05:21 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Tue, 12 Sep 2006 05:21:27 +0000 (05:21 +0000)
- This gets us as far as 24061(+24048) for booting.

svn path=/trunk/; revision=24078

reactos/dll/ntdll/ldr/utils.c
reactos/lib/rtl/image.c
reactos/ntoskrnl/include/internal/po.h
reactos/ntoskrnl/ke/thrdobj.c
reactos/ntoskrnl/ke/thrdschd.c

index 5fbb7d9..f7a94cd 100644 (file)
@@ -1198,89 +1198,126 @@ LdrGetExportByName(PVOID BaseAddress,
    return (PVOID)NULL;
 }
 
-/*++
-* @name LdrpSetProtection
-*
-*     Local routine, used to set or reset pages protection.
-*     Used during PE relocation process.
-*
-* @param BaseAddress
-*        Base address of the image.
-*
-* @param Protection
-*        FALSE to disable protection, TRUE to enable it
-*
-* @return Usual NTSTATUS.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-LdrpSetProtection(IN PVOID BaseAddress,
-                  IN BOOLEAN Protection)
-{
-    PIMAGE_NT_HEADERS NtHeaders;
-    PIMAGE_SECTION_HEADER SectionHeader;
-    ULONG i;
-    PVOID Address;
-    SIZE_T Size;
-    NTSTATUS Status;
-    ULONG NewAccess, OldAccess;
 
-    NtHeaders = RtlImageNtHeader(BaseAddress);
+/**********************************************************************
+ * NAME                                                         LOCAL
+ *      LdrPerformRelocations
+ *
+ * DESCRIPTION
+ *      Relocate a DLL's memory image.
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ *
+ * NOTE
+ *
+ */
+static NTSTATUS
+LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
+                      PVOID ImageBase)
+{
+  PIMAGE_DATA_DIRECTORY RelocationDDir;
+  PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
+  ULONG Count, ProtectSize, OldProtect, OldProtect2;
+  PVOID Page, ProtectPage, ProtectPage2;
+  PUSHORT TypeOffset;
+  ULONG_PTR Delta;
+  NTSTATUS Status;
 
-    /* Ensure image is valid */
-    if (NtHeaders == NULL)
-        return STATUS_INVALID_IMAGE_FORMAT;
+  if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+    {
+      return STATUS_UNSUCCESSFUL;
+    }
 
-    /* Get the first section header */
-    SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
+  RelocationDDir =
+    &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
 
-    /* Loop through every section */
-    for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++)
+  if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
     {
-        /* If section has no data - just skip to the next section */
-        if (SectionHeader->SizeOfRawData == 0)
-            continue;
+      return STATUS_SUCCESS;
+    }
 
-        /* We need to act only if section isn't RW */
-        if (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))
+  ProtectSize = PAGE_SIZE;
+  Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
+  RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
+                  RelocationDDir->VirtualAddress);
+  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(USHORT);
+      Page = (PVOID)((ULONG_PTR)ImageBase + (ULONG_PTR)RelocationDir->VirtualAddress);
+      TypeOffset = (PUSHORT)(RelocationDir + 1);
+
+      /* Unprotect the page(s) we're about to relocate. */
+      ProtectPage = Page;
+      Status = NtProtectVirtualMemory(NtCurrentProcess(),
+                                      &ProtectPage,
+                                      &ProtectSize,
+                                      PAGE_READWRITE,
+                                      &OldProtect);
+      if (!NT_SUCCESS(Status))
         {
-            if (Protection)
-            {
-                /* Check if the section was also executable, then we should
-                   give it PAGE_EXECUTE, otherwise just PAGE_READONLY */
-                NewAccess = (SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ? PAGE_EXECUTE : PAGE_READONLY;
+          DPRINT1("Failed to unprotect relocation target.\n");
+          return Status;
+        }
 
-                /* Also check caching */
-                NewAccess |= (SectionHeader->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) ? PAGE_NOCACHE : 0;
-            }
-            else
+      if (RelocationDir->VirtualAddress + PAGE_SIZE <
+          NTHeaders->OptionalHeader.SizeOfImage)
+        {
+          ProtectPage2 = (PVOID)((ULONG_PTR)ProtectPage + PAGE_SIZE);
+          Status = NtProtectVirtualMemory(NtCurrentProcess(),
+                                          &ProtectPage2,
+                                          &ProtectSize,
+                                          PAGE_READWRITE,
+                                          &OldProtect2);
+          if (!NT_SUCCESS(Status))
             {
-                /* Set access to RW */
-                NewAccess = PAGE_READWRITE;
+              DPRINT1("Failed to unprotect relocation target (2).\n");
+              NtProtectVirtualMemory(NtCurrentProcess(),
+                                     &ProtectPage,
+                                     &ProtectSize,
+                                     OldProtect,
+                                     &OldProtect);
+              return Status;
             }
+        }
+      else
+        {
+          ProtectPage2 = NULL;
+        }
 
-            /* Get the address and size of the section, and set protectin accordingly */
-            Address = (PVOID)((ULONG_PTR)BaseAddress + SectionHeader->VirtualAddress);
-            Size = SectionHeader->SizeOfRawData;
-
-            Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                &Address,
-                &Size,
-                NewAccess,
-                &OldAccess);
-
-            if (!NT_SUCCESS(Status))
-                return Status;
+      RelocationDir = LdrProcessRelocationBlock((ULONG_PTR)Page,
+                                                Count,
+                                                TypeOffset,
+                                                Delta);
+      if (RelocationDir == NULL)
+        return STATUS_UNSUCCESSFUL;
+
+      /* Restore old page protection. */
+      NtProtectVirtualMemory(NtCurrentProcess(),
+                             &ProtectPage,
+                             &ProtectSize,
+                             OldProtect,
+                             &OldProtect);
+
+      if (ProtectPage2 != NULL)
+        {
+          NtProtectVirtualMemory(NtCurrentProcess(),
+                                 &ProtectPage2,
+                                 &ProtectSize,
+                                 OldProtect2,
+                                 &OldProtect2);
         }
     }
 
-    /* Instruction cache should be flushed if we enabled protection */
-    if (Protection)
-        NtFlushInstructionCache(NtCurrentProcess(), NULL, 0);
-
-    return STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 static NTSTATUS
@@ -1861,32 +1898,12 @@ PEPFUNC LdrPEStartup (PVOID  ImageBase,
    if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
      {
        DPRINT("LDR: Performing relocations\n");
-
-       /* Remove protection */
-       Status = LdrpSetProtection(ImageBase, FALSE);
-       if (!NT_SUCCESS(Status))
-         {
-           DPRINT1("LdrpSetProtection() failed with Status=0x%08X\n", Status);
-           return NULL;
-         }
-
-       /* Relocate */
-       Status = LdrRelocateImageWithBias(ImageBase, 0, "", STATUS_SUCCESS,
-           STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
-       if (!NT_SUCCESS(Status))
-         {
-           DPRINT1("LdrRelocateImageWithBias() failed with Status=0x%08X\n", Status);
-           return NULL;
-         }
-
-       /* Set protection back */
-       Status = LdrpSetProtection(ImageBase, TRUE);
+       Status = LdrPerformRelocations(NTHeaders, ImageBase);
        if (!NT_SUCCESS(Status))
          {
-           DPRINT1("LdrpSetProtection() failed with Status=0x%08X\n", Status);
+           DPRINT1("LdrPerformRelocations() failed\n");
            return NULL;
          }
-
      }
 
    if (Module != NULL)
@@ -2061,13 +2078,10 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
           {
             DPRINT1("Relocating (%lx -> %p) %wZ\n",
               NtHeaders->OptionalHeader.ImageBase, ImageBase, &FullDosName);
-
-            Status = LdrRelocateImageWithBias(ImageBase, 0, "", STATUS_SUCCESS,
-                STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
-
+            Status = LdrPerformRelocations(NtHeaders, ImageBase);
             if (!NT_SUCCESS(Status))
               {
-                DPRINT1("LdrRelocateImageWithBias() failed\n");
+                DPRINT1("LdrPerformRelocations() failed\n");
                 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
                 NtClose (SectionHandle);
                 RtlFreeUnicodeString(&FullDosName);
index 388e3ac..97b5a9b 100644 (file)
@@ -3,10 +3,8 @@
  * FILE:            lib/rtl/image.c
  * PURPOSE:         Image handling functions
  *                  Relocate functions were previously located in
- *                  ntoskrnl/ldr/loader.c and
- *                  dll/ntdll/ldr/utils.c files
- * PROGRAMMER:      Eric Kohl + original authors from loader.c and utils.c file
- *                  Aleksey Bragin
+ *                  ntoskrnl/ldr/loader.c
+ * PROGRAMMER:      Eric Kohl + original authors from loader.c file
  */
 
 /* INCLUDES *****************************************************************/
@@ -151,76 +149,12 @@ RtlImageRvaToVa (
                       (ULONG_PTR)Section->VirtualAddress);
 }
 
-PIMAGE_BASE_RELOCATION
-LdrProcessRelocationBlockLongLong(
-    IN ULONG_PTR Address,
-    IN ULONG Count,
-    IN PUSHORT TypeOffset,
-    IN LONGLONG Delta
-    )
-{
-    SHORT Offset;
-    USHORT Type;
-    USHORT i;
-    PUSHORT ShortPtr;
-    PULONG LongPtr;
-
-    for (i = 0; i < Count; i++)
-    {
-        Offset = *TypeOffset & 0xFFF;
-        Type = *TypeOffset >> 12;
-        ShortPtr = (PUSHORT)(RVA(Address, Offset));
-
-        /*
-        * Don't relocate within the relocation section itself.
-        * GCC/LD generates sometimes relocation records for the relocation section.
-        * This is a bug in GCC/LD.
-        * Fix for it disabled, since it was only in ntoskrnl and not in ntdll
-        */
-        /*
-        if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
-        (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
-        {*/
-        switch (Type)
-        {
-        /* case IMAGE_REL_BASED_SECTION : */
-        /* case IMAGE_REL_BASED_REL32 : */
-        case IMAGE_REL_BASED_ABSOLUTE:
-            break;
-
-        case IMAGE_REL_BASED_HIGH:
-            *ShortPtr += HIWORD(Delta);
-            break;
-
-        case IMAGE_REL_BASED_LOW:
-            *ShortPtr += LOWORD(Delta);
-            break;
-
-        case IMAGE_REL_BASED_HIGHLOW:
-            LongPtr = (PULONG)RVA(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);
-            DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
-            return (PIMAGE_BASE_RELOCATION)NULL;
-        }
-
-        TypeOffset++;
-    }
-
-    return (PIMAGE_BASE_RELOCATION)TypeOffset;
-}
-
 ULONG
 NTAPI
 LdrRelocateImageWithBias(
     IN PVOID BaseAddress,
     IN LONGLONG AdditionalBias,
-    IN PCCH LoaderName,
+    IN PCCH  LoaderName,
     IN ULONG Success,
     IN ULONG Conflict,
     IN ULONG Invalid
@@ -229,10 +163,14 @@ LdrRelocateImageWithBias(
     PIMAGE_NT_HEADERS NtHeaders;
     PIMAGE_DATA_DIRECTORY RelocationDDir;
     PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
-    ULONG Count;
-    ULONG_PTR Address;
+    ULONG Count, i;
+    PVOID Address;//, MaxAddress;
     PUSHORT TypeOffset;
-    LONGLONG Delta;
+    ULONG_PTR Delta;
+    SHORT Offset;
+    USHORT Type;
+    PUSHORT ShortPtr;
+    PULONG LongPtr;
 
     NtHeaders = RtlImageNtHeader(BaseAddress);
 
@@ -254,24 +192,64 @@ LdrRelocateImageWithBias(
     Delta = (ULONG_PTR)BaseAddress - NtHeaders->OptionalHeader.ImageBase + AdditionalBias;
     RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + RelocationDDir->VirtualAddress);
     RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
+    //MaxAddress = RVA(BaseAddress, DriverSize);
 
     while (RelocationDir < RelocationEnd &&
         RelocationDir->SizeOfBlock > 0)
     {
         Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
-        Address = (ULONG_PTR)RVA(BaseAddress, RelocationDir->VirtualAddress);
+        Address = RVA(BaseAddress, RelocationDir->VirtualAddress);
         TypeOffset = (PUSHORT)(RelocationDir + 1);
 
-        RelocationDir = LdrProcessRelocationBlockLongLong(Address,
-                                                          Count,
-                                                          TypeOffset,
-                                                          Delta);
-
-        if (RelocationDir == NULL)
+        for (i = 0; i < Count; i++)
         {
-            DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");
-            return Invalid;
+            Offset = *TypeOffset & 0xFFF;
+            Type = *TypeOffset >> 12;
+            ShortPtr = (PUSHORT)(RVA(Address, Offset));
+
+            /* Don't relocate after the end of the loaded driver */
+            /*if ((PVOID)ShortPtr >= MaxAddress)
+            {
+                break;
+            }*/
+
+            /*
+            * Don't relocate within the relocation section itself.
+            * GCC/LD generates sometimes relocation records for the relocation section.
+            * This is a bug in GCC/LD.
+            */
+            if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
+                (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
+            {
+                switch (Type)
+                {
+                case IMAGE_REL_BASED_ABSOLUTE:
+                    break;
+
+                case IMAGE_REL_BASED_HIGH:
+                    *ShortPtr += HIWORD(Delta);
+                    break;
+
+                case IMAGE_REL_BASED_LOW:
+                    *ShortPtr += LOWORD(Delta);
+                    break;
+
+                case IMAGE_REL_BASED_HIGHLOW:
+                    LongPtr = (PULONG)ShortPtr;
+                    *LongPtr += Delta;
+                    break;
+
+                case IMAGE_REL_BASED_HIGHADJ:
+                case IMAGE_REL_BASED_MIPS_JMPADDR:
+                default:
+                    DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
+                    DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
+                    return Invalid;
+                }
+            }
+            TypeOffset++;
         }
+        RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
     }
 
     return Success;
index 6d6ce24..5677d28 100644 (file)
@@ -1,15 +1,54 @@
-#ifndef __NTOSKRNL_INCLUDE_INTERNAL_PO_H
-#define __NTOSKRNL_INCLUDE_INTERNAL_PO_H
+/*
+* PROJECT:         ReactOS Kernel
+* LICENSE:         GPL - See COPYING in the top level directory
+* FILE:            ntoskrnl/include/po.h
+* PURPOSE:         Internal header for the Power Manager
+* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+*/
 
-extern PDEVICE_NODE PopSystemPowerDeviceNode;
+//
+// Define this if you want debugging support
+//
+#define _PO_DEBUG_                                      0x00
+
+//
+// These define the Debug Masks Supported
+//
+#define PO_STATE_DEBUG                                  0x01
 
+//
+// Debug/Tracing support
+//
+#if _PO_DEBUG_
+#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
+#define POTRACE DbgPrintEx
+#else
+#define POTRACE(x, ...)                                 \
+    if (x & PopTraceLevel) DbgPrint(__VA_ARGS__)
+#endif
+#else
+#define POTRACE(x, ...) DPRINT(__VA_ARGS__)
+#endif
+
+//
+// Initialization routines
+//
 VOID
 NTAPI
 PoInit(
-    PROS_LOADER_PARAMETER_BLOCK LoaderBlock, 
+    PROS_LOADER_PARAMETER_BLOCK LoaderBlock,
     BOOLEAN ForceAcpiDisable
 );
 
+VOID
+NTAPI
+PoInitializePrcb(
+    IN PKPRCB Prcb
+);
+
+//
+// Power State routines
+//
 NTSTATUS
 NTAPI
 PopSetSystemPowerState(
@@ -22,10 +61,7 @@ PopCleanupPowerState(
     IN PPOWER_STATE PowerState
 );
 
-VOID
-NTAPI
-PoInitializePrcb(
-    IN PKPRCB Prcb
-);
-
-#endif /* __NTOSKRNL_INCLUDE_INTERNAL_PO_H */
+//
+// Global data inside the Power Manager
+//
+extern PDEVICE_NODE PopSystemPowerDeviceNode;
index 15d9435..3841656 100644 (file)
@@ -697,6 +697,12 @@ KeInitThread(IN OUT PKTHREAD Thread,
     Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE;\r
     Thread->KernelStackResident = TRUE;\r
 \r
+    /* ROS Mm HACK */\r
+    MmUpdatePageDir((PEPROCESS)Process,\r
+                    (PVOID)Thread->StackLimit,\r
+                    KERNEL_STACK_SIZE);\r
+    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));\r
+\r
     /* Enter SEH to avoid crashes due to user mode */\r
     Status = STATUS_SUCCESS;\r
     _SEH_TRY\r
index 9bda109..9425307 100644 (file)
@@ -150,6 +150,8 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus)
                 KiIdleSummary |= Affinity;\r
             }\r
 \r
+            MmUpdatePageDir((PEPROCESS)PsGetCurrentProcess(),((PETHREAD)CurrentThread)->ThreadsProcess, sizeof(EPROCESS));\r
+\r
             /* Special note for Filip: This will release the Dispatcher DB Lock ;-) -- Alex */\r
             DPRINT("You are : %x, swapping to: %x.\n", OldThread, CurrentThread);\r
             ApcState = KiSwapContext(OldThread, CurrentThread);\r