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
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
37 #include "fusionpriv.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(fusion
);
42 const IAssemblyNameVtbl
*lpIAssemblyNameVtbl
;
60 static const WCHAR separator
[] = {',',' ',0};
61 static const WCHAR version
[] = {'V','e','r','s','i','o','n',0};
62 static const WCHAR culture
[] = {'C','u','l','t','u','r','e',0};
63 static const WCHAR pubkey
[] =
64 {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
65 static const WCHAR procarch
[] = {'p','r','o','c','e','s','s','o','r',
66 'A','r','c','h','i','t','e','c','t','u','r','e',0};
68 #define CHARS_PER_PUBKEY 16
70 static HRESULT WINAPI
IAssemblyNameImpl_QueryInterface(IAssemblyName
*iface
,
71 REFIID riid
, LPVOID
*ppobj
)
73 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
75 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppobj
);
79 if (IsEqualIID(riid
, &IID_IUnknown
) ||
80 IsEqualIID(riid
, &IID_IAssemblyName
))
82 IUnknown_AddRef(iface
);
87 WARN("(%p, %s, %p): not found\n", This
, debugstr_guid(riid
), ppobj
);
91 static ULONG WINAPI
IAssemblyNameImpl_AddRef(IAssemblyName
*iface
)
93 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
94 ULONG refCount
= InterlockedIncrement(&This
->ref
);
96 TRACE("(%p)->(ref before = %u)\n", This
, refCount
- 1);
101 static ULONG WINAPI
IAssemblyNameImpl_Release(IAssemblyName
*iface
)
103 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
104 ULONG refCount
= InterlockedDecrement(&This
->ref
);
106 TRACE("(%p)->(ref before = %u)\n", This
, refCount
+ 1);
110 HeapFree(GetProcessHeap(), 0, This
->path
);
111 HeapFree(GetProcessHeap(), 0, This
->displayname
);
112 HeapFree(GetProcessHeap(), 0, This
->name
);
113 HeapFree(GetProcessHeap(), 0, This
->culture
);
114 HeapFree(GetProcessHeap(), 0, This
);
120 static HRESULT WINAPI
IAssemblyNameImpl_SetProperty(IAssemblyName
*iface
,
125 FIXME("(%p, %d, %p, %d) stub!\n", iface
, PropertyId
, pvProperty
, cbProperty
);
129 static HRESULT WINAPI
IAssemblyNameImpl_GetProperty(IAssemblyName
*iface
,
134 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
136 TRACE("(%p, %d, %p, %p)\n", iface
, PropertyId
, pvProperty
, pcbProperty
);
138 *((LPWSTR
)pvProperty
) = '\0';
142 case ASM_NAME_NULL_PUBLIC_KEY
:
143 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN
:
148 case ASM_NAME_NULL_CUSTOM
:
155 lstrcpyW(pvProperty
, name
->name
);
156 *pcbProperty
= (lstrlenW(name
->name
) + 1) * 2;
160 case ASM_NAME_MAJOR_VERSION
:
162 *((WORD
*)pvProperty
) = name
->version
[0];
163 if (name
->versize
>= 1)
164 *pcbProperty
= sizeof(WORD
);
167 case ASM_NAME_MINOR_VERSION
:
169 *((WORD
*)pvProperty
) = name
->version
[1];
170 if (name
->versize
>= 2)
171 *pcbProperty
= sizeof(WORD
);
174 case ASM_NAME_BUILD_NUMBER
:
176 *((WORD
*)pvProperty
) = name
->version
[2];
177 if (name
->versize
>= 3)
178 *pcbProperty
= sizeof(WORD
);
181 case ASM_NAME_REVISION_NUMBER
:
183 *((WORD
*)pvProperty
) = name
->version
[3];
184 if (name
->versize
>= 4)
185 *pcbProperty
= sizeof(WORD
);
188 case ASM_NAME_CULTURE
:
192 lstrcpyW(pvProperty
, name
->culture
);
193 *pcbProperty
= (lstrlenW(name
->culture
) + 1) * 2;
197 case ASM_NAME_PUBLIC_KEY_TOKEN
:
201 memcpy(pvProperty
, name
->pubkey
, sizeof(DWORD
) * 2);
202 *pcbProperty
= sizeof(DWORD
) * 2;
214 static HRESULT WINAPI
IAssemblyNameImpl_Finalize(IAssemblyName
*iface
)
216 FIXME("(%p) stub!\n", iface
);
220 static HRESULT WINAPI
IAssemblyNameImpl_GetDisplayName(IAssemblyName
*iface
,
221 LPOLESTR szDisplayName
,
222 LPDWORD pccDisplayName
,
223 DWORD dwDisplayFlags
)
225 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
228 LPWSTR cultureval
= 0;
230 static const WCHAR equals
[] = {'=',0};
232 TRACE("(%p, %p, %p, %d)\n", iface
, szDisplayName
,
233 pccDisplayName
, dwDisplayFlags
);
235 if (dwDisplayFlags
== 0)
237 if (!name
->displayname
|| !*name
->displayname
)
238 return FUSION_E_INVALID_NAME
;
240 size
= min(*pccDisplayName
, lstrlenW(name
->displayname
) + 1);
242 lstrcpynW(szDisplayName
, name
->displayname
, size
);
243 *pccDisplayName
= size
;
248 if (!name
->name
|| !*name
->name
)
249 return FUSION_E_INVALID_NAME
;
251 /* Verify buffer size is sufficient */
252 size
= lstrlenW(name
->name
) + 1;
254 if ((dwDisplayFlags
& ASM_DISPLAYF_VERSION
) && (name
->versize
> 0))
256 static const WCHAR spec
[] = {'%','d',0};
257 static const WCHAR period
[] = {'.',0};
260 wsprintfW(verstr
, spec
, name
->version
[0]);
262 for (i
= 1; i
< name
->versize
; i
++)
265 wsprintfW(value
, spec
, name
->version
[i
]);
267 lstrcatW(verstr
, period
);
268 lstrcatW(verstr
, value
);
271 size
+= lstrlenW(separator
) + lstrlenW(version
) + lstrlenW(equals
) + lstrlenW(verstr
);
274 if ((dwDisplayFlags
& ASM_DISPLAYF_CULTURE
) && (name
->culture
))
276 static const WCHAR neutral
[] = {'n','e','u','t','r','a','l', 0};
278 cultureval
= (lstrlenW(name
->culture
) == 2) ? name
->culture
: (LPWSTR
) neutral
;
279 size
+= lstrlenW(separator
) + lstrlenW(culture
) + lstrlenW(equals
) + lstrlenW(cultureval
);
282 if ((dwDisplayFlags
& ASM_DISPLAYF_PUBLIC_KEY_TOKEN
) && (name
->haspubkey
))
283 size
+= lstrlenW(separator
) + lstrlenW(pubkey
) + lstrlenW(equals
) + CHARS_PER_PUBKEY
;
285 if ((dwDisplayFlags
& ASM_DISPLAYF_PROCESSORARCHITECTURE
) && (name
->procarch
))
286 size
+= lstrlenW(separator
) + lstrlenW(procarch
) + lstrlenW(equals
) + lstrlenW(name
->procarch
);
288 if (size
> *pccDisplayName
)
291 /* Construct the string */
292 lstrcpyW(szDisplayName
, name
->name
);
294 if ((dwDisplayFlags
& ASM_DISPLAYF_VERSION
) && (name
->versize
> 0))
296 lstrcatW(szDisplayName
, separator
);
298 lstrcatW(szDisplayName
, version
);
299 lstrcatW(szDisplayName
, equals
);
300 lstrcatW(szDisplayName
, verstr
);
303 if ((dwDisplayFlags
& ASM_DISPLAYF_CULTURE
) && (name
->culture
))
305 lstrcatW(szDisplayName
, separator
);
307 lstrcatW(szDisplayName
, culture
);
308 lstrcatW(szDisplayName
, equals
);
309 lstrcatW(szDisplayName
, cultureval
);
312 if ((dwDisplayFlags
& ASM_DISPLAYF_PUBLIC_KEY_TOKEN
) && (name
->haspubkey
))
314 WCHAR pkt
[CHARS_PER_PUBKEY
+ 1];
315 static const WCHAR spec
[] = {'%','0','x','%','0','x','%','0','x',
316 '%','0','x','%','0','x','%','0','x','%','0','x','%','0','x',0};
318 lstrcatW(szDisplayName
, separator
);
320 lstrcatW(szDisplayName
, pubkey
);
321 lstrcatW(szDisplayName
, equals
);
323 wsprintfW(pkt
, spec
, name
->pubkey
[0], name
->pubkey
[1], name
->pubkey
[2],
324 name
->pubkey
[3], name
->pubkey
[4], name
->pubkey
[5], name
->pubkey
[6],
327 lstrcatW(szDisplayName
, pkt
);
330 if ((dwDisplayFlags
& ASM_DISPLAYF_PROCESSORARCHITECTURE
) && (name
->procarch
))
332 lstrcatW(szDisplayName
, separator
);
334 lstrcatW(szDisplayName
, procarch
);
335 lstrcatW(szDisplayName
, equals
);
336 lstrcatW(szDisplayName
, name
->procarch
);
339 *pccDisplayName
= size
;
343 static HRESULT WINAPI
IAssemblyNameImpl_Reserved(IAssemblyName
*iface
,
345 IUnknown
*pUnkReserved1
,
346 IUnknown
*pUnkReserved2
,
347 LPCOLESTR szReserved
,
353 TRACE("(%p, %s, %p, %p, %s, %x%08x, %p, %d, %p)\n", iface
,
354 debugstr_guid(refIID
), pUnkReserved1
, pUnkReserved2
,
355 debugstr_w(szReserved
), (DWORD
)(llReserved
>> 32), (DWORD
)llReserved
,
356 pvReserved
, cbReserved
, ppReserved
);
361 static HRESULT WINAPI
IAssemblyNameImpl_GetName(IAssemblyName
*iface
,
365 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
367 TRACE("(%p, %p, %p)\n", iface
, lpcwBuffer
, pwzName
);
376 lstrcpyW(pwzName
, name
->name
);
377 *lpcwBuffer
= lstrlenW(pwzName
) + 1;
382 static HRESULT WINAPI
IAssemblyNameImpl_GetVersion(IAssemblyName
*iface
,
383 LPDWORD pdwVersionHi
,
384 LPDWORD pdwVersionLow
)
386 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
388 TRACE("(%p, %p, %p)\n", iface
, pdwVersionHi
, pdwVersionLow
);
393 if (name
->versize
!= 4)
394 return FUSION_E_INVALID_NAME
;
396 *pdwVersionHi
= (name
->version
[0] << 16) + name
->version
[1];
397 *pdwVersionLow
= (name
->version
[2] << 16) + name
->version
[3];
402 static HRESULT WINAPI
IAssemblyNameImpl_IsEqual(IAssemblyName
*iface
,
403 IAssemblyName
*pName
,
406 FIXME("(%p, %p, %d) stub!\n", iface
, pName
, dwCmpFlags
);
410 static HRESULT WINAPI
IAssemblyNameImpl_Clone(IAssemblyName
*iface
,
411 IAssemblyName
**pName
)
413 FIXME("(%p, %p) stub!\n", iface
, pName
);
417 static const IAssemblyNameVtbl AssemblyNameVtbl
= {
418 IAssemblyNameImpl_QueryInterface
,
419 IAssemblyNameImpl_AddRef
,
420 IAssemblyNameImpl_Release
,
421 IAssemblyNameImpl_SetProperty
,
422 IAssemblyNameImpl_GetProperty
,
423 IAssemblyNameImpl_Finalize
,
424 IAssemblyNameImpl_GetDisplayName
,
425 IAssemblyNameImpl_Reserved
,
426 IAssemblyNameImpl_GetName
,
427 IAssemblyNameImpl_GetVersion
,
428 IAssemblyNameImpl_IsEqual
,
429 IAssemblyNameImpl_Clone
432 /* Internal methods */
433 HRESULT
IAssemblyName_SetPath(IAssemblyName
*iface
, LPCWSTR path
)
435 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
437 assert(name
->lpIAssemblyNameVtbl
== &AssemblyNameVtbl
);
439 name
->path
= strdupW(path
);
441 return E_OUTOFMEMORY
;
446 HRESULT
IAssemblyName_GetPath(IAssemblyName
*iface
, LPWSTR buf
, ULONG
*len
)
448 ULONG buffer_size
= *len
;
449 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
451 assert(name
->lpIAssemblyNameVtbl
== &AssemblyNameVtbl
);
459 *len
= lstrlenW(name
->path
) + 1;
461 if (*len
<= buffer_size
)
462 lstrcpyW(buf
, name
->path
);
464 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
469 static HRESULT
parse_version(IAssemblyNameImpl
*name
, LPWSTR version
)
474 for (i
= 0, beg
= version
; i
< 4; i
++)
479 end
= strchrW(beg
, '.');
481 if (end
) *end
= '\0';
482 name
->version
[i
] = atolW(beg
);
494 static HRESULT
parse_culture(IAssemblyNameImpl
*name
, LPCWSTR culture
)
496 static const WCHAR empty
[] = {0};
498 if (lstrlenW(culture
) == 2)
499 name
->culture
= strdupW(culture
);
501 name
->culture
= strdupW(empty
);
506 static BOOL
is_hex(WCHAR c
)
508 return ((c
>= 'a' && c
<= 'f') ||
509 (c
>= 'A' && c
<= 'F') ||
510 (c
>= '0' && c
<= '9'));
513 static BYTE
hextobyte(WCHAR c
)
515 if(c
>= '0' && c
<= '9')
517 if(c
>= 'A' && c
<= 'F')
519 if(c
>= 'a' && c
<= 'f')
524 static HRESULT
parse_pubkey(IAssemblyNameImpl
*name
, LPCWSTR pubkey
)
529 if (lstrlenW(pubkey
) < CHARS_PER_PUBKEY
)
530 return FUSION_E_INVALID_NAME
;
532 for (i
= 0; i
< CHARS_PER_PUBKEY
; i
++)
533 if (!is_hex(pubkey
[i
]))
534 return FUSION_E_INVALID_NAME
;
536 name
->haspubkey
= TRUE
;
538 for (i
= 0; i
< CHARS_PER_PUBKEY
; i
+= 2)
540 val
= (hextobyte(pubkey
[i
]) << 4) + hextobyte(pubkey
[i
+ 1]);
541 name
->pubkey
[i
/ 2] = val
;
547 static HRESULT
parse_display_name(IAssemblyNameImpl
*name
, LPCWSTR szAssemblyName
)
557 name
->displayname
= strdupW(szAssemblyName
);
558 if (!name
->displayname
)
559 return E_OUTOFMEMORY
;
561 str
= strdupW(szAssemblyName
);
564 return E_OUTOFMEMORY
;
566 ptr
= strchrW(str
, ',');
567 if (ptr
) *ptr
= '\0';
569 /* no ',' but ' ' only */
570 if( !ptr
&& strchrW(str
, ' ') )
572 hr
= FUSION_E_INVALID_NAME
;
576 name
->name
= strdupW(str
);
578 return E_OUTOFMEMORY
;
586 ptr
= strchrW(str
, '=');
589 hr
= FUSION_E_INVALID_NAME
;
596 hr
= FUSION_E_INVALID_NAME
;
600 if (!(ptr2
= strstrW(ptr
, separator
)))
602 if (!(ptr2
= strchrW(ptr
, '\0')))
604 hr
= FUSION_E_INVALID_NAME
;
613 while (*str
== ' ') str
++;
615 if (!lstrcmpW(str
, version
))
616 hr
= parse_version(name
, ptr
);
617 else if (!lstrcmpW(str
, culture
))
618 hr
= parse_culture(name
, ptr
);
619 else if (!lstrcmpW(str
, pubkey
))
620 hr
= parse_pubkey(name
, ptr
);
621 else if (!lstrcmpW(str
, procarch
))
623 name
->procarch
= strdupW(ptr
);
634 HeapFree(GetProcessHeap(), 0, save
);
637 HeapFree(GetProcessHeap(), 0, name
->displayname
);
638 HeapFree(GetProcessHeap(), 0, name
->name
);
643 /******************************************************************
644 * CreateAssemblyNameObject (FUSION.@)
646 HRESULT WINAPI
CreateAssemblyNameObject(LPASSEMBLYNAME
*ppAssemblyNameObj
,
647 LPCWSTR szAssemblyName
, DWORD dwFlags
,
650 IAssemblyNameImpl
*name
;
653 TRACE("(%p, %s, %08x, %p) stub!\n", ppAssemblyNameObj
,
654 debugstr_w(szAssemblyName
), dwFlags
, pvReserved
);
656 if (!ppAssemblyNameObj
)
659 if ((dwFlags
& CANOF_PARSE_DISPLAY_NAME
) &&
660 (!szAssemblyName
|| !*szAssemblyName
))
663 name
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAssemblyNameImpl
));
665 return E_OUTOFMEMORY
;
667 name
->lpIAssemblyNameVtbl
= &AssemblyNameVtbl
;
670 hr
= parse_display_name(name
, szAssemblyName
);
673 HeapFree(GetProcessHeap(), 0, name
);
677 *ppAssemblyNameObj
= (IAssemblyName
*)name
;