+User acceptable message on incompatible W32 binary modules.
[reactos.git] / ntoskrnl / ldr / loader.c
index eba5f27..90a6200 100644 (file)
@@ -18,6 +18,7 @@
  *   JF   26/01/2000 Recoded some parts to retrieve export details correctly
  *   DW   27/06/2000 Removed redundant header files
  *   CSH  11/04/2001 Added automatic loading of module symbols if they exist
+ *   KJK  02/04/2003 Nebbet-ized a couple of type names
  */
 
 
 #define NDEBUG
 #include <internal/debug.h>
 
+#ifdef LIBCAPTIVE
+#include <glib/gmessages.h>
+#endif /* LIBCAPTIVE */
+
 /* GLOBALS *******************************************************************/
 
 LIST_ENTRY ModuleListHead;
 KSPIN_LOCK ModuleListLock;
 
 LIST_ENTRY ModuleTextListHead;
+#ifndef LIBCAPTIVE
 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
 STATIC MODULE_TEXT_SECTION LdrHalTextSection;
+#endif /* LIBCAPTIVE */
 ULONG_PTR LdrHalBase;
 
 #define TAG_DRIVER_MEM  TAG('D', 'R', 'V', 'M')
@@ -70,7 +77,10 @@ LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
                    char *Name,
                    unsigned short Hint);
 
-static VOID
+#ifndef LIBCAPTIVE
+static
+#endif /* LIBCAPTIVE */
+VOID
 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
                        PUNICODE_STRING FullName);
 
@@ -88,10 +98,12 @@ LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
                      PCHAR Name,
                      USHORT Hint);
 
+#ifndef LIBCAPTIVE
 static PVOID
 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
                          PCHAR Name,
                          USHORT Hint);
+#endif /* LIBCAPTIVE */
 
 static PVOID
 LdrPEFixupForward(PCHAR ForwardName);
@@ -99,6 +111,8 @@ LdrPEFixupForward(PCHAR ForwardName);
 
 /* FUNCTIONS *****************************************************************/
 
+#ifndef LIBCAPTIVE
+
 VOID
 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
 {
@@ -418,6 +432,7 @@ LdrLoadModule(PUNICODE_STRING Filename,
   return(STATUS_SUCCESS);
 }
 
+#endif /* LIBCAPTIVE */
 
 NTSTATUS
 LdrUnloadModule(PMODULE_OBJECT ModuleObject)
@@ -449,6 +464,7 @@ LdrUnloadModule(PMODULE_OBJECT ModuleObject)
   return(STATUS_SUCCESS);
 }
 
+#ifndef LIBCAPTIVE
 
 NTSTATUS
 LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
@@ -533,10 +549,13 @@ LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
     Length = wcslen(Start);
 
   wcsncpy(Buffer, Start, Length);
+  Buffer[Length] = 0;
   RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
 
   Status = IopInitializeDriver(ModuleObject->EntryPoint,
-                              DeviceNode, FALSE);
+                              DeviceNode, FALSE,
+                              ModuleObject->Base,
+                              ModuleObject->Length);
   if (!NT_SUCCESS(Status))
     {
       IopFreeDeviceNode(DeviceNode);
@@ -546,6 +565,7 @@ LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
   return(Status);
 }
 
+#endif /* LIBCAPTIVE */
 
 NTSTATUS
 LdrProcessModule(PVOID ModuleLoadBase,
@@ -583,6 +603,7 @@ LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
     }
 }
 
+#ifndef LIBCAPTIVE
 
 NTSTATUS
 LdrpQueryModuleInformation(PVOID Buffer,
@@ -608,7 +629,7 @@ LdrpQueryModuleInformation(PVOID Buffer,
     }
 
   *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
-    (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
+    (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY);
 
   if (Size < *ReqSize)
     {
@@ -628,15 +649,18 @@ LdrpQueryModuleInformation(PVOID Buffer,
     {
       current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
 
+      Smi->Module[ModuleCount].Unknown1 = 0;           /* Always 0 */
       Smi->Module[ModuleCount].Unknown2 = 0;           /* Always 0 */
-      Smi->Module[ModuleCount].BaseAddress = current->Base;
+      Smi->Module[ModuleCount].Base = current->Base;
       Smi->Module[ModuleCount].Size = current->Length;
       Smi->Module[ModuleCount].Flags = 0;              /* Flags ??? (GN) */
-      Smi->Module[ModuleCount].EntryIndex = ModuleCount;
+      Smi->Module[ModuleCount].Index = ModuleCount;
+      Smi->Module[ModuleCount].NameLength = 0;
+      Smi->Module[ModuleCount].LoadCount = 0; /* FIXME */
 
       AnsiName.Length = 0;
       AnsiName.MaximumLength = 256;
-      AnsiName.Buffer = Smi->Module[ModuleCount].Name;
+      AnsiName.Buffer = Smi->Module[ModuleCount].ImageName;
       RtlUnicodeStringToAnsiString(&AnsiName,
                                   &current->FullName,
                                   FALSE);
@@ -645,13 +669,11 @@ LdrpQueryModuleInformation(PVOID Buffer,
       if (p == NULL)
        {
          Smi->Module[ModuleCount].PathLength = 0;
-         Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
        }
       else
        {
          p++;
          Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
-         Smi->Module[ModuleCount].NameLength = strlen(p);
        }
 
       ModuleCount++;
@@ -663,8 +685,12 @@ LdrpQueryModuleInformation(PVOID Buffer,
   return(STATUS_SUCCESS);
 }
 
+#endif /* LIBCAPTIVE */
 
-static VOID
+#ifndef LIBCAPTIVE
+static
+#endif /* LIBCAPTIVE */
+VOID
 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
                        PUNICODE_STRING FullName)
 {
@@ -811,6 +837,40 @@ LdrGetModuleObject(PUNICODE_STRING ModuleName)
 
 /*  ----------------------------------------------  PE Module support */
 
+static BOOL
+PageNeedsWriteAccess(PVOID PageStart,
+                     PVOID DriverBase,
+                     PIMAGE_FILE_HEADER PEFileHeader,
+                     PIMAGE_SECTION_HEADER PESectionHeaders)
+{
+  BOOL NeedsWriteAccess;
+  unsigned Idx;
+  ULONG Characteristics;
+  ULONG Length;
+  PVOID BaseAddress;
+
+  NeedsWriteAccess = FALSE;
+  /* Set the protections for the various parts of the driver */
+  for (Idx = 0; Idx < PEFileHeader->NumberOfSections && ! NeedsWriteAccess; Idx++)
+    {
+      Characteristics = PESectionHeaders[Idx].Characteristics;
+      if (!(Characteristics & IMAGE_SECTION_CHAR_CODE) ||
+         (Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
+          Characteristics & IMAGE_SECTION_CHAR_DATA ||
+          Characteristics & IMAGE_SECTION_CHAR_BSS))
+       {
+         Length = 
+             max(PESectionHeaders[Idx].Misc.VirtualSize,
+                 PESectionHeaders[Idx].SizeOfRawData);
+         BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
+         NeedsWriteAccess = BaseAddress < PageStart + PAGE_SIZE &&
+                            PageStart < (PVOID)((PCHAR) BaseAddress + Length);
+       }
+    }
+
+  return(NeedsWriteAccess);
+}
+
 static NTSTATUS
 LdrPEProcessModule(PVOID ModuleLoadBase,
                   PUNICODE_STRING FileName,
@@ -1033,15 +1093,22 @@ LdrPEProcessModule(PVOID ModuleLoadBase,
           LibraryModuleObject = LdrGetModuleObject(&ModuleName);
           if (LibraryModuleObject == NULL)
             {
-              CPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
-              wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\");
+              DPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
+              wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\drivers\\"));
               wcscat(NameBuffer, ModuleName.Buffer);
               RtlInitUnicodeString(&NameString, NameBuffer);
               Status = LdrLoadModule(&NameString, &LibraryModuleObject);
               if (!NT_SUCCESS(Status))
                 {
-                  CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
-                  return(Status);
+                  wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\"));
+                  wcscat(NameBuffer, ModuleName.Buffer);
+                  RtlInitUnicodeString(&NameString, NameBuffer);
+                  Status = LdrLoadModule(&NameString, &LibraryModuleObject);
+                  if (!NT_SUCCESS(Status))
+                    {
+                      DPRINT1("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
+                      return(Status);
+                    }
                 }
             }
           /*  Get the import address list  */
@@ -1105,20 +1172,32 @@ LdrPEProcessModule(PVOID ModuleLoadBase,
       ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
       ULONG Length;
       PVOID BaseAddress;
-      ULONG i;
-      Length = 
-       max(PESectionHeaders[Idx].Misc.VirtualSize,
-           PESectionHeaders[Idx].SizeOfRawData);
-      BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
+      PVOID PageAddress;
       if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
          !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
            Characteristics & IMAGE_SECTION_CHAR_DATA ||
            Characteristics & IMAGE_SECTION_CHAR_BSS))
        {
-         for (i = 0; i < PAGE_ROUND_DOWN(Length) / PAGE_SIZE; i++)
+         Length = 
+             max(PESectionHeaders[Idx].Misc.VirtualSize,
+                 PESectionHeaders[Idx].SizeOfRawData);
+         BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
+         PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
+         if (! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
+           {
+             MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
+           }
+         PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
+         while ((PVOID)((PCHAR) PageAddress + PAGE_SIZE) <
+                (PVOID)((PCHAR) BaseAddress + Length))
            {
-             MmSetPageProtect(NULL, BaseAddress + (i * PAGE_SIZE), 
-                              PAGE_READONLY);
+             MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
+             PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
+           }
+         if (PageAddress < (PVOID)((PCHAR) BaseAddress + Length) &&
+             ! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
+           {
+             MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
            }
        }
     }
@@ -1195,6 +1274,7 @@ LdrPEProcessModule(PVOID ModuleLoadBase,
   return STATUS_SUCCESS;
 }
 
+#ifndef LIBCAPTIVE
 
 PVOID
 LdrSafePEProcessModule(PVOID ModuleLoadBase,
@@ -1338,7 +1418,7 @@ LdrSafePEProcessModule(PVOID ModuleLoadBase,
         {
          ULONG Offset;
          ULONG Type;
-         PDWORD RelocItem;
+         PULONG RelocItem;
 
          Offset = RelocEntry[Idx].TypeOffset & 0xfff;
          Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
@@ -1435,6 +1515,7 @@ LdrSafePEProcessModule(PVOID ModuleLoadBase,
   return(0);
 }
 
+#endif /* LIBCAPTIVE */
 
 static PVOID
 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
@@ -1494,21 +1575,31 @@ LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
     }
   else  /*  use hint  */
     {
+#ifndef LIBCAPTIVE
       ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
         FunctionList[Hint - ExportDir->Base]);
+#else /* !LIBCAPTIVE */
+      /* Ordinals not supported by libcaptive */
+      KeBugCheck(0);
+#endif /* !LIBCAPTIVE */
     }
 
   if (ExportAddress == NULL)
     {
-      CPRINT("Export not found for %d:%s\n",
+      DbgPrint("Export not found for %d:%s\n",
             Hint,
             Name != NULL ? Name : "(Ordinal)");
-      KeBugCheck(0);
+#ifdef LIBCAPTIVE
+      g_error("Please check the versions of \"ntfs.sys\" and \"ntoskrnl.exe\" - do they match each other?\n"
+              "Because export not found for: %d:%s",Hint,(Name ? Name : "(Ordinal)"));
+#endif /* LIBCAPTIVE */
+      KEBUGCHECK(0);
     }
 
   return(ExportAddress);
 }
 
+#ifndef LIBCAPTIVE
 
 static PVOID
 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
@@ -1565,11 +1656,12 @@ LdrSafePEGetExportAddress(PVOID ImportModuleBase,
       ps("Export not found for %d:%s\n",
         Hint,
         Name != NULL ? Name : "(Ordinal)");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   return ExportAddress;
 }
 
+#endif /* LIBCAPTIVE */
 
 static PVOID
 LdrPEFixupForward(PCHAR ForwardName)