-- v2: msi: Fix getting version info for library loaded into wow64 process. msi: Get system directory just once. msi: Allocate buffer in msi_get_file_version_info(). msi/tests: Test insalling 64 bit library loaded into wow64 installer process. version/tests: Test GetFileVersionInfoW() with wow64 FS redirection. kernel32/tests: Test loading dll as resource or datafile with wow64 FS redirection disabled.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/kernel32/tests/loader.c | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index 9ecaf438322..cd621a04ff4 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -4616,10 +4616,27 @@ static void test_wow64_redirection(void) char buffer[MAX_PATH]; static const char *dlls[] = {"wlanapi.dll", "dxgi.dll", "dwrite.dll"}; unsigned i; + HMODULE mod, mod_fixed, kernelbase; + IMAGE_NT_HEADERS *nt; + WORD machine;
if (!is_wow64) return;
+ kernelbase = GetModuleHandleW(L"kernelbase.dll"); + nt = RtlImageNtHeader(kernelbase); + machine = nt->FileHeader.Machine; + + ok(!GetModuleHandleA("rasapi32.dll"), "rasapi32.dll is already loaded.\n"); + + mod = LoadLibraryExW(L"c:\windows\system32\rasapi32.dll", 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE); + mod_fixed = (HMODULE)((ULONG_PTR)mod & ~(ULONG_PTR)3); + ok(!!mod_fixed, "got NULL.\n" ); + nt = RtlImageNtHeader(mod_fixed); + ok(!!nt, "got NULL.\n"); + ok(nt->FileHeader.Machine == machine, "got wrong machine.\n"); + FreeLibrary(mod); + /* Disable FS redirection, then test loading system libraries (pick ones that shouldn't * already be loaded in this process). */ @@ -4632,6 +4649,34 @@ static void test_wow64_redirection(void) test_wow64_redirection_for_dll(buffer, TRUE); }
+ mod = LoadLibraryExW(L"c:\windows\system32\kernelbase.dll", 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE); + ok(!!mod, "got NULL.\n" ); + ok(mod == kernelbase, "got different modules.\n"); + FreeLibrary(mod); + + mod = LoadLibraryExW(L"c:\windows\system32\kernelbase.dll", 0, LOAD_LIBRARY_AS_DATAFILE); + ok(!!mod, "got NULL.\n" ); + ok(mod == kernelbase, "got different modules.\n"); + FreeLibrary(mod); + + ok(!GetModuleHandleA("rasapi32.dll"), "rasapi32.dll is already loaded.\n"); + mod = LoadLibraryExW(L"c:\windows\system32\rasapi32.dll", 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE); + mod_fixed = (HMODULE)((ULONG_PTR)mod & ~(ULONG_PTR)3); + ok(!!mod_fixed, "got NULL.\n" ); + nt = RtlImageNtHeader(mod_fixed); + ok(!!nt, "got NULL.\n"); + ok(nt->FileHeader.Machine != machine, "got 32 bit dll.\n"); + FreeLibrary(mod); + + ok(!GetModuleHandleA("rasapi32.dll"), "rasapi32.dll is already loaded.\n"); + mod = LoadLibraryExW(L"c:\windows\system32\rasapi32.dll", 0, LOAD_LIBRARY_AS_DATAFILE); + mod_fixed = (HMODULE)((ULONG_PTR)mod & ~(ULONG_PTR)3); + ok(!!mod_fixed, "got NULL.\n" ); + nt = RtlImageNtHeader(mod_fixed); + ok(!!nt, "got NULL.\n"); + ok(nt->FileHeader.Machine != machine, "got 32 bit dll.\n"); + FreeLibrary(mod); + ok(pWow64RevertWow64FsRedirection(OldValue), "Re-enabling FS redirection failed\n"); /* and results don't depend whether redirection is enabled or not */ for (i = 0; i < ARRAY_SIZE(dlls); i++)
From: Paul Gofman pgofman@codeweavers.com
--- dlls/version/tests/info.c | 109 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+)
diff --git a/dlls/version/tests/info.c b/dlls/version/tests/info.c index 9eba180f215..b498f5331c8 100644 --- a/dlls/version/tests/info.c +++ b/dlls/version/tests/info.c @@ -30,6 +30,14 @@ #include "verrsrc.h" #include "wine/test.h"
+static BOOL is_wow64; + +static char system_dir[MAX_PATH]; +static char syswow_dir[MAX_PATH]; + +static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(void **); +static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(void *); + #define MY_LAST_ERROR ((DWORD)-1) #define EXPECT_BAD_PATH__NOT_FOUND \ ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \ @@ -868,8 +876,108 @@ static void test_GetFileVersionInfoEx(void) return; }
+static void test_wow64_redirection(void) +{ + char buf[MAX_PATH], buf2[MAX_PATH]; + UINT size, translation; + char *ver, *p; + void *cookie; + HMODULE module; + BOOL ret; + + if (!is_wow64) + return; + + ret = pWow64DisableWow64FsRedirection(&cookie); + ok(ret, "got error %lu.\n", GetLastError()); + + sprintf(buf, "%s\psapi.dll", syswow_dir); + sprintf(buf2, "%s\test.dll", syswow_dir); + ret = CopyFileA(buf, buf2, FALSE); + if (!ret && GetLastError() == ERROR_ACCESS_DENIED) + { + ret = pWow64RevertWow64FsRedirection(cookie); + ok(ret, "got error %lu.\n", GetLastError()); + skip("Can't copy file to system directory.\n"); + return; + } + ok(ret, "got error %lu.\n", GetLastError()); + + sprintf(buf, "%s\iphlpapi.dll", system_dir); + sprintf(buf2, "%s\test.dll", system_dir); + ret = CopyFileA(buf, buf2, FALSE); + ok(ret, "got error %lu.\n", GetLastError()); + + module = LoadLibraryA("test.dll"); + ok(!!module, "got error %lu.\n", GetLastError()); + + size = GetFileVersionInfoSizeW(L"C:\windows\system32\test.dll", NULL); + ok(size, "got error %lu.\n", GetLastError()); + ver = malloc(size); + ret = GetFileVersionInfoW(L"C:\windows\system32\test.dll", 0, size, ver); + ok(ret, "got error %lu.\n", GetLastError()); + ret = VerQueryValueA(ver, "\VarFileInfo\Translation", (void **)&p, &size); + ok(ret, "got error %lu.\n", GetLastError()); + translation = *(UINT *)p; + translation = MAKELONG(HIWORD(translation), LOWORD(translation)); + sprintf(buf, "\StringFileInfo\%08x\OriginalFileName", translation); + ret = VerQueryValueA(ver, buf, (LPVOID*)&p, &size); + ok(ret, "got error %lu.\n", GetLastError()); + /* When the module is already loaded GetFileVersionInfoW finds redirected loaded one while the file which + * should've been open with disabled redirection is different. */ + ok(!strnicmp(p, "psapi", 5), "got %s.\n", debugstr_a(p)); + free(ver); + + FreeLibrary(module); + + size = GetFileVersionInfoSizeW(L"C:\windows\system32\test.dll", NULL); + ok(size, "got error %lu.\n", GetLastError()); + ver = malloc(size); + ret = GetFileVersionInfoW(L"C:\windows\system32\test.dll", 0, size, ver); + ok(ret, "got error %lu.\n", GetLastError()); + ret = VerQueryValueA(ver, "\VarFileInfo\Translation", (void **)&p, &size); + ok(ret, "got error %lu.\n", GetLastError()); + translation = *(UINT *)p; + translation = MAKELONG(HIWORD(translation), LOWORD(translation)); + sprintf(buf, "\StringFileInfo\%08x\OriginalFileName", translation); + ret = VerQueryValueA(ver, buf, (LPVOID*)&p, &size); + ok(ret, "got error %lu.\n", GetLastError()); + /* When the module is not loaded GetFileVersionInfoW finds the module in system32 as one would expect. */ + ok(!strnicmp(p, "iphlpapi", 8), "got %s.\n", debugstr_a(p)); + free(ver); + + sprintf(buf2, "%s\test.dll", syswow_dir); + ret = DeleteFileA(buf2); + ok(ret, "got error %lu.\n", GetLastError()); + + sprintf(buf2, "%s\test.dll", system_dir); + ret = DeleteFileA(buf2); + ok(ret, "got error %lu.\n", GetLastError()); + + ret = pWow64RevertWow64FsRedirection(cookie); + ok(ret, "got error %lu.\n", GetLastError()); +} + START_TEST(info) { + HMODULE kernel32 =kernel32 = GetModuleHandleA("kernel32.dll"); + BOOL (WINAPI *pIsWow64Process)(HANDLE, BOOL *); + DWORD size; + + pWow64DisableWow64FsRedirection = (void *)GetProcAddress(kernel32, "Wow64DisableWow64FsRedirection"); + pWow64RevertWow64FsRedirection = (void *)GetProcAddress(kernel32, "Wow64RevertWow64FsRedirection"); + + if ((pIsWow64Process = (void *)GetProcAddress(kernel32, "IsWow64Process"))) + pIsWow64Process( GetCurrentProcess(), &is_wow64 ); + + size = GetSystemDirectoryA(system_dir, ARRAY_SIZE(system_dir)); + ok(size && size < ARRAY_SIZE(system_dir), "Couldn't get system directory: %lu\n", GetLastError()); + if (is_wow64) + { + size = GetSystemWow64DirectoryA(syswow_dir, ARRAY_SIZE(syswow_dir)); + ok(size && size < ARRAY_SIZE(syswow_dir), "Couldn't get wow directory: %lu\n", GetLastError()); + } + test_info_size(); test_info(); test_32bit_win(); @@ -877,4 +985,5 @@ START_TEST(info) test_VerQueryValue_EmptyData(); test_extra_block(); test_GetFileVersionInfoEx(); + test_wow64_redirection(); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/msi/tests/install.c | 150 ++++++++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 43 deletions(-)
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 3bf28cc1e54..57ee48c2d7a 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -52,6 +52,8 @@ char PROG_FILES_DIR_NATIVE[MAX_PATH]; char COMMON_FILES_DIR[MAX_PATH]; char APP_DATA_DIR[MAX_PATH]; char WINDOWS_DIR[MAX_PATH]; +static char system_dir[MAX_PATH]; +static char syswow_dir[MAX_PATH];
static const char *customdll;
@@ -102,7 +104,7 @@ static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n" static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" "File\tFile\n" - "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n" + "five.txt\tFive\tfive.txt\t1000\t0.0.0.0\t\t16384\t5\n" "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n" "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n" "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n" @@ -1348,9 +1350,9 @@ static const CHAR x64_directory_dat[] = "CABOUTDIR\tMSITESTDIR\tcabout\n" "CHANGEDDIR\tMSITESTDIR\tchanged:second\n" "FIRSTDIR\tMSITESTDIR\tfirst\n" - "MSITESTDIR\tProgramFiles64Folder\tmsitest\n" + "MSITESTDIR\tSystem64Folder\tmsitest\n" "NEWDIR\tCABOUTDIR\tnew\n" - "ProgramFiles64Folder\tTARGETDIR\t.\n" + "System64Folder\tTARGETDIR\t.\n" "TARGETDIR\t\tSourceDir";
static const CHAR sr_install_exec_seq_dat[] = @@ -2388,6 +2390,16 @@ BOOL get_system_dirs(void) if(!GetWindowsDirectoryA(WINDOWS_DIR, MAX_PATH)) return FALSE;
+ size = GetSystemDirectoryA(system_dir, ARRAY_SIZE(system_dir)); + if (!size || size >= ARRAY_SIZE(system_dir)) + return FALSE; + if (is_wow64) + { + size = GetSystemWow64DirectoryA(syswow_dir, ARRAY_SIZE(syswow_dir)); + if (!size || size >= ARRAY_SIZE(syswow_dir)) + return FALSE; + } + return TRUE; }
@@ -2430,13 +2442,11 @@ static void create_test_files(void) DeleteFileA("five.txt"); }
-BOOL delete_pf(const CHAR *rel_path, BOOL is_file) +static BOOL delete_pf_dir(const char *rel_path, BOOL is_file, const char *basedir) { - CHAR path[MAX_PATH]; + char path[MAX_PATH];
- lstrcpyA(path, PROG_FILES_DIR); - lstrcatA(path, "\"); - lstrcatA(path, rel_path); + sprintf(path, "%s\%s", basedir, rel_path);
if (is_file) return DeleteFileA(path); @@ -2444,18 +2454,9 @@ BOOL delete_pf(const CHAR *rel_path, BOOL is_file) return RemoveDirectoryA(path); }
-static BOOL delete_pf_native(const CHAR *rel_path, BOOL is_file) +BOOL delete_pf(const CHAR *rel_path, BOOL is_file) { - CHAR path[MAX_PATH]; - - lstrcpyA(path, PROG_FILES_DIR_NATIVE); - lstrcatA(path, "\"); - lstrcatA(path, rel_path); - - if (is_file) - return DeleteFileA(path); - else - return RemoveDirectoryA(path); + return delete_pf_dir(rel_path, is_file, PROG_FILES_DIR); }
static BOOL delete_cf(const CHAR *rel_path, BOOL is_file) @@ -6215,7 +6216,12 @@ error:
static void test_wow64(void) { + WIN32_FILE_ATTRIBUTE_DATA attr; + char path[MAX_PATH]; + HMODULE module; + DWORD dll_size; void *cookie; + BOOL ret; UINT r;
if (!is_wow64) @@ -6230,7 +6236,59 @@ static void test_wow64(void) return; }
- create_test_files(); + sprintf(path, "%s\msitest", "C:\windows\syswow64"); + ret = CreateDirectoryA(path, NULL); + ok(ret, "got error %lu.\n", GetLastError()); + sprintf(path, "%s\msitest\cabout", "C:\windows\syswow64"); + ret = CreateDirectoryA(path, NULL); + ok(ret, "got error %lu.\n", GetLastError()); + sprintf(path, "%s\msitest\cabout\new", "C:\windows\syswow64"); + ret = CreateDirectoryA(path, NULL); + ok(ret, "got error %lu.\n", GetLastError()); + + sprintf(path, "%s\msitest\cabout\new\five.txt", "C:\windows\syswow64"); + ret = CopyFileA("C:\windows\system32\psapi.dll", path, FALSE); + ok(ret, "got error %lu.\n", GetLastError()); + + module = LoadLibraryA(path); + ok(!!module, "failed to load module.\n"); + + Wow64DisableWow64FsRedirection(&cookie); + + sprintf(path, "%s\msitest", "C:\windows\system32"); + ret = CreateDirectoryA(path, NULL); + ok(ret, "%s, got error %lu.\n", path, GetLastError()); + sprintf(path, "%s\msitest\cabout", "C:\windows\system32"); + ret = CreateDirectoryA(path, NULL); + ok(ret, "got error %lu.\n", GetLastError()); + sprintf(path, "%s\msitest\cabout\new", "C:\windows\system32"); + ret = CreateDirectoryA(path, NULL); + ok(ret, "got error %lu.\n", GetLastError()); + + sprintf(path, "%s\msitest\cabout\new\five.txt", "C:\windows\system32"); + create_file(path, 100); + + CreateDirectoryA("msitest", NULL); + + create_file("msitest\one.txt", 100); + CreateDirectoryA("msitest\first", NULL); + create_file("msitest\first\two.txt", 100); + CreateDirectoryA("msitest\second", NULL); + create_file("msitest\second\three.txt", 100); + + create_file("four.txt", 100); + ret = GetFileAttributesExA("C:\windows\system32\psapi.dll", GetFileExInfoStandard, &attr); + ok(ret, "got error %lu.\n", GetLastError()); + dll_size = attr.nFileSizeLow; + ret = CopyFileA("C:\windows\system32\psapi.dll", "five.txt", FALSE); + ok(ret, "got error %lu.\n", GetLastError()); + create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0"); + create_file("msitest\filename", 100); + + DeleteFileA("four.txt"); + DeleteFileA("five.txt"); + Wow64RevertWow64FsRedirection(cookie); + create_database_template(msifile, x64_tables, ARRAY_SIZE(x64_tables), 200, "x64;0"); r = MsiInstallProductA(msifile, NULL); if (r == ERROR_INSTALL_PACKAGE_REJECTED) @@ -6238,32 +6296,38 @@ static void test_wow64(void) skip("Not enough rights to perform tests\n"); goto error; } + FreeLibrary(module);
Wow64DisableWow64FsRedirection(&cookie);
- ok(!delete_pf("msitest\cabout\new\five.txt", TRUE), "File installed\n"); - ok(!delete_pf("msitest\cabout\new", FALSE), "Directory created\n"); - ok(!delete_pf("msitest\cabout\four.txt", TRUE), "File installed\n"); - ok(!delete_pf("msitest\cabout", FALSE), "Directory created\n"); - ok(!delete_pf("msitest\changed\three.txt", TRUE), "File installed\n"); - ok(!delete_pf("msitest\changed", FALSE), "Directory created\n"); - ok(!delete_pf("msitest\first\two.txt", TRUE), "File installed\n"); - ok(!delete_pf("msitest\first", FALSE), "Directory created\n"); - ok(!delete_pf("msitest\one.txt", TRUE), "File installed\n"); - ok(!delete_pf("msitest\filename", TRUE), "File installed\n"); - ok(!delete_pf("msitest", FALSE), "Directory created\n"); - - ok(delete_pf_native("msitest\cabout\new\five.txt", TRUE), "File not installed\n"); - ok(delete_pf_native("msitest\cabout\new", FALSE), "Directory not created\n"); - ok(delete_pf_native("msitest\cabout\four.txt", TRUE), "File not installed\n"); - ok(delete_pf_native("msitest\cabout", FALSE), "Directory not created\n"); - ok(delete_pf_native("msitest\changed\three.txt", TRUE), "File not installed\n"); - ok(delete_pf_native("msitest\changed", FALSE), "Directory not created\n"); - ok(delete_pf_native("msitest\first\two.txt", TRUE), "File not installed\n"); - ok(delete_pf_native("msitest\first", FALSE), "Directory not created\n"); - ok(delete_pf_native("msitest\one.txt", TRUE), "File not installed\n"); - ok(delete_pf_native("msitest\filename", TRUE), "File not installed\n"); - ok(delete_pf_native("msitest", FALSE), "Directory not created\n"); + ok(delete_pf_dir("msitest\cabout\new\five.txt", TRUE, syswow_dir), "File installed\n"); + ok(delete_pf_dir("msitest\cabout\new", FALSE, syswow_dir), "Directory created\n"); + ok(!delete_pf_dir("msitest\cabout\four.txt", TRUE, syswow_dir), "File installed\n"); + ok(delete_pf_dir("msitest\cabout", FALSE, syswow_dir), "Directory created\n"); + ok(!delete_pf_dir("msitest\changed\three.txt", TRUE, syswow_dir), "File installed\n"); + ok(!delete_pf_dir("msitest\changed", FALSE, syswow_dir), "Directory created\n"); + ok(!delete_pf_dir("msitest\first\two.txt", TRUE, syswow_dir), "File installed\n"); + ok(!delete_pf_dir("msitest\first", FALSE, syswow_dir), "Directory created\n"); + ok(!delete_pf_dir("msitest\one.txt", TRUE, syswow_dir), "File installed\n"); + ok(!delete_pf_dir("msitest\filename", TRUE, syswow_dir), "File installed\n"); + ok(delete_pf_dir("msitest", FALSE, syswow_dir), "Directory created\n"); + + sprintf(path, "%s\msitest\cabout\new\five.txt", system_dir); + ret = GetFileAttributesExA(path, GetFileExInfoStandard, &attr); + ok(ret, "got error %lu.\n", GetLastError()); + todo_wine ok(attr.nFileSizeLow == dll_size, "got %lu, expected %lu.\n", attr.nFileSizeLow, dll_size); + + ok(delete_pf_dir("msitest\cabout\new\five.txt", TRUE, system_dir), "File not installed\n"); + ok(delete_pf_dir("msitest\cabout\new", FALSE, system_dir), "Directory not created\n"); + ok(delete_pf_dir("msitest\cabout\four.txt", TRUE, system_dir), "File not installed\n"); + ok(delete_pf_dir("msitest\cabout", FALSE, system_dir), "Directory not created\n"); + ok(delete_pf_dir("msitest\changed\three.txt", TRUE, system_dir), "File not installed\n"); + ok(delete_pf_dir("msitest\changed", FALSE, system_dir), "Directory not created\n"); + ok(delete_pf_dir("msitest\first\two.txt", TRUE, system_dir), "File not installed\n"); + ok(delete_pf_dir("msitest\first", FALSE, system_dir), "Directory not created\n"); + ok(delete_pf_dir("msitest\one.txt", TRUE, system_dir), "File not installed\n"); + ok(delete_pf_dir("msitest\filename", TRUE, system_dir), "File not installed\n"); + ok(delete_pf_dir("msitest", FALSE, system_dir), "Directory not created\n");
Wow64RevertWow64FsRedirection(cookie);
From: Paul Gofman pgofman@codeweavers.com
--- dlls/msi/appsearch.c | 20 ++++---------------- dlls/msi/files.c | 24 ++++++++++++++---------- dlls/msi/msipriv.h | 2 +- 3 files changed, 19 insertions(+), 27 deletions(-)
diff --git a/dlls/msi/appsearch.c b/dlls/msi/appsearch.c index 88450087196..092a61560a4 100644 --- a/dlls/msi/appsearch.c +++ b/dlls/msi/appsearch.c @@ -178,18 +178,9 @@ static WCHAR *search_file( MSIPACKAGE *package, WCHAR *path, struct signature *s if (attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY)) return NULL;
- size = msi_get_file_version_info( package, path, 0, NULL ); - if (!size) + if (!(buffer = msi_get_file_version_info( package, path ))) return wcsdup(path);
- buffer = malloc(size); - if (!buffer) - return NULL; - - size = msi_get_file_version_info( package, path, size, buffer ); - if (!size) - goto done; - if (!VerQueryValueW(buffer, L"\", (LPVOID)&info, &size) || !info) goto done;
@@ -656,17 +647,14 @@ static UINT file_version_matches( MSIPACKAGE *package, const struct signature *s BOOL *matches ) { UINT len; - void *version; VS_FIXEDFILEINFO *info = NULL; - DWORD size = msi_get_file_version_info( package, filePath, 0, NULL ); + void *version;
*matches = FALSE;
- if (!size) return ERROR_SUCCESS; - if (!(version = malloc( size ))) return ERROR_OUTOFMEMORY; + if (!(version = msi_get_file_version_info( package, filePath ))) return ERROR_SUCCESS;
- if (msi_get_file_version_info( package, filePath, size, version )) - VerQueryValueW( version, L"\", (void **)&info, &len ); + VerQueryValueW( version, L"\", (void **)&info, &len );
if (info) { diff --git a/dlls/msi/files.c b/dlls/msi/files.c index 35166788dae..8dd2b67a792 100644 --- a/dlls/msi/files.c +++ b/dlls/msi/files.c @@ -157,27 +157,31 @@ static BOOL apply_filepatch( MSIPACKAGE *package, const WCHAR *patch, const WCHA return ret; }
-DWORD msi_get_file_version_info( MSIPACKAGE *package, const WCHAR *path, DWORD buflen, BYTE *buffer ) +BYTE *msi_get_file_version_info( MSIPACKAGE *package, const WCHAR *path ) { - DWORD size, handle; + DWORD size; + BYTE *buffer = NULL; + msi_disable_fs_redirection( package ); - if (buffer) size = GetFileVersionInfoW( path, 0, buflen, buffer ); - else size = GetFileVersionInfoSizeW( path, &handle ); + if (!(size = GetFileVersionInfoSizeW( path, NULL ))) goto done; + if (!(buffer = malloc( size ))) goto done; + if (!GetFileVersionInfoW( path, 0, size, buffer )) + { + free( buffer ); + buffer = NULL; + } +done: msi_revert_fs_redirection( package ); - return size; + return buffer; }
VS_FIXEDFILEINFO *msi_get_disk_file_version( MSIPACKAGE *package, const WCHAR *filename ) { VS_FIXEDFILEINFO *ptr, *ret; - DWORD version_size; UINT size; void *version;
- if (!(version_size = msi_get_file_version_info( package, filename, 0, NULL ))) return NULL; - if (!(version = malloc( version_size ))) return NULL; - - msi_get_file_version_info( package, filename, version_size, version ); + if (!(version = msi_get_file_version_info( package, filename ))) return NULL;
if (!VerQueryValueW( version, L"\", (void **)&ptr, &size )) { diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index e20ead557ce..aebfc85ab76 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -1114,7 +1114,7 @@ extern BOOL msi_set_file_attributes( MSIPACKAGE *, const WCHAR *, DWORD ); extern HANDLE msi_find_first_file( MSIPACKAGE *, const WCHAR *, WIN32_FIND_DATAW * ); extern BOOL msi_find_next_file( MSIPACKAGE *, HANDLE, WIN32_FIND_DATAW * ); extern BOOL msi_move_file( MSIPACKAGE *, const WCHAR *, const WCHAR *, DWORD ); -extern DWORD msi_get_file_version_info( MSIPACKAGE *, const WCHAR *, DWORD, BYTE * ); +extern BYTE *msi_get_file_version_info( MSIPACKAGE *, const WCHAR * ); extern BOOL msi_create_full_path( MSIPACKAGE *, const WCHAR * ); extern DWORD msi_get_disk_file_size( MSIPACKAGE *, const WCHAR * ); extern VS_FIXEDFILEINFO *msi_get_disk_file_version( MSIPACKAGE *, const WCHAR * );
From: Paul Gofman pgofman@codeweavers.com
--- dlls/msi/action.c | 3 +-- dlls/msi/assembly.c | 3 +-- dlls/msi/custom.c | 2 +- dlls/msi/msi_main.c | 3 +++ dlls/msi/msipriv.h | 2 ++ dlls/msi/package.c | 4 ++-- 6 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c index f9b43692ab3..f750b875d6b 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -5210,12 +5210,11 @@ static UINT ACTION_InstallFinalize(MSIPACKAGE *package)
UINT ACTION_ForceReboot(MSIPACKAGE *package) { - WCHAR buffer[256], sysdir[MAX_PATH], squashed_pc[SQUASHED_GUID_SIZE]; + WCHAR buffer[256], squashed_pc[SQUASHED_GUID_SIZE]; HKEY hkey;
squash_guid( package->ProductCode, squashed_pc );
- GetSystemDirectoryW(sysdir, ARRAY_SIZE(sysdir)); RegCreateKeyW(HKEY_LOCAL_MACHINE, L"Software\Microsoft\Windows\CurrentVersion\RunOnce", &hkey); swprintf(buffer, ARRAY_SIZE(buffer), L"%s\MsiExec.exe /@ "%s"", sysdir, squashed_pc);
diff --git a/dlls/msi/assembly.c b/dlls/msi/assembly.c index 47e8071502c..6613bf3bf96 100644 --- a/dlls/msi/assembly.c +++ b/dlls/msi/assembly.c @@ -34,9 +34,8 @@ static void load_fusion_dlls( MSIPACKAGE *package ) { HRESULT (WINAPI *pLoadLibraryShim)( const WCHAR *, const WCHAR *, void *, HMODULE * ); WCHAR path[MAX_PATH]; - DWORD len = GetSystemDirectoryW( path, MAX_PATH );
- lstrcpyW( path + len, L"\mscoree.dll" ); + lstrcpyW( path + sysdir_len, L"\mscoree.dll" ); if (!package->hmscoree && !(package->hmscoree = LoadLibraryW( path ))) return; if (!(pLoadLibraryShim = (void *)GetProcAddress( package->hmscoree, "LoadLibraryShim" ))) { diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c index 12a7c3c3676..54e1897a2c5 100644 --- a/dlls/msi/custom.c +++ b/dlls/msi/custom.c @@ -612,7 +612,7 @@ static DWORD custom_start_server(MSIPACKAGE *package, DWORD arch) if ((sizeof(void *) == 8 || is_wow64) && arch == SCS_32BIT_BINARY) GetSystemWow64DirectoryW(path, MAX_PATH - ARRAY_SIZE(L"\msiexec.exe")); else - GetSystemDirectoryW(path, MAX_PATH - ARRAY_SIZE(L"\msiexec.exe")); + wcscpy(path, sysdir); lstrcatW(path, L"\msiexec.exe"); swprintf(cmdline, ARRAY_SIZE(cmdline), L"%s -Embedding %d", path, GetCurrentProcessId());
diff --git a/dlls/msi/msi_main.c b/dlls/msi/msi_main.c index a2b6b6a0503..32b4f9ad45d 100644 --- a/dlls/msi/msi_main.c +++ b/dlls/msi/msi_main.c @@ -50,6 +50,8 @@ LPVOID gUIContextRecord = NULL; WCHAR *gszLogFile = NULL; HINSTANCE msi_hInstance;
+WCHAR sysdir[MAX_PATH]; +SIZE_T sysdir_len;
/* * Dll lifetime tracking declaration @@ -75,6 +77,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) msi_hInstance = hinstDLL; DisableThreadLibraryCalls(hinstDLL); IsWow64Process( GetCurrentProcess(), &is_wow64 ); + sysdir_len = GetSystemDirectoryW( sysdir, ARRAY_SIZE(sysdir) ); break; case DLL_PROCESS_DETACH: if (lpvReserved) break; diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index aebfc85ab76..bd8f6ec7a48 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -43,6 +43,8 @@
static const BOOL is_64bit = sizeof(void *) > sizeof(int); extern BOOL is_wow64; +extern WCHAR sysdir[MAX_PATH]; +extern SIZE_T sysdir_len;
#define MSI_DATASIZEMASK 0x00ff #define MSITYPE_VALID 0x0100 diff --git a/dlls/msi/package.c b/dlls/msi/package.c index b8966a0df90..969441f8827 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -777,7 +777,7 @@ static VOID set_installer_properties(MSIPACKAGE *package) msi_set_property( package->db, L"Intel", bufstr, len ); if (sys_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) { - GetSystemDirectoryW( pth, MAX_PATH ); + wcscpy( pth, sysdir ); PathAddBackslashW( pth ); msi_set_property( package->db, L"SystemFolder", pth, -1 );
@@ -798,7 +798,7 @@ static VOID set_installer_properties(MSIPACKAGE *package) msi_set_property( package->db, L"Msix64", bufstr, -1 ); msi_set_property( package->db, L"VersionNT64", verstr, -1 );
- GetSystemDirectoryW( pth, MAX_PATH ); + wcscpy( pth, sysdir ); PathAddBackslashW( pth ); msi_set_property( package->db, L"System64Folder", pth, -1 );
From: Paul Gofman pgofman@codeweavers.com
--- dlls/msi/files.c | 9 +++++++++ dlls/msi/tests/install.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/msi/files.c b/dlls/msi/files.c index 8dd2b67a792..218851646cf 100644 --- a/dlls/msi/files.c +++ b/dlls/msi/files.c @@ -159,10 +159,19 @@ static BOOL apply_filepatch( MSIPACKAGE *package, const WCHAR *patch, const WCHA
BYTE *msi_get_file_version_info( MSIPACKAGE *package, const WCHAR *path ) { + WCHAR temppath[MAX_PATH]; DWORD size; BYTE *buffer = NULL;
msi_disable_fs_redirection( package ); + if (is_wow64 && is_platform_64bit( package->platform ) && !wcsnicmp( path, sysdir, sysdir_len )) + { + SIZE_T len = sysdir_len; + + while (len && sysdir[len] != '\') --len; + swprintf( temppath, ARRAY_SIZE(temppath), L"%.*s\sysnative%s", len, sysdir, path + sysdir_len ); + path = temppath; + } if (!(size = GetFileVersionInfoSizeW( path, NULL ))) goto done; if (!(buffer = malloc( size ))) goto done; if (!GetFileVersionInfoW( path, 0, size, buffer )) diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 57ee48c2d7a..4b967d1aa4b 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -6315,7 +6315,7 @@ static void test_wow64(void) sprintf(path, "%s\msitest\cabout\new\five.txt", system_dir); ret = GetFileAttributesExA(path, GetFileExInfoStandard, &attr); ok(ret, "got error %lu.\n", GetLastError()); - todo_wine ok(attr.nFileSizeLow == dll_size, "got %lu, expected %lu.\n", attr.nFileSizeLow, dll_size); + ok(attr.nFileSizeLow == dll_size, "got %lu, expected %lu.\n", attr.nFileSizeLow, dll_size);
ok(delete_pf_dir("msitest\cabout\new\five.txt", TRUE, system_dir), "File not installed\n"); ok(delete_pf_dir("msitest\cabout\new", FALSE, system_dir), "Directory not created\n");
On Wed Jun 11 17:01:35 2025 +0000, Hans Leidekker wrote:
You're right that disabling redirection works around missing installer service and it would be nice to solve this some day. We also have msi property bugs related to this architecture difference. Copying the file as a workaround isn't very pretty IMO and I think a local copy of version info parsing is a cleaner workaround.
I think I found a better way, substituting 'c:\windows\sysnative' in place of "c:\windows\system32". This is a sure way to bypass system32 redirection which works through out the loader and GetFileVersionInfo. Copying the code from kernelbase looks rather unfortunate, it is some amount of not entirely trivial code with its own FIXMEs. Then, that probably obviates the need in "msi: Allocate buffer in msi_get_file_version_info()." but it seems to me it is mildly better this way so I kept the patch.
v2: - replace system32 with sysnative instead of copying file.