* Sync up to trunk head (r60691).
[reactos.git] / dll / win32 / sxs / name.c
1 /*
2 * IAssemblyName implementation
3 *
4 * Copyright 2012 Hans Leidekker for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #include <stdarg.h>
26
27 #define COBJMACROS
28
29 #include <windef.h>
30 #include <winbase.h>
31 #include <ole2.h>
32 #include <winsxs.h>
33
34 #include <wine/debug.h>
35 #include <wine/unicode.h>
36 #include "sxs_private.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(sxs);
39
40 struct name
41 {
42 IAssemblyName IAssemblyName_iface;
43 LONG refs;
44 WCHAR *name;
45 WCHAR *arch;
46 WCHAR *token;
47 WCHAR *type;
48 WCHAR *version;
49 };
50
51 static const WCHAR archW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
52 static const WCHAR tokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
53 static const WCHAR typeW[] = {'t','y','p','e',0};
54 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
55
56 static inline struct name *impl_from_IAssemblyName( IAssemblyName *iface )
57 {
58 return CONTAINING_RECORD( iface, struct name, IAssemblyName_iface );
59 }
60
61 static HRESULT WINAPI name_QueryInterface(
62 IAssemblyName *iface,
63 REFIID riid,
64 void **obj )
65 {
66 struct name *name = impl_from_IAssemblyName( iface );
67
68 TRACE("%p, %s, %p\n", name, debugstr_guid(riid), obj);
69
70 *obj = NULL;
71
72 if (IsEqualIID( riid, &IID_IUnknown ) ||
73 IsEqualIID( riid, &IID_IAssemblyName ))
74 {
75 IAssemblyName_AddRef( iface );
76 *obj = name;
77 return S_OK;
78 }
79
80 return E_NOINTERFACE;
81 }
82
83 static ULONG WINAPI name_AddRef(
84 IAssemblyName *iface )
85 {
86 struct name *name = impl_from_IAssemblyName( iface );
87 return InterlockedIncrement( &name->refs );
88 }
89
90 static ULONG WINAPI name_Release( IAssemblyName *iface )
91 {
92 struct name *name = impl_from_IAssemblyName( iface );
93 ULONG refs = InterlockedDecrement( &name->refs );
94
95 if (!refs)
96 {
97 TRACE("destroying %p\n", name);
98 HeapFree( GetProcessHeap(), 0, name->name );
99 HeapFree( GetProcessHeap(), 0, name->arch );
100 HeapFree( GetProcessHeap(), 0, name->token );
101 HeapFree( GetProcessHeap(), 0, name->type );
102 HeapFree( GetProcessHeap(), 0, name->version );
103 HeapFree( GetProcessHeap(), 0, name );
104 }
105 return refs;
106 }
107
108 static HRESULT WINAPI name_SetProperty(
109 IAssemblyName *iface,
110 DWORD id,
111 LPVOID property,
112 DWORD size )
113 {
114 FIXME("%p, %d, %p, %d\n", iface, id, property, size);
115 return E_NOTIMPL;
116 }
117
118 static HRESULT WINAPI name_GetProperty(
119 IAssemblyName *iface,
120 DWORD id,
121 LPVOID buffer,
122 LPDWORD buflen )
123 {
124 FIXME("%p, %d, %p, %p\n", iface, id, buffer, buflen);
125 return E_NOTIMPL;
126 }
127
128 static HRESULT WINAPI name_Finalize(
129 IAssemblyName *iface )
130 {
131 FIXME("%p\n", iface);
132 return E_NOTIMPL;
133 }
134
135 static HRESULT WINAPI name_GetDisplayName(
136 IAssemblyName *iface,
137 LPOLESTR buffer,
138 LPDWORD buflen,
139 DWORD flags )
140 {
141 static const WCHAR fmtW[] = {',','%','s','=','\"','%','s','\"',0};
142 struct name *name = impl_from_IAssemblyName( iface );
143 WCHAR version[30];
144 unsigned int len;
145
146 TRACE("%p, %p, %p, 0x%08x\n", iface, buffer, buflen, flags);
147
148 if (!buflen || flags) return E_INVALIDARG;
149
150 len = strlenW( name->name ) + 1;
151 if (name->arch) len += strlenW( archW ) + strlenW( name->arch ) + 4;
152 if (name->token) len += strlenW( tokenW ) + strlenW( name->token ) + 4;
153 if (name->type) len += strlenW( typeW ) + strlenW( name->type ) + 4;
154 if (name->version) len += strlenW( versionW ) + strlenW( version ) + 4;
155 if (len > *buflen)
156 {
157 *buflen = len;
158 return HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
159 }
160 strcpyW( buffer, name->name );
161 len = strlenW( buffer );
162 if (name->arch) len += sprintfW( buffer + len, fmtW, archW, name->arch );
163 if (name->token) len += sprintfW( buffer + len, fmtW, tokenW, name->token );
164 if (name->type) len += sprintfW( buffer + len, fmtW, typeW, name->type );
165 if (name->version) len += sprintfW( buffer + len, fmtW, versionW, name->version );
166 return S_OK;
167 }
168
169 static HRESULT WINAPI name_Reserved(
170 IAssemblyName *iface,
171 REFIID riid,
172 IUnknown *pUnkReserved1,
173 IUnknown *pUnkReserved2,
174 LPCOLESTR szReserved,
175 LONGLONG llReserved,
176 LPVOID pvReserved,
177 DWORD cbReserved,
178 LPVOID *ppReserved )
179 {
180 FIXME("%p, %s, %p, %p, %s, %x%08x, %p, %d, %p\n", iface,
181 debugstr_guid(riid), pUnkReserved1, pUnkReserved2,
182 debugstr_w(szReserved), (DWORD)(llReserved >> 32), (DWORD)llReserved,
183 pvReserved, cbReserved, ppReserved);
184 return E_NOTIMPL;
185 }
186
187 const WCHAR *get_name_attribute( IAssemblyName *iface, enum name_attr_id id )
188 {
189 struct name *name = impl_from_IAssemblyName( iface );
190
191 switch (id)
192 {
193 case NAME_ATTR_ID_NAME: return name->name;
194 case NAME_ATTR_ID_ARCH: return name->arch;
195 case NAME_ATTR_ID_TOKEN: return name->token;
196 case NAME_ATTR_ID_TYPE: return name->type;
197 case NAME_ATTR_ID_VERSION: return name->version;
198 default:
199 ERR("unhandled name attribute %u\n", id);
200 break;
201 }
202 return NULL;
203 }
204
205 static HRESULT WINAPI name_GetName(
206 IAssemblyName *iface,
207 LPDWORD buflen,
208 WCHAR *buffer )
209 {
210 const WCHAR *name;
211 int len;
212
213 TRACE("%p, %p, %p\n", iface, buflen, buffer);
214
215 if (!buflen || !buffer) return E_INVALIDARG;
216
217 name = get_name_attribute( iface, NAME_ATTR_ID_NAME );
218 len = strlenW( name ) + 1;
219 if (len > *buflen)
220 {
221 *buflen = len;
222 return HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
223 }
224 strcpyW( buffer, name );
225 *buflen = len + 3;
226 return S_OK;
227 }
228
229 static HRESULT parse_version( WCHAR *version, DWORD *high, DWORD *low )
230 {
231 WORD ver[4];
232 WCHAR *p, *q;
233 unsigned int i;
234
235 memset( ver, 0, sizeof(ver) );
236 for (i = 0, p = version; i < 4; i++)
237 {
238 if (!*p) break;
239 q = strchrW( p, '.' );
240 if (q) *q = 0;
241 ver[i] = atolW( p );
242 if (!q && i < 3) break;
243 p = q + 1;
244 }
245 *high = (ver[0] << 16) + ver[1];
246 *low = (ver[2] << 16) + ver[3];
247 return S_OK;
248 }
249
250 static HRESULT WINAPI name_GetVersion(
251 IAssemblyName *iface,
252 LPDWORD high,
253 LPDWORD low )
254 {
255 struct name *name = impl_from_IAssemblyName( iface );
256 WCHAR *version;
257 HRESULT hr;
258
259 TRACE("%p, %p, %p\n", iface, high, low);
260
261 if (!name->version) return HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
262 if (!(version = strdupW( name->version ))) return E_OUTOFMEMORY;
263 hr = parse_version( version, high, low );
264 HeapFree( GetProcessHeap(), 0, version );
265 return hr;
266 }
267
268 static HRESULT WINAPI name_IsEqual(
269 IAssemblyName *name1,
270 IAssemblyName *name2,
271 DWORD flags )
272 {
273 FIXME("%p, %p, 0x%08x\n", name1, name2, flags);
274 return E_NOTIMPL;
275 }
276
277 static HRESULT WINAPI name_Clone(
278 IAssemblyName *iface,
279 IAssemblyName **name )
280 {
281 FIXME("%p, %p\n", iface, name);
282 return E_NOTIMPL;
283 }
284
285 static const IAssemblyNameVtbl name_vtbl =
286 {
287 name_QueryInterface,
288 name_AddRef,
289 name_Release,
290 name_SetProperty,
291 name_GetProperty,
292 name_Finalize,
293 name_GetDisplayName,
294 name_Reserved,
295 name_GetName,
296 name_GetVersion,
297 name_IsEqual,
298 name_Clone
299 };
300
301 static WCHAR *parse_value( const WCHAR *str, unsigned int *len )
302 {
303 WCHAR *ret;
304 const WCHAR *p = str;
305
306 if (*p++ != '\"') return NULL;
307 while (*p && *p != '\"') p++;
308 if (!*p) return NULL;
309
310 *len = p - str;
311 if (!(ret = HeapAlloc( GetProcessHeap(), 0, *len * sizeof(WCHAR) ))) return NULL;
312 memcpy( ret, str + 1, (*len - 1) * sizeof(WCHAR) );
313 ret[*len - 1] = 0;
314 return ret;
315 }
316
317 static HRESULT parse_displayname( struct name *name, const WCHAR *displayname )
318 {
319 const WCHAR *p, *q;
320 unsigned int len;
321
322 p = q = displayname;
323 while (*q && *q != ',') q++;
324 len = q - p;
325 if (!(name->name = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
326 memcpy( name->name, p, len * sizeof(WCHAR) );
327 name->name[len] = 0;
328 if (!*q) return S_OK;
329
330 for (;;)
331 {
332 p = ++q;
333 while (*q && *q != '=') q++;
334 if (!*q) return E_INVALIDARG;
335 len = q - p;
336 if (len == sizeof(archW)/sizeof(archW[0]) - 1 && !memcmp( p, archW, len * sizeof(WCHAR) ))
337 {
338 p = ++q;
339 if (!(name->arch = parse_value( p, &len ))) return E_INVALIDARG;
340 q += len;
341 }
342 else if (len == sizeof(tokenW)/sizeof(tokenW[0]) - 1 && !memcmp( p, tokenW, len * sizeof(WCHAR) ))
343 {
344 p = ++q;
345 if (!(name->token = parse_value( p, &len ))) return E_INVALIDARG;
346 q += len;
347 }
348 else if (len == sizeof(typeW)/sizeof(typeW[0]) - 1 && !memcmp( p, typeW, len * sizeof(WCHAR) ))
349 {
350 p = ++q;
351 if (!(name->type = parse_value( p, &len ))) return E_INVALIDARG;
352 q += len;
353 }
354 else if (len == sizeof(versionW)/sizeof(versionW[0]) - 1 && !memcmp( p, versionW, len * sizeof(WCHAR) ))
355 {
356 p = ++q;
357 if (!(name->version = parse_value( p, &len ))) return E_INVALIDARG;
358 q += len;
359 }
360 else return HRESULT_FROM_WIN32( ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME );
361 while (*q && *q != ',') q++;
362 if (!*q) break;
363 }
364 return S_OK;
365 }
366
367 /******************************************************************
368 * CreateAssemblyNameObject (SXS.@)
369 */
370 HRESULT WINAPI CreateAssemblyNameObject(
371 LPASSEMBLYNAME *obj,
372 LPCWSTR assembly,
373 DWORD flags,
374 LPVOID reserved )
375 {
376 struct name *name;
377 HRESULT hr;
378
379 TRACE("%p, %s, 0x%08x, %p\n", obj, debugstr_w(assembly), flags, reserved);
380
381 if (!obj) return E_INVALIDARG;
382
383 *obj = NULL;
384 if (!assembly || !assembly[0] || flags != CANOF_PARSE_DISPLAY_NAME)
385 return E_INVALIDARG;
386
387 if (!(name = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*name) )))
388 return E_OUTOFMEMORY;
389
390 name->IAssemblyName_iface.lpVtbl = &name_vtbl;
391 name->refs = 1;
392
393 hr = parse_displayname( name, assembly );
394 if (hr != S_OK)
395 {
396 HeapFree( GetProcessHeap(), 0, name->name );
397 HeapFree( GetProcessHeap(), 0, name->arch );
398 HeapFree( GetProcessHeap(), 0, name->token );
399 HeapFree( GetProcessHeap(), 0, name->type );
400 HeapFree( GetProcessHeap(), 0, name->version );
401 HeapFree( GetProcessHeap(), 0, name );
402 return hr;
403 }
404 *obj = &name->IAssemblyName_iface;
405 return S_OK;
406 }