fusion/tests: Don't crash on .NET 1.x.
[wine] / dlls / fusion / tests / asmname.c
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
21 #include <stdio.h>
22
23 #include <windows.h>
24 #include <mscoree.h>
25 #include <fusion.h>
26 #include <corerror.h>
27
28 #include "wine/test.h"
29
30 /* ok-like statement which takes two unicode strings or one unicode and one ANSI string as arguments */
31 static CHAR string1[MAX_PATH];
32
33 #define ok_aw(aString, wString) \
34     WideCharToMultiByte(CP_ACP, 0, wString, -1, string1, MAX_PATH, NULL, NULL); \
35     if (lstrcmpA(string1, aString) != 0) \
36         ok(0, "Expected \"%s\", got \"%s\"\n", aString, string1);
37
38 static HRESULT (WINAPI *pCreateAssemblyNameObject)(LPASSEMBLYNAME *ppAssemblyNameObj,
39                                                    LPCWSTR szAssemblyName, DWORD dwFlags,
40                                                    LPVOID pvReserved);
41 static HRESULT (WINAPI *pLoadLibraryShim)(LPCWSTR szDllName, LPCWSTR szVersion,
42                                           LPVOID pvReserved, HMODULE *phModDll);
43
44 static BOOL init_functionpointers(void)
45 {
46     HRESULT hr;
47     HMODULE hfusion;
48     HMODULE hmscoree;
49
50     static const WCHAR szFusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
51
52     hmscoree = LoadLibraryA("mscoree.dll");
53     if (!hmscoree)
54         return FALSE;
55
56     pLoadLibraryShim = (void *)GetProcAddress(hmscoree, "LoadLibraryShim");
57     if (!pLoadLibraryShim)
58     {
59         FreeLibrary(hmscoree);
60         return FALSE;
61     }
62
63     hr = pLoadLibraryShim(szFusion, NULL, NULL, &hfusion);
64     if (FAILED(hr))
65         return FALSE;
66
67     pCreateAssemblyNameObject = (void *)GetProcAddress(hfusion, "CreateAssemblyNameObject");
68     if (!pCreateAssemblyNameObject)
69         return FALSE;
70
71     return TRUE;
72 }
73
74 typedef struct _tagASMPROP_RES
75 {
76     HRESULT hr;
77     CHAR val[MAX_PATH];
78     DWORD size;
79 } ASMPROP_RES;
80
81 static const ASMPROP_RES defaults[ASM_NAME_MAX_PARAMS] =
82 {
83     {S_OK, "", 0},
84     {S_OK, "", 0},
85     {S_OK, "", 0},
86     {S_OK, "", 0},
87     {S_OK, "", 0},
88     {S_OK, "", 0},
89     {S_OK, "", 0},
90     {S_OK, "", 0},
91     {S_OK, "", 0},
92     {S_OK, "", 0},
93     {S_OK, "", 0},
94     {S_OK, "", 0},
95     {S_OK, "", 0},
96     {S_OK, "", 0},
97     {S_OK, "", 0},
98     {S_FALSE, "", MAX_PATH},
99     {S_FALSE, "", MAX_PATH},
100     {S_OK, "", 0},
101     {S_OK, "", MAX_PATH},
102     {S_OK, "", 0},
103     {S_OK, "", 0},
104     {S_OK, "", 0},
105     {S_OK, "", 0},
106     {S_OK, "", 0},
107     {S_OK, "", 0},
108     {S_OK, "", 0},
109     {S_OK, "", 0},
110     {S_OK, "", 0}
111 };
112
113 static const ASMPROP_RES emptyname[ASM_NAME_MAX_PARAMS] =
114 {
115     {S_OK, "", 0},
116     {S_OK, "", 0},
117     {S_OK, "", 0},
118     {S_OK, "", 2},
119     {S_OK, "", 0},
120     {S_OK, "", 0},
121     {S_OK, "", 0},
122     {S_OK, "", 0},
123     {S_OK, "", 0},
124     {S_OK, "", 0},
125     {S_OK, "", 0},
126     {S_OK, "", 0},
127     {S_OK, "", 0},
128     {S_OK, "", 0},
129     {S_OK, "", 0},
130     {S_FALSE, "", MAX_PATH},
131     {S_FALSE, "", MAX_PATH},
132     {S_OK, "", 0},
133     {S_OK, "", MAX_PATH},
134     {S_OK, "", 0},
135     {S_OK, "", 0},
136     {S_OK, "", 0},
137     {S_OK, "", 0},
138     {S_OK, "", 0},
139     {S_OK, "", 0},
140     {S_OK, "", 0},
141     {S_OK, "", 0},
142     {S_OK, "", 0}
143 };
144
145 static const ASMPROP_RES winename[ASM_NAME_MAX_PARAMS] =
146 {
147     {S_OK, "", 0},
148     {S_OK, "", 0},
149     {S_OK, "", 0},
150     {S_OK, "wine", 10},
151     {S_OK, "", 0},
152     {S_OK, "", 0},
153     {S_OK, "", 0},
154     {S_OK, "", 0},
155     {S_OK, "", 0},
156     {S_OK, "", 0},
157     {S_OK, "", 0},
158     {S_OK, "", 0},
159     {S_OK, "", 0},
160     {S_OK, "", 0},
161     {S_OK, "", 0},
162     {S_FALSE, "", MAX_PATH},
163     {S_FALSE, "", MAX_PATH},
164     {S_OK, "", 0},
165     {S_OK, "", MAX_PATH},
166     {S_OK, "", 0},
167     {S_OK, "", 0},
168     {S_OK, "", 0},
169     {S_OK, "", 0},
170     {S_OK, "", 0},
171     {S_OK, "", 0},
172     {S_OK, "", 0},
173     {S_OK, "", 0},
174     {S_OK, "", 0}
175 };
176
177 static const ASMPROP_RES vername[ASM_NAME_MAX_PARAMS] =
178 {
179     {S_OK, "", 0},
180     {S_OK, "", 0},
181     {S_OK, "", 0},
182     {S_OK, "wine", 10},
183     {S_OK, "\x01", 2},
184     {S_OK, "\x02", 2},
185     {S_OK, "\x03", 2},
186     {S_OK, "\x04", 2},
187     {S_OK, "", 0},
188     {S_OK, "", 0},
189     {S_OK, "", 0},
190     {S_OK, "", 0},
191     {S_OK, "", 0},
192     {S_OK, "", 0},
193     {S_OK, "", 0},
194     {S_FALSE, "", MAX_PATH},
195     {S_FALSE, "", MAX_PATH},
196     {S_OK, "", 0},
197     {S_OK, "", MAX_PATH},
198     {S_OK, "", 0},
199     {S_OK, "", 0},
200     {S_OK, "", 0},
201     {S_OK, "", 0},
202     {S_OK, "", 0},
203     {S_OK, "", 0},
204     {S_OK, "", 0},
205     {S_OK, "", 0},
206     {S_OK, "", 0}
207 };
208
209 static const ASMPROP_RES badvername[ASM_NAME_MAX_PARAMS] =
210 {
211     {S_OK, "", 0},
212     {S_OK, "", 0},
213     {S_OK, "", 0},
214     {S_OK, "wine", 10},
215     {S_OK, "\x01", 2},
216     {S_OK, "\x05", 2},
217     {S_OK, "", 0},
218     {S_OK, "", 0},
219     {S_OK, "", 0},
220     {S_OK, "", 0},
221     {S_OK, "", 0},
222     {S_OK, "", 0},
223     {S_OK, "", 0},
224     {S_OK, "", 0},
225     {S_OK, "", 0},
226     {S_FALSE, "", MAX_PATH},
227     {S_FALSE, "", MAX_PATH},
228     {S_OK, "", 0},
229     {S_OK, "", MAX_PATH},
230     {S_OK, "", 0},
231     {S_OK, "", 0},
232     {S_OK, "", 0},
233     {S_OK, "", 0},
234     {S_OK, "", 0},
235     {S_OK, "", 0},
236     {S_OK, "", 0},
237     {S_OK, "", 0},
238     {S_OK, "", 0}
239 };
240
241 static const ASMPROP_RES neutralname[ASM_NAME_MAX_PARAMS] =
242 {
243     {S_OK, "", 0},
244     {S_OK, "", 0},
245     {S_OK, "", 0},
246     {S_OK, "wine", 10},
247     {S_OK, "", 0},
248     {S_OK, "", 0},
249     {S_OK, "", 0},
250     {S_OK, "", 0},
251     {S_OK, "", 2},
252     {S_OK, "", 0},
253     {S_OK, "", 0},
254     {S_OK, "", 0},
255     {S_OK, "", 0},
256     {S_OK, "", 0},
257     {S_OK, "", 0},
258     {S_FALSE, "", MAX_PATH},
259     {S_FALSE, "", MAX_PATH},
260     {S_OK, "", 0},
261     {S_OK, "", MAX_PATH},
262     {S_OK, "", 0},
263     {S_OK, "", 0},
264     {S_OK, "", 0},
265     {S_OK, "", 0},
266     {S_OK, "", 0},
267     {S_OK, "", 0},
268     {S_OK, "", 0},
269     {S_OK, "", 0},
270     {S_OK, "", 0}
271 };
272
273 static const ASMPROP_RES enname[ASM_NAME_MAX_PARAMS] =
274 {
275     {S_OK, "", 0},
276     {S_OK, "", 0},
277     {S_OK, "", 0},
278     {S_OK, "wine", 10},
279     {S_OK, "", 0},
280     {S_OK, "", 0},
281     {S_OK, "", 0},
282     {S_OK, "", 0},
283     {S_OK, "en", 6},
284     {S_OK, "", 0},
285     {S_OK, "", 0},
286     {S_OK, "", 0},
287     {S_OK, "", 0},
288     {S_OK, "", 0},
289     {S_OK, "", 0},
290     {S_FALSE, "", MAX_PATH},
291     {S_FALSE, "", MAX_PATH},
292     {S_OK, "", 0},
293     {S_OK, "", MAX_PATH},
294     {S_OK, "", 0},
295     {S_OK, "", 0},
296     {S_OK, "", 0},
297     {S_OK, "", 0},
298     {S_OK, "", 0},
299     {S_OK, "", 0},
300     {S_OK, "", 0},
301     {S_OK, "", 0},
302     {S_OK, "", 0}
303 };
304
305 static const ASMPROP_RES pubkeyname[ASM_NAME_MAX_PARAMS] =
306 {
307     {S_OK, "", 0},
308     {S_OK, "\x12\x34\x56\x78\x90\xab\xcd\xef", 8},
309     {S_OK, "", 0},
310     {S_OK, "wine", 10},
311     {S_OK, "", 0},
312     {S_OK, "", 0},
313     {S_OK, "", 0},
314     {S_OK, "", 0},
315     {S_OK, "", 0},
316     {S_OK, "", 0},
317     {S_OK, "", 0},
318     {S_OK, "", 0},
319     {S_OK, "", 0},
320     {S_OK, "", 0},
321     {S_OK, "", 0},
322     {S_OK, "", MAX_PATH},
323     {S_OK, "", MAX_PATH},
324     {S_OK, "", 0},
325     {S_OK, "", MAX_PATH},
326     {S_OK, "", 0},
327     {S_OK, "", 0},
328     {S_OK, "", 0},
329     {S_OK, "", 0},
330     {S_OK, "", 0},
331     {S_OK, "", 0},
332     {S_OK, "", 0},
333     {S_OK, "", 0},
334     {S_OK, "", 0}
335 };
336
337 static inline void to_widechar(LPWSTR dest, LPCSTR src)
338 {
339     MultiByteToWideChar(CP_ACP, 0, src, -1, dest, MAX_PATH);
340 }
341
342 static inline void to_multibyte(LPSTR dest, LPWSTR src)
343 {
344     WideCharToMultiByte(CP_ACP, 0, src, -1, dest, MAX_PATH, NULL, NULL);
345 }
346
347 static void test_assembly_name_props_line(IAssemblyName *name,
348                                           const ASMPROP_RES *vals, int line)
349 {
350     HRESULT hr;
351     DWORD i, size;
352     WCHAR expect[MAX_PATH];
353     WCHAR str[MAX_PATH];
354     CHAR val[MAX_PATH];
355
356     for (i = 0; i < ASM_NAME_MAX_PARAMS; i++)
357     {
358         to_widechar(expect, vals[i].val);
359
360         size = MAX_PATH;
361         ZeroMemory(str, MAX_PATH);
362         hr = IAssemblyName_GetProperty(name, i, str, &size);
363         to_multibyte(val, str);
364
365         ok(hr == vals[i].hr ||
366            broken(i >= ASM_NAME_CONFIG_MASK && hr == E_INVALIDARG) || /* .NET 1.1 */
367            broken(i >= ASM_NAME_FILE_MAJOR_VERSION && hr == E_INVALIDARG), /* .NET 1.0 */
368            "%d: prop %d: Expected %08x, got %08x\n", line, i, vals[i].hr, hr);
369         if (hr != E_INVALIDARG)
370         {
371             if (i == ASM_NAME_PUBLIC_KEY_TOKEN)
372                 ok(!memcmp(vals[i].val, str, size), "Expected a correct ASM_NAME_PUBLIC_KEY_TOKEN\n");
373             else
374                 ok(!lstrcmpA(vals[i].val, val), "%d: prop %d: Expected \"%s\", got \"%s\"\n", line, i, vals[i].val, val);
375             ok(size == vals[i].size, "%d: prop %d: Expected %d, got %d\n", line, i, vals[i].size, size);
376         }
377     }
378 }
379
380 #define test_assembly_name_props(name, vals) \
381     test_assembly_name_props_line(name, vals, __LINE__);
382
383 static void test_CreateAssemblyNameObject(void)
384 {
385     IAssemblyName *name;
386     WCHAR str[MAX_PATH];
387     WCHAR namestr[MAX_PATH];
388     DWORD size, hi, lo;
389     HRESULT hr;
390
391     static const WCHAR empty[] = {0};
392
393     /* NULL ppAssemblyNameObj */
394     to_widechar(namestr, "wine.dll");
395     hr = pCreateAssemblyNameObject(NULL, namestr, 0, NULL);
396     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
397
398     /* NULL szAssemblyName, CANOF_PARSE_DISPLAY_NAME */
399     name = (IAssemblyName *)0xdeadbeef;
400     hr = pCreateAssemblyNameObject(&name, NULL, CANOF_PARSE_DISPLAY_NAME, NULL);
401     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
402     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
403
404     /* empty szAssemblyName, CANOF_PARSE_DISPLAY_NAME */
405     name = (IAssemblyName *)0xdeadbeef;
406     hr = pCreateAssemblyNameObject(&name, empty, CANOF_PARSE_DISPLAY_NAME, NULL);
407     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
408     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
409
410     /* check the contents of the AssemblyName for default values */
411
412     /* NULL szAssemblyName */
413     name = NULL;
414     hr = pCreateAssemblyNameObject(&name, NULL, CANOF_SET_DEFAULT_VALUES, NULL);
415     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
416     ok(name != NULL, "Expected non-NULL name\n");
417
418     size = MAX_PATH;
419     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
420     ok(hr == FUSION_E_INVALID_NAME,
421        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
422
423     size = MAX_PATH;
424     str[0] = '\0';
425     hr = IAssemblyName_GetName(name, &size, str);
426     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
427     ok(lstrlenW(str) == 0, "Expected empty name\n");
428     ok(size == 0, "Expected 0, got %d\n", size);
429
430     hi = 0xbeefcace;
431     lo = 0xcafebabe;
432     hr = IAssemblyName_GetVersion(name, &hi, &lo);
433     ok(hr == FUSION_E_INVALID_NAME,
434        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
435     ok(hi == 0, "Expected 0, got %08x\n", hi);
436     ok(lo == 0, "Expected 0, got %08x\n", lo);
437
438     test_assembly_name_props(name, defaults);
439
440     IAssemblyName_Release(name);
441
442     /* empty szAssemblyName */
443     name = NULL;
444     hr = pCreateAssemblyNameObject(&name, empty, CANOF_SET_DEFAULT_VALUES, NULL);
445     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
446     ok(name != NULL, "Expected non-NULL name\n");
447
448     size = MAX_PATH;
449     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
450     ok(hr == FUSION_E_INVALID_NAME,
451        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
452
453     size = MAX_PATH;
454     str[0] = '\0';
455     hr = IAssemblyName_GetName(name, &size, str);
456     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
457     ok(lstrlenW(str) == 0, "Expected empty name\n");
458     ok(size == 1, "Expected 1, got %d\n", size);
459
460     hi = 0xbeefcace;
461     lo = 0xcafebabe;
462     hr = IAssemblyName_GetVersion(name, &hi, &lo);
463     ok(hr == FUSION_E_INVALID_NAME,
464        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
465     ok(hi == 0, "Expected 0, got %08x\n", hi);
466     ok(lo == 0, "Expected 0, got %08x\n", lo);
467
468     test_assembly_name_props(name, emptyname);
469
470     IAssemblyName_Release(name);
471
472     /* 'wine' */
473     to_widechar(namestr, "wine");
474     name = NULL;
475     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_SET_DEFAULT_VALUES, NULL);
476     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
477     ok(name != NULL, "Expected non-NULL name\n");
478
479     size = MAX_PATH;
480     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
481     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
482     ok_aw("wine", str);
483     ok(size == 5, "Expected 5, got %d\n", size);
484
485     size = MAX_PATH;
486     str[0] = '\0';
487     hr = IAssemblyName_GetName(name, &size, str);
488     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
489     ok_aw("wine", str);
490     ok(size == 5, "Expected 5, got %d\n", size);
491
492     hi = 0xbeefcace;
493     lo = 0xcafebabe;
494     hr = IAssemblyName_GetVersion(name, &hi, &lo);
495     ok(hr == FUSION_E_INVALID_NAME,
496        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
497     ok(hi == 0, "Expected 0, got %08x\n", hi);
498     ok(lo == 0, "Expected 0, got %08x\n", lo);
499
500     test_assembly_name_props(name, winename);
501
502     IAssemblyName_Release(name);
503
504     /* check the contents of the AssemblyName with parsing */
505
506     /* 'wine' */
507     to_widechar(namestr, "wine");
508     name = NULL;
509     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
510     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
511     ok(name != NULL, "Expected non-NULL name\n");
512
513     size = MAX_PATH;
514     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
515     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
516     ok_aw("wine", str);
517     ok(size == 5, "Expected 5, got %d\n", size);
518
519     size = MAX_PATH;
520     str[0] = '\0';
521     hr = IAssemblyName_GetName(name, &size, str);
522     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
523     ok_aw("wine", str);
524     ok(size == 5, "Expected 5, got %d\n", size);
525
526     hi = 0xbeefcace;
527     lo = 0xcafebabe;
528     hr = IAssemblyName_GetVersion(name, &hi, &lo);
529     ok(hr == FUSION_E_INVALID_NAME,
530        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
531     ok(hi == 0, "Expected 0, got %08x\n", hi);
532     ok(lo == 0, "Expected 0, got %08x\n", lo);
533
534     test_assembly_name_props(name, winename);
535
536     IAssemblyName_Release(name);
537
538     /* 'wine, Version=1.2.3.4' */
539     to_widechar(namestr, "wine, Version=1.2.3.4");
540     name = NULL;
541     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
542     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
543     ok(name != NULL, "Expected non-NULL name\n");
544
545     size = MAX_PATH;
546     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
547     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
548     ok_aw("wine, Version=1.2.3.4", str);
549     ok(size == 22, "Expected 22, got %d\n", size);
550
551     size = MAX_PATH;
552     str[0] = '\0';
553     hr = IAssemblyName_GetName(name, &size, str);
554     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
555     ok_aw("wine", str);
556     ok(size == 5, "Expected 5, got %d\n", size);
557
558     hi = 0xbeefcace;
559     lo = 0xcafebabe;
560     hr = IAssemblyName_GetVersion(name, &hi, &lo);
561     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
562     ok(hi == 0x00010002, "Expected 0x00010002, got %08x\n", hi);
563     ok(lo == 0x00030004, "Expected 0x00030004, got %08x\n", lo);
564
565     test_assembly_name_props(name, vername);
566
567     IAssemblyName_Release(name);
568
569     /* Version isn't of the form 1.x.x.x */
570     to_widechar(namestr, "wine, Version=1.5");
571     name = NULL;
572     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
573     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
574     ok(name != NULL, "Expected non-NULL name\n");
575
576     size = MAX_PATH;
577     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
578     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
579     ok_aw("wine, Version=1.5", str);
580     ok(size == 18, "Expected 18, got %d\n", size);
581
582     size = MAX_PATH;
583     str[0] = '\0';
584     hr = IAssemblyName_GetName(name, &size, str);
585     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
586     ok_aw("wine", str);
587     ok(size == 5, "Expected 5, got %d\n", size);
588
589     hi = 0xbeefcace;
590     lo = 0xcafebabe;
591     hr = IAssemblyName_GetVersion(name, &hi, &lo);
592     ok(hr == FUSION_E_INVALID_NAME,
593        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
594     ok(hi == 0, "Expected 0, got %08x\n", hi);
595     ok(lo == 0, "Expected 0, got %08x\n", lo);
596
597     test_assembly_name_props(name, badvername);
598
599     IAssemblyName_Release(name);
600
601     /* 'wine, Culture=neutral' */
602     to_widechar(namestr, "wine, Culture=neutral");
603     name = NULL;
604     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
605     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
606     ok(name != NULL, "Expected non-NULL name\n");
607
608     size = MAX_PATH;
609     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
610     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
611     ok_aw("wine, Culture=neutral", str);
612     ok(size == 22, "Expected 22, got %d\n", size);
613
614     size = MAX_PATH;
615     str[0] = '\0';
616     hr = IAssemblyName_GetName(name, &size, str);
617     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
618     ok_aw("wine", str);
619     ok(size == 5, "Expected 5, got %d\n", size);
620
621     hi = 0xbeefcace;
622     lo = 0xcafebabe;
623     hr = IAssemblyName_GetVersion(name, &hi, &lo);
624     ok(hr == FUSION_E_INVALID_NAME,
625        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
626     ok(hi == 0, "Expected 0, got %08x\n", hi);
627     ok(lo == 0, "Expected 0, got %08x\n", lo);
628
629     test_assembly_name_props(name, neutralname);
630
631     IAssemblyName_Release(name);
632
633     /* 'wine, Culture=en' */
634     to_widechar(namestr, "wine, Culture=en");
635     name = NULL;
636     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
637     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
638     ok(name != NULL, "Expected non-NULL name\n");
639
640     size = MAX_PATH;
641     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
642     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
643     ok_aw("wine, Culture=en", str);
644     ok(size == 17, "Expected 17, got %d\n", size);
645
646     size = MAX_PATH;
647     str[0] = '\0';
648     hr = IAssemblyName_GetName(name, &size, str);
649     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
650     ok_aw("wine", str);
651     ok(size == 5, "Expected 5, got %d\n", size);
652
653     hi = 0xbeefcace;
654     lo = 0xcafebabe;
655     hr = IAssemblyName_GetVersion(name, &hi, &lo);
656     ok(hr == FUSION_E_INVALID_NAME,
657        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
658     ok(hi == 0, "Expected 0, got %08x\n", hi);
659     ok(lo == 0, "Expected 0, got %08x\n", lo);
660
661     test_assembly_name_props(name, enname);
662
663     IAssemblyName_Release(name);
664
665     /* 'wine, PublicKeyToken=1234567890abcdef' */
666     to_widechar(namestr, "wine, PublicKeyToken=1234567890abcdef");
667     name = NULL;
668     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
669     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
670     ok(name != NULL, "Expected non-NULL name\n");
671
672     size = MAX_PATH;
673     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
674     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
675     ok_aw("wine, PublicKeyToken=1234567890abcdef", str);
676     ok(size == 38, "Expected 38, got %d\n", size);
677
678     size = MAX_PATH;
679     str[0] = '\0';
680     hr = IAssemblyName_GetName(name, &size, str);
681     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
682     ok_aw("wine", str);
683     ok(size == 5, "Expected 5, got %d\n", size);
684
685     hi = 0xbeefcace;
686     lo = 0xcafebabe;
687     hr = IAssemblyName_GetVersion(name, &hi, &lo);
688     ok(hr == FUSION_E_INVALID_NAME,
689        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
690     ok(hi == 0, "Expected 0, got %08x\n", hi);
691     ok(lo == 0, "Expected 0, got %08x\n", lo);
692
693     test_assembly_name_props(name, pubkeyname);
694
695     IAssemblyName_Release(name);
696
697     /* PublicKeyToken is not 16 chars long */
698     to_widechar(namestr, "wine, PublicKeyToken=567890abcdef");
699     name = (IAssemblyName *)0xdeadbeef;
700     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
701     ok(hr == FUSION_E_INVALID_NAME,
702        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
703     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
704
705     /* PublicKeyToken contains invalid chars */
706     to_widechar(namestr, "wine, PublicKeyToken=1234567890ghijkl");
707     name = (IAssemblyName *)0xdeadbeef;
708     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
709     ok(hr == FUSION_E_INVALID_NAME,
710        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
711     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
712
713     /* no comma separator */
714     to_widechar(namestr, "wine PublicKeyToken=1234567890abcdef");
715     name = (IAssemblyName *)0xdeadbeef;
716     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
717     todo_wine
718     {
719         ok(hr == FUSION_E_INVALID_NAME,
720            "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
721         ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
722     }
723
724     /* no '=' */
725     to_widechar(namestr, "wine, PublicKeyToken");
726     name = (IAssemblyName *)0xdeadbeef;
727     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
728     ok(hr == FUSION_E_INVALID_NAME,
729        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
730     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
731
732     /* no value */
733     to_widechar(namestr, "wine, PublicKeyToken=");
734     name = (IAssemblyName *)0xdeadbeef;
735     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
736     ok(hr == FUSION_E_INVALID_NAME,
737        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
738     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
739
740     /* invalid property */
741     to_widechar(namestr, "wine, BadProp=42");
742     name = NULL;
743     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
744     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
745     ok(name != NULL, "Expected non-NULL name\n");
746
747     size = MAX_PATH;
748     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
749     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
750     todo_wine
751     {
752         ok_aw("wine", str);
753         ok(size == 5, "Expected 5, got %d\n", size);
754     }
755
756     size = MAX_PATH;
757     str[0] = '\0';
758     hr = IAssemblyName_GetName(name, &size, str);
759     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
760     ok_aw("wine", str);
761     ok(size == 5, "Expected 5, got %d\n", size);
762
763     hi = 0xbeefcace;
764     lo = 0xcafebabe;
765     hr = IAssemblyName_GetVersion(name, &hi, &lo);
766     ok(hr == FUSION_E_INVALID_NAME,
767        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
768     ok(hi == 0, "Expected 0, got %08x\n", hi);
769     ok(lo == 0, "Expected 0, got %08x\n", lo);
770
771     test_assembly_name_props(name, winename);
772
773     IAssemblyName_Release(name);
774 }
775
776 START_TEST(asmname)
777 {
778     if (!init_functionpointers())
779     {
780         skip("fusion.dll not available\n");
781         return;
782     }
783
784     test_CreateAssemblyNameObject();
785 }