From 5ffb258f8a7eeed6145ed82b8a859a3c0518df74 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 4 May 2013 20:21:39 +0000 Subject: [PATCH] [FUSION] * Sync with Wine 1.5.26. svn path=/trunk/; revision=58927 --- reactos/dll/win32/fusion/CMakeLists.txt | 3 +- reactos/dll/win32/fusion/asmcache.c | 152 +++++++++++++++++++----- reactos/dll/win32/fusion/asmenum.c | 137 ++++++++++++++------- reactos/dll/win32/fusion/asmname.c | 97 +++++++++++---- reactos/dll/win32/fusion/assembly.c | 125 ++++++++++++------- reactos/dll/win32/fusion/fusion.c | 67 ++++++----- reactos/dll/win32/fusion/fusion.spec | 2 +- reactos/dll/win32/fusion/fusion_main.c | 51 -------- reactos/dll/win32/fusion/fusionpriv.h | 4 +- reactos/include/psdk/corerror.h | 1 + reactos/include/psdk/fusion.idl | 4 +- reactos/media/doc/README.WINE | 2 +- 12 files changed, 417 insertions(+), 228 deletions(-) delete mode 100644 reactos/dll/win32/fusion/fusion_main.c diff --git a/reactos/dll/win32/fusion/CMakeLists.txt b/reactos/dll/win32/fusion/CMakeLists.txt index 82f671844ba..7e19b1e14e1 100644 --- a/reactos/dll/win32/fusion/CMakeLists.txt +++ b/reactos/dll/win32/fusion/CMakeLists.txt @@ -10,7 +10,6 @@ list(APPEND SOURCE asmname.c assembly.c fusion.c - fusion_main.c version.rc ${CMAKE_CURRENT_BINARY_DIR}/fusion_stubs.c ${CMAKE_CURRENT_BINARY_DIR}/fusion.def) @@ -18,7 +17,7 @@ list(APPEND SOURCE add_library(fusion SHARED ${SOURCE}) set_module_type(fusion win32dll) target_link_libraries(fusion wine uuid) -add_importlibs(fusion shlwapi advapi32 dbghelp user32 msvcrt kernel32 ntdll) +add_importlibs(fusion advapi32 dbghelp shlwapi user32 msvcrt kernel32 ntdll) add_cd_file(TARGET fusion DESTINATION reactos/Microsoft.NET/Framework/v1.0.3705 FOR all) add_cd_file(TARGET fusion DESTINATION reactos/Microsoft.NET/Framework/v1.1.4322 FOR all) add_cd_file(TARGET fusion DESTINATION reactos/Microsoft.NET/Framework/v2.0.50727 FOR all) diff --git a/reactos/dll/win32/fusion/asmcache.c b/reactos/dll/win32/fusion/asmcache.c index df89800dc41..2b02390f497 100644 --- a/reactos/dll/win32/fusion/asmcache.c +++ b/reactos/dll/win32/fusion/asmcache.c @@ -98,32 +98,48 @@ static BOOL create_full_path(LPCWSTR path) return ret; } -static BOOL get_assembly_directory(LPWSTR dir, DWORD size, BYTE architecture) +static BOOL get_assembly_directory(LPWSTR dir, DWORD size, const char *version, PEKIND architecture) { + static const WCHAR dotnet[] = {'\\','M','i','c','r','o','s','o','f','t','.','N','E','T','\\',0}; static const WCHAR gac[] = {'\\','a','s','s','e','m','b','l','y','\\','G','A','C',0}; - static const WCHAR msil[] = {'_','M','S','I','L',0}; static const WCHAR x86[] = {'_','3','2',0}; static const WCHAR amd64[] = {'_','6','4',0}; + DWORD len = GetWindowsDirectoryW(dir, size); - GetWindowsDirectoryW(dir, size); - strcatW(dir, gac); - + if (!strcmp(version, "v4.0.30319")) + { + strcpyW(dir + len, dotnet); + len += sizeof(dotnet)/sizeof(WCHAR) -1; + strcpyW(dir + len, gac + 1); + len += sizeof(gac)/sizeof(WCHAR) - 2; + } + else + { + strcpyW(dir + len, gac); + len += sizeof(gac)/sizeof(WCHAR) - 1; + } switch (architecture) { + case peNone: + break; + case peMSIL: - strcatW(dir, msil); + strcpyW(dir + len, msil); break; case peI386: - strcatW(dir, x86); + strcpyW(dir + len, x86); break; case peAMD64: - strcatW(dir, amd64); + strcpyW(dir + len, amd64); break; - } + default: + WARN("unhandled architecture %u\n", architecture); + return FALSE; + } return TRUE; } @@ -153,7 +169,7 @@ static HRESULT WINAPI IAssemblyCacheImpl_QueryInterface(IAssemblyCache *iface, if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAssemblyCache)) { - IUnknown_AddRef(iface); + IAssemblyCache_AddRef(iface); *ppobj = This; return S_OK; } @@ -312,11 +328,16 @@ static HRESULT WINAPI IAssemblyCacheImpl_QueryAssemblyInfo(IAssemblyCache *iface if (FAILED(hr)) goto done; - hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); - if (hr == S_FALSE) + for (;;) { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - goto done; + hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); + if (hr != S_OK) + { + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + goto done; + } + hr = IAssemblyName_IsEqual(asmname, next, ASM_CMPF_IL_ALL); + if (hr == S_OK) break; } if (!pAsmInfo) @@ -353,24 +374,51 @@ 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, LPCFUSION_INSTALL_REFERENCE pRefData) { - static const WCHAR format[] = {'%','s','\\','%','s','\\','%','s','_','_','%','s','\\',0}; + static const WCHAR format[] = + {'%','s','\\','%','s','\\','%','s','_','_','%','s','\\',0}; + static const WCHAR format_v40[] = + {'%','s','\\','%','s','\\','v','4','.','0','_','%','s','_','_','%','s','\\',0}; static const WCHAR ext_exe[] = {'.','e','x','e',0}; static const WCHAR ext_dll[] = {'.','d','l','l',0}; IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface); ASSEMBLY *assembly; - LPWSTR filename; - LPWSTR name = NULL; - LPWSTR token = NULL; - LPWSTR version = NULL; - LPWSTR asmpath = NULL; - WCHAR path[MAX_PATH]; - WCHAR asmdir[MAX_PATH]; - LPWSTR ext; + const WCHAR *extension, *filename, *src_dir; + WCHAR *name = NULL, *token = NULL, *version = NULL, *asmpath = NULL; + 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, @@ -379,10 +427,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) @@ -407,29 +455,67 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, if (FAILED(hr)) goto done; + hr = assembly_get_runtime_version(assembly, &clr_version); + if (FAILED(hr)) + goto done; + + hr = assembly_get_external_files(assembly, &external_files, &count); + if (FAILED(hr)) + goto done; + cache_lock( cache ); - get_assembly_directory(asmdir, MAX_PATH, assembly_get_architecture(assembly)); + architecture = assembly_get_architecture(assembly); + get_assembly_directory(asmdir, MAX_PATH, clr_version, architecture); - sprintfW(path, format, asmdir, name, version, token); + 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")) + dst_len = sprintfW(dst_dir, format_v40, asmdir, name, version, token); + else + 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; @@ -501,7 +587,7 @@ static HRESULT WINAPI IAssemblyCacheItemImpl_QueryInterface(IAssemblyCacheItem * if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAssemblyCacheItem)) { - IUnknown_AddRef(iface); + IAssemblyCacheItem_AddRef(iface); *ppobj = This; return S_OK; } diff --git a/reactos/dll/win32/fusion/asmenum.c b/reactos/dll/win32/fusion/asmenum.c index 89e11057ffd..23ed47b1949 100644 --- a/reactos/dll/win32/fusion/asmenum.c +++ b/reactos/dll/win32/fusion/asmenum.c @@ -25,6 +25,8 @@ #include #define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT #include #include @@ -73,7 +75,7 @@ static HRESULT WINAPI IAssemblyEnumImpl_QueryInterface(IAssemblyEnum *iface, if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAssemblyEnum)) { - IUnknown_AddRef(iface); + IAssemblyEnum_AddRef(iface); *ppobj = This; return S_OK; } @@ -168,23 +170,32 @@ static const IAssemblyEnumVtbl AssemblyEnumVtbl = { IAssemblyEnumImpl_Clone }; -static void parse_name(IAssemblyName *name, int depth, LPWSTR path, LPWSTR buf) +static void build_file_mask(IAssemblyName *name, int depth, const WCHAR *path, + const WCHAR *prefix, WCHAR *buf) { - WCHAR disp[MAX_PATH]; + static const WCHAR star[] = {'*',0}; + static const WCHAR ss_fmt[] = {'%','s','\\','%','s',0}; + static const WCHAR sss_fmt[] = {'%','s','\\','%','s','_','_','%','s',0}; + static const WCHAR ssss_fmt[] = {'%','s','\\','%','s','%','s','_','_','%','s',0}; + static const WCHAR ver_fmt[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; + static const WCHAR star_fmt[] = {'%','s','\\','*',0}; + static const WCHAR star_prefix_fmt[] = {'%','s','\\','%','s','*',0}; + WCHAR disp[MAX_PATH], version[24]; /* strlen("65535") * 4 + 3 + 1 */ LPCWSTR verptr, pubkeyptr; HRESULT hr; DWORD size, major_size, minor_size, build_size, revision_size; WORD major, minor, build, revision; - - static const WCHAR star[] = {'*',0}; - static const WCHAR ss_fmt[] = {'%','s','\\','%','s',0}; - static const WCHAR verpubkey[] = {'%','s','\\','%','s','_','_','%','s',0}; - static const WCHAR ver_fmt[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; - - WCHAR version[24]; /* strlen("65535") * 4 + 3 + 1 */ WCHAR token_str[TOKEN_LENGTH + 1]; BYTE token[BYTES_PER_TOKEN]; + if (!name) + { + if (prefix && depth == 1) + sprintfW(buf, star_prefix_fmt, path, prefix); + else + sprintfW(buf, star_fmt, path); + return; + } if (depth == 0) { size = MAX_PATH; @@ -226,7 +237,10 @@ static void parse_name(IAssemblyName *name, int depth, LPWSTR path, LPWSTR buf) pubkeyptr = token_str; } - sprintfW(buf, verpubkey, path, verptr, pubkeyptr); + if (prefix) + sprintfW(buf, ssss_fmt, path, prefix, verptr, pubkeyptr); + else + sprintfW(buf, sss_fmt, path, verptr, pubkeyptr); } } @@ -291,34 +305,24 @@ static void insert_assembly(struct list *assemblies, ASMNAME *to_insert) } static HRESULT enum_gac_assemblies(struct list *assemblies, IAssemblyName *name, - int depth, LPWSTR path) + int depth, const WCHAR *prefix, LPWSTR path) { - WIN32_FIND_DATAW ffd; - WCHAR buf[MAX_PATH]; - WCHAR disp[MAX_PATH]; - WCHAR asmpath[MAX_PATH]; - ASMNAME *asmname; - HANDLE hfind; - LPWSTR ptr; - HRESULT hr = S_OK; - - static WCHAR parent[MAX_PATH]; - static const WCHAR dot[] = {'.',0}; static const WCHAR dotdot[] = {'.','.',0}; - static const WCHAR search_fmt[] = {'%','s','\\','*',0}; static const WCHAR dblunder[] = {'_','_',0}; static const WCHAR path_fmt[] = {'%','s','\\','%','s','\\','%','s','.','d','l','l',0}; - static const WCHAR fmt[] = {'%','s',',',' ','V','e','r','s','i','o','n','=','%','s',',',' ', + static const WCHAR name_fmt[] = {'%','s',',',' ','V','e','r','s','i','o','n','=','%','s',',',' ', 'C','u','l','t','u','r','e','=','n','e','u','t','r','a','l',',',' ', 'P','u','b','l','i','c','K','e','y','T','o','k','e','n','=','%','s',0}; static const WCHAR ss_fmt[] = {'%','s','\\','%','s',0}; + WIN32_FIND_DATAW ffd; + WCHAR buf[MAX_PATH], disp[MAX_PATH], asmpath[MAX_PATH], *ptr; + static WCHAR parent[MAX_PATH]; + ASMNAME *asmname; + HANDLE hfind; + HRESULT hr = S_OK; - if (name) - parse_name(name, depth, path, buf); - else - sprintfW(buf, search_fmt, path); - + build_file_mask(name, depth, path, prefix, buf); hfind = FindFirstFileW(buf, &ffd); if (hfind == INVALID_HANDLE_VALUE) return S_OK; @@ -339,13 +343,21 @@ static HRESULT enum_gac_assemblies(struct list *assemblies, IAssemblyName *name, } else if (depth == 1) { - sprintfW(asmpath, path_fmt, path, ffd.cFileName, parent); + const WCHAR *token, *version = ffd.cFileName; + sprintfW(asmpath, path_fmt, path, ffd.cFileName, parent); ptr = strstrW(ffd.cFileName, dblunder); *ptr = '\0'; - ptr += 2; + token = ptr + 2; - sprintfW(disp, fmt, parent, ffd.cFileName, ptr); + if (prefix) + { + unsigned int prefix_len = strlenW(prefix); + if (strlenW(ffd.cFileName) >= prefix_len && + !memicmpW(ffd.cFileName, prefix, prefix_len)) + version += prefix_len; + } + sprintfW(disp, name_fmt, parent, version, token); asmname = HeapAlloc(GetProcessHeap(), 0, sizeof(ASMNAME)); if (!asmname) @@ -375,7 +387,7 @@ static HRESULT enum_gac_assemblies(struct list *assemblies, IAssemblyName *name, } sprintfW(buf, ss_fmt, path, ffd.cFileName); - hr = enum_gac_assemblies(assemblies, name, depth + 1, buf); + hr = enum_gac_assemblies(assemblies, name, depth + 1, prefix, buf); if (FAILED(hr)) break; } while (FindNextFileW(hfind, &ffd) != 0); @@ -386,32 +398,65 @@ static HRESULT enum_gac_assemblies(struct list *assemblies, IAssemblyName *name, static HRESULT enumerate_gac(IAssemblyEnumImpl *asmenum, IAssemblyName *pName) { - WCHAR path[MAX_PATH]; - WCHAR buf[MAX_PATH]; + static const WCHAR gac[] = {'\\','G','A','C',0}; + static const WCHAR gac_32[] = {'\\','G','A','C','_','3','2',0}; + static const WCHAR gac_64[] = {'\\','G','A','C','_','6','4',0}; + static const WCHAR gac_msil[] = {'\\','G','A','C','_','M','S','I','L',0}; + static const WCHAR v40[] = {'v','4','.','0','_',0}; + WCHAR path[MAX_PATH], buf[MAX_PATH]; + SYSTEM_INFO info; HRESULT hr; DWORD size; - static WCHAR under32[] = {'_','3','2',0}; - static WCHAR msil[] = {'_','M','S','I','L',0}; + size = MAX_PATH; + hr = GetCachePath(ASM_CACHE_ROOT_EX, buf, &size); + if (FAILED(hr)) + return hr; + + strcpyW(path, buf); + GetNativeSystemInfo(&info); + if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + { + strcpyW(path + size - 1, gac_64); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, v40, path); + if (FAILED(hr)) + return hr; + } + strcpyW(path + size - 1, gac_32); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, v40, path); + if (FAILED(hr)) + return hr; + + strcpyW(path + size - 1, gac_msil); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, v40, path); + if (FAILED(hr)) + return hr; size = MAX_PATH; - hr = GetCachePath(ASM_CACHE_GAC, buf, &size); + hr = GetCachePath(ASM_CACHE_ROOT, buf, &size); if (FAILED(hr)) return hr; - lstrcpyW(path, buf); - lstrcatW(path, under32); - hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, path); + strcpyW(path, buf); + if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + { + strcpyW(path + size - 1, gac_64); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, NULL, path); + if (FAILED(hr)) + return hr; + } + strcpyW(path + size - 1, gac_32); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, NULL, path); if (FAILED(hr)) return hr; - lstrcpyW(path, buf); - lstrcatW(path, msil); - hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, path); + strcpyW(path + size - 1, gac_msil); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, NULL, path); if (FAILED(hr)) return hr; - hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, buf); + strcpyW(path + size - 1, gac); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, NULL, path); if (FAILED(hr)) return hr; diff --git a/reactos/dll/win32/fusion/asmname.c b/reactos/dll/win32/fusion/asmname.c index f41933ea35a..019d0e5dad3 100644 --- a/reactos/dll/win32/fusion/asmname.c +++ b/reactos/dll/win32/fusion/asmname.c @@ -88,7 +88,7 @@ static HRESULT WINAPI IAssemblyNameImpl_QueryInterface(IAssemblyName *iface, if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAssemblyName)) { - IUnknown_AddRef(iface); + IAssemblyName_AddRef(iface); *ppobj = This; return S_OK; } @@ -265,7 +265,7 @@ static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface, { static const WCHAR spec[] = {'%','d',0}; static const WCHAR period[] = {'.',0}; - int i; + DWORD i; wsprintfW(verstr, spec, name->version[0]); @@ -411,10 +411,37 @@ static HRESULT WINAPI IAssemblyNameImpl_GetVersion(IAssemblyName *iface, static HRESULT WINAPI IAssemblyNameImpl_IsEqual(IAssemblyName *iface, IAssemblyName *pName, - DWORD dwCmpFlags) + DWORD flags) { - FIXME("(%p, %p, %d) stub!\n", iface, pName, dwCmpFlags); - return E_NOTIMPL; + IAssemblyNameImpl *name1 = impl_from_IAssemblyName(iface); + IAssemblyNameImpl *name2 = impl_from_IAssemblyName(pName); + + TRACE("(%p, %p, 0x%08x)\n", iface, pName, flags); + + if (!pName) return S_FALSE; + if (flags & ~ASM_CMPF_IL_ALL) FIXME("unsupported flags\n"); + + if ((flags & ASM_CMPF_NAME) && strcmpW(name1->name, name2->name)) return S_FALSE; + if (name1->versize && name2->versize) + { + if ((flags & ASM_CMPF_MAJOR_VERSION) && + name1->version[0] != name2->version[0]) return S_FALSE; + if ((flags & ASM_CMPF_MINOR_VERSION) && + name1->version[1] != name2->version[1]) return S_FALSE; + if ((flags & ASM_CMPF_BUILD_NUMBER) && + name1->version[2] != name2->version[2]) return S_FALSE; + if ((flags & ASM_CMPF_REVISION_NUMBER) && + name1->version[3] != name2->version[3]) return S_FALSE; + } + if ((flags & ASM_CMPF_PUBLIC_KEY_TOKEN) && + name1->haspubkey && name2->haspubkey && + memcmp(name1->pubkey, name2->pubkey, sizeof(name1->pubkey))) return S_FALSE; + + if ((flags & ASM_CMPF_CULTURE) && + name1->culture && name2->culture && + strcmpW(name1->culture, name2->culture)) return S_FALSE; + + return S_OK; } static HRESULT WINAPI IAssemblyNameImpl_Clone(IAssemblyName *iface, @@ -538,6 +565,10 @@ static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPCWSTR pubkey) { int i; BYTE val; + static const WCHAR nullstr[] = {'n','u','l','l',0}; + + if(lstrcmpiW(pubkey, nullstr) == 0) + return FUSION_E_PRIVATE_ASM_DISALLOWED; if (lstrlenW(pubkey) < CHARS_PER_PUBKEY) return FUSION_E_INVALID_NAME; @@ -557,10 +588,32 @@ static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPCWSTR pubkey) return S_OK; } +static WCHAR *parse_value( const WCHAR *str, unsigned int len ) +{ + WCHAR *ret; + const WCHAR *p = str; + BOOL quoted = FALSE; + unsigned int i = 0; + + if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return NULL; + if (*p == '\"') + { + quoted = TRUE; + p++; + } + while (*p && *p != '\"') ret[i++] = *p++; + if ((quoted && *p != '\"') || (!quoted && *p == '\"')) + { + HeapFree( GetProcessHeap(), 0, ret ); + return NULL; + } + ret[i] = 0; + return ret; +} + static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyName) { - LPWSTR str, save; - LPWSTR ptr, ptr2; + LPWSTR str, save, ptr, ptr2, value; HRESULT hr = S_OK; BOOL done = FALSE; @@ -599,7 +652,7 @@ static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyNam if (!ptr) goto done; - str = ptr + 2; + str = ptr + 1; while (!done) { ptr = strchrW(str, '='); @@ -616,7 +669,7 @@ static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyNam goto done; } - if (!(ptr2 = strstrW(ptr, separator))) + if (!(ptr2 = strchrW(ptr, ','))) { if (!(ptr2 = strchrW(ptr, '\0'))) { @@ -628,21 +681,25 @@ static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyNam } *ptr2 = '\0'; - + if (!(value = parse_value( ptr, ptr2 - ptr ))) + { + hr = FUSION_E_INVALID_NAME; + goto done; + } while (*str == ' ') str++; - if (!lstrcmpW(str, version)) - hr = parse_version(name, ptr); - else if (!lstrcmpW(str, culture)) - hr = parse_culture(name, ptr); - else if (!lstrcmpW(str, pubkey)) - hr = parse_pubkey(name, ptr); - else if (!lstrcmpW(str, procarch)) + if (!lstrcmpiW(str, version)) + hr = parse_version( name, value ); + else if (!lstrcmpiW(str, culture)) + hr = parse_culture( name, value ); + else if (!lstrcmpiW(str, pubkey)) + hr = parse_pubkey( name, value ); + else if (!lstrcmpiW(str, procarch)) { - name->procarch = strdupW(ptr); - if (!name->procarch) - hr = E_OUTOFMEMORY; + name->procarch = value; + value = NULL; } + HeapFree( GetProcessHeap(), 0, value ); if (FAILED(hr)) goto done; diff --git a/reactos/dll/win32/fusion/assembly.c b/reactos/dll/win32/fusion/assembly.c index c9ec1764815..f429ecc5085 100644 --- a/reactos/dll/win32/fusion/assembly.c +++ b/reactos/dll/win32/fusion/assembly.c @@ -486,8 +486,9 @@ static inline ULONG get_table_size(const ASSEMBLY *assembly, DWORD index) static HRESULT parse_clr_tables(ASSEMBLY *assembly, ULONG offset) { - DWORD i, previ, offidx; + DWORD i, count; ULONG currofs; + ULONGLONG mask; currofs = offset; assembly->tableshdr = assembly_data_offset(assembly, currofs); @@ -506,44 +507,22 @@ static HRESULT parse_clr_tables(ASSEMBLY *assembly, ULONG offset) if (!assembly->numrows) return E_FAIL; - assembly->numtables = 0; - for (i = 0; i < MAX_CLR_TABLES; i++) - { - if ((i < 32 && (assembly->tableshdr->MaskValid.u.LowPart >> i) & 1) || - (i >= 32 && (assembly->tableshdr->MaskValid.u.HighPart >> i) & 1)) - { - assembly->numtables++; - } - } - - currofs += assembly->numtables * sizeof(DWORD); memset(assembly->tables, -1, MAX_CLR_TABLES * sizeof(CLRTABLE)); - if (assembly->tableshdr->MaskValid.u.LowPart & 1) - assembly->tables[0].offset = currofs; - - offidx = 0; - for (i = 0; i < MAX_CLR_TABLES; i++) + for (i = count = 0, mask = 1; i < MAX_CLR_TABLES; i++, mask <<= 1) { - if ((i < 32 && (assembly->tableshdr->MaskValid.u.LowPart >> i) & 1) || - (i >= 32 && (assembly->tableshdr->MaskValid.u.HighPart >> i) & 1)) - { - assembly->tables[i].rows = assembly->numrows[offidx]; - offidx++; - } + if (assembly->tableshdr->MaskValid.QuadPart & mask) + assembly->tables[i].rows = assembly->numrows[count++]; } + assembly->numtables = count; + currofs += assembly->numtables * sizeof(DWORD); - previ = 0; - offidx = 1; - for (i = 1; i < MAX_CLR_TABLES; i++) + for (i = 0, mask = 1; i < MAX_CLR_TABLES; i++, mask <<= 1) { - if ((i < 32 && (assembly->tableshdr->MaskValid.u.LowPart >> i) & 1) || - (i >= 32 && (assembly->tableshdr->MaskValid.u.HighPart >> i) & 1)) + if (assembly->tableshdr->MaskValid.QuadPart & mask) { - currofs += get_table_size(assembly, previ) * assembly->numrows[offidx - 1]; assembly->tables[i].offset = currofs; - offidx++; - previ = i; + currofs += get_table_size(assembly, i) * assembly->tables[i].rows; } } @@ -571,7 +550,7 @@ static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz) size = FIELD_OFFSET(METADATAHDR, Version); memcpy(assembly->metadatahdr, metadatahdr, size); - /* we don't care about the version string */ + assembly->metadatahdr->Version = (LPSTR)&metadatahdr->Version; ofs = FIELD_OFFSET(METADATAHDR, Flags); ptr += FIELD_OFFSET(METADATAHDR, Version) + metadatahdr->VersionLength + 1; @@ -765,9 +744,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) @@ -815,10 +794,10 @@ HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version) return S_OK; } -BYTE assembly_get_architecture(ASSEMBLY *assembly) +PEKIND assembly_get_architecture(ASSEMBLY *assembly) { if ((assembly->corhdr->MajorRuntimeVersion == 2) && (assembly->corhdr->MinorRuntimeVersion == 0)) - return 0; /* .NET 1.x assembly */ + return peNone; /* .NET 1.x assembly */ if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) return peAMD64; /* AMD64/IA64 assembly */ @@ -829,23 +808,22 @@ BYTE assembly_get_architecture(ASSEMBLY *assembly) return peI386; /* x86 assembly */ } -static BYTE *assembly_get_blob(ASSEMBLY *assembly, WORD index, ULONG *size) +static BYTE *assembly_get_blob(ASSEMBLY *assembly, DWORD index, ULONG *size) { return GetData(&assembly->blobs[index], size); } HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token) { - ASSEMBLYTABLE *asmtbl; ULONG i, size; LONG offset; - BYTE *hashdata; + BYTE *hashdata, *pubkey, *ptr; HCRYPTPROV crypt; HCRYPTHASH hash; - BYTE *pubkey; BYTE tokbytes[BYTES_PER_TOKEN]; HRESULT hr = E_FAIL; LPWSTR tok; + DWORD idx; *token = NULL; @@ -853,11 +831,17 @@ HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token) if (offset == -1) return E_FAIL; - asmtbl = assembly_data_offset(assembly, offset); - if (!asmtbl) + ptr = assembly_data_offset(assembly, offset); + if (!ptr) return E_FAIL; - pubkey = assembly_get_blob(assembly, asmtbl->PublicKey, &size); + ptr += FIELD_OFFSET(ASSEMBLYTABLE, PublicKey); + if (assembly->blobsz == sizeof(DWORD)) + idx = *(DWORD *)ptr; + else + idx = *(WORD *)ptr; + + pubkey = assembly_get_blob(assembly, idx, &size); if (!CryptAcquireContextA(&crypt, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) @@ -905,3 +889,58 @@ done: return hr; } + +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/reactos/dll/win32/fusion/fusion.c b/reactos/dll/win32/fusion/fusion.c index 1543ed73fad..c8d3fad95da 100644 --- a/reactos/dll/win32/fusion/fusion.c +++ b/reactos/dll/win32/fusion/fusion.c @@ -36,6 +36,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(fusion); + +/****************************************************************** + * InitializeFusion (FUSION.@) + */ +HRESULT WINAPI InitializeFusion(void) +{ + FIXME("\n"); + return E_NOTIMPL; +} + /****************************************************************** * ClearDownloadCache (FUSION.@) */ @@ -80,9 +90,9 @@ static HRESULT get_corversion(LPWSTR version, DWORD size) pGetCORVersion = (void *)GetProcAddress(hmscoree, "GetCORVersion"); if (!pGetCORVersion) - return E_FAIL; - - hr = pGetCORVersion(version, size, &len); + hr = E_FAIL; + else + hr = pGetCORVersion(version, size, &len); FreeLibrary(hmscoree); return hr; @@ -94,32 +104,26 @@ static HRESULT get_corversion(LPWSTR version, DWORD size) HRESULT WINAPI GetCachePath(ASM_CACHE_FLAGS dwCacheFlags, LPWSTR pwzCachePath, PDWORD pcchPath) { - WCHAR path[MAX_PATH]; - WCHAR windir[MAX_PATH]; - WCHAR version[MAX_PATH]; - DWORD len; - HRESULT hr = S_OK; - - static const WCHAR backslash[] = {'\\',0}; - static const WCHAR assembly[] = {'a','s','s','e','m','b','l','y',0}; - static const WCHAR gac[] = {'G','A','C',0}; - static const WCHAR nativeimg[] = { - 'N','a','t','i','v','e','I','m','a','g','e','s','_',0}; + static const WCHAR assembly[] = {'\\','a','s','s','e','m','b','l','y',0}; + static const WCHAR gac[] = {'\\','G','A','C',0}; + static const WCHAR nativeimg[] = {'N','a','t','i','v','e','I','m','a','g','e','s','_',0}; + static const WCHAR dotnet[] = {'\\','M','i','c','r','o','s','o','f','t','.','N','E','T',0}; #ifdef _WIN64 static const WCHAR zapfmt[] = {'%','s','\\','%','s','\\','%','s','%','s','_','6','4',0}; #else static const WCHAR zapfmt[] = {'%','s','\\','%','s','\\','%','s','%','s','_','3','2',0}; #endif + WCHAR path[MAX_PATH], windir[MAX_PATH], version[MAX_PATH]; + DWORD len; + HRESULT hr = S_OK; TRACE("(%08x, %p, %p)\n", dwCacheFlags, pwzCachePath, pcchPath); if (!pcchPath) return E_INVALIDARG; - GetWindowsDirectoryW(windir, MAX_PATH); - lstrcpyW(path, windir); - lstrcatW(path, backslash); - lstrcatW(path, assembly); + len = GetWindowsDirectoryW(windir, MAX_PATH); + strcpyW(path, windir); switch (dwCacheFlags) { @@ -129,37 +133,42 @@ HRESULT WINAPI GetCachePath(ASM_CACHE_FLAGS dwCacheFlags, LPWSTR pwzCachePath, if (FAILED(hr)) return hr; - sprintfW(path, zapfmt, windir, assembly, nativeimg, version); + len = sprintfW(path, zapfmt, windir, assembly + 1, nativeimg, version); break; } - case ASM_CACHE_GAC: { - lstrcatW(path, backslash); - lstrcatW(path, gac); + strcpyW(path + len, assembly); + len += sizeof(assembly)/sizeof(WCHAR) - 1; + strcpyW(path + len, gac); + len += sizeof(gac)/sizeof(WCHAR) - 1; break; } - case ASM_CACHE_DOWNLOAD: { FIXME("Download cache not implemented\n"); return E_FAIL; } - case ASM_CACHE_ROOT: - break; /* already set */ - + strcpyW(path + len, assembly); + len += sizeof(assembly)/sizeof(WCHAR) - 1; + break; + case ASM_CACHE_ROOT_EX: + strcpyW(path + len, dotnet); + len += sizeof(dotnet)/sizeof(WCHAR) - 1; + strcpyW(path + len, assembly); + len += sizeof(assembly)/sizeof(WCHAR) - 1; + break; default: return E_INVALIDARG; } - len = lstrlenW(path) + 1; + len++; if (*pcchPath <= len || !pwzCachePath) hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); else if (pwzCachePath) - lstrcpyW(pwzCachePath, path); + strcpyW(pwzCachePath, path); *pcchPath = len; - return hr; } diff --git a/reactos/dll/win32/fusion/fusion.spec b/reactos/dll/win32/fusion/fusion.spec index 54e4eadd715..264aff70959 100644 --- a/reactos/dll/win32/fusion/fusion.spec +++ b/reactos/dll/win32/fusion/fusion.spec @@ -8,7 +8,7 @@ @ stdcall CreateInstallReferenceEnum(ptr ptr long ptr) @ stdcall GetCachePath(long wstr ptr) @ stub GetHistoryFileDirectory -@ stub InitializeFusion +@ stdcall InitializeFusion() @ stub InstallCustomAssembly @ stub InstallCustomModule @ stub LookupHistoryAssembly diff --git a/reactos/dll/win32/fusion/fusion_main.c b/reactos/dll/win32/fusion/fusion_main.c deleted file mode 100644 index 8af1fc86d21..00000000000 --- a/reactos/dll/win32/fusion/fusion_main.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * fusion main - * - * Copyright 2008 James Hawkins - * - * 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 - */ - -#define WIN32_NO_STATUS - -#include - -#include - -#include -#include -#include - -WINE_DEFAULT_DEBUG_CHANNEL(fusion); - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); - - switch (fdwReason) - { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hinstDLL); - break; - case DLL_PROCESS_DETACH: - break; - default: - break; - } - - return TRUE; -} diff --git a/reactos/dll/win32/fusion/fusionpriv.h b/reactos/dll/win32/fusion/fusionpriv.h index 374b14abb8b..db89154803e 100644 --- a/reactos/dll/win32/fusion/fusionpriv.h +++ b/reactos/dll/win32/fusion/fusionpriv.h @@ -433,8 +433,10 @@ HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN; HRESULT assembly_get_name(ASSEMBLY *assembly, LPWSTR *name) DECLSPEC_HIDDEN; HRESULT assembly_get_path(const ASSEMBLY *assembly, LPWSTR *path) DECLSPEC_HIDDEN; HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version) DECLSPEC_HIDDEN; -BYTE assembly_get_architecture(ASSEMBLY *assembly) DECLSPEC_HIDDEN; +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; diff --git a/reactos/include/psdk/corerror.h b/reactos/include/psdk/corerror.h index 1537f93e2cd..3ddfe474ac9 100644 --- a/reactos/include/psdk/corerror.h +++ b/reactos/include/psdk/corerror.h @@ -119,6 +119,7 @@ #define COR_E_HOSTPROTECTION EMAKEHR(0x1640) #define COR_E_ILLEGAL_REENTRANCY EMAKEHR(0x1641) +#define FUSION_E_PRIVATE_ASM_DISALLOWED EMAKEHR(0x1044) #define FUSION_E_INVALID_NAME EMAKEHR(0x1047) #define CLDB_E_FILE_OLDVER EMAKEHR(0x1107) diff --git a/reactos/include/psdk/fusion.idl b/reactos/include/psdk/fusion.idl index 99638383535..cff1e6cb8d3 100644 --- a/reactos/include/psdk/fusion.idl +++ b/reactos/include/psdk/fusion.idl @@ -28,7 +28,8 @@ typedef enum ASM_CACHE_ZAP = 0x1, ASM_CACHE_GAC = 0x2, ASM_CACHE_DOWNLOAD = 0x4, - ASM_CACHE_ROOT = 0x8 + ASM_CACHE_ROOT = 0x8, + ASM_CACHE_ROOT_EX = 0x80 } ASM_CACHE_FLAGS; typedef enum @@ -38,6 +39,7 @@ typedef enum peI386 = 0x00000002, peIA64 = 0x00000003, peAMD64 = 0x00000004, + peARM = 0x00000005, peInvalid = 0xffffffff } PEKIND; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 42c68c2979a..78a954f7274 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -62,7 +62,7 @@ reactos/dll/win32/dbghelp # Synced to Wine-1.3.37 reactos/dll/win32/dciman32 # Synced to Wine-1.5.19 reactos/dll/win32/dwmapi # Synced to Wine-1.5.19 reactos/dll/win32/faultrep # Synced to Wine-1.5.4 -reactos/dll/win32/fusion # Synced to Wine-1.5.4 +reactos/dll/win32/fusion # Synced to Wine-1.5.26 reactos/dll/win32/gdiplus # Synced to Wine-1.5.4 reactos/dll/win32/hhctrl.ocx # Synced to Wine-1.5.26 reactos/dll/win32/hlink # Synced to Wine-1.5.4