xref: /reactos/dll/win32/sxs/name.c (revision 682f85ad)
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 }
405