- fixed definition of RtlImageRvaToVa
authorThomas Bluemel <thomas@reactsoft.com>
Thu, 8 Dec 2005 23:55:34 +0000 (23:55 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Thu, 8 Dec 2005 23:55:34 +0000 (23:55 +0000)
- imported the Ldr resource functions from wine and share them in lib/rtl

svn path=/trunk/; revision=19987

13 files changed:
reactos/include/ndk/rtlfuncs.h
reactos/lib/ntdll/def/ntdll.def
reactos/lib/ntdll/ldr/res.c [deleted file]
reactos/lib/ntdll/ntdll.xml
reactos/lib/ntdll/rtl/libsupp.c
reactos/lib/rtl/i386/res_asm.s [new file with mode: 0644]
reactos/lib/rtl/image.c
reactos/lib/rtl/res.c [new file with mode: 0644]
reactos/lib/rtl/rtl.h
reactos/lib/rtl/rtl.xml
reactos/ntoskrnl/ldr/resource.c [deleted file]
reactos/ntoskrnl/ntoskrnl.xml
reactos/ntoskrnl/rtl/libsupp.c

index 606045e..1736b51 100644 (file)
@@ -2092,7 +2092,7 @@ RtlImageDirectoryEntryToData(
 );
 
 NTSYSAPI
-ULONG
+PVOID
 NTAPI
 RtlImageRvaToVa(
     PIMAGE_NT_HEADERS NtHeader,
index b75f87e..6fe320a 100644 (file)
@@ -36,7 +36,7 @@ KiUserCallbackDispatcher@12
 KiUserExceptionDispatcher@8
 LdrAccessResource@16
 LdrDisableThreadCalloutsForDll@4
-;LdrEnumResources@20
+LdrEnumResources@20
 LdrFindEntryForAddress@8
 LdrFindResourceDirectory_U@16
 LdrFindResource_U@16
diff --git a/reactos/lib/ntdll/ldr/res.c b/reactos/lib/ntdll/ldr/res.c
deleted file mode 100644 (file)
index d3478b3..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            lib/ntdll/ldr/res.c
- * PURPOSE:         Resource access for PE executables
- * PROGRAMMERS:     Jean Michault
- *                  Rex Jolliff (rex@lvcablemodem.com)
- *                  Robert Dickenson (robd@mok.lvcm.com)
- * NOTES:           Parts based on Wine code
- *                  Copyright 1995 Thomas Sandford
- *                  Copyright 1996 Martin von Loewis
- *                  Copyright 2003 Alexandre Julliard
- *                  Copyright 1993 Robert J. Amstadt
- *                  Copyright 1995 Alexandre Julliard
- *                  Copyright 1997 Marcus Meissner
- */
-
-/*
- * TODO:
- *  - any comments ??
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntdll.h>
-#define NDEBUG
-#include <debug.h>
-
-/* PROTOTYPES ****************************************************************/
-
-
-
-/* FUNCTIONS *****************************************************************/
-
-static PIMAGE_RESOURCE_DIRECTORY_ENTRY FASTCALL
-FindEntryById(PIMAGE_RESOURCE_DIRECTORY ResDir,
-              ULONG Id)
-{
-    PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
-    LONG low, high, mid, result;
-
-    /* We use ID number instead of string */
-    ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1) + ResDir->NumberOfNamedEntries;
-    DPRINT("ResEntry %x - Resource ID number instead of string\n", (ULONG)ResEntry);
-    DPRINT("EntryCount %d\n", (ULONG)ResDir->NumberOfIdEntries);
-
-    low = 0;
-    high = ResDir->NumberOfIdEntries - 1;
-    mid = high/2;
-    while( low <= high ) {
-        result = Id - ResEntry[mid].Name;
-        if(result == 0)
-            return ResEntry + mid;
-        if(result < 0)
-            high = mid - 1;
-        else
-            low = mid + 1;
-
-        mid = (low + high)/2;
-    }
-
-    return NULL;
-}
-
-static int FASTCALL
-PushLanguage(WORD *list, int pos, WORD lang)
-{
-    int i;
-
-    for (i = 0; i < pos; i++) {
-        if (list[i] == lang) {
-            return pos;
-        }
-    }
-
-    list[pos++] = lang;
-
-    return pos;
-}
-
-/*
-       Status = LdrFindResource_U (hModule,
-                                   &ResourceInfo,
-                                   RESOURCE_DATA_LEVEL,
-                                   &ResourceDataEntry);
- */
-NTSTATUS NTAPI
-LdrFindResource_U(PVOID BaseAddress,
-                  PLDR_RESOURCE_INFO ResourceInfo,
-                  ULONG Level,
-                  PIMAGE_RESOURCE_DATA_ENTRY* ResourceDataEntry)
-{
-    PIMAGE_RESOURCE_DIRECTORY ResDir;
-    PIMAGE_RESOURCE_DIRECTORY ResBase;
-    PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
-    NTSTATUS Status = STATUS_SUCCESS;
-    PWCHAR ws;
-    ULONG i;
-    ULONG Id;
-    LONG low, high, mid, result;
-    WORD list[9];  /* list of languages to try */
-    int j, pos = 0;
-    LCID UserLCID, SystemLCID;
-    LANGID UserLangID, SystemLangID;
-    BOOLEAN 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,
-                      ! MappedAsDataFile, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
-    if (ResDir == NULL) {
-        return STATUS_RESOURCE_DATA_NOT_FOUND;
-    }
-
-    DPRINT("ResourceDirectory: %x  Size: %d\n", (ULONG)ResDir, (int)i);
-
-    ResBase = ResDir;
-
-    /* Let's go into resource tree */
-    for (i = 0; i < (2 < Level ? 2 : Level); i++) {
-        DPRINT("ResDir: %x  Level: %d\n", (ULONG)ResDir, i);
-
-        Id = ((PULONG)ResourceInfo)[i];
-
-        if (Id & 0xFFFF0000) {
-            /* Resource name is a unicode string */
-            ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
-            DPRINT("ResEntry %x - Resource name is a unicode string\n", (ULONG)ResEntry);
-            DPRINT("EntryCount %d\n", (ULONG)ResDir->NumberOfNamedEntries);
-
-            low = 0;
-            high = ResDir->NumberOfNamedEntries - 1;
-            mid = high/2;
-            while( low <= high ) {
-               /* Does we need check if it's named entry, think not */
-               ws = (PWCHAR)((ULONG)ResBase + (ResEntry[mid].Name & 0x7FFFFFFF));
-               result = _wcsnicmp((PWCHAR)Id, ws + 1, *ws);
-               /* Need double check for lexical & length */
-               if(result == 0) {
-                  result = (wcslen((PWCHAR)Id) - (int)*ws);
-                  if(result == 0) {
-                      ResEntry += mid;
-                      goto found;
-                  }
-               }
-               if(result < 0)
-                  high = mid - 1;
-               else
-                  low = mid + 1;
-
-               mid = (low + high)/2;
-            }
-        } else {
-            /* We use ID number instead of string */
-            ResEntry = FindEntryById(ResDir, Id);
-            if (NULL != ResEntry) goto found;
-        }
-
-        switch (i) {
-        case 0:
-            DPRINT("Error %lu - STATUS_RESOURCE_TYPE_NOT_FOUND\n", i);
-            return STATUS_RESOURCE_TYPE_NOT_FOUND;
-        case 1:
-            DPRINT("Error %lu - STATUS_RESOURCE_NAME_NOT_FOUND\n", i);
-            return STATUS_RESOURCE_NAME_NOT_FOUND;
-        case 2:
-            if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
-                /* Use the first available language */
-                ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
-                break;
-            }
-            DPRINT("Error %lu - STATUS_RESOURCE_LANG_NOT_FOUND\n", i);
-            return STATUS_RESOURCE_LANG_NOT_FOUND;
-         case 3:
-            DPRINT("Error %lu - STATUS_RESOURCE_DATA_NOT_FOUND\n", i);
-            return STATUS_RESOURCE_DATA_NOT_FOUND;
-         default:
-            DPRINT("Error %lu - STATUS_INVALID_PARAMETER\n", i);
-            return STATUS_INVALID_PARAMETER;
-        }
-found:;
-        ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
-                     (ResEntry->OffsetToData & 0x7FFFFFFF));
-    }
-
-    if (3 <= Level) {
-        /* 1. specified language */
-        pos = PushLanguage(list, pos, ResourceInfo->Language );
-
-        /* 2. specified language with neutral sublanguage */
-        pos = PushLanguage(list, pos, MAKELANGID(PRIMARYLANGID(ResourceInfo->Language), SUBLANG_NEUTRAL));
-
-        /* 3. neutral language with neutral sublanguage */
-        pos = PushLanguage(list, pos, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
-
-        /* if no explicitly specified language, try some defaults */
-        if (LANG_NEUTRAL == PRIMARYLANGID(ResourceInfo->Language)) {
-            /* user defaults, unless SYS_DEFAULT sublanguage specified  */
-            if (SUBLANG_SYS_DEFAULT != SUBLANGID(ResourceInfo->Language)) {
-                NtQueryDefaultLocale(TRUE, &UserLCID);
-                UserLangID = LANGIDFROMLCID(UserLCID);
-
-                /* 4. current thread locale language */
-                pos = PushLanguage(list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale));
-
-                /* 5. user locale language */
-                pos = PushLanguage(list, pos, UserLangID);
-
-                /* 6. user locale language with neutral sublanguage  */
-                pos = PushLanguage(list, pos, MAKELANGID(PRIMARYLANGID(UserLangID),
-                                                         SUBLANG_NEUTRAL));
-            }
-
-            /* now system defaults */
-            NtQueryDefaultLocale(FALSE, &SystemLCID);
-            SystemLangID = LANGIDFROMLCID(SystemLCID);
-
-            /* 7. system locale language */
-            pos = PushLanguage(list, pos, SystemLangID);
-
-            /* 8. system locale language with neutral sublanguage */
-            pos = PushLanguage(list, pos, MAKELANGID(PRIMARYLANGID(SystemLangID),
-                                                     SUBLANG_NEUTRAL));
-
-            /* 9. English */
-            pos = PushLanguage(list, pos, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT));
-        }
-
-        ResEntry = NULL;
-        for (j = 0; NULL == ResEntry && j < pos; j++)
-            ResEntry = FindEntryById(ResDir, list[j]);
-        if (NULL == ResEntry) {
-            if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
-                /* Use the first available language */
-                ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
-            } else {
-                DPRINT("Error - STATUS_RESOURCE_LANG_NOT_FOUND\n", i);
-                return STATUS_RESOURCE_LANG_NOT_FOUND;
-            }
-        }
-        ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
-                     (ResEntry->OffsetToData & 0x7FFFFFFF));
-        if (3 < Level) {
-            DPRINT("Error - STATUS_INVALID_PARAMETER\n", i);
-            return STATUS_INVALID_PARAMETER;
-        }
-    }
-    DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
-
-    if (ResourceDataEntry) {
-        *ResourceDataEntry = (PVOID)ResDir;
-    }
-    return Status;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrAccessResource(IN  PVOID BaseAddress,
-                  IN  PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
-                  OUT PVOID* Resource OPTIONAL,
-                  OUT PULONG Size OPTIONAL)
-{
-    PIMAGE_SECTION_HEADER Section;
-    PIMAGE_NT_HEADERS NtHeader;
-    ULONG SectionRva;
-    ULONG SectionVa;
-    ULONG DataSize;
-    ULONG Offset = 0;
-    ULONG Data;
-    BOOLEAN 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 (MappedAsDataFile) {
-        /* loaded as ordinary file */
-        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) {
-            return STATUS_RESOURCE_DATA_NOT_FOUND;
-        }
-        if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData) {
-            SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
-            SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
-            Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
-        }
-    }
-    if (Resource) {
-        *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress);
-    }
-    if (Size) {
-        *Size = ResourceDataEntry->Size;
-    }
-    return STATUS_SUCCESS;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrFindResourceDirectory_U(IN PVOID BaseAddress,
-                           IN PLDR_RESOURCE_INFO info,
-                           IN ULONG level,
-                          OUT PIMAGE_RESOURCE_DIRECTORY* addr)
-{
-    PIMAGE_RESOURCE_DIRECTORY ResDir;
-    PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
-    ULONG EntryCount;
-    ULONG i;
-    NTSTATUS Status = STATUS_SUCCESS;
-    WCHAR* ws;
-    PWCHAR* name = (PWCHAR*) info;
-
-    /* Get the pointer to the resource directory */
-    ResDir = (PIMAGE_RESOURCE_DIRECTORY)
-    RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
-    if (ResDir == NULL) {
-        return STATUS_RESOURCE_DATA_NOT_FOUND;
-    }
-
-    /* Let's go into resource tree */
-    for (i = 0; i < level; i++, name++) {
-        EntryCount = ResDir->NumberOfNamedEntries;
-        ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
-        if ((ULONG)(*name) & 0xFFFF0000) {
-            /* Resource name is a unicode string */
-            for (; EntryCount--; ResEntry++) {
-                /* Scan entries for equal name */
-                if (ResEntry->Name & 0x80000000) {
-                    ws = (WCHAR*)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
-                    if (!wcsncmp(*name, ws + 1, *ws) && wcslen(*name) == (int)*ws) {
-                        goto found;
-                    }
-                }
-            }
-        } else {
-            /* We use ID number instead of string */
-            ResEntry += EntryCount;
-            EntryCount = ResDir->NumberOfIdEntries;
-            for (; EntryCount--; ResEntry++) {
-                /* Scan entries for equal name */
-                if (ResEntry->Name == (ULONG)(*name))
-                    goto found;
-            }
-        }
-        switch (i) {
-        case 0:
-            return STATUS_RESOURCE_TYPE_NOT_FOUND;
-        case 1:
-            return STATUS_RESOURCE_NAME_NOT_FOUND;
-        case 2:
-            Status = STATUS_RESOURCE_LANG_NOT_FOUND;
-            /* Just use first language entry */
-            if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
-                ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
-                break;
-            }
-            return Status;
-        case 3:
-            return STATUS_RESOURCE_DATA_NOT_FOUND;
-        default:
-            return STATUS_INVALID_PARAMETER;
-        }
-found:;
-        ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResDir + ResEntry->OffsetToData);
-    }
-    if (addr) {
-        *addr = (PVOID)ResDir;
-    }
-    return Status;
-}
-
-/* EOF */
index d100957..eacce54 100644 (file)
@@ -11,6 +11,7 @@
        <library>rtl</library>
        <library>intrlck</library>
        <library>string</library>
+       <library>pseh</library>
        <linkerflag>-lgcc</linkerflag>
        <linkerflag>-nostdlib</linkerflag>
        <linkerflag>-nostartfiles</linkerflag>
@@ -23,7 +24,6 @@
                <file>dbgui.c</file>
        </directory>
        <directory name="ldr">
-               <file>res.c</file>
                <file>startup.c</file>
                <file>utils.c</file>
        </directory>
index 954bcb5..dd84115 100644 (file)
@@ -328,3 +328,105 @@ RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
    return NULL;
 }
 
+
+/*
+ * Ldr Resource support code
+ */
+
+IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
+                                              LPCWSTR name, void *root,
+                                              int want_dir );
+IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
+                                            WORD id, void *root, int want_dir );
+IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
+                                            void *root, int want_dir );
+int push_language( USHORT *list, ULONG pos, WORD lang );
+
+/**********************************************************************
+ *  find_entry
+ *
+ * Find a resource entry
+ */
+NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
+                     ULONG level, void **ret, int want_dir )
+{
+    ULONG size;
+    void *root;
+    IMAGE_RESOURCE_DIRECTORY *resdirptr;
+    USHORT list[9];  /* list of languages to try */
+    int i, pos = 0;
+    LCID user_lcid, system_lcid;
+
+    root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
+    if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
+    resdirptr = root;
+
+    if (!level--) goto done;
+    if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
+        return STATUS_RESOURCE_TYPE_NOT_FOUND;
+    if (!level--) return STATUS_SUCCESS;
+
+    resdirptr = *ret;
+    if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
+        return STATUS_RESOURCE_NAME_NOT_FOUND;
+    if (!level--) return STATUS_SUCCESS;
+    if (level) return STATUS_INVALID_PARAMETER;  /* level > 3 */
+
+    /* 1. specified language */
+    pos = push_language( list, pos, info->Language );
+
+    /* 2. specified language with neutral sublanguage */
+    pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) );
+
+    /* 3. neutral language with neutral sublanguage */
+    pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
+
+    /* if no explicitly specified language, try some defaults */
+    if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
+    {
+        /* user defaults, unless SYS_DEFAULT sublanguage specified  */
+        if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT)
+        {
+            /* 4. current thread locale language */
+            pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) );
+
+            if (NT_SUCCESS(NtQueryDefaultLocale(TRUE, &user_lcid)))
+            {
+                /* 5. user locale language */
+                pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) );
+
+                /* 6. user locale language with neutral sublanguage  */
+                pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) );
+            }
+        }
+
+        /* now system defaults */
+
+        if (NT_SUCCESS(NtQueryDefaultLocale(FALSE, &system_lcid)))
+        {
+            /* 7. system locale language */
+            pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) );
+
+            /* 8. system locale language with neutral sublanguage */
+            pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) );
+        }
+
+        /* 9. English */
+        pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
+    }
+
+    resdirptr = *ret;
+    for (i = 0; i < pos; i++)
+        if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS;
+
+    /* if no explicitly specified language, return the first entry */
+    if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
+    {
+        if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
+    }
+    return STATUS_RESOURCE_LANG_NOT_FOUND;
+
+done:
+    *ret = resdirptr;
+    return STATUS_SUCCESS;
+}
diff --git a/reactos/lib/rtl/i386/res_asm.s b/reactos/lib/rtl/i386/res_asm.s
new file mode 100644 (file)
index 0000000..46c61e0
--- /dev/null
@@ -0,0 +1,20 @@
+#include <ndk/asm.h>
+.intel_syntax noprefix
+
+/*
+ * On x86, Shrinker, an executable compressor, depends on the
+ * "call access_resource" instruction being there.
+ */
+.globl _LdrAccessResource@16
+_LdrAccessResource@16:
+    push ebp
+    mov ebp, esp
+    sub esp, 4
+    push [ebp + 24]
+    push [ebp + 20]
+    push [ebp + 16]
+    push [ebp + 12]
+    push [ebp + 8]
+    call _LdrpAccessResource@16
+    leave
+    ret 16
index 0cdc54e..fc07d69 100644 (file)
@@ -80,7 +80,7 @@ RtlImageDirectoryEntryToData (
                return (PVOID)((ULONG_PTR)BaseAddress + Va);
 
        /* image mapped as ordinary file, we must find raw pointer */
-       return (PVOID)RtlImageRvaToVa (NtHeader, BaseAddress, Va, NULL);
+       return RtlImageRvaToVa (NtHeader, BaseAddress, Va, NULL);
 }
 
 
@@ -117,7 +117,7 @@ RtlImageRvaToSection (
 /*
  * @implemented
  */
-ULONG
+PVOID
 NTAPI
 RtlImageRvaToVa (
        PIMAGE_NT_HEADERS       NtHeader,
@@ -143,7 +143,7 @@ RtlImageRvaToVa (
                        *SectionHeader = Section;
        }
 
-       return (ULONG)((ULONG_PTR)BaseAddress +
+       return (PVOID)((ULONG_PTR)BaseAddress +
                       Rva +
                       Section->PointerToRawData -
                       (ULONG_PTR)Section->VirtualAddress);
diff --git a/reactos/lib/rtl/res.c b/reactos/lib/rtl/res.c
new file mode 100644 (file)
index 0000000..edd0c72
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * PE file resources
+ *
+ * Copyright 1995 Thomas Sandford
+ * Copyright 1996 Martin von Loewis
+ * Copyright 2003 Alexandre Julliard
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1997 Marcus Meissner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <rtl.h>
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
+                     ULONG level, void **ret, int want_dir );
+
+/* FUNCTIONS ****************************************************************/
+
+_SEH_FILTER(page_fault)
+{
+    if (_SEH_GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
+        _SEH_GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
+        return EXCEPTION_EXECUTE_HANDLER;
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
+/**********************************************************************
+ *  is_data_file_module
+ *
+ * Check if a module handle is for a LOAD_LIBRARY_AS_DATAFILE module.
+ */
+static int is_data_file_module( PVOID BaseAddress )
+{
+    return (ULONG_PTR)BaseAddress & 1;
+}
+
+
+/**********************************************************************
+ *  push_language
+ *
+ * push a language in the list of languages to try
+ */
+int push_language( USHORT *list, ULONG pos, WORD lang )
+{
+    int i;
+    for (i = 0; i < pos; i++) if (list[i] == lang) return pos;
+    list[pos++] = lang;
+    return pos;
+}
+
+
+/**********************************************************************
+ *  find_first_entry
+ *
+ * Find the first suitable entry in a resource directory
+ */
+IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
+                                            void *root, int want_dir )
+{
+    const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
+    int pos;
+
+    for (pos = 0; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++)
+    {
+        if (!entry[pos].DataIsDirectory == !want_dir)
+            return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
+    }
+    return NULL;
+}
+
+
+/**********************************************************************
+ *  find_entry_by_id
+ *
+ * Find an entry by id in a resource directory
+ */
+IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
+                                            WORD id, void *root, int want_dir )
+{
+    const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
+    int min, max, pos;
+
+    entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
+    min = dir->NumberOfNamedEntries;
+    max = min + dir->NumberOfIdEntries - 1;
+    while (min <= max)
+    {
+        pos = (min + max) / 2;
+        if (entry[pos].Id == id)
+        {
+            if (!entry[pos].DataIsDirectory == !want_dir)
+            {
+                DPRINT("root %p dir %p id %04x ret %p\n",
+                       root, dir, id, (const char*)root + entry[pos].OffsetToDirectory);
+                return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
+            }
+            break;
+        }
+        if (entry[pos].Id > id) max = pos - 1;
+        else min = pos + 1;
+    }
+    DPRINT("root %p dir %p id %04x not found\n", root, dir, id );
+    return NULL;
+}
+
+
+/**********************************************************************
+ *  find_entry_by_name
+ *
+ * Find an entry by name in a resource directory
+ */
+IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
+                                              LPCWSTR name, void *root,
+                                              int want_dir )
+{
+    const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
+    const IMAGE_RESOURCE_DIR_STRING_U *str;
+    int min, max, res, pos, namelen;
+
+    if (!((ULONG_PTR)name & 0xFFFF0000)) return find_entry_by_id( dir, (ULONG_PTR)name & 0xFFFF, root, want_dir );
+    entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
+    namelen = wcslen(name);
+    min = 0;
+    max = dir->NumberOfNamedEntries - 1;
+    while (min <= max)
+    {
+        pos = (min + max) / 2;
+        str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const char *)root + entry[pos].NameOffset);
+        res = wcsncmp( name, str->NameString, str->Length );
+        if (!res && namelen == str->Length)
+        {
+            if (!entry[pos].DataIsDirectory == !want_dir)
+            {
+                DPRINT("root %p dir %p name %ws ret %p\n",
+                       root, dir, name, (const char*)root + entry[pos].OffsetToDirectory);
+                return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
+            }
+            break;
+        }
+        if (res < 0) max = pos - 1;
+        else min = pos + 1;
+    }
+    DPRINT("root %p dir %p name %ws not found\n", root, dir, name);
+    return NULL;
+}
+
+#ifdef __i386__
+NTSTATUS NTAPI LdrpAccessResource( PVOID BaseAddress, IMAGE_RESOURCE_DATA_ENTRY *entry,
+                                   void **ptr, ULONG *size )
+#else
+static NTSTATUS LdrpAccessResource( PVOID BaseAddress, IMAGE_RESOURCE_DATA_ENTRY *entry,
+                                    void **ptr, ULONG *size )
+#endif
+{
+    NTSTATUS status = STATUS_SUCCESS;
+
+    _SEH_TRY
+    {
+        ULONG dirsize;
+
+        if (!RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &dirsize ))
+            status = STATUS_RESOURCE_DATA_NOT_FOUND;
+        else
+        {
+            if (ptr)
+            {
+                if (is_data_file_module(BaseAddress))
+                {
+                    PVOID mod = (PVOID)((ULONG_PTR)BaseAddress & ~1);
+                    *ptr = RtlImageRvaToVa( RtlImageNtHeader(mod), mod, entry->OffsetToData, NULL );
+                }
+                else *ptr = (char *)BaseAddress + entry->OffsetToData;
+            }
+            if (size) *size = entry->Size;
+        }
+    }
+    _SEH_EXCEPT(page_fault)
+    {
+        status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+    return status;
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS NTAPI
+LdrFindResource_U(PVOID BaseAddress,
+                  PLDR_RESOURCE_INFO ResourceInfo,
+                  ULONG Level,
+                  PIMAGE_RESOURCE_DATA_ENTRY* ResourceDataEntry)
+{
+    void *res;
+    NTSTATUS status = STATUS_SUCCESS;
+
+    _SEH_TRY
+    {
+       if (ResourceInfo) 
+        {
+            DPRINT( "module %p type %ws name %ws lang %04lx level %ld\n",
+                     BaseAddress, (LPCWSTR)ResourceInfo->Type,
+                     Level > 1 ? (LPCWSTR)ResourceInfo->Name : L"",
+                     Level > 2 ? ResourceInfo->Language : 0, Level );
+        }
+
+        status = find_entry( BaseAddress, ResourceInfo, Level, &res, FALSE );
+        if (status == STATUS_SUCCESS) *ResourceDataEntry = res;
+    }
+    _SEH_EXCEPT(page_fault)
+    {
+        status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+    return status;
+}
+
+#ifndef __i386__
+/*
+ * @implemented
+ */
+NTSTATUS NTAPI
+LdrAccessResource(IN  PVOID BaseAddress,
+                  IN  PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
+                  OUT PVOID* Resource OPTIONAL,
+                  OUT PULONG Size OPTIONAL)
+{
+    return LdrpAccessResource( BaseAddress, ResourceDataEntry, Resource, Size );
+}
+#endif
+
+/*
+ * @implemented
+ */
+NTSTATUS NTAPI
+LdrFindResourceDirectory_U(IN PVOID BaseAddress,
+                           IN PLDR_RESOURCE_INFO info,
+                           IN ULONG level,
+                           OUT PIMAGE_RESOURCE_DIRECTORY* addr)
+{
+    void *res;
+    NTSTATUS status = STATUS_SUCCESS;
+
+    _SEH_TRY
+    {
+       if (info)
+        {
+            DPRINT( "module %p type %ws name %ws lang %04lx level %ld\n",
+                     BaseAddress, (LPCWSTR)info->Type,
+                     level > 1 ? (LPCWSTR)info->Name : L"",
+                     level > 2 ? info->Language : 0, level );
+        }
+
+        status = find_entry( BaseAddress, info, level, &res, TRUE );
+        if (status == STATUS_SUCCESS) *addr = res;
+    }
+    _SEH_EXCEPT(page_fault)
+    {
+        status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+    return status;
+}
+
+
+/*
+ * @unimplemented
+ */
+NTSTATUS NTAPI
+LdrEnumResources(IN PVOID BaseAddress,
+                 IN PLDR_RESOURCE_INFO ResourceInfo,
+                 IN ULONG Level,
+                 IN OUT PULONG ResourceCount,
+                 OUT PVOID Resources  OPTIONAL)
+{
+       UNIMPLEMENTED;
+       return STATUS_NOT_IMPLEMENTED;
+}
index bed66c3..e2609bc 100644 (file)
@@ -23,4 +23,6 @@
 #include <reactos/helper.h>
 #include "rtlp.h"
 
+#include <pseh/pseh.h>
+
 /* EOF */
index 2ca2cf5..611c303 100644 (file)
@@ -5,6 +5,7 @@
        <define name="NO_RTL_INLINES" />
        <define name="_NTSYSTEM_" />
        <define name="_NTDLLBUILD_" />
+       <define name="_SEH_NO_NATIVE_NLG" />
        <include base="rtl">.</include>
        <if property="ARCH" value="i386">
                <directory name="i386">
@@ -36,6 +37,7 @@
                        <file>random_asm.S</file>
                        <file>pow_asm.s</file>
                        <file>prefetchmemory_asm.s</file>
+                       <file>res_asm.s</file>
                        <file>sin_asm.s</file>
                        <file>sqrt_asm.s</file>
                        <file>tan_asm.s</file>                  
@@ -76,6 +78,7 @@
        <file>random.c</file>
        <file>rangelist.c</file>
        <file>registry.c</file>
+       <file>res.c</file>
        <file>resource.c</file>
        <file>sd.c</file>
        <file>security.c</file>
diff --git a/reactos/ntoskrnl/ldr/resource.c b/reactos/ntoskrnl/ldr/resource.c
deleted file mode 100644 (file)
index 34c8201..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/ldr/resource.c
- * PURPOSE:         Resource loader
- *
- * PROGRAMMERS:     Eric Kohl (ekohl@rz-online.de)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-/* FUNCTIONS ****************************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-LdrAccessResource(IN  PVOID BaseAddress,
-                  IN  PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
-                  OUT PVOID *Resource OPTIONAL,
-                  OUT PULONG Size OPTIONAL)
-{
-   PIMAGE_SECTION_HEADER Section;
-   PIMAGE_NT_HEADERS NtHeader;
-   ULONG SectionRva;
-   ULONG SectionVa;
-   ULONG DataSize;
-   ULONG Offset = 0;
-   ULONG Data;
-
-   if(!ResourceDataEntry)
-        return STATUS_RESOURCE_DATA_NOT_FOUND;
-
-   Data = (ULONG)RtlImageDirectoryEntryToData (BaseAddress,
-                                              TRUE,
-                                              IMAGE_DIRECTORY_ENTRY_RESOURCE,
-                                              &DataSize);
-   if (Data == 0)
-       return STATUS_RESOURCE_DATA_NOT_FOUND;
-
-   if ((ULONG_PTR)BaseAddress & 1)
-     {
-       /* loaded as ordinary file */
-       NtHeader = RtlImageNtHeader((PVOID)((ULONG_PTR)BaseAddress & ~1));
-       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)
-         {
-            return STATUS_RESOURCE_DATA_NOT_FOUND;
-         }
-
-       if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData)
-         {
-            SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
-            SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
-            Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
-         }
-     }
-
-   if (Resource)
-     {
-       *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + ((ULONG_PTR)BaseAddress & ~1));
-     }
-
-   if (Size)
-     {
-       *Size = ResourceDataEntry->Size;
-     }
-
-   return STATUS_SUCCESS;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-LdrFindResource_U(PVOID BaseAddress,
-                  PLDR_RESOURCE_INFO ResourceInfo,
-                  ULONG Level,
-                  PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry)
-{
-   PIMAGE_RESOURCE_DIRECTORY ResDir;
-   PIMAGE_RESOURCE_DIRECTORY ResBase;
-   PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
-   NTSTATUS Status = STATUS_SUCCESS;
-   ULONG EntryCount;
-   PWCHAR ws;
-   ULONG i;
-   ULONG Id;
-
-   DPRINT ("LdrFindResource_U()\n");
-
-   /* Get the pointer to the resource directory */
-   ResDir = (PIMAGE_RESOURCE_DIRECTORY)
-       RtlImageDirectoryEntryToData (BaseAddress,
-                                     TRUE,
-                                     IMAGE_DIRECTORY_ENTRY_RESOURCE,
-                                     &i);
-   if (ResDir == NULL)
-     {
-       return STATUS_RESOURCE_DATA_NOT_FOUND;
-     }
-
-   DPRINT("ResourceDirectory: %x\n", (ULONG)ResDir);
-
-   ResBase = ResDir;
-
-   /* Let's go into resource tree */
-   for (i = 0; i < Level; i++)
-     {
-       DPRINT("ResDir: %x\n", (ULONG)ResDir);
-       Id = ((PULONG)ResourceInfo)[i];
-       EntryCount = ResDir->NumberOfNamedEntries;
-       ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
-       DPRINT("ResEntry %x\n", (ULONG)ResEntry);
-       if (Id & 0xFFFF0000)
-         {
-            /* Resource name is a unicode string */
-            for (; EntryCount--; ResEntry++)
-              {
-                 /* Scan entries for equal name */
-                 if (ResEntry->Name & 0x80000000)
-                   {
-                      ws = (PWCHAR)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
-                      if (!wcsncmp((PWCHAR)Id, ws + 1, *ws ) &&
-                          wcslen((PWCHAR)Id) == (ULONG)*ws )
-                        {
-                           goto found;
-                        }
-                   }
-              }
-         }
-       else
-         {
-            /* We use ID number instead of string */
-            ResEntry += EntryCount;
-            EntryCount = ResDir->NumberOfIdEntries;
-            for (; EntryCount--; ResEntry++)
-              {
-                 /* Scan entries for equal name */
-                 if (ResEntry->Name == Id)
-                   {
-                    DPRINT("ID entry found %x\n", Id);
-                    goto found;
-                   }
-              }
-         }
-       DPRINT("Error %lu\n", i);
-
-         switch (i)
-         {
-            case 0:
-               return STATUS_RESOURCE_TYPE_NOT_FOUND;
-
-            case 1:
-               return STATUS_RESOURCE_NAME_NOT_FOUND;
-
-            case 2:
-               if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries)
-                 {
-                    /* Use the first available language */
-                    ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
-                    break;
-                 }
-               return STATUS_RESOURCE_LANG_NOT_FOUND;
-
-            case 3:
-               return STATUS_RESOURCE_DATA_NOT_FOUND;
-
-            default:
-               return STATUS_INVALID_PARAMETER;
-         }
-found:;
-       ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
-               (ResEntry->OffsetToData & 0x7FFFFFFF));
-     }
-   DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
-
-   if (ResourceDataEntry)
-     {
-       *ResourceDataEntry = (PVOID)ResDir;
-     }
-
-  return Status;
-}
-
-/* STUBS */
-
-/*
- * @unimplemented
- */
-NTSTATUS
-STDCALL
-LdrFindResourceDirectory_U(
-       IN PVOID        BaseAddress,
-       IN PLDR_RESOURCE_INFO                   ResourceInfo,
-       IN  ULONG                                               Level,
-       OUT PIMAGE_RESOURCE_DIRECTORY   *ResourceDirectory
-)
-{
-       UNIMPLEMENTED;
-       return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-STDCALL
-LdrEnumResources(
-       IN PVOID        BaseAddress,
-       IN PLDR_RESOURCE_INFO                   ResourceInfo,
-       IN  ULONG                                               Level,
-       IN OUT PULONG                                   ResourceCount,
-       OUT PVOID                                               Resources  OPTIONAL
-)
-{
-       UNIMPLEMENTED;
-       return STATUS_NOT_IMPLEMENTED;
-}
-
-/* EOF */
index d0c2b82..d36ff57 100644 (file)
        <directory name="ldr">
                <compilationunit name="ldr.c">
                        <file>loader.c</file>
-                       <file>resource.c</file>
                        <file>rtl.c</file>
                </compilationunit>
        </directory>
index d966de6..90a50b3 100644 (file)
@@ -363,4 +363,55 @@ RtlpCreateUnicodeString(
    return TRUE;
 }
 
+/*
+ * Ldr Resource support code
+ */
+
+IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
+                                              LPCWSTR name, void *root,
+                                              int want_dir );
+IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
+                                            WORD id, void *root, int want_dir );
+IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
+                                            void *root, int want_dir );
+
+/**********************************************************************
+ *  find_entry
+ *
+ * Find a resource entry
+ */
+NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
+                     ULONG level, void **ret, int want_dir )
+{
+    ULONG size;
+    void *root;
+    IMAGE_RESOURCE_DIRECTORY *resdirptr;
+
+    root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
+    if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
+    resdirptr = root;
+
+    if (!level--) goto done;
+    if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
+        return STATUS_RESOURCE_TYPE_NOT_FOUND;
+    if (!level--) return STATUS_SUCCESS;
+
+    resdirptr = *ret;
+    if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
+        return STATUS_RESOURCE_NAME_NOT_FOUND;
+    if (!level--) return STATUS_SUCCESS;
+    if (level) return STATUS_INVALID_PARAMETER;  /* level > 3 */
+
+    resdirptr = *ret;
+
+    if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
+
+    return STATUS_RESOURCE_DATA_NOT_FOUND;
+
+done:
+    *ret = resdirptr;
+    return STATUS_SUCCESS;
+}
+
+
 /* EOF */