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