uiautomationcore: Implement UiaDisconnectProvider.
[wine.git] / dlls / fusion / asmname.c
blob1d4d588762db9e9b9743a0948e1f8a9dda73ba97
1 /*
2 * IAssemblyName implementation
4 * Copyright 2008 James Hawkins
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.
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.
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
21 #include <stdarg.h>
22 #include <assert.h>
24 #define COBJMACROS
25 #define INITGUID
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "ole2.h"
31 #include "guiddef.h"
32 #include "fusion.h"
33 #include "corerror.h"
34 #include "strsafe.h"
36 #include "wine/debug.h"
37 #include "fusionpriv.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(fusion);
41 typedef struct {
42 IAssemblyName IAssemblyName_iface;
44 LPWSTR path;
46 LPWSTR displayname;
47 LPWSTR name;
48 LPWSTR culture;
49 LPWSTR procarch;
51 WORD version[4];
52 DWORD versize;
54 BYTE pubkey[8];
55 BOOL haspubkey;
57 PEKIND pekind;
59 LONG ref;
60 } IAssemblyNameImpl;
62 static const WCHAR separator[] = {',',' ',0};
63 static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
64 static const WCHAR culture[] = {'C','u','l','t','u','r','e',0};
65 static const WCHAR pubkey[] =
66 {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
67 static const WCHAR procarch[] = {'p','r','o','c','e','s','s','o','r',
68 'A','r','c','h','i','t','e','c','t','u','r','e',0};
70 #define CHARS_PER_PUBKEY 16
72 static inline IAssemblyNameImpl *impl_from_IAssemblyName(IAssemblyName *iface)
74 return CONTAINING_RECORD(iface, IAssemblyNameImpl, IAssemblyName_iface);
77 static HRESULT WINAPI IAssemblyNameImpl_QueryInterface(IAssemblyName *iface,
78 REFIID riid, LPVOID *ppobj)
80 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
82 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
84 *ppobj = NULL;
86 if (IsEqualIID(riid, &IID_IUnknown) ||
87 IsEqualIID(riid, &IID_IAssemblyName))
89 IAssemblyName_AddRef(iface);
90 *ppobj = &This->IAssemblyName_iface;
91 return S_OK;
94 WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
95 return E_NOINTERFACE;
98 static ULONG WINAPI IAssemblyNameImpl_AddRef(IAssemblyName *iface)
100 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
101 ULONG refCount = InterlockedIncrement(&This->ref);
103 TRACE("(%p)->(ref before = %lu)\n", This, refCount - 1);
105 return refCount;
108 static ULONG WINAPI IAssemblyNameImpl_Release(IAssemblyName *iface)
110 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
111 ULONG refCount = InterlockedDecrement(&This->ref);
113 TRACE("(%p)->(ref before = %lu)\n", This, refCount + 1);
115 if (!refCount)
117 free(This->path);
118 free(This->displayname);
119 free(This->name);
120 free(This->culture);
121 free(This->procarch);
122 free(This);
125 return refCount;
128 static HRESULT WINAPI IAssemblyNameImpl_SetProperty(IAssemblyName *iface,
129 DWORD PropertyId,
130 LPVOID pvProperty,
131 DWORD cbProperty)
133 FIXME("(%p, %ld, %p, %ld) stub!\n", iface, PropertyId, pvProperty, cbProperty);
134 return E_NOTIMPL;
137 static HRESULT WINAPI IAssemblyNameImpl_GetProperty(IAssemblyName *iface,
138 DWORD PropertyId,
139 LPVOID pvProperty,
140 LPDWORD pcbProperty)
142 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
143 DWORD size;
145 TRACE("(%p, %ld, %p, %p)\n", iface, PropertyId, pvProperty, pcbProperty);
147 size = *pcbProperty;
148 switch (PropertyId)
150 case ASM_NAME_NULL_PUBLIC_KEY:
151 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN:
152 if (name->haspubkey)
153 return S_OK;
154 return S_FALSE;
156 case ASM_NAME_NULL_CUSTOM:
157 return S_OK;
159 case ASM_NAME_NAME:
160 *pcbProperty = 0;
161 if (name->name)
163 *pcbProperty = (lstrlenW(name->name) + 1) * 2;
164 if (size < *pcbProperty)
165 return STRSAFE_E_INSUFFICIENT_BUFFER;
166 lstrcpyW(pvProperty, name->name);
168 break;
170 case ASM_NAME_MAJOR_VERSION:
171 *pcbProperty = 0;
172 if (name->versize >= 1)
174 *pcbProperty = sizeof(WORD);
175 if (size < *pcbProperty)
176 return STRSAFE_E_INSUFFICIENT_BUFFER;
177 *((WORD *)pvProperty) = name->version[0];
179 break;
181 case ASM_NAME_MINOR_VERSION:
182 *pcbProperty = 0;
183 if (name->versize >= 2)
185 *pcbProperty = sizeof(WORD);
186 if (size < *pcbProperty)
187 return STRSAFE_E_INSUFFICIENT_BUFFER;
188 *((WORD *)pvProperty) = name->version[1];
190 break;
192 case ASM_NAME_BUILD_NUMBER:
193 *pcbProperty = 0;
194 if (name->versize >= 3)
196 *pcbProperty = sizeof(WORD);
197 if (size < *pcbProperty)
198 return STRSAFE_E_INSUFFICIENT_BUFFER;
199 *((WORD *)pvProperty) = name->version[2];
201 break;
203 case ASM_NAME_REVISION_NUMBER:
204 *pcbProperty = 0;
205 if (name->versize >= 4)
207 *pcbProperty = sizeof(WORD);
208 if (size < *pcbProperty)
209 return STRSAFE_E_INSUFFICIENT_BUFFER;
210 *((WORD *)pvProperty) = name->version[3];
212 break;
214 case ASM_NAME_CULTURE:
215 *pcbProperty = 0;
216 if (name->culture)
218 *pcbProperty = (lstrlenW(name->culture) + 1) * 2;
219 if (size < *pcbProperty)
220 return STRSAFE_E_INSUFFICIENT_BUFFER;
221 lstrcpyW(pvProperty, name->culture);
223 break;
225 case ASM_NAME_PUBLIC_KEY_TOKEN:
226 *pcbProperty = 0;
227 if (name->haspubkey)
229 *pcbProperty = sizeof(DWORD) * 2;
230 if (size < *pcbProperty)
231 return STRSAFE_E_INSUFFICIENT_BUFFER;
232 memcpy(pvProperty, name->pubkey, sizeof(DWORD) * 2);
234 break;
236 case ASM_NAME_ARCHITECTURE:
237 *pcbProperty = 0;
238 if (name->pekind != peNone)
240 *pcbProperty = sizeof(PEKIND);
241 if (size < *pcbProperty)
242 return STRSAFE_E_INSUFFICIENT_BUFFER;
243 *((PEKIND *)pvProperty) = name->pekind;
245 break;
247 default:
248 *pcbProperty = 0;
249 break;
252 return S_OK;
255 static HRESULT WINAPI IAssemblyNameImpl_Finalize(IAssemblyName *iface)
257 FIXME("(%p) stub!\n", iface);
258 return E_NOTIMPL;
261 static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface,
262 LPOLESTR szDisplayName,
263 LPDWORD pccDisplayName,
264 DWORD dwDisplayFlags)
266 static const WCHAR equals[] = {'=',0};
267 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
268 WCHAR verstr[30], *cultureval = NULL;
269 DWORD size;
271 TRACE("(%p, %p, %p, %ld)\n", iface, szDisplayName,
272 pccDisplayName, dwDisplayFlags);
274 if (dwDisplayFlags == 0)
276 if (!name->displayname || !*name->displayname)
277 return FUSION_E_INVALID_NAME;
279 size = lstrlenW(name->displayname) + 1;
281 if (*pccDisplayName < size)
283 *pccDisplayName = size;
284 return E_NOT_SUFFICIENT_BUFFER;
287 if (szDisplayName) lstrcpyW(szDisplayName, name->displayname);
288 *pccDisplayName = size;
290 return S_OK;
293 if (!name->name || !*name->name)
294 return FUSION_E_INVALID_NAME;
296 /* Verify buffer size is sufficient */
297 size = lstrlenW(name->name) + 1;
299 if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0))
301 static const WCHAR spec[] = {'%','d',0};
302 static const WCHAR period[] = {'.',0};
303 DWORD i;
305 wsprintfW(verstr, spec, name->version[0]);
307 for (i = 1; i < name->versize; i++)
309 WCHAR value[6];
310 wsprintfW(value, spec, name->version[i]);
312 lstrcatW(verstr, period);
313 lstrcatW(verstr, value);
316 size += lstrlenW(separator) + lstrlenW(version) + lstrlenW(equals) + lstrlenW(verstr);
319 if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture))
321 static const WCHAR neutral[] = {'n','e','u','t','r','a','l', 0};
323 cultureval = (lstrlenW(name->culture) == 2) ? name->culture : (LPWSTR) neutral;
324 size += lstrlenW(separator) + lstrlenW(culture) + lstrlenW(equals) + lstrlenW(cultureval);
327 if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey))
328 size += lstrlenW(separator) + lstrlenW(pubkey) + lstrlenW(equals) + CHARS_PER_PUBKEY;
330 if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch))
331 size += lstrlenW(separator) + lstrlenW(procarch) + lstrlenW(equals) + lstrlenW(name->procarch);
333 if (size > *pccDisplayName)
335 *pccDisplayName = size;
336 return E_NOT_SUFFICIENT_BUFFER;
339 /* Construct the string */
340 lstrcpyW(szDisplayName, name->name);
342 if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0))
344 lstrcatW(szDisplayName, separator);
346 lstrcatW(szDisplayName, version);
347 lstrcatW(szDisplayName, equals);
348 lstrcatW(szDisplayName, verstr);
351 if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture))
353 lstrcatW(szDisplayName, separator);
355 lstrcatW(szDisplayName, culture);
356 lstrcatW(szDisplayName, equals);
357 lstrcatW(szDisplayName, cultureval);
360 if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey))
362 WCHAR pkt[CHARS_PER_PUBKEY + 1];
363 static const WCHAR spec[] = {'%','0','2','x','%','0','2','x','%','0','2','x',
364 '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',0};
366 lstrcatW(szDisplayName, separator);
368 lstrcatW(szDisplayName, pubkey);
369 lstrcatW(szDisplayName, equals);
371 wsprintfW(pkt, spec, name->pubkey[0], name->pubkey[1], name->pubkey[2],
372 name->pubkey[3], name->pubkey[4], name->pubkey[5], name->pubkey[6],
373 name->pubkey[7]);
375 lstrcatW(szDisplayName, pkt);
378 if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch))
380 lstrcatW(szDisplayName, separator);
382 lstrcatW(szDisplayName, procarch);
383 lstrcatW(szDisplayName, equals);
384 lstrcatW(szDisplayName, name->procarch);
387 *pccDisplayName = size;
388 return S_OK;
391 static HRESULT WINAPI IAssemblyNameImpl_Reserved(IAssemblyName *iface,
392 REFIID refIID,
393 IUnknown *pUnkReserved1,
394 IUnknown *pUnkReserved2,
395 LPCOLESTR szReserved,
396 LONGLONG llReserved,
397 LPVOID pvReserved,
398 DWORD cbReserved,
399 LPVOID *ppReserved)
401 TRACE("(%p, %s, %p, %p, %s, %s, %p, %ld, %p)\n", iface,
402 debugstr_guid(refIID), pUnkReserved1, pUnkReserved2,
403 debugstr_w(szReserved), wine_dbgstr_longlong(llReserved),
404 pvReserved, cbReserved, ppReserved);
406 return E_NOTIMPL;
409 static HRESULT WINAPI IAssemblyNameImpl_GetName(IAssemblyName *iface,
410 LPDWORD lpcwBuffer,
411 WCHAR *pwzName)
413 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
414 DWORD len;
416 TRACE("(%p, %p, %p)\n", iface, lpcwBuffer, pwzName);
418 if (name->name)
419 len = lstrlenW(name->name) + 1;
420 else
421 len = 0;
423 if (*lpcwBuffer < len)
425 *lpcwBuffer = len;
426 return E_NOT_SUFFICIENT_BUFFER;
428 if (!name->name) lpcwBuffer[0] = 0;
429 else lstrcpyW(pwzName, name->name);
431 *lpcwBuffer = len;
432 return S_OK;
435 static HRESULT WINAPI IAssemblyNameImpl_GetVersion(IAssemblyName *iface,
436 LPDWORD pdwVersionHi,
437 LPDWORD pdwVersionLow)
439 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
441 TRACE("(%p, %p, %p)\n", iface, pdwVersionHi, pdwVersionLow);
443 *pdwVersionHi = 0;
444 *pdwVersionLow = 0;
446 if (name->versize != 4)
447 return FUSION_E_INVALID_NAME;
449 *pdwVersionHi = (name->version[0] << 16) + name->version[1];
450 *pdwVersionLow = (name->version[2] << 16) + name->version[3];
452 return S_OK;
455 static HRESULT WINAPI IAssemblyNameImpl_IsEqual(IAssemblyName *iface,
456 IAssemblyName *pName,
457 DWORD flags)
459 IAssemblyNameImpl *name1 = impl_from_IAssemblyName(iface);
460 IAssemblyNameImpl *name2 = impl_from_IAssemblyName(pName);
462 TRACE("(%p, %p, 0x%08lx)\n", iface, pName, flags);
464 if (!pName) return S_FALSE;
465 if (flags & ~ASM_CMPF_IL_ALL) FIXME("unsupported flags\n");
467 if ((flags & ASM_CMPF_NAME) && lstrcmpW(name1->name, name2->name)) return S_FALSE;
468 if (name1->versize && name2->versize)
470 if ((flags & ASM_CMPF_MAJOR_VERSION) &&
471 name1->version[0] != name2->version[0]) return S_FALSE;
472 if ((flags & ASM_CMPF_MINOR_VERSION) &&
473 name1->version[1] != name2->version[1]) return S_FALSE;
474 if ((flags & ASM_CMPF_BUILD_NUMBER) &&
475 name1->version[2] != name2->version[2]) return S_FALSE;
476 if ((flags & ASM_CMPF_REVISION_NUMBER) &&
477 name1->version[3] != name2->version[3]) return S_FALSE;
479 if ((flags & ASM_CMPF_PUBLIC_KEY_TOKEN) &&
480 name1->haspubkey && name2->haspubkey &&
481 memcmp(name1->pubkey, name2->pubkey, sizeof(name1->pubkey))) return S_FALSE;
483 if ((flags & ASM_CMPF_CULTURE) &&
484 name1->culture && name2->culture &&
485 lstrcmpW(name1->culture, name2->culture)) return S_FALSE;
487 return S_OK;
490 static HRESULT WINAPI IAssemblyNameImpl_Clone(IAssemblyName *iface,
491 IAssemblyName **pName)
493 FIXME("(%p, %p) stub!\n", iface, pName);
494 return E_NOTIMPL;
497 static const IAssemblyNameVtbl AssemblyNameVtbl = {
498 IAssemblyNameImpl_QueryInterface,
499 IAssemblyNameImpl_AddRef,
500 IAssemblyNameImpl_Release,
501 IAssemblyNameImpl_SetProperty,
502 IAssemblyNameImpl_GetProperty,
503 IAssemblyNameImpl_Finalize,
504 IAssemblyNameImpl_GetDisplayName,
505 IAssemblyNameImpl_Reserved,
506 IAssemblyNameImpl_GetName,
507 IAssemblyNameImpl_GetVersion,
508 IAssemblyNameImpl_IsEqual,
509 IAssemblyNameImpl_Clone
512 /* Internal methods */
513 static inline IAssemblyNameImpl *unsafe_impl_from_IAssemblyName(IAssemblyName *iface)
515 assert(iface->lpVtbl == &AssemblyNameVtbl);
517 return impl_from_IAssemblyName(iface);
520 HRESULT IAssemblyName_SetPath(IAssemblyName *iface, LPCWSTR path)
522 IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface);
524 name->path = wcsdup(path);
525 if (!name->path)
526 return E_OUTOFMEMORY;
528 return S_OK;
531 HRESULT IAssemblyName_GetPath(IAssemblyName *iface, LPWSTR buf, ULONG *len)
533 ULONG buffer_size = *len;
534 IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface);
536 if (!name->path)
537 return S_OK;
539 if (!buf)
540 buffer_size = 0;
542 *len = lstrlenW(name->path) + 1;
544 if (*len <= buffer_size)
545 lstrcpyW(buf, name->path);
546 else
547 return E_NOT_SUFFICIENT_BUFFER;
549 return S_OK;
552 static HRESULT parse_version(IAssemblyNameImpl *name, LPWSTR version)
554 LPWSTR beg, end;
555 int i;
557 for (i = 0, beg = version; i < 4; i++)
559 if (!*beg)
560 return S_OK;
562 end = wcschr(beg, '.');
564 if (end) *end = '\0';
565 name->version[i] = wcstol(beg, NULL, 10);
566 name->versize++;
568 if (!end && i < 3)
569 return S_OK;
571 beg = end + 1;
574 return S_OK;
577 static HRESULT parse_culture(IAssemblyNameImpl *name, LPCWSTR culture)
579 if (lstrlenW(culture) == 2)
580 name->culture = wcsdup(culture);
581 else
582 name->culture = wcsdup(L"");
584 return S_OK;
587 static BOOL is_hex(WCHAR c)
589 return ((c >= 'a' && c <= 'f') ||
590 (c >= 'A' && c <= 'F') ||
591 (c >= '0' && c <= '9'));
594 static BYTE hextobyte(WCHAR c)
596 if(c >= '0' && c <= '9')
597 return c - '0';
598 if(c >= 'A' && c <= 'F')
599 return c - 'A' + 10;
600 if(c >= 'a' && c <= 'f')
601 return c - 'a' + 10;
602 return 0;
605 static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPCWSTR pubkey)
607 int i;
608 BYTE val;
609 static const WCHAR nullstr[] = {'n','u','l','l',0};
611 if(lstrcmpiW(pubkey, nullstr) == 0)
612 return FUSION_E_PRIVATE_ASM_DISALLOWED;
614 if (lstrlenW(pubkey) < CHARS_PER_PUBKEY)
615 return FUSION_E_INVALID_NAME;
617 for (i = 0; i < CHARS_PER_PUBKEY; i++)
618 if (!is_hex(pubkey[i]))
619 return FUSION_E_INVALID_NAME;
621 name->haspubkey = TRUE;
623 for (i = 0; i < CHARS_PER_PUBKEY; i += 2)
625 val = (hextobyte(pubkey[i]) << 4) + hextobyte(pubkey[i + 1]);
626 name->pubkey[i / 2] = val;
629 return S_OK;
632 static HRESULT parse_procarch(IAssemblyNameImpl *name, LPCWSTR procarch)
634 static const WCHAR msilW[] = {'m','s','i','l',0};
635 static const WCHAR x86W[] = {'x','8','6',0};
636 static const WCHAR ia64W[] = {'i','a','6','4',0};
637 static const WCHAR amd64W[] = {'a','m','d','6','4',0};
639 if (!lstrcmpiW(procarch, msilW))
640 name->pekind = peMSIL;
641 else if (!lstrcmpiW(procarch, x86W))
642 name->pekind = peI386;
643 else if (!lstrcmpiW(procarch, ia64W))
644 name->pekind = peIA64;
645 else if (!lstrcmpiW(procarch, amd64W))
646 name->pekind = peAMD64;
647 else
649 ERR("unrecognized architecture: %s\n", wine_dbgstr_w(procarch));
650 return FUSION_E_INVALID_NAME;
653 return S_OK;
656 static WCHAR *parse_value( const WCHAR *str, unsigned int len )
658 WCHAR *ret;
659 const WCHAR *p = str;
660 BOOL quoted = FALSE;
661 unsigned int i = 0;
663 if (!(ret = malloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
664 if (*p == '\"')
666 quoted = TRUE;
667 p++;
669 while (*p && *p != '\"') ret[i++] = *p++;
670 if ((quoted && *p != '\"') || (!quoted && *p == '\"'))
672 free( ret );
673 return NULL;
675 ret[i] = 0;
676 return ret;
679 static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyName)
681 LPWSTR str, save, ptr, ptr2, value;
682 HRESULT hr = S_OK;
683 BOOL done = FALSE;
685 if (!szAssemblyName)
686 return S_OK;
688 name->displayname = wcsdup(szAssemblyName);
689 if (!name->displayname)
690 return E_OUTOFMEMORY;
692 str = wcsdup(szAssemblyName);
693 save = str;
694 if (!str)
696 hr = E_OUTOFMEMORY;
697 goto done;
700 ptr = wcschr(str, ',');
701 if (ptr) *ptr = '\0';
703 /* no ',' but ' ' only */
704 if( !ptr && wcschr(str, ' ') )
706 hr = FUSION_E_INVALID_NAME;
707 goto done;
710 name->name = wcsdup(str);
711 if (!name->name)
713 hr = E_OUTOFMEMORY;
714 goto done;
717 if (!ptr)
718 goto done;
720 str = ptr + 1;
721 while (!done)
723 ptr = wcschr(str, '=');
724 if (!ptr)
726 hr = FUSION_E_INVALID_NAME;
727 goto done;
730 *(ptr++) = '\0';
731 if (!*ptr)
733 hr = FUSION_E_INVALID_NAME;
734 goto done;
737 if (!(ptr2 = wcschr(ptr, ',')))
739 if (!(ptr2 = wcschr(ptr, '\0')))
741 hr = FUSION_E_INVALID_NAME;
742 goto done;
745 done = TRUE;
748 *ptr2 = '\0';
749 if (!(value = parse_value( ptr, ptr2 - ptr )))
751 hr = FUSION_E_INVALID_NAME;
752 goto done;
754 while (*str == ' ') str++;
756 if (!lstrcmpiW(str, version))
757 hr = parse_version( name, value );
758 else if (!lstrcmpiW(str, culture))
759 hr = parse_culture( name, value );
760 else if (!lstrcmpiW(str, pubkey))
761 hr = parse_pubkey( name, value );
762 else if (!lstrcmpiW(str, procarch))
764 name->procarch = value;
765 value = NULL;
767 hr = parse_procarch( name, name->procarch );
769 free( value );
771 if (FAILED(hr))
772 goto done;
774 str = ptr2 + 1;
777 done:
778 free(save);
779 if (FAILED(hr))
781 free(name->displayname);
782 free(name->name);
783 free(name->culture);
784 free(name->procarch);
786 return hr;
789 /******************************************************************
790 * CreateAssemblyNameObject (FUSION.@)
792 HRESULT WINAPI CreateAssemblyNameObject(IAssemblyName **ppAssemblyNameObj,
793 LPCWSTR szAssemblyName, DWORD dwFlags,
794 LPVOID pvReserved)
796 IAssemblyNameImpl *name;
797 HRESULT hr;
799 TRACE("(%p, %s, %08lx, %p)\n", ppAssemblyNameObj,
800 debugstr_w(szAssemblyName), dwFlags, pvReserved);
802 if (!ppAssemblyNameObj)
803 return E_INVALIDARG;
805 if ((dwFlags & CANOF_PARSE_DISPLAY_NAME) &&
806 (!szAssemblyName || !*szAssemblyName))
807 return E_INVALIDARG;
809 if (!(name = calloc(1, sizeof(*name)))) return E_OUTOFMEMORY;
811 name->IAssemblyName_iface.lpVtbl = &AssemblyNameVtbl;
812 name->ref = 1;
814 hr = parse_display_name(name, szAssemblyName);
815 if (FAILED(hr))
817 free(name);
818 return hr;
821 *ppAssemblyNameObj = &name->IAssemblyName_iface;
823 return S_OK;