Re: [5/5] fusion: Implement IAssemblyCache::QueryAssemblyInfo.
It would be a lot easier if you just took over my patches that implement this properly: [PATCH 1/3] fusion: Implement the IAssemblyEnum interface. [try4] http://winehq.org/pipermail/wine-patches/2009-January/066994.html [PATCH 2/3] fusion: Add tests for the IAssemblyEnum interface. [try4] http://winehq.org/pipermail/wine-patches/2009-January/066995.html [PATCH 3/3] fusion: Add initial implementation of IAssemblyCache::QueryAssemblyInfo. [try4] http://winehq.org/pipermail/wine-patches/2009-January/066996.html The tests need to be fixed in a couple places to take directory ordering (or lack-thereof) into account. http://winehq.org/pipermail/wine-devel/2009-January/071727.html -- James Hawkins On Fri, Feb 13, 2009 at 12:14 AM, Hans Leidekker <hans(a)meelstraat.net> wrote:
diff --git a/dlls/fusion/asmcache.c b/dlls/fusion/asmcache.c index 73756b3..2ce1995 100644 --- a/dlls/fusion/asmcache.c +++ b/dlls/fusion/asmcache.c @@ -41,6 +41,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(fusion);
+static const WCHAR ext_exe[] = {'.','e','x','e',0}; +static const WCHAR ext_dll[] = {'.','d','l','l',0}; + static BOOL create_full_path(LPCWSTR path) { LPWSTR new_path; @@ -167,15 +170,102 @@ static HRESULT WINAPI IAssemblyCacheImpl_UninstallAssembly(IAssemblyCache *iface return E_NOTIMPL; }
+static BOOL get_file_size(const WCHAR *filename, LARGE_INTEGER *size) +{ + HANDLE file; + + size->QuadPart = 0; + file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) return FALSE; + GetFileSizeEx(file, size); + CloseHandle(file); + return TRUE; +} + +#define TOKEN_LEN 16 +#define CULTURE_LEN 17 +#define NAME_LEN 100 + static HRESULT WINAPI IAssemblyCacheImpl_QueryAssemblyInfo(IAssemblyCache *iface, DWORD dwFlags, LPCWSTR pszAssemblyName, ASSEMBLY_INFO *pAsmInfo) { - FIXME("(%p, %d, %s, %p) stub!\n", iface, dwFlags, - debugstr_w(pszAssemblyName), pAsmInfo); + static const WCHAR fmt[] = + {'%','s','\\','%','s','\\','%','u','.','%','u','.','%','u', + '.','%','u','_','%','s','_','%','s','\\','%','s','%','s',0};
- return E_NOTIMPL; + HRESULT hr; + IAssemblyName *asmname; + WCHAR asmdir[MAX_PATH], path[MAX_PATH]; + WCHAR name[NAME_LEN + 1], culture[CULTURE_LEN + 1], token[TOKEN_LEN + 1]; + WORD major, minor, build, revision; + BYTE buf[8]; + DWORD size; + LARGE_INTEGER filesize; + BOOL installed; + + TRACE("(%p, %d, %s, %p)\n", iface, dwFlags, debugstr_w(pszAssemblyName), pAsmInfo); + + hr = CreateAssemblyNameObject(&asmname, pszAssemblyName, CANOF_PARSE_DISPLAY_NAME, NULL); + if (FAILED(hr)) + return hr; + + size = sizeof(name); + IAssemblyName_GetProperty(asmname, ASM_NAME_NAME, name, &size); + + size = sizeof(buf); + memset(buf, 0, sizeof(buf)); + IAssemblyName_GetProperty(asmname, ASM_NAME_PUBLIC_KEY_TOKEN, buf, &size); + + token_to_str(buf, token); + + size = sizeof(major); + IAssemblyName_GetProperty(asmname, ASM_NAME_MAJOR_VERSION, &major, &size); + + size = sizeof(minor); + IAssemblyName_GetProperty(asmname, ASM_NAME_MINOR_VERSION, &minor, &size); + + size = sizeof(build); + IAssemblyName_GetProperty(asmname, ASM_NAME_BUILD_NUMBER, &build, &size); + + size = sizeof(revision); + IAssemblyName_GetProperty(asmname, ASM_NAME_REVISION_NUMBER, &revision, &size); + + size = sizeof(culture); + IAssemblyName_GetProperty(asmname, ASM_NAME_CULTURE, &culture, &size); + + get_assembly_directory(asmdir, MAX_PATH); + + sprintfW(path, fmt, asmdir, + name, major, minor, build, revision, culture, token, name, ext_dll); + + /* FIXME: there can be more than one file */ + if (!(installed = get_file_size(path, &filesize))) + { + strcpyW(strrchrW(path, '.'), ext_exe); + if (!(installed = get_file_size(path, &filesize))) + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + } + + if (pAsmInfo) + { + pAsmInfo->uliAssemblySizeInKB.QuadPart = filesize.QuadPart; + pAsmInfo->dwAssemblyFlags = 0; + if (installed) + { + pAsmInfo->cbAssemblyInfo = sizeof(ASSEMBLY_INFO); + pAsmInfo->dwAssemblyFlags = ASSEMBLYINFO_FLAG_INSTALLED; + pAsmInfo->pszCurrentAssemblyPathBuf = strdupW(path); + pAsmInfo->cchBuf = strlenW(pAsmInfo->pszCurrentAssemblyPathBuf) + 1; + } + } + + if (dwFlags & QUERYASMINFO_FLAG_VALIDATE) FIXME("not validating assembly\n"); + + IAssemblyName_Release(asmname); + return hr; }
static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyCacheItem(IAssemblyCache *iface, @@ -216,9 +306,6 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, LPWSTR ext; HRESULT hr;
- static const WCHAR ext_exe[] = {'.','e','x','e',0}; - static const WCHAR ext_dll[] = {'.','d','l','l',0}; - TRACE("(%p, %d, %s, %p)\n", iface, dwFlags, debugstr_w(pszManifestFilePath), pRefData);
diff --git a/dlls/fusion/assembly.c b/dlls/fusion/assembly.c index 049bf15..a7b09c8 100644 --- a/dlls/fusion/assembly.c +++ b/dlls/fusion/assembly.c @@ -818,25 +818,6 @@ 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, 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 < 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, LPWSTR *token) { ASSEMBLYTABLE *asmtbl; @@ -896,8 +877,7 @@ HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token) 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/dlls/fusion/fusionpriv.h b/dlls/fusion/fusionpriv.h index 405133b..6dec11b 100644 --- a/dlls/fusion/fusionpriv.h +++ b/dlls/fusion/fusionpriv.h @@ -445,4 +445,24 @@ static inline WCHAR *strdupW(const WCHAR *src) return dst; }
+#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__ */ diff --git a/dlls/fusion/tests/asmcache.c b/dlls/fusion/tests/asmcache.c index fe2b466..42d8cba 100644 --- a/dlls/fusion/tests/asmcache.c +++ b/dlls/fusion/tests/asmcache.c @@ -1020,11 +1020,8 @@ static void test_QueryAssemblyInfo(void) /* assembly not installed yet */ INIT_ASM_INFO(); hr = IAssemblyCache_QueryAssemblyInfo(cache, 0, wine, &info); - todo_wine - { - ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), - "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); - } + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), + "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO), "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo); ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags); @@ -1043,10 +1040,7 @@ static void test_QueryAssemblyInfo(void) INIT_ASM_INFO(); hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE, NULL, &info); - todo_wine - { - ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); - } + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO), "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo); ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags); @@ -1062,10 +1056,7 @@ static void test_QueryAssemblyInfo(void) INIT_ASM_INFO(); hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE, empty, &info); - todo_wine - { - ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); - } + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO), "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo); ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags); @@ -1100,11 +1091,8 @@ static void test_QueryAssemblyInfo(void) /* pwzCachePath is full filename */ INIT_ASM_INFO(); hr = IAssemblyCache_QueryAssemblyInfo(cache, 0, winedll, &info); - todo_wine - { - ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), - "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); - } + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), + "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO), "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo); ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags); @@ -1332,11 +1320,8 @@ static void test_QueryAssemblyInfo(void) lstrcatW(name, badver); hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE, name, &info); - todo_wine - { - ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), - "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); - } + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), + "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO), "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo); ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags); @@ -1379,11 +1364,8 @@ static void test_QueryAssemblyInfo(void) lstrcatW(name, badculture); hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE, name, &info); - todo_wine - { - ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), - "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); - } + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), + "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO), "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo); ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags); @@ -1426,11 +1408,8 @@ static void test_QueryAssemblyInfo(void) lstrcatW(name, badpubkey); hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE, name, &info); - todo_wine - { - ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), - "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); - } + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), + "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr); ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO), "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo); ok(info.dwAssemblyFlags == 0, "Expected 0, got %08x\n", info.dwAssemblyFlags); @@ -1466,6 +1445,31 @@ static void test_QueryAssemblyInfo(void) "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf); }
+ /* fully qualified display name */ + INIT_ASM_INFO(); + lstrcpyW(name, wine); + lstrcatW(name, commasep); + lstrcatW(name, ver); + lstrcatW(name, commasep); + lstrcatW(name, culture); + lstrcatW(name, commasep); + lstrcatW(name, pubkey); + hr = IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_GETSIZE, + name, &info); + ok(info.cbAssemblyInfo == sizeof(ASSEMBLY_INFO), + "Expected sizeof(ASSEMBLY_INFO), got %d\n", info.cbAssemblyInfo); + ok(info.uliAssemblySizeInKB.u.HighPart == 0, + "Expected 0, got %d\n", info.uliAssemblySizeInKB.u.HighPart); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED, + "Expected ASSEMBLYINFO_FLAG_INSTALLED, got %08x\n", info.dwAssemblyFlags); + ok(info.uliAssemblySizeInKB.u.LowPart == sizeof(ASSEMBLY), + "Expected 4, got %d\n", info.uliAssemblySizeInKB.u.LowPart); + ok(!lstrcmpW(info.pszCurrentAssemblyPathBuf, asmpath), + "Wrong assembly path returned\n"); + ok(info.cchBuf == lstrlenW(asmpath) + 1, + "Expected %d, got %d\n", lstrlenW(asmpath) + 1, info.cchBuf); + /* uninstall the assembly from the GAC */ disp = 0xf00dbad; hr = IAssemblyCache_UninstallAssembly(cache, 0, wine, NULL, &disp);
On Friday 13 February 2009 09:31:54 James Hawkins wrote:
It would be a lot easier if you just took over my patches that implement this properly:
Hmm, I missed those. I'll integrate them with mine. -Hans
On Fri, Feb 13, 2009 at 12:43 AM, Hans Leidekker <hans(a)codeweavers.com> wrote:
On Friday 13 February 2009 09:31:54 James Hawkins wrote:
It would be a lot easier if you just took over my patches that implement this properly:
Hmm, I missed those. I'll integrate them with mine.
Thanks! -- James Hawkins
participants (2)
-
Hans Leidekker -
James Hawkins