[SXS]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 19 May 2012 14:52:48 +0000 (14:52 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 19 May 2012 14:52:48 +0000 (14:52 +0000)
* Sync to Wine 1.5.4.

svn path=/trunk/; revision=56633

reactos/dll/win32/sxs/CMakeLists.txt
reactos/dll/win32/sxs/cache.c
reactos/dll/win32/sxs/name.c [new file with mode: 0644]
reactos/dll/win32/sxs/sxs.spec
reactos/dll/win32/sxs/sxs_private.h [new file with mode: 0644]
reactos/include/psdk/winsxs.idl
reactos/media/doc/README.WINE

index a009000..d2db519 100644 (file)
@@ -2,10 +2,11 @@
 include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
 add_definitions(-D__WINESRC__)
 
-spec2def(sxs.dll sxs.spec)
+spec2def(sxs.dll sxs.spec ADD_IMPORTLIB)
 
 list(APPEND SOURCE
     cache.c
+    name.c
     sxs.c
     ${CMAKE_CURRENT_BINARY_DIR}/sxs_stubs.c
     ${CMAKE_CURRENT_BINARY_DIR}/sxs.def)
index af19e60..46686e5 100644 (file)
 #include "wine/debug.h"
 #include "wine/list.h"
 #include "wine/unicode.h"
+#include "sxs_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(sxs);
 
-static inline WCHAR *strdupW( const WCHAR *s )
-{
-    WCHAR *t;
-    if (!s) return NULL;
-    if ((t = HeapAlloc( GetProcessHeap(), 0, (strlenW( s ) + 1) * sizeof(WCHAR) ))) strcpyW( t, s );
-    return t;
-}
+static const WCHAR cache_mutex_nameW[] =
+    {'_','_','W','I','N','E','_','S','X','S','_','C','A','C','H','E','_','M','U','T','E','X','_','_',0};
+
+static const WCHAR win32W[] = {'w','i','n','3','2',0};
+static const WCHAR win32_policyW[] = {'w','i','n','3','2','-','p','o','l','i','c','y',0};
+static const WCHAR backslashW[] = {'\\',0};
 
 struct cache
 {
     IAssemblyCache IAssemblyCache_iface;
     LONG refs;
+    HANDLE lock;
 };
 
 static inline struct cache *impl_from_IAssemblyCache(IAssemblyCache *iface)
@@ -90,30 +91,185 @@ static ULONG WINAPI cache_Release( IAssemblyCache *iface )
     if (!refs)
     {
         TRACE("destroying %p\n", cache);
+        CloseHandle( cache->lock );
         HeapFree( GetProcessHeap(), 0, cache );
     }
     return refs;
 }
 
-static HRESULT WINAPI cache_UninstallAssembly(
-    IAssemblyCache *iface,
-    DWORD flags,
-    LPCWSTR name,
-    LPCFUSION_INSTALL_REFERENCE ref,
-    ULONG *disp )
+static unsigned int build_sxs_path( WCHAR *path )
 {
-    FIXME("%p, 0x%08x, %s, %p, %p\n", iface, flags, debugstr_w(name), ref, disp);
-    return E_NOTIMPL;
+    static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\',0};
+    unsigned int len = GetWindowsDirectoryW( path, MAX_PATH );
+
+    memcpy( path + len, winsxsW, sizeof(winsxsW) );
+    return len + sizeof(winsxsW) / sizeof(winsxsW[0]) - 1;
+}
+
+static WCHAR *build_assembly_name( const WCHAR *arch, const WCHAR *name, const WCHAR *token,
+                                   const WCHAR *version, unsigned int *len )
+{
+    static const WCHAR fmtW[] =
+        {'%','s','_','%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0};
+    unsigned int buflen = sizeof(fmtW) / sizeof(fmtW[0]);
+    WCHAR *ret, *p;
+
+    buflen += strlenW( arch );
+    buflen += strlenW( name );
+    buflen += strlenW( token );
+    buflen += strlenW( version );
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, buflen * sizeof(WCHAR) ))) return NULL;
+    *len = sprintfW( ret, fmtW, arch, name, token, version );
+    for (p = ret; *p; p++) *p = tolowerW( *p );
+    return ret;
 }
 
+static WCHAR *build_manifest_path( const WCHAR *arch, const WCHAR *name, const WCHAR *token,
+                                   const WCHAR *version )
+{
+    static const WCHAR fmtW[] =
+        {'%','s','m','a','n','i','f','e','s','t','s','\\','%','s','.','m','a','n','i','f','e','s','t',0};
+    WCHAR *path = NULL, *ret, sxsdir[MAX_PATH];
+    unsigned int len;
+
+    if (!(path = build_assembly_name( arch, name, token, version, &len ))) return NULL;
+    len += sizeof(fmtW) / sizeof(fmtW[0]);
+    len += build_sxs_path( sxsdir );
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+    {
+        HeapFree( GetProcessHeap(), 0, path );
+        return NULL;
+    }
+    sprintfW( ret, fmtW, sxsdir, path );
+    HeapFree( GetProcessHeap(), 0, path );
+    return ret;
+}
+
+static WCHAR *build_policy_name( const WCHAR *arch, const WCHAR *name, const WCHAR *token,
+                                 unsigned int *len )
+{
+    static const WCHAR fmtW[] =
+        {'%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0};
+    unsigned int buflen = sizeof(fmtW) / sizeof(fmtW[0]);
+    WCHAR *ret, *p;
+
+    buflen += strlenW( arch );
+    buflen += strlenW( name );
+    buflen += strlenW( token );
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, buflen * sizeof(WCHAR) ))) return NULL;
+    *len = sprintfW( ret, fmtW, arch, name, token );
+    for (p = ret; *p; p++) *p = tolowerW( *p );
+    return ret;
+}
+
+static WCHAR *build_policy_path( const WCHAR *arch, const WCHAR *name, const WCHAR *token,
+                                 const WCHAR *version )
+{
+    static const WCHAR fmtW[] =
+        {'%','s','p','o','l','i','c','i','e','s','\\','%','s','\\','%','s','.','p','o','l','i','c','y',0};
+    WCHAR *path = NULL, *ret, sxsdir[MAX_PATH];
+    unsigned int len;
+
+    if (!(path = build_policy_name( arch, name, token, &len ))) return NULL;
+    len += sizeof(fmtW) / sizeof(fmtW[0]);
+    len += build_sxs_path( sxsdir );
+    len += strlenW( version );
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+    {
+        HeapFree( GetProcessHeap(), 0, path );
+        return NULL;
+    }
+    sprintfW( ret, fmtW, sxsdir, path, version );
+    HeapFree( GetProcessHeap(), 0, path );
+    return ret;
+}
+
+static void cache_lock( struct cache *cache )
+{
+    WaitForSingleObject( cache->lock, INFINITE );
+}
+
+static void cache_unlock( struct cache *cache )
+{
+    ReleaseMutex( cache->lock );
+}
+
+#define ASSEMBLYINFO_FLAG_INSTALLED 1
+
 static HRESULT WINAPI cache_QueryAssemblyInfo(
     IAssemblyCache *iface,
     DWORD flags,
-    LPCWSTR name,
+    LPCWSTR assembly_name,
     ASSEMBLY_INFO *info )
 {
-    FIXME("%p, 0x%08x, %s, %p\n", iface, flags, debugstr_w(name), info);
-    return E_NOTIMPL;
+    struct cache *cache = impl_from_IAssemblyCache( iface );
+    IAssemblyName *name_obj;
+    const WCHAR *arch, *name, *token, *type, *version;
+    WCHAR *p, *path = NULL;
+    unsigned int len;
+    HRESULT hr;
+
+    TRACE("%p, 0x%08x, %s, %p\n", iface, flags, debugstr_w(assembly_name), info);
+
+    if (flags || (info && info->cbAssemblyInfo != sizeof(*info)))
+        return E_INVALIDARG;
+
+    hr = CreateAssemblyNameObject( &name_obj, assembly_name, CANOF_PARSE_DISPLAY_NAME, 0 );
+    if (FAILED( hr ))
+        return hr;
+
+    arch = get_name_attribute( name_obj, NAME_ATTR_ID_ARCH );
+    name = get_name_attribute( name_obj, NAME_ATTR_ID_NAME );
+    token = get_name_attribute( name_obj, NAME_ATTR_ID_TOKEN );
+    type = get_name_attribute( name_obj, NAME_ATTR_ID_TYPE );
+    version = get_name_attribute( name_obj, NAME_ATTR_ID_VERSION );
+    if (!arch || !name || !token || !type || !version)
+    {
+        IAssemblyName_Release( name_obj );
+        return HRESULT_FROM_WIN32( ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE );
+    }
+    if (!info)
+    {
+        IAssemblyName_Release( name_obj );
+        return S_OK;
+    }
+    cache_lock( cache );
+
+    if (!strcmpW( type, win32W )) path = build_manifest_path( arch, name, token, version );
+    else if (!strcmpW( type, win32_policyW )) path = build_policy_path( arch, name, token, version );
+    else
+    {
+        hr = HRESULT_FROM_WIN32( ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE );
+        goto done;
+    }
+    if (!path)
+    {
+        hr = E_OUTOFMEMORY;
+        goto done;
+    }
+    hr = S_OK;
+    if (GetFileAttributesW( path ) != INVALID_FILE_ATTRIBUTES) /* FIXME: better check */
+    {
+        info->dwAssemblyFlags = ASSEMBLYINFO_FLAG_INSTALLED;
+        TRACE("assembly is installed\n");
+    }
+    if ((p = strrchrW( path, '\\' ))) *p = 0;
+    len = strlenW( path ) + 1;
+    if (info->pszCurrentAssemblyPathBuf)
+    {
+        if (info->cchBuf < len)
+        {
+            info->cchBuf = len;
+            hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
+        }
+        else strcpyW( info->pszCurrentAssemblyPathBuf, path );
+    }
+
+done:
+    HeapFree( GetProcessHeap(), 0, path );
+    IAssemblyName_Release( name_obj );
+    cache_unlock( cache );
+    return hr;
 }
 
 static HRESULT WINAPI cache_CreateAssemblyCacheItem(
@@ -274,8 +430,6 @@ static HRESULT parse_assembly( IXMLDOMDocument *doc, struct assembly **assembly
     static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
     static const WCHAR architectureW[] = {'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 win32W[] = {'w','i','n','3','2',0};
-    static const WCHAR policyW[] = {'w','i','n','3','2','-','p','o','l','i','c','y',0};
     IXMLDOMNodeList *list = NULL;
     IXMLDOMNode *node = NULL;
     IXMLDOMNamedNodeMap *attrs = NULL;
@@ -319,7 +473,7 @@ static HRESULT parse_assembly( IXMLDOMDocument *doc, struct assembly **assembly
     a->arch    = get_attribute_value( attrs, architectureW );
     a->token   = get_attribute_value( attrs, tokenW );
 
-    if (!a->type || (strcmpW( a->type, win32W ) && strcmpW( a->type, policyW )) ||
+    if (!a->type || (strcmpW( a->type, win32W ) && strcmpW( a->type, win32_policyW )) ||
         !a->name || !a->version || !a->arch || !a->token)
     {
         WARN("invalid win32 assembly\n");
@@ -337,97 +491,56 @@ done:
     return hr;
 }
 
-static WCHAR *build_sxs_path( void )
+static WCHAR *build_policy_filename( const WCHAR *arch, const WCHAR *name, const WCHAR *token,
+                                     const WCHAR *version )
 {
-    static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\',0};
-    WCHAR sxsdir[MAX_PATH];
-
-    GetWindowsDirectoryW( sxsdir, MAX_PATH );
-    strcatW( sxsdir, winsxsW );
-    return strdupW( sxsdir );
-}
-
-static WCHAR *build_assembly_name( struct assembly *assembly )
-{
-    static const WCHAR fmtW[] =
-        {'%','s','_','%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0};
-    WCHAR *ret, *p;
-    int len;
-
-    len = strlenW( fmtW );
-    len += strlenW( assembly->arch );
-    len += strlenW( assembly->name );
-    len += strlenW( assembly->token );
-    len += strlenW( assembly->version );
-
-    if (!(ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
-    sprintfW( ret, fmtW, assembly->arch, assembly->name, assembly->token, assembly->version );
-    for (p = ret; *p; p++) *p = tolowerW( *p );
-    return ret;
-}
-
-static WCHAR *build_policy_name( struct assembly *assembly )
-{
-    static const WCHAR fmtW[] =
-        {'%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0};
-    WCHAR *ret, *p;
-    int len;
-
-    len = strlenW( fmtW );
-    len += strlenW( assembly->arch );
-    len += strlenW( assembly->name );
-    len += strlenW( assembly->token );
-
-    if (!(ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
-    sprintfW( ret, fmtW, assembly->arch, assembly->name, assembly->token );
-    for (p = ret; *p; p++) *p = tolowerW( *p );
+    static const WCHAR policiesW[] = {'p','o','l','i','c','i','e','s','\\',0};
+    static const WCHAR suffixW[] = {'.','p','o','l','i','c','y',0};
+    WCHAR sxsdir[MAX_PATH], *ret, *fullname;
+    unsigned int len;
+
+    if (!(fullname = build_policy_name( arch, name, token, &len ))) return NULL;
+    len += build_sxs_path( sxsdir );
+    len += sizeof(policiesW) / sizeof(policiesW[0]) - 1;
+    len += strlenW( version );
+    len += sizeof(suffixW) / sizeof(suffixW[0]) - 1;
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
+    {
+        HeapFree( GetProcessHeap(), 0, fullname );
+        return NULL;
+    }
+    strcpyW( ret, sxsdir );
+    strcatW( ret, policiesW );
+    CreateDirectoryW( ret, NULL );
+    strcatW( ret, name );
+    CreateDirectoryW( ret, NULL );
+    strcatW( ret, backslashW );
+    strcatW( ret, version );
+    strcatW( ret, suffixW );
+
+    HeapFree( GetProcessHeap(), 0, fullname );
     return ret;
 }
 
 static HRESULT install_policy( const WCHAR *manifest, struct assembly *assembly )
 {
-    static const WCHAR policiesW[] = {'p','o','l','i','c','i','e','s','\\',0};
-    static const WCHAR suffixW[] = {'.','p','o','l','i','c','y',0};
-    static const WCHAR backslashW[] = {'\\',0};
-    WCHAR *sxsdir, *name, *dst;
-    HRESULT hr = E_OUTOFMEMORY;
+    WCHAR *dst;
     BOOL ret;
-    int len;
 
     /* FIXME: handle catalog file */
 
-    if (!(sxsdir = build_sxs_path())) return E_OUTOFMEMORY;
-    if (!(name = build_policy_name( assembly ))) goto done;
-
-    len = strlenW( sxsdir );
-    len += strlenW( policiesW );
-    len += strlenW( name ) + 1;
-    len += strlenW( assembly->version );
-    len += strlenW( suffixW );
-
-    if (!(dst = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) goto done;
-    strcpyW( dst, sxsdir );
-    strcatW( dst, policiesW );
-    CreateDirectoryW( dst, NULL );
-    strcatW( dst, name );
-    CreateDirectoryW( dst, NULL );
-    strcatW( dst, backslashW );
-    strcatW( dst, assembly->version );
-    strcatW( dst, suffixW );
+    dst = build_policy_filename( assembly->arch, assembly->name, assembly->token, assembly->version );
+    if (!dst) return E_OUTOFMEMORY;
 
     ret = CopyFileW( manifest, dst, FALSE );
     HeapFree( GetProcessHeap(), 0, dst );
     if (!ret)
     {
-        hr = HRESULT_FROM_WIN32( GetLastError() );
+        HRESULT hr = HRESULT_FROM_WIN32( GetLastError() );
         WARN("failed to copy policy manifest file 0x%08x\n", hr);
+        return hr;
     }
-    hr = S_OK;
-
-done:
-    HeapFree( GetProcessHeap(), 0, sxsdir );
-    HeapFree( GetProcessHeap(), 0, name );
-    return hr;
+    return S_OK;
 }
 
 static WCHAR *build_source_filename( const WCHAR *manifest, struct file *file )
@@ -449,29 +562,64 @@ static WCHAR *build_source_filename( const WCHAR *manifest, struct file *file )
     return src;
 }
 
-static HRESULT install_assembly( const WCHAR *manifest, struct assembly *assembly )
+static WCHAR *build_manifest_filename( const WCHAR *arch, const WCHAR *name, const WCHAR *token,
+                                       const WCHAR *version )
 {
     static const WCHAR manifestsW[] = {'m','a','n','i','f','e','s','t','s','\\',0};
     static const WCHAR suffixW[] = {'.','m','a','n','i','f','e','s','t',0};
-    static const WCHAR backslashW[] = {'\\',0};
-    WCHAR *sxsdir, *p, *name, *dst, *src;
+    WCHAR sxsdir[MAX_PATH], *ret, *fullname;
+    unsigned int len;
+
+    if (!(fullname = build_assembly_name( arch, name, token, version, &len ))) return NULL;
+    len += build_sxs_path( sxsdir );
+    len += sizeof(manifestsW) / sizeof(manifestsW[0]) - 1;
+    len += sizeof(suffixW) / sizeof(suffixW[0]) - 1;
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
+    {
+        HeapFree( GetProcessHeap(), 0, fullname );
+        return NULL;
+    }
+    strcpyW( ret, sxsdir );
+    strcatW( ret, manifestsW );
+    strcatW( ret, fullname );
+    strcatW( ret, suffixW );
+
+    HeapFree( GetProcessHeap(), 0, fullname );
+    return ret;
+}
+
+static HRESULT load_manifest( IXMLDOMDocument *doc, const WCHAR *filename )
+{
+    HRESULT hr;
+    VARIANT var;
+    VARIANT_BOOL b;
+    BSTR str;
+
+    str = SysAllocString( filename );
+    VariantInit( &var );
+    V_VT( &var ) = VT_BSTR;
+    V_BSTR( &var ) = str;
+    hr = IXMLDOMDocument_load( doc, var, &b );
+    SysFreeString( str );
+    if (hr != S_OK) return hr;
+    if (!b)
+    {
+        WARN("failed to load manifest\n");
+        return S_FALSE;
+    }
+    return S_OK;
+}
+
+static HRESULT install_assembly( const WCHAR *manifest, struct assembly *assembly )
+{
+    WCHAR sxsdir[MAX_PATH], *p, *name, *dst, *src;
+    unsigned int len, len_name, len_sxsdir = build_sxs_path( sxsdir );
     struct file *file;
     HRESULT hr = E_OUTOFMEMORY;
     BOOL ret;
-    int len;
 
-    if (!(sxsdir = build_sxs_path())) return E_OUTOFMEMORY;
-    if (!(name = build_assembly_name( assembly ))) goto done;
-
-    len = strlenW( sxsdir );
-    len += strlenW( manifestsW );
-    len += strlenW( name );
-    len += strlenW( suffixW );
-    if (!(dst = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) goto done;
-    strcpyW( dst, sxsdir );
-    strcatW( dst, manifestsW );
-    strcatW( dst, name );
-    strcatW( dst, suffixW );
+    dst = build_manifest_filename( assembly->arch, assembly->name, assembly->token, assembly->version );
+    if (!dst) return E_OUTOFMEMORY;
 
     ret = CopyFileW( manifest, dst, FALSE );
     HeapFree( GetProcessHeap(), 0, dst );
@@ -479,22 +627,22 @@ static HRESULT install_assembly( const WCHAR *manifest, struct assembly *assembl
     {
         hr = HRESULT_FROM_WIN32( GetLastError() );
         WARN("failed to copy manifest file 0x%08x\n", hr);
-        goto done;
+        return hr;
     }
 
+    name = build_assembly_name( assembly->arch, assembly->name, assembly->token, assembly->version,
+                                &len_name );
+    if (!name) return E_OUTOFMEMORY;
+
     /* FIXME: this should be a transaction */
     LIST_FOR_EACH_ENTRY( file, &assembly->files, struct file, entry )
     {
-        if (!(src = build_source_filename( manifest, file )))
-        {
-            hr = E_OUTOFMEMORY;
-            goto done;
-        }
-        len = strlenW( sxsdir ) + strlenW( name ) + strlenW( file->name );
+        if (!(src = build_source_filename( manifest, file ))) goto done;
+
+        len = len_sxsdir + len_name + strlenW( file->name );
         if (!(dst = HeapAlloc( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) )))
         {
             HeapFree( GetProcessHeap(), 0, src );
-            hr = E_OUTOFMEMORY;
             goto done;
         }
         strcpyW( dst, sxsdir );
@@ -518,7 +666,6 @@ static HRESULT install_assembly( const WCHAR *manifest, struct assembly *assembl
     hr = S_OK;
 
 done:
-    HeapFree( GetProcessHeap(), 0, sxsdir );
     HeapFree( GetProcessHeap(), 0, name );
     return hr;
 }
@@ -529,43 +676,26 @@ static HRESULT WINAPI cache_InstallAssembly(
     LPCWSTR path,
     LPCFUSION_INSTALL_REFERENCE ref )
 {
-    static const WCHAR policyW[] = {'w','i','n','3','2','-','p','o','l','i','c','y',0};
+    struct cache *cache = impl_from_IAssemblyCache( iface );
     HRESULT hr, init;
     IXMLDOMDocument *doc = NULL;
     struct assembly *assembly = NULL;
-    BSTR str;
-    VARIANT var;
-    VARIANT_BOOL b;
 
     TRACE("%p, 0x%08x, %s, %p\n", iface, flags, debugstr_w(path), ref);
 
+    cache_lock( cache );
     init = CoInitialize( NULL );
 
     hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&doc );
     if (hr != S_OK)
         goto done;
 
-    str = SysAllocString( path );
-    VariantInit( &var );
-    V_VT( &var ) = VT_BSTR;
-    V_BSTR( &var ) = str;
-    hr = IXMLDOMDocument_load( doc, var, &b );
-    SysFreeString( str );
-    if (hr != S_OK) goto done;
-    if (!b)
-    {
-        WARN("failed to load manifest\n");
-        hr = S_FALSE;
-        goto done;
-    }
-
-    hr = parse_assembly( doc, &assembly );
-    if (hr != S_OK)
-        goto done;
+    if ((hr = load_manifest( doc, path )) != S_OK) goto done;
+    if ((hr = parse_assembly( doc, &assembly )) != S_OK) goto done;
 
     /* FIXME: verify name attributes */
 
-    if (!strcmpW( assembly->type, policyW ))
+    if (!strcmpW( assembly->type, win32_policyW ))
         hr = install_policy( path, assembly );
     else
         hr = install_assembly( path, assembly );
@@ -573,10 +703,115 @@ static HRESULT WINAPI cache_InstallAssembly(
 done:
     free_assembly( assembly );
     if (doc) IXMLDOMDocument_Release( doc );
+    if (SUCCEEDED(init)) CoUninitialize();
+    cache_unlock( cache );
+    return hr;
+}
+
+static HRESULT uninstall_assembly( struct assembly *assembly )
+{
+    WCHAR sxsdir[MAX_PATH], *name, *dirname, *filename;
+    unsigned int len, len_name, len_sxsdir = build_sxs_path( sxsdir );
+    HRESULT hr = E_OUTOFMEMORY;
+    struct file *file;
+
+    name = build_assembly_name( assembly->arch, assembly->name, assembly->token, assembly->version,
+                                &len_name );
+    if (!name) return E_OUTOFMEMORY;
+    if (!(dirname = HeapAlloc( GetProcessHeap(), 0, (len_sxsdir + len_name + 1) * sizeof(WCHAR) )))
+        goto done;
+    strcpyW( dirname, sxsdir );
+    strcpyW( dirname + len_sxsdir, name );
+
+    LIST_FOR_EACH_ENTRY( file, &assembly->files, struct file, entry )
+    {
+        len = len_sxsdir + len_name + 1 + strlenW( file->name );
+        if (!(filename = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) goto done;
+        strcpyW( filename, dirname );
+        strcatW( filename, backslashW );
+        strcatW( filename, file->name );
+
+        if (!DeleteFileW( filename )) WARN( "failed to delete file %u\n", GetLastError() );
+        HeapFree( GetProcessHeap(), 0, filename );
+    }
+    RemoveDirectoryW( dirname );
+    hr = S_OK;
+
+done:
+    HeapFree( GetProcessHeap(), 0, dirname );
+    HeapFree( GetProcessHeap(), 0, name );
+    return hr;
+}
+
+static HRESULT WINAPI cache_UninstallAssembly(
+    IAssemblyCache *iface,
+    DWORD flags,
+    LPCWSTR assembly_name,
+    LPCFUSION_INSTALL_REFERENCE ref,
+    ULONG *disp )
+{
+    struct cache *cache = impl_from_IAssemblyCache( iface );
+    HRESULT hr, init;
+    IXMLDOMDocument *doc = NULL;
+    struct assembly *assembly = NULL;
+    IAssemblyName *name_obj = NULL;
+    const WCHAR *arch, *name, *token, *type, *version;
+    WCHAR *p, *path = NULL;
 
-    if (SUCCEEDED(init))
-        CoUninitialize();
+    TRACE("%p, 0x%08x, %s, %p, %p\n", iface, flags, debugstr_w(assembly_name), ref, disp);
 
+    if (ref)
+    {
+        FIXME("application reference not supported\n");
+        return E_NOTIMPL;
+    }
+    cache_lock( cache );
+    init = CoInitialize( NULL );
+
+    hr = CreateAssemblyNameObject( &name_obj, assembly_name, CANOF_PARSE_DISPLAY_NAME, NULL );
+    if (FAILED( hr ))
+        goto done;
+
+    arch = get_name_attribute( name_obj, NAME_ATTR_ID_ARCH );
+    name = get_name_attribute( name_obj, NAME_ATTR_ID_NAME );
+    token = get_name_attribute( name_obj, NAME_ATTR_ID_TOKEN );
+    type = get_name_attribute( name_obj, NAME_ATTR_ID_TYPE );
+    version = get_name_attribute( name_obj, NAME_ATTR_ID_VERSION );
+    if (!arch || !name || !token || !type || !version)
+    {
+        hr = E_INVALIDARG;
+        goto done;
+    }
+    if (!strcmpW( type, win32W )) path = build_manifest_filename( arch, name, token, version );
+    else if (!strcmpW( type, win32_policyW )) path = build_policy_filename( arch, name, token, version );
+    else
+    {
+        hr = E_INVALIDARG;
+        goto done;
+    }
+
+    hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&doc );
+    if (hr != S_OK)
+        goto done;
+
+    if ((hr = load_manifest( doc, path )) != S_OK) goto done;
+    if ((hr = parse_assembly( doc, &assembly )) != S_OK) goto done;
+
+    if (!DeleteFileW( path )) WARN( "unable to remove manifest file %u\n", GetLastError() );
+    else if ((p = strrchrW( path, '\\' )))
+    {
+        *p = 0;
+        RemoveDirectoryW( path );
+    }
+    if (!strcmpW( assembly->type, win32W )) hr = uninstall_assembly( assembly );
+
+done:
+    if (name_obj) IAssemblyName_Release( name_obj );
+    HeapFree( GetProcessHeap(), 0, path );
+    free_assembly( assembly );
+    if (doc) IXMLDOMDocument_Release( doc );
+    if (SUCCEEDED(init)) CoUninitialize();
+    cache_unlock( cache );
     return hr;
 }
 
@@ -612,7 +847,12 @@ HRESULT WINAPI CreateAssemblyCache( IAssemblyCache **obj, DWORD reserved )
 
     cache->IAssemblyCache_iface.lpVtbl = &cache_vtbl;
     cache->refs = 1;
-
+    cache->lock = CreateMutexW( NULL, FALSE, cache_mutex_nameW );
+    if (!cache->lock)
+    {
+        HeapFree( GetProcessHeap(), 0, cache );
+        return HRESULT_FROM_WIN32( GetLastError() );
+    }
     *obj = &cache->IAssemblyCache_iface;
     return S_OK;
 }
diff --git a/reactos/dll/win32/sxs/name.c b/reactos/dll/win32/sxs/name.c
new file mode 100644 (file)
index 0000000..9ca911b
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * 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 ))
+    {
+        IUnknown_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;
+}
index e199bb1..2a27313 100644 (file)
@@ -1,2 +1,2 @@
 @ stdcall CreateAssemblyCache(ptr long)
-@ stub CreateAssemblyNameObject
+@ stdcall CreateAssemblyNameObject(ptr wstr long ptr)
diff --git a/reactos/dll/win32/sxs/sxs_private.h b/reactos/dll/win32/sxs/sxs_private.h
new file mode 100644 (file)
index 0000000..8ff9920
--- /dev/null
@@ -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;
+}
index 202b91f..775c69a 100644 (file)
@@ -21,6 +21,7 @@ import "oleidl.idl";
 
 interface IAssemblyCache;
 interface IAssemblyCacheItem;
+interface IAssemblyName;
 
 typedef struct _FUSION_INSTALL_REFERENCE_
 {
@@ -99,4 +100,99 @@ interface IAssemblyCacheItem : IUnknown
     HRESULT AbortItem();
 }
 
+[
+    object,
+    uuid(cd193bc0-b4bc-11D2-9833-00c04fc31d2e),
+    pointer_default(unique),
+    local
+]
+interface IAssemblyName : IUnknown
+{
+    typedef [public] enum
+    {
+        ASM_NAME_PUBLIC_KEY,
+        ASM_NAME_PUBLIC_KEY_TOKEN,
+        ASM_NAME_HASH_VALUE,
+        ASM_NAME_NAME,
+        ASM_NAME_MAJOR_VERSION,
+        ASM_NAME_MINOR_VERSION,
+        ASM_NAME_BUILD_NUMBER,
+        ASM_NAME_REVISION_NUMBER,
+        ASM_NAME_CULTURE,
+        ASM_NAME_PROCESSOR_ID_ARRAY,
+        ASM_NAME_OSINFO_ARRAY,
+        ASM_NAME_HASH_ALGID,
+        ASM_NAME_ALIAS,
+        ASM_NAME_CODEBASE_URL,
+        ASM_NAME_CODEBASE_LASTMOD,
+        ASM_NAME_NULL_PUBLIC_KEY,
+        ASM_NAME_NULL_PUBLIC_KEY_TOKEN,
+        ASM_NAME_CUSTOM,
+        ASM_NAME_NULL_CUSTOM,
+        ASM_NAME_MVID,
+        ASM_NAME_MAX_PARAMS
+    } ASM_NAME;
+
+    typedef [public] enum
+    {
+        ASM_DISPLAYF_VERSION               = 0x1,
+        ASM_DISPLAYF_CULTURE               = 0x2,
+        ASM_DISPLAYF_PUBLIC_KEY_TOKEN      = 0x4,
+        ASM_DISPLAYF_PUBLIC_KEY            = 0x8,
+        ASM_DISPLAYF_CUSTOM                = 0x10,
+        ASM_DISPLAYF_PROCESSORARCHITECTURE = 0x20,
+        ASM_DISPLAYF_LANGUAGEID            = 0x40
+    } ASM_DISPLAY_FLAGS;
+
+    HRESULT SetProperty(
+        [in] DWORD id,
+        [in] LPVOID property,
+        [in] DWORD size);
+
+    HRESULT GetProperty(
+        [in] DWORD id,
+        [out] LPVOID buffer,
+        [in][out] LPDWORD buflen);
+
+    HRESULT Finalize();
+
+    HRESULT GetDisplayName(
+        [out] LPWSTR buffer,
+        [in][out] LPDWORD buflen,
+        [in] DWORD flags);
+
+    HRESULT Reserved(
+        [in] REFIID riid,
+        [in] IUnknown *pUnkReserved1,
+        [in] IUnknown *pUnkReserved2,
+        [in] LPCOLESTR szReserved,
+        [in] LONGLONG llReserved,
+        [in] LPVOID pvReserved,
+        [in] DWORD cbReserved,
+        [out] LPVOID *ppReserved);
+
+    HRESULT GetName(
+        [in][out] LPDWORD buflen,
+        [out] LPWSTR buffer);
+
+    HRESULT GetVersion(
+        [out] LPDWORD hi,
+        [out] LPDWORD low);
+
+    HRESULT IsEqual(
+        [in] IAssemblyName *name,
+        [in] DWORD flags);
+
+    HRESULT Clone(
+        [out] IAssemblyName **name);
+}
+
+typedef [unique] IAssemblyName *LPASSEMBLYNAME;
+typedef [public] enum
+{
+    CANOF_PARSE_DISPLAY_NAME = 0x1,
+    CANOF_SET_DEFAULT_VALUES = 0x2
+} CREATE_ASM_NAME_OBJ_FLAGS;
+
 cpp_quote("HRESULT WINAPI CreateAssemblyCache(IAssemblyCache**,DWORD);")
+cpp_quote("HRESULT WINAPI CreateAssemblyNameObject(LPASSEMBLYNAME *,LPCWSTR,DWORD,LPVOID);")
index 940b3ac..2c76184 100644 (file)
@@ -161,7 +161,7 @@ reactos/dll/win32/spoolss         # Synced to Wine-1.5.4
 reactos/dll/win32/stdole2.tlb     # Synced to Wine-1.3.37
 reactos/dll/win32/stdole32.tlb    # Synced to Wine-1.3.37
 reactos/dll/win32/sti             # Synced to Wine-1.5.4
-reactos/dll/win32/sxs             # Synced to Wine-1.3.37
+reactos/dll/win32/sxs             # Synced to Wine-1.5.4
 reactos/dll/win32/tapi32          # Autosync
 reactos/dll/win32/traffic         # Autosync
 reactos/dll/win32/twain_32        # Out of sync