Module: wine Branch: master Commit: 45473a65a0a1fe2e61809d80f6d09bb96f923126 URL: http://source.winehq.org/git/wine.git/?a=commit;h=45473a65a0a1fe2e61809d80f6...
Author: Hans Leidekker hans@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;