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