James Hawkins : fusion: The VersionLength member is not constant, so dynamically load the metadata header.

Alexandre Julliard julliard at winehq.org
Wed Jul 16 13:33:04 CDT 2008


Module: wine
Branch: master
Commit: 8f985a338abcf9ed7dbf1c549f69a6a470c332c5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=8f985a338abcf9ed7dbf1c549f69a6a470c332c5

Author: James Hawkins <jhawkins at codeweavers.com>
Date:   Wed Jul 16 10:51:54 2008 -0500

fusion: The VersionLength member is not constant, so dynamically load the metadata header.

---

 dlls/fusion/assembly.c   |   49 ++++++++++++++++++++++++++++++++++++++-------
 dlls/fusion/fusionpriv.h |    6 ++--
 2 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/dlls/fusion/assembly.c b/dlls/fusion/assembly.c
index 5bc8725..56ad060 100644
--- a/dlls/fusion/assembly.c
+++ b/dlls/fusion/assembly.c
@@ -271,22 +271,54 @@ static HRESULT parse_clr_tables(ASSEMBLY *assembly, ULONG offset)
     return S_OK;
 }
 
+static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
+{
+    METADATAHDR *metadatahdr;
+    BYTE *ptr, *dest;
+    DWORD size, ofs;
+    ULONG rva;
+
+    rva = assembly->corhdr->MetaData.VirtualAddress;
+    ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
+    if (!ptr)
+        return E_FAIL;
+
+    metadatahdr = (METADATAHDR *)ptr;
+
+    assembly->metadatahdr = HeapAlloc(GetProcessHeap(), 0, sizeof(METADATAHDR));
+    if (!assembly->metadatahdr)
+        return E_OUTOFMEMORY;
+
+    size = FIELD_OFFSET(METADATAHDR, Version);
+    memcpy(assembly->metadatahdr, metadatahdr, size);
+
+    /* we don't care about the version string */
+
+    ofs = FIELD_OFFSET(METADATAHDR, Flags);
+    ptr += FIELD_OFFSET(METADATAHDR, Version) + metadatahdr->VersionLength + 1;
+    dest = (BYTE *)assembly->metadatahdr + ofs;
+    memcpy(dest, ptr, sizeof(METADATAHDR) - ofs);
+
+    *hdrsz = sizeof(METADATAHDR) - sizeof(LPSTR) + metadatahdr->VersionLength + 1;
+
+    return S_OK;
+}
+
 static HRESULT parse_clr_metadata(ASSEMBLY *assembly)
 {
     METADATASTREAMHDR *streamhdr;
     ULONG rva, i, ofs;
     LPSTR stream;
     HRESULT hr;
+    DWORD hdrsz;
     BYTE *ptr;
 
-    rva = assembly->corhdr->MetaData.VirtualAddress;
-    assembly->metadatahdr = ImageRvaToVa(assembly->nthdr, assembly->data,
-                                         rva, NULL);
-    if (!assembly->metadatahdr)
-        return E_FAIL;
+    hr = parse_metadata_header(assembly, &hdrsz);
+    if (FAILED(hr))
+        return hr;
 
-    ptr = ImageRvaToVa(assembly->nthdr, assembly->data,
-                       rva + sizeof(METADATAHDR), NULL);
+    rva = assembly->corhdr->MetaData.VirtualAddress;
+    ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva + hdrsz, NULL);
     if (!ptr)
         return E_FAIL;
 
@@ -393,7 +425,7 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
     return S_OK;
 
 failed:
-    assembly_release( assembly );
+    assembly_release(assembly);
     return hr;
 }
 
@@ -402,6 +434,7 @@ HRESULT assembly_release(ASSEMBLY *assembly)
     if (!assembly)
         return S_OK;
 
+    HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
     HeapFree(GetProcessHeap(), 0, assembly->path);
     UnmapViewOfFile(assembly->data);
     CloseHandle(assembly->hmap);
diff --git a/dlls/fusion/fusionpriv.h b/dlls/fusion/fusionpriv.h
index 08a2d5c..a4e6193 100644
--- a/dlls/fusion/fusionpriv.h
+++ b/dlls/fusion/fusionpriv.h
@@ -27,6 +27,8 @@
 #include "winbase.h"
 #include "winuser.h"
 
+#include <pshpack1.h>
+
 typedef struct
 {
     ULONG Signature;
@@ -34,13 +36,11 @@ typedef struct
     USHORT MinorVersion;
     ULONG Reserved;
     ULONG VersionLength;
-    BYTE Version[12];
+    LPSTR Version;
     BYTE Flags;
     WORD Streams;
 } METADATAHDR;
 
-#include <pshpack1.h>
-
 typedef struct
 {
     DWORD Offset;




More information about the wine-cvs mailing list