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
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36 #include "fusionpriv.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(fusion
);
41 const IAssemblyNameVtbl
*lpIAssemblyNameVtbl
;
57 static const WCHAR separator
[] = {',',' ',0};
58 static const WCHAR version
[] = {'V','e','r','s','i','o','n',0};
59 static const WCHAR culture
[] = {'C','u','l','t','u','r','e',0};
60 static const WCHAR pubkey
[] =
61 {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
62 static const WCHAR procarch
[] = {'p','r','o','c','e','s','s','o','r',
63 'A','r','c','h','i','t','e','c','t','u','r','e',0};
65 #define CHARS_PER_PUBKEY 16
67 static HRESULT WINAPI
IAssemblyNameImpl_QueryInterface(IAssemblyName
*iface
,
68 REFIID riid
, LPVOID
*ppobj
)
70 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
72 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppobj
);
76 if (IsEqualIID(riid
, &IID_IUnknown
) ||
77 IsEqualIID(riid
, &IID_IAssemblyName
))
79 IUnknown_AddRef(iface
);
84 WARN("(%p, %s, %p): not found\n", This
, debugstr_guid(riid
), ppobj
);
88 static ULONG WINAPI
IAssemblyNameImpl_AddRef(IAssemblyName
*iface
)
90 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
91 ULONG refCount
= InterlockedIncrement(&This
->ref
);
93 TRACE("(%p)->(ref before = %u)\n", This
, refCount
- 1);
98 static ULONG WINAPI
IAssemblyNameImpl_Release(IAssemblyName
*iface
)
100 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
101 ULONG refCount
= InterlockedDecrement(&This
->ref
);
103 TRACE("(%p)->(ref before = %u)\n", This
, refCount
+ 1);
107 HeapFree(GetProcessHeap(), 0, This
->displayname
);
108 HeapFree(GetProcessHeap(), 0, This
->name
);
109 HeapFree(GetProcessHeap(), 0, This
->culture
);
110 HeapFree(GetProcessHeap(), 0, This
);
116 static HRESULT WINAPI
IAssemblyNameImpl_SetProperty(IAssemblyName
*iface
,
121 FIXME("(%p, %d, %p, %d) stub!\n", iface
, PropertyId
, pvProperty
, cbProperty
);
125 static HRESULT WINAPI
IAssemblyNameImpl_GetProperty(IAssemblyName
*iface
,
130 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
132 TRACE("(%p, %d, %p, %p)\n", iface
, PropertyId
, pvProperty
, pcbProperty
);
134 *((LPWSTR
)pvProperty
) = '\0';
138 case ASM_NAME_NULL_PUBLIC_KEY
:
139 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN
:
144 case ASM_NAME_NULL_CUSTOM
:
151 lstrcpyW(pvProperty
, name
->name
);
152 *pcbProperty
= (lstrlenW(name
->name
) + 1) * 2;
156 case ASM_NAME_MAJOR_VERSION
:
158 *((WORD
*)pvProperty
) = name
->version
[0];
159 if (name
->versize
>= 1)
160 *pcbProperty
= sizeof(WORD
);
163 case ASM_NAME_MINOR_VERSION
:
165 *((WORD
*)pvProperty
) = name
->version
[1];
166 if (name
->versize
>= 2)
167 *pcbProperty
= sizeof(WORD
);
170 case ASM_NAME_BUILD_NUMBER
:
172 *((WORD
*)pvProperty
) = name
->version
[2];
173 if (name
->versize
>= 3)
174 *pcbProperty
= sizeof(WORD
);
177 case ASM_NAME_REVISION_NUMBER
:
179 *((WORD
*)pvProperty
) = name
->version
[3];
180 if (name
->versize
>= 4)
181 *pcbProperty
= sizeof(WORD
);
184 case ASM_NAME_CULTURE
:
188 lstrcpyW(pvProperty
, name
->culture
);
189 *pcbProperty
= (lstrlenW(name
->culture
) + 1) * 2;
193 case ASM_NAME_PUBLIC_KEY_TOKEN
:
197 memcpy(pvProperty
, name
->pubkey
, sizeof(DWORD
) * 2);
198 *pcbProperty
= sizeof(DWORD
) * 2;
210 static HRESULT WINAPI
IAssemblyNameImpl_Finalize(IAssemblyName
*iface
)
212 FIXME("(%p) stub!\n", iface
);
216 static HRESULT WINAPI
IAssemblyNameImpl_GetDisplayName(IAssemblyName
*iface
,
217 LPOLESTR szDisplayName
,
218 LPDWORD pccDisplayName
,
219 DWORD dwDisplayFlags
)
221 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
224 LPWSTR cultureval
= 0;
226 static const WCHAR equals
[] = {'=',0};
228 TRACE("(%p, %p, %p, %d)\n", iface
, szDisplayName
,
229 pccDisplayName
, dwDisplayFlags
);
231 if (dwDisplayFlags
== 0)
233 if (!name
->displayname
|| !*name
->displayname
)
234 return FUSION_E_INVALID_NAME
;
236 size
= min(*pccDisplayName
, lstrlenW(name
->displayname
) + 1);
238 lstrcpynW(szDisplayName
, name
->displayname
, size
);
239 *pccDisplayName
= size
;
244 if (!name
->name
|| !*name
->name
)
245 return FUSION_E_INVALID_NAME
;
247 /* Verify buffer size is sufficient */
248 size
= lstrlenW(name
->name
) + 1;
250 if ((dwDisplayFlags
& ASM_DISPLAYF_VERSION
) && (name
->versize
> 0))
252 static const WCHAR spec
[] = {'%','d',0};
253 static const WCHAR period
[] = {'.',0};
256 wsprintfW(verstr
, spec
, name
->version
[0]);
258 for (i
= 1; i
< name
->versize
; i
++)
261 wsprintfW(value
, spec
, name
->version
[i
]);
263 lstrcatW(verstr
, period
);
264 lstrcatW(verstr
, value
);
267 size
+= lstrlenW(separator
) + lstrlenW(version
) + lstrlenW(equals
) + lstrlenW(verstr
);
270 if ((dwDisplayFlags
& ASM_DISPLAYF_CULTURE
) && (name
->culture
))
272 static const WCHAR neutral
[] = {'n','e','u','t','r','a','l', 0};
274 cultureval
= (lstrlenW(name
->culture
) == 2) ? name
->culture
: (LPWSTR
) neutral
;
275 size
+= lstrlenW(separator
) + lstrlenW(culture
) + lstrlenW(equals
) + lstrlenW(cultureval
);
278 if ((dwDisplayFlags
& ASM_DISPLAYF_PUBLIC_KEY_TOKEN
) && (name
->haspubkey
))
279 size
+= lstrlenW(separator
) + lstrlenW(pubkey
) + lstrlenW(equals
) + CHARS_PER_PUBKEY
;
281 if ((dwDisplayFlags
& ASM_DISPLAYF_PROCESSORARCHITECTURE
) && (name
->procarch
))
282 size
+= lstrlenW(separator
) + lstrlenW(procarch
) + lstrlenW(equals
) + lstrlenW(name
->procarch
);
284 if (size
> *pccDisplayName
)
287 /* Construct the string */
288 lstrcpyW(szDisplayName
, name
->name
);
290 if ((dwDisplayFlags
& ASM_DISPLAYF_VERSION
) && (name
->versize
> 0))
292 lstrcatW(szDisplayName
, separator
);
294 lstrcatW(szDisplayName
, version
);
295 lstrcatW(szDisplayName
, equals
);
296 lstrcatW(szDisplayName
, verstr
);
299 if ((dwDisplayFlags
& ASM_DISPLAYF_CULTURE
) && (name
->culture
))
301 lstrcatW(szDisplayName
, separator
);
303 lstrcatW(szDisplayName
, culture
);
304 lstrcatW(szDisplayName
, equals
);
305 lstrcatW(szDisplayName
, cultureval
);
308 if ((dwDisplayFlags
& ASM_DISPLAYF_PUBLIC_KEY_TOKEN
) && (name
->haspubkey
))
310 WCHAR pkt
[CHARS_PER_PUBKEY
+ 1];
311 static const WCHAR spec
[] = {'%','0','x','%','0','x','%','0','x',
312 '%','0','x','%','0','x','%','0','x','%','0','x','%','0','x',0};
314 lstrcatW(szDisplayName
, separator
);
316 lstrcatW(szDisplayName
, pubkey
);
317 lstrcatW(szDisplayName
, equals
);
319 wsprintfW(pkt
, spec
, name
->pubkey
[0], name
->pubkey
[1], name
->pubkey
[2],
320 name
->pubkey
[3], name
->pubkey
[4], name
->pubkey
[5], name
->pubkey
[6],
323 lstrcatW(szDisplayName
, pkt
);
326 if ((dwDisplayFlags
& ASM_DISPLAYF_PROCESSORARCHITECTURE
) && (name
->procarch
))
328 lstrcatW(szDisplayName
, separator
);
330 lstrcatW(szDisplayName
, procarch
);
331 lstrcatW(szDisplayName
, equals
);
332 lstrcatW(szDisplayName
, name
->procarch
);
335 *pccDisplayName
= size
;
339 static HRESULT WINAPI
IAssemblyNameImpl_Reserved(IAssemblyName
*iface
,
341 IUnknown
*pUnkReserved1
,
342 IUnknown
*pUnkReserved2
,
343 LPCOLESTR szReserved
,
349 TRACE("(%p, %s, %p, %p, %s, %x%08x, %p, %d, %p)\n", iface
,
350 debugstr_guid(refIID
), pUnkReserved1
, pUnkReserved2
,
351 debugstr_w(szReserved
), (DWORD
)(llReserved
>> 32), (DWORD
)llReserved
,
352 pvReserved
, cbReserved
, ppReserved
);
357 static HRESULT WINAPI
IAssemblyNameImpl_GetName(IAssemblyName
*iface
,
361 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
363 TRACE("(%p, %p, %p)\n", iface
, lpcwBuffer
, pwzName
);
372 lstrcpyW(pwzName
, name
->name
);
373 *lpcwBuffer
= lstrlenW(pwzName
) + 1;
378 static HRESULT WINAPI
IAssemblyNameImpl_GetVersion(IAssemblyName
*iface
,
379 LPDWORD pdwVersionHi
,
380 LPDWORD pdwVersionLow
)
382 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
384 TRACE("(%p, %p, %p)\n", iface
, pdwVersionHi
, pdwVersionLow
);
389 if (name
->versize
!= 4)
390 return FUSION_E_INVALID_NAME
;
392 *pdwVersionHi
= (name
->version
[0] << 16) + name
->version
[1];
393 *pdwVersionLow
= (name
->version
[2] << 16) + name
->version
[3];
398 static HRESULT WINAPI
IAssemblyNameImpl_IsEqual(IAssemblyName
*iface
,
399 IAssemblyName
*pName
,
402 FIXME("(%p, %p, %d) stub!\n", iface
, pName
, dwCmpFlags
);
406 static HRESULT WINAPI
IAssemblyNameImpl_Clone(IAssemblyName
*iface
,
407 IAssemblyName
**pName
)
409 FIXME("(%p, %p) stub!\n", iface
, pName
);
413 static const IAssemblyNameVtbl AssemblyNameVtbl
= {
414 IAssemblyNameImpl_QueryInterface
,
415 IAssemblyNameImpl_AddRef
,
416 IAssemblyNameImpl_Release
,
417 IAssemblyNameImpl_SetProperty
,
418 IAssemblyNameImpl_GetProperty
,
419 IAssemblyNameImpl_Finalize
,
420 IAssemblyNameImpl_GetDisplayName
,
421 IAssemblyNameImpl_Reserved
,
422 IAssemblyNameImpl_GetName
,
423 IAssemblyNameImpl_GetVersion
,
424 IAssemblyNameImpl_IsEqual
,
425 IAssemblyNameImpl_Clone
428 static HRESULT
parse_version(IAssemblyNameImpl
*name
, LPWSTR version
)
433 for (i
= 0, beg
= version
; i
< 4; i
++)
438 end
= strchrW(beg
, '.');
440 if (end
) *end
= '\0';
441 name
->version
[i
] = atolW(beg
);
453 static HRESULT
parse_culture(IAssemblyNameImpl
*name
, LPWSTR culture
)
455 static const WCHAR empty
[] = {0};
457 if (lstrlenW(culture
) == 2)
458 name
->culture
= strdupW(culture
);
460 name
->culture
= strdupW(empty
);
465 static BOOL
is_hex(WCHAR c
)
467 return ((c
>= 'a' && c
<= 'f') ||
468 (c
>= 'A' && c
<= 'F') ||
469 (c
>= '0' && c
<= '9'));
472 static BYTE
hextobyte(WCHAR c
)
474 if(c
>= '0' && c
<= '9')
476 if(c
>= 'A' && c
<= 'F')
478 if(c
>= 'a' && c
<= 'f')
483 static HRESULT
parse_pubkey(IAssemblyNameImpl
*name
, LPWSTR pubkey
)
488 if (lstrlenW(pubkey
) < CHARS_PER_PUBKEY
)
489 return FUSION_E_INVALID_NAME
;
491 for (i
= 0; i
< CHARS_PER_PUBKEY
; i
++)
492 if (!is_hex(pubkey
[i
]))
493 return FUSION_E_INVALID_NAME
;
495 name
->haspubkey
= TRUE
;
497 for (i
= 0; i
< CHARS_PER_PUBKEY
; i
+= 2)
499 val
= (hextobyte(pubkey
[i
]) << 4) + hextobyte(pubkey
[i
+ 1]);
500 name
->pubkey
[i
/ 2] = val
;
506 static HRESULT
parse_display_name(IAssemblyNameImpl
*name
, LPCWSTR szAssemblyName
)
516 name
->displayname
= strdupW(szAssemblyName
);
517 if (!name
->displayname
)
518 return E_OUTOFMEMORY
;
520 str
= strdupW(szAssemblyName
);
523 return E_OUTOFMEMORY
;
525 ptr
= strstrW(str
, separator
);
526 if (ptr
) *ptr
= '\0';
527 name
->name
= strdupW(str
);
529 return E_OUTOFMEMORY
;
537 ptr
= strchrW(str
, '=');
540 hr
= FUSION_E_INVALID_NAME
;
547 hr
= FUSION_E_INVALID_NAME
;
551 if (!(ptr2
= strstrW(ptr
, separator
)))
553 if (!(ptr2
= strchrW(ptr
, '\0')))
555 hr
= FUSION_E_INVALID_NAME
;
564 while (*str
== ' ') str
++;
566 if (!lstrcmpW(str
, version
))
567 hr
= parse_version(name
, ptr
);
568 else if (!lstrcmpW(str
, culture
))
569 hr
= parse_culture(name
, ptr
);
570 else if (!lstrcmpW(str
, pubkey
))
571 hr
= parse_pubkey(name
, ptr
);
572 else if (!lstrcmpW(str
, procarch
))
574 name
->procarch
= strdupW(ptr
);
585 HeapFree(GetProcessHeap(), 0, save
);
588 HeapFree(GetProcessHeap(), 0, name
->displayname
);
589 HeapFree(GetProcessHeap(), 0, name
->name
);
594 /******************************************************************
595 * CreateAssemblyNameObject (FUSION.@)
597 HRESULT WINAPI
CreateAssemblyNameObject(LPASSEMBLYNAME
*ppAssemblyNameObj
,
598 LPCWSTR szAssemblyName
, DWORD dwFlags
,
601 IAssemblyNameImpl
*name
;
604 TRACE("(%p, %s, %08x, %p) stub!\n", ppAssemblyNameObj
,
605 debugstr_w(szAssemblyName
), dwFlags
, pvReserved
);
607 if (!ppAssemblyNameObj
)
610 if ((dwFlags
& CANOF_PARSE_DISPLAY_NAME
) &&
611 (!szAssemblyName
|| !*szAssemblyName
))
614 name
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAssemblyNameImpl
));
616 return E_OUTOFMEMORY
;
618 name
->lpIAssemblyNameVtbl
= &AssemblyNameVtbl
;
621 hr
= parse_display_name(name
, szAssemblyName
);
624 HeapFree(GetProcessHeap(), 0, name
);
628 *ppAssemblyNameObj
= (IAssemblyName
*)name
;