Module: wine Branch: master Commit: 5a6b9ec329e852345599d5f18cd5461c8eff48fc URL: http://source.winehq.org/git/wine.git/?a=commit;h=5a6b9ec329e852345599d5f18c...
Author: Hans Leidekker hans@codeweavers.com Date: Wed Mar 28 15:33:30 2012 +0200
sxs: Parse the display name in CreateAssemblyNameObject.
---
dlls/sxs/name.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++-- dlls/sxs/sxs_private.h | 38 +++++++++ 2 files changed, 227 insertions(+), 7 deletions(-)
diff --git a/dlls/sxs/name.c b/dlls/sxs/name.c index 1adeebd..9ca911b 100644 --- a/dlls/sxs/name.c +++ b/dlls/sxs/name.c @@ -28,6 +28,8 @@ #include "winsxs.h"
#include "wine/debug.h" +#include "wine/unicode.h" +#include "sxs_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(sxs);
@@ -35,8 +37,18 @@ 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 ); @@ -79,6 +91,11 @@ static ULONG WINAPI name_Release( IAssemblyName *iface ) 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; @@ -117,8 +134,32 @@ static HRESULT WINAPI name_GetDisplayName( LPDWORD buflen, DWORD flags ) { - FIXME("%p, %p, %p, 0x%08x\n", iface, buffer, buflen, flags); - return E_NOTIMPL; + 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( @@ -139,22 +180,85 @@ static HRESULT WINAPI name_Reserved( 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 ) { - FIXME("%p, %p, %p\n", iface, buflen, buffer); - return E_NOTIMPL; + 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 hi, + LPDWORD high, LPDWORD low ) { - FIXME("%p, %p, %p\n", iface, hi, low); - return E_NOTIMPL; + 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( @@ -190,6 +294,72 @@ static const IAssemblyNameVtbl name_vtbl = 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.@) */ @@ -200,6 +370,7 @@ HRESULT WINAPI CreateAssemblyNameObject( LPVOID reserved ) { struct name *name; + HRESULT hr;
TRACE("%p, %s, 0x%08x, %p\n", obj, debugstr_w(assembly), flags, reserved);
@@ -215,6 +386,17 @@ HRESULT WINAPI CreateAssemblyNameObject( 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; } diff --git a/dlls/sxs/sxs_private.h b/dlls/sxs/sxs_private.h new file mode 100644 index 0000000..8ff9920 --- /dev/null +++ b/dlls/sxs/sxs_private.h @@ -0,0 +1,38 @@ +/* + * 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 + */ + +enum name_attr_id +{ + NAME_ATTR_ID_NAME, + NAME_ATTR_ID_ARCH, + NAME_ATTR_ID_TOKEN, + NAME_ATTR_ID_TYPE, + NAME_ATTR_ID_VERSION +}; + +const WCHAR *get_name_attribute( IAssemblyName *, enum name_attr_id ); + +static inline WCHAR *strdupW( const WCHAR *src ) +{ + WCHAR *dst; + + if (!src) return NULL; + dst = HeapAlloc( GetProcessHeap(), 0, (strlenW( src ) + 1) * sizeof(WCHAR) ); + if (dst) strcpyW( dst, src ); + return dst; +}