1 /*
2  * Copyright 2008 James Hawkins
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #define COBJMACROS
20 #define INITGUID
21 
22 #include <stdio.h>
23 
24 #include <windows.h>
25 #include <mscoree.h>
26 #include <fusion.h>
27 #include <corerror.h>
28 
29 #include "wine/test.h"
30 
31 typedef struct _tagASSEMBLY ASSEMBLY;
32 
33 typedef struct
34 {
35     ULONG Signature;
36     USHORT MajorVersion;
37     USHORT MinorVersion;
38     ULONG Reserved;
39     ULONG VersionLength;
40     BYTE Version[12];
41     BYTE Flags;
42     WORD Streams;
43 } METADATAHDR;
44 
45 #include <pshpack1.h>
46 
47 typedef struct
48 {
49     DWORD Offset;
50     DWORD Size;
51 } METADATASTREAMHDR;
52 
53 typedef struct
54 {
55     DWORD Reserved1;
56     BYTE MajorVersion;
57     BYTE MinorVersion;
58     BYTE HeapOffsetSizes;
59     BYTE Reserved2;
60     LARGE_INTEGER MaskValid;
61     LARGE_INTEGER MaskSorted;
62 } METADATATABLESHDR;
63 
64 typedef struct
65 {
66     WORD Generation;
67     WORD Name;
68     WORD Mvid;
69     WORD EncId;
70     WORD EncBaseId;
71 } MODULETABLE;
72 
73 typedef struct
74 {
75     DWORD Flags;
76     WORD Name;
77     WORD Namespace;
78     WORD Extends;
79     WORD FieldList;
80     WORD MethodList;
81 } TYPEDEFTABLE;
82 
83 typedef struct
84 {
85     DWORD HashAlgId;
86     WORD MajorVersion;
87     WORD MinorVersion;
88     WORD BuildNumber;
89     WORD RevisionNumber;
90     DWORD Flags;
91     WORD PublicKey;
92     WORD Name;
93     WORD Culture;
94 } ASSEMBLYTABLE;
95 
96 typedef struct
97 {
98     DWORD Offset;
99     DWORD Flags;
100     WORD Name;
101     WORD Implementation;
102 } MANIFESTRESTABLE;
103 
104 typedef struct
105 {
106     DWORD ImportLookupTable;
107     DWORD DateTimeStamp;
108     DWORD ForwarderChain;
109     DWORD Name;
110     DWORD ImportAddressTable;
111     BYTE pad[20];
112 } IMPORTTABLE;
113 
114 typedef struct
115 {
116     DWORD HintNameTableRVA;
117     BYTE pad[8];
118 } IMPORTLOOKUPTABLE;
119 
120 typedef struct
121 {
122     WORD Hint;
123     BYTE Name[12];
124     BYTE Module[12];
125     DWORD Reserved;
126     WORD EntryPoint;
127     DWORD RVA;
128 } HINTNAMETABLE;
129 
130 typedef struct
131 {
132     DWORD PageRVA;
133     DWORD Size;
134     DWORD Relocation;
135 } RELOCATION;
136 
137 typedef struct
138 {
139     WORD wLength;
140     WORD wValueLength;
141     WORD wType;
142     WCHAR szKey[17];
143     VS_FIXEDFILEINFO Value;
144 } VS_VERSIONINFO;
145 
146 typedef struct
147 {
148     WORD wLength;
149     WORD wValueLength;
150     WORD wType;
151     WCHAR szKey[13];
152 } VARFILEINFO;
153 
154 typedef struct
155 {
156     WORD wLength;
157     WORD wValueLength;
158     WORD wType;
159     WCHAR szKey[13];
160     DWORD Value;
161 } VAR;
162 
163 typedef struct
164 {
165     WORD wLength;
166     WORD wValueLength;
167     WORD wType;
168     WCHAR szKey[15];
169 } STRINGFILEINFO;
170 
171 typedef struct
172 {
173     WORD wLength;
174     WORD wValueLength;
175     WORD wType;
176     WCHAR szKey[9];
177 } STRINGTABLE;
178 
179 typedef struct
180 {
181     WORD wLength;
182     WORD wValueLength;
183     WORD wType;
184 } STRINGHDR;
185 
186 typedef struct
187 {
188     DWORD Size;
189     DWORD Signature;
190     DWORD HeaderVersion;
191     DWORD SkipBytes;
192     BYTE Data[168];
193 } RESOURCE;
194 
195 #include <poppack.h>
196 
197 static struct _tagASSEMBLY
198 {
199     IMAGE_DOS_HEADER doshdr;
200     WORD unknown[32];
201     IMAGE_NT_HEADERS32 nthdrs;
202     IMAGE_SECTION_HEADER text;
203     IMAGE_SECTION_HEADER rsrc;
204     IMAGE_SECTION_HEADER reloc;
205     BYTE pad[16];
206     IMAGE_IMPORT_BY_NAME iat;
207     BYTE pad2[3];
208     IMAGE_COR20_HEADER clrhdr;
209     WORD strongname[64];
210     RESOURCE resource;
211     METADATAHDR metadatahdr;
212     METADATASTREAMHDR roothdr;
213     BYTE rootname[4];
214     METADATASTREAMHDR stringshdr;
215     BYTE stringsname[12];
216     METADATASTREAMHDR ushdr;
217     BYTE usname[4];
218     METADATASTREAMHDR guidhdr;
219     BYTE guidname[8];
220     METADATASTREAMHDR blobhdr;
221     BYTE blobname[8];
222     METADATATABLESHDR tableshdr;
223     DWORD numrows[4];
224     MODULETABLE modtable;
225     TYPEDEFTABLE tdtable;
226     ASSEMBLYTABLE asmtable;
227     MANIFESTRESTABLE manifestrestable;
228     WORD pad3;
229     BYTE stringheap[40];
230     WORD usheap[4];
231     WORD guidheap[8];
232     WORD blobheap[82];
233     IMAGE_IMPORT_DESCRIPTOR importdesc;
234     BYTE pad4[20];
235     IMPORTLOOKUPTABLE importlookup;
236     HINTNAMETABLE hintnametable;
237     BYTE pad5[108];
238     IMAGE_RESOURCE_DIRECTORY topresdir;
239     IMAGE_RESOURCE_DIRECTORY_ENTRY labelres;
240     IMAGE_RESOURCE_DIRECTORY res11dir;
241     IMAGE_RESOURCE_DIRECTORY_ENTRY label11res;
242     IMAGE_RESOURCE_DIRECTORY res10dir;
243     IMAGE_RESOURCE_DIRECTORY_ENTRY label10res;
244     IMAGE_RESOURCE_DATA_ENTRY resdata;
245     VS_VERSIONINFO verinfo;
246     VARFILEINFO varfileinfo;
247     VAR translation;
248     STRINGFILEINFO strfileinfo;
249     STRINGTABLE strtable;
250     STRINGHDR filedeschdr;
251     WCHAR filedesckey[17];
252     WCHAR filedescval[2];
253     STRINGHDR fileverhdr;
254     WCHAR fileverkey[13];
255     WCHAR fileverval[8];
256     STRINGHDR intnamehdr;
257     WCHAR intnamekey[13];
258     WCHAR intnameval[10];
259     STRINGHDR copyrighthdr;
260     WCHAR copyrightkey[15];
261     WCHAR copyrightval[2];
262     STRINGHDR orignamehdr;
263     WCHAR orignamekey[17];
264     WCHAR orignameval[10];
265     STRINGHDR prodverhdr;
266     WCHAR prodverkey[15];
267     WCHAR prodverval[8];
268     STRINGHDR asmverhdr;
269     WCHAR asmverkey[17];
270     WCHAR asmverval[8];
271     WORD pad6[182];
272     RELOCATION relocation;
273     WORD pad7[250];
274 } assembly =
275 {
276     /* IMAGE_DOS_HEADER */
277     {
278         IMAGE_DOS_SIGNATURE, 144, 3, 0, 4, 0, 0xFFFF, 0, 0xB8, 0, 0, 0, 0x40,
279         0, { 0  }, 0, 0, { 0 }, 0x80
280     },
281     /* binary to print "This program cannot be run in DOS mode." */
282     {
283         0x1F0E, 0x0EBA, 0xB400, 0xCD09, 0xB821, 0x4C01, 0x21CD, 0x6854, 0x7369,
284         0x7020, 0x6F72, 0x7267, 0x6D61, 0x6320, 0x6E61, 0x6F6E, 0x2074, 0x6562,
285         0x7220, 0x6E75, 0x6920, 0x206E, 0x4F44, 0x2053, 0x6F6D, 0x6564, 0x0D2E,
286         0x0A0D, 0x0024, 0x0000, 0x0000, 0x0000
287     },
288     /* IMAGE_NT_HEADERS32 */
289     {
290         IMAGE_NT_SIGNATURE, /* Signature */
291         /* IMAGE_FILE_HEADER */
292         {
293             IMAGE_FILE_MACHINE_I386, /* Machine */
294             3, /* NumberOfSections */
295             0x47EFDF09, /* TimeDateStamp */
296             0, /* PointerToSymbolTable */
297             0, /* NumberOfSymbols */
298             0xE0, /* SizeOfOptionalHeader */
299             IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED |
300             IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE |
301             IMAGE_FILE_DLL, /* Characteristics */
302         },
303         /* IMAGE_OPTIONAL_HEADER32 */
304         {
305             IMAGE_NT_OPTIONAL_HDR32_MAGIC, /* Magic */
306             8, /* MajorLinkerVersion */
307             0, /* MinorLinkerVersion */
308             0x400, /* SizeOfCode */
309             0x600, /* SizeOfInitializedData */
310             0, /* SizeOfUninitializedData */
311             0x238E, /* AddressOfEntryPoint */
312             0x2000, /* BaseOfCode */
313             0x4000, /* BaseOfData */
314             0x400000, /* ImageBase */
315             0x2000, /* SectionAlignment */
316             0x200, /* FileAlignment */
317             4, /* MajorOperatingSystemVersion */
318             0, /* MinorOperatingSystemVersion */
319             0, /* MajorImageVersion */
320             0, /* MinorImageVersion */
321             4, /* MajorSubsystemVersion */
322             0, /* MinorSubsystemVersion */
323             0, /* Win32VersionValue */
324             0x8000, /* SizeOfImage */
325             0x200, /* SizeOfHeaders */
326             0xB576, /* CheckSum */
327             IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
328             IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
329             IMAGE_DLLCHARACTERISTICS_NO_SEH |
330             IMAGE_DLLCHARACTERISTICS_NX_COMPAT, /* DllCharacteristics */
331             0x100000, /* SizeOfStackReserve */
332             0x1000, /* SizeOfStackCommit */
333             0x100000, /* SizeOfHeapReserve */
334             0x1000, /* SizeOfHeapCommit */
335             0, /* LoaderFlags */
336             0x10, /* NumberOfRvaAndSizes */
337             /* IMAGE_DATA_DIRECTORY */
338             {
339                 { 0 }, /* Export Table */
340                 { 0x233C, 0x4F }, /* Import Table */
341                 { 0x4000, 0x298 }, /* Resource Table */
342                 { 0 }, /* Exception Table */
343                 { 0 }, /* Certificate Table */
344                 { 0x6000, 0xC }, /* Base Relocation Table */
345                 { 0 }, /* Debug */
346                 { 0 }, /* Copyright */
347                 { 0 }, /* Global Ptr */
348                 { 0 }, /* TLS Table */
349                 { 0 }, /* Load Config Table */
350                 { 0 }, /* Bound Import */
351                 { 0x2000, 8 }, /* IAT */
352                 { 0 }, /* Delay Import Descriptor */
353                 { 0x2008, 0x48 }, /* CLI Header */
354                 { 0 } /* Reserved */
355             }
356         }
357     },
358     /* IMAGE_SECTION_HEADER */
359     {
360         ".text", /* Name */
361         { 0x394 }, /* Misc.VirtualSize */
362         0x2000, /* VirtualAddress */
363         0x400, /* SizeOfRawData */
364         0x200, /* PointerToRawData */
365         0, /* PointerToRelocations */
366         0, /* PointerToLinenumbers */
367         0, /* NumberOfRelocations */
368         0, /* NumberOfLinenumbers */
369         IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE |
370         IMAGE_SCN_CNT_CODE, /* Characteristics */
371     },
372     /* IMAGE_SECTION_HEADER */
373     {
374         ".rsrc", /* Name */
375         { 0x298 }, /* Misc.VirtualSize */
376         0x4000, /* VirtualAddress */
377         0x400, /* SizeOfRawData */
378         0x600, /* PointerToRawData */
379         0, /* PointerToRelocations */
380         0, /* PointerToLinenumbers */
381         0, /* NumberOfRelocations */
382         0, /* NumberOfLinenumbers */
383         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
384     },
385     /* IMAGE_SECTION_HEADER */
386     {
387         ".reloc", /* Name */
388         { 0xC }, /* Misc.VirtualSize */
389         0x6000, /* VirtualAddress */
390         0x200, /* SizeOfRawData */
391         0xA00, /* PointerToRawData */
392         0, /* PointerToRelocations */
393         0, /* PointerToLinenumbers */
394         0, /* NumberOfRelocations */
395         0, /* NumberOfLinenumbers */
396         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
397         IMAGE_SCN_MEM_DISCARDABLE, /* Characteristics */
398     },
399     /* fill */
400     { 0 },
401     /* IMAGE_IMPORT_BY_NAME */
402     {
403         0x2370, /* Hint */
404         { 0 } /* Name */
405     },
406     /* fill */
407     { 0 },
408     /* IMAGE_COR20_HEADER */
409     {
410         0x48, /* Cb */
411         2, /* MajorRuntimeVersion */
412         5, /* MinorRuntimeVersion */
413         { 0x2188, 0x1B4 }, /* MetaData */
414         COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_STRONGNAMESIGNED, /* Flags */
415         { 0 }, /* EntryPointToken */
416         { 0x20D0, 0xB8 }, /* Resources */
417         { 0x2050, 0x80 }, /* StrongNameSignature */
418         { 0 }, /* CodeManagerTable */
419         { 0 }, /* VTableFixups */
420         { 0 }, /* ExportAddressTableJumps */
421         { 0 } /* ManagedNativeHeader */
422     },
423     { 0xE496, 0x9A6E, 0xD95E, 0xA2A1, 0x5D72, 0x9CEF, 0x41E3, 0xD483,
424       0xCB5C, 0x329A, 0x887C, 0xE18E, 0xE664, 0x2E1C, 0x0E61, 0xB361,
425       0x8B88, 0xC8D0, 0x47A5, 0x9260, 0x6CC5, 0xE60F, 0x1F61, 0x1E3E,
426       0xAFEE, 0x925A, 0xA084, 0x6B44, 0x2DC6, 0x8126, 0xEBC9, 0xD812,
427       0xF3E9, 0xA3F3, 0xD0D5, 0x2C7F, 0x4592, 0xA0AF, 0x8B15, 0xD91E,
428       0x693E, 0x7A4F, 0x5567, 0xC466, 0xC410, 0x3D29, 0xB25F, 0xCD6C,
429       0x53EF, 0x0D29, 0x085A, 0xEC39, 0xE3BD, 0x58E0, 0x78F5, 0x0587,
430       0xF8D8, 0x14E4, 0x77CE, 0xCCC9, 0x4DCF, 0x8A18, 0x90E8, 0x1A52
431     },
432     /* RESOURCE */
433     {
434         0xB4, /* Size */
435         0xBEEFCACE, /* Signature */
436         1, /* HeaderVersion */
437         0x91, /* SkipBytes */
438         { 'l','S','y','s','t','e','m','.','R','e','s','o','u','r','c','e','s','.',
439           'R','e','s','o','u','r','c','e','R','e','a','d','e','r',',',' ',
440           'm','s','c','o','r','l','i','b',',',' ','V','e','r','s','i','o','n','=',
441           '2','.','0','.','0','.','0',',',' ','C','u','l','t','u','r','e','=',
442           'n','e','u','t','r','a','l',',',' ','P','u','b','l','i','c','K','e','y','T','o','k','e','n','=',
443           'b','7','7','a','5','c','5','6','1','9','3','4','e','0','8','9',
444           '#','S','y','s','t','e','m','.','R','e','s','o','u','r','c','e','s','.',
445           'R','u','n','t','i','m','e','R','e','s','o','u','r','c','e','S','e','t',
446           2,0,0,0,0,0,0,0,0,0,0,0,'P','A','D','P','A','D','P',180,0,0,0
447         }
448     },
449     /* METADATAHDR */
450     {
451         0x424A5342, /* Signature */
452         1, /* MajorVersion */
453         1, /* MinorVersion */
454         0, /* Reserved */
455         0xC, /* VersionLength */
456         "v2.0.50727", /* Version */
457         0, /* Flags */
458         5 /* Streams */
459     },
460     /* METADATASTREAMHDR */
461     {
462         0x6C, /* Offset */
463         0x64, /* Size */
464     },
465     "#~\0\0",
466     /* METADATASTREAMHDR */
467     {
468         0xD0, /* Offset */
469         0x28, /* Size */
470     },
471     "#Strings\0\0\0\0",
472     /* METADATASTREAMHDR */
473     {
474         0xF8, /* Offset */
475         0x8, /* Size */
476     },
477     "#US\0",
478     /* METADATASTREAMHDR */
479     {
480         0x100, /* Offset */
481         0x10, /* Size */
482     },
483     "#GUID\0\0\0",
484     /* METADATASTREAMHDR */
485     {
486         0x110, /* Offset */
487         0xA4, /* Size */
488     },
489     "#Blob\0\0\0",
490     /* METADATATABLESHDR */
491     {
492         0, /* Reserved1 */
493         2, /* MajorVersion */
494         0, /* MinorVersion */
495         0, /* HeapOffsetSizes */
496         1, /* Reserved2 */
497         { { 0 } }, /* MaskValid */
498         { { 0 } } /* MaskSorted */
499     },
500     /* numrows */
501     { 1, 1, 1, 1 },
502     /* MODULETABLE */
503     {
504         0, /* Generation */
505         0xA, /* Name */
506         1, /* Mvid */
507         0, /* EncId */
508         0 /* EncBaseId */
509     },
510     /* TYPEDEFTABLE */
511     {
512         0, /* Flags */
513         0x1, /* Name */
514         0, /* Namespace */
515         0, /* Extends */
516         1, /* FieldList */
517         1 /* MethodList */
518     },
519     /* ASSEMBLYTABLE */
520     {
521         0x8004, /* HashAlgId */
522         1, /* MajorVersion */
523         0, /* MinorVersion */
524         0, /* BuildNumber */
525         0, /* RevisionNumber */
526         1, /* Flags */
527         1, /* PublicKey */
528         0x13, /* Name */
529         0 /* Culture */
530     },
531     /* MANIFESTRESTABLE */
532     {
533         0, /* Offset */
534         0x2, /* Flags */
535         0x18, /* Name */
536         0 /* Implementation */
537     },
538     /* pad */
539     0,
540     /* String heap */
541     "\0<Module>\0wine.dll\0wine\0wine.resources\0\0",
542     /* US heap */
543     { 0x0300, 0x0020 },
544     /* GUID heap */
545     { 0x86EF, 0x5B5A, 0x2C5E, 0x4F6D, 0xC2AB, 0x0A94, 0xD658, 0x31DA },
546     /* BLOB heap */
547     { 0x8000, 0x00A0, 0x0024, 0x0400, 0x0080, 0x9400, 0x0000, 0x0600,
548       0x0002, 0x0000, 0x0024, 0x5200, 0x4153, 0x0031, 0x0004, 0x0100,
549       0x0100, 0x2F00, 0x60E0, 0x4D76, 0x5E5C, 0x430A, 0x6FF3, 0x77D6,
550       0x04CA, 0xF6AD, 0xF54D, 0x0AD2, 0x9FB6, 0x39C2, 0x2E66, 0xD30F,
551       0x916F, 0x1826, 0xFB52, 0x78A0, 0x8262, 0x6902, 0xBD47, 0xAF30,
552       0xBAB1, 0x29DA, 0xAA6D, 0xF189, 0x296A, 0x0F13, 0x4982, 0x531D,
553       0x8283, 0x1343, 0x5A33, 0x5D36, 0xEB3F, 0x0863, 0xA771, 0x0679,
554       0x4DFF, 0xD30A, 0xBEAD, 0x2A9F, 0x12A8, 0x4319, 0x5706, 0x333D,
555       0x0CAC, 0xE80A, 0xFD99, 0xC82D, 0x3D3B, 0xBFFE, 0xF256, 0x25E3,
556       0x1A12, 0xC116, 0x8936, 0xF237, 0x5F26, 0xC68A, 0x1E42, 0xCE41,
557       0xC17C, 0x00C4
558     },
559     /* IMAGE_IMPORT_DESCRIPTOR */
560     {
561         { 0x2364 }, /* OriginalFirstThunk */
562         0, /* TimeDateStamp */
563         0, /* ForwarderChain */
564         0x237E, /* Name */
565         0x2000, /* FirstThunk */
566     },
567     /* pad */
568     { 0 },
569     /* IMPORTLOOKUPTABLE */
570     {
571         0x2370, /* HintNameTableRVA */
572         { 0 }, /* pad */
573     },
574     /* HINTNAMETABLE */
575     {
576         0, /* Hint */
577         "_CorDllMain", /* Name */
578         "mscoree.dll", /* Module */
579         0, /* Reserved */
580         0x25FF, /* EntryPoint */
581         0x402000 /* RVA */
582     },
583     /* pad to 0x600 */
584     { 0 },
585     /* IMAGE_RESOURCE_DIRECTORY */
586     {
587         0, /* Characteristics */
588         0, /* TimeDateStamp */
589         0, /* MajorVersion */
590         0, /* MinorVersion */
591         0, /* NumberOfNamedEntries */
592         1, /* NumberOfIdEntries */
593     },
594     /* IMAGE_RESOURCE_DIRECTORY_ENTRY */
595     { { { 0 } }, { 0 } }, /* nameless unions initialized later */
596     /* IMAGE_RESOURCE_DIRECTORY */
597     {
598         0, /* Characteristics */
599         0, /* TimeDateStamp */
600         0, /* MajorVersion */
601         0, /* MinorVersion */
602         0, /* NumberOfNamedEntries */
603         1, /* NumberOfIdEntries */
604     },
605     /* IMAGE_RESOURCE_DIRECTORY_ENTRY */
606     { { { 0 } }, { 0 } }, /* nameless unions initialized later */
607     /* IMAGE_RESOURCE_DIRECTORY */
608     {
609         0, /* Characteristics */
610         0, /* TimeDateStamp */
611         0, /* MajorVersion */
612         0, /* MinorVersion */
613         0, /* NumberOfNamedEntries */
614         1, /* NumberOfIdEntries */
615     },
616     /* IMAGE_RESOURCE_DIRECTORY_ENTRY */
617     { { { 0 } }, { 0 } }, /* nameless unions initialized later */
618     /* IMAGE_RESOURCE_DATA_ENTRY */
619     {
620         0x4058, /* OffsetToData */
621         0x23C, /* Size */
622         0, /* CodePage */
623         0, /* Reserved */
624     },
625     /* VS_VERSIONINFO */
626     {
627         0x23C, /* wLength */
628         0x34, /* wValueLength */
629         0, /* wType */
630         { 'V','S','_','V','E','R','S','I','O','N','_','I','N','F','O',0,0 }, /* szKey */
631         /* VS_FIXEDFILEINFO */
632         {
633             VS_FFI_SIGNATURE, /* dwSignature */
634             VS_FFI_STRUCVERSION, /* dwStrucVersion */
635             0x10000, /* dwFileVersionMS */
636             0x00000, /* dwFileVersionLS */
637             0x10000, /* dwProductVersionMS */
638             0x00000, /* dwProductVersionLS */
639             VS_FFI_FILEFLAGSMASK, /* dwFileFlagsMask */
640             0x0, /* dwFileFlags */
641             VOS__WINDOWS32, /* dwFileOS */
642             VFT_DLL, /* dwFileType */
643             VFT2_UNKNOWN, /* dwFileSubtype */
644             0, /* dwFileDateMS */
645             0, /* dwFileDateLS */
646         },
647     },
648     /* VARFILEINFO */
649     {
650         0x44, /* wLength */
651         0, /* wValueLength */
652         1, /* wType */
653         { 'V','a','r','F','i','l','e','I','n','f','o',0,0 } /* szKey */
654     },
655     /* VAR */
656     {
657         0x24, /* wLength */
658         0x4, /* wValueLength */
659         0, /* wType */
660         { 'T','r','a','n','s','l','a','t','i','o','n',0,0 }, /* szKey */
661         0x4B00000, /* Value */
662     },
663     /* STRINGFILEINFO */
664     {
665         0x19C, /* wLength */
666         0, /* wValueLength */
667         1, /* wType */
668         { 'S','t','r','i','n','g','F','i','l','e','I','n','f','o',0 }, /* szKey */
669     },
670     /* STRINGTABLE */
671     {
672         0x178, /* wLength */
673         0, /* wValueLength */
674         1, /* wType */
675         { '0','0','0','0','0','4','b','0',0 }, /* szKey */
676     },
677     /* STRINGHDR */
678     {
679         0x2C, /* wLength */
680         2, /* wValueLength */
681         1, /* wType */
682     },
683     { 'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0,0 }, /* szKey */
684     { ' ',0 }, /* szValue */
685     /* STRINGHDR */
686     {
687         0x30, /* wLength */
688         8, /* wValueLength */
689         1, /* wType */
690     },
691     { 'F','i','l','e','V','e','r','s','i','o','n',0,0 }, /* szKey */
692     { '1','.','0','.','0','.','0',0 }, /* szValue */
693     /* STRINGHDR */
694     {
695         0x34, /* wLength */
696         9, /* wValueLength */
697         1, /* wType */
698     },
699     { 'I','n','t','e','r','n','a','l','N','a','m','e',0 }, /* szKey */
700     { 'w','i','n','e','.','d','l','l',0 }, /* szValue */
701     /* STRINGHDR */
702     {
703         0x28, /* wLength */
704         2, /* wValueLength */
705         1, /* wType */
706     },
707     { 'L','e','g','a','l','C','o','p','y','r','i','g','h','t',0 }, /* szKey */
708     { ' ',0 }, /* szValue */
709     /* STRINGHDR */
710     {
711         0x3C, /* wLength */
712         9, /* wValueLength */
713         1, /* wType */
714     },
715     { 'O','r','i','g','i','n','a','l','F','i','l','e','n','a','m','e',0 }, /* szKey */
716     { 'w','i','n','e','.','d','l','l',0,0 }, /* szValue */
717     /* STRINGHDR */
718     {
719         0x34, /* wLength */
720         8, /* wValueLength */
721         1, /* wType */
722     },
723     { 'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 }, /* szKey */
724     { '1','.','0','.','0','.','0',0 }, /* szValue */
725     /* STRINGHDR */
726     {
727         0x38, /* wLength */
728         8, /* wValueLength */
729         1, /* wType */
730     },
731     { 'A','s','s','e','m','b','l','y',' ','V','e','r','s','i','o','n',0 }, /* szKey */
732     { '1','.','0','.','0','.','0',0 }, /* szValue */
733     { 0 }, /* pad */
734     /* RELOCATION */
735     {
736         0x2000, /* PageRVA */
737         0xC, /* Size */
738         0x3390, /* Relocation */
739     },
740     { 0 }
741 };
742 
743 
744 static HRESULT (WINAPI *pCreateAssemblyCache)(IAssemblyCache **ppAsmCache,
745                                               DWORD dwReserved);
746 static HRESULT (WINAPI *pGetCachePath)(ASM_CACHE_FLAGS dwCacheFlags,
747                                        LPWSTR pwzCachePath, PDWORD pcchPath);
748 static HRESULT (WINAPI *pLoadLibraryShim)(LPCWSTR szDllName, LPCWSTR szVersion,
749                                           LPVOID pvReserved, HMODULE *phModDll);
750 
init_functionpointers(void)751 static BOOL init_functionpointers(void)
752 {
753     HRESULT hr;
754     HMODULE hfusion;
755     HMODULE hmscoree;
756 
757     static const WCHAR szFusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
758 
759     hmscoree = LoadLibraryA("mscoree.dll");
760     if (!hmscoree)
761     {
762         win_skip("mscoree.dll not available\n");
763         return FALSE;
764     }
765 
766     pLoadLibraryShim = (void *)GetProcAddress(hmscoree, "LoadLibraryShim");
767     if (!pLoadLibraryShim)
768     {
769         win_skip("LoadLibraryShim not available\n");
770         FreeLibrary(hmscoree);
771         return FALSE;
772     }
773 
774     hr = pLoadLibraryShim(szFusion, NULL, NULL, &hfusion);
775     if (FAILED(hr))
776     {
777         win_skip("fusion.dll not available\n");
778         FreeLibrary(hmscoree);
779         return FALSE;
780     }
781 
782     pCreateAssemblyCache = (void *)GetProcAddress(hfusion, "CreateAssemblyCache");
783     pGetCachePath = (void *)GetProcAddress(hfusion, "GetCachePath");
784 
785     if (!pCreateAssemblyCache || !pGetCachePath)
786     {
787         win_skip("fusion.dll not implemented\n");
788         return FALSE;
789     }
790 
791     FreeLibrary(hmscoree);
792     return TRUE;
793 }
794 
create_file_data(LPCSTR name,LPCSTR data,DWORD size)795 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
796 {
797     HANDLE file;
798     DWORD written;
799 
800     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
801     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
802     WriteFile(file, data, strlen(data), &written, NULL);
803 
804     if (size)
805     {
806         SetFilePointer(file, size, NULL, FILE_BEGIN);
807         SetEndOfFile(file);
808     }
809 
810     CloseHandle(file);
811 }
812 
813 #define create_file(name, size) create_file_data(name, name, size)
814 
create_assembly(LPCSTR file)815 static void create_assembly(LPCSTR file)
816 {
817     HANDLE hfile;
818     DWORD written;
819 
820     /* nameless unions initialized here */
821     assembly.tableshdr.MaskValid.u.HighPart = 0x101;
822     assembly.tableshdr.MaskValid.u.LowPart = 0x00000005;
823     assembly.tableshdr.MaskSorted.u.HighPart = 0x1600;
824     assembly.tableshdr.MaskSorted.u.LowPart = 0x3301FA00;
825     U(assembly.labelres).Name = 0x10;
826     U2(assembly.labelres).OffsetToData = 0x80000018;
827     U(assembly.label11res).Name = 0x1;
828     U2(assembly.label11res).OffsetToData = 0x80000030;
829     U(assembly.label10res).Name = 0x0;
830     U2(assembly.label10res).OffsetToData = 0x48;
831 
832     hfile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
833 
834     WriteFile(hfile, &assembly, sizeof(ASSEMBLY), &written, NULL);
835     CloseHandle(hfile);
836 }
837 
check_dotnet20(void)838 static BOOL check_dotnet20(void)
839 {
840     IAssemblyCache *cache;
841     HRESULT hr;
842     BOOL ret = FALSE;
843     ULONG disp;
844 
845     static const WCHAR winedll[] = {'w','i','n','e','.','d','l','l',0};
846 
847     create_assembly("wine.dll");
848 
849     hr = pCreateAssemblyCache(&cache, 0);
850     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
851 
852     hr = IAssemblyCache_InstallAssembly(cache, 0, winedll, NULL);
853     if (hr == S_OK)
854         ret = TRUE;
855     else if (hr == CLDB_E_FILE_OLDVER)
856         win_skip("Tests can't be run on older .NET version (.NET 1.1)\n");
857     else if (hr == E_ACCESSDENIED)
858         skip("Not enough rights to install an assembly\n");
859     else
860         ok(0, "Expected S_OK, got %08x\n", hr);
861 
862     DeleteFileA("wine.dll");
863     IAssemblyCache_UninstallAssembly(cache, 0, winedll, NULL, &disp);
864     IAssemblyCache_Release(cache);
865     return ret;
866 }
867 
test_CreateAssemblyCache(void)868 static void test_CreateAssemblyCache(void)
869 {
870     IAssemblyCache *cache;
871     HRESULT hr;
872 
873     /* NULL ppAsmCache */
874     hr = pCreateAssemblyCache(NULL, 0);
875     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
876 
877     /* dwReserved is non-zero */
878     hr = pCreateAssemblyCache(&cache, 42);
879     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
880 
881     IAssemblyCache_Release(cache);
882 }
883 
test_CreateAssemblyCacheItem(void)884 static void test_CreateAssemblyCacheItem(void)
885 {
886     IAssemblyCache *cache;
887     IAssemblyCacheItem *item;
888     HRESULT hr;
889 
890     static const WCHAR wine[] = {'w','i','n','e',0};
891 
892     hr = pCreateAssemblyCache(&cache, 0);
893     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
894 
895     hr = IAssemblyCache_CreateAssemblyCacheItem(cache, 0, NULL, NULL, NULL);
896     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
897 
898     hr = IAssemblyCache_CreateAssemblyCacheItem(cache, 0, NULL, &item, NULL);
899     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
900     IAssemblyCacheItem_Release(item);
901 
902     hr = IAssemblyCache_CreateAssemblyCacheItem(cache, 0, NULL, &item, wine);
903     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
904     IAssemblyCacheItem_Release(item);
905 
906     hr = IAssemblyCache_CreateAssemblyCacheItem(cache, 1, (void *)0xdeadbeef, &item, NULL);
907     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
908     IAssemblyCacheItem_Release(item);
909 
910     hr = IAssemblyCache_CreateAssemblyCacheItem(cache, 1, NULL, &item, NULL);
911     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
912     IAssemblyCacheItem_Release(item);
913 
914     hr = IAssemblyCache_CreateAssemblyCacheItem(cache, 0, (void *)0xdeadbeef, &item, NULL);
915     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
916     IAssemblyCacheItem_Release(item);
917 
918     IAssemblyCache_Release(cache);
919 }
920 
test_InstallAssembly(void)921 static void test_InstallAssembly(void)
922 {
923     IAssemblyCache *cache;
924     HRESULT hr;
925     ULONG disp;
926     DWORD attr;
927     char dllpath[MAX_PATH];
928 
929     static const WCHAR empty[] = {0};
930     static const WCHAR noext[] = {'f','i','l','e',0};
931     static const WCHAR badext[] = {'f','i','l','e','.','b','a','d',0};
932     static const WCHAR dllext[] = {'f','i','l','e','.','d','l','l',0};
933     static const WCHAR exeext[] = {'f','i','l','e','.','e','x','e',0};
934     static const WCHAR testdll[] = {'t','e','s','t','.','d','l','l',0};
935     static const WCHAR winedll[] = {'w','i','n','e','.','d','l','l',0};
936     static const WCHAR wine[] = {'w','i','n','e',0};
937 
938     create_file("test.dll", 100);
939     create_assembly("wine.dll");
940 
941     hr = pCreateAssemblyCache(&cache, 0);
942     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
943 
944     /* NULL pszManifestFilePath */
945     hr = IAssemblyCache_InstallAssembly(cache, 0, NULL, NULL);
946     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
947 
948     /* empty pszManifestFilePath */
949     hr = IAssemblyCache_InstallAssembly(cache, 0, empty, NULL);
950     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
951 
952     /* pszManifestFilePath has no extension */
953     hr = IAssemblyCache_InstallAssembly(cache, 0, noext, NULL);
954     ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
955        "Expected HRESULT_FROM_WIN32(ERROR_INVALID_NAME), got %08x\n", hr);
956 
957     /* pszManifestFilePath has bad extension */
958     hr = IAssemblyCache_InstallAssembly(cache, 0, badext, NULL);
959     ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
960        "Expected HRESULT_FROM_WIN32(ERROR_INVALID_NAME), got %08x\n", hr);
961 
962     /* pszManifestFilePath has dll extension */
963     hr = IAssemblyCache_InstallAssembly(cache, 0, dllext, NULL);
964     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
965        "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
966 
967     /* pszManifestFilePath has exe extension */
968     hr = IAssemblyCache_InstallAssembly(cache, 0, exeext, NULL);
969     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
970        "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
971 
972     /* empty file */
973     hr = IAssemblyCache_InstallAssembly(cache, 0, testdll, NULL);
974     ok(hr == COR_E_ASSEMBLYEXPECTED,
975        "Expected COR_E_ASSEMBLYEXPECTED, got %08x\n", hr);
976 
977     /* wine assembly */
978     hr = IAssemblyCache_InstallAssembly(cache, 0, winedll, NULL);
979     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
980 
981     GetWindowsDirectoryA(dllpath, MAX_PATH);
982     strcat(dllpath, "\\assembly\\GAC_MSIL\\wine\\\\1.0.0.0__2d03617b1c31e2f5\\wine.dll");
983 
984     attr = GetFileAttributesA(dllpath);
985     ok(attr != INVALID_FILE_ATTRIBUTES, "Expected assembly to exist\n");
986 
987     /* uninstall the assembly from the GAC */
988     disp = 0xf00dbad;
989     hr = IAssemblyCache_UninstallAssembly(cache, 0, wine, NULL, &disp);
990     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
991     ok(disp == IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED,
992        "Expected IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED, got %d\n", disp);
993 
994     attr = GetFileAttributesA(dllpath);
995     ok(attr == INVALID_FILE_ATTRIBUTES, "Expected assembly not to exist\n");
996 
997     disp = 0xf00dbad;
998     hr = IAssemblyCache_UninstallAssembly(cache, 0, wine, NULL, &disp);
999     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
1000     ok(disp == IASSEMBLYCACHE_UNINSTALL_DISPOSITION_ALREADY_UNINSTALLED,
1001        "Expected IASSEMBLYCACHE_UNINSTALL_DISPOSITION_ALREADY_UNINSTALLED, got %d\n", disp);
1002 
1003     DeleteFileA("test.dll");
1004     DeleteFileA("wine.dll");
1005     IAssemblyCache_Release(cache);
1006 }
1007 
1008 #define INIT_ASM_INFO() \
1009     ZeroMemory(&info, sizeof(ASSEMBLY_INFO)); \
1010     info.cbAssemblyInfo = sizeof(ASSEMBLY_INFO); \
1011     info.pszCurrentAssemblyPathBuf = path; \
1012     info.cchBuf = MAX_PATH; \
1013     path[0] = '\0';
1014 
test_QueryAssemblyInfo(void)1015 static void test_QueryAssemblyInfo(void)
1016 {
1017     IAssemblyCache *cache;
1018     ASSEMBLY_INFO info;
1019     WCHAR path[MAX_PATH];
1020     WCHAR asmpath[MAX_PATH];
1021     WCHAR name[MAX_PATH];
1022     HRESULT hr;
1023     DWORD size;
1024     ULONG disp;
1025 
1026     static const WCHAR empty[] = {0};
1027     static const WCHAR commasep[] = {',',' ',0};
1028     static const WCHAR winedll[] = {'w','i','n','e','.','d','l','l',0};
1029     static const WCHAR wine[] = {'w','i','n','e',0};
1030     static const WCHAR ver[] = {
1031         'V','e','r','s','i','o','n','=','1','.','0','.','0','.','0',0};
1032     static const WCHAR otherver[] = {
1033         'V','e','r','s','i','o','n','=','1','.','0','.','0','.','0','0','0','0','0',0};
1034     static const WCHAR badver[] = {
1035         'V','e','r','s','i','o','n','=','1','.','0','.','0','.','1',0};
1036     static const WCHAR culture[] = {
1037         'C','u','l','t','u','r','e','=','n','e','u','t','r','a','l',0};
1038     static const WCHAR badculture[] = {
1039         'C','u','l','t','u','r','e','=','e','n',0};
1040     static const WCHAR pubkey[] = {
1041         'P','u','b','l','i','c','K','e','y','T','o','k','e','n','=',
1042         '2','d','0','3','6','1','7','b','1','c','3','1','e','2','f','5',0};
1043     static const WCHAR badpubkey[] = {
1044         'P','u','b','l','i','c','K','e','y','T','o','k','e','n','=',
1045         'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0};
1046     static const WCHAR badprop[] = {'B','a','d','P','r','o','p','=','b','u','h',0};
1047     static const WCHAR msil[] = {
1048         '_','M','S','I','L','\\','w','i','n','e','\\',
1049         '1','.','0','.','0','.','0','_','_','2','d','0','3','6','1','7','b',
1050         '1','c','3','1','e','2','f','5','\\',0};
1051     static const WCHAR wine2[] = {
1052         'w','i','n','e',',','v','e','r','s','i','o','n','=','1','.','0','.','0','.','1',',',
1053         'p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',
1054         '2','d','0','3','6','1','7','b','1','c','3','1','e','2','f','5',',',
1055         'c','u','l','t','u','r','e','=','n','e','u','t','r','a','l',0};
1056     static const WCHAR nullpublickey[] = {
1057         'm','s','c','o','r','l','i','b','.','d','l','l',',','v','e','r','s','i','o','n','=','0','.','0','.',
1058         '0','.','0',',','c','u','l','t','u','r','e','=','n','e','u','t','r','a','l',',',
1059         'p','u','b','l','i','c','K','e','y','T','o','k','e','n','=','n','u','l','l',0};
1060     static const WCHAR nullpublickey1[] = {
1061         'm','s','c','o','r','l','i','b','.','d','l','l',',',
1062         'p','u','b','l','i','c','K','e','y','T','o','k','e','n','=','n','u','L','l',0};
1063 
1064     size = MAX_PATH;
1065     hr = pGetCachePath(ASM_CACHE_GAC, asmpath, &size);
1066     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1067 
1068     lstrcatW(asmpath, msil);
1069     lstrcatW(asmpath, winedll);
1070 
1071     create_assembly("wine.dll");
1072 
1073     hr = pCreateAssemblyCache(&cache, 0);
1074     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1075 
1076     /* assembly not installed yet */
1077     INIT_ASM_INFO();
1078     hr = IAssemblyCache_QueryAssemblyInfo(cache, 0, wine, &info);
1079     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
1080        "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
1081     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1082        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1083     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1084     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1085        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1086     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1087        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1088     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1089        "Assembly path was changed\n");
1090     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1091 
1092     hr = IAssemblyCache_InstallAssembly(cache, 0, winedll, NULL);
1093     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1094 
1095     /* NULL pszAssemblyName */
1096     INIT_ASM_INFO();
1097     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE,
1098                                           NULL, &info);
1099     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
1100     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1101        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1102     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1103     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1104        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1105     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1106        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1107     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1108        "Assembly path was changed\n");
1109     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1110 
1111     /* empty pszAssemblyName */
1112     INIT_ASM_INFO();
1113     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE,
1114                                           empty, &info);
1115     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
1116     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1117        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1118     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1119     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1120        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1121     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1122        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1123     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1124        "Assembly path was changed\n");
1125     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1126 
1127     /* no dwFlags */
1128     INIT_ASM_INFO();
1129     hr = IAssemblyCache_QueryAssemblyInfo(cache, 0, wine, &info);
1130     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1131     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1132        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1133     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1134        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1135     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1136        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1137     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1138        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1139     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1140        "Wrong assembly path returned\n");
1141     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1142        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1143 
1144     /* pwzCachePath is full filename */
1145     INIT_ASM_INFO();
1146     hr = IAssemblyCache_QueryAssemblyInfo(cache, 0, winedll, &info);
1147     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
1148        "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
1149     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1150        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1151     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1152     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1153        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1154     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1155        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1156     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1157        "Assembly path was changed\n");
1158     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1159 
1160     /* NULL pAsmInfo, QUERYASMINFO_FLAG_VALIDATE */
1161     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE,
1162                                           wine, NULL);
1163     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1164 
1165     /* NULL pAsmInfo, QUERYASMINFO_FLAG_GETSIZE */
1166     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1167                                           wine, NULL);
1168     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1169 
1170     /* info.cbAssemblyInfo is 0 */
1171     INIT_ASM_INFO();
1172     info.cbAssemblyInfo = 0;
1173     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE,
1174                                           wine, &info);
1175     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1176     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1177        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1178     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1179        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1180     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1181        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1182     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1183        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1184     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1185        "Wrong assembly path returned\n");
1186     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1187        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1188 
1189     /* info.cbAssemblyInfo is 1 */
1190     INIT_ASM_INFO();
1191     info.cbAssemblyInfo = 1;
1192     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE,
1193                                           wine, &info);
1194     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
1195     ok(info.cbAssemblyInfo == 1, "Expected 1, got %d\n", info.cbAssemblyInfo);
1196     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1197     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1198        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1199     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1200        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1201     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1202        "Assembly path was changed\n");
1203     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1204 
1205     /* info.cbAssemblyInfo is > sizeof(ASSEMBLY_INFO) */
1206     INIT_ASM_INFO();
1207     info.cbAssemblyInfo = sizeof(ASSEMBLY_INFO) * 2;
1208     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1209                                           wine, &info);
1210     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
1211     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO) * 2,
1212        "Expected sizeof(ASSEMBLY_INFO) * 2, got %d\n", info.cbAssemblyInfo);
1213     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1214     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1215        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1216     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1217        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1218     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1219        "Assembly path was changed\n");
1220     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1221 
1222     /* QUERYASMINFO_FLAG_GETSIZE */
1223     INIT_ASM_INFO();
1224     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1225                                           wine, &info);
1226     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1227     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1228        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1229     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1230        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1231     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1232        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1233     todo_wine
1234     {
1235         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1236            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1237     }
1238     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1239        "Wrong assembly path returned\n");
1240     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1241        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1242 
1243     /* QUERYASMINFO_FLAG_GETSIZE and QUERYASMINFO_FLAG_VALIDATE */
1244     INIT_ASM_INFO();
1245     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE |
1246                                           QUERYASMINFO_FLAG_VALIDATE,wine, &info);
1247     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1248     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1249        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1250     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1251        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1252     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1253        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1254     todo_wine
1255     {
1256         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1257            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1258     }
1259     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1260        "Wrong assembly path returned\n");
1261     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1262        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1263 
1264     /* info.pszCurrentAssemblyPathBuf is NULL */
1265     INIT_ASM_INFO();
1266     info.pszCurrentAssemblyPathBuf = NULL;
1267     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1268                                           wine, &info);
1269     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1270        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1271     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1272        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1273     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1274        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1275     ok(hr == E_NOT_SUFFICIENT_BUFFER, "Expected E_NOT_SUFFICIENT_BUFFER, got %08x\n", hr);
1276     todo_wine
1277     {
1278         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1279            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1280     }
1281     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1282        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1283 
1284     /* info.cchBuf is exactly size of asmpath */
1285     INIT_ASM_INFO();
1286     info.cchBuf = lstrlenW(asmpath);
1287     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1288                                           wine, &info);
1289     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1290        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1291     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1292        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1293     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1294        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1295     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1296        "Assembly path was changed\n");
1297     ok(hr == E_NOT_SUFFICIENT_BUFFER, "Expected E_NOT_SUFFICIENT_BUFFER, got %08x\n", hr);
1298     todo_wine
1299     {
1300         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1301            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1302     }
1303     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1304        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1305 
1306     /* info.cchBuf has room for NULL-terminator */
1307     INIT_ASM_INFO();
1308     info.cchBuf = lstrlenW(asmpath) + 1;
1309     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1310                                           wine, &info);
1311     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1312     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1313        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1314     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1315        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1316     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1317        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1318     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1319        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1320     todo_wine
1321     {
1322         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1323            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1324     }
1325     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1326        "Wrong assembly path returned\n");
1327 
1328     /* display name is "wine, Version=1.0.0.0" */
1329     INIT_ASM_INFO();
1330     lstrcpyW(name, wine);
1331     lstrcatW(name, commasep);
1332     lstrcatW(name, ver);
1333     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1334                                           name, &info);
1335     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1336     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1337        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1338     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1339        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1340     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1341        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1342     todo_wine
1343     {
1344         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1345            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1346     }
1347     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1348        "Wrong assembly path returned\n");
1349     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1350        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1351 
1352     /* short buffer, QUERYASMINFO_FLAG_VALIDATE */
1353     memset(&info, 0, sizeof(info));
1354     lstrcpyW(name, wine);
1355     lstrcatW(name, commasep);
1356     lstrcatW(name, otherver);
1357     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE,
1358                                           name, &info);
1359     ok(hr == E_NOT_SUFFICIENT_BUFFER, "got %08x\n", hr);
1360     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED, "got %08x\n", info.dwAssemblyFlags);
1361 
1362     /* short buffer, QUERYASMINFO_FLAG_GETSIZE */
1363     memset(&info, 0, sizeof(info));
1364     lstrcpyW(name, wine);
1365     lstrcatW(name, commasep);
1366     lstrcatW(name, otherver);
1367     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1368                                           name, &info);
1369     ok(hr == E_NOT_SUFFICIENT_BUFFER, "got %08x\n", hr);
1370     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED, "got %08x\n", info.dwAssemblyFlags);
1371 
1372     /* display name is "wine, Version=1.0.0.00000" */
1373     INIT_ASM_INFO();
1374     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1375                                           name, &info);
1376     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1377     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1378        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1379     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1380        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1381     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1382        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1383     todo_wine
1384     {
1385         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1386            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1387     }
1388     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1389        "Wrong assembly path returned\n");
1390     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1391        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1392 
1393     /* display name is "wine, Version=1.0.0.1", versions don't match */
1394     INIT_ASM_INFO();
1395     lstrcpyW(name, wine);
1396     lstrcatW(name, commasep);
1397     lstrcatW(name, badver);
1398     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1399                                           name, &info);
1400     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
1401        "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
1402     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1403        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1404     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1405     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1406        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1407     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1408        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1409     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1410        "Assembly path was changed\n");
1411     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1412 
1413     /* display name is "wine,version=1.0.0.1,publicKeyToken=2d03617b1c31e2f5,culture=neutral" */
1414     INIT_ASM_INFO();
1415     lstrcpyW(name, wine2);
1416     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1417                                           name, &info);
1418     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
1419        "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
1420     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1421        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1422     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1423     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1424        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1425     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1426        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1427     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1428        "Assembly path was changed\n");
1429     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1430 
1431     /* display name is "mscorlib.dll,version=0.0.0.0,culture=neutral,publicKeyToken=null" */
1432     INIT_ASM_INFO();
1433     lstrcpyW(name, nullpublickey);
1434     hr = IAssemblyCache_QueryAssemblyInfo(cache, 0, name, &info);
1435     ok(hr == FUSION_E_PRIVATE_ASM_DISALLOWED, "got %08x\n", hr);
1436 
1437     /* display name is "mscorlib.dll,publicKeyToken=nuLl" */
1438     INIT_ASM_INFO();
1439     lstrcpyW(name, nullpublickey1);
1440     hr = IAssemblyCache_QueryAssemblyInfo(cache, 0, name, &info);
1441     ok(hr == FUSION_E_PRIVATE_ASM_DISALLOWED, "got %08x\n", hr);
1442 
1443     /* display name is "wine, Culture=neutral" */
1444     INIT_ASM_INFO();
1445     lstrcpyW(name, wine);
1446     lstrcatW(name, commasep);
1447     lstrcatW(name, culture);
1448     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1449                                           name, &info);
1450     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1451     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1452        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1453     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1454        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1455     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1456        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1457     todo_wine
1458     {
1459         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1460            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1461     }
1462     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1463        "Wrong assembly path returned\n");
1464     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1465        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1466 
1467     /* display name is "wine, Culture=en", cultures don't match */
1468     INIT_ASM_INFO();
1469     lstrcpyW(name, wine);
1470     lstrcatW(name, commasep);
1471     lstrcatW(name, badculture);
1472     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1473                                           name, &info);
1474     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
1475        "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
1476     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1477     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1478        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1479     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1480        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1481     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1482        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1483     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1484        "Assembly path was changed\n");
1485     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1486 
1487     /* display name is "wine, PublicKeyTokens=2d03617b1c31e2f5" */
1488     INIT_ASM_INFO();
1489     lstrcpyW(name, wine);
1490     lstrcatW(name, commasep);
1491     lstrcatW(name, pubkey);
1492     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1493                                           name, &info);
1494     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1495     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1496        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1497     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1498        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1499     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1500        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1501     todo_wine
1502     {
1503         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1504            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1505     }
1506     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1507        "Wrong assembly path returned\n");
1508     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1509        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1510 
1511     /* display name is "wine, PublicKeyToken=aaaaaaaaaaaaaaaa", pubkeys don't match */
1512     INIT_ASM_INFO();
1513     lstrcpyW(name, wine);
1514     lstrcatW(name, commasep);
1515     lstrcatW(name, badpubkey);
1516     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1517                                           name, &info);
1518     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
1519        "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
1520     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1521        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1522     ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags);
1523     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1524        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1525     ok(info.uliAssemblySizeInKB.u.LowPart == 0,
1526        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1527     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, empty),
1528        "Assembly path was changed\n");
1529     ok(info.cchBuf == MAX_PATH, "Expected MAX_PATH, got %d\n", info.cchBuf);
1530 
1531     /* display name is "wine, BadProp=buh", bad property */
1532     INIT_ASM_INFO();
1533     lstrcpyW(name, wine);
1534     lstrcatW(name, commasep);
1535     lstrcatW(name, badprop);
1536     hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE,
1537                                           name, &info);
1538     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1539     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1540        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1541     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1542        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1543     ok(info.uliAssemblySizeInKB.u.HighPart == 0,
1544        "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart);
1545     todo_wine
1546     {
1547         ok((info.uliAssemblySizeInKB.u.LowPart == 4),
1548            "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart);
1549     }
1550     ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath),
1551        "Wrong assembly path returned\n");
1552     ok(info.cchBuf == lstrlenW(asmpath) + 1,
1553        "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf);
1554 
1555     /* no flags, display name is "wine, Version=1.0.0.0" */
1556     INIT_ASM_INFO();
1557     info.pszCurrentAssemblyPathBuf = NULL;
1558     info.cchBuf = 0;
1559     lstrcpyW(name, wine);
1560     lstrcatW(name, commasep);
1561     lstrcatW(name, ver);
1562     hr = IAssemblyCache_QueryAssemblyInfo(cache, 0, name, &info);
1563     ok(hr == E_NOT_SUFFICIENT_BUFFER, "Expected E_NOT_SUFFICIENT_BUFFER, got %08x\n", hr);
1564     ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO),
1565        "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo);
1566     ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED,
1567        "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags);
1568 
1569     /* uninstall the assembly from the GAC */
1570     disp = 0xf00dbad;
1571     hr = IAssemblyCache_UninstallAssembly(cache, 0, wine, NULL, &disp);
1572     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1573     ok(disp == IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED,
1574        "Expected IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED, got %d\n", disp);
1575 
1576     DeleteFileA("test.dll");
1577     DeleteFileA("wine.dll");
1578     IAssemblyCache_Release(cache);
1579 }
1580 
START_TEST(asmcache)1581 START_TEST(asmcache)
1582 {
1583     if (!init_functionpointers())
1584         return;
1585 
1586     if (!check_dotnet20())
1587         return;
1588 
1589     test_CreateAssemblyCache();
1590     test_CreateAssemblyCacheItem();
1591     test_InstallAssembly();
1592     test_QueryAssemblyInfo();
1593 }
1594