msvcrt: Added unicode modes support _setmode function.
[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        broken(hr == E_INVALIDARG), /* .NET 1.x */
422        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
423
424     size = MAX_PATH;
425     str[0] = '\0';
426     hr = IAssemblyName_GetName(name, &size, str);
427     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
428     ok(lstrlenW(str) == 0, "Expected empty name\n");
429     ok(size == 0, "Expected 0, got %d\n", size);
430
431     hi = 0xbeefcace;
432     lo = 0xcafebabe;
433     hr = IAssemblyName_GetVersion(name, &hi, &lo);
434     ok(hr == FUSION_E_INVALID_NAME ||
435        broken(hr == S_OK), /* .NET 1.x */
436        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
437     ok(hi == 0, "Expected 0, got %08x\n", hi);
438     ok(lo == 0, "Expected 0, got %08x\n", lo);
439
440     if (hr == S_OK)
441         win_skip(".NET 1.x doesn't handle ASM_NAME_PROCESSOR_ID_ARRAY"
442                  " and ASM_NAME_OSINFO_ARRAY correctly\n");
443     else
444         test_assembly_name_props(name, defaults);
445
446     IAssemblyName_Release(name);
447
448     /* empty szAssemblyName */
449     name = NULL;
450     hr = pCreateAssemblyNameObject(&name, empty, CANOF_SET_DEFAULT_VALUES, NULL);
451     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
452     ok(name != NULL, "Expected non-NULL name\n");
453
454     size = MAX_PATH;
455     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
456     ok(hr == FUSION_E_INVALID_NAME ||
457        broken(hr == S_OK), /* .NET 1.x */
458        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
459
460     size = MAX_PATH;
461     str[0] = '\0';
462     hr = IAssemblyName_GetName(name, &size, str);
463     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
464     ok(lstrlenW(str) == 0, "Expected empty name\n");
465     ok(size == 1, "Expected 1, got %d\n", size);
466
467     hi = 0xbeefcace;
468     lo = 0xcafebabe;
469     hr = IAssemblyName_GetVersion(name, &hi, &lo);
470     ok(hr == FUSION_E_INVALID_NAME ||
471        broken(hr == S_OK), /* .NET 1.x */
472        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
473     ok(hi == 0, "Expected 0, got %08x\n", hi);
474     ok(lo == 0, "Expected 0, got %08x\n", lo);
475
476     if (hr == S_OK)
477         win_skip(".NET 1.x doesn't handle ASM_NAME_PROCESSOR_ID_ARRAY"
478                  " and ASM_NAME_OSINFO_ARRAY correctly\n");
479     else
480         test_assembly_name_props(name, emptyname);
481
482     IAssemblyName_Release(name);
483
484     /* 'wine' */
485     to_widechar(namestr, "wine");
486     name = NULL;
487     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_SET_DEFAULT_VALUES, NULL);
488     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
489     ok(name != NULL, "Expected non-NULL name\n");
490
491     size = MAX_PATH;
492     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
493     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
494     ok_aw("wine", str);
495     ok(size == 5, "Expected 5, got %d\n", size);
496
497     size = MAX_PATH;
498     str[0] = '\0';
499     hr = IAssemblyName_GetName(name, &size, str);
500     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
501     ok_aw("wine", str);
502     ok(size == 5, "Expected 5, got %d\n", size);
503
504     hi = 0xbeefcace;
505     lo = 0xcafebabe;
506     hr = IAssemblyName_GetVersion(name, &hi, &lo);
507     ok(hr == FUSION_E_INVALID_NAME ||
508        broken(hr == S_OK), /* .NET 1.x */
509        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
510     ok(hi == 0, "Expected 0, got %08x\n", hi);
511     ok(lo == 0, "Expected 0, got %08x\n", lo);
512
513     if (hr == S_OK)
514         win_skip(".NET 1.x doesn't handle ASM_NAME_PROCESSOR_ID_ARRAY"
515                  " and ASM_NAME_OSINFO_ARRAY correctly\n");
516     else
517         test_assembly_name_props(name, winename);
518
519     IAssemblyName_Release(name);
520
521     /* check the contents of the AssemblyName with parsing */
522
523     /* 'wine' */
524     to_widechar(namestr, "wine");
525     name = NULL;
526     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
527     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
528     ok(name != NULL, "Expected non-NULL name\n");
529
530     size = MAX_PATH;
531     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
532     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
533     ok_aw("wine", str);
534     ok(size == 5, "Expected 5, got %d\n", size);
535
536     size = MAX_PATH;
537     str[0] = '\0';
538     hr = IAssemblyName_GetName(name, &size, str);
539     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
540     ok_aw("wine", str);
541     ok(size == 5, "Expected 5, got %d\n", size);
542
543     hi = 0xbeefcace;
544     lo = 0xcafebabe;
545     hr = IAssemblyName_GetVersion(name, &hi, &lo);
546     ok(hr == FUSION_E_INVALID_NAME ||
547        broken(hr == S_OK), /* .NET 1.x */
548        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
549     ok(hi == 0, "Expected 0, got %08x\n", hi);
550     ok(lo == 0, "Expected 0, got %08x\n", lo);
551
552     test_assembly_name_props(name, winename);
553
554     IAssemblyName_Release(name);
555
556     /* 'wine, Version=1.2.3.4' */
557     to_widechar(namestr, "wine, Version=1.2.3.4");
558     name = NULL;
559     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
560     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
561     ok(name != NULL, "Expected non-NULL name\n");
562
563     size = MAX_PATH;
564     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
565     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
566     ok_aw("wine, Version=1.2.3.4", str);
567     ok(size == 22, "Expected 22, got %d\n", size);
568
569     size = MAX_PATH;
570     str[0] = '\0';
571     hr = IAssemblyName_GetName(name, &size, str);
572     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
573     ok_aw("wine", str);
574     ok(size == 5, "Expected 5, got %d\n", size);
575
576     hi = 0xbeefcace;
577     lo = 0xcafebabe;
578     hr = IAssemblyName_GetVersion(name, &hi, &lo);
579     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
580     ok(hi == 0x00010002, "Expected 0x00010002, got %08x\n", hi);
581     ok(lo == 0x00030004, "Expected 0x00030004, got %08x\n", lo);
582
583     test_assembly_name_props(name, vername);
584
585     IAssemblyName_Release(name);
586
587     /* Version isn't of the form 1.x.x.x */
588     to_widechar(namestr, "wine, Version=1.5");
589     name = NULL;
590     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
591     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
592     ok(name != NULL, "Expected non-NULL name\n");
593
594     size = MAX_PATH;
595     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
596     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
597     ok_aw("wine, Version=1.5", str);
598     ok(size == 18, "Expected 18, got %d\n", size);
599
600     size = MAX_PATH;
601     str[0] = '\0';
602     hr = IAssemblyName_GetName(name, &size, str);
603     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
604     ok_aw("wine", str);
605     ok(size == 5, "Expected 5, got %d\n", size);
606
607     hi = 0xbeefcace;
608     lo = 0xcafebabe;
609     hr = IAssemblyName_GetVersion(name, &hi, &lo);
610     ok(hr == FUSION_E_INVALID_NAME ||
611        broken(hr == S_OK), /* .NET 1.x */
612        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
613     ok(hi == 0 ||
614        broken(hi == 0x10005), /* .NET 1.x */
615        "Expected 0, got %08x\n", hi);
616     ok(lo == 0, "Expected 0, got %08x\n", lo);
617
618     test_assembly_name_props(name, badvername);
619
620     IAssemblyName_Release(name);
621
622     /* 'wine, Culture=neutral' */
623     to_widechar(namestr, "wine, Culture=neutral");
624     name = NULL;
625     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
626     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
627     ok(name != NULL, "Expected non-NULL name\n");
628
629     size = MAX_PATH;
630     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
631     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
632     ok_aw("wine, Culture=neutral", str);
633     ok(size == 22, "Expected 22, got %d\n", size);
634
635     size = MAX_PATH;
636     str[0] = '\0';
637     hr = IAssemblyName_GetName(name, &size, str);
638     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
639     ok_aw("wine", str);
640     ok(size == 5, "Expected 5, got %d\n", size);
641
642     hi = 0xbeefcace;
643     lo = 0xcafebabe;
644     hr = IAssemblyName_GetVersion(name, &hi, &lo);
645     ok(hr == FUSION_E_INVALID_NAME ||
646        broken(hr == S_OK), /* .NET 1.x */
647        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
648     ok(hi == 0, "Expected 0, got %08x\n", hi);
649     ok(lo == 0, "Expected 0, got %08x\n", lo);
650
651     test_assembly_name_props(name, neutralname);
652
653     IAssemblyName_Release(name);
654
655     /* 'wine, Culture=en' */
656     to_widechar(namestr, "wine, Culture=en");
657     name = NULL;
658     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
659     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
660     ok(name != NULL, "Expected non-NULL name\n");
661
662     size = MAX_PATH;
663     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
664     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
665     ok_aw("wine, Culture=en", str);
666     ok(size == 17, "Expected 17, got %d\n", size);
667
668     size = MAX_PATH;
669     str[0] = '\0';
670     hr = IAssemblyName_GetName(name, &size, str);
671     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
672     ok_aw("wine", str);
673     ok(size == 5, "Expected 5, got %d\n", size);
674
675     hi = 0xbeefcace;
676     lo = 0xcafebabe;
677     hr = IAssemblyName_GetVersion(name, &hi, &lo);
678     ok(hr == FUSION_E_INVALID_NAME ||
679        broken(hr == S_OK), /* .NET 1.x */
680        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
681     ok(hi == 0, "Expected 0, got %08x\n", hi);
682     ok(lo == 0, "Expected 0, got %08x\n", lo);
683
684     test_assembly_name_props(name, enname);
685
686     IAssemblyName_Release(name);
687
688     /* 'wine, PublicKeyToken=1234567890abcdef' */
689     to_widechar(namestr, "wine, PublicKeyToken=1234567890abcdef");
690     name = NULL;
691     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
692     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
693     ok(name != NULL, "Expected non-NULL name\n");
694
695     size = MAX_PATH;
696     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
697     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
698     ok_aw("wine, PublicKeyToken=1234567890abcdef", str);
699     ok(size == 38, "Expected 38, got %d\n", size);
700
701     size = MAX_PATH;
702     str[0] = '\0';
703     hr = IAssemblyName_GetName(name, &size, str);
704     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
705     ok_aw("wine", str);
706     ok(size == 5, "Expected 5, got %d\n", size);
707
708     hi = 0xbeefcace;
709     lo = 0xcafebabe;
710     hr = IAssemblyName_GetVersion(name, &hi, &lo);
711     ok(hr == FUSION_E_INVALID_NAME ||
712        broken(hr == S_OK), /* .NET 1.x */
713        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
714     ok(hi == 0, "Expected 0, got %08x\n", hi);
715     ok(lo == 0, "Expected 0, got %08x\n", lo);
716
717     test_assembly_name_props(name, pubkeyname);
718
719     IAssemblyName_Release(name);
720
721     /* Processor architecture tests */
722     to_widechar(namestr, "wine, processorArchitecture=x86");
723     name = NULL;
724     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
725     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
726
727     ok(name != NULL, "Expected non-NULL name\n");
728
729     size = MAX_PATH;
730     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_PROCESSORARCHITECTURE);
731     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
732
733     WideCharToMultiByte(CP_ACP, 0, str, -1, string1, MAX_PATH, NULL, NULL);
734
735     if (lstrcmpA(string1, "wine") == 0)
736         win_skip("processorArchitecture not supported on .NET 1.x\n");
737     else
738     {
739         ok_aw("wine, processorArchitecture=x86", str);
740         ok(size == 32, "Expected 32, got %d\n", size);
741
742         IAssemblyName_Release(name);
743
744         /* amd64 */
745         to_widechar(namestr, "wine, processorArchitecture=AMD64");
746         name = NULL;
747         hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
748         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
749
750         size = MAX_PATH;
751         hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_PROCESSORARCHITECTURE);
752         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
753         ok_aw("wine, processorArchitecture=AMD64", str);
754         ok(size == 34, "Expected 34, got %d\n", size);
755
756         IAssemblyName_Release(name);
757
758         /* ia64 */
759         to_widechar(namestr, "wine, processorArchitecture=IA64");
760         name = NULL;
761         hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
762         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
763
764         size = MAX_PATH;
765         hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_PROCESSORARCHITECTURE);
766         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
767         ok_aw("wine, processorArchitecture=IA64", str);
768         ok(size == 33, "Expected 33, got %d\n", size);
769
770         IAssemblyName_Release(name);
771
772         /* msil */
773         to_widechar(namestr, "wine, processorArchitecture=MSIL");
774         name = NULL;
775         hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
776         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
777
778         size = MAX_PATH;
779         hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_PROCESSORARCHITECTURE);
780         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
781         ok_aw("wine, processorArchitecture=MSIL", str);
782         ok(size == 33, "Expected 33, got %d\n", size);
783
784         IAssemblyName_Release(name);
785     }
786
787     /* Pulling out various different values */
788     to_widechar(namestr, "wine, Version=1.2.3.4, Culture=en, PublicKeyToken=1234567890abcdef");
789     name = NULL;
790     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
791     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
792     ok(name != NULL, "Expected non-NULL name\n");
793
794     size = MAX_PATH;
795     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE);
796     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
797     ok_aw("wine, Version=1.2.3.4, Culture=en", str);
798     ok(size == 34, "Expected 34, got %d\n", size);
799
800     size = MAX_PATH;
801     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_CULTURE | ASM_DISPLAYF_PUBLIC_KEY_TOKEN);
802     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
803     ok_aw("wine, Culture=en, PublicKeyToken=1234567890abcdef", str);
804     ok(size == 50, "Expected 50, got %d\n", size);
805
806     size = MAX_PATH;
807     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
808     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
809     ok_aw("wine, Version=1.2.3.4, Culture=en, PublicKeyToken=1234567890abcdef", str);
810     ok(size == 67, "Expected 67, got %d\n", size);
811
812     IAssemblyName_Release(name);
813
814     /* invalid property */
815     to_widechar(namestr, "wine, BadProp=42");
816     name = NULL;
817     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
818     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
819     ok(name != NULL, "Expected non-NULL name\n");
820
821     size = MAX_PATH;
822     str[0] = '\0';
823     hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
824     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
825     ok_aw("wine", str);
826     ok(size == 5, "Expected 5, got %d\n", size);
827
828     size = MAX_PATH;
829     str[0] = '\0';
830     hr = IAssemblyName_GetName(name, &size, str);
831     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
832     ok_aw("wine", str);
833     ok(size == 5, "Expected 5, got %d\n", size);
834
835     hi = 0xbeefcace;
836     lo = 0xcafebabe;
837     hr = IAssemblyName_GetVersion(name, &hi, &lo);
838     ok(hr == FUSION_E_INVALID_NAME ||
839        broken(hr == S_OK), /* .NET 1.x */
840        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
841     ok(hi == 0, "Expected 0, got %08x\n", hi);
842     ok(lo == 0, "Expected 0, got %08x\n", lo);
843
844     test_assembly_name_props(name, winename);
845
846     IAssemblyName_Release(name);
847
848     /* PublicKeyToken is not 16 chars long */
849     to_widechar(namestr, "wine, PublicKeyToken=567890abcdef");
850     name = (IAssemblyName *)0xdeadbeef;
851     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
852     if (hr == S_OK && name != (IAssemblyName *)0xdeadbeef)
853     {
854         win_skip(".NET 1.x doesn't check PublicKeyToken correctly\n");
855         IAssemblyName_Release(name);
856         return;
857     }
858     ok(hr == FUSION_E_INVALID_NAME,
859        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
860     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
861
862     /* PublicKeyToken contains invalid chars */
863     to_widechar(namestr, "wine, PublicKeyToken=1234567890ghijkl");
864     name = (IAssemblyName *)0xdeadbeef;
865     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
866     ok(hr == FUSION_E_INVALID_NAME,
867        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
868     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
869
870     /* no comma separator */
871     to_widechar(namestr, "wine PublicKeyToken=1234567890abcdef");
872     name = (IAssemblyName *)0xdeadbeef;
873     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
874     ok(hr == FUSION_E_INVALID_NAME,
875        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
876     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
877     if(SUCCEEDED(hr)) IAssemblyName_Release(name);
878
879     /* no '=' */
880     to_widechar(namestr, "wine, PublicKeyToken");
881     name = (IAssemblyName *)0xdeadbeef;
882     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
883     ok(hr == FUSION_E_INVALID_NAME,
884        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
885     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
886
887     /* no value */
888     to_widechar(namestr, "wine, PublicKeyToken=");
889     name = (IAssemblyName *)0xdeadbeef;
890     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
891     ok(hr == FUSION_E_INVALID_NAME,
892        "Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
893     ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
894
895     /* no spaces */
896     to_widechar(namestr, "wine,version=1.0.0.0");
897     name = (IAssemblyName *)0xdeadbeef;
898     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
899     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
900     ok(name != NULL, "Expected non-NULL name\n");
901     hi = lo = 0xdeadbeef;
902     hr = IAssemblyName_GetVersion(name, &hi, &lo);
903     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
904     ok(hi == 65536, "Expected 536, got %u\n", hi);
905     ok(lo == 0, "Expected 0, got %u\n", lo);
906     IAssemblyName_Release(name);
907
908     /* quoted values */
909     to_widechar(namestr, "wine, version=\"1.0.0.0\",culture=\"en\"");
910     name = (IAssemblyName *)0xdeadbeef;
911     hr = pCreateAssemblyNameObject(&name, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
912     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
913     ok(name != NULL, "Expected non-NULL name\n");
914     hi = lo = 0xdeadbeef;
915     hr = IAssemblyName_GetVersion(name, &hi, &lo);
916     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
917     ok(hi == 65536, "Expected 65536, got %u\n", hi);
918     ok(lo == 0, "Expected 0, got %u\n", lo);
919     IAssemblyName_Release(name);
920 }
921
922 static void test_IAssemblyName_IsEqual(void)
923 {
924     static const WCHAR wine1[] =
925         {'w','i','n','e',0};
926     static const WCHAR wine2[] =
927         {'w','i','n','e',',','v','e','r','s','i','o','n','=','1','.','0','.','0','.','0',0};
928     static const WCHAR wine3[] =
929         {'w','i','n','e',',','v','e','r','s','i','o','n','=','1','.','0','.','0','.','0',',',
930          'c','u','l','t','u','r','e','=','n','e','u','t','r','a','l',0};
931     static const WCHAR wine4[] =
932         {'w','i','n','e',',','v','e','r','s','i','o','n','=','1','.','0','.','0','.','0',',',
933          'c','u','l','t','u','r','e','=','e','n',0};
934     static const WCHAR wine5[] =
935         {'w','i','n','e',',','v','e','r','s','i','o','n','=','1','.','0','.','0','.','0',',',
936          'p','u','b','l','i','c','K','e','y','T','o','k','e','n','=','1','2','3','4','5','6',
937          '7','8','9','0','a','b','c','d','e','f',0};
938     HRESULT hr;
939     IAssemblyName *name1, *name2;
940
941     hr = pCreateAssemblyNameObject( &name1, wine1, CANOF_PARSE_DISPLAY_NAME, NULL );
942     ok( hr == S_OK, "got %08x\n", hr );
943
944     hr = pCreateAssemblyNameObject( &name2, wine1, CANOF_PARSE_DISPLAY_NAME, NULL );
945     ok( hr == S_OK, "got %08x\n", hr );
946
947     if (0) { /* crashes on some old version */
948     hr = IAssemblyName_IsEqual( name1, NULL, 0 );
949     ok( hr == S_FALSE, "got %08x\n", hr );
950
951     hr = IAssemblyName_IsEqual( name1, NULL, ASM_CMPF_IL_ALL );
952     ok( hr == S_FALSE, "got %08x\n", hr );
953     }
954
955     hr = IAssemblyName_IsEqual( name1, name1, ASM_CMPF_IL_ALL );
956     ok( hr == S_OK, "got %08x\n", hr );
957
958     hr = IAssemblyName_IsEqual( name1, name2, ASM_CMPF_IL_ALL );
959     ok( hr == S_OK, "got %08x\n", hr );
960
961     IAssemblyName_Release( name2 );
962     hr = pCreateAssemblyNameObject( &name2, wine2, CANOF_PARSE_DISPLAY_NAME, NULL );
963     ok( hr == S_OK, "got %08x\n", hr );
964
965     hr = IAssemblyName_IsEqual( name1, name2, ASM_CMPF_IL_ALL );
966     ok( hr == S_OK, "got %08x\n", hr );
967
968     IAssemblyName_Release( name2 );
969     hr = pCreateAssemblyNameObject( &name2, wine3, CANOF_PARSE_DISPLAY_NAME, NULL );
970     ok( hr == S_OK, "got %08x\n", hr );
971
972     hr = IAssemblyName_IsEqual( name1, name2, ASM_CMPF_IL_ALL );
973     ok( hr == S_OK, "got %08x\n", hr );
974
975     IAssemblyName_Release( name1 );
976     hr = pCreateAssemblyNameObject( &name1, wine4, CANOF_PARSE_DISPLAY_NAME, NULL );
977     ok( hr == S_OK, "got %08x\n", hr );
978
979     hr = IAssemblyName_IsEqual( name1, name2, ASM_CMPF_IL_ALL );
980     ok( hr == S_FALSE, "got %08x\n", hr );
981
982     IAssemblyName_Release( name1 );
983     hr = pCreateAssemblyNameObject( &name1, wine1, CANOF_PARSE_DISPLAY_NAME, NULL );
984     ok( hr == S_OK, "got %08x\n", hr );
985
986     IAssemblyName_Release( name2 );
987     hr = pCreateAssemblyNameObject( &name2, wine5, CANOF_PARSE_DISPLAY_NAME, NULL );
988     ok( hr == S_OK, "got %08x\n", hr );
989
990     hr = IAssemblyName_IsEqual( name1, name2, ASM_CMPF_IL_ALL );
991     ok( hr == S_OK, "got %08x\n", hr );
992
993     IAssemblyName_Release( name1 );
994     IAssemblyName_Release( name2 );
995 }
996
997 START_TEST(asmname)
998 {
999     if (!init_functionpointers())
1000     {
1001         win_skip("fusion.dll not available\n");
1002         return;
1003     }
1004
1005     test_CreateAssemblyNameObject();
1006     test_IAssemblyName_IsEqual();
1007 }