From 6370393c43ed5a59950924343bacf3a58a8009af Mon Sep 17 00:00:00 2001 From: Christoph von Wittich Date: Wed, 20 May 2009 14:43:24 +0000 Subject: [PATCH] sync fusion with wine 1.1.21 svn path=/trunk/; revision=41022 --- reactos/dll/win32/fusion/asmcache.c | 183 +++++----- reactos/dll/win32/fusion/asmenum.c | 443 +++++++++++++++++++++++++ reactos/dll/win32/fusion/asmname.c | 29 +- reactos/dll/win32/fusion/assembly.c | 131 +++----- reactos/dll/win32/fusion/fusion.c | 19 +- reactos/dll/win32/fusion/fusion.rbuild | 1 + reactos/dll/win32/fusion/fusionpriv.h | 43 ++- 7 files changed, 616 insertions(+), 233 deletions(-) create mode 100644 reactos/dll/win32/fusion/asmenum.c diff --git a/reactos/dll/win32/fusion/asmcache.c b/reactos/dll/win32/fusion/asmcache.c index 57c7aeded7d..f35de7f142a 100644 --- a/reactos/dll/win32/fusion/asmcache.c +++ b/reactos/dll/win32/fusion/asmcache.c @@ -41,24 +41,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(fusion); -static BOOL create_full_path(LPCSTR path) +static BOOL create_full_path(LPCWSTR path) { - LPSTR new_path; + LPWSTR new_path; BOOL ret = TRUE; int len; - new_path = HeapAlloc(GetProcessHeap(), 0, lstrlenA(path) + 1); + new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR)); if (!new_path) return FALSE; - lstrcpyA(new_path, path); + strcpyW(new_path, path); - while ((len = lstrlenA(new_path)) && new_path[len - 1] == '\\') + while ((len = strlenW(new_path)) && new_path[len - 1] == '\\') new_path[len - 1] = 0; - while (!CreateDirectoryA(new_path, NULL)) + while (!CreateDirectoryW(new_path, NULL)) { - LPSTR slash; + LPWSTR slash; DWORD last_error = GetLastError(); if(last_error == ERROR_ALREADY_EXISTS) @@ -70,7 +70,7 @@ static BOOL create_full_path(LPCSTR path) break; } - if(!(slash = strrchr(new_path, '\\'))) + if(!(slash = strrchrW(new_path, '\\'))) { ret = FALSE; break; @@ -91,6 +91,18 @@ static BOOL create_full_path(LPCSTR path) return ret; } +static BOOL get_assembly_directory(LPWSTR dir, DWORD size) +{ + static const WCHAR gac[] = + {'\\','a','s','s','e','m','b','l','y','\\','G','A','C','_','M','S','I','L',0}; + + FIXME("Ignoring assembly architecture\n"); + + GetWindowsDirectoryW(dir, size); + strcatW(dir, gac); + return TRUE; +} + /* IAssemblyCache */ typedef struct { @@ -160,10 +172,48 @@ static HRESULT WINAPI IAssemblyCacheImpl_QueryAssemblyInfo(IAssemblyCache *iface LPCWSTR pszAssemblyName, ASSEMBLY_INFO *pAsmInfo) { - FIXME("(%p, %d, %s, %p) stub!\n", iface, dwFlags, + IAssemblyName *asmname, *next = NULL; + IAssemblyEnum *asmenum = NULL; + HRESULT hr; + + TRACE("(%p, %d, %s, %p)\n", iface, dwFlags, debugstr_w(pszAssemblyName), pAsmInfo); - return E_NOTIMPL; + if (pAsmInfo) + { + if (pAsmInfo->cbAssemblyInfo == 0) + pAsmInfo->cbAssemblyInfo = sizeof(ASSEMBLY_INFO); + else if (pAsmInfo->cbAssemblyInfo != sizeof(ASSEMBLY_INFO)) + return E_INVALIDARG; + } + + hr = CreateAssemblyNameObject(&asmname, pszAssemblyName, + CANOF_PARSE_DISPLAY_NAME, NULL); + if (FAILED(hr)) + return hr; + + hr = CreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL); + if (FAILED(hr)) + goto done; + + hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0); + if (hr == S_FALSE) + { + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + goto done; + } + + if (!pAsmInfo) + goto done; + + pAsmInfo->dwAssemblyFlags = ASSEMBLYINFO_FLAG_INSTALLED; + +done: + IAssemblyName_Release(asmname); + if (next) IAssemblyName_Release(next); + if (asmenum) IAssemblyEnum_Release(asmenum); + + return hr; } static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyCacheItem(IAssemblyCache *iface, @@ -190,14 +240,17 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, LPCWSTR pszManifestFilePath, LPCFUSION_INSTALL_REFERENCE pRefData) { + static const WCHAR format[] = + {'%','s','\\','%','s','\\','%','s','_','_','%','s','\\',0}; + ASSEMBLY *assembly; - LPSTR filename; - LPSTR name = NULL; - LPSTR token = NULL; - LPSTR version = NULL; - LPSTR asmpath = NULL; - CHAR path[MAX_PATH]; - CHAR windir[MAX_PATH]; + LPWSTR filename; + LPWSTR name = NULL; + LPWSTR token = NULL; + LPWSTR version = NULL; + LPWSTR asmpath = NULL; + WCHAR path[MAX_PATH]; + WCHAR asmdir[MAX_PATH]; LPWSTR ext; HRESULT hr; @@ -238,12 +291,9 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, if (FAILED(hr)) goto done; - GetWindowsDirectoryA(windir, MAX_PATH); + get_assembly_directory(asmdir, MAX_PATH); - FIXME("Ignoring assembly architecture!\n"); - - sprintf(path, "%s\\assembly\\GAC_MSIL\\%s\\%s__%s\\", windir, name, - version, token); + sprintfW(path, format, asmdir, name, version, token); create_full_path(path); @@ -251,10 +301,10 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, if (FAILED(hr)) goto done; - filename = PathFindFileNameA(asmpath); + filename = PathFindFileNameW(asmpath); - lstrcatA(path, filename); - if (!CopyFileA(asmpath, path, FALSE)) + strcatW(path, filename); + if (!CopyFileW(asmpath, path, FALSE)) hr = HRESULT_FROM_WIN32(GetLastError()); done: @@ -391,86 +441,3 @@ static const IAssemblyCacheItemVtbl AssemblyCacheItemVtbl = { IAssemblyCacheItemImpl_Commit, IAssemblyCacheItemImpl_AbortItem }; - -/* IAssemblyEnum */ - -typedef struct { - const IAssemblyEnumVtbl *lpIAssemblyEnumVtbl; - - LONG ref; -} IAssemblyEnumImpl; - -static HRESULT WINAPI IAssemblyEnumImpl_QueryInterface(IAssemblyEnum *iface, - REFIID riid, LPVOID *ppobj) -{ - IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface; - - TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj); - - *ppobj = NULL; - - if (IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IAssemblyEnum)) - { - IUnknown_AddRef(iface); - *ppobj = This; - return S_OK; - } - - WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj); - return E_NOINTERFACE; -} - -static ULONG WINAPI IAssemblyEnumImpl_AddRef(IAssemblyEnum *iface) -{ - IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->ref); - - TRACE("(%p)->(ref before = %u)\n", This, refCount - 1); - - return refCount; -} - -static ULONG WINAPI IAssemblyEnumImpl_Release(IAssemblyEnum *iface) -{ - IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface; - ULONG refCount = InterlockedDecrement(&This->ref); - - TRACE("(%p)->(ref before = %u)\n", This, refCount + 1); - - if (!refCount) - HeapFree(GetProcessHeap(), 0, This); - - return refCount; -} - -static HRESULT WINAPI IAssemblyEnumImpl_GetNextAssembly(IAssemblyEnum *iface, - LPVOID pvReserved, - IAssemblyName **ppName, - DWORD dwFlags) -{ - FIXME("(%p, %p, %p, %d) stub!\n", iface, pvReserved, ppName, dwFlags); - return E_NOTIMPL; -} - -static HRESULT WINAPI IAssemblyEnumImpl_Reset(IAssemblyEnum *iface) -{ - FIXME("(%p) stub!\n", iface); - return E_NOTIMPL; -} - -static HRESULT WINAPI IAssemblyEnumImpl_Clone(IAssemblyEnum *iface, - IAssemblyEnum **ppEnum) -{ - FIXME("(%p, %p) stub!\n", iface, ppEnum); - return E_NOTIMPL; -} - -static const IAssemblyEnumVtbl AssemblyEnumVtbl = { - IAssemblyEnumImpl_QueryInterface, - IAssemblyEnumImpl_AddRef, - IAssemblyEnumImpl_Release, - IAssemblyEnumImpl_GetNextAssembly, - IAssemblyEnumImpl_Reset, - IAssemblyEnumImpl_Clone -}; diff --git a/reactos/dll/win32/fusion/asmenum.c b/reactos/dll/win32/fusion/asmenum.c new file mode 100644 index 00000000000..3706f07f511 --- /dev/null +++ b/reactos/dll/win32/fusion/asmenum.c @@ -0,0 +1,443 @@ +/* + * IAssemblyEnum implementation + * + * 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 + */ + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "ole2.h" +#include "guiddef.h" +#include "fusion.h" +#include "corerror.h" +#include "fusionpriv.h" + +#include "wine/debug.h" +#include "wine/unicode.h" +#include "wine/list.h" + +WINE_DEFAULT_DEBUG_CHANNEL(fusion); + +typedef struct _tagASMNAME +{ + struct list entry; + IAssemblyName *name; +} ASMNAME; + +typedef struct +{ + const IAssemblyEnumVtbl *lpIAssemblyEnumVtbl; + + struct list assemblies; + struct list *iter; + LONG ref; +} IAssemblyEnumImpl; + +static HRESULT WINAPI IAssemblyEnumImpl_QueryInterface(IAssemblyEnum *iface, + REFIID riid, LPVOID *ppobj) +{ + IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface; + + TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj); + + *ppobj = NULL; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IAssemblyEnum)) + { + IUnknown_AddRef(iface); + *ppobj = This; + return S_OK; + } + + WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj); + return E_NOINTERFACE; +} + +static ULONG WINAPI IAssemblyEnumImpl_AddRef(IAssemblyEnum *iface) +{ + IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface; + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before = %u)\n", This, refCount - 1); + + return refCount; +} + +static ULONG WINAPI IAssemblyEnumImpl_Release(IAssemblyEnum *iface) +{ + IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface; + ULONG refCount = InterlockedDecrement(&This->ref); + struct list *item, *cursor; + + TRACE("(%p)->(ref before = %u)\n", This, refCount + 1); + + if (!refCount) + { + LIST_FOR_EACH_SAFE(item, cursor, &This->assemblies) + { + ASMNAME *asmname = LIST_ENTRY(item, ASMNAME, entry); + + list_remove(&asmname->entry); + IAssemblyName_Release(asmname->name); + HeapFree(GetProcessHeap(), 0, asmname); + } + + HeapFree(GetProcessHeap(), 0, This); + } + + return refCount; +} + +static HRESULT WINAPI IAssemblyEnumImpl_GetNextAssembly(IAssemblyEnum *iface, + LPVOID pvReserved, + IAssemblyName **ppName, + DWORD dwFlags) +{ + IAssemblyEnumImpl *asmenum = (IAssemblyEnumImpl *)iface; + ASMNAME *asmname; + + TRACE("(%p, %p, %p, %d)\n", iface, pvReserved, ppName, dwFlags); + + if (!ppName) + return E_INVALIDARG; + + asmname = LIST_ENTRY(asmenum->iter, ASMNAME, entry); + if (!asmname) + return S_FALSE; + + *ppName = asmname->name; + IAssemblyName_AddRef(*ppName); + + asmenum->iter = list_next(&asmenum->assemblies, asmenum->iter); + + return S_OK; +} + +static HRESULT WINAPI IAssemblyEnumImpl_Reset(IAssemblyEnum *iface) +{ + IAssemblyEnumImpl *asmenum = (IAssemblyEnumImpl *)iface; + + TRACE("(%p)\n", iface); + + asmenum->iter = list_head(&asmenum->assemblies); + return S_OK; +} + +static HRESULT WINAPI IAssemblyEnumImpl_Clone(IAssemblyEnum *iface, + IAssemblyEnum **ppEnum) +{ + FIXME("(%p, %p) stub!\n", iface, ppEnum); + return E_NOTIMPL; +} + +static const IAssemblyEnumVtbl AssemblyEnumVtbl = { + IAssemblyEnumImpl_QueryInterface, + IAssemblyEnumImpl_AddRef, + IAssemblyEnumImpl_Release, + IAssemblyEnumImpl_GetNextAssembly, + IAssemblyEnumImpl_Reset, + IAssemblyEnumImpl_Clone +}; + +static void parse_name(IAssemblyName *name, int depth, LPWSTR path, LPWSTR buf) +{ + WCHAR disp[MAX_PATH]; + 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 (depth == 0) + { + size = MAX_PATH; + *disp = '\0'; + hr = IAssemblyName_GetName(name, &size, disp); + if (SUCCEEDED(hr)) + sprintfW(buf, ss_fmt, path, disp); + else + sprintfW(buf, ss_fmt, path, star); + } + else if (depth == 1) + { + major_size = sizeof(major); + IAssemblyName_GetProperty(name, ASM_NAME_MAJOR_VERSION, &major, &major_size); + + minor_size = sizeof(minor); + IAssemblyName_GetProperty(name, ASM_NAME_MINOR_VERSION, &minor, &minor_size); + + build_size = sizeof(build); + IAssemblyName_GetProperty(name, ASM_NAME_BUILD_NUMBER, &build, &build_size); + + revision_size = sizeof(revision); + IAssemblyName_GetProperty(name, ASM_NAME_REVISION_NUMBER, &revision, &revision_size); + + if (!major_size || !minor_size || !build_size || !revision_size) verptr = star; + else + { + sprintfW(version, ver_fmt, major, minor, build, revision); + verptr = version; + } + + size = sizeof(token); + IAssemblyName_GetProperty(name, ASM_NAME_PUBLIC_KEY_TOKEN, token, &size); + + if (!size) pubkeyptr = star; + else + { + token_to_str(token, token_str); + pubkeyptr = token_str; + } + + sprintfW(buf, verpubkey, path, verptr, pubkeyptr); + } +} + +static int compare_assembly_names(ASMNAME *asmname1, ASMNAME *asmname2) +{ + int ret; + WORD version1, version2; + WCHAR name1[MAX_PATH], name2[MAX_PATH]; + WCHAR token_str1[TOKEN_LENGTH + 1], token_str2[TOKEN_LENGTH + 1]; + BYTE token1[BYTES_PER_TOKEN], token2[BYTES_PER_TOKEN]; + DWORD size, i; + + size = sizeof(name1); + IAssemblyName_GetProperty(asmname1->name, ASM_NAME_NAME, &name1, &size); + size = sizeof(name2); + IAssemblyName_GetProperty(asmname2->name, ASM_NAME_NAME, &name2, &size); + + if ((ret = strcmpiW(name1, name2))) return ret; + + for (i = ASM_NAME_MAJOR_VERSION; i < ASM_NAME_CULTURE; i++) + { + size = sizeof(version1); + IAssemblyName_GetProperty(asmname1->name, i, &version1, &size); + size = sizeof(version2); + IAssemblyName_GetProperty(asmname2->name, i, &version2, &size); + + if (version1 < version2) return -1; + if (version1 > version2) return 1; + } + + /* FIXME: compare cultures */ + + size = sizeof(token1); + IAssemblyName_GetProperty(asmname1->name, ASM_NAME_PUBLIC_KEY_TOKEN, token1, &size); + size = sizeof(token2); + IAssemblyName_GetProperty(asmname2->name, ASM_NAME_PUBLIC_KEY_TOKEN, token2, &size); + + token_to_str(token1, token_str1); + token_to_str(token2, token_str2); + + if ((ret = strcmpiW(token_str1, token_str2))) return ret; + + return 0; +} + +/* insert assembly in list preserving sort order */ +static void insert_assembly(struct list *assemblies, ASMNAME *to_insert) +{ + struct list *item; + + LIST_FOR_EACH(item, assemblies) + { + ASMNAME *name = LIST_ENTRY(item, ASMNAME, entry); + + if (compare_assembly_names(name, to_insert) > 0) + { + list_add_before(&name->entry, &to_insert->entry); + return; + } + } + list_add_tail(assemblies, &to_insert->entry); +} + +static HRESULT enum_gac_assemblies(struct list *assemblies, IAssemblyName *name, + int depth, LPWSTR path) +{ + WIN32_FIND_DATAW ffd; + WCHAR buf[MAX_PATH]; + WCHAR disp[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 parent_fmt[] = {'%','s',',',' ',0}; + static const WCHAR dblunder[] = {'_','_',0}; + static const WCHAR fmt[] = {'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}; + + if (name) + parse_name(name, depth, path, buf); + else + sprintfW(buf, search_fmt, path); + + hfind = FindFirstFileW(buf, &ffd); + if (hfind == INVALID_HANDLE_VALUE) + return S_OK; + + do + { + if (!lstrcmpW(ffd.cFileName, dot) || !lstrcmpW(ffd.cFileName, dotdot)) + continue; + + if (depth == 0) + { + if (name) + ptr = strrchrW(buf, '\\') + 1; + else + ptr = ffd.cFileName; + + sprintfW(parent, parent_fmt, ptr); + } + else if (depth == 1) + { + ptr = strstrW(ffd.cFileName, dblunder); + *ptr = '\0'; + ptr += 2; + sprintfW(buf, fmt, ffd.cFileName, ptr); + + lstrcpyW(disp, parent); + lstrcatW(disp, buf); + + asmname = HeapAlloc(GetProcessHeap(), 0, sizeof(ASMNAME)); + if (!asmname) + { + hr = E_OUTOFMEMORY; + break; + } + + hr = CreateAssemblyNameObject(&asmname->name, disp, + CANOF_PARSE_DISPLAY_NAME, NULL); + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, asmname); + break; + } + + insert_assembly(assemblies, asmname); + continue; + } + + sprintfW(buf, ss_fmt, path, ffd.cFileName); + hr = enum_gac_assemblies(assemblies, name, depth + 1, buf); + if (FAILED(hr)) + break; + } while (FindNextFileW(hfind, &ffd) != 0); + + FindClose(hfind); + return hr; +} + +static HRESULT enumerate_gac(IAssemblyEnumImpl *asmenum, IAssemblyName *pName) +{ + WCHAR path[MAX_PATH]; + WCHAR buf[MAX_PATH]; + 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_GAC, buf, &size); + if (FAILED(hr)) + return hr; + + lstrcpyW(path, buf); + lstrcatW(path, under32); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, path); + if (FAILED(hr)) + return hr; + + lstrcpyW(path, buf); + lstrcatW(path, msil); + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, path); + if (FAILED(hr)) + return hr; + + hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, buf); + if (FAILED(hr)) + return hr; + + return S_OK; +} + +/****************************************************************** + * CreateAssemblyEnum (FUSION.@) + */ +HRESULT WINAPI CreateAssemblyEnum(IAssemblyEnum **pEnum, IUnknown *pUnkReserved, + IAssemblyName *pName, DWORD dwFlags, LPVOID pvReserved) +{ + IAssemblyEnumImpl *asmenum; + HRESULT hr; + + TRACE("(%p, %p, %p, %08x, %p)\n", pEnum, pUnkReserved, + pName, dwFlags, pvReserved); + + if (!pEnum) + return E_INVALIDARG; + + if (dwFlags == 0 || dwFlags == ASM_CACHE_ROOT) + return E_INVALIDARG; + + asmenum = HeapAlloc(GetProcessHeap(), 0, sizeof(IAssemblyEnumImpl)); + if (!asmenum) + return E_OUTOFMEMORY; + + asmenum->lpIAssemblyEnumVtbl = &AssemblyEnumVtbl; + asmenum->ref = 1; + list_init(&asmenum->assemblies); + + if (dwFlags & ASM_CACHE_GAC) + { + hr = enumerate_gac(asmenum, pName); + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, asmenum); + return hr; + } + } + + asmenum->iter = list_head(&asmenum->assemblies); + *pEnum = (IAssemblyEnum *)asmenum; + + return S_OK; +} diff --git a/reactos/dll/win32/fusion/asmname.c b/reactos/dll/win32/fusion/asmname.c index 50ae05ec525..913674aa80e 100644 --- a/reactos/dll/win32/fusion/asmname.c +++ b/reactos/dll/win32/fusion/asmname.c @@ -33,23 +33,10 @@ #include "wine/debug.h" #include "wine/unicode.h" +#include "fusionpriv.h" WINE_DEFAULT_DEBUG_CHANNEL(fusion); -static inline LPWSTR strdupW(LPCWSTR src) -{ - LPWSTR dest; - - if (!src) - return NULL; - - dest = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(src) + 1) * sizeof(WCHAR)); - if (dest) - lstrcpyW(dest, src); - - return dest; -} - typedef struct { const IAssemblyNameVtbl *lpIAssemblyNameVtbl; @@ -57,7 +44,7 @@ typedef struct { LPWSTR name; LPWSTR culture; - BYTE version[4]; + WORD version[4]; DWORD versize; BYTE pubkey[8]; @@ -157,28 +144,28 @@ static HRESULT WINAPI IAssemblyNameImpl_GetProperty(IAssemblyName *iface, case ASM_NAME_MAJOR_VERSION: *pcbProperty = 0; - *((LPDWORD)pvProperty) = name->version[0]; + *((WORD *)pvProperty) = name->version[0]; if (name->versize >= 1) *pcbProperty = sizeof(WORD); break; case ASM_NAME_MINOR_VERSION: *pcbProperty = 0; - *((LPDWORD)pvProperty) = name->version[1]; + *((WORD *)pvProperty) = name->version[1]; if (name->versize >= 2) *pcbProperty = sizeof(WORD); break; case ASM_NAME_BUILD_NUMBER: *pcbProperty = 0; - *((LPDWORD)pvProperty) = name->version[2]; + *((WORD *)pvProperty) = name->version[2]; if (name->versize >= 3) *pcbProperty = sizeof(WORD); break; case ASM_NAME_REVISION_NUMBER: *pcbProperty = 0; - *((LPDWORD)pvProperty) = name->version[3]; + *((WORD *)pvProperty) = name->version[3]; if (name->versize >= 4) *pcbProperty = sizeof(WORD); break; @@ -222,7 +209,7 @@ static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface, { IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface; - TRACE("(%p, %s, %p, %d)\n", iface, debugstr_w(szDisplayName), + TRACE("(%p, %p, %p, %d)\n", iface, szDisplayName, pccDisplayName, dwDisplayFlags); if (!name->displayname || !*name->displayname) @@ -467,6 +454,8 @@ static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyNam *ptr2 = '\0'; + while (*str == ' ') str++; + if (!lstrcmpW(str, version)) hr = parse_version(name, ptr); else if (!lstrcmpW(str, culture)) diff --git a/reactos/dll/win32/fusion/assembly.c b/reactos/dll/win32/fusion/assembly.c index 7be541c4a4f..faef8efdd15 100644 --- a/reactos/dll/win32/fusion/assembly.c +++ b/reactos/dll/win32/fusion/assembly.c @@ -52,7 +52,7 @@ typedef struct tagCLRTABLE struct tagASSEMBLY { - LPSTR path; + LPWSTR path; HANDLE hfile; HANDLE hmap; @@ -76,22 +76,6 @@ struct tagASSEMBLY BYTE *blobs; }; -static LPSTR strdupWtoA(LPCWSTR str) -{ - LPSTR ret = NULL; - DWORD len; - - if (!str) - return ret; - - len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL); - ret = HeapAlloc(GetProcessHeap(), 0, len); - if (ret) - WideCharToMultiByte(CP_ACP, 0, str, -1, ret, len, NULL, NULL); - - return ret; -} - static DWORD rva_to_offset(IMAGE_NT_HEADERS *nthdrs, DWORD rva) { DWORD offset = rva, limit; @@ -647,14 +631,18 @@ static HRESULT parse_pe_header(ASSEMBLY *assembly) if (!assembly->nthdr) return E_FAIL; - if (assembly->nthdr->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) + if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { IMAGE_OPTIONAL_HEADER64 *opthdr = (IMAGE_OPTIONAL_HEADER64 *)&assembly->nthdr->OptionalHeader; datadirs = opthdr->DataDirectory; } else - datadirs = assembly->nthdr->OptionalHeader.DataDirectory; + { + IMAGE_OPTIONAL_HEADER32 *opthdr = + (IMAGE_OPTIONAL_HEADER32 *)&assembly->nthdr->OptionalHeader; + datadirs = opthdr->DataDirectory; + } if (!datadirs) return E_FAIL; @@ -684,7 +672,7 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) if (!assembly) return E_OUTOFMEMORY; - assembly->path = strdupWtoA(file); + assembly->path = strdupW(file); if (!assembly->path) { hr = E_OUTOFMEMORY; @@ -743,16 +731,21 @@ HRESULT assembly_release(ASSEMBLY *assembly) return S_OK; } -static LPSTR assembly_dup_str(ASSEMBLY *assembly, DWORD index) +static LPWSTR assembly_dup_str(ASSEMBLY *assembly, DWORD index) { + int len; + LPWSTR cpy; LPSTR str = (LPSTR)&assembly->strings[index]; - LPSTR cpy = HeapAlloc(GetProcessHeap(), 0, strlen(str)+1); - if (cpy) - strcpy(cpy, str); + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + + if ((cpy = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) + MultiByteToWideChar(CP_ACP, 0, str, -1, cpy, len); + return cpy; } -HRESULT assembly_get_name(ASSEMBLY *assembly, LPSTR *name) +HRESULT assembly_get_name(ASSEMBLY *assembly, LPWSTR *name) { BYTE *ptr; LONG offset; @@ -779,59 +772,43 @@ HRESULT assembly_get_name(ASSEMBLY *assembly, LPSTR *name) return S_OK; } -HRESULT assembly_get_path(ASSEMBLY *assembly, LPSTR *path) +HRESULT assembly_get_path(ASSEMBLY *assembly, LPWSTR *path) { - LPSTR cpy = HeapAlloc(GetProcessHeap(), 0, strlen(assembly->path)+1); + LPWSTR cpy = HeapAlloc(GetProcessHeap(), 0, (strlenW(assembly->path) + 1) * sizeof(WCHAR)); *path = cpy; if (cpy) - strcpy(cpy, assembly->path); + strcpyW(cpy, assembly->path); else return E_OUTOFMEMORY; return S_OK; } -HRESULT assembly_get_version(ASSEMBLY *assembly, LPSTR *version) +HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version) { - LPSTR verdata; - VS_FIXEDFILEINFO *ffi; - HRESULT hr = S_OK; - DWORD size; + static const WCHAR format[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; - size = GetFileVersionInfoSizeA(assembly->path, NULL); - if (!size) - return HRESULT_FROM_WIN32(GetLastError()); + ASSEMBLYTABLE *asmtbl; + LONG offset; - verdata = HeapAlloc(GetProcessHeap(), 0, size); - if (!verdata) + *version = NULL; + + offset = assembly->tables[TableFromToken(mdtAssembly)].offset; + if (offset == -1) + return E_FAIL; + + asmtbl = assembly_data_offset(assembly, offset); + if (!asmtbl) + return E_FAIL; + + *version = HeapAlloc(GetProcessHeap(), 0, sizeof(format) + 4 * strlen("65535") * sizeof(WCHAR)); + if (!*version) return E_OUTOFMEMORY; - if (!GetFileVersionInfoA(assembly->path, 0, size, verdata)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - goto done; - } + sprintfW(*version, format, asmtbl->MajorVersion, asmtbl->MinorVersion, + asmtbl->BuildNumber, asmtbl->RevisionNumber); - if (!VerQueryValueA(verdata, "\\", (LPVOID *)&ffi, &size)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - goto done; - } - - *version = HeapAlloc(GetProcessHeap(), 0, MAX_PATH); - if (!*version) - { - hr = E_OUTOFMEMORY; - goto done; - } - - sprintf(*version, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS), - LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS), - LOWORD(ffi->dwFileVersionLS)); - -done: - HeapFree(GetProcessHeap(), 0, verdata); - return hr; + return S_OK; } HRESULT assembly_get_architecture(ASSEMBLY *assembly, DWORD fixme) @@ -845,26 +822,7 @@ static BYTE *assembly_get_blob(ASSEMBLY *assembly, WORD index, ULONG *size) return GetData(&assembly->blobs[index], size); } -static void bytes_to_str(BYTE *bytes, DWORD len, LPSTR str) -{ - DWORD i; - - static const char hexval[16] = { - '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' - }; - - for(i = 0; i < len; i++) - { - str[i * 2] = hexval[((bytes[i] >> 4) & 0xF)]; - str[i * 2 + 1] = hexval[(bytes[i]) & 0x0F]; - } -} - -#define BYTES_PER_TOKEN 8 -#define CHARS_PER_BYTE 2 -#define TOKEN_LENGTH (BYTES_PER_TOKEN * CHARS_PER_BYTE + 1) - -HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPSTR *token) +HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token) { ASSEMBLYTABLE *asmtbl; ULONG i, size; @@ -875,7 +833,7 @@ HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPSTR *token) BYTE *pubkey; BYTE tokbytes[BYTES_PER_TOKEN]; HRESULT hr = E_FAIL; - LPSTR tok; + LPWSTR tok; *token = NULL; @@ -916,15 +874,14 @@ HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPSTR *token) for (i = size - 1; i >= size - 8; i--) tokbytes[size - i - 1] = hashdata[i]; - tok = HeapAlloc(GetProcessHeap(), 0, TOKEN_LENGTH); + tok = HeapAlloc(GetProcessHeap(), 0, (TOKEN_LENGTH + 1) * sizeof(WCHAR)); if (!tok) { hr = E_OUTOFMEMORY; goto done; } - bytes_to_str(tokbytes, BYTES_PER_TOKEN, tok); - tok[TOKEN_LENGTH - 1] = '\0'; + token_to_str(tokbytes, tok); *token = tok; hr = S_OK; diff --git a/reactos/dll/win32/fusion/fusion.c b/reactos/dll/win32/fusion/fusion.c index ac01cf415ee..1435743d8c9 100644 --- a/reactos/dll/win32/fusion/fusion.c +++ b/reactos/dll/win32/fusion/fusion.c @@ -54,18 +54,6 @@ HRESULT WINAPI CompareAssemblyIdentity(LPCWSTR pwzAssemblyIdentity1, BOOL fUnifi return E_NOTIMPL; } -/****************************************************************** - * CreateAssemblyEnum (FUSION.@) - */ -HRESULT WINAPI CreateAssemblyEnum(IAssemblyEnum **pEnum, IUnknown *pUnkReserved, - IAssemblyName *pName, DWORD dwFlags, LPVOID pvReserved) -{ - FIXME("(%p, %p, %p, %08x, %p) stub!\n", pEnum, pUnkReserved, - pName, dwFlags, pvReserved); - - return E_NOTIMPL; -} - /****************************************************************** * CreateInstallReferenceEnum (FUSION.@) */ @@ -129,8 +117,11 @@ HRESULT WINAPI GetCachePath(ASM_CACHE_FLAGS dwCacheFlags, LPWSTR pwzCachePath, 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 zapfmt[] = { - '%','s','\\','%','s','\\','%','s','%','s','_','3','2',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 TRACE("(%08x, %p, %p)\n", dwCacheFlags, pwzCachePath, pcchPath); diff --git a/reactos/dll/win32/fusion/fusion.rbuild b/reactos/dll/win32/fusion/fusion.rbuild index bef97c68936..a493d97795e 100644 --- a/reactos/dll/win32/fusion/fusion.rbuild +++ b/reactos/dll/win32/fusion/fusion.rbuild @@ -10,6 +10,7 @@ advapi32 dbghelp asmcache.c + asmenum.c asmname.c assembly.c fusion.c diff --git a/reactos/dll/win32/fusion/fusionpriv.h b/reactos/dll/win32/fusion/fusionpriv.h index a4e6193b054..363d530313d 100644 --- a/reactos/dll/win32/fusion/fusionpriv.h +++ b/reactos/dll/win32/fusion/fusionpriv.h @@ -26,6 +26,7 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" +#include "winver.h" #include @@ -429,10 +430,44 @@ typedef struct tagASSEMBLY ASSEMBLY; HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file); HRESULT assembly_release(ASSEMBLY *assembly); -HRESULT assembly_get_name(ASSEMBLY *assembly, LPSTR *name); -HRESULT assembly_get_path(ASSEMBLY *assembly, LPSTR *path); -HRESULT assembly_get_version(ASSEMBLY *assembly, LPSTR *version); +HRESULT assembly_get_name(ASSEMBLY *assembly, LPWSTR *name); +HRESULT assembly_get_path(ASSEMBLY *assembly, LPWSTR *path); +HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version); HRESULT assembly_get_architecture(ASSEMBLY *assembly, DWORD fixme); -HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPSTR *token); +HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token); + +static inline LPWSTR strdupW(LPCWSTR src) +{ + LPWSTR dest; + + if (!src) + return NULL; + + dest = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(src) + 1) * sizeof(WCHAR)); + if (dest) + lstrcpyW(dest, src); + + return dest; +} + +#define BYTES_PER_TOKEN 8 +#define CHARS_PER_BYTE 2 +#define TOKEN_LENGTH (BYTES_PER_TOKEN * CHARS_PER_BYTE + 1) + +static inline void token_to_str(BYTE *bytes, LPWSTR str) +{ + DWORD i; + + static const WCHAR hexval[16] = { + '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' + }; + + for(i = 0; i < BYTES_PER_TOKEN; i++) + { + str[i * 2] = hexval[((bytes[i] >> 4) & 0xF)]; + str[i * 2 + 1] = hexval[(bytes[i]) & 0x0F]; + } + str[i * 2] = 0; +} #endif /* __WINE_FUSION_PRIVATE__ */