/* * IAssemblyName implementation * * Copyright 2012 Hans Leidekker for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include <stdarg.h> #define COBJMACROS #include "windef.h" #include "winbase.h" #include "ole2.h" #include "winsxs.h" #include "wine/debug.h" #include "wine/unicode.h" #include "sxs_private.h" WINE_DEFAULT_DEBUG_CHANNEL(sxs); struct name { IAssemblyName IAssemblyName_iface; LONG refs; WCHAR *name; WCHAR *arch; WCHAR *token; WCHAR *type; WCHAR *version; }; 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}; static const WCHAR tokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0}; static const WCHAR typeW[] = {'t','y','p','e',0}; static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; static inline struct name *impl_from_IAssemblyName( IAssemblyName *iface ) { return CONTAINING_RECORD( iface, struct name, IAssemblyName_iface ); } static HRESULT WINAPI name_QueryInterface( IAssemblyName *iface, REFIID riid, void **obj ) { struct name *name = impl_from_IAssemblyName( iface ); TRACE("%p, %s, %p\n", name, debugstr_guid(riid), obj); *obj = NULL; if (IsEqualIID( riid, &IID_IUnknown ) || IsEqualIID( riid, &IID_IAssemblyName )) { IAssemblyName_AddRef( iface ); *obj = name; return S_OK; } return E_NOINTERFACE; } static ULONG WINAPI name_AddRef( IAssemblyName *iface ) { struct name *name = impl_from_IAssemblyName( iface ); return InterlockedIncrement( &name->refs ); } static ULONG WINAPI name_Release( IAssemblyName *iface ) { struct name *name = impl_from_IAssemblyName( iface ); ULONG refs = InterlockedDecrement( &name->refs ); if (!refs) { TRACE("destroying %p\n", name); HeapFree( GetProcessHeap(), 0, name->name ); HeapFree( GetProcessHeap(), 0, name->arch ); HeapFree( GetProcessHeap(), 0, name->token ); HeapFree( GetProcessHeap(), 0, name->type ); HeapFree( GetProcessHeap(), 0, name->version ); HeapFree( GetProcessHeap(), 0, name ); } return refs; } static HRESULT WINAPI name_SetProperty( IAssemblyName *iface, DWORD id, LPVOID property, DWORD size ) { FIXME("%p, %d, %p, %d\n", iface, id, property, size); return E_NOTIMPL; } static HRESULT WINAPI name_GetProperty( IAssemblyName *iface, DWORD id, LPVOID buffer, LPDWORD buflen ) { FIXME("%p, %d, %p, %p\n", iface, id, buffer, buflen); return E_NOTIMPL; } static HRESULT WINAPI name_Finalize( IAssemblyName *iface ) { FIXME("%p\n", iface); return E_NOTIMPL; } static HRESULT WINAPI name_GetDisplayName( IAssemblyName *iface, LPOLESTR buffer, LPDWORD buflen, DWORD flags ) { static const WCHAR fmtW[] = {',','%','s','=','\"','%','s','\"',0}; struct name *name = impl_from_IAssemblyName( iface ); WCHAR version[30]; unsigned int len; TRACE("%p, %p, %p, 0x%08x\n", iface, buffer, buflen, flags); if (!buflen || flags) return E_INVALIDARG; len = strlenW( name->name ) + 1; if (name->arch) len += strlenW( archW ) + strlenW( name->arch ) + 4; if (name->token) len += strlenW( tokenW ) + strlenW( name->token ) + 4; if (name->type) len += strlenW( typeW ) + strlenW( name->type ) + 4; if (name->version) len += strlenW( versionW ) + strlenW( version ) + 4; if (len > *buflen) { *buflen = len; return HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); } strcpyW( buffer, name->name ); len = strlenW( buffer ); if (name->arch) len += sprintfW( buffer + len, fmtW, archW, name->arch ); if (name->token) len += sprintfW( buffer + len, fmtW, tokenW, name->token ); if (name->type) len += sprintfW( buffer + len, fmtW, typeW, name->type ); if (name->version) len += sprintfW( buffer + len, fmtW, versionW, name->version ); return S_OK; } static HRESULT WINAPI name_Reserved( IAssemblyName *iface, REFIID riid, IUnknown *pUnkReserved1, IUnknown *pUnkReserved2, LPCOLESTR szReserved, LONGLONG llReserved, LPVOID pvReserved, DWORD cbReserved, LPVOID *ppReserved ) { FIXME("%p, %s, %p, %p, %s, %x%08x, %p, %d, %p\n", iface, debugstr_guid(riid), pUnkReserved1, pUnkReserved2, debugstr_w(szReserved), (DWORD)(llReserved >> 32), (DWORD)llReserved, pvReserved, cbReserved, ppReserved); return E_NOTIMPL; } const WCHAR *get_name_attribute( IAssemblyName *iface, enum name_attr_id id ) { struct name *name = impl_from_IAssemblyName( iface ); switch (id) { case NAME_ATTR_ID_NAME: return name->name; case NAME_ATTR_ID_ARCH: return name->arch; case NAME_ATTR_ID_TOKEN: return name->token; case NAME_ATTR_ID_TYPE: return name->type; case NAME_ATTR_ID_VERSION: return name->version; default: ERR("unhandled name attribute %u\n", id); break; } return NULL; } static HRESULT WINAPI name_GetName( IAssemblyName *iface, LPDWORD buflen, WCHAR *buffer ) { const WCHAR *name; int len; TRACE("%p, %p, %p\n", iface, buflen, buffer); if (!buflen || !buffer) return E_INVALIDARG; name = get_name_attribute( iface, NAME_ATTR_ID_NAME ); len = strlenW( name ) + 1; if (len > *buflen) { *buflen = len; return HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); } strcpyW( buffer, name ); *buflen = len + 3; return S_OK; } static HRESULT parse_version( WCHAR *version, DWORD *high, DWORD *low ) { WORD ver[4]; WCHAR *p, *q; unsigned int i; memset( ver, 0, sizeof(ver) ); for (i = 0, p = version; i < 4; i++) { if (!*p) break; q = strchrW( p, '.' ); if (q) *q = 0; ver[i] = atolW( p ); if (!q && i < 3) break; p = q + 1; } *high = (ver[0] << 16) + ver[1]; *low = (ver[2] << 16) + ver[3]; return S_OK; } static HRESULT WINAPI name_GetVersion( IAssemblyName *iface, LPDWORD high, LPDWORD low ) { struct name *name = impl_from_IAssemblyName( iface ); WCHAR *version; HRESULT hr; TRACE("%p, %p, %p\n", iface, high, low); if (!name->version) return HRESULT_FROM_WIN32( ERROR_NOT_FOUND ); if (!(version = strdupW( name->version ))) return E_OUTOFMEMORY; hr = parse_version( version, high, low ); HeapFree( GetProcessHeap(), 0, version ); return hr; } static HRESULT WINAPI name_IsEqual( IAssemblyName *name1, IAssemblyName *name2, DWORD flags ) { FIXME("%p, %p, 0x%08x\n", name1, name2, flags); return E_NOTIMPL; } static HRESULT WINAPI name_Clone( IAssemblyName *iface, IAssemblyName **name ) { FIXME("%p, %p\n", iface, name); return E_NOTIMPL; } static const IAssemblyNameVtbl name_vtbl = { name_QueryInterface, name_AddRef, name_Release, name_SetProperty, name_GetProperty, name_Finalize, name_GetDisplayName, name_Reserved, name_GetName, name_GetVersion, name_IsEqual, name_Clone }; static WCHAR *parse_value( const WCHAR *str, unsigned int *len ) { WCHAR *ret; const WCHAR *p = str; if (*p++ != '\"') return NULL; while (*p && *p != '\"') p++; if (!*p) return NULL; *len = p - str; if (!(ret = HeapAlloc( GetProcessHeap(), 0, *len * sizeof(WCHAR) ))) return NULL; memcpy( ret, str + 1, (*len - 1) * sizeof(WCHAR) ); ret[*len - 1] = 0; return ret; } static HRESULT parse_displayname( struct name *name, const WCHAR *displayname ) { const WCHAR *p, *q; unsigned int len; p = q = displayname; while (*q && *q != ',') q++; len = q - p; if (!(name->name = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY; memcpy( name->name, p, len * sizeof(WCHAR) ); name->name[len] = 0; if (!*q) return S_OK; for (;;) { p = ++q; while (*q && *q != '=') q++; if (!*q) return E_INVALIDARG; len = q - p; if (len == sizeof(archW)/sizeof(archW[0]) - 1 && !memcmp( p, archW, len * sizeof(WCHAR) )) { p = ++q; if (!(name->arch = parse_value( p, &len ))) return E_INVALIDARG; q += len; } else if (len == sizeof(tokenW)/sizeof(tokenW[0]) - 1 && !memcmp( p, tokenW, len * sizeof(WCHAR) )) { p = ++q; if (!(name->token = parse_value( p, &len ))) return E_INVALIDARG; q += len; } else if (len == sizeof(typeW)/sizeof(typeW[0]) - 1 && !memcmp( p, typeW, len * sizeof(WCHAR) )) { p = ++q; if (!(name->type = parse_value( p, &len ))) return E_INVALIDARG; q += len; } else if (len == sizeof(versionW)/sizeof(versionW[0]) - 1 && !memcmp( p, versionW, len * sizeof(WCHAR) )) { p = ++q; if (!(name->version = parse_value( p, &len ))) return E_INVALIDARG; q += len; } else return HRESULT_FROM_WIN32( ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME ); while (*q && *q != ',') q++; if (!*q) break; } return S_OK; } /****************************************************************** * CreateAssemblyNameObject (SXS.@) */ HRESULT WINAPI CreateAssemblyNameObject( LPASSEMBLYNAME *obj, LPCWSTR assembly, DWORD flags, LPVOID reserved ) { struct name *name; HRESULT hr; TRACE("%p, %s, 0x%08x, %p\n", obj, debugstr_w(assembly), flags, reserved); if (!obj) return E_INVALIDARG; *obj = NULL; if (!assembly || !assembly[0] || flags != CANOF_PARSE_DISPLAY_NAME) return E_INVALIDARG; if (!(name = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*name) ))) return E_OUTOFMEMORY; name->IAssemblyName_iface.lpVtbl = &name_vtbl; name->refs = 1; hr = parse_displayname( name, assembly ); if (hr != S_OK) { HeapFree( GetProcessHeap(), 0, name->name ); HeapFree( GetProcessHeap(), 0, name->arch ); HeapFree( GetProcessHeap(), 0, name->token ); HeapFree( GetProcessHeap(), 0, name->type ); HeapFree( GetProcessHeap(), 0, name->version ); HeapFree( GetProcessHeap(), 0, name ); return hr; } *obj = &name->IAssemblyName_iface; return S_OK; }