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
;
56 static HRESULT WINAPI
IAssemblyNameImpl_QueryInterface(IAssemblyName
*iface
,
57 REFIID riid
, LPVOID
*ppobj
)
59 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
61 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppobj
);
65 if (IsEqualIID(riid
, &IID_IUnknown
) ||
66 IsEqualIID(riid
, &IID_IAssemblyName
))
68 IUnknown_AddRef(iface
);
73 WARN("(%p, %s, %p): not found\n", This
, debugstr_guid(riid
), ppobj
);
77 static ULONG WINAPI
IAssemblyNameImpl_AddRef(IAssemblyName
*iface
)
79 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
80 ULONG refCount
= InterlockedIncrement(&This
->ref
);
82 TRACE("(%p)->(ref before = %u)\n", This
, refCount
- 1);
87 static ULONG WINAPI
IAssemblyNameImpl_Release(IAssemblyName
*iface
)
89 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
90 ULONG refCount
= InterlockedDecrement(&This
->ref
);
92 TRACE("(%p)->(ref before = %u)\n", This
, refCount
+ 1);
96 HeapFree(GetProcessHeap(), 0, This
->displayname
);
97 HeapFree(GetProcessHeap(), 0, This
->name
);
98 HeapFree(GetProcessHeap(), 0, This
->culture
);
99 HeapFree(GetProcessHeap(), 0, This
);
105 static HRESULT WINAPI
IAssemblyNameImpl_SetProperty(IAssemblyName
*iface
,
110 FIXME("(%p, %d, %p, %d) stub!\n", iface
, PropertyId
, pvProperty
, cbProperty
);
114 static HRESULT WINAPI
IAssemblyNameImpl_GetProperty(IAssemblyName
*iface
,
119 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
121 TRACE("(%p, %d, %p, %p)\n", iface
, PropertyId
, pvProperty
, pcbProperty
);
123 *((LPWSTR
)pvProperty
) = '\0';
127 case ASM_NAME_NULL_PUBLIC_KEY
:
128 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN
:
133 case ASM_NAME_NULL_CUSTOM
:
140 lstrcpyW(pvProperty
, name
->name
);
141 *pcbProperty
= (lstrlenW(name
->name
) + 1) * 2;
145 case ASM_NAME_MAJOR_VERSION
:
147 *((WORD
*)pvProperty
) = name
->version
[0];
148 if (name
->versize
>= 1)
149 *pcbProperty
= sizeof(WORD
);
152 case ASM_NAME_MINOR_VERSION
:
154 *((WORD
*)pvProperty
) = name
->version
[1];
155 if (name
->versize
>= 2)
156 *pcbProperty
= sizeof(WORD
);
159 case ASM_NAME_BUILD_NUMBER
:
161 *((WORD
*)pvProperty
) = name
->version
[2];
162 if (name
->versize
>= 3)
163 *pcbProperty
= sizeof(WORD
);
166 case ASM_NAME_REVISION_NUMBER
:
168 *((WORD
*)pvProperty
) = name
->version
[3];
169 if (name
->versize
>= 4)
170 *pcbProperty
= sizeof(WORD
);
173 case ASM_NAME_CULTURE
:
177 lstrcpyW(pvProperty
, name
->culture
);
178 *pcbProperty
= (lstrlenW(name
->culture
) + 1) * 2;
182 case ASM_NAME_PUBLIC_KEY_TOKEN
:
186 memcpy(pvProperty
, name
->pubkey
, sizeof(DWORD
) * 2);
187 *pcbProperty
= sizeof(DWORD
) * 2;
199 static HRESULT WINAPI
IAssemblyNameImpl_Finalize(IAssemblyName
*iface
)
201 FIXME("(%p) stub!\n", iface
);
205 static HRESULT WINAPI
IAssemblyNameImpl_GetDisplayName(IAssemblyName
*iface
,
206 LPOLESTR szDisplayName
,
207 LPDWORD pccDisplayName
,
208 DWORD dwDisplayFlags
)
210 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
212 TRACE("(%p, %p, %p, %d)\n", iface
, szDisplayName
,
213 pccDisplayName
, dwDisplayFlags
);
215 if (!name
->displayname
|| !*name
->displayname
)
216 return FUSION_E_INVALID_NAME
;
218 lstrcpyW(szDisplayName
, name
->displayname
);
219 *pccDisplayName
= lstrlenW(szDisplayName
) + 1;
224 static HRESULT WINAPI
IAssemblyNameImpl_Reserved(IAssemblyName
*iface
,
226 IUnknown
*pUnkReserved1
,
227 IUnknown
*pUnkReserved2
,
228 LPCOLESTR szReserved
,
234 TRACE("(%p, %s, %p, %p, %s, %x%08x, %p, %d, %p)\n", iface
,
235 debugstr_guid(refIID
), pUnkReserved1
, pUnkReserved2
,
236 debugstr_w(szReserved
), (DWORD
)(llReserved
>> 32), (DWORD
)llReserved
,
237 pvReserved
, cbReserved
, ppReserved
);
242 static HRESULT WINAPI
IAssemblyNameImpl_GetName(IAssemblyName
*iface
,
246 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
248 TRACE("(%p, %p, %p)\n", iface
, lpcwBuffer
, pwzName
);
257 lstrcpyW(pwzName
, name
->name
);
258 *lpcwBuffer
= lstrlenW(pwzName
) + 1;
263 static HRESULT WINAPI
IAssemblyNameImpl_GetVersion(IAssemblyName
*iface
,
264 LPDWORD pdwVersionHi
,
265 LPDWORD pdwVersionLow
)
267 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
269 TRACE("(%p, %p, %p)\n", iface
, pdwVersionHi
, pdwVersionLow
);
274 if (name
->versize
!= 4)
275 return FUSION_E_INVALID_NAME
;
277 *pdwVersionHi
= (name
->version
[0] << 16) + name
->version
[1];
278 *pdwVersionLow
= (name
->version
[2] << 16) + name
->version
[3];
283 static HRESULT WINAPI
IAssemblyNameImpl_IsEqual(IAssemblyName
*iface
,
284 IAssemblyName
*pName
,
287 FIXME("(%p, %p, %d) stub!\n", iface
, pName
, dwCmpFlags
);
291 static HRESULT WINAPI
IAssemblyNameImpl_Clone(IAssemblyName
*iface
,
292 IAssemblyName
**pName
)
294 FIXME("(%p, %p) stub!\n", iface
, pName
);
298 static const IAssemblyNameVtbl AssemblyNameVtbl
= {
299 IAssemblyNameImpl_QueryInterface
,
300 IAssemblyNameImpl_AddRef
,
301 IAssemblyNameImpl_Release
,
302 IAssemblyNameImpl_SetProperty
,
303 IAssemblyNameImpl_GetProperty
,
304 IAssemblyNameImpl_Finalize
,
305 IAssemblyNameImpl_GetDisplayName
,
306 IAssemblyNameImpl_Reserved
,
307 IAssemblyNameImpl_GetName
,
308 IAssemblyNameImpl_GetVersion
,
309 IAssemblyNameImpl_IsEqual
,
310 IAssemblyNameImpl_Clone
313 static HRESULT
parse_version(IAssemblyNameImpl
*name
, LPWSTR version
)
318 for (i
= 0, beg
= version
; i
< 4; i
++)
323 end
= strchrW(beg
, '.');
325 if (end
) *end
= '\0';
326 name
->version
[i
] = atolW(beg
);
338 static HRESULT
parse_culture(IAssemblyNameImpl
*name
, LPWSTR culture
)
340 static const WCHAR empty
[] = {0};
342 if (lstrlenW(culture
) == 2)
343 name
->culture
= strdupW(culture
);
345 name
->culture
= strdupW(empty
);
350 #define CHARS_PER_PUBKEY 16
352 static BOOL
is_hex(WCHAR c
)
354 return ((c
>= 'a' && c
<= 'f') ||
355 (c
>= 'A' && c
<= 'F') ||
356 (c
>= '0' && c
<= '9'));
359 static BYTE
hextobyte(WCHAR c
)
361 if(c
>= '0' && c
<= '9')
363 if(c
>= 'A' && c
<= 'F')
365 if(c
>= 'a' && c
<= 'f')
370 static HRESULT
parse_pubkey(IAssemblyNameImpl
*name
, LPWSTR pubkey
)
375 if (lstrlenW(pubkey
) < CHARS_PER_PUBKEY
)
376 return FUSION_E_INVALID_NAME
;
378 for (i
= 0; i
< CHARS_PER_PUBKEY
; i
++)
379 if (!is_hex(pubkey
[i
]))
380 return FUSION_E_INVALID_NAME
;
382 name
->haspubkey
= TRUE
;
384 for (i
= 0; i
< CHARS_PER_PUBKEY
; i
+= 2)
386 val
= (hextobyte(pubkey
[i
]) << 4) + hextobyte(pubkey
[i
+ 1]);
387 name
->pubkey
[i
/ 2] = val
;
393 static HRESULT
parse_display_name(IAssemblyNameImpl
*name
, LPCWSTR szAssemblyName
)
400 static const WCHAR separator
[] = {',',' ',0};
401 static const WCHAR version
[] = {'V','e','r','s','i','o','n',0};
402 static const WCHAR culture
[] = {'C','u','l','t','u','r','e',0};
403 static const WCHAR pubkey
[] =
404 {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
409 name
->displayname
= strdupW(szAssemblyName
);
410 if (!name
->displayname
)
411 return E_OUTOFMEMORY
;
413 str
= strdupW(szAssemblyName
);
416 return E_OUTOFMEMORY
;
418 ptr
= strstrW(str
, separator
);
419 if (ptr
) *ptr
= '\0';
420 name
->name
= strdupW(str
);
422 return E_OUTOFMEMORY
;
430 ptr
= strchrW(str
, '=');
433 hr
= FUSION_E_INVALID_NAME
;
440 hr
= FUSION_E_INVALID_NAME
;
444 if (!(ptr2
= strstrW(ptr
, separator
)))
446 if (!(ptr2
= strchrW(ptr
, '\0')))
448 hr
= FUSION_E_INVALID_NAME
;
457 while (*str
== ' ') str
++;
459 if (!lstrcmpW(str
, version
))
460 hr
= parse_version(name
, ptr
);
461 else if (!lstrcmpW(str
, culture
))
462 hr
= parse_culture(name
, ptr
);
463 else if (!lstrcmpW(str
, pubkey
))
464 hr
= parse_pubkey(name
, ptr
);
473 HeapFree(GetProcessHeap(), 0, save
);
476 HeapFree(GetProcessHeap(), 0, name
->displayname
);
477 HeapFree(GetProcessHeap(), 0, name
->name
);
482 /******************************************************************
483 * CreateAssemblyNameObject (FUSION.@)
485 HRESULT WINAPI
CreateAssemblyNameObject(LPASSEMBLYNAME
*ppAssemblyNameObj
,
486 LPCWSTR szAssemblyName
, DWORD dwFlags
,
489 IAssemblyNameImpl
*name
;
492 TRACE("(%p, %s, %08x, %p) stub!\n", ppAssemblyNameObj
,
493 debugstr_w(szAssemblyName
), dwFlags
, pvReserved
);
495 if (!ppAssemblyNameObj
)
498 if ((dwFlags
& CANOF_PARSE_DISPLAY_NAME
) &&
499 (!szAssemblyName
|| !*szAssemblyName
))
502 name
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAssemblyNameImpl
));
504 return E_OUTOFMEMORY
;
506 name
->lpIAssemblyNameVtbl
= &AssemblyNameVtbl
;
509 hr
= parse_display_name(name
, szAssemblyName
);
512 HeapFree(GetProcessHeap(), 0, name
);
516 *ppAssemblyNameObj
= (IAssemblyName
*)name
;