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