comctl32/tests: Add NULL terminator to unicode string constant.
[wine/hramrach.git] / dlls / fusion / asmname.c
blob3c014ea32445e74db1802cb122e018c2b8b2dae1
1 /*
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
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define INITGUID
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "guiddef.h"
31 #include "fusion.h"
32 #include "corerror.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36 #include "fusionpriv.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(fusion);
40 typedef struct {
41 const IAssemblyNameVtbl *lpIAssemblyNameVtbl;
43 LPWSTR displayname;
44 LPWSTR name;
45 LPWSTR culture;
47 WORD version[4];
48 DWORD versize;
50 BYTE pubkey[8];
51 BOOL haspubkey;
53 LONG ref;
54 } IAssemblyNameImpl;
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);
63 *ppobj = NULL;
65 if (IsEqualIID(riid, &IID_IUnknown) ||
66 IsEqualIID(riid, &IID_IAssemblyName))
68 IUnknown_AddRef(iface);
69 *ppobj = This;
70 return S_OK;
73 WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
74 return E_NOINTERFACE;
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);
84 return refCount;
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);
94 if (!refCount)
96 HeapFree(GetProcessHeap(), 0, This->displayname);
97 HeapFree(GetProcessHeap(), 0, This->name);
98 HeapFree(GetProcessHeap(), 0, This->culture);
99 HeapFree(GetProcessHeap(), 0, This);
102 return refCount;
105 static HRESULT WINAPI IAssemblyNameImpl_SetProperty(IAssemblyName *iface,
106 DWORD PropertyId,
107 LPVOID pvProperty,
108 DWORD cbProperty)
110 FIXME("(%p, %d, %p, %d) stub!\n", iface, PropertyId, pvProperty, cbProperty);
111 return E_NOTIMPL;
114 static HRESULT WINAPI IAssemblyNameImpl_GetProperty(IAssemblyName *iface,
115 DWORD PropertyId,
116 LPVOID pvProperty,
117 LPDWORD pcbProperty)
119 IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface;
121 TRACE("(%p, %d, %p, %p)\n", iface, PropertyId, pvProperty, pcbProperty);
123 *((LPWSTR)pvProperty) = '\0';
125 switch (PropertyId)
127 case ASM_NAME_NULL_PUBLIC_KEY:
128 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN:
129 if (name->haspubkey)
130 return S_OK;
131 return S_FALSE;
133 case ASM_NAME_NULL_CUSTOM:
134 return S_OK;
136 case ASM_NAME_NAME:
137 *pcbProperty = 0;
138 if (name->name)
140 lstrcpyW(pvProperty, name->name);
141 *pcbProperty = (lstrlenW(name->name) + 1) * 2;
143 break;
145 case ASM_NAME_MAJOR_VERSION:
146 *pcbProperty = 0;
147 *((WORD *)pvProperty) = name->version[0];
148 if (name->versize >= 1)
149 *pcbProperty = sizeof(WORD);
150 break;
152 case ASM_NAME_MINOR_VERSION:
153 *pcbProperty = 0;
154 *((WORD *)pvProperty) = name->version[1];
155 if (name->versize >= 2)
156 *pcbProperty = sizeof(WORD);
157 break;
159 case ASM_NAME_BUILD_NUMBER:
160 *pcbProperty = 0;
161 *((WORD *)pvProperty) = name->version[2];
162 if (name->versize >= 3)
163 *pcbProperty = sizeof(WORD);
164 break;
166 case ASM_NAME_REVISION_NUMBER:
167 *pcbProperty = 0;
168 *((WORD *)pvProperty) = name->version[3];
169 if (name->versize >= 4)
170 *pcbProperty = sizeof(WORD);
171 break;
173 case ASM_NAME_CULTURE:
174 *pcbProperty = 0;
175 if (name->culture)
177 lstrcpyW(pvProperty, name->culture);
178 *pcbProperty = (lstrlenW(name->culture) + 1) * 2;
180 break;
182 case ASM_NAME_PUBLIC_KEY_TOKEN:
183 *pcbProperty = 0;
184 if (name->haspubkey)
186 memcpy(pvProperty, name->pubkey, sizeof(DWORD) * 2);
187 *pcbProperty = sizeof(DWORD) * 2;
189 break;
191 default:
192 *pcbProperty = 0;
193 break;
196 return S_OK;
199 static HRESULT WINAPI IAssemblyNameImpl_Finalize(IAssemblyName *iface)
201 FIXME("(%p) stub!\n", iface);
202 return E_NOTIMPL;
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;
221 return S_OK;
224 static HRESULT WINAPI IAssemblyNameImpl_Reserved(IAssemblyName *iface,
225 REFIID refIID,
226 IUnknown *pUnkReserved1,
227 IUnknown *pUnkReserved2,
228 LPCOLESTR szReserved,
229 LONGLONG llReserved,
230 LPVOID pvReserved,
231 DWORD cbReserved,
232 LPVOID *ppReserved)
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);
239 return E_NOTIMPL;
242 static HRESULT WINAPI IAssemblyNameImpl_GetName(IAssemblyName *iface,
243 LPDWORD lpcwBuffer,
244 WCHAR *pwzName)
246 IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface;
248 TRACE("(%p, %p, %p)\n", iface, lpcwBuffer, pwzName);
250 if (!name->name)
252 *pwzName = '\0';
253 *lpcwBuffer = 0;
254 return S_OK;
257 lstrcpyW(pwzName, name->name);
258 *lpcwBuffer = lstrlenW(pwzName) + 1;
260 return S_OK;
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);
271 *pdwVersionHi = 0;
272 *pdwVersionLow = 0;
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];
280 return S_OK;
283 static HRESULT WINAPI IAssemblyNameImpl_IsEqual(IAssemblyName *iface,
284 IAssemblyName *pName,
285 DWORD dwCmpFlags)
287 FIXME("(%p, %p, %d) stub!\n", iface, pName, dwCmpFlags);
288 return E_NOTIMPL;
291 static HRESULT WINAPI IAssemblyNameImpl_Clone(IAssemblyName *iface,
292 IAssemblyName **pName)
294 FIXME("(%p, %p) stub!\n", iface, pName);
295 return E_NOTIMPL;
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)
315 LPWSTR beg, end;
316 int i;
318 for (i = 0, beg = version; i < 4; i++)
320 if (!*beg)
321 return S_OK;
323 end = strchrW(beg, '.');
325 if (end) *end = '\0';
326 name->version[i] = atolW(beg);
327 name->versize++;
329 if (!end && i < 3)
330 return S_OK;
332 beg = end + 1;
335 return S_OK;
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);
344 else
345 name->culture = strdupW(empty);
347 return S_OK;
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')
362 return c - '0';
363 if(c >= 'A' && c <= 'F')
364 return c - 'A' + 10;
365 if(c >= 'a' && c <= 'f')
366 return c - 'a' + 10;
367 return 0;
370 static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPWSTR pubkey)
372 int i;
373 BYTE val;
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;
390 return S_OK;
393 static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyName)
395 LPWSTR str, save;
396 LPWSTR ptr, ptr2;
397 HRESULT hr = S_OK;
398 BOOL done = FALSE;
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};
406 if (!szAssemblyName)
407 return S_OK;
409 name->displayname = strdupW(szAssemblyName);
410 if (!name->displayname)
411 return E_OUTOFMEMORY;
413 str = strdupW(szAssemblyName);
414 save = str;
415 if (!str)
416 return E_OUTOFMEMORY;
418 ptr = strstrW(str, separator);
419 if (ptr) *ptr = '\0';
420 name->name = strdupW(str);
421 if (!name->name)
422 return E_OUTOFMEMORY;
424 if (!ptr)
425 goto done;
427 str = ptr + 2;
428 while (!done)
430 ptr = strchrW(str, '=');
431 if (!ptr)
433 hr = FUSION_E_INVALID_NAME;
434 goto done;
437 *(ptr++) = '\0';
438 if (!*ptr)
440 hr = FUSION_E_INVALID_NAME;
441 goto done;
444 if (!(ptr2 = strstrW(ptr, separator)))
446 if (!(ptr2 = strchrW(ptr, '\0')))
448 hr = FUSION_E_INVALID_NAME;
449 goto done;
452 done = TRUE;
455 *ptr2 = '\0';
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);
466 if (FAILED(hr))
467 goto done;
469 str = ptr2 + 1;
472 done:
473 HeapFree(GetProcessHeap(), 0, save);
474 if (FAILED(hr))
476 HeapFree(GetProcessHeap(), 0, name->displayname);
477 HeapFree(GetProcessHeap(), 0, name->name);
479 return hr;
482 /******************************************************************
483 * CreateAssemblyNameObject (FUSION.@)
485 HRESULT WINAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj,
486 LPCWSTR szAssemblyName, DWORD dwFlags,
487 LPVOID pvReserved)
489 IAssemblyNameImpl *name;
490 HRESULT hr;
492 TRACE("(%p, %s, %08x, %p) stub!\n", ppAssemblyNameObj,
493 debugstr_w(szAssemblyName), dwFlags, pvReserved);
495 if (!ppAssemblyNameObj)
496 return E_INVALIDARG;
498 if ((dwFlags & CANOF_PARSE_DISPLAY_NAME) &&
499 (!szAssemblyName || !*szAssemblyName))
500 return E_INVALIDARG;
502 name = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAssemblyNameImpl));
503 if (!name)
504 return E_OUTOFMEMORY;
506 name->lpIAssemblyNameVtbl = &AssemblyNameVtbl;
507 name->ref = 1;
509 hr = parse_display_name(name, szAssemblyName);
510 if (FAILED(hr))
512 HeapFree(GetProcessHeap(), 0, name);
513 return hr;
516 *ppAssemblyNameObj = (IAssemblyName *)name;
518 return S_OK;