Hans Leidekker : fusion: Also copy external files in IAssemblyCache:: InstallAssembly.

Alexandre Julliard julliard at winehq.org
Mon Jul 9 14:56:36 CDT 2012


Module: wine
Branch: master
Commit: 45473a65a0a1fe2e61809d80f6d09bb96f923126
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=45473a65a0a1fe2e61809d80f6d09bb96f923126

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri Jul  6 15:51:00 2012 +0200

fusion: Also copy external files in IAssemblyCache::InstallAssembly.

---

 dlls/fusion/asmcache.c   |   79 +++++++++++++++++++++++++++++++++++++++------
 dlls/fusion/assembly.c   |   53 +++++++++++++++++++++++++++++-
 dlls/fusion/fusionpriv.h |    1 +
 3 files changed, 120 insertions(+), 13 deletions(-)

diff --git a/dlls/fusion/asmcache.c b/dlls/fusion/asmcache.c
index 1cba6f6..485a56c 100644
--- a/dlls/fusion/asmcache.c
+++ b/dlls/fusion/asmcache.c
@@ -370,6 +370,32 @@ static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyScavenger(IAssemblyCache
     return E_NOTIMPL;
 }
 
+static HRESULT copy_file( const WCHAR *src_dir, DWORD src_len, const WCHAR *dst_dir, DWORD dst_len,
+                          const WCHAR *filename )
+{
+    WCHAR *src_file, *dst_file;
+    DWORD len = strlenW( filename );
+    HRESULT hr = S_OK;
+
+    if (!(src_file = HeapAlloc( GetProcessHeap(), 0, (src_len + len + 1) * sizeof(WCHAR) )))
+        return E_OUTOFMEMORY;
+    memcpy( src_file, src_dir, src_len * sizeof(WCHAR) );
+    strcpyW( src_file + src_len, filename );
+
+    if (!(dst_file = HeapAlloc( GetProcessHeap(), 0, (dst_len + len + 1) * sizeof(WCHAR) )))
+    {
+        HeapFree( GetProcessHeap(), 0, src_file );
+        return E_OUTOFMEMORY;
+    }
+    memcpy( dst_file, dst_dir, dst_len * sizeof(WCHAR) );
+    strcpyW( dst_file + dst_len, filename );
+
+    if (!CopyFileW( src_file, dst_file, FALSE )) hr = HRESULT_FROM_WIN32( GetLastError() );
+    HeapFree( GetProcessHeap(), 0, src_file );
+    HeapFree( GetProcessHeap(), 0, dst_file );
+    return hr;
+}
+
 static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface,
                                                          DWORD dwFlags,
                                                          LPCWSTR pszManifestFilePath,
@@ -383,11 +409,12 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface,
     static const WCHAR ext_dll[] = {'.','d','l','l',0};
     IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
     ASSEMBLY *assembly;
-    WCHAR *filename, *ext;
+    const WCHAR *extension, *filename, *src_dir;
     WCHAR *name = NULL, *token = NULL, *version = NULL, *asmpath = NULL;
-    WCHAR path[MAX_PATH], asmdir[MAX_PATH];
+    WCHAR asmdir[MAX_PATH], *p, **external_files = NULL, *dst_dir = NULL;
     PEKIND architecture;
     char *clr_version;
+    DWORD i, count = 0, src_len, dst_len = sizeof(format_v40)/sizeof(format_v40[0]);
     HRESULT hr;
 
     TRACE("(%p, %d, %s, %p)\n", iface, dwFlags,
@@ -396,10 +423,10 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface,
     if (!pszManifestFilePath || !*pszManifestFilePath)
         return E_INVALIDARG;
 
-    if (!(ext = strrchrW(pszManifestFilePath, '.')))
+    if (!(extension = strrchrW(pszManifestFilePath, '.')))
         return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
 
-    if (lstrcmpiW(ext, ext_exe) && lstrcmpiW(ext, ext_dll))
+    if (lstrcmpiW(extension, ext_exe) && lstrcmpiW(extension, ext_dll))
         return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
 
     if (GetFileAttributesW(pszManifestFilePath) == INVALID_FILE_ATTRIBUTES)
@@ -428,33 +455,63 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface,
     if (FAILED(hr))
         goto done;
 
+    hr = assembly_get_external_files(assembly, &external_files, &count);
+    if (FAILED(hr))
+        goto done;
+
     cache_lock( cache );
 
     architecture = assembly_get_architecture(assembly);
     get_assembly_directory(asmdir, MAX_PATH, clr_version, architecture);
 
+    dst_len += strlenW(asmdir) + strlenW(name) + strlenW(version) + strlenW(token);
+    if (!(dst_dir = HeapAlloc(GetProcessHeap(), 0, dst_len * sizeof(WCHAR))))
+    {
+        hr = E_OUTOFMEMORY;
+        goto done;
+    }
     if (!strcmp(clr_version, "v4.0.30319"))
-        sprintfW(path, format_v40, asmdir, name, version, token);
+        dst_len = sprintfW(dst_dir, format_v40, asmdir, name, version, token);
     else
-        sprintfW(path, format, asmdir, name, version, token);
+        dst_len = sprintfW(dst_dir, format, asmdir, name, version, token);
 
-    create_full_path(path);
+    create_full_path(dst_dir);
 
     hr = assembly_get_path(assembly, &asmpath);
     if (FAILED(hr))
         goto done;
 
-    filename = PathFindFileNameW(asmpath);
+    if ((p = strrchrW(asmpath, '\\')))
+    {
+        filename = p + 1;
+        src_dir  = asmpath;
+        src_len  = filename - asmpath;
+    }
+    else
+    {
+        filename = asmpath;
+        src_dir  = NULL;
+        src_len  = 0;
+    }
+    hr = copy_file(src_dir, src_len, dst_dir, dst_len, filename);
+    if (FAILED(hr))
+        goto done;
 
-    strcatW(path, filename);
-    if (!CopyFileW(asmpath, path, FALSE))
-        hr = HRESULT_FROM_WIN32(GetLastError());
+    for (i = 0; i < count; i++)
+    {
+        hr = copy_file(src_dir, src_len, dst_dir, dst_len, external_files[i]);
+        if (FAILED(hr))
+            break;
+    }
 
 done:
     HeapFree(GetProcessHeap(), 0, name);
     HeapFree(GetProcessHeap(), 0, token);
     HeapFree(GetProcessHeap(), 0, version);
     HeapFree(GetProcessHeap(), 0, asmpath);
+    HeapFree(GetProcessHeap(), 0, dst_dir);
+    for (i = 0; i < count; i++) HeapFree(GetProcessHeap(), 0, external_files[i]);
+    HeapFree(GetProcessHeap(), 0, external_files);
     assembly_release(assembly);
     cache_unlock( cache );
     return hr;
diff --git a/dlls/fusion/assembly.c b/dlls/fusion/assembly.c
index b655df1..d04ba73 100644
--- a/dlls/fusion/assembly.c
+++ b/dlls/fusion/assembly.c
@@ -761,9 +761,9 @@ HRESULT assembly_get_name(ASSEMBLY *assembly, LPWSTR *name)
 
     ptr += FIELD_OFFSET(ASSEMBLYTABLE, PublicKey) + assembly->blobsz;
     if (assembly->stringsz == sizeof(DWORD))
-        stridx = *((DWORD *)ptr);
+        stridx = *(DWORD *)ptr;
     else
-        stridx = *((WORD *)ptr);
+        stridx = *(WORD *)ptr;
 
     *name = assembly_dup_str(assembly, stridx);
     if (!*name)
@@ -912,3 +912,52 @@ HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
     *version = assembly->metadatahdr->Version;
     return S_OK;
 }
+
+HRESULT assembly_get_external_files(ASSEMBLY *assembly, LPWSTR **files, DWORD *count)
+{
+    LONG offset;
+    INT i, num_rows;
+    WCHAR **ret;
+    BYTE *ptr;
+    DWORD idx;
+
+    *count = 0;
+
+    offset = assembly->tables[TableFromToken(mdtFile)].offset;
+    if (offset == -1)
+        return S_OK;
+
+    ptr = assembly_data_offset(assembly, offset);
+    if (!ptr)
+        return S_OK;
+
+    num_rows = assembly->tables[TableFromToken(mdtFile)].rows;
+    if (num_rows <= 0)
+        return S_OK;
+
+    ret = HeapAlloc(GetProcessHeap(), 0, num_rows * sizeof(WCHAR *));
+    if (!ret)
+        return E_OUTOFMEMORY;
+
+    for (i = 0; i < num_rows; i++)
+    {
+        ptr += sizeof(DWORD); /* skip Flags field */
+        if (assembly->stringsz == sizeof(DWORD))
+            idx = *(DWORD *)ptr;
+        else
+            idx = *(WORD *)ptr;
+
+        ret[i] = assembly_dup_str(assembly, idx);
+        if (!ret[i])
+        {
+            for (; i >= 0; i--) HeapFree(GetProcessHeap(), 0, ret[i]);
+            HeapFree(GetProcessHeap(), 0, ret);
+            return E_OUTOFMEMORY;
+        }
+        ptr += assembly->stringsz; /* skip Name field */
+        ptr += assembly->blobsz; /* skip Hash field */
+    }
+    *count = num_rows;
+    *files = ret;
+    return S_OK;
+}
diff --git a/dlls/fusion/fusionpriv.h b/dlls/fusion/fusionpriv.h
index 3d538e3..95b1282 100644
--- a/dlls/fusion/fusionpriv.h
+++ b/dlls/fusion/fusionpriv.h
@@ -436,6 +436,7 @@ HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version) DECLSPEC_HIDDE
 PEKIND assembly_get_architecture(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
 HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token) DECLSPEC_HIDDEN;
 HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
+HRESULT assembly_get_external_files(ASSEMBLY *assembly, LPWSTR **files, DWORD *count) DECLSPEC_HIDDEN;
 
 extern HRESULT IAssemblyName_SetPath(IAssemblyName *iface, LPCWSTR path) DECLSPEC_HIDDEN;
 extern HRESULT IAssemblyName_GetPath(IAssemblyName *iface, LPWSTR buf, ULONG *len) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list