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