From 9e021cff3d6af045b4d2e302f0a76054afdd0aa1 Mon Sep 17 00:00:00 2001
From: James Hawkins <jhawkins@codeweavers.com>
Date: Mon, 31 Mar 2008 01:03:24 -0500
Subject: [PATCH] fusion: Add initial tests for IAssemblyCache.

---
 .gitignore                    |   4 +
 Makefile.in                   |   2 +
 configure                     |   3 +
 configure.ac                  |   1 +
 dlls/Makefile.in              |   1 +
 dlls/fusion/tests/Makefile.in |  13 +
 dlls/fusion/tests/asmcache.c  | 961 ++++++++++++++++++++++++++++++++++
 programs/winetest/Makefile.in |   3 +
 programs/winetest/winetest.rc |   1 +
 9 files changed, 989 insertions(+)
 create mode 100644 dlls/fusion/tests/Makefile.in
 create mode 100644 dlls/fusion/tests/asmcache.c

diff --git a/.gitignore b/.gitignore
index 826912d135e..da8d139a1bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -129,6 +129,9 @@ dlls/dsound/tests/*.ok
 dlls/dsound/tests/dsound_crosstest.exe
 dlls/dsound/tests/testlist.c
 dlls/dwmapi/libdwmapi.def
+dlls/fusion/tests/*.ok
+dlls/fusion/tests/fusion_crosstest.exe
+dlls/fusion/tests/testlist.c
 dlls/gdi.exe16
 dlls/gdi32/libgdi32.def
 dlls/gdi32/tests/*.ok
@@ -630,6 +633,7 @@ programs/winetest/dinput_test.exe
 programs/winetest/dnsapi_test.exe
 programs/winetest/dplayx_test.exe
 programs/winetest/dsound_test.exe
+programs/winetest/fusion_test.exe
 programs/winetest/gdi32_test.exe
 programs/winetest/gdiplus_test.exe
 programs/winetest/hlink_test.exe
diff --git a/Makefile.in b/Makefile.in
index cfc8be9da50..b8962a9efd2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -267,6 +267,7 @@ ALL_MAKEFILES = \
 	dlls/dxguid/Makefile \
 	dlls/faultrep/Makefile \
 	dlls/fusion/Makefile \
+	dlls/fusion/tests/Makefile \
 	dlls/gdi32/Makefile \
 	dlls/gdi32/tests/Makefile \
 	dlls/gdiplus/Makefile \
@@ -691,6 +692,7 @@ dlls/dxerr9/Makefile: dlls/dxerr9/Makefile.in dlls/Makeimplib.rules
 dlls/dxguid/Makefile: dlls/dxguid/Makefile.in dlls/Makeimplib.rules
 dlls/faultrep/Makefile: dlls/faultrep/Makefile.in dlls/Makedll.rules
 dlls/fusion/Makefile: dlls/fusion/Makefile.in dlls/Makedll.rules
+dlls/fusion/tests/Makefile: dlls/fusion/tests/Makefile.in dlls/Maketest.rules
 dlls/gdi32/Makefile: dlls/gdi32/Makefile.in dlls/Makedll.rules
 dlls/gdi32/tests/Makefile: dlls/gdi32/tests/Makefile.in dlls/Maketest.rules
 dlls/gdiplus/Makefile: dlls/gdiplus/Makefile.in dlls/Makedll.rules
diff --git a/configure b/configure
index f752c3eb2fd..86b9bf026d8 100755
--- a/configure
+++ b/configure
@@ -21482,6 +21482,8 @@ ac_config_files="$ac_config_files dlls/faultrep/Makefile"
 
 ac_config_files="$ac_config_files dlls/fusion/Makefile"
 
+ac_config_files="$ac_config_files dlls/fusion/tests/Makefile"
+
 ac_config_files="$ac_config_files dlls/gdi32/Makefile"
 
 ac_config_files="$ac_config_files dlls/gdi32/tests/Makefile"
@@ -22765,6 +22767,7 @@ do
     "dlls/dxguid/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/dxguid/Makefile" ;;
     "dlls/faultrep/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/faultrep/Makefile" ;;
     "dlls/fusion/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/fusion/Makefile" ;;
+    "dlls/fusion/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/fusion/tests/Makefile" ;;
     "dlls/gdi32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/gdi32/Makefile" ;;
     "dlls/gdi32/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/gdi32/tests/Makefile" ;;
     "dlls/gdiplus/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/gdiplus/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index d63dcecc723..0cab238dc16 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1770,6 +1770,7 @@ AC_CONFIG_FILES([dlls/dxerr9/Makefile])
 AC_CONFIG_FILES([dlls/dxguid/Makefile])
 AC_CONFIG_FILES([dlls/faultrep/Makefile])
 AC_CONFIG_FILES([dlls/fusion/Makefile])
+AC_CONFIG_FILES([dlls/fusion/tests/Makefile])
 AC_CONFIG_FILES([dlls/gdi32/Makefile])
 AC_CONFIG_FILES([dlls/gdi32/tests/Makefile])
 AC_CONFIG_FILES([dlls/gdiplus/Makefile])
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index 68c6be48b67..bb473e27eb4 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -303,6 +303,7 @@ TESTSUBDIRS = \
 	dnsapi/tests \
 	dplayx/tests \
 	dsound/tests \
+	fusion/tests \
 	gdi32/tests \
 	gdiplus/tests \
 	hlink/tests \
diff --git a/dlls/fusion/tests/Makefile.in b/dlls/fusion/tests/Makefile.in
new file mode 100644
index 00000000000..2c33666241e
--- /dev/null
+++ b/dlls/fusion/tests/Makefile.in
@@ -0,0 +1,13 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+TESTDLL   = fusion.dll
+IMPORTS   = kernel32
+
+CTESTS = \
+	asmcache.c \
+
+@MAKE_TEST_RULES@
+
+@DEPENDENCIES@  # everything below this line is overwritten by make depend
diff --git a/dlls/fusion/tests/asmcache.c b/dlls/fusion/tests/asmcache.c
new file mode 100644
index 00000000000..eac2109ccbc
--- /dev/null
+++ b/dlls/fusion/tests/asmcache.c
@@ -0,0 +1,961 @@
+/*
+ * Copyright 2008 James Hawkins
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+#define INITGUID
+
+#include <stdio.h>
+
+#include <windows.h>
+#include <mscoree.h>
+#include <fusion.h>
+#include <corerror.h>
+
+#include "wine/test.h"
+
+typedef struct _tagASSEMBLY ASSEMBLY;
+
+typedef struct
+{
+    ULONG Signature;
+    USHORT MajorVersion;
+    USHORT MinorVersion;
+    ULONG Reserved;
+    ULONG VersionLength;
+    BYTE Version[12];
+    BYTE Flags;
+    WORD Streams;
+} METADATAHDR;
+
+#include <pshpack1.h>
+
+typedef struct
+{
+    DWORD Offset;
+    DWORD Size;
+} METADATASTREAMHDR;
+
+typedef struct
+{
+    DWORD Reserved1;
+    BYTE MajorVersion;
+    BYTE MinorVersion;
+    BYTE HeapOffsetSizes;
+    BYTE Reserved2;
+    LARGE_INTEGER MaskValid;
+    LARGE_INTEGER MaskSorted;
+} METADATATABLESHDR;
+
+typedef struct
+{
+    WORD Generation;
+    WORD Name;
+    WORD Mvid;
+    WORD EncId;
+    WORD EncBaseId;
+} MODULETABLE;
+
+typedef struct
+{
+    DWORD Flags;
+    WORD Name;
+    WORD Namespace;
+    WORD Extends;
+    WORD FieldList;
+    WORD MethodList;
+} TYPEDEFTABLE;
+
+typedef struct
+{
+    DWORD HashAlgId;
+    WORD MajorVersion;
+    WORD MinorVersion;
+    WORD BuildNumber;
+    WORD RevisionNumber;
+    DWORD Flags;
+    WORD PublicKey;
+    WORD Name;
+    WORD Culture;
+} ASSEMBLYTABLE;
+
+typedef struct
+{
+    DWORD Offset;
+    DWORD Flags;
+    WORD Name;
+    WORD Implementation;
+} MANIFESTRESTABLE;
+
+typedef struct
+{
+    DWORD ImportLookupTable;
+    DWORD DateTimeStamp;
+    DWORD ForwarderChain;
+    DWORD Name;
+    DWORD ImportAddressTable;
+    BYTE pad[20];
+} IMPORTTABLE;
+
+typedef struct
+{
+    DWORD HintNameTableRVA;
+    BYTE pad[8];
+} IMPORTLOOKUPTABLE;
+
+typedef struct
+{
+    WORD Hint;
+    BYTE Name[12];
+    BYTE Module[12];
+    DWORD Reserved;
+    WORD EntryPoint;
+    DWORD RVA;
+} HINTNAMETABLE;
+
+typedef struct
+{
+    DWORD PageRVA;
+    DWORD Size;
+    DWORD Relocation;
+} RELOCATION;
+
+typedef struct
+{
+    WORD wLength;
+    WORD wValueLength;
+    WORD wType;
+    WCHAR szKey[17];
+    VS_FIXEDFILEINFO Value;
+} VS_VERSIONINFO;
+
+typedef struct
+{
+    WORD wLength;
+    WORD wValueLength;
+    WORD wType;
+    WCHAR szKey[13];
+} VARFILEINFO;
+
+typedef struct
+{
+    WORD wLength;
+    WORD wValueLength;
+    WORD wType;
+    WCHAR szKey[13];
+    DWORD Value;
+} VAR;
+
+typedef struct
+{
+    WORD wLength;
+    WORD wValueLength;
+    WORD wType;
+    WCHAR szKey[15];
+} STRINGFILEINFO;
+
+typedef struct
+{
+    WORD wLength;
+    WORD wValueLength;
+    WORD wType;
+    WCHAR szKey[9];
+} STRINGTABLE;
+
+typedef struct
+{
+    WORD wLength;
+    WORD wValueLength;
+    WORD wType;
+} STRINGHDR;
+
+typedef struct
+{
+    DWORD Size;
+    DWORD Signature;
+    DWORD HeaderVersion;
+    DWORD SkipBytes;
+    BYTE Data[168];
+} RESOURCE;
+
+#include <poppack.h>
+
+static struct _tagASSEMBLY
+{
+    IMAGE_DOS_HEADER doshdr;
+    WORD unknown[32];
+    IMAGE_NT_HEADERS32 nthdrs;
+    IMAGE_SECTION_HEADER text;
+    IMAGE_SECTION_HEADER rsrc;
+    IMAGE_SECTION_HEADER reloc;
+    BYTE pad[16];
+    IMAGE_IMPORT_BY_NAME iat;
+    BYTE pad2[3];
+    IMAGE_COR20_HEADER clrhdr;
+    WORD strongname[64];
+    RESOURCE resource;
+    METADATAHDR metadatahdr;
+    METADATASTREAMHDR roothdr;
+    BYTE rootname[4];
+    METADATASTREAMHDR stringshdr;
+    BYTE stringsname[12];
+    METADATASTREAMHDR ushdr;
+    BYTE usname[4];
+    METADATASTREAMHDR guidhdr;
+    BYTE guidname[8];
+    METADATASTREAMHDR blobhdr;
+    BYTE blobname[8];
+    METADATATABLESHDR tableshdr;
+    DWORD numrows[4];
+    MODULETABLE modtable;
+    TYPEDEFTABLE tdtable;
+    ASSEMBLYTABLE asmtable;
+    MANIFESTRESTABLE manifestrestable;
+    WORD pad3;
+    BYTE stringheap[40];
+    WORD usheap[4];
+    WORD guidheap[8];
+    WORD blobheap[82];
+    IMAGE_IMPORT_DESCRIPTOR importdesc;
+    BYTE pad4[20];
+    IMPORTLOOKUPTABLE importlookup;
+    HINTNAMETABLE hintnametable;
+    BYTE pad5[108];
+    IMAGE_RESOURCE_DIRECTORY topresdir;
+    IMAGE_RESOURCE_DIRECTORY_ENTRY labelres;
+    IMAGE_RESOURCE_DIRECTORY res11dir;
+    IMAGE_RESOURCE_DIRECTORY_ENTRY label11res;
+    IMAGE_RESOURCE_DIRECTORY res10dir;
+    IMAGE_RESOURCE_DIRECTORY_ENTRY label10res;
+    IMAGE_RESOURCE_DATA_ENTRY resdata;
+    VS_VERSIONINFO verinfo;
+    VARFILEINFO varfileinfo;
+    VAR translation;
+    STRINGFILEINFO strfileinfo;
+    STRINGTABLE strtable;
+    STRINGHDR filedeschdr;
+    WCHAR filedesckey[17];
+    WCHAR filedescval[2];
+    STRINGHDR fileverhdr;
+    WCHAR fileverkey[13];
+    WCHAR fileverval[8];
+    STRINGHDR intnamehdr;
+    WCHAR intnamekey[13];
+    WCHAR intnameval[10];
+    STRINGHDR copyrighthdr;
+    WCHAR copyrightkey[15];
+    WCHAR copyrightval[2];
+    STRINGHDR orignamehdr;
+    WCHAR orignamekey[17];
+    WCHAR orignameval[10];
+    STRINGHDR prodverhdr;
+    WCHAR prodverkey[15];
+    WCHAR prodverval[8];
+    STRINGHDR asmverhdr;
+    WCHAR asmverkey[17];
+    WCHAR asmverval[8];
+    WORD pad6[182];
+    RELOCATION relocation;
+    WORD pad7[250];
+} assembly =
+{
+    /* IMAGE_DOS_HEADER */
+    {
+        IMAGE_DOS_SIGNATURE, 144, 3, 0, 4, 0, 0xFFFF, 0, 0xB8, 0, 0, 0, 0x40,
+        0, { 0  }, 0, 0, { 0 }, 0x80
+    },
+    /* binary to print "This program cannot be run in DOS mode." */
+    {
+        0x1F0E, 0x0EBA, 0xB400, 0xCD09, 0xB821, 0x4C01, 0x21CD, 0x6854, 0x7369,
+        0x7020, 0x6F72, 0x7267, 0x6D61, 0x6320, 0x6E61, 0x6F6E, 0x2074, 0x6562,
+        0x7220, 0x6E75, 0x6920, 0x206E, 0x4F44, 0x2053, 0x6F6D, 0x6564, 0x0D2E,
+        0x0A0D, 0x0024, 0x0000, 0x0000, 0x0000
+    },
+    /* IMAGE_NT_HEADERS32 */
+    {
+        IMAGE_NT_SIGNATURE, /* Signature */
+        /* IMAGE_FILE_HEADER */
+        {
+            IMAGE_FILE_MACHINE_I386, /* Machine */
+            3, /* NumberOfSections */
+            0x47EFDF09, /* TimeDateStamp */
+            0, /* PointerToSymbolTable */
+            0, /* NumberOfSymbols */
+            0xE0, /* SizeOfOptionalHeader */
+            IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED |
+            IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE |
+            IMAGE_FILE_DLL, /* Characteristics */
+        },
+        /* IMAGE_OPTIONAL_HEADER32 */
+        {
+            IMAGE_NT_OPTIONAL_HDR_MAGIC, /* Magic */
+            8, /* MajorLinkerVersion */
+            0, /* MinorLinkerVersion */
+            0x400, /* SizeOfCode */
+            0x600, /* SizeOfInitializedData */
+            0, /* SizeOfUninitializedData */
+            0x238E, /* AddressOfEntryPoint */
+            0x2000, /* BaseOfCode */
+            0x4000, /* BaseOfData */
+            0x400000, /* ImageBase */
+            0x2000, /* SectionAlignment */
+            0x200, /* FileAlignment */
+            4, /* MajorOperatingSystemVersion */
+            0, /* MinorOperatingSystemVersion */
+            0, /* MajorImageVersion */
+            0, /* MinorImageVersion */
+            4, /* MajorSubsystemVersion */
+            0, /* MinorSubsystemVersion */
+            0, /* Win32VersionValue */
+            0x8000, /* SizeOfImage */
+            0x200, /* SizeOfHeaders */
+            0xB576, /* CheckSum */
+            IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
+            IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
+            IMAGE_DLLCHARACTERISTICS_NO_SEH |
+            IMAGE_DLLCHARACTERISTICS_NX_COMPAT, /* DllCharacteristics */
+            0x100000, /* SizeOfStackReserve */
+            0x1000, /* SizeOfStackCommit */
+            0x100000, /* SizeOfHeapReserve */
+            0x1000, /* SizeOfHeapCommit */
+            0, /* LoaderFlags */
+            0x10, /* NumberOfRvaAndSizes */
+            /* IMAGE_DATA_DIRECTORY */
+            {
+                { 0 }, /* Export Table */
+                { 0x233C, 0x4F }, /* Import Table */
+                { 0x4000, 0x298 }, /* Resource Table */
+                { 0 }, /* Exception Table */
+                { 0 }, /* Certificate Table */
+                { 0x6000, 0xC }, /* Base Relocation Table */
+                { 0 }, /* Debug */
+                { 0 }, /* Copyright */
+                { 0 }, /* Global Ptr */
+                { 0 }, /* TLS Table */
+                { 0 }, /* Load Config Table */
+                { 0 }, /* Bound Import */
+                { 0x2000, 8 }, /* IAT */
+                { 0 }, /* Delay Import Descriptor */
+                { 0x2008, 0x48 }, /* CLI Header */
+                { 0 } /* Reserved */
+            }
+        }
+    },
+    /* IMAGE_SECTION_HEADER */
+    {
+        ".text", /* Name */
+        { 0x394 }, /* Misc.VirtualSize */
+        0x2000, /* VirtualAddress */
+        0x400, /* SizeOfRawData */
+        0x200, /* PointerToRawData */
+        0, /* PointerToRelocations */
+        0, /* PointerToLinenumbers */
+        0, /* NumberOfRelocations */
+        0, /* NumberOfLinenumbers */
+        IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE |
+        IMAGE_SCN_CNT_CODE, /* Characteristics */
+    },
+    /* IMAGE_SECTION_HEADER */
+    {
+        ".rsrc", /* Name */
+        { 0x298 }, /* Misc.VirtualSize */
+        0x4000, /* VirtualAddress */
+        0x400, /* SizeOfRawData */
+        0x600, /* PointerToRawData */
+        0, /* PointerToRelocations */
+        0, /* PointerToLinenumbers */
+        0, /* NumberOfRelocations */
+        0, /* NumberOfLinenumbers */
+        IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
+    },
+    /* IMAGE_SECTION_HEADER */
+    {
+        ".reloc", /* Name */
+        { 0xC }, /* Misc.VirtualSize */
+        0x6000, /* VirtualAddress */
+        0x200, /* SizeOfRawData */
+        0xA00, /* PointerToRawData */
+        0, /* PointerToRelocations */
+        0, /* PointerToLinenumbers */
+        0, /* NumberOfRelocations */
+        0, /* NumberOfLinenumbers */
+        IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
+        IMAGE_SCN_MEM_DISCARDABLE, /* Characteristics */
+    },
+    /* fill */
+    { 0 },
+    /* IMAGE_IMPORT_BY_NAME */
+    {
+        0x2370, /* Hint */
+        { 0 } /* Name */
+    },
+    /* fill */
+    { 0 },
+    /* IMAGE_COR20_HEADER */
+    {
+        0x48, /* Cb */
+        2, /* MajorRuntimeVersion */
+        5, /* MinorRuntimeVersion */
+        { 0x2188, 0x1B4 }, /* MetaData */
+        COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_STRONGNAMESIGNED, /* Flags */
+        0, /* EntryPointToken */
+        { 0x20D0, 0xB8 }, /* Resources */
+        { 0x2050, 0x80 }, /* StrongNameSignature */
+        { 0 }, /* CodeManagerTable */
+        { 0 }, /* VTableFixups */
+        { 0 }, /* ExportAddressTableJumps */
+        { 0 } /* ManagedNativeHeader */
+    },
+    { 0xE496, 0x9A6E, 0xD95E, 0xA2A1, 0x5D72, 0x9CEF, 0x41E3, 0xD483,
+      0xCB5C, 0x329A, 0x887C, 0xE18E, 0xE664, 0x2E1C, 0x0E61, 0xB361,
+      0x8B88, 0xC8D0, 0x47A5, 0x9260, 0x6CC5, 0xE60F, 0x1F61, 0x1E3E,
+      0xAFEE, 0x925A, 0xA084, 0x6B44, 0x2DC6, 0x8126, 0xEBC9, 0xD812,
+      0xF3E9, 0xA3F3, 0xD0D5, 0x2C7F, 0x4592, 0xA0AF, 0x8B15, 0xD91E,
+      0x693E, 0x7A4F, 0x5567, 0xC466, 0xC410, 0x3D29, 0xB25F, 0xCD6C,
+      0x53EF, 0x0D29, 0x085A, 0xEC39, 0xE3BD, 0x58E0, 0x78F5, 0x0587,
+      0xF8D8, 0x14E4, 0x77CE, 0xCCC9, 0x4DCF, 0x8A18, 0x90E8, 0x1A52
+    },
+    /* RESOURCE */
+    {
+        0xB4, /* Size */
+        0xBEEFCACE, /* Signature */
+        1, /* HeaderVersion */
+        0x91, /* SkipBytes */
+        { 'l','S','y','s','t','e','m','.','R','e','s','o','u','r','c','e','s','.',
+          'R','e','s','o','u','r','c','e','R','e','a','d','e','r',',',' ',
+          'm','s','c','o','r','l','i','b',',',' ','V','e','r','s','i','o','n','=',
+          '2','.','0','.','0','.','0',',',' ','C','u','l','t','u','r','e','=',
+          'n','e','u','t','r','a','l',',',' ','P','u','b','l','i','c','K','e','y','T','o','k','e','n','=',
+          'b','7','7','a','5','c','5','6','1','9','3','4','e','0','8','9',
+          '#','S','y','s','t','e','m','.','R','e','s','o','u','r','c','e','s','.',
+          'R','u','n','t','i','m','e','R','e','s','o','u','r','c','e','S','e','t',
+          2,0,0,0,0,0,0,0,0,0,0,0,'P','A','D','P','A','D','P',180,0,0,0
+        }
+    },
+    /* METADATAHDR */
+    {
+        0x424A5342, /* Signature */
+        1, /* MajorVersion */
+        1, /* MinorVersion */
+        0, /* Reserved */
+        0xC, /* VersionLength */
+        "v2.0.50727", /* Version */
+        0, /* Flags */
+        5 /* Streams */
+    },
+    /* METADATASTREAMHDR */
+    {
+        0x6C, /* Offset */
+        0x64, /* Size */
+    },
+    "#~\0\0",
+    /* METADATASTREAMHDR */
+    {
+        0xD0, /* Offset */
+        0x28, /* Size */
+    },
+    "#Strings\0\0\0\0",
+    /* METADATASTREAMHDR */
+    {
+        0xF8, /* Offset */
+        0x8, /* Size */
+    },
+    "#US\0",
+    /* METADATASTREAMHDR */
+    {
+        0x100, /* Offset */
+        0x10, /* Size */
+    },
+    "#GUID\0\0\0",
+    /* METADATASTREAMHDR */
+    {
+        0x110, /* Offset */
+        0xA4, /* Size */
+    },
+    "#Blob\0\0\0",
+    /* METADATATABLESHDR */
+    {
+        0, /* Reserved1 */
+        2, /* MajorVersion */
+        0, /* MinorVersion */
+        0, /* HeapOffsetSizes */
+        1, /* Reserved2 */
+        { { 0 } }, /* MaskValid */
+        { { 0 } } /* MaskSorted */
+    },
+    /* numrows */
+    { 1, 1, 1, 1 },
+    /* MODULETABLE */
+    {
+        0, /* Generation */
+        0xA, /* Name */
+        1, /* Mvid */
+        0, /* EncId */
+        0 /* EncBaseId */
+    },
+    /* TYPEDEFTABLE */
+    {
+        0, /* Flags */
+        0x1, /* Name */
+        0, /* Namespace */
+        0, /* Extends */
+        1, /* FieldList */
+        1 /* MethodList */
+    },
+    /* ASSEMBLYTABLE */
+    {
+        0x8004, /* HashAlgId */
+        1, /* MajorVersion */
+        0, /* MinorVersion */
+        0, /* BuildNumber */
+        0, /* RevisionNumber */
+        1, /* Flags */
+        1, /* PublicKey */
+        0x13, /* Name */
+        0 /* Culture */
+    },
+    /* MANIFESTRESTABLE */
+    {
+        0, /* Offset */
+        0x2, /* Flags */
+        0x18, /* Name */
+        0 /* Implementation */
+    },
+    /* pad */
+    0,
+    /* String heap */
+    "\0<Module>\0wine.dll\0wine\0wine.resources\0\0",
+    /* US heap */
+    { 0x0300, 0x0020 },
+    /* GUID heap */
+    { 0x86EF, 0x5B5A, 0x2C5E, 0x4F6D, 0xC2AB, 0x0A94, 0xD658, 0x31DA },
+    /* BLOB heap */
+    { 0x8000, 0x00A0, 0x0024, 0x0400, 0x0080, 0x9400, 0x0000, 0x0600,
+      0x0002, 0x0000, 0x0024, 0x5200, 0x4153, 0x0031, 0x0004, 0x0100,
+      0x0100, 0x2F00, 0x60E0, 0x4D76, 0x5E5C, 0x430A, 0x6FF3, 0x77D6,
+      0x04CA, 0xF6AD, 0xF54D, 0x0AD2, 0x9FB6, 0x39C2, 0x2E66, 0xD30F,
+      0x916F, 0x1826, 0xFB52, 0x78A0, 0x8262, 0x6902, 0xBD47, 0xAF30,
+      0xBAB1, 0x29DA, 0xAA6D, 0xF189, 0x296A, 0x0F13, 0x4982, 0x531D,
+      0x8283, 0x1343, 0x5A33, 0x5D36, 0xEB3F, 0x0863, 0xA771, 0x0679,
+      0x4DFF, 0xD30A, 0xBEAD, 0x2A9F, 0x12A8, 0x4319, 0x5706, 0x333D,
+      0x0CAC, 0xE80A, 0xFD99, 0xC82D, 0x3D3B, 0xBFFE, 0xF256, 0x25E3,
+      0x1A12, 0xC116, 0x8936, 0xF237, 0x5F26, 0xC68A, 0x1E42, 0xCE41,
+      0xC17C, 0x00C4
+    },
+    /* IMAGE_IMPORT_DESCRIPTOR */
+    {
+        { 0x2364 }, /* OriginalFirstThunk */
+        0, /* TimeDateStamp */
+        0, /* ForwarderChain */
+        0x237E, /* Name */
+        0x2000, /* FirstThunk */
+    },
+    /* pad */
+    { 0 },
+    /* IMPORTLOOKUPTABLE */
+    {
+        0x2370, /* HintNameTableRVA */
+        { 0 }, /* pad */
+    },
+    /* HINTNAMETABLE */
+    {
+        0, /* Hint */
+        "_CorDllMain", /* Name */
+        "mscoree.dll", /* Module */
+        0, /* Reserved */
+        0x25FF, /* EntryPoint */
+        0x402000 /* RVA */
+    },
+    /* pad to 0x600 */
+    { 0 },
+    /* IMAGE_RESOURCE_DIRECTORY */
+    {
+        0, /* Characteristics */
+        0, /* TimeDateStamp */
+        0, /* MajorVersion */
+        0, /* MinorVersion */
+        0, /* NumberOfNamedEntries */
+        1, /* NumberOfIdEntries */
+    },
+    /* IMAGE_RESOURCE_DIRECTORY_ENTRY */
+    { { { 0 } }, { 0 } }, /* nameless unions initialized later */
+    /* IMAGE_RESOURCE_DIRECTORY */
+    {
+        0, /* Characteristics */
+        0, /* TimeDateStamp */
+        0, /* MajorVersion */
+        0, /* MinorVersion */
+        0, /* NumberOfNamedEntries */
+        1, /* NumberOfIdEntries */
+    },
+    /* IMAGE_RESOURCE_DIRECTORY_ENTRY */
+    { { { 0 } }, { 0 } }, /* nameless unions initialized later */
+    /* IMAGE_RESOURCE_DIRECTORY */
+    {
+        0, /* Characteristics */
+        0, /* TimeDateStamp */
+        0, /* MajorVersion */
+        0, /* MinorVersion */
+        0, /* NumberOfNamedEntries */
+        1, /* NumberOfIdEntries */
+    },
+    /* IMAGE_RESOURCE_DIRECTORY_ENTRY */
+    { { { 0 } }, { 0 } }, /* nameless unions initialized later */
+    /* IMAGE_RESOURCE_DATA_ENTRY */
+    {
+        0x4058, /* OffsetToData */
+        0x23C, /* Size */
+        0, /* CodePage */
+        0, /* Reserved */
+    },
+    /* VS_VERSIONINFO */
+    {
+        0x23C, /* wLength */
+        0x34, /* wValueLength */
+        0, /* wType */
+        { 'V','S','_','V','E','R','S','I','O','N','_','I','N','F','O',0,0 }, /* szKey */
+        /* VS_FIXEDFILEINFO */
+        {
+            VS_FFI_SIGNATURE, /* dwSignature */
+            VS_FFI_STRUCVERSION, /* dwStrucVersion */
+            0x10000, /* dwFileVersionMS */
+            0x00000, /* dwFileVersionLS */
+            0x10000, /* dwProductVersionMS */
+            0x00000, /* dwProductVersionLS */
+            VS_FFI_FILEFLAGSMASK, /* dwFileFlagsMask */
+            0x0, /* dwFileFlags */
+            VOS__WINDOWS32, /* dwFileOS */
+            VFT_DLL, /* dwFileType */
+            VFT2_UNKNOWN, /* dwFileSubtype */
+            0, /* dwFileDateMS */
+            0, /* dwFileDateLS */
+        },
+    },
+    /* VARFILEINFO */
+    {
+        0x44, /* wLength */
+        0, /* wValueLength */
+        1, /* wType */
+        { 'V','a','r','F','i','l','e','I','n','f','o',0,0 } /* szKey */
+    },
+    /* VAR */
+    {
+        0x24, /* wLength */
+        0x4, /* wValueLength */
+        0, /* wType */
+        { 'T','r','a','n','s','l','a','t','i','o','n',0,0 }, /* szKey */
+        0x4B00000, /* Value */
+    },
+    /* STRINGFILEINFO */
+    {
+        0x19C, /* wLength */
+        0, /* wValueLength */
+        1, /* wType */
+        { 'S','t','r','i','n','g','F','i','l','e','I','n','f','o',0 }, /* szKey */
+    },
+    /* STRINGTABLE */
+    {
+        0x178, /* wLength */
+        0, /* wValueLength */
+        1, /* wType */
+        { '0','0','0','0','0','4','b','0',0 }, /* szKey */
+    },
+    /* STRINGHDR */
+    {
+        0x2C, /* wLength */
+        2, /* wValueLength */
+        1, /* wType */
+    },
+    { 'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0,0 }, /* szKey */
+    { ' ',0 }, /* szValue */
+    /* STRINGHDR */
+    {
+        0x30, /* wLength */
+        8, /* wValueLength */
+        1, /* wType */
+    },
+    { 'F','i','l','e','V','e','r','s','i','o','n',0,0 }, /* szKey */
+    { '1','.','0','.','0','.','0',0 }, /* szValue */
+    /* STRINGHDR */
+    {
+        0x34, /* wLength */
+        9, /* wValueLength */
+        1, /* wType */
+    },
+    { 'I','n','t','e','r','n','a','l','N','a','m','e',0 }, /* szKey */
+    { 'w','i','n','e','.','d','l','l',0 }, /* szValue */
+    /* STRINGHDR */
+    {
+        0x28, /* wLength */
+        2, /* wValueLength */
+        1, /* wType */
+    },
+    { 'L','e','g','a','l','C','o','p','y','r','i','g','h','t',0 }, /* szKey */
+    { ' ',0 }, /* szValue */
+    /* STRINGHDR */
+    {
+        0x3C, /* wLength */
+        9, /* wValueLength */
+        1, /* wType */
+    },
+    { 'O','r','i','g','i','n','a','l','F','i','l','e','n','a','m','e',0 }, /* szKey */
+    { 'w','i','n','e','.','d','l','l',0,0 }, /* szValue */
+    /* STRINGHDR */
+    {
+        0x34, /* wLength */
+        8, /* wValueLength */
+        1, /* wType */
+    },
+    { 'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 }, /* szKey */
+    { '1','.','0','.','0','.','0',0 }, /* szValue */
+    /* STRINGHDR */
+    {
+        0x38, /* wLength */
+        8, /* wValueLength */
+        1, /* wType */
+    },
+    { 'A','s','s','e','m','b','l','y',' ','V','e','r','s','i','o','n',0 }, /* szKey */
+    { '1','.','0','.','0','.','0',0 }, /* szValue */
+    { 0 }, /* pad */
+    /* RELOCATION */
+    {
+        0x2000, /* PageRVA */
+        0xC, /* Size */
+        0x3390, /* Relocation */
+    },
+    { 0 }
+};
+
+
+static HRESULT (WINAPI *pCreateAssemblyCache)(IAssemblyCache **ppAsmCache,
+                                              DWORD dwReserved);
+static HRESULT (WINAPI *pLoadLibraryShim)(LPCWSTR szDllName, LPCWSTR szVersion,
+                                          LPVOID pvReserved, HMODULE *phModDll);
+
+static BOOL init_functionpointers(void)
+{
+    HRESULT hr;
+    HMODULE hfusion;
+    HMODULE hmscoree;
+
+    static const WCHAR szFusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
+
+    hmscoree = LoadLibraryA("mscoree.dll");
+    if (!hmscoree)
+    {
+        skip("mscoree.dll not available\n");
+        return FALSE;
+    }
+
+    pLoadLibraryShim = (void *)GetProcAddress(hmscoree, "LoadLibraryShim");
+    if (!pLoadLibraryShim)
+    {
+        skip("LoadLibraryShim not available\n");
+        FreeLibrary(hmscoree);
+        return FALSE;
+    }
+
+    hr = pLoadLibraryShim(szFusion, NULL, NULL, &hfusion);
+    if (FAILED(hr))
+    {
+        skip("fusion.dll not available\n");
+        FreeLibrary(hmscoree);
+        return FALSE;
+    }
+
+    pCreateAssemblyCache = (void *)GetProcAddress(hfusion, "CreateAssemblyCache");
+
+    FreeLibrary(hmscoree);
+    return TRUE;
+}
+
+static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
+{
+    HANDLE file;
+    DWORD written;
+
+    file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
+    WriteFile(file, data, strlen(data), &written, NULL);
+
+    if (size)
+    {
+        SetFilePointer(file, size, NULL, FILE_BEGIN);
+        SetEndOfFile(file);
+    }
+
+    CloseHandle(file);
+}
+
+#define create_file(name, size) create_file_data(name, name, size)
+
+static void create_assembly(LPCSTR file)
+{
+    HANDLE hfile;
+    DWORD written;
+
+    /* nameless unions initialized here */
+    assembly.tableshdr.MaskValid.HighPart = 0x101;
+    assembly.tableshdr.MaskValid.LowPart = 0x00000005;
+    assembly.tableshdr.MaskSorted.HighPart = 0x1600;
+    assembly.tableshdr.MaskSorted.LowPart = 0x3301FA00;
+    assembly.labelres.Name = 0x10;
+    assembly.labelres.OffsetToData = 0x80000018;
+    assembly.label11res.Name = 0x1;
+    assembly.label11res.OffsetToData = 0x80000030;
+    assembly.label10res.Name = 0x0;
+    assembly.label10res.OffsetToData = 0x48;
+
+    hfile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+
+    WriteFile(hfile, &assembly, sizeof(ASSEMBLY), &written, NULL);
+    CloseHandle(hfile);
+}
+
+static void test_CreateAssemblyCache(void)
+{
+    IAssemblyCache *cache;
+    HRESULT hr;
+
+    if (!pCreateAssemblyCache)
+    {
+        skip("CreateAssemblyCache not implemented\n");
+        return;
+    }
+
+    /* NULL ppAsmCache */
+    hr = pCreateAssemblyCache(NULL, 0);
+    ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
+
+    /* dwReserved is non-zero */
+    hr = pCreateAssemblyCache(&cache, 42);
+    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+
+    IAssemblyCache_Release(cache);
+}
+
+static void test_InstallAssembly(void)
+{
+    IAssemblyCache *cache;
+    HRESULT hr;
+    ULONG disp;
+
+    static const WCHAR empty[] = {0};
+    static const WCHAR noext[] = {'f','i','l','e',0};
+    static const WCHAR badext[] = {'f','i','l','e','.','b','a','d',0};
+    static const WCHAR dllext[] = {'f','i','l','e','.','d','l','l',0};
+    static const WCHAR exeext[] = {'f','i','l','e','.','e','x','e',0};
+    static const WCHAR testdll[] = {'t','e','s','t','.','d','l','l',0};
+    static const WCHAR winedll[] = {'w','i','n','e','.','d','l','l',0};
+    static const WCHAR wine[] = {'w','i','n','e',0};
+
+    if (!pCreateAssemblyCache)
+    {
+        skip("CreateAssemblyCache not implemented\n");
+        return;
+    }
+
+    create_file("test.dll", 100);
+    create_assembly("wine.dll");
+
+    hr = pCreateAssemblyCache(&cache, 0);
+    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+
+    /* NULL pszManifestFilePath */
+    hr = IAssemblyCache_InstallAssembly(cache, 0, NULL, NULL);
+    todo_wine
+    {
+        ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
+    }
+
+    /* empty pszManifestFilePath */
+    hr = IAssemblyCache_InstallAssembly(cache, 0, empty, NULL);
+    todo_wine
+    {
+        ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
+    }
+
+    /* pszManifestFilePath has no extension */
+    hr = IAssemblyCache_InstallAssembly(cache, 0, noext, NULL);
+    todo_wine
+    {
+        ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
+           "Expected HRESULT_FROM_WIN32(ERROR_INVALID_NAME), got %08x\n", hr);
+    }
+
+    /* pszManifestFilePath has bad extension */
+    hr = IAssemblyCache_InstallAssembly(cache, 0, badext, NULL);
+    todo_wine
+    {
+        ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
+           "Expected HRESULT_FROM_WIN32(ERROR_INVALID_NAME), got %08x\n", hr);
+    }
+
+    /* pszManifestFilePath has dll extension */
+    hr = IAssemblyCache_InstallAssembly(cache, 0, dllext, NULL);
+    todo_wine
+    {
+        ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+           "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
+    }
+
+    /* pszManifestFilePath has exe extension */
+    hr = IAssemblyCache_InstallAssembly(cache, 0, exeext, NULL);
+    todo_wine
+    {
+        ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+           "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
+    }
+
+    /* empty file */
+    hr = IAssemblyCache_InstallAssembly(cache, 0, testdll, NULL);
+    todo_wine
+    {
+        ok(hr == COR_E_ASSEMBLYEXPECTED,
+           "Expected COR_E_ASSEMBLYEXPECTED, got %08x\n", hr);
+    }
+
+    /* wine assembly */
+    hr = IAssemblyCache_InstallAssembly(cache, 0, winedll, NULL);
+    todo_wine
+    {
+        ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+    }
+
+    /* uninstall the assembly from the GAC */
+    hr = IAssemblyCache_UninstallAssembly(cache, 0, wine, NULL, &disp);
+    todo_wine
+    {
+        ok(hr == S_OK, "Expected S_OK, got %d\n", S_OK);
+        ok(disp == IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED,
+           "Expected IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED, got %d\n", disp);
+    }
+
+    DeleteFileA("test.dll");
+    DeleteFileA("wine.dll");
+    IAssemblyCache_Release(cache);
+}
+
+START_TEST(asmcache)
+{
+    if (!init_functionpointers())
+        return;
+
+    test_CreateAssemblyCache();
+    test_InstallAssembly();
+
+}
diff --git a/programs/winetest/Makefile.in b/programs/winetest/Makefile.in
index 6f3d634960e..7ccce1896df 100644
--- a/programs/winetest/Makefile.in
+++ b/programs/winetest/Makefile.in
@@ -44,6 +44,7 @@ TESTBINS = \
 	dnsapi_test.exe \
 	dplayx_test.exe \
 	dsound_test.exe \
+	fusion_test.exe \
 	gdi32_test.exe \
 	gdiplus_test.exe \
 	hlink_test.exe \
@@ -144,6 +145,8 @@ dplayx_test.exe: $(DLLDIR)/dplayx/tests/dplayx_test.exe$(DLLEXT)
 	cp $(DLLDIR)/dplayx/tests/dplayx_test.exe$(DLLEXT) $@ && $(STRIP) $@
 dsound_test.exe: $(DLLDIR)/dsound/tests/dsound_test.exe$(DLLEXT)
 	cp $(DLLDIR)/dsound/tests/dsound_test.exe$(DLLEXT) $@ && $(STRIP) $@
+fusion_test.exe: $(DLLDIR)/fusion/tests/fusion_test.exe$(DLLEXT)
+	cp $(DLLDIR)/fusion/tests/fusion_test.exe$(DLLEXT) $@ && $(STRIP) $@
 gdi32_test.exe: $(DLLDIR)/gdi32/tests/gdi32_test.exe$(DLLEXT)
 	cp $(DLLDIR)/gdi32/tests/gdi32_test.exe$(DLLEXT) $@ && $(STRIP) $@
 gdiplus_test.exe: $(DLLDIR)/gdiplus/tests/gdiplus_test.exe$(DLLEXT)
diff --git a/programs/winetest/winetest.rc b/programs/winetest/winetest.rc
index ceec920d3a3..8c36d63d060 100644
--- a/programs/winetest/winetest.rc
+++ b/programs/winetest/winetest.rc
@@ -105,6 +105,7 @@ dinput_test.exe TESTRES "dinput_test.exe"
 dnsapi_test.exe TESTRES "dnsapi_test.exe"
 dplayx_test.exe TESTRES "dplayx_test.exe"
 dsound_test.exe TESTRES "dsound_test.exe"
+fusion_test.exe TESTRES "fusion_test.exe"
 gdi32_test.exe TESTRES "gdi32_test.exe"
 gdiplus_test.exe TESTRES "gdiplus_test.exe"
 hlink_test.exe TESTRES "hlink_test.exe"
-- 
GitLab