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