CVS: winex/dlls/ntdll ntdll.spec, 1.51, 1.52 rtl.c, 1.7, 1.8

[email protected] 12 Sep 2007 12:17:00 -0000
Newsgroups gmane.comp.emulators.winex.cvs
Message-ID <[email protected]>
Subject: winex/dlls/ntdll ntdll.spec,1.51,1.52 rtl.c,1.7,1.8Update of /var/lib/cvsd/cvsroot/winex/dlls/ntdll
In directory agravaine:/tmp/cvs-serv7276/dlls/ntdll

Modified Files:
	ntdll.spec rtl.c 
Log Message:

- added implementations for the RtlImageRvaToSection(), RtlImageRvaToVa(), and RtlImageDirectoryEntryToData() functions.  These are all used by winehq's dbghelp dll.  These were all tested against native for identical behaviour.



Index: ntdll.spec
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/ntdll/ntdll.spec,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- ntdll.spec	12 Sep 2007 12:14:45 -0000	1.51
+++ ntdll.spec	12 Sep 2007 12:16:58 -0000	1.52
@@ -424,8 +424,10 @@
 @ stdcall RtlGetSaclSecurityDescriptor(ptr ptr ptr ptr)RtlGetSaclSecurityDescriptor
 @ stub RtlGetUserInfoHeap
 @ stdcall RtlIdentifierAuthoritySid(ptr) RtlIdentifierAuthoritySid
-@ stub RtlImageDirectoryEntryToData
+@ stdcall RtlImageDirectoryEntryToData(long long long ptr) RtlImageDirectoryEntryToData
 @ stdcall RtlImageNtHeader(long) RtlImageNtHeader
+@ stdcall RtlImageRvaToSection(ptr long long) RtlImageRvaToSection
+@ stdcall RtlImageRvaToVa(ptr long long ptr) RtlImageRvaToVa
 @ stdcall RtlImpersonateSelf(long) RtlImpersonateSelf
 @ stdcall RtlInitAnsiString(ptr str) RtlInitAnsiString
 @ stub RtlInitCodePageTable

Index: rtl.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/ntdll/rtl.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- rtl.c	6 Nov 2006 16:22:25 -0000	1.7
+++ rtl.c	12 Sep 2007 12:16:58 -0000	1.8
@@ -354,6 +354,133 @@
     return ret;
 }
 
+/***********************************************************************
+ *          RtlImageRvaToSection    (NTDLL.@)
+ */
+PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection(const IMAGE_NT_HEADERS *ntHeaders, HMODULE base, DWORD rva){
+    int                     i;
+    int                     sectionCount;
+    IMAGE_SECTION_HEADER *  nextSection = NULL;
+
+
+    /* make sure we got a valid header */
+    if (ntHeaders == NULL)
+        return NULL;
+
+    /* this parameter is reserved for future use */
+    /*if (base != 0)
+        return NULL;*/
+
+
+    /* MSDN says the section table starts immediately after the file and optional headers */
+    sectionCount = ntHeaders->FileHeader.NumberOfSections;
+    nextSection = (IMAGE_SECTION_HEADER *)(((BYTE *)&ntHeaders->OptionalHeader) + ntHeaders->FileHeader.SizeOfOptionalHeader);
+
+
+    for (i = 0; i < sectionCount; i++){
+
+        /* each section table entry conveniently contains its mapped virtual address and size on disk.  Just test to
+           see if the address we're interested in is in the range of this section.  All addresses seem to be relative
+           to the image's base address (which is ignored in this call) */
+        if (rva >= nextSection->VirtualAddress && rva < nextSection->VirtualAddress + nextSection->SizeOfRawData)
+            return nextSection;
+
+        nextSection++;
+    }
+
+    return NULL;
+}
+
+/***********************************************************************
+ *          RtlImageRvaToVa    (NTDLL.@)
+ */
+PVOID WINAPI RtlImageRvaToVa(const IMAGE_NT_HEADERS *ntHeaders, HMODULE base, DWORD rva, IMAGE_SECTION_HEADER **lastRvaSection){
+    IMAGE_SECTION_HEADER *section = NULL;
+
+
+    /* test the last used section for the address first.  We could luck out and the new 
+       RVA will also be in the same section. */
+    if (lastRvaSection)
+        section = *lastRvaSection;
+
+    /* a previous section was passed in => test that one first */
+    if (section){
+
+        /* test to see if the requested RVA is in the section that was last used */
+        if (rva >= section->VirtualAddress && rva < section->VirtualAddress + section->SizeOfRawData){
+
+            /* the address will be the memory mapped base of the section plus the RVA's 
+               offset into the section.  In this case <lastRvaSection> will keep the
+               same value. */
+            return (PVOID)(((ULONG_PTR)base + section->PointerToRawData) + (rva - section->VirtualAddress));
+        }
+    }
+
+    
+    /* find the section that the requested RVA is in */
+    section = RtlImageRvaToSection(ntHeaders, base, rva);
+
+
+    /* section not found => fail */
+    if (section == NULL)
+        return NULL;
+
+    /* save the last used section for an optimized search next time */
+    if (lastRvaSection)
+        *lastRvaSection = section;
+
+
+    /* the address will be the memory mapped base of the section plus the RVA's 
+       offset into the section. */
+    return (PVOID)(((ULONG_PTR)base + section->PointerToRawData) + (rva - section->VirtualAddress));
+}
+
+/***********************************************************************
+ *          RtlImageDirectoryEntryToData    (NTDLL.@)
+ */
+PVOID WINAPI RtlImageDirectoryEntryToData(HMODULE base, BOOL mappedAsImage, WORD directoryEntry, ULONG *size){
+    IMAGE_NT_HEADERS *  ntHeader;
+    DWORD               va;
+
+
+    /* invalid image base => fail */
+    if (!base)
+        return NULL;
+
+
+    /* attempt to retrieve the PE header */
+    ntHeader = RtlImageNtHeader(base);
+
+    /* could not retrieve header => fail */
+    if (ntHeader == NULL)
+        return NULL;
+
+
+    /* invalid directory entry name => fail */
+    if (directoryEntry >= ntHeader->OptionalHeader.NumberOfRvaAndSizes)
+        return NULL;
+
+
+    /* grab the virtual address and section size */
+    va = ntHeader->OptionalHeader.DataDirectory[directoryEntry].VirtualAddress;
+
+    if (size)
+        *size = (ULONG)ntHeader->OptionalHeader.DataDirectory[directoryEntry].Size;
+
+    /* the section does not exist in this module => fail */
+    if (va == 0)
+        return NULL;
+
+
+    /* the file is already mapped as a loaded executeable => the VA will already have been updated */
+    if (mappedAsImage)
+        return (PVOID)(((ULONG_PTR)base) + va);
+
+
+    /* the file is not mapped -> the listed VA is actually an RVA => convert it */
+    return RtlImageRvaToVa(ntHeader, base, va, NULL);
+}
+
 
 /******************************************************************************
  *  RtlCreateEnvironment		[NTDLL.@]