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((LPWSTR)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((LPWSTR)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;