Implement LOAD_LIBRARY_AS_DATAFILE flag
authorGé van Geldorp <ge@gse.nl>
Sun, 16 Jan 2005 09:36:19 +0000 (09:36 +0000)
committerGé van Geldorp <ge@gse.nl>
Sun, 16 Jan 2005 09:36:19 +0000 (09:36 +0000)
svn path=/trunk/; revision=13073

reactos/lib/ntdll/ldr/res.c
reactos/lib/ntdll/ldr/utils.c

index b829e98..6b28897 100644 (file)
@@ -110,12 +110,14 @@ LdrFindResource_U(PVOID BaseAddress,
     int j, pos = 0;
     LCID UserLCID, SystemLCID;
     LANGID UserLangID, SystemLangID;
+    BOOL MappedAsDataFile;
 
+    MappedAsDataFile = LdrMappedAsDataFile(&BaseAddress);
     DPRINT("LdrFindResource_U(%08x, %08x, %d, %08x)\n", BaseAddress, ResourceInfo, Level, ResourceDataEntry);
 
     /* Get the pointer to the resource directory */
     ResDir = (PIMAGE_RESOURCE_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress,
-                      TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
+                      ! MappedAsDataFile, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
     if (ResDir == NULL) {
         return STATUS_RESOURCE_DATA_NOT_FOUND;
     }
@@ -278,18 +280,20 @@ LdrAccessResource(IN  PVOID BaseAddress,
     ULONG DataSize;
     ULONG Offset = 0;
     ULONG Data;
+    BOOL MappedAsDataFile;
 
     if(!ResourceDataEntry)
         return STATUS_RESOURCE_DATA_NOT_FOUND;
 
+    MappedAsDataFile = LdrMappedAsDataFile(&BaseAddress);
     Data = (ULONG)RtlImageDirectoryEntryToData(BaseAddress,
                            TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &DataSize);
     if (Data == 0) {
         return STATUS_RESOURCE_DATA_NOT_FOUND;
     }
-    if ((ULONG)BaseAddress & 1) {
+    if (MappedAsDataFile) {
         /* loaded as ordinary file */
-        NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL));
+        NtHeader = RtlImageNtHeader(BaseAddress);
         Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
         Section = RtlImageRvaToSection(NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
         if (Section == NULL) {
index d08142f..1c85690 100644 (file)
@@ -61,7 +61,8 @@ static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hin
 static NTSTATUS LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
                                IN ULONG LoadFlags,
                                IN PUNICODE_STRING Name,
-                               OUT PLDR_MODULE *Module);
+                               OUT PLDR_MODULE *Module,
+                               OUT PVOID *BaseAddress OPTIONAL);
 static NTSTATUS LdrpAttachProcess(VOID);
 static VOID LdrpDetachProcess(BOOL UnloadAll);
 
@@ -83,6 +84,18 @@ LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule)
 
 #endif /* DBG || KDBG */
 
+BOOL
+LdrMappedAsDataFile(PVOID *BaseAddress)
+{
+  if (0 != ((DWORD_PTR) *BaseAddress & (PAGE_SIZE - 1)))
+    {
+      *BaseAddress = (PVOID) ((DWORD_PTR) *BaseAddress & ~ ((DWORD_PTR) PAGE_SIZE - 1));
+      return TRUE;
+    }
+
+   return FALSE;
+}
+
 static inline LONG LdrpDecrementLoadCount(PLDR_MODULE Module, BOOL Locked)
 {
    LONG LoadCount;
@@ -548,6 +561,7 @@ static NTSTATUS
 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
                     IN PUNICODE_STRING DllName,
                     OUT PUNICODE_STRING FullDosName,
+                    IN BOOL MapAsDataFile,
                     OUT PHANDLE SectionHandle)
 {
   WCHAR                 SearchPathBuffer[MAX_PATH];
@@ -558,8 +572,6 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
   char                  BlockBuffer [1024];
   PIMAGE_DOS_HEADER     DosHeader;
   PIMAGE_NT_HEADERS     NTHeaders;
-  PVOID                 ImageBase;
-  ULONG                 ImageSize;
   IO_STATUS_BLOCK       IoStatusBlock;
   NTSTATUS              Status;
   ULONG                 len;
@@ -663,11 +675,6 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
       return STATUS_UNSUCCESSFUL;
     }
 
-  ImageBase = (PVOID) NTHeaders->OptionalHeader.ImageBase;
-  ImageSize = NTHeaders->OptionalHeader.SizeOfImage;
-
-  DPRINT("ImageBase 0x%08x\n", ImageBase);
-
   /*
    * Create a section for dll.
    */
@@ -676,7 +683,7 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
                            NULL,
                            NULL,
                            PAGE_READWRITE,
-                           SEC_COMMIT | SEC_IMAGE,
+                           SEC_COMMIT | (MapAsDataFile ? 0 : SEC_IMAGE),
                            FileHandle);
   NtClose(FileHandle);
 
@@ -732,8 +739,8 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
 
   *BaseAddress = NULL;
 
-  Status = LdrpLoadModule(SearchPath, LoadFlags, Name, &Module);
-  if (NT_SUCCESS(Status))
+  Status = LdrpLoadModule(SearchPath, LoadFlags, Name, &Module, BaseAddress);
+  if (NT_SUCCESS(Status) && 0 == (LoadFlags & LOAD_LIBRARY_AS_DATAFILE))
     {
       RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
       Status = LdrpAttachProcess();
@@ -1346,7 +1353,8 @@ LdrpGetOrLoadModule(PWCHAR SerachPath,
        Status = LdrpLoadModule(SerachPath,
                                NtCurrentPeb()->Ldr->Initialized ? 0 : LDRP_PROCESS_CREATION_TIME,
                                &DllName,
-                               Module);
+                               Module,
+                               NULL);
        if (NT_SUCCESS(Status))
          {
            Status = LdrFindEntryForName (&DllName, Module, FALSE);
@@ -1978,7 +1986,8 @@ static NTSTATUS
 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
                IN ULONG LoadFlags,
                IN PUNICODE_STRING Name,
-               PLDR_MODULE *Module)
+               PLDR_MODULE *Module,
+               PVOID *BaseAddress OPTIONAL)
 {
     UNICODE_STRING AdjustedName;
     UNICODE_STRING FullDosName;
@@ -1988,6 +1997,7 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
     ULONG ViewSize;
     PVOID ImageBase;
     PIMAGE_NT_HEADERS NtHeaders;
+    BOOL MappedAsDataFile;
 
     if (Module == NULL)
       {
@@ -1998,11 +2008,16 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
 
     DPRINT("%wZ\n", &AdjustedName);
 
+    MappedAsDataFile = FALSE;
     /* Test if dll is already loaded */
     Status = LdrFindEntryForName(&AdjustedName, Module, TRUE);
     if (NT_SUCCESS(Status))
       {
         RtlFreeUnicodeString(&AdjustedName);
+        if (NULL != BaseAddress)
+          {
+            *BaseAddress = (*Module)->BaseAddress;
+          }
       }
     else
       {
@@ -2010,7 +2025,9 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
         Status = LdrpMapKnownDll(&AdjustedName, &FullDosName, &SectionHandle);
         if (!NT_SUCCESS(Status))
           {
-            Status = LdrpMapDllImageFile(SearchPath, &AdjustedName, &FullDosName, &SectionHandle);
+            MappedAsDataFile = (0 != (LoadFlags & LOAD_LIBRARY_AS_DATAFILE));
+            Status = LdrpMapDllImageFile(SearchPath, &AdjustedName, &FullDosName,
+                                         MappedAsDataFile, &SectionHandle);
           }
         if (!NT_SUCCESS(Status))
           {
@@ -2039,6 +2056,10 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
             NtClose(SectionHandle);
             return(Status);
           }
+        if (NULL != BaseAddress)
+          {
+            *BaseAddress = ImageBase;
+          }
         /* Get and check the NT headers */
         NtHeaders = RtlImageNtHeader(ImageBase);
         if (NtHeaders == NULL)
@@ -2049,6 +2070,19 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
             RtlFreeUnicodeString(&FullDosName);
             return STATUS_UNSUCCESSFUL;
           }
+        DPRINT("Mapped %wZ at %x\n", &FullDosName, ImageBase);
+        if (MappedAsDataFile)
+          {
+            assert(NULL != BaseAddress);
+            if (NULL != BaseAddress)
+              {
+                *BaseAddress = (PVOID) ((char *) *BaseAddress + 1);
+              }
+            *Module = NULL;
+            RtlFreeUnicodeString(&FullDosName);
+            NtClose(SectionHandle);
+            return STATUS_SUCCESS;
+          }
         /* If the base address is different from the
          * one the DLL is actually loaded, perform any
          * relocation. */
@@ -2212,12 +2246,20 @@ LdrUnloadDll (IN PVOID BaseAddress)
    if (BaseAddress == NULL)
      return STATUS_SUCCESS;
 
-   Status = LdrFindEntryForAddress(BaseAddress, &Module);
-   if (NT_SUCCESS(Status))
+   if (LdrMappedAsDataFile(&BaseAddress))
      {
-       TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module->BaseDllName);
-       Status = LdrpUnloadModule(Module, TRUE);
+       Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
      }
+   else
+     {
+       Status = LdrFindEntryForAddress(BaseAddress, &Module);
+       if (NT_SUCCESS(Status))
+         {
+           TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module->BaseDllName);
+           Status = LdrpUnloadModule(Module, TRUE);
+         }
+     }
+
    return Status;
 }