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