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);
477 /******************************************************************
478 * CreateAssemblyNameObject (FUSION.@)
480 HRESULT WINAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj,
481 LPCWSTR szAssemblyName, DWORD dwFlags,
484 IAssemblyNameImpl *name;
487 TRACE("(%p, %s, %08x, %p) stub!\n", ppAssemblyNameObj,
488 debugstr_w(szAssemblyName), dwFlags, pvReserved);
490 if (!ppAssemblyNameObj)
493 if ((dwFlags & CANOF_PARSE_DISPLAY_NAME) &&
494 (!szAssemblyName || !*szAssemblyName))
497 name = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAssemblyNameImpl));
499 return E_OUTOFMEMORY;
501 name->lpIAssemblyNameVtbl = &AssemblyNameVtbl;
504 hr = parse_display_name(name, szAssemblyName);
507 HeapFree(GetProcessHeap(), 0, name);
511 *ppAssemblyNameObj = (IAssemblyName *)name;