[ROSTESTS]
[reactos.git] / rostests / winetests / fusion / asmenum.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 WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #define COBJMACROS
24
25 #include <stdio.h>
26
27 //#include <windows.h>
28 #include <windef.h>
29 #include <winbase.h>
30 #include <winreg.h>
31 #include <winnls.h>
32 #include <shlwapi.h>
33 //#include <mscoree.h>
34 #include <fusion.h>
35 //#include <corerror.h>
36
37 #include <wine/test.h>
38 #include <wine/list.h>
39
40 static HRESULT (WINAPI *pCreateAssemblyEnum)(IAssemblyEnum **pEnum,
41 IUnknown *pUnkReserved,
42 IAssemblyName *pName,
43 DWORD dwFlags, LPVOID pvReserved);
44 static HRESULT (WINAPI *pCreateAssemblyNameObject)(LPASSEMBLYNAME *ppAssemblyNameObj,
45 LPCWSTR szAssemblyName, DWORD dwFlags,
46 LPVOID pvReserved);
47 static HRESULT (WINAPI *pGetCachePath)(ASM_CACHE_FLAGS dwCacheFlags,
48 LPWSTR pwzCachePath, PDWORD pcchPath);
49 static HRESULT (WINAPI *pLoadLibraryShim)(LPCWSTR szDllName, LPCWSTR szVersion,
50 LPVOID pvReserved, HMODULE *phModDll);
51
52 static BOOL init_functionpointers(void)
53 {
54 HRESULT hr;
55 HMODULE hfusion;
56 HMODULE hmscoree;
57
58 static const WCHAR szFusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
59
60 hmscoree = LoadLibraryA("mscoree.dll");
61 if (!hmscoree)
62 {
63 win_skip("mscoree.dll not available\n");
64 return FALSE;
65 }
66
67 pLoadLibraryShim = (void *)GetProcAddress(hmscoree, "LoadLibraryShim");
68 if (!pLoadLibraryShim)
69 {
70 win_skip("LoadLibraryShim not available\n");
71 FreeLibrary(hmscoree);
72 return FALSE;
73 }
74
75 hr = pLoadLibraryShim(szFusion, NULL, NULL, &hfusion);
76 if (FAILED(hr))
77 {
78 win_skip("fusion.dll not available\n");
79 FreeLibrary(hmscoree);
80 return FALSE;
81 }
82
83 pCreateAssemblyEnum = (void *)GetProcAddress(hfusion, "CreateAssemblyEnum");
84 pCreateAssemblyNameObject = (void *)GetProcAddress(hfusion, "CreateAssemblyNameObject");
85 pGetCachePath = (void *)GetProcAddress(hfusion, "GetCachePath");
86
87 if (!pCreateAssemblyEnum ||
88 !pCreateAssemblyNameObject || !pGetCachePath)
89 {
90 win_skip("fusion.dll not implemented\n");
91 return FALSE;
92 }
93
94 FreeLibrary(hmscoree);
95 return TRUE;
96 }
97
98 static inline void to_widechar(LPWSTR dest, LPCSTR src)
99 {
100 MultiByteToWideChar(CP_ACP, 0, src, -1, dest, MAX_PATH);
101 }
102
103 static inline void to_multibyte(LPSTR dest, LPWSTR src)
104 {
105 WideCharToMultiByte(CP_ACP, 0, src, -1, dest, MAX_PATH, NULL, NULL);
106 }
107
108 static BOOL create_full_path(LPCSTR path)
109 {
110 LPSTR new_path;
111 BOOL ret = TRUE;
112 int len;
113
114 new_path = HeapAlloc(GetProcessHeap(), 0, lstrlenA(path) + 1);
115 if (!new_path)
116 return FALSE;
117
118 lstrcpyA(new_path, path);
119
120 while ((len = lstrlenA(new_path)) && new_path[len - 1] == '\\')
121 new_path[len - 1] = 0;
122
123 while (!CreateDirectoryA(new_path, NULL))
124 {
125 LPSTR slash;
126 DWORD last_error = GetLastError();
127
128 if(last_error == ERROR_ALREADY_EXISTS)
129 break;
130
131 if(last_error != ERROR_PATH_NOT_FOUND)
132 {
133 ret = FALSE;
134 break;
135 }
136
137 if(!(slash = strrchr(new_path, '\\')))
138 {
139 ret = FALSE;
140 break;
141 }
142
143 len = slash - new_path;
144 new_path[len] = 0;
145 if(!create_full_path(new_path))
146 {
147 ret = FALSE;
148 break;
149 }
150
151 new_path[len] = '\\';
152 }
153
154 HeapFree(GetProcessHeap(), 0, new_path);
155 return ret;
156 }
157
158 static BOOL create_file_data(LPCSTR name, LPCSTR data, DWORD size)
159 {
160 HANDLE file;
161 DWORD written;
162
163 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
164 if (file == INVALID_HANDLE_VALUE)
165 return FALSE;
166
167 WriteFile(file, data, strlen(data), &written, NULL);
168
169 if (size)
170 {
171 SetFilePointer(file, size, NULL, FILE_BEGIN);
172 SetEndOfFile(file);
173 }
174
175 CloseHandle(file);
176 return TRUE;
177 }
178
179 static void test_CreateAssemblyEnum(void)
180 {
181 HRESULT hr;
182 WCHAR namestr[MAX_PATH];
183 IAssemblyEnum *asmenum;
184 IAssemblyName *asmname;
185
186 to_widechar(namestr, "wine");
187 asmname = NULL;
188 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
189 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
190 ok(asmname != NULL, "Expected non-NULL asmname\n");
191
192 /* pEnum is NULL */
193 if (0)
194 {
195 /* Crashes on .NET 1.x */
196 hr = pCreateAssemblyEnum(NULL, NULL, asmname, ASM_CACHE_GAC, NULL);
197 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
198 }
199
200 /* pName is NULL */
201 asmenum = NULL;
202 hr = pCreateAssemblyEnum(&asmenum, NULL, NULL, ASM_CACHE_GAC, NULL);
203 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
204 ok(asmenum != NULL, "Expected non-NULL asmenum\n");
205
206 IAssemblyEnum_Release(asmenum);
207
208 /* dwFlags is ASM_CACHE_ROOT */
209 asmenum = (IAssemblyEnum *)0xdeadbeef;
210 hr = pCreateAssemblyEnum(&asmenum, NULL, NULL, ASM_CACHE_ROOT, NULL);
211 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
212 ok(asmenum == (IAssemblyEnum *)0xdeadbeef,
213 "Expected asmenum to be unchanged, got %p\n", asmenum);
214
215 /* invalid dwFlags */
216 asmenum = (IAssemblyEnum *)0xdeadbeef;
217 hr = pCreateAssemblyEnum(&asmenum, NULL, NULL, 0, NULL);
218 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
219 ok(asmenum == (IAssemblyEnum *)0xdeadbeef,
220 "Expected asmenum to be unchanged, got %p\n", asmenum);
221
222 IAssemblyName_Release(asmname);
223 }
224
225 typedef struct _tagASMNAME
226 {
227 struct list entry;
228 LPSTR data;
229 } ASMNAME;
230
231 static BOOL enum_gac_assemblies(struct list *assemblies, int depth, LPSTR path)
232 {
233 WIN32_FIND_DATAA ffd;
234 CHAR buf[MAX_PATH];
235 CHAR disp[MAX_PATH];
236 ASMNAME *name;
237 HANDLE hfind;
238 LPSTR ptr;
239
240 static CHAR parent[MAX_PATH];
241
242 sprintf(buf, "%s\\*", path);
243 hfind = FindFirstFileA(buf, &ffd);
244 if (hfind == INVALID_HANDLE_VALUE)
245 return FALSE;
246
247 do
248 {
249 if (!lstrcmpA(ffd.cFileName, ".") || !lstrcmpA(ffd.cFileName, ".."))
250 continue;
251
252 if (depth == 0)
253 {
254 lstrcpyA(parent, ffd.cFileName);
255 }
256 else if (depth == 1)
257 {
258 char culture[MAX_PATH];
259 char dll[MAX_PATH], exe[MAX_PATH];
260
261 /* Directories with no dll or exe will not be enumerated */
262 sprintf(dll, "%s\\%s\\%s.dll", path, ffd.cFileName, parent);
263 sprintf(exe, "%s\\%s\\%s.exe", path, ffd.cFileName, parent);
264 if (GetFileAttributesA(dll) == INVALID_FILE_ATTRIBUTES &&
265 GetFileAttributesA(exe) == INVALID_FILE_ATTRIBUTES)
266 continue;
267
268 ptr = strstr(ffd.cFileName, "_");
269 *ptr = '\0';
270 ptr++;
271
272 if (*ptr != '_')
273 {
274 lstrcpyA(culture, ptr);
275 *strstr(culture, "_") = '\0';
276 }
277 else
278 lstrcpyA(culture, "neutral");
279
280 ptr = strchr(ptr, '_');
281 ptr++;
282 sprintf(buf, ", Version=%s, Culture=%s, PublicKeyToken=%s",
283 ffd.cFileName, culture, ptr);
284 lstrcpyA(disp, parent);
285 lstrcatA(disp, buf);
286
287 name = HeapAlloc(GetProcessHeap(), 0, sizeof(ASMNAME));
288 name->data = HeapAlloc(GetProcessHeap(), 0, lstrlenA(disp) + 1);
289 lstrcpyA(name->data, disp);
290 list_add_tail(assemblies, &name->entry);
291
292 continue;
293 }
294
295 sprintf(buf, "%s\\%s", path, ffd.cFileName);
296 enum_gac_assemblies(assemblies, depth + 1, buf);
297 } while (FindNextFileA(hfind, &ffd) != 0);
298
299 FindClose(hfind);
300 return TRUE;
301 }
302
303 static void test_enumerate(void)
304 {
305 struct list assemblies = LIST_INIT(assemblies);
306 struct list *item, *cursor;
307 IAssemblyEnum *asmenum;
308 IAssemblyName *next;
309 WCHAR buf[MAX_PATH];
310 CHAR path[MAX_PATH];
311 CHAR disp[MAX_PATH];
312 HRESULT hr;
313 BOOL found;
314 DWORD size;
315
316 size = MAX_PATH;
317 hr = pGetCachePath(ASM_CACHE_GAC, buf, &size);
318 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
319
320 to_multibyte(path, buf);
321 lstrcatA(path, "_32");
322 enum_gac_assemblies(&assemblies, 0, path);
323
324 to_multibyte(path, buf);
325 lstrcatA(path, "_64");
326 enum_gac_assemblies(&assemblies, 0, path);
327
328 to_multibyte(path, buf);
329 lstrcatA(path, "_MSIL");
330 enum_gac_assemblies(&assemblies, 0, path);
331
332 to_multibyte(path, buf);
333 enum_gac_assemblies(&assemblies, 0, path);
334
335 asmenum = NULL;
336 hr = pCreateAssemblyEnum(&asmenum, NULL, NULL, ASM_CACHE_GAC, NULL);
337 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
338 ok(asmenum != NULL, "Expected non-NULL asmenum\n");
339
340 while (IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0) == S_OK)
341 {
342 size = MAX_PATH;
343 IAssemblyName_GetDisplayName(next, buf, &size, 0);
344 to_multibyte(disp, buf);
345
346 found = FALSE;
347 LIST_FOR_EACH_SAFE(item, cursor, &assemblies)
348 {
349 ASMNAME *asmname = LIST_ENTRY(item, ASMNAME, entry);
350
351 if (!lstrcmpA(asmname->data, disp))
352 {
353 found = TRUE;
354
355 list_remove(&asmname->entry);
356 HeapFree(GetProcessHeap(), 0, asmname->data);
357 HeapFree(GetProcessHeap(), 0, asmname);
358 break;
359 }
360 }
361
362 ok(found, "Extra assembly enumerated: %s\n", disp);
363 IAssemblyName_Release(next);
364 }
365
366 /* enumeration is exhausted */
367 next = (IAssemblyName *)0xdeadbeef;
368 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
369 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
370 ok(next == (IAssemblyName *)0xdeadbeef,
371 "Expected next to be unchanged, got %p\n", next);
372
373 LIST_FOR_EACH_SAFE(item, cursor, &assemblies)
374 {
375 ASMNAME *asmname = LIST_ENTRY(item, ASMNAME, entry);
376
377 ok(FALSE, "Assembly not enumerated: %s\n", asmname->data);
378
379 list_remove(&asmname->entry);
380 HeapFree(GetProcessHeap(), 0, asmname->data);
381 HeapFree(GetProcessHeap(), 0, asmname);
382 }
383
384 IAssemblyEnum_Release(asmenum);
385 }
386
387 static void test_enumerate_name(void)
388 {
389 IAssemblyEnum *asmenum;
390 IAssemblyName *asmname, *next;
391 WCHAR buf[MAX_PATH];
392 CHAR gac[MAX_PATH];
393 CHAR path[MAX_PATH];
394 CHAR disp[MAX_PATH];
395 WCHAR namestr[MAX_PATH];
396 CHAR exp[6][MAX_PATH];
397 HRESULT hr;
398 DWORD size;
399
400 lstrcpyA(exp[0], "wine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=16a3fcd171e93a8d");
401 lstrcpyA(exp[1], "wine, Version=1.0.1.2, Culture=neutral, PublicKeyToken=123456789abcdef0");
402 lstrcpyA(exp[2], "wine, Version=1.0.1.2, Culture=neutral, PublicKeyToken=16a3fcd171e93a8d");
403 lstrcpyA(exp[3], "Wine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=16a3fcd171e93a8d");
404 lstrcpyA(exp[4], "Wine, Version=1.0.1.2, Culture=neutral, PublicKeyToken=123456789abcdef0");
405 lstrcpyA(exp[5], "Wine, Version=1.0.1.2, Culture=neutral, PublicKeyToken=16a3fcd171e93a8d");
406
407 size = MAX_PATH;
408 hr = pGetCachePath(ASM_CACHE_GAC, buf, &size);
409 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
410
411 to_multibyte(gac, buf);
412 create_full_path(gac);
413
414 sprintf(path, "%s\\Wine", gac);
415 CreateDirectoryA(path, NULL);
416
417 sprintf(path, "%s\\Wine\\1.0.0.0__16a3fcd171e93a8d", gac);
418 CreateDirectoryA(path, NULL);
419
420 lstrcatA(path, "\\Wine.dll");
421 if (!create_file_data(path, path, 100))
422 {
423 win_skip("Failed to open file %s, skipping name enumeration tests\n", path);
424 goto done;
425 }
426
427 sprintf(path, "%s\\Wine\\1.0.1.2__16a3fcd171e93a8d", gac);
428 CreateDirectoryA(path, NULL);
429
430 lstrcatA(path, "\\Wine.dll");
431 if (!create_file_data(path, path, 100))
432 {
433 win_skip("Failed to open file %s, skipping name enumeration tests\n", path);
434 goto done;
435 }
436
437 sprintf(path, "%s\\Wine\\1.0.1.2__123456789abcdef0", gac);
438 CreateDirectoryA(path, NULL);
439
440 lstrcatA(path, "\\Wine.dll");
441 if (!create_file_data(path, path, 100))
442 {
443 win_skip("Failed to open file %s, skipping name enumeration tests\n", path);
444 goto done;
445 }
446
447 /* test case sensitivity */
448 to_widechar(namestr, "wine");
449 asmname = NULL;
450 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
451 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
452 ok(asmname != NULL, "Expected non-NULL asmname\n");
453
454 asmenum = NULL;
455 hr = pCreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL);
456 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
457 ok(asmenum != NULL, "Expected non-NULL asmenum\n");
458
459 next = NULL;
460 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
461 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
462 ok(next != NULL, "Expected non-NULL next\n");
463
464 size = MAX_PATH;
465 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
466 to_multibyte(disp, buf);
467 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
468 ok(!lstrcmpA(disp, exp[0]),
469 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[0], exp[1], disp);
470
471 IAssemblyName_Release(next);
472
473 next = NULL;
474 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
475 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
476 ok(next != NULL, "Expected non-NULL next\n");
477
478 size = MAX_PATH;
479 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
480 to_multibyte(disp, buf);
481 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
482 ok(!lstrcmpA(disp, exp[1]) ||
483 !lstrcmpA(disp, exp[2]), /* Win98 */
484 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[1], exp[2], disp);
485
486 IAssemblyName_Release(next);
487
488 next = NULL;
489 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
490 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
491 ok(next != NULL, "Expected non-NULL next\n");
492
493 size = MAX_PATH;
494 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
495 to_multibyte(disp, buf);
496 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
497 ok(!lstrcmpA(disp, exp[2]) ||
498 !lstrcmpA(disp, exp[1]), /* Win98 */
499 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[2], exp[1], disp);
500
501 IAssemblyName_Release(next);
502
503 next = (IAssemblyName *)0xdeadbeef;
504 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
505 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
506 ok(next == (IAssemblyName *)0xdeadbeef,
507 "Expected next to be unchanged, got %p\n", next);
508
509 IAssemblyEnum_Release(asmenum);
510 IAssemblyName_Release(asmname);
511
512 /* only Version */
513 to_widechar(namestr, "Wine, Version=1.0.1.2");
514 asmname = NULL;
515 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
516 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
517 ok(asmname != NULL, "Expected non-NULL asmname\n");
518
519 asmenum = NULL;
520 hr = pCreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL);
521 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
522 ok(asmenum != NULL, "Expected non-NULL asmenum\n");
523
524 next = NULL;
525 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
526 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
527 ok(next != NULL, "Expected non-NULL next\n");
528
529 size = MAX_PATH;
530 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
531 to_multibyte(disp, buf);
532 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
533 ok(!lstrcmpA(disp, exp[4]) ||
534 !lstrcmpA(disp, exp[5]), /* Win98 */
535 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[4], exp[5], disp);
536
537 IAssemblyName_Release(next);
538
539 next = NULL;
540 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
541 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
542 ok(next != NULL, "Expected non-NULL next\n");
543
544 size = MAX_PATH;
545 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
546 to_multibyte(disp, buf);
547 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
548 ok(!lstrcmpA(disp, exp[5]) ||
549 !lstrcmpA(disp, exp[4]), /* Win98 */
550 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[5], exp[4], disp);
551
552 IAssemblyName_Release(next);
553
554 next = (IAssemblyName *)0xdeadbeef;
555 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
556 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
557 ok(next == (IAssemblyName *)0xdeadbeef,
558 "Expected next to be unchanged, got %p\n", next);
559
560 IAssemblyEnum_Release(asmenum);
561 IAssemblyName_Release(asmname);
562
563 /* only PublicKeyToken */
564 to_widechar(namestr, "Wine, PublicKeyToken=16a3fcd171e93a8d");
565 asmname = NULL;
566 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
567 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
568 ok(asmname != NULL, "Expected non-NULL asmname\n");
569
570 asmenum = NULL;
571 hr = pCreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL);
572 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
573 ok(asmenum != NULL, "Expected non-NULL asmenum\n");
574
575 next = NULL;
576 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
577 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
578 ok(next != NULL, "Expected non-NULL next\n");
579
580 size = MAX_PATH;
581 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
582 to_multibyte(disp, buf);
583 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
584 ok(!lstrcmpA(disp, exp[3]), "Expected \"%s\", got \"%s\"\n", exp[3], disp);
585
586 IAssemblyName_Release(next);
587
588 next = NULL;
589 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
590 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
591 ok(next != NULL, "Expected non-NULL next\n");
592
593 size = MAX_PATH;
594 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
595 to_multibyte(disp, buf);
596 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
597 ok(!lstrcmpA(disp, exp[5]), "Expected \"%s\", got \"%s\"\n", exp[5], disp);
598
599 IAssemblyName_Release(next);
600
601 next = (IAssemblyName *)0xdeadbeef;
602 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
603 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
604 ok(next == (IAssemblyName *)0xdeadbeef,
605 "Expected next to be unchanged, got %p\n", next);
606
607 IAssemblyEnum_Release(asmenum);
608 IAssemblyName_Release(asmname);
609
610 /* only Culture */
611 to_widechar(namestr, "wine, Culture=neutral");
612 asmname = NULL;
613 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL);
614 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
615 ok(asmname != NULL, "Expected non-NULL asmname\n");
616
617 asmenum = NULL;
618 hr = pCreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL);
619 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
620 ok(asmenum != NULL, "Expected non-NULL asmenum\n");
621
622 next = NULL;
623 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
624 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
625 ok(next != NULL, "Expected non-NULL next\n");
626
627 size = MAX_PATH;
628 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
629 to_multibyte(disp, buf);
630 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
631 ok(!lstrcmpA(disp, exp[0]), "Expected \"%s\", got \"%s\"\n", exp[0], disp);
632
633 IAssemblyName_Release(next);
634
635 next = NULL;
636 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
637 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
638 ok(next != NULL, "Expected non-NULL next\n");
639
640 size = MAX_PATH;
641 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
642 to_multibyte(disp, buf);
643 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
644 ok(!lstrcmpA(disp, exp[1]) ||
645 !lstrcmpA(disp, exp[2]), /* Win98 */
646 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[1], exp[2], disp);
647
648 IAssemblyName_Release(next);
649
650 next = NULL;
651 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
652 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
653 ok(next != NULL, "Expected non-NULL next\n");
654
655 size = MAX_PATH;
656 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0);
657 to_multibyte(disp, buf);
658 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
659 ok(!lstrcmpA(disp, exp[2]) ||
660 !lstrcmpA(disp, exp[1]), /* Win98 */
661 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[2], exp[1], disp);
662
663 IAssemblyName_Release(next);
664
665 next = (IAssemblyName *)0xdeadbeef;
666 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
667 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
668 ok(next == (IAssemblyName *)0xdeadbeef,
669 "Expected next to be unchanged, got %p\n", next);
670
671 IAssemblyEnum_Release(asmenum);
672 IAssemblyName_Release(asmname);
673
674 done:
675 sprintf(path, "%s\\Wine\\1.0.0.0__16a3fcd171e93a8d\\Wine.dll", gac);
676 DeleteFileA(path);
677 sprintf(path, "%s\\Wine\\1.0.1.2__16a3fcd171e93a8d\\Wine.dll", gac);
678 DeleteFileA(path);
679 sprintf(path, "%s\\Wine\\1.0.1.2__123456789abcdef0\\Wine.dll", gac);
680 DeleteFileA(path);
681 sprintf(path, "%s\\Wine\\1.0.0.0__16a3fcd171e93a8d", gac);
682 RemoveDirectoryA(path);
683 sprintf(path, "%s\\Wine\\1.0.1.2__16a3fcd171e93a8d", gac);
684 RemoveDirectoryA(path);
685 sprintf(path, "%s\\Wine\\1.0.1.2__123456789abcdef0", gac);
686 RemoveDirectoryA(path);
687 sprintf(path, "%s\\Wine", gac);
688 RemoveDirectoryA(path);
689 }
690
691 START_TEST(asmenum)
692 {
693 if (!init_functionpointers())
694 return;
695
696 test_CreateAssemblyEnum();
697 test_enumerate();
698 test_enumerate_name();
699 }