Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/setupapi/misc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/setupapi/misc.c b/dlls/setupapi/misc.c index 3b5d62b682c..3b0c9477747 100644 --- a/dlls/setupapi/misc.c +++ b/dlls/setupapi/misc.c @@ -933,6 +933,8 @@ static BOOL find_existing_inf(const WCHAR *source, WCHAR *target) if (dest_file == INVALID_HANDLE_VALUE) continue;
+ SetFilePointer( source_file, 0, NULL, FILE_BEGIN ); + if (GetFileSizeEx( dest_file, &dest_file_size ) && dest_file_size.QuadPart == source_file_size.QuadPart && !compare_files( source_file, dest_file ))
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- I've added todo_wine to the tests rather than try to fix SetupUninstallOEMInf(), since fixing that function would require a nontrivial amount of work, whereas the now failing tests seem unlikely to cause any more problems in real applications.
dlls/setupapi/Makefile.in | 2 +- dlls/setupapi/misc.c | 17 ++++++++++++++++- dlls/setupapi/setupapi_private.h | 2 ++ dlls/setupapi/tests/misc.c | 4 ++-- 4 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/dlls/setupapi/Makefile.in b/dlls/setupapi/Makefile.in index 6c31365546f..539bfed0caa 100644 --- a/dlls/setupapi/Makefile.in +++ b/dlls/setupapi/Makefile.in @@ -1,7 +1,7 @@ EXTRADEFS = -D_SETUPAPI_ MODULE = setupapi.dll IMPORTLIB = setupapi -IMPORTS = uuid version advapi32 rpcrt4 +IMPORTS = uuid version advapi32 rpcrt4 kernelbase DELAYIMPORTS = shell32 wintrust ole32 winspool.drv comdlg32 user32
EXTRADLLFLAGS = -mno-cygwin diff --git a/dlls/setupapi/misc.c b/dlls/setupapi/misc.c index 3b0c9477747..26e5359804c 100644 --- a/dlls/setupapi/misc.c +++ b/dlls/setupapi/misc.c @@ -31,6 +31,7 @@ #include "softpub.h" #include "mscat.h" #include "shlobj.h" +#include "shlwapi.h"
#include "wine/debug.h"
@@ -962,10 +963,11 @@ BOOL WINAPI SetupCopyOEMInfW( PCWSTR source, PCWSTR location, DWORD buffer_size, DWORD *required_size, WCHAR **filepart ) { BOOL ret = FALSE; - WCHAR target[MAX_PATH], catalog_file[MAX_PATH], *p; + WCHAR target[MAX_PATH], catalog_file[MAX_PATH], pnf_path[MAX_PATH], *p; static const WCHAR inf[] = { '\','i','n','f','\',0 }; static const WCHAR wszVersion[] = { 'V','e','r','s','i','o','n',0 }; static const WCHAR wszCatalogFile[] = { 'C','a','t','a','l','o','g','F','i','l','e',0 }; + FILE *pnf_file; unsigned int i; DWORD size; HINF hinf; @@ -1069,6 +1071,19 @@ done: if (style & SP_COPY_DELETESOURCE) DeleteFileW( source );
+ if (ret) + { + wcscpy(pnf_path, target); + PathRemoveExtensionW(pnf_path); + PathAddExtensionW(pnf_path, L".pnf"); + if ((pnf_file = _wfopen(pnf_path, L"w"))) + { + fputws(PNF_HEADER, pnf_file); + fputws(source, pnf_file); + fclose(pnf_file); + } + } + size = lstrlenW( target ) + 1; if (dest) { diff --git a/dlls/setupapi/setupapi_private.h b/dlls/setupapi/setupapi_private.h index f4685ab2b4c..21ac50e0f3c 100644 --- a/dlls/setupapi/setupapi_private.h +++ b/dlls/setupapi/setupapi_private.h @@ -43,6 +43,8 @@ #define REGPART_RENAME "\Rename" #define REG_VERSIONCONFLICT "Software\Microsoft\VersionConflictManager"
+#define PNF_HEADER L"Wine PNF header\n" + extern HINSTANCE SETUPAPI_hInstance DECLSPEC_HIDDEN;
static inline void * __WINE_ALLOC_SIZE(2) heap_realloc_zero(void *mem, size_t len) diff --git a/dlls/setupapi/tests/misc.c b/dlls/setupapi/tests/misc.c index 3bb308ef4a7..f16f310b3f7 100644 --- a/dlls/setupapi/tests/misc.c +++ b/dlls/setupapi/tests/misc.c @@ -320,7 +320,7 @@ static void test_SetupCopyOEMInf(void) DeleteFileA(dest); strcpy(pnf, dest); *(strrchr(pnf, '.') + 1) = 'p'; - ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf); + todo_wine ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf);
res = SetupUninstallOEMInfA(strrchr(orig_dest, '\') + 1, 0, NULL); ok(res, "Failed to uninstall '%s', error %u.\n", orig_dest, GetLastError()); @@ -328,7 +328,7 @@ static void test_SetupCopyOEMInf(void) DeleteFileA(orig_dest); strcpy(pnf, dest); *(strrchr(pnf, '.') + 1) = 'p'; - ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf); + todo_wine ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf);
GetWindowsDirectoryA(orig_dest, sizeof(orig_dest)); strcat(orig_dest, "\inf\");
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35903 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/setupapi/install.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/dlls/setupapi/install.c b/dlls/setupapi/install.c index 730beba7217..56a9d4f36c3 100644 --- a/dlls/setupapi/install.c +++ b/dlls/setupapi/install.c @@ -32,6 +32,7 @@ #include "winnls.h" #include "winsvc.h" #include "shlobj.h" +#include "shlwapi.h" #include "objidl.h" #include "objbase.h" #include "setupapi.h" @@ -112,6 +113,29 @@ static WCHAR *dup_section_line_field( HINF hinf, const WCHAR *section, const WCH return buffer; }
+static void get_inf_src_path( HINF hinf, WCHAR *path ) +{ + const WCHAR *inf_path = PARSER_get_inf_filename( hinf ); + WCHAR pnf_path[MAX_PATH]; + FILE *pnf; + + wcscpy( pnf_path, inf_path ); + PathRemoveExtensionW( pnf_path ); + PathAddExtensionW( pnf_path, L".pnf" ); + if ((pnf = _wfopen( pnf_path, L"r" ))) + { + if (fgetws( path, MAX_PATH, pnf ) && !wcscmp( path, PNF_HEADER )) + { + fgetws( path, MAX_PATH, pnf ); + TRACE("using original source path %s\n", debugstr_w(path)); + fclose( pnf ); + return; + } + fclose( pnf ); + } + wcscpy( path, inf_path ); +} + /*********************************************************************** * copy_files_callback * @@ -141,7 +165,7 @@ static BOOL copy_files_callback( HINF hinf, PCWSTR field, void *arg ) } else { - lstrcpyW( src_root, PARSER_get_inf_filename( hinf ) ); + get_inf_src_path( hinf, src_root ); if ((p = wcsrchr( src_root, '\' ))) *p = 0; } }
--- This test only successfully passes on Windows XP, and generates dialogs elsewhere, so I'm attaching it essentially just as a proof of concept.
dlls/setupapi/tests/install.c | 70 +++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+)
diff --git a/dlls/setupapi/tests/install.c b/dlls/setupapi/tests/install.c index c085b724b59..03bf2411c36 100644 --- a/dlls/setupapi/tests/install.c +++ b/dlls/setupapi/tests/install.c @@ -2129,6 +2129,75 @@ static void test_register_dlls(void) ok(ret, "Failed to delete test DLL, error %u.\n", GetLastError()); }
+static void test_oem_source_path(void) +{ + static const char inf_data[] = "[Version]\n" + "Signature="$Chicago$"\n" + "[DefaultInstall]\n" + "CopyFiles=files_section\n" + "[files_section]\n" + "one.txt\n" + "[SourceDisksNames]\n" + "1=heis\n" + "[SourceDisksFiles]\n" + "one.txt=1\n" + "[DestinationDirs]\n" + "files_section=40000,dst\n"; + + void *context = SetupInitDefaultQueueCallbackEx(NULL, INVALID_HANDLE_VALUE, 0, 0, 0); + char path[MAX_PATH + 9], oem_path[MAX_PATH]; + HSPFILEQ queue; + HINF hinf; + BOOL ret; + + ret = CreateDirectoryA("src", NULL); + ok(ret, "Failed to create test directory, error %u.\n", GetLastError()); + create_inf_file("src/test.inf", inf_data); + create_file("src/one.txt"); + + sprintf(path, "%s\src\test.inf", CURR_DIR); + ret = SetupCopyOEMInfA(path, NULL, SPOST_PATH, 0, oem_path, sizeof(oem_path), NULL, NULL); + if (!ret && (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_WRONG_INF_TYPE + || GetLastError() == ERROR_UNSUPPORTED_TYPE /* Win7 */)) + { + skip("Failed to install INF, error %u.\n", GetLastError()); + delete_file("src/one.txt"); + delete_file("src/test.inf"); + delete_file("src/"); + return; + } + ok(ret, "Failed to install INF, error %u.\n", GetLastError()); + + hinf = SetupOpenInfFileA(oem_path, NULL, INF_STYLE_WIN4, NULL); + ok(hinf != INVALID_HANDLE_VALUE, "Failed to open INF file, error %#x.\n", GetLastError()); + + ret = SetupSetDirectoryIdA(hinf, 40000, CURR_DIR); + ok(ret, "Failed to set directory ID, error %u.\n", GetLastError()); + + queue = SetupOpenFileQueue(); + ok(queue != INVALID_HANDLE_VALUE, "Failed to open queue, error %#x.\n", GetLastError()); + + ret = SetupInstallFilesFromInfSectionA(hinf, NULL, queue, "DefaultInstall", NULL, 0); + ok(ret, "Failed to install files, error %#x.\n", GetLastError()); + + ret = SetupCommitFileQueueA(NULL, queue, SetupDefaultQueueCallbackA, context); + ok(ret, "Failed to commit queue, error %#x.\n", GetLastError()); + + ok(delete_file("dst/one.txt"), "Destination file should exist.\n"); + + SetupTermDefaultQueueCallback(context); + ret = SetupCloseFileQueue(queue); + ok(ret, "Failed to close queue, error %#x.\n", GetLastError()); + + ret = SetupUninstallOEMInfA(strrchr(oem_path, '\') + 1, 0, NULL); + ok(ret, "Failed to uninstall INF, error %u.\n", GetLastError()); + SetupCloseInfFile(hinf); + delete_file("dst/"); + delete_file("src/one.txt"); + delete_file("src/test.inf"); + delete_file("src/"); +} + START_TEST(install) { char temp_path[MAX_PATH], prev_path[MAX_PATH]; @@ -2159,6 +2228,7 @@ START_TEST(install) test_install_file(); test_start_copy(); test_register_dlls(); + test_oem_source_path();
UnhookWindowsHookEx(hhook);