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, %s, %p, %d, %p\n", iface, 177 debugstr_guid(riid), pUnkReserved1, pUnkReserved2, 178 debugstr_w(szReserved), wine_dbgstr_longlong(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 == ARRAY_SIZE(archW) - 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 == ARRAY_SIZE(tokenW) - 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 == ARRAY_SIZE(typeW) - 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 == ARRAY_SIZE(versionW) - 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 } 403