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"
37 WINE_DEFAULT_DEBUG_CHANNEL(fusion
);
39 static inline LPWSTR
strdupW(LPCWSTR src
)
46 dest
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(src
) + 1) * sizeof(WCHAR
));
54 const IAssemblyNameVtbl
*lpIAssemblyNameVtbl
;
69 static HRESULT WINAPI
IAssemblyNameImpl_QueryInterface(IAssemblyName
*iface
,
70 REFIID riid
, LPVOID
*ppobj
)
72 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
74 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppobj
);
78 if (IsEqualIID(riid
, &IID_IUnknown
) ||
79 IsEqualIID(riid
, &IID_IAssemblyName
))
81 IUnknown_AddRef(iface
);
86 WARN("(%p, %s, %p): not found\n", This
, debugstr_guid(riid
), ppobj
);
90 static ULONG WINAPI
IAssemblyNameImpl_AddRef(IAssemblyName
*iface
)
92 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
93 ULONG refCount
= InterlockedIncrement(&This
->ref
);
95 TRACE("(%p)->(ref before = %u)\n", This
, refCount
- 1);
100 static ULONG WINAPI
IAssemblyNameImpl_Release(IAssemblyName
*iface
)
102 IAssemblyNameImpl
*This
= (IAssemblyNameImpl
*)iface
;
103 ULONG refCount
= InterlockedDecrement(&This
->ref
);
105 TRACE("(%p)->(ref before = %u)\n", This
, refCount
+ 1);
109 HeapFree(GetProcessHeap(), 0, This
->displayname
);
110 HeapFree(GetProcessHeap(), 0, This
->name
);
111 HeapFree(GetProcessHeap(), 0, This
->culture
);
112 HeapFree(GetProcessHeap(), 0, This
);
118 static HRESULT WINAPI
IAssemblyNameImpl_SetProperty(IAssemblyName
*iface
,
123 FIXME("(%p, %d, %p, %d) stub!\n", iface
, PropertyId
, pvProperty
, cbProperty
);
127 static HRESULT WINAPI
IAssemblyNameImpl_GetProperty(IAssemblyName
*iface
,
132 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
134 TRACE("(%p, %d, %p, %p)\n", iface
, PropertyId
, pvProperty
, pcbProperty
);
136 *((LPWSTR
)pvProperty
) = '\0';
140 case ASM_NAME_NULL_PUBLIC_KEY
:
141 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN
:
146 case ASM_NAME_NULL_CUSTOM
:
153 lstrcpyW(pvProperty
, name
->name
);
154 *pcbProperty
= (lstrlenW(name
->name
) + 1) * 2;
158 case ASM_NAME_MAJOR_VERSION
:
160 *((LPDWORD
)pvProperty
) = name
->version
[0];
161 if (name
->versize
>= 1)
162 *pcbProperty
= sizeof(WORD
);
165 case ASM_NAME_MINOR_VERSION
:
167 *((LPDWORD
)pvProperty
) = name
->version
[1];
168 if (name
->versize
>= 2)
169 *pcbProperty
= sizeof(WORD
);
172 case ASM_NAME_BUILD_NUMBER
:
174 *((LPDWORD
)pvProperty
) = name
->version
[2];
175 if (name
->versize
>= 3)
176 *pcbProperty
= sizeof(WORD
);
179 case ASM_NAME_REVISION_NUMBER
:
181 *((LPDWORD
)pvProperty
) = name
->version
[3];
182 if (name
->versize
>= 4)
183 *pcbProperty
= sizeof(WORD
);
186 case ASM_NAME_CULTURE
:
190 lstrcpyW(pvProperty
, name
->culture
);
191 *pcbProperty
= (lstrlenW(name
->culture
) + 1) * 2;
195 case ASM_NAME_PUBLIC_KEY_TOKEN
:
199 memcpy(pvProperty
, name
->pubkey
, sizeof(DWORD
) * 2);
200 *pcbProperty
= sizeof(DWORD
) * 2;
212 static HRESULT WINAPI
IAssemblyNameImpl_Finalize(IAssemblyName
*iface
)
214 FIXME("(%p) stub!\n", iface
);
218 static HRESULT WINAPI
IAssemblyNameImpl_GetDisplayName(IAssemblyName
*iface
,
219 LPOLESTR szDisplayName
,
220 LPDWORD pccDisplayName
,
221 DWORD dwDisplayFlags
)
223 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
225 TRACE("(%p, %s, %p, %d)\n", iface
, debugstr_w(szDisplayName
),
226 pccDisplayName
, dwDisplayFlags
);
228 if (!name
->displayname
|| !*name
->displayname
)
229 return FUSION_E_INVALID_NAME
;
231 lstrcpyW(szDisplayName
, name
->displayname
);
232 *pccDisplayName
= lstrlenW(szDisplayName
) + 1;
237 static HRESULT WINAPI
IAssemblyNameImpl_Reserved(IAssemblyName
*iface
,
239 IUnknown
*pUnkReserved1
,
240 IUnknown
*pUnkReserved2
,
241 LPCOLESTR szReserved
,
247 TRACE("(%p, %s, %p, %p, %s, %x%08x, %p, %d, %p)\n", iface
,
248 debugstr_guid(refIID
), pUnkReserved1
, pUnkReserved2
,
249 debugstr_w(szReserved
), (DWORD
)(llReserved
>> 32), (DWORD
)llReserved
,
250 pvReserved
, cbReserved
, ppReserved
);
255 static HRESULT WINAPI
IAssemblyNameImpl_GetName(IAssemblyName
*iface
,
259 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
261 TRACE("(%p, %p, %p)\n", iface
, lpcwBuffer
, pwzName
);
270 lstrcpyW(pwzName
, name
->name
);
271 *lpcwBuffer
= lstrlenW(pwzName
) + 1;
276 static HRESULT WINAPI
IAssemblyNameImpl_GetVersion(IAssemblyName
*iface
,
277 LPDWORD pdwVersionHi
,
278 LPDWORD pdwVersionLow
)
280 IAssemblyNameImpl
*name
= (IAssemblyNameImpl
*)iface
;
282 TRACE("(%p, %p, %p)\n", iface
, pdwVersionHi
, pdwVersionLow
);
287 if (name
->versize
!= 4)
288 return FUSION_E_INVALID_NAME
;
290 *pdwVersionHi
= (name
->version
[0] << 16) + name
->version
[1];
291 *pdwVersionLow
= (name
->version
[2] << 16) + name
->version
[3];
296 static HRESULT WINAPI
IAssemblyNameImpl_IsEqual(IAssemblyName
*iface
,
297 IAssemblyName
*pName
,
300 FIXME("(%p, %p, %d) stub!\n", iface
, pName
, dwCmpFlags
);
304 static HRESULT WINAPI
IAssemblyNameImpl_Clone(IAssemblyName
*iface
,
305 IAssemblyName
**pName
)
307 FIXME("(%p, %p) stub!\n", iface
, pName
);
311 static const IAssemblyNameVtbl AssemblyNameVtbl
= {
312 IAssemblyNameImpl_QueryInterface
,
313 IAssemblyNameImpl_AddRef
,
314 IAssemblyNameImpl_Release
,
315 IAssemblyNameImpl_SetProperty
,
316 IAssemblyNameImpl_GetProperty
,
317 IAssemblyNameImpl_Finalize
,
318 IAssemblyNameImpl_GetDisplayName
,
319 IAssemblyNameImpl_Reserved
,
320 IAssemblyNameImpl_GetName
,
321 IAssemblyNameImpl_GetVersion
,
322 IAssemblyNameImpl_IsEqual
,
323 IAssemblyNameImpl_Clone
326 static HRESULT
parse_version(IAssemblyNameImpl
*name
, LPWSTR version
)
331 for (i
= 0, beg
= version
; i
< 4; i
++)
336 end
= strchrW(beg
, '.');
338 if (end
) *end
= '\0';
339 name
->version
[i
] = atolW(beg
);
351 static HRESULT
parse_culture(IAssemblyNameImpl
*name
, LPWSTR culture
)
353 static const WCHAR empty
[] = {0};
355 if (lstrlenW(culture
) == 2)
356 name
->culture
= strdupW(culture
);
358 name
->culture
= strdupW(empty
);
363 #define CHARS_PER_PUBKEY 16
365 static BOOL
is_hex(WCHAR c
)
367 return ((c
>= 'a' && c
<= 'f') ||
368 (c
>= 'A' && c
<= 'F') ||
369 (c
>= '0' && c
<= '9'));
372 static BYTE
hextobyte(WCHAR c
)
374 if(c
>= '0' && c
<= '9')
376 if(c
>= 'A' && c
<= 'F')
378 if(c
>= 'a' && c
<= 'f')
383 static HRESULT
parse_pubkey(IAssemblyNameImpl
*name
, LPWSTR pubkey
)
388 if (lstrlenW(pubkey
) < CHARS_PER_PUBKEY
)
389 return FUSION_E_INVALID_NAME
;
391 for (i
= 0; i
< CHARS_PER_PUBKEY
; i
++)
392 if (!is_hex(pubkey
[i
]))
393 return FUSION_E_INVALID_NAME
;
395 name
->haspubkey
= TRUE
;
397 for (i
= 0; i
< CHARS_PER_PUBKEY
; i
+= 2)
399 val
= (hextobyte(pubkey
[i
]) << 4) + hextobyte(pubkey
[i
+ 1]);
400 name
->pubkey
[i
/ 2] = val
;
406 static HRESULT
parse_display_name(IAssemblyNameImpl
*name
, LPCWSTR szAssemblyName
)
413 static const WCHAR separator
[] = {',',' ',0};
414 static const WCHAR version
[] = {'V','e','r','s','i','o','n',0};
415 static const WCHAR culture
[] = {'C','u','l','t','u','r','e',0};
416 static const WCHAR pubkey
[] =
417 {'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
422 name
->displayname
= strdupW(szAssemblyName
);
423 if (!name
->displayname
)
424 return E_OUTOFMEMORY
;
426 str
= strdupW(szAssemblyName
);
429 return E_OUTOFMEMORY
;
431 ptr
= strstrW(str
, separator
);
432 if (ptr
) *ptr
= '\0';
433 name
->name
= strdupW(str
);
435 return E_OUTOFMEMORY
;
443 ptr
= strchrW(str
, '=');
446 hr
= FUSION_E_INVALID_NAME
;
453 hr
= FUSION_E_INVALID_NAME
;
457 if (!(ptr2
= strstrW(ptr
, separator
)))
459 if (!(ptr2
= strchrW(ptr
, '\0')))
461 hr
= FUSION_E_INVALID_NAME
;
470 if (!lstrcmpW(str
, version
))
471 hr
= parse_version(name
, ptr
);
472 else if (!lstrcmpW(str
, culture
))
473 hr
= parse_culture(name
, ptr
);
474 else if (!lstrcmpW(str
, pubkey
))
475 hr
= parse_pubkey(name
, ptr
);
484 HeapFree(GetProcessHeap(), 0, save
);
488 /******************************************************************
489 * CreateAssemblyNameObject (FUSION.@)
491 HRESULT WINAPI
CreateAssemblyNameObject(LPASSEMBLYNAME
*ppAssemblyNameObj
,
492 LPCWSTR szAssemblyName
, DWORD dwFlags
,
495 IAssemblyNameImpl
*name
;
498 TRACE("(%p, %s, %08x, %p) stub!\n", ppAssemblyNameObj
,
499 debugstr_w(szAssemblyName
), dwFlags
, pvReserved
);
501 if (!ppAssemblyNameObj
)
504 if ((dwFlags
& CANOF_PARSE_DISPLAY_NAME
) &&
505 (!szAssemblyName
|| !*szAssemblyName
))
508 name
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAssemblyNameImpl
));
510 return E_OUTOFMEMORY
;
512 name
->lpIAssemblyNameVtbl
= &AssemblyNameVtbl
;
515 hr
= parse_display_name(name
, szAssemblyName
);
518 HeapFree(GetProcessHeap(), 0, name
);
522 *ppAssemblyNameObj
= (IAssemblyName
*)name
;