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)(IAssemblyName **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 char data[1]; 229 } ASMNAME; 230 231 static void enum_gac_assembly_dirs(struct list *assemblies, const char *parent, char path[MAX_PATH]) 232 { 233 static const char format[] = "%s, Version=%s, Culture=%s, PublicKeyToken=%s"; 234 WIN32_FIND_DATAA ffd; 235 ASMNAME *name; 236 HANDLE hfind; 237 int len; 238 char *ptr, *end = path + strlen( path ); 239 240 lstrcpynA( end, "\\*", path + MAX_PATH - end ); 241 hfind = FindFirstFileA(path, &ffd); 242 if (hfind == INVALID_HANDLE_VALUE) return; 243 end++; 244 245 do 246 { 247 char culture[MAX_PATH]; 248 249 if (!strcmp(ffd.cFileName, ".") || !strcmp(ffd.cFileName, "..")) continue; 250 251 *end = 0; 252 /* Directories with no dll or exe will not be enumerated */ 253 snprintf(end, path + MAX_PATH - end, "%s\\%s.dll", ffd.cFileName, parent); 254 if (GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) 255 { 256 snprintf(end, path + MAX_PATH - end, "%s\\%s.exe", ffd.cFileName, parent); 257 if (GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) continue; 258 } 259 260 if (!(ptr = strchr(ffd.cFileName, '_'))) continue; 261 *ptr++ = 0; 262 263 if (*ptr != '_') 264 { 265 lstrcpyA(culture, ptr); 266 *strchr(culture, '_') = 0; 267 } 268 else 269 lstrcpyA(culture, "neutral"); 270 271 ptr = strchr(ptr, '_'); 272 ptr++; 273 len = sizeof(format) + strlen(parent) + strlen(ffd.cFileName) + strlen(culture) + strlen(ptr); 274 275 name = HeapAlloc(GetProcessHeap(), 0, offsetof( ASMNAME, data[len] )); 276 sprintf( name->data, format, parent, ffd.cFileName, culture, ptr); 277 list_add_tail(assemblies, &name->entry); 278 } while (FindNextFileA(hfind, &ffd) != 0); 279 280 FindClose(hfind); 281 } 282 283 static void enum_gac_assemblies(struct list *assemblies, char path[MAX_PATH]) 284 { 285 WIN32_FIND_DATAA ffd; 286 HANDLE hfind; 287 char *end = path + strlen( path ); 288 289 lstrcpynA( end, "\\*", path + MAX_PATH - end ); 290 hfind = FindFirstFileA(path, &ffd); 291 if (hfind == INVALID_HANDLE_VALUE) return; 292 end++; 293 294 do 295 { 296 if (!strcmp(ffd.cFileName, ".") || !strcmp(ffd.cFileName, "..")) continue; 297 lstrcpynA( end, ffd.cFileName, path + MAX_PATH - end ); 298 enum_gac_assembly_dirs( assemblies, ffd.cFileName, path ); 299 } while (FindNextFileA(hfind, &ffd) != 0); 300 301 FindClose(hfind); 302 } 303 304 static void test_enumerate(void) 305 { 306 struct list assemblies = LIST_INIT(assemblies); 307 struct list *item, *cursor; 308 IAssemblyEnum *asmenum; 309 IAssemblyName *next; 310 WCHAR buf[MAX_PATH]; 311 CHAR path[MAX_PATH]; 312 CHAR disp[MAX_PATH]; 313 HRESULT hr; 314 BOOL found; 315 DWORD size; 316 317 size = MAX_PATH; 318 hr = pGetCachePath(ASM_CACHE_GAC, buf, &size); 319 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 320 321 to_multibyte(path, buf); 322 lstrcatA(path, "_32"); 323 enum_gac_assemblies(&assemblies, path); 324 325 to_multibyte(path, buf); 326 lstrcatA(path, "_64"); 327 enum_gac_assemblies(&assemblies, path); 328 329 to_multibyte(path, buf); 330 lstrcatA(path, "_MSIL"); 331 enum_gac_assemblies(&assemblies, path); 332 333 to_multibyte(path, buf); 334 enum_gac_assemblies(&assemblies, path); 335 336 asmenum = NULL; 337 hr = pCreateAssemblyEnum(&asmenum, NULL, NULL, ASM_CACHE_GAC, NULL); 338 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 339 ok(asmenum != NULL, "Expected non-NULL asmenum\n"); 340 341 while (IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0) == S_OK) 342 { 343 size = MAX_PATH; 344 IAssemblyName_GetDisplayName(next, buf, &size, 0); 345 to_multibyte(disp, buf); 346 347 found = FALSE; 348 LIST_FOR_EACH_SAFE(item, cursor, &assemblies) 349 { 350 ASMNAME *asmname = LIST_ENTRY(item, ASMNAME, entry); 351 352 if (!lstrcmpA(asmname->data, disp)) 353 { 354 found = TRUE; 355 356 list_remove(&asmname->entry); 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); 381 } 382 383 IAssemblyEnum_Release(asmenum); 384 } 385 386 static void test_enumerate_name(void) 387 { 388 IAssemblyEnum *asmenum; 389 IAssemblyName *asmname, *next; 390 WCHAR buf[MAX_PATH]; 391 CHAR gac[MAX_PATH]; 392 CHAR path[MAX_PATH]; 393 CHAR disp[MAX_PATH]; 394 WCHAR namestr[MAX_PATH]; 395 CHAR exp[6][MAX_PATH]; 396 HRESULT hr; 397 DWORD size; 398 399 lstrcpyA(exp[0], "wine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=16a3fcd171e93a8d"); 400 lstrcpyA(exp[1], "wine, Version=1.0.1.2, Culture=neutral, PublicKeyToken=123456789abcdef0"); 401 lstrcpyA(exp[2], "wine, Version=1.0.1.2, Culture=neutral, PublicKeyToken=16a3fcd171e93a8d"); 402 lstrcpyA(exp[3], "Wine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=16a3fcd171e93a8d"); 403 lstrcpyA(exp[4], "Wine, Version=1.0.1.2, Culture=neutral, PublicKeyToken=123456789abcdef0"); 404 lstrcpyA(exp[5], "Wine, Version=1.0.1.2, Culture=neutral, PublicKeyToken=16a3fcd171e93a8d"); 405 406 size = MAX_PATH; 407 hr = pGetCachePath(ASM_CACHE_GAC, buf, &size); 408 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 409 410 to_multibyte(gac, buf); 411 create_full_path(gac); 412 413 sprintf(path, "%s\\Wine", gac); 414 CreateDirectoryA(path, NULL); 415 416 sprintf(path, "%s\\Wine\\1.0.0.0__16a3fcd171e93a8d", gac); 417 CreateDirectoryA(path, NULL); 418 419 lstrcatA(path, "\\Wine.dll"); 420 if (!create_file_data(path, path, 100)) 421 { 422 win_skip("Failed to open file %s, skipping name enumeration tests\n", path); 423 goto done; 424 } 425 426 sprintf(path, "%s\\Wine\\1.0.1.2__16a3fcd171e93a8d", gac); 427 CreateDirectoryA(path, NULL); 428 429 lstrcatA(path, "\\Wine.dll"); 430 if (!create_file_data(path, path, 100)) 431 { 432 win_skip("Failed to open file %s, skipping name enumeration tests\n", path); 433 goto done; 434 } 435 436 sprintf(path, "%s\\Wine\\1.0.1.2__123456789abcdef0", gac); 437 CreateDirectoryA(path, NULL); 438 439 lstrcatA(path, "\\Wine.dll"); 440 if (!create_file_data(path, path, 100)) 441 { 442 win_skip("Failed to open file %s, skipping name enumeration tests\n", path); 443 goto done; 444 } 445 446 /* test case sensitivity */ 447 to_widechar(namestr, "wine"); 448 asmname = NULL; 449 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL); 450 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 451 ok(asmname != NULL, "Expected non-NULL asmname\n"); 452 453 asmenum = NULL; 454 hr = pCreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL); 455 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 456 ok(asmenum != NULL, "Expected non-NULL asmenum\n"); 457 458 next = NULL; 459 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 460 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 461 ok(next != NULL, "Expected non-NULL next\n"); 462 463 size = MAX_PATH; 464 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 465 to_multibyte(disp, buf); 466 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 467 ok(!lstrcmpA(disp, exp[0]), 468 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[0], exp[1], disp); 469 470 IAssemblyName_Release(next); 471 472 next = NULL; 473 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 474 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 475 ok(next != NULL, "Expected non-NULL next\n"); 476 477 size = MAX_PATH; 478 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 479 to_multibyte(disp, buf); 480 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 481 ok(!lstrcmpA(disp, exp[1]) || 482 !lstrcmpA(disp, exp[2]), /* Win98 */ 483 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[1], exp[2], disp); 484 485 IAssemblyName_Release(next); 486 487 next = NULL; 488 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 489 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 490 ok(next != NULL, "Expected non-NULL next\n"); 491 492 size = MAX_PATH; 493 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 494 to_multibyte(disp, buf); 495 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 496 ok(!lstrcmpA(disp, exp[2]) || 497 !lstrcmpA(disp, exp[1]), /* Win98 */ 498 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[2], exp[1], disp); 499 500 IAssemblyName_Release(next); 501 502 next = (IAssemblyName *)0xdeadbeef; 503 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 504 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr); 505 ok(next == (IAssemblyName *)0xdeadbeef, 506 "Expected next to be unchanged, got %p\n", next); 507 508 IAssemblyEnum_Release(asmenum); 509 IAssemblyName_Release(asmname); 510 511 /* only Version */ 512 to_widechar(namestr, "Wine, Version=1.0.1.2"); 513 asmname = NULL; 514 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL); 515 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 516 ok(asmname != NULL, "Expected non-NULL asmname\n"); 517 518 asmenum = NULL; 519 hr = pCreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL); 520 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 521 ok(asmenum != NULL, "Expected non-NULL asmenum\n"); 522 523 next = NULL; 524 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 525 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 526 ok(next != NULL, "Expected non-NULL next\n"); 527 528 size = MAX_PATH; 529 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 530 to_multibyte(disp, buf); 531 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 532 ok(!lstrcmpA(disp, exp[4]) || 533 !lstrcmpA(disp, exp[5]), /* Win98 */ 534 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[4], exp[5], disp); 535 536 IAssemblyName_Release(next); 537 538 next = NULL; 539 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 540 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 541 ok(next != NULL, "Expected non-NULL next\n"); 542 543 size = MAX_PATH; 544 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 545 to_multibyte(disp, buf); 546 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 547 ok(!lstrcmpA(disp, exp[5]) || 548 !lstrcmpA(disp, exp[4]), /* Win98 */ 549 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[5], exp[4], disp); 550 551 IAssemblyName_Release(next); 552 553 next = (IAssemblyName *)0xdeadbeef; 554 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 555 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr); 556 ok(next == (IAssemblyName *)0xdeadbeef, 557 "Expected next to be unchanged, got %p\n", next); 558 559 IAssemblyEnum_Release(asmenum); 560 IAssemblyName_Release(asmname); 561 562 /* only PublicKeyToken */ 563 to_widechar(namestr, "Wine, PublicKeyToken=16a3fcd171e93a8d"); 564 asmname = NULL; 565 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL); 566 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 567 ok(asmname != NULL, "Expected non-NULL asmname\n"); 568 569 asmenum = NULL; 570 hr = pCreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL); 571 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 572 ok(asmenum != NULL, "Expected non-NULL asmenum\n"); 573 574 next = NULL; 575 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 576 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 577 ok(next != NULL, "Expected non-NULL next\n"); 578 579 size = MAX_PATH; 580 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 581 to_multibyte(disp, buf); 582 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 583 ok(!lstrcmpA(disp, exp[3]), "Expected \"%s\", got \"%s\"\n", exp[3], disp); 584 585 IAssemblyName_Release(next); 586 587 next = NULL; 588 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 589 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 590 ok(next != NULL, "Expected non-NULL next\n"); 591 592 size = MAX_PATH; 593 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 594 to_multibyte(disp, buf); 595 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 596 ok(!lstrcmpA(disp, exp[5]), "Expected \"%s\", got \"%s\"\n", exp[5], disp); 597 598 IAssemblyName_Release(next); 599 600 next = (IAssemblyName *)0xdeadbeef; 601 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 602 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr); 603 ok(next == (IAssemblyName *)0xdeadbeef, 604 "Expected next to be unchanged, got %p\n", next); 605 606 IAssemblyEnum_Release(asmenum); 607 IAssemblyName_Release(asmname); 608 609 /* only Culture */ 610 to_widechar(namestr, "wine, Culture=neutral"); 611 asmname = NULL; 612 hr = pCreateAssemblyNameObject(&asmname, namestr, CANOF_PARSE_DISPLAY_NAME, NULL); 613 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 614 ok(asmname != NULL, "Expected non-NULL asmname\n"); 615 616 asmenum = NULL; 617 hr = pCreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL); 618 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 619 ok(asmenum != NULL, "Expected non-NULL asmenum\n"); 620 621 next = NULL; 622 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 623 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 624 ok(next != NULL, "Expected non-NULL next\n"); 625 626 size = MAX_PATH; 627 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 628 to_multibyte(disp, buf); 629 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 630 ok(!lstrcmpA(disp, exp[0]), "Expected \"%s\", got \"%s\"\n", exp[0], disp); 631 632 IAssemblyName_Release(next); 633 634 next = NULL; 635 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 636 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 637 ok(next != NULL, "Expected non-NULL next\n"); 638 639 size = MAX_PATH; 640 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 641 to_multibyte(disp, buf); 642 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 643 ok(!lstrcmpA(disp, exp[1]) || 644 !lstrcmpA(disp, exp[2]), /* Win98 */ 645 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[1], exp[2], disp); 646 647 IAssemblyName_Release(next); 648 649 next = NULL; 650 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 651 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 652 ok(next != NULL, "Expected non-NULL next\n"); 653 654 size = MAX_PATH; 655 hr = IAssemblyName_GetDisplayName(next, buf, &size, 0); 656 to_multibyte(disp, buf); 657 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 658 ok(!lstrcmpA(disp, exp[2]) || 659 !lstrcmpA(disp, exp[1]), /* Win98 */ 660 "Expected \"%s\" or \"%s\", got \"%s\"\n", exp[2], exp[1], disp); 661 662 IAssemblyName_Release(next); 663 664 next = (IAssemblyName *)0xdeadbeef; 665 hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); 666 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr); 667 ok(next == (IAssemblyName *)0xdeadbeef, 668 "Expected next to be unchanged, got %p\n", next); 669 670 IAssemblyEnum_Release(asmenum); 671 IAssemblyName_Release(asmname); 672 673 done: 674 sprintf(path, "%s\\Wine\\1.0.0.0__16a3fcd171e93a8d\\Wine.dll", gac); 675 DeleteFileA(path); 676 sprintf(path, "%s\\Wine\\1.0.1.2__16a3fcd171e93a8d\\Wine.dll", gac); 677 DeleteFileA(path); 678 sprintf(path, "%s\\Wine\\1.0.1.2__123456789abcdef0\\Wine.dll", gac); 679 DeleteFileA(path); 680 sprintf(path, "%s\\Wine\\1.0.0.0__16a3fcd171e93a8d", gac); 681 RemoveDirectoryA(path); 682 sprintf(path, "%s\\Wine\\1.0.1.2__16a3fcd171e93a8d", gac); 683 RemoveDirectoryA(path); 684 sprintf(path, "%s\\Wine\\1.0.1.2__123456789abcdef0", gac); 685 RemoveDirectoryA(path); 686 sprintf(path, "%s\\Wine", gac); 687 RemoveDirectoryA(path); 688 } 689 690 START_TEST(asmenum) 691 { 692 if (!init_functionpointers()) 693 return; 694 695 test_CreateAssemblyEnum(); 696 test_enumerate(); 697 test_enumerate_name(); 698 } 699