fusion: Fix IAssemblyNameImpl_GetDisplayName behavior on too small buffer.
[wine.git] / dlls / fusion / asmname.c
blob96345b6db05fdc6ff9c32d9b18e19065e39cc61d
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 "wine/unicode.h"
38 #include "fusionpriv.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(fusion);
42 typedef struct {
43 IAssemblyName IAssemblyName_iface;
45 LPWSTR path;
47 LPWSTR displayname;
48 LPWSTR name;
49 LPWSTR culture;
50 LPWSTR procarch;
52 WORD version[4];
53 DWORD versize;
55 BYTE pubkey[8];
56 BOOL haspubkey;
58 PEKIND pekind;
60 LONG ref;
61 } IAssemblyNameImpl;
63 static const WCHAR separator[] = {',',' ',0};
64 static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
65 static const WCHAR culture[] = {'C','u','l','t','u','r','e',0};
66 static const WCHAR pubkey[] =
67 {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
68 static const WCHAR procarch[] = {'p','r','o','c','e','s','s','o','r',
69 'A','r','c','h','i','t','e','c','t','u','r','e',0};
71 #define CHARS_PER_PUBKEY 16
73 static inline IAssemblyNameImpl *impl_from_IAssemblyName(IAssemblyName *iface)
75 return CONTAINING_RECORD(iface, IAssemblyNameImpl, IAssemblyName_iface);
78 static HRESULT WINAPI IAssemblyNameImpl_QueryInterface(IAssemblyName *iface,
79 REFIID riid, LPVOID *ppobj)
81 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
83 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
85 *ppobj = NULL;
87 if (IsEqualIID(riid, &IID_IUnknown) ||
88 IsEqualIID(riid, &IID_IAssemblyName))
90 IAssemblyName_AddRef(iface);
91 *ppobj = &This->IAssemblyName_iface;
92 return S_OK;
95 WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
96 return E_NOINTERFACE;
99 static ULONG WINAPI IAssemblyNameImpl_AddRef(IAssemblyName *iface)
101 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
102 ULONG refCount = InterlockedIncrement(&This->ref);
104 TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
106 return refCount;
109 static ULONG WINAPI IAssemblyNameImpl_Release(IAssemblyName *iface)
111 IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
112 ULONG refCount = InterlockedDecrement(&This->ref);
114 TRACE("(%p)->(ref before = %u)\n", This, refCount + 1);
116 if (!refCount)
118 HeapFree(GetProcessHeap(), 0, This->path);
119 HeapFree(GetProcessHeap(), 0, This->displayname);
120 HeapFree(GetProcessHeap(), 0, This->name);
121 HeapFree(GetProcessHeap(), 0, This->culture);
122 HeapFree(GetProcessHeap(), 0, This->procarch);
123 HeapFree(GetProcessHeap(), 0, This);
126 return refCount;
129 static HRESULT WINAPI IAssemblyNameImpl_SetProperty(IAssemblyName *iface,
130 DWORD PropertyId,
131 LPVOID pvProperty,
132 DWORD cbProperty)
134 FIXME("(%p, %d, %p, %d) stub!\n", iface, PropertyId, pvProperty, cbProperty);
135 return E_NOTIMPL;
138 static HRESULT WINAPI IAssemblyNameImpl_GetProperty(IAssemblyName *iface,
139 DWORD PropertyId,
140 LPVOID pvProperty,
141 LPDWORD pcbProperty)
143 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
144 DWORD size;
146 TRACE("(%p, %d, %p, %p)\n", iface, PropertyId, pvProperty, pcbProperty);
148 size = *pcbProperty;
149 switch (PropertyId)
151 case ASM_NAME_NULL_PUBLIC_KEY:
152 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN:
153 if (name->haspubkey)
154 return S_OK;
155 return S_FALSE;
157 case ASM_NAME_NULL_CUSTOM:
158 return S_OK;
160 case ASM_NAME_NAME:
161 *pcbProperty = 0;
162 if (name->name)
164 *pcbProperty = (lstrlenW(name->name) + 1) * 2;
165 if (size < *pcbProperty)
166 return STRSAFE_E_INSUFFICIENT_BUFFER;
167 lstrcpyW(pvProperty, name->name);
169 break;
171 case ASM_NAME_MAJOR_VERSION:
172 *pcbProperty = 0;
173 if (name->versize >= 1)
175 *pcbProperty = sizeof(WORD);
176 if (size < *pcbProperty)
177 return STRSAFE_E_INSUFFICIENT_BUFFER;
178 *((WORD *)pvProperty) = name->version[0];
180 break;
182 case ASM_NAME_MINOR_VERSION:
183 *pcbProperty = 0;
184 if (name->versize >= 2)
186 *pcbProperty = sizeof(WORD);
187 if (size < *pcbProperty)
188 return STRSAFE_E_INSUFFICIENT_BUFFER;
189 *((WORD *)pvProperty) = name->version[1];
191 break;
193 case ASM_NAME_BUILD_NUMBER:
194 *pcbProperty = 0;
195 if (name->versize >= 3)
197 *pcbProperty = sizeof(WORD);
198 if (size < *pcbProperty)
199 return STRSAFE_E_INSUFFICIENT_BUFFER;
200 *((WORD *)pvProperty) = name->version[2];
202 break;
204 case ASM_NAME_REVISION_NUMBER:
205 *pcbProperty = 0;
206 if (name->versize >= 4)
208 *pcbProperty = sizeof(WORD);
209 if (size < *pcbProperty)
210 return STRSAFE_E_INSUFFICIENT_BUFFER;
211 *((WORD *)pvProperty) = name->version[3];
213 break;
215 case ASM_NAME_CULTURE:
216 *pcbProperty = 0;
217 if (name->culture)
219 *pcbProperty = (lstrlenW(name->culture) + 1) * 2;
220 if (size < *pcbProperty)
221 return STRSAFE_E_INSUFFICIENT_BUFFER;
222 lstrcpyW(pvProperty, name->culture);
224 break;
226 case ASM_NAME_PUBLIC_KEY_TOKEN:
227 *pcbProperty = 0;
228 if (name->haspubkey)
230 *pcbProperty = sizeof(DWORD) * 2;
231 if (size < *pcbProperty)
232 return STRSAFE_E_INSUFFICIENT_BUFFER;
233 memcpy(pvProperty, name->pubkey, sizeof(DWORD) * 2);
235 break;
237 case ASM_NAME_ARCHITECTURE:
238 *pcbProperty = 0;
239 if (name->pekind != peNone)
241 *pcbProperty = sizeof(PEKIND);
242 if (size < *pcbProperty)
243 return STRSAFE_E_INSUFFICIENT_BUFFER;
244 *((PEKIND *)pvProperty) = name->pekind;
246 break;
248 default:
249 *pcbProperty = 0;
250 break;
253 return S_OK;
256 static HRESULT WINAPI IAssemblyNameImpl_Finalize(IAssemblyName *iface)
258 FIXME("(%p) stub!\n", iface);
259 return E_NOTIMPL;
262 static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface,
263 LPOLESTR szDisplayName,
264 LPDWORD pccDisplayName,
265 DWORD dwDisplayFlags)
267 static const WCHAR equals[] = {'=',0};
268 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
269 WCHAR verstr[30], *cultureval = NULL;
270 DWORD size;
272 TRACE("(%p, %p, %p, %d)\n", iface, szDisplayName,
273 pccDisplayName, dwDisplayFlags);
275 if (dwDisplayFlags == 0)
277 if (!name->displayname || !*name->displayname)
278 return FUSION_E_INVALID_NAME;
280 size = strlenW(name->displayname) + 1;
282 if (*pccDisplayName < size)
284 *pccDisplayName = size;
285 return E_NOT_SUFFICIENT_BUFFER;
288 if (szDisplayName) strcpyW(szDisplayName, name->displayname);
289 *pccDisplayName = size;
291 return S_OK;
294 if (!name->name || !*name->name)
295 return FUSION_E_INVALID_NAME;
297 /* Verify buffer size is sufficient */
298 size = lstrlenW(name->name) + 1;
300 if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0))
302 static const WCHAR spec[] = {'%','d',0};
303 static const WCHAR period[] = {'.',0};
304 DWORD i;
306 wsprintfW(verstr, spec, name->version[0]);
308 for (i = 1; i < name->versize; i++)
310 WCHAR value[6];
311 wsprintfW(value, spec, name->version[i]);
313 lstrcatW(verstr, period);
314 lstrcatW(verstr, value);
317 size += lstrlenW(separator) + lstrlenW(version) + lstrlenW(equals) + lstrlenW(verstr);
320 if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture))
322 static const WCHAR neutral[] = {'n','e','u','t','r','a','l', 0};
324 cultureval = (lstrlenW(name->culture) == 2) ? name->culture : (LPWSTR) neutral;
325 size += lstrlenW(separator) + lstrlenW(culture) + lstrlenW(equals) + lstrlenW(cultureval);
328 if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey))
329 size += lstrlenW(separator) + lstrlenW(pubkey) + lstrlenW(equals) + CHARS_PER_PUBKEY;
331 if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch))
332 size += lstrlenW(separator) + lstrlenW(procarch) + lstrlenW(equals) + lstrlenW(name->procarch);
334 if (size > *pccDisplayName)
336 *pccDisplayName = size;
337 return E_NOT_SUFFICIENT_BUFFER;
340 /* Construct the string */
341 lstrcpyW(szDisplayName, name->name);
343 if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0))
345 lstrcatW(szDisplayName, separator);
347 lstrcatW(szDisplayName, version);
348 lstrcatW(szDisplayName, equals);
349 lstrcatW(szDisplayName, verstr);
352 if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture))
354 lstrcatW(szDisplayName, separator);
356 lstrcatW(szDisplayName, culture);
357 lstrcatW(szDisplayName, equals);
358 lstrcatW(szDisplayName, cultureval);
361 if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey))
363 WCHAR pkt[CHARS_PER_PUBKEY + 1];
364 static const WCHAR spec[] = {'%','0','x','%','0','x','%','0','x',
365 '%','0','x','%','0','x','%','0','x','%','0','x','%','0','x',0};
367 lstrcatW(szDisplayName, separator);
369 lstrcatW(szDisplayName, pubkey);
370 lstrcatW(szDisplayName, equals);
372 wsprintfW(pkt, spec, name->pubkey[0], name->pubkey[1], name->pubkey[2],
373 name->pubkey[3], name->pubkey[4], name->pubkey[5], name->pubkey[6],
374 name->pubkey[7]);
376 lstrcatW(szDisplayName, pkt);
379 if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch))
381 lstrcatW(szDisplayName, separator);
383 lstrcatW(szDisplayName, procarch);
384 lstrcatW(szDisplayName, equals);
385 lstrcatW(szDisplayName, name->procarch);
388 *pccDisplayName = size;
389 return S_OK;
392 static HRESULT WINAPI IAssemblyNameImpl_Reserved(IAssemblyName *iface,
393 REFIID refIID,
394 IUnknown *pUnkReserved1,
395 IUnknown *pUnkReserved2,
396 LPCOLESTR szReserved,
397 LONGLONG llReserved,
398 LPVOID pvReserved,
399 DWORD cbReserved,
400 LPVOID *ppReserved)
402 TRACE("(%p, %s, %p, %p, %s, %s, %p, %d, %p)\n", iface,
403 debugstr_guid(refIID), pUnkReserved1, pUnkReserved2,
404 debugstr_w(szReserved), wine_dbgstr_longlong(llReserved),
405 pvReserved, cbReserved, ppReserved);
407 return E_NOTIMPL;
410 static HRESULT WINAPI IAssemblyNameImpl_GetName(IAssemblyName *iface,
411 LPDWORD lpcwBuffer,
412 WCHAR *pwzName)
414 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
415 DWORD len;
417 TRACE("(%p, %p, %p)\n", iface, lpcwBuffer, pwzName);
419 if (name->name)
420 len = strlenW(name->name) + 1;
421 else
422 len = 0;
424 if (*lpcwBuffer < len)
426 *lpcwBuffer = len;
427 return E_NOT_SUFFICIENT_BUFFER;
429 if (!name->name) lpcwBuffer[0] = 0;
430 else strcpyW(pwzName, name->name);
432 *lpcwBuffer = len;
433 return S_OK;
436 static HRESULT WINAPI IAssemblyNameImpl_GetVersion(IAssemblyName *iface,
437 LPDWORD pdwVersionHi,
438 LPDWORD pdwVersionLow)
440 IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
442 TRACE("(%p, %p, %p)\n", iface, pdwVersionHi, pdwVersionLow);
444 *pdwVersionHi = 0;
445 *pdwVersionLow = 0;
447 if (name->versize != 4)
448 return FUSION_E_INVALID_NAME;
450 *pdwVersionHi = (name->version[0] << 16) + name->version[1];
451 *pdwVersionLow = (name->version[2] << 16) + name->version[3];
453 return S_OK;
456 static HRESULT WINAPI IAssemblyNameImpl_IsEqual(IAssemblyName *iface,
457 IAssemblyName *pName,
458 DWORD flags)
460 IAssemblyNameImpl *name1 = impl_from_IAssemblyName(iface);
461 IAssemblyNameImpl *name2 = impl_from_IAssemblyName(pName);
463 TRACE("(%p, %p, 0x%08x)\n", iface, pName, flags);
465 if (!pName) return S_FALSE;
466 if (flags & ~ASM_CMPF_IL_ALL) FIXME("unsupported flags\n");
468 if ((flags & ASM_CMPF_NAME) && strcmpW(name1->name, name2->name)) return S_FALSE;
469 if (name1->versize && name2->versize)
471 if ((flags & ASM_CMPF_MAJOR_VERSION) &&
472 name1->version[0] != name2->version[0]) return S_FALSE;
473 if ((flags & ASM_CMPF_MINOR_VERSION) &&
474 name1->version[1] != name2->version[1]) return S_FALSE;
475 if ((flags & ASM_CMPF_BUILD_NUMBER) &&
476 name1->version[2] != name2->version[2]) return S_FALSE;
477 if ((flags & ASM_CMPF_REVISION_NUMBER) &&
478 name1->version[3] != name2->version[3]) return S_FALSE;
480 if ((flags & ASM_CMPF_PUBLIC_KEY_TOKEN) &&
481 name1->haspubkey && name2->haspubkey &&
482 memcmp(name1->pubkey, name2->pubkey, sizeof(name1->pubkey))) return S_FALSE;
484 if ((flags & ASM_CMPF_CULTURE) &&
485 name1->culture && name2->culture &&
486 strcmpW(name1->culture, name2->culture)) return S_FALSE;
488 return S_OK;
491 static HRESULT WINAPI IAssemblyNameImpl_Clone(IAssemblyName *iface,
492 IAssemblyName **pName)
494 FIXME("(%p, %p) stub!\n", iface, pName);
495 return E_NOTIMPL;
498 static const IAssemblyNameVtbl AssemblyNameVtbl = {
499 IAssemblyNameImpl_QueryInterface,
500 IAssemblyNameImpl_AddRef,
501 IAssemblyNameImpl_Release,
502 IAssemblyNameImpl_SetProperty,
503 IAssemblyNameImpl_GetProperty,
504 IAssemblyNameImpl_Finalize,
505 IAssemblyNameImpl_GetDisplayName,
506 IAssemblyNameImpl_Reserved,
507 IAssemblyNameImpl_GetName,
508 IAssemblyNameImpl_GetVersion,
509 IAssemblyNameImpl_IsEqual,
510 IAssemblyNameImpl_Clone
513 /* Internal methods */
514 static inline IAssemblyNameImpl *unsafe_impl_from_IAssemblyName(IAssemblyName *iface)
516 assert(iface->lpVtbl == &AssemblyNameVtbl);
518 return impl_from_IAssemblyName(iface);
521 HRESULT IAssemblyName_SetPath(IAssemblyName *iface, LPCWSTR path)
523 IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface);
525 name->path = strdupW(path);
526 if (!name->path)
527 return E_OUTOFMEMORY;
529 return S_OK;
532 HRESULT IAssemblyName_GetPath(IAssemblyName *iface, LPWSTR buf, ULONG *len)
534 ULONG buffer_size = *len;
535 IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface);
537 if (!name->path)
538 return S_OK;
540 if (!buf)
541 buffer_size = 0;
543 *len = lstrlenW(name->path) + 1;
545 if (*len <= buffer_size)
546 lstrcpyW(buf, name->path);
547 else
548 return E_NOT_SUFFICIENT_BUFFER;
550 return S_OK;
553 static HRESULT parse_version(IAssemblyNameImpl *name, LPWSTR version)
555 LPWSTR beg, end;
556 int i;
558 for (i = 0, beg = version; i < 4; i++)
560 if (!*beg)
561 return S_OK;
563 end = strchrW(beg, '.');
565 if (end) *end = '\0';
566 name->version[i] = atolW(beg);
567 name->versize++;
569 if (!end && i < 3)
570 return S_OK;
572 beg = end + 1;
575 return S_OK;
578 static HRESULT parse_culture(IAssemblyNameImpl *name, LPCWSTR culture)
580 static const WCHAR empty[] = {0};
582 if (lstrlenW(culture) == 2)
583 name->culture = strdupW(culture);
584 else
585 name->culture = strdupW(empty);
587 return S_OK;
590 static BOOL is_hex(WCHAR c)
592 return ((c >= 'a' && c <= 'f') ||
593 (c >= 'A' && c <= 'F') ||
594 (c >= '0' && c <= '9'));
597 static BYTE hextobyte(WCHAR c)
599 if(c >= '0' && c <= '9')
600 return c - '0';
601 if(c >= 'A' && c <= 'F')
602 return c - 'A' + 10;
603 if(c >= 'a' && c <= 'f')
604 return c - 'a' + 10;
605 return 0;
608 static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPCWSTR pubkey)
610 int i;
611 BYTE val;
612 static const WCHAR nullstr[] = {'n','u','l','l',0};
614 if(lstrcmpiW(pubkey, nullstr) == 0)
615 return FUSION_E_PRIVATE_ASM_DISALLOWED;
617 if (lstrlenW(pubkey) < CHARS_PER_PUBKEY)
618 return FUSION_E_INVALID_NAME;
620 for (i = 0; i < CHARS_PER_PUBKEY; i++)
621 if (!is_hex(pubkey[i]))
622 return FUSION_E_INVALID_NAME;
624 name->haspubkey = TRUE;
626 for (i = 0; i < CHARS_PER_PUBKEY; i += 2)
628 val = (hextobyte(pubkey[i]) << 4) + hextobyte(pubkey[i + 1]);
629 name->pubkey[i / 2] = val;
632 return S_OK;
635 static HRESULT parse_procarch(IAssemblyNameImpl *name, LPCWSTR procarch)
637 static const WCHAR msilW[] = {'m','s','i','l',0};
638 static const WCHAR x86W[] = {'x','8','6',0};
639 static const WCHAR ia64W[] = {'i','a','6','4',0};
640 static const WCHAR amd64W[] = {'a','m','d','6','4',0};
642 if (!lstrcmpiW(procarch, msilW))
643 name->pekind = peMSIL;
644 else if (!lstrcmpiW(procarch, x86W))
645 name->pekind = peI386;
646 else if (!lstrcmpiW(procarch, ia64W))
647 name->pekind = peIA64;
648 else if (!lstrcmpiW(procarch, amd64W))
649 name->pekind = peAMD64;
650 else
652 ERR("unrecognized architecture: %s\n", wine_dbgstr_w(procarch));
653 return FUSION_E_INVALID_NAME;
656 return S_OK;
659 static WCHAR *parse_value( const WCHAR *str, unsigned int len )
661 WCHAR *ret;
662 const WCHAR *p = str;
663 BOOL quoted = FALSE;
664 unsigned int i = 0;
666 if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return NULL;
667 if (*p == '\"')
669 quoted = TRUE;
670 p++;
672 while (*p && *p != '\"') ret[i++] = *p++;
673 if ((quoted && *p != '\"') || (!quoted && *p == '\"'))
675 HeapFree( GetProcessHeap(), 0, ret );
676 return NULL;
678 ret[i] = 0;
679 return ret;
682 static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyName)
684 LPWSTR str, save, ptr, ptr2, value;
685 HRESULT hr = S_OK;
686 BOOL done = FALSE;
688 if (!szAssemblyName)
689 return S_OK;
691 name->displayname = strdupW(szAssemblyName);
692 if (!name->displayname)
693 return E_OUTOFMEMORY;
695 str = strdupW(szAssemblyName);
696 save = str;
697 if (!str)
699 hr = E_OUTOFMEMORY;
700 goto done;
703 ptr = strchrW(str, ',');
704 if (ptr) *ptr = '\0';
706 /* no ',' but ' ' only */
707 if( !ptr && strchrW(str, ' ') )
709 hr = FUSION_E_INVALID_NAME;
710 goto done;
713 name->name = strdupW(str);
714 if (!name->name)
716 hr = E_OUTOFMEMORY;
717 goto done;
720 if (!ptr)
721 goto done;
723 str = ptr + 1;
724 while (!done)
726 ptr = strchrW(str, '=');
727 if (!ptr)
729 hr = FUSION_E_INVALID_NAME;
730 goto done;
733 *(ptr++) = '\0';
734 if (!*ptr)
736 hr = FUSION_E_INVALID_NAME;
737 goto done;
740 if (!(ptr2 = strchrW(ptr, ',')))
742 if (!(ptr2 = strchrW(ptr, '\0')))
744 hr = FUSION_E_INVALID_NAME;
745 goto done;
748 done = TRUE;
751 *ptr2 = '\0';
752 if (!(value = parse_value( ptr, ptr2 - ptr )))
754 hr = FUSION_E_INVALID_NAME;
755 goto done;
757 while (*str == ' ') str++;
759 if (!lstrcmpiW(str, version))
760 hr = parse_version( name, value );
761 else if (!lstrcmpiW(str, culture))
762 hr = parse_culture( name, value );
763 else if (!lstrcmpiW(str, pubkey))
764 hr = parse_pubkey( name, value );
765 else if (!lstrcmpiW(str, procarch))
767 name->procarch = value;
768 value = NULL;
770 hr = parse_procarch( name, name->procarch );
772 HeapFree( GetProcessHeap(), 0, value );
774 if (FAILED(hr))
775 goto done;
777 str = ptr2 + 1;
780 done:
781 HeapFree(GetProcessHeap(), 0, save);
782 if (FAILED(hr))
784 HeapFree(GetProcessHeap(), 0, name->displayname);
785 HeapFree(GetProcessHeap(), 0, name->name);
786 HeapFree(GetProcessHeap(), 0, name->culture);
787 HeapFree(GetProcessHeap(), 0, name->procarch);
789 return hr;
792 /******************************************************************
793 * CreateAssemblyNameObject (FUSION.@)
795 HRESULT WINAPI CreateAssemblyNameObject(IAssemblyName **ppAssemblyNameObj,
796 LPCWSTR szAssemblyName, DWORD dwFlags,
797 LPVOID pvReserved)
799 IAssemblyNameImpl *name;
800 HRESULT hr;
802 TRACE("(%p, %s, %08x, %p)\n", ppAssemblyNameObj,
803 debugstr_w(szAssemblyName), dwFlags, pvReserved);
805 if (!ppAssemblyNameObj)
806 return E_INVALIDARG;
808 if ((dwFlags & CANOF_PARSE_DISPLAY_NAME) &&
809 (!szAssemblyName || !*szAssemblyName))
810 return E_INVALIDARG;
812 name = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAssemblyNameImpl));
813 if (!name)
814 return E_OUTOFMEMORY;
816 name->IAssemblyName_iface.lpVtbl = &AssemblyNameVtbl;
817 name->ref = 1;
819 hr = parse_display_name(name, szAssemblyName);
820 if (FAILED(hr))
822 HeapFree(GetProcessHeap(), 0, name);
823 return hr;
826 *ppAssemblyNameObj = &name->IAssemblyName_iface;
828 return S_OK;