1 /* 2 * IAssemblyName implementation 3 * 4 * Copyright 2008 James Hawkins 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <assert.h> 23 24 #define COBJMACROS 25 #define INITGUID 26 #ifdef __REACTOS__ 27 #define WIN32_NO_STATUS 28 #endif 29 30 #include "windef.h" 31 #include "winbase.h" 32 #include "winuser.h" 33 #include "ole2.h" 34 #include "guiddef.h" 35 #include "fusion.h" 36 #include "corerror.h" 37 #include "strsafe.h" 38 39 #include "wine/debug.h" 40 #include "fusionpriv.h" 41 42 WINE_DEFAULT_DEBUG_CHANNEL(fusion); 43 44 typedef struct { 45 IAssemblyName IAssemblyName_iface; 46 47 LPWSTR path; 48 49 LPWSTR displayname; 50 LPWSTR name; 51 LPWSTR culture; 52 LPWSTR procarch; 53 54 WORD version[4]; 55 DWORD versize; 56 57 BYTE pubkey[8]; 58 BOOL haspubkey; 59 60 PEKIND pekind; 61 62 LONG ref; 63 } IAssemblyNameImpl; 64 65 static const WCHAR separator[] = {',',' ',0}; 66 static const WCHAR version[] = {'V','e','r','s','i','o','n',0}; 67 static const WCHAR culture[] = {'C','u','l','t','u','r','e',0}; 68 static const WCHAR pubkey[] = 69 {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0}; 70 static const WCHAR procarch[] = {'p','r','o','c','e','s','s','o','r', 71 'A','r','c','h','i','t','e','c','t','u','r','e',0}; 72 73 #define CHARS_PER_PUBKEY 16 74 75 static inline IAssemblyNameImpl *impl_from_IAssemblyName(IAssemblyName *iface) 76 { 77 return CONTAINING_RECORD(iface, IAssemblyNameImpl, IAssemblyName_iface); 78 } 79 80 static HRESULT WINAPI IAssemblyNameImpl_QueryInterface(IAssemblyName *iface, 81 REFIID riid, LPVOID *ppobj) 82 { 83 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface); 84 85 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj); 86 87 *ppobj = NULL; 88 89 if (IsEqualIID(riid, &IID_IUnknown) || 90 IsEqualIID(riid, &IID_IAssemblyName)) 91 { 92 IAssemblyName_AddRef(iface); 93 *ppobj = &This->IAssemblyName_iface; 94 return S_OK; 95 } 96 97 WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj); 98 return E_NOINTERFACE; 99 } 100 101 static ULONG WINAPI IAssemblyNameImpl_AddRef(IAssemblyName *iface) 102 { 103 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface); 104 ULONG refCount = InterlockedIncrement(&This->ref); 105 106 TRACE("(%p)->(ref before = %u)\n", This, refCount - 1); 107 108 return refCount; 109 } 110 111 static ULONG WINAPI IAssemblyNameImpl_Release(IAssemblyName *iface) 112 { 113 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface); 114 ULONG refCount = InterlockedDecrement(&This->ref); 115 116 TRACE("(%p)->(ref before = %u)\n", This, refCount + 1); 117 118 if (!refCount) 119 { 120 heap_free(This->path); 121 heap_free(This->displayname); 122 heap_free(This->name); 123 heap_free(This->culture); 124 heap_free(This->procarch); 125 heap_free(This); 126 } 127 128 return refCount; 129 } 130 131 static HRESULT WINAPI IAssemblyNameImpl_SetProperty(IAssemblyName *iface, 132 DWORD PropertyId, 133 LPVOID pvProperty, 134 DWORD cbProperty) 135 { 136 FIXME("(%p, %d, %p, %d) stub!\n", iface, PropertyId, pvProperty, cbProperty); 137 return E_NOTIMPL; 138 } 139 140 static HRESULT WINAPI IAssemblyNameImpl_GetProperty(IAssemblyName *iface, 141 DWORD PropertyId, 142 LPVOID pvProperty, 143 LPDWORD pcbProperty) 144 { 145 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface); 146 DWORD size; 147 148 TRACE("(%p, %d, %p, %p)\n", iface, PropertyId, pvProperty, pcbProperty); 149 150 size = *pcbProperty; 151 switch (PropertyId) 152 { 153 case ASM_NAME_NULL_PUBLIC_KEY: 154 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN: 155 if (name->haspubkey) 156 return S_OK; 157 return S_FALSE; 158 159 case ASM_NAME_NULL_CUSTOM: 160 return S_OK; 161 162 case ASM_NAME_NAME: 163 *pcbProperty = 0; 164 if (name->name) 165 { 166 *pcbProperty = (lstrlenW(name->name) + 1) * 2; 167 if (size < *pcbProperty) 168 return STRSAFE_E_INSUFFICIENT_BUFFER; 169 lstrcpyW(pvProperty, name->name); 170 } 171 break; 172 173 case ASM_NAME_MAJOR_VERSION: 174 *pcbProperty = 0; 175 if (name->versize >= 1) 176 { 177 *pcbProperty = sizeof(WORD); 178 if (size < *pcbProperty) 179 return STRSAFE_E_INSUFFICIENT_BUFFER; 180 *((WORD *)pvProperty) = name->version[0]; 181 } 182 break; 183 184 case ASM_NAME_MINOR_VERSION: 185 *pcbProperty = 0; 186 if (name->versize >= 2) 187 { 188 *pcbProperty = sizeof(WORD); 189 if (size < *pcbProperty) 190 return STRSAFE_E_INSUFFICIENT_BUFFER; 191 *((WORD *)pvProperty) = name->version[1]; 192 } 193 break; 194 195 case ASM_NAME_BUILD_NUMBER: 196 *pcbProperty = 0; 197 if (name->versize >= 3) 198 { 199 *pcbProperty = sizeof(WORD); 200 if (size < *pcbProperty) 201 return STRSAFE_E_INSUFFICIENT_BUFFER; 202 *((WORD *)pvProperty) = name->version[2]; 203 } 204 break; 205 206 case ASM_NAME_REVISION_NUMBER: 207 *pcbProperty = 0; 208 if (name->versize >= 4) 209 { 210 *pcbProperty = sizeof(WORD); 211 if (size < *pcbProperty) 212 return STRSAFE_E_INSUFFICIENT_BUFFER; 213 *((WORD *)pvProperty) = name->version[3]; 214 } 215 break; 216 217 case ASM_NAME_CULTURE: 218 *pcbProperty = 0; 219 if (name->culture) 220 { 221 *pcbProperty = (lstrlenW(name->culture) + 1) * 2; 222 if (size < *pcbProperty) 223 return STRSAFE_E_INSUFFICIENT_BUFFER; 224 lstrcpyW(pvProperty, name->culture); 225 } 226 break; 227 228 case ASM_NAME_PUBLIC_KEY_TOKEN: 229 *pcbProperty = 0; 230 if (name->haspubkey) 231 { 232 *pcbProperty = sizeof(DWORD) * 2; 233 if (size < *pcbProperty) 234 return STRSAFE_E_INSUFFICIENT_BUFFER; 235 memcpy(pvProperty, name->pubkey, sizeof(DWORD) * 2); 236 } 237 break; 238 239 case ASM_NAME_ARCHITECTURE: 240 *pcbProperty = 0; 241 if (name->pekind != peNone) 242 { 243 *pcbProperty = sizeof(PEKIND); 244 if (size < *pcbProperty) 245 return STRSAFE_E_INSUFFICIENT_BUFFER; 246 *((PEKIND *)pvProperty) = name->pekind; 247 } 248 break; 249 250 default: 251 *pcbProperty = 0; 252 break; 253 } 254 255 return S_OK; 256 } 257 258 static HRESULT WINAPI IAssemblyNameImpl_Finalize(IAssemblyName *iface) 259 { 260 FIXME("(%p) stub!\n", iface); 261 return E_NOTIMPL; 262 } 263 264 static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface, 265 LPOLESTR szDisplayName, 266 LPDWORD pccDisplayName, 267 DWORD dwDisplayFlags) 268 { 269 static const WCHAR equals[] = {'=',0}; 270 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface); 271 WCHAR verstr[30], *cultureval = NULL; 272 DWORD size; 273 274 TRACE("(%p, %p, %p, %d)\n", iface, szDisplayName, 275 pccDisplayName, dwDisplayFlags); 276 277 if (dwDisplayFlags == 0) 278 { 279 if (!name->displayname || !*name->displayname) 280 return FUSION_E_INVALID_NAME; 281 282 size = lstrlenW(name->displayname) + 1; 283 284 if (*pccDisplayName < size) 285 { 286 *pccDisplayName = size; 287 return E_NOT_SUFFICIENT_BUFFER; 288 } 289 290 if (szDisplayName) lstrcpyW(szDisplayName, name->displayname); 291 *pccDisplayName = size; 292 293 return S_OK; 294 } 295 296 if (!name->name || !*name->name) 297 return FUSION_E_INVALID_NAME; 298 299 /* Verify buffer size is sufficient */ 300 size = lstrlenW(name->name) + 1; 301 302 if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0)) 303 { 304 static const WCHAR spec[] = {'%','d',0}; 305 static const WCHAR period[] = {'.',0}; 306 DWORD i; 307 308 wsprintfW(verstr, spec, name->version[0]); 309 310 for (i = 1; i < name->versize; i++) 311 { 312 WCHAR value[6]; 313 wsprintfW(value, spec, name->version[i]); 314 315 lstrcatW(verstr, period); 316 lstrcatW(verstr, value); 317 } 318 319 size += lstrlenW(separator) + lstrlenW(version) + lstrlenW(equals) + lstrlenW(verstr); 320 } 321 322 if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture)) 323 { 324 static const WCHAR neutral[] = {'n','e','u','t','r','a','l', 0}; 325 326 cultureval = (lstrlenW(name->culture) == 2) ? name->culture : (LPWSTR) neutral; 327 size += lstrlenW(separator) + lstrlenW(culture) + lstrlenW(equals) + lstrlenW(cultureval); 328 } 329 330 if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey)) 331 size += lstrlenW(separator) + lstrlenW(pubkey) + lstrlenW(equals) + CHARS_PER_PUBKEY; 332 333 if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch)) 334 size += lstrlenW(separator) + lstrlenW(procarch) + lstrlenW(equals) + lstrlenW(name->procarch); 335 336 if (size > *pccDisplayName) 337 { 338 *pccDisplayName = size; 339 return E_NOT_SUFFICIENT_BUFFER; 340 } 341 342 /* Construct the string */ 343 lstrcpyW(szDisplayName, name->name); 344 345 if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0)) 346 { 347 lstrcatW(szDisplayName, separator); 348 349 lstrcatW(szDisplayName, version); 350 lstrcatW(szDisplayName, equals); 351 lstrcatW(szDisplayName, verstr); 352 } 353 354 if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture)) 355 { 356 lstrcatW(szDisplayName, separator); 357 358 lstrcatW(szDisplayName, culture); 359 lstrcatW(szDisplayName, equals); 360 lstrcatW(szDisplayName, cultureval); 361 } 362 363 if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey)) 364 { 365 WCHAR pkt[CHARS_PER_PUBKEY + 1]; 366 static const WCHAR spec[] = {'%','0','2','x','%','0','2','x','%','0','2','x', 367 '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',0}; 368 369 lstrcatW(szDisplayName, separator); 370 371 lstrcatW(szDisplayName, pubkey); 372 lstrcatW(szDisplayName, equals); 373 374 wsprintfW(pkt, spec, name->pubkey[0], name->pubkey[1], name->pubkey[2], 375 name->pubkey[3], name->pubkey[4], name->pubkey[5], name->pubkey[6], 376 name->pubkey[7]); 377 378 lstrcatW(szDisplayName, pkt); 379 } 380 381 if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch)) 382 { 383 lstrcatW(szDisplayName, separator); 384 385 lstrcatW(szDisplayName, procarch); 386 lstrcatW(szDisplayName, equals); 387 lstrcatW(szDisplayName, name->procarch); 388 } 389 390 *pccDisplayName = size; 391 return S_OK; 392 } 393 394 static HRESULT WINAPI IAssemblyNameImpl_Reserved(IAssemblyName *iface, 395 REFIID refIID, 396 IUnknown *pUnkReserved1, 397 IUnknown *pUnkReserved2, 398 LPCOLESTR szReserved, 399 LONGLONG llReserved, 400 LPVOID pvReserved, 401 DWORD cbReserved, 402 LPVOID *ppReserved) 403 { 404 TRACE("(%p, %s, %p, %p, %s, %s, %p, %d, %p)\n", iface, 405 debugstr_guid(refIID), pUnkReserved1, pUnkReserved2, 406 debugstr_w(szReserved), wine_dbgstr_longlong(llReserved), 407 pvReserved, cbReserved, ppReserved); 408 409 return E_NOTIMPL; 410 } 411 412 static HRESULT WINAPI IAssemblyNameImpl_GetName(IAssemblyName *iface, 413 LPDWORD lpcwBuffer, 414 WCHAR *pwzName) 415 { 416 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface); 417 DWORD len; 418 419 TRACE("(%p, %p, %p)\n", iface, lpcwBuffer, pwzName); 420 421 if (name->name) 422 len = lstrlenW(name->name) + 1; 423 else 424 len = 0; 425 426 if (*lpcwBuffer < len) 427 { 428 *lpcwBuffer = len; 429 return E_NOT_SUFFICIENT_BUFFER; 430 } 431 if (!name->name) lpcwBuffer[0] = 0; 432 else lstrcpyW(pwzName, name->name); 433 434 *lpcwBuffer = len; 435 return S_OK; 436 } 437 438 static HRESULT WINAPI IAssemblyNameImpl_GetVersion(IAssemblyName *iface, 439 LPDWORD pdwVersionHi, 440 LPDWORD pdwVersionLow) 441 { 442 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface); 443 444 TRACE("(%p, %p, %p)\n", iface, pdwVersionHi, pdwVersionLow); 445 446 *pdwVersionHi = 0; 447 *pdwVersionLow = 0; 448 449 if (name->versize != 4) 450 return FUSION_E_INVALID_NAME; 451 452 *pdwVersionHi = (name->version[0] << 16) + name->version[1]; 453 *pdwVersionLow = (name->version[2] << 16) + name->version[3]; 454 455 return S_OK; 456 } 457 458 static HRESULT WINAPI IAssemblyNameImpl_IsEqual(IAssemblyName *iface, 459 IAssemblyName *pName, 460 DWORD flags) 461 { 462 IAssemblyNameImpl *name1 = impl_from_IAssemblyName(iface); 463 IAssemblyNameImpl *name2 = impl_from_IAssemblyName(pName); 464 465 TRACE("(%p, %p, 0x%08x)\n", iface, pName, flags); 466 467 if (!pName) return S_FALSE; 468 if (flags & ~ASM_CMPF_IL_ALL) FIXME("unsupported flags\n"); 469 470 if ((flags & ASM_CMPF_NAME) && lstrcmpW(name1->name, name2->name)) return S_FALSE; 471 if (name1->versize && name2->versize) 472 { 473 if ((flags & ASM_CMPF_MAJOR_VERSION) && 474 name1->version[0] != name2->version[0]) return S_FALSE; 475 if ((flags & ASM_CMPF_MINOR_VERSION) && 476 name1->version[1] != name2->version[1]) return S_FALSE; 477 if ((flags & ASM_CMPF_BUILD_NUMBER) && 478 name1->version[2] != name2->version[2]) return S_FALSE; 479 if ((flags & ASM_CMPF_REVISION_NUMBER) && 480 name1->version[3] != name2->version[3]) return S_FALSE; 481 } 482 if ((flags & ASM_CMPF_PUBLIC_KEY_TOKEN) && 483 name1->haspubkey && name2->haspubkey && 484 memcmp(name1->pubkey, name2->pubkey, sizeof(name1->pubkey))) return S_FALSE; 485 486 if ((flags & ASM_CMPF_CULTURE) && 487 name1->culture && name2->culture && 488 lstrcmpW(name1->culture, name2->culture)) return S_FALSE; 489 490 return S_OK; 491 } 492 493 static HRESULT WINAPI IAssemblyNameImpl_Clone(IAssemblyName *iface, 494 IAssemblyName **pName) 495 { 496 FIXME("(%p, %p) stub!\n", iface, pName); 497 return E_NOTIMPL; 498 } 499 500 static const IAssemblyNameVtbl AssemblyNameVtbl = { 501 IAssemblyNameImpl_QueryInterface, 502 IAssemblyNameImpl_AddRef, 503 IAssemblyNameImpl_Release, 504 IAssemblyNameImpl_SetProperty, 505 IAssemblyNameImpl_GetProperty, 506 IAssemblyNameImpl_Finalize, 507 IAssemblyNameImpl_GetDisplayName, 508 IAssemblyNameImpl_Reserved, 509 IAssemblyNameImpl_GetName, 510 IAssemblyNameImpl_GetVersion, 511 IAssemblyNameImpl_IsEqual, 512 IAssemblyNameImpl_Clone 513 }; 514 515 /* Internal methods */ 516 static inline IAssemblyNameImpl *unsafe_impl_from_IAssemblyName(IAssemblyName *iface) 517 { 518 assert(iface->lpVtbl == &AssemblyNameVtbl); 519 520 return impl_from_IAssemblyName(iface); 521 } 522 523 HRESULT IAssemblyName_SetPath(IAssemblyName *iface, LPCWSTR path) 524 { 525 IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface); 526 527 name->path = strdupW(path); 528 if (!name->path) 529 return E_OUTOFMEMORY; 530 531 return S_OK; 532 } 533 534 HRESULT IAssemblyName_GetPath(IAssemblyName *iface, LPWSTR buf, ULONG *len) 535 { 536 ULONG buffer_size = *len; 537 IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface); 538 539 if (!name->path) 540 return S_OK; 541 542 if (!buf) 543 buffer_size = 0; 544 545 *len = lstrlenW(name->path) + 1; 546 547 if (*len <= buffer_size) 548 lstrcpyW(buf, name->path); 549 else 550 return E_NOT_SUFFICIENT_BUFFER; 551 552 return S_OK; 553 } 554 555 static HRESULT parse_version(IAssemblyNameImpl *name, LPWSTR version) 556 { 557 LPWSTR beg, end; 558 int i; 559 560 for (i = 0, beg = version; i < 4; i++) 561 { 562 if (!*beg) 563 return S_OK; 564 565 end = wcschr(beg, '.'); 566 567 if (end) *end = '\0'; 568 name->version[i] = wcstol(beg, NULL, 10); 569 name->versize++; 570 571 if (!end && i < 3) 572 return S_OK; 573 574 beg = end + 1; 575 } 576 577 return S_OK; 578 } 579 580 static HRESULT parse_culture(IAssemblyNameImpl *name, LPCWSTR culture) 581 { 582 static const WCHAR empty[] = {0}; 583 584 if (lstrlenW(culture) == 2) 585 name->culture = strdupW(culture); 586 else 587 name->culture = strdupW(empty); 588 589 return S_OK; 590 } 591 592 static BOOL is_hex(WCHAR c) 593 { 594 return ((c >= 'a' && c <= 'f') || 595 (c >= 'A' && c <= 'F') || 596 (c >= '0' && c <= '9')); 597 } 598 599 static BYTE hextobyte(WCHAR c) 600 { 601 if(c >= '0' && c <= '9') 602 return c - '0'; 603 if(c >= 'A' && c <= 'F') 604 return c - 'A' + 10; 605 if(c >= 'a' && c <= 'f') 606 return c - 'a' + 10; 607 return 0; 608 } 609 610 static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPCWSTR pubkey) 611 { 612 int i; 613 BYTE val; 614 static const WCHAR nullstr[] = {'n','u','l','l',0}; 615 616 if(lstrcmpiW(pubkey, nullstr) == 0) 617 return FUSION_E_PRIVATE_ASM_DISALLOWED; 618 619 if (lstrlenW(pubkey) < CHARS_PER_PUBKEY) 620 return FUSION_E_INVALID_NAME; 621 622 for (i = 0; i < CHARS_PER_PUBKEY; i++) 623 if (!is_hex(pubkey[i])) 624 return FUSION_E_INVALID_NAME; 625 626 name->haspubkey = TRUE; 627 628 for (i = 0; i < CHARS_PER_PUBKEY; i += 2) 629 { 630 val = (hextobyte(pubkey[i]) << 4) + hextobyte(pubkey[i + 1]); 631 name->pubkey[i / 2] = val; 632 } 633 634 return S_OK; 635 } 636 637 static HRESULT parse_procarch(IAssemblyNameImpl *name, LPCWSTR procarch) 638 { 639 static const WCHAR msilW[] = {'m','s','i','l',0}; 640 static const WCHAR x86W[] = {'x','8','6',0}; 641 static const WCHAR ia64W[] = {'i','a','6','4',0}; 642 static const WCHAR amd64W[] = {'a','m','d','6','4',0}; 643 644 if (!lstrcmpiW(procarch, msilW)) 645 name->pekind = peMSIL; 646 else if (!lstrcmpiW(procarch, x86W)) 647 name->pekind = peI386; 648 else if (!lstrcmpiW(procarch, ia64W)) 649 name->pekind = peIA64; 650 else if (!lstrcmpiW(procarch, amd64W)) 651 name->pekind = peAMD64; 652 else 653 { 654 ERR("unrecognized architecture: %s\n", wine_dbgstr_w(procarch)); 655 return FUSION_E_INVALID_NAME; 656 } 657 658 return S_OK; 659 } 660 661 static WCHAR *parse_value( const WCHAR *str, unsigned int len ) 662 { 663 WCHAR *ret; 664 const WCHAR *p = str; 665 BOOL quoted = FALSE; 666 unsigned int i = 0; 667 668 if (!(ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL; 669 if (*p == '\"') 670 { 671 quoted = TRUE; 672 p++; 673 } 674 while (*p && *p != '\"') ret[i++] = *p++; 675 if ((quoted && *p != '\"') || (!quoted && *p == '\"')) 676 { 677 heap_free( ret ); 678 return NULL; 679 } 680 ret[i] = 0; 681 return ret; 682 } 683 684 static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyName) 685 { 686 LPWSTR str, save, ptr, ptr2, value; 687 HRESULT hr = S_OK; 688 BOOL done = FALSE; 689 690 if (!szAssemblyName) 691 return S_OK; 692 693 name->displayname = strdupW(szAssemblyName); 694 if (!name->displayname) 695 return E_OUTOFMEMORY; 696 697 str = strdupW(szAssemblyName); 698 save = str; 699 if (!str) 700 { 701 hr = E_OUTOFMEMORY; 702 goto done; 703 } 704 705 ptr = wcschr(str, ','); 706 if (ptr) *ptr = '\0'; 707 708 /* no ',' but ' ' only */ 709 if( !ptr && wcschr(str, ' ') ) 710 { 711 hr = FUSION_E_INVALID_NAME; 712 goto done; 713 } 714 715 name->name = strdupW(str); 716 if (!name->name) 717 { 718 hr = E_OUTOFMEMORY; 719 goto done; 720 } 721 722 if (!ptr) 723 goto done; 724 725 str = ptr + 1; 726 while (!done) 727 { 728 ptr = wcschr(str, '='); 729 if (!ptr) 730 { 731 hr = FUSION_E_INVALID_NAME; 732 goto done; 733 } 734 735 *(ptr++) = '\0'; 736 if (!*ptr) 737 { 738 hr = FUSION_E_INVALID_NAME; 739 goto done; 740 } 741 742 if (!(ptr2 = wcschr(ptr, ','))) 743 { 744 if (!(ptr2 = wcschr(ptr, '\0'))) 745 { 746 hr = FUSION_E_INVALID_NAME; 747 goto done; 748 } 749 750 done = TRUE; 751 } 752 753 *ptr2 = '\0'; 754 if (!(value = parse_value( ptr, ptr2 - ptr ))) 755 { 756 hr = FUSION_E_INVALID_NAME; 757 goto done; 758 } 759 while (*str == ' ') str++; 760 761 if (!lstrcmpiW(str, version)) 762 hr = parse_version( name, value ); 763 else if (!lstrcmpiW(str, culture)) 764 hr = parse_culture( name, value ); 765 else if (!lstrcmpiW(str, pubkey)) 766 hr = parse_pubkey( name, value ); 767 else if (!lstrcmpiW(str, procarch)) 768 { 769 name->procarch = value; 770 value = NULL; 771 772 hr = parse_procarch( name, name->procarch ); 773 } 774 heap_free( value ); 775 776 if (FAILED(hr)) 777 goto done; 778 779 str = ptr2 + 1; 780 } 781 782 done: 783 heap_free(save); 784 if (FAILED(hr)) 785 { 786 heap_free(name->displayname); 787 heap_free(name->name); 788 heap_free(name->culture); 789 heap_free(name->procarch); 790 } 791 return hr; 792 } 793 794 /****************************************************************** 795 * CreateAssemblyNameObject (FUSION.@) 796 */ 797 HRESULT WINAPI CreateAssemblyNameObject(IAssemblyName **ppAssemblyNameObj, 798 LPCWSTR szAssemblyName, DWORD dwFlags, 799 LPVOID pvReserved) 800 { 801 IAssemblyNameImpl *name; 802 HRESULT hr; 803 804 TRACE("(%p, %s, %08x, %p)\n", ppAssemblyNameObj, 805 debugstr_w(szAssemblyName), dwFlags, pvReserved); 806 807 if (!ppAssemblyNameObj) 808 return E_INVALIDARG; 809 810 if ((dwFlags & CANOF_PARSE_DISPLAY_NAME) && 811 (!szAssemblyName || !*szAssemblyName)) 812 return E_INVALIDARG; 813 814 if (!(name = heap_alloc_zero(sizeof(*name)))) return E_OUTOFMEMORY; 815 816 name->IAssemblyName_iface.lpVtbl = &AssemblyNameVtbl; 817 name->ref = 1; 818 819 hr = parse_display_name(name, szAssemblyName); 820 if (FAILED(hr)) 821 { 822 heap_free(name); 823 return hr; 824 } 825 826 *ppAssemblyNameObj = &name->IAssemblyName_iface; 827 828 return S_OK; 829 } 830