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
impl_from_IAssemblyName(IAssemblyName * iface)75 static inline IAssemblyNameImpl *impl_from_IAssemblyName(IAssemblyName *iface)
76 {
77 return CONTAINING_RECORD(iface, IAssemblyNameImpl, IAssemblyName_iface);
78 }
79
IAssemblyNameImpl_QueryInterface(IAssemblyName * iface,REFIID riid,LPVOID * ppobj)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
IAssemblyNameImpl_AddRef(IAssemblyName * iface)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
IAssemblyNameImpl_Release(IAssemblyName * iface)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
IAssemblyNameImpl_SetProperty(IAssemblyName * iface,DWORD PropertyId,LPVOID pvProperty,DWORD cbProperty)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
IAssemblyNameImpl_GetProperty(IAssemblyName * iface,DWORD PropertyId,LPVOID pvProperty,LPDWORD pcbProperty)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
IAssemblyNameImpl_Finalize(IAssemblyName * iface)258 static HRESULT WINAPI IAssemblyNameImpl_Finalize(IAssemblyName *iface)
259 {
260 FIXME("(%p) stub!\n", iface);
261 return E_NOTIMPL;
262 }
263
IAssemblyNameImpl_GetDisplayName(IAssemblyName * iface,LPOLESTR szDisplayName,LPDWORD pccDisplayName,DWORD dwDisplayFlags)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
IAssemblyNameImpl_Reserved(IAssemblyName * iface,REFIID refIID,IUnknown * pUnkReserved1,IUnknown * pUnkReserved2,LPCOLESTR szReserved,LONGLONG llReserved,LPVOID pvReserved,DWORD cbReserved,LPVOID * ppReserved)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
IAssemblyNameImpl_GetName(IAssemblyName * iface,LPDWORD lpcwBuffer,WCHAR * pwzName)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
IAssemblyNameImpl_GetVersion(IAssemblyName * iface,LPDWORD pdwVersionHi,LPDWORD pdwVersionLow)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
IAssemblyNameImpl_IsEqual(IAssemblyName * iface,IAssemblyName * pName,DWORD flags)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
IAssemblyNameImpl_Clone(IAssemblyName * iface,IAssemblyName ** pName)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 */
unsafe_impl_from_IAssemblyName(IAssemblyName * iface)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
IAssemblyName_SetPath(IAssemblyName * iface,LPCWSTR path)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
IAssemblyName_GetPath(IAssemblyName * iface,LPWSTR buf,ULONG * len)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
parse_version(IAssemblyNameImpl * name,LPWSTR version)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
parse_culture(IAssemblyNameImpl * name,LPCWSTR culture)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
is_hex(WCHAR c)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
hextobyte(WCHAR c)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
parse_pubkey(IAssemblyNameImpl * name,LPCWSTR pubkey)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
parse_procarch(IAssemblyNameImpl * name,LPCWSTR procarch)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
parse_value(const WCHAR * str,unsigned int len)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
parse_display_name(IAssemblyNameImpl * name,LPCWSTR szAssemblyName)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 */
CreateAssemblyNameObject(IAssemblyName ** ppAssemblyNameObj,LPCWSTR szAssemblyName,DWORD dwFlags,LPVOID pvReserved)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