xref: /reactos/dll/win32/sxs/name.c (revision 84ccccab)
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, %s, %p, %d, %p\n", iface,
164           debugstr_guid(riid), pUnkReserved1, pUnkReserved2,
165           debugstr_w(szReserved), wine_dbgstr_longlong(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 }
390