From e04949b586d7087f0a94a50918dca56d6f90996a Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 24 Jan 2024 13:13:56 +1100 Subject: [PATCH] Added scrrun_move_folder patchset --- .../0001-scrrun-Implement-MoveFolder.patch | 74 ++++++++++ ...-null-and-empty-arguments-in-MoveFol.patch | 61 ++++++++ ...Folder-with-already-existing-destina.patch | 35 +++++ ...or-non-existant-source-in-MoveFolder.patch | 66 +++++++++ ...at-source-is-directory-in-MoveFolder.patch | 79 +++++++++++ ...ce-dir-into-destination-dir-if-desti.patch | 111 +++++++++++++++ ...rrun-Support-wildcards-in-MoveFolder.patch | 131 ++++++++++++++++++ ...-Move-directories-only-in-MoveFolder.patch | 81 +++++++++++ ...th-not-found-error-if-source-ends-wi.patch | 57 ++++++++ ...th-not-found-error-if-no-folders-wer.patch | 79 +++++++++++ patches/scrrun_move_folder/definition | 5 + 11 files changed, 779 insertions(+) create mode 100644 patches/scrrun_move_folder/0001-scrrun-Implement-MoveFolder.patch create mode 100644 patches/scrrun_move_folder/0002-scrrun-Check-for-null-and-empty-arguments-in-MoveFol.patch create mode 100644 patches/scrrun_move_folder/0003-scrrun-Test-MoveFolder-with-already-existing-destina.patch create mode 100644 patches/scrrun_move_folder/0004-scrrun-Check-for-non-existant-source-in-MoveFolder.patch create mode 100644 patches/scrrun_move_folder/0005-scrrun-Check-that-source-is-directory-in-MoveFolder.patch create mode 100644 patches/scrrun_move_folder/0006-scrrun-Move-source-dir-into-destination-dir-if-desti.patch create mode 100644 patches/scrrun_move_folder/0007-scrrun-Support-wildcards-in-MoveFolder.patch create mode 100644 patches/scrrun_move_folder/0008-scrrun-Move-directories-only-in-MoveFolder.patch create mode 100644 patches/scrrun_move_folder/0009-scrrun-return-path-not-found-error-if-source-ends-wi.patch create mode 100644 patches/scrrun_move_folder/0010-scrrun-Return-path-not-found-error-if-no-folders-wer.patch create mode 100644 patches/scrrun_move_folder/definition diff --git a/patches/scrrun_move_folder/0001-scrrun-Implement-MoveFolder.patch b/patches/scrrun_move_folder/0001-scrrun-Implement-MoveFolder.patch new file mode 100644 index 00000000..f09bb8d9 --- /dev/null +++ b/patches/scrrun_move_folder/0001-scrrun-Implement-MoveFolder.patch @@ -0,0 +1,74 @@ +From 291a45af5ab416fc896f1343453c7e3a24f188d8 Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Wed, 29 Jun 2022 16:05:48 +0200 +Subject: [PATCH] scrrun: Implement MoveFolder(). + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52128 + +Signed-off-by: Robert Wilhelm +--- + dlls/scrrun/filesystem.c | 7 +++---- + dlls/scrrun/tests/filesystem.c | 20 ++++++++++++++++++++ + 2 files changed, 23 insertions(+), 4 deletions(-) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index e53355267db..ab02d4680cd 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3803,12 +3803,11 @@ static HRESULT WINAPI filesys_MoveFile(IFileSystem3 *iface, BSTR source, BSTR de + return MoveFileW(source, destination) ? S_OK : create_error(GetLastError()); + } + +-static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface,BSTR Source, +- BSTR Destination) ++static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR destination) + { +- FIXME("%p %s %s\n", iface, debugstr_w(Source), debugstr_w(Destination)); ++ TRACE("%p %s %s\n", iface, debugstr_w(source), debugstr_w(destination)); + +- return E_NOTIMPL; ++ return MoveFileW(source, destination) ? S_OK : create_error(GetLastError()); + } + + static inline HRESULT copy_file(const WCHAR *source, DWORD source_len, +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index e53bd092ce9..7a5de4407a8 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2639,6 +2639,25 @@ static void test_MoveFile(void) + SysFreeString(str); + } + ++static void test_MoveFolder(void) ++{ ++ BSTR src, dst; ++ WCHAR buffW1[MAX_PATH],buffW2[MAX_PATH]; ++ HRESULT hr; ++ ++ get_temp_path(L"foo", buffW1); ++ get_temp_path(L"bar", buffW2); ++ ++ ok(CreateDirectoryW(buffW1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW1)); ++ src = SysAllocString(buffW1); ++ dst = SysAllocString(buffW2); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); ++ ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); ++} ++ + static void test_DoOpenPipeStream(void) + { + static const char testdata[] = "test"; +@@ -2772,6 +2791,7 @@ START_TEST(filesystem) + test_GetExtensionName(); + test_GetSpecialFolder(); + test_MoveFile(); ++ test_MoveFolder(); + test_DoOpenPipeStream(); + + IFileSystem3_Release(fs3); +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0002-scrrun-Check-for-null-and-empty-arguments-in-MoveFol.patch b/patches/scrrun_move_folder/0002-scrrun-Check-for-null-and-empty-arguments-in-MoveFol.patch new file mode 100644 index 00000000..d8a49c0d --- /dev/null +++ b/patches/scrrun_move_folder/0002-scrrun-Check-for-null-and-empty-arguments-in-MoveFol.patch @@ -0,0 +1,61 @@ +From 0e42b8f30afc0984703f09258e1fbc6224c207fa Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Wed, 29 Jun 2022 16:11:56 +0200 +Subject: [PATCH] scrrun: Check for null and empty arguments in MoveFolder. + +Signed-off-by: Robert Wilhelm +--- + dlls/scrrun/filesystem.c | 3 +++ + dlls/scrrun/tests/filesystem.c | 15 ++++++++++++++- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index ab02d4680cd..a56af2f0461 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3807,6 +3807,9 @@ static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR + { + TRACE("%p %s %s\n", iface, debugstr_w(source), debugstr_w(destination)); + ++ if(!source || !source[0] || !destination || !destination[0]) ++ return E_INVALIDARG; ++ + return MoveFileW(source, destination) ? S_OK : create_error(GetLastError()); + } + +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index 7a5de4407a8..3ddd782a6fe 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2641,7 +2641,7 @@ static void test_MoveFile(void) + + static void test_MoveFolder(void) + { +- BSTR src, dst; ++ BSTR src, dst, str, empty; + WCHAR buffW1[MAX_PATH],buffW2[MAX_PATH]; + HRESULT hr; + +@@ -2656,6 +2656,19 @@ static void test_MoveFolder(void) + SysFreeString(src); + SysFreeString(dst); + ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); ++ ++ str = SysAllocString(L"null.dir"); ++ empty = SysAllocString(L""); ++ hr = IFileSystem3_MoveFolder(fs3, str, NULL); ++ ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ++ hr = IFileSystem3_MoveFolder(fs3, NULL, str); ++ ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ++ hr = IFileSystem3_MoveFolder(fs3, str, empty); ++ ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ++ hr = IFileSystem3_MoveFolder(fs3, empty, str); ++ ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(str); ++ SysFreeString(empty); + } + + static void test_DoOpenPipeStream(void) +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0003-scrrun-Test-MoveFolder-with-already-existing-destina.patch b/patches/scrrun_move_folder/0003-scrrun-Test-MoveFolder-with-already-existing-destina.patch new file mode 100644 index 00000000..e6c7d2d2 --- /dev/null +++ b/patches/scrrun_move_folder/0003-scrrun-Test-MoveFolder-with-already-existing-destina.patch @@ -0,0 +1,35 @@ +From 8aadb303edcc5b1fc951bbdef62269a1d42ad7aa Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Wed, 29 Jun 2022 16:15:47 +0200 +Subject: [PATCH] scrrun: Test MoveFolder with already existing destination. + +Signed-off-by: Robert Wilhelm +--- + dlls/scrrun/tests/filesystem.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index 3ddd782a6fe..4305ac394e6 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2669,6 +2669,17 @@ static void test_MoveFolder(void) + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + SysFreeString(str); + SysFreeString(empty); ++ ++ ok(CreateDirectoryW(buffW1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW1)); ++ ok(CreateDirectoryW(buffW2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW2)); ++ src = SysAllocString(buffW1); ++ dst = SysAllocString(buffW2); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); /* dst already exists */ ++ ok(hr == CTL_E_FILEALREADYEXISTS, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); ++ ok(RemoveDirectoryW(buffW1), "can't remove %s directory\n", wine_dbgstr_w(buffW1)); ++ ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); + } + + static void test_DoOpenPipeStream(void) +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0004-scrrun-Check-for-non-existant-source-in-MoveFolder.patch b/patches/scrrun_move_folder/0004-scrrun-Check-for-non-existant-source-in-MoveFolder.patch new file mode 100644 index 00000000..46c9242e --- /dev/null +++ b/patches/scrrun_move_folder/0004-scrrun-Check-for-non-existant-source-in-MoveFolder.patch @@ -0,0 +1,66 @@ +From bbf3d65137f48e763a8a7e4c1eee1dcaed657fd9 Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Wed, 29 Jun 2022 16:24:40 +0200 +Subject: [PATCH] scrrun: Check for non-existant source in MoveFolder(). + +Signed-off-by: Robert Wilhelm +--- + dlls/scrrun/filesystem.c | 16 +++++++++++++++- + dlls/scrrun/tests/filesystem.c | 7 +++++++ + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index a56af2f0461..5c4b13d48b8 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3803,6 +3803,20 @@ static HRESULT WINAPI filesys_MoveFile(IFileSystem3 *iface, BSTR source, BSTR de + return MoveFileW(source, destination) ? S_OK : create_error(GetLastError()); + } + ++static inline HRESULT create_movefolder_error(DWORD err) ++{ ++ switch(err) { ++ case ERROR_FILE_NOT_FOUND: ++ case ERROR_PATH_NOT_FOUND: return CTL_E_PATHNOTFOUND; ++ case ERROR_ACCESS_DENIED: return CTL_E_PERMISSIONDENIED; ++ case ERROR_FILE_EXISTS: return CTL_E_FILEALREADYEXISTS; ++ case ERROR_ALREADY_EXISTS: return CTL_E_FILEALREADYEXISTS; ++ default: ++ FIXME("Unsupported error code: %ld\n", err); ++ return E_FAIL; ++ } ++} ++ + static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR destination) + { + TRACE("%p %s %s\n", iface, debugstr_w(source), debugstr_w(destination)); +@@ -3810,7 +3824,7 @@ static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR + if(!source || !source[0] || !destination || !destination[0]) + return E_INVALIDARG; + +- return MoveFileW(source, destination) ? S_OK : create_error(GetLastError()); ++ return MoveFileW(source, destination) ? S_OK : create_movefolder_error(GetLastError()); + } + + static inline HRESULT copy_file(const WCHAR *source, DWORD source_len, +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index 4305ac394e6..9b352797073 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2680,6 +2680,13 @@ static void test_MoveFolder(void) + SysFreeString(dst); + ok(RemoveDirectoryW(buffW1), "can't remove %s directory\n", wine_dbgstr_w(buffW1)); + ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); ++ ++ src = SysAllocString(buffW1); ++ dst = SysAllocString(buffW2); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); /* src nonexistant */ ++ ok(hr == CTL_E_PATHNOTFOUND, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); + } + + static void test_DoOpenPipeStream(void) +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0005-scrrun-Check-that-source-is-directory-in-MoveFolder.patch b/patches/scrrun_move_folder/0005-scrrun-Check-that-source-is-directory-in-MoveFolder.patch new file mode 100644 index 00000000..6e6b23c2 --- /dev/null +++ b/patches/scrrun_move_folder/0005-scrrun-Check-that-source-is-directory-in-MoveFolder.patch @@ -0,0 +1,79 @@ +From e7ce13576f0ef1b73622a32568fce45eda879613 Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Wed, 29 Jun 2022 16:29:55 +0200 +Subject: [PATCH] scrrun: Check that source is directory in MoveFolder(). + +Signed-off-by: Robert Wilhelm +--- + dlls/scrrun/filesystem.c | 10 +++++++++- + dlls/scrrun/tests/filesystem.c | 14 ++++++++++++++ + 2 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index 5c4b13d48b8..72a15aae545 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3806,6 +3806,7 @@ static HRESULT WINAPI filesys_MoveFile(IFileSystem3 *iface, BSTR source, BSTR de + static inline HRESULT create_movefolder_error(DWORD err) + { + switch(err) { ++ case ERROR_INVALID_NAME: + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: return CTL_E_PATHNOTFOUND; + case ERROR_ACCESS_DENIED: return CTL_E_PERMISSIONDENIED; +@@ -3819,12 +3820,19 @@ static inline HRESULT create_movefolder_error(DWORD err) + + static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR destination) + { ++ int len; ++ WCHAR src_path[MAX_PATH]; ++ + TRACE("%p %s %s\n", iface, debugstr_w(source), debugstr_w(destination)); + + if(!source || !source[0] || !destination || !destination[0]) + return E_INVALIDARG; + +- return MoveFileW(source, destination) ? S_OK : create_movefolder_error(GetLastError()); ++ len = SysStringLen(source); ++ lstrcpyW(src_path, source); ++ if (source[len-1] != '\\' && source[len-1] != '/') wcscat(src_path, L"\\"); ++ ++ return MoveFileW(src_path, destination) ? S_OK : create_movefolder_error(GetLastError()); + } + + static inline HRESULT copy_file(const WCHAR *source, DWORD source_len, +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index 9b352797073..0236a02aa74 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2644,6 +2644,7 @@ static void test_MoveFolder(void) + BSTR src, dst, str, empty; + WCHAR buffW1[MAX_PATH],buffW2[MAX_PATH]; + HRESULT hr; ++ HANDLE file; + + get_temp_path(L"foo", buffW1); + get_temp_path(L"bar", buffW2); +@@ -2687,6 +2688,19 @@ static void test_MoveFolder(void) + ok(hr == CTL_E_PATHNOTFOUND, "Unexpected hr %#lx.\n", hr); + SysFreeString(src); + SysFreeString(dst); ++ ++ file = CreateFileW(buffW1, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, ++ FILE_ATTRIBUTE_NORMAL, NULL); ++ ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n"); ++ CloseHandle(file); ++ ++ src = SysAllocString(buffW1); ++ dst = SysAllocString(buffW2); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); /* src is regular file */ ++ ok(hr == CTL_E_PATHNOTFOUND, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); ++ DeleteFileW(buffW1); + } + + static void test_DoOpenPipeStream(void) +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0006-scrrun-Move-source-dir-into-destination-dir-if-desti.patch b/patches/scrrun_move_folder/0006-scrrun-Move-source-dir-into-destination-dir-if-desti.patch new file mode 100644 index 00000000..50dd7154 --- /dev/null +++ b/patches/scrrun_move_folder/0006-scrrun-Move-source-dir-into-destination-dir-if-desti.patch @@ -0,0 +1,111 @@ +From 30c175a9e90bc7889f97ad54ae82a34a832650dc Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Wed, 29 Jun 2022 17:21:10 +0200 +Subject: [PATCH] scrrun: Move source dir into destination dir if destination + ends with separator in MoveFolder(). + +Signed-off-by: Robert Wilhelm +--- + dlls/scrrun/filesystem.c | 22 +++++++++++++++----- + dlls/scrrun/tests/filesystem.c | 38 +++++++++++++++++++++++++++++++++- + 2 files changed, 54 insertions(+), 6 deletions(-) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index 72a15aae545..2c364ec6e08 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3820,18 +3820,30 @@ static inline HRESULT create_movefolder_error(DWORD err) + + static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR destination) + { +- int len; +- WCHAR src_path[MAX_PATH]; ++ int src_len, dst_len; ++ WCHAR src_path[MAX_PATH], dst_path[MAX_PATH]; ++ WCHAR *filename; + + TRACE("%p %s %s\n", iface, debugstr_w(source), debugstr_w(destination)); + + if(!source || !source[0] || !destination || !destination[0]) + return E_INVALIDARG; + +- len = SysStringLen(source); +- lstrcpyW(src_path, source); +- if (source[len-1] != '\\' && source[len-1] != '/') wcscat(src_path, L"\\"); ++ if (!GetFullPathNameW(source, MAX_PATH, src_path, &filename)) ++ return E_FAIL; + ++ src_len = SysStringLen(src_path); ++ if (src_path[src_len-1] != '\\' && src_path[src_len-1] != '/') ++ wcscat(src_path, L"\\"); ++ ++ dst_len = lstrlenW(destination); ++ if (destination[dst_len-1] == '\\' || destination[dst_len-1] == '/') { ++ lstrcpyW(dst_path, destination); ++ lstrcatW(dst_path, filename); ++ TRACE("move %s to %s\n", debugstr_w(src_path), debugstr_w(dst_path)); ++ return MoveFileW(src_path, dst_path) ? S_OK : create_movefolder_error(GetLastError()); ++ } ++ TRACE("move %s to %s\n", debugstr_w(src_path), debugstr_w(destination)); + return MoveFileW(src_path, destination) ? S_OK : create_movefolder_error(GetLastError()); + } + +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index 0236a02aa74..d237e21e9a6 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2642,7 +2642,7 @@ static void test_MoveFile(void) + static void test_MoveFolder(void) + { + BSTR src, dst, str, empty; +- WCHAR buffW1[MAX_PATH],buffW2[MAX_PATH]; ++ WCHAR buffW1[MAX_PATH],buffW2[MAX_PATH],pathW[MAX_PATH]; + HRESULT hr; + HANDLE file; + +@@ -2701,6 +2701,42 @@ static void test_MoveFolder(void) + SysFreeString(src); + SysFreeString(dst); + DeleteFileW(buffW1); ++ ++ GetTempPathW(MAX_PATH, buffW1); ++ lstrcatW(buffW1,L"foo"); ++ GetTempPathW(MAX_PATH, buffW2); ++ lstrcatW(buffW2,L"bar"); ++ ok(CreateDirectoryW(buffW1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW1)); ++ ok(CreateDirectoryW(buffW2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW2)); ++ lstrcpyW(pathW,buffW2); ++ lstrcatW(pathW,L"\\"); ++ src = SysAllocString(buffW1); ++ dst = SysAllocString(pathW); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); ++ lstrcatW(pathW,L"foo"); ++ ok(RemoveDirectoryW(pathW), "can't remove %s directory\n", wine_dbgstr_w(pathW)); ++ ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); ++ ++ GetTempPathW(MAX_PATH, buffW1); ++ lstrcatW(buffW1,L"foo"); ++ GetTempPathW(MAX_PATH, buffW2); ++ lstrcatW(buffW2,L"bar"); ++ ok(CreateDirectoryW(buffW1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW1)); ++ ok(CreateDirectoryW(buffW2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW2)); ++ lstrcpyW(pathW,buffW2); ++ lstrcatW(pathW,L"/"); ++ src = SysAllocString(buffW1); ++ dst = SysAllocString(pathW); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); ++ lstrcatW(pathW,L"foo"); ++ ok(RemoveDirectoryW(pathW), "can't remove %s directory\n", wine_dbgstr_w(pathW)); ++ ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); + } + + static void test_DoOpenPipeStream(void) +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0007-scrrun-Support-wildcards-in-MoveFolder.patch b/patches/scrrun_move_folder/0007-scrrun-Support-wildcards-in-MoveFolder.patch new file mode 100644 index 00000000..53ce3243 --- /dev/null +++ b/patches/scrrun_move_folder/0007-scrrun-Support-wildcards-in-MoveFolder.patch @@ -0,0 +1,131 @@ +From 870d98b28ca3ff52c21feedfb3b1e5f3d6ade7b9 Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Wed, 29 Jun 2022 17:40:58 +0200 +Subject: [PATCH] scrrun: Support wildcards in MoveFolder(). + +Signed-off-by: Robert Wilhelm +--- + dlls/scrrun/filesystem.c | 49 ++++++++++++++++++++++++++-------- + dlls/scrrun/tests/filesystem.c | 27 ++++++++++++++++++- + 2 files changed, 64 insertions(+), 12 deletions(-) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index 2c364ec6e08..749a06739c7 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3820,9 +3820,12 @@ static inline HRESULT create_movefolder_error(DWORD err) + + static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR destination) + { +- int src_len, dst_len; ++ int src_len, dst_len, name_len; + WCHAR src_path[MAX_PATH], dst_path[MAX_PATH]; + WCHAR *filename; ++ WIN32_FIND_DATAW ffd; ++ HANDLE f; ++ BOOL wildcard = FALSE, separator = FALSE; + + TRACE("%p %s %s\n", iface, debugstr_w(source), debugstr_w(destination)); + +@@ -3832,19 +3835,43 @@ static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR + if (!GetFullPathNameW(source, MAX_PATH, src_path, &filename)) + return E_FAIL; + +- src_len = SysStringLen(src_path); +- if (src_path[src_len-1] != '\\' && src_path[src_len-1] != '/') +- wcscat(src_path, L"\\"); ++ if (wcspbrk(filename,L"*?")) ++ wildcard = TRUE; + + dst_len = lstrlenW(destination); +- if (destination[dst_len-1] == '\\' || destination[dst_len-1] == '/') { +- lstrcpyW(dst_path, destination); +- lstrcatW(dst_path, filename); +- TRACE("move %s to %s\n", debugstr_w(src_path), debugstr_w(dst_path)); +- return MoveFileW(src_path, dst_path) ? S_OK : create_movefolder_error(GetLastError()); ++ if (destination[dst_len-1] == '\\' || destination[dst_len-1] == '/') ++ separator = TRUE; ++ ++ if (!wildcard && !separator) { ++ src_len = SysStringLen(src_path); ++ if (src_path[src_len-1] != '\\' && src_path[src_len-1] != '/') ++ wcscat(src_path, L"\\"); ++ TRACE("move %s to %s\n", debugstr_w(src_path), debugstr_w(destination)); ++ return MoveFileW(src_path, destination) ? S_OK : create_movefolder_error(GetLastError()); + } +- TRACE("move %s to %s\n", debugstr_w(src_path), debugstr_w(destination)); +- return MoveFileW(src_path, destination) ? S_OK : create_movefolder_error(GetLastError()); ++ ++ memcpy(dst_path, destination, dst_len*sizeof(WCHAR)); ++ if (!separator) ++ dst_path[dst_len++] = '\\'; ++ src_len = filename - src_path; ++ f = FindFirstFileW(source, &ffd); ++ if(f == INVALID_HANDLE_VALUE) ++ return create_error(GetLastError()); ++ ++ do { ++ name_len = lstrlenW(ffd.cFileName); ++ if(src_len+name_len+1 >= MAX_PATH || dst_len+name_len+1 >= MAX_PATH) { ++ FindClose(f); ++ return E_FAIL; ++ } ++ memcpy(filename, ffd.cFileName, (name_len+1)*sizeof(WCHAR)); ++ memcpy(dst_path + dst_len, ffd.cFileName, (name_len+1)*sizeof(WCHAR)); ++ TRACE("move %s to %s\n", debugstr_w(src_path), debugstr_w(dst_path)); ++ if (!MoveFileW(src_path, dst_path)) return create_error(GetLastError()); ++ } while(FindNextFileW(f, &ffd)); ++ FindClose(f); ++ ++ return S_OK; + } + + static inline HRESULT copy_file(const WCHAR *source, DWORD source_len, +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index d237e21e9a6..4f5f1b0a7b8 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2642,7 +2642,7 @@ static void test_MoveFile(void) + static void test_MoveFolder(void) + { + BSTR src, dst, str, empty; +- WCHAR buffW1[MAX_PATH],buffW2[MAX_PATH],pathW[MAX_PATH]; ++ WCHAR buffW1[MAX_PATH], buffW2[MAX_PATH], pathW[MAX_PATH], srcW[MAX_PATH]; + HRESULT hr; + HANDLE file; + +@@ -2737,6 +2737,31 @@ static void test_MoveFolder(void) + lstrcatW(pathW,L"foo"); + ok(RemoveDirectoryW(pathW), "can't remove %s directory\n", wine_dbgstr_w(pathW)); + ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); ++ ++ GetTempPathW(MAX_PATH, buffW1); ++ lstrcatW(buffW1,L"foo1"); ++ GetTempPathW(MAX_PATH, buffW2); ++ lstrcatW(buffW2,L"foo2"); ++ GetTempPathW(MAX_PATH, srcW); ++ lstrcatW(srcW,L"foo?"); ++ GetTempPathW(MAX_PATH, pathW); ++ lstrcatW(pathW,L"bar"); ++ ok(CreateDirectoryW(buffW1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW1)); ++ ok(CreateDirectoryW(buffW2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW2)); ++ ok(CreateDirectoryW(pathW, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(pathW)); ++ src = SysAllocString(srcW); ++ dst = SysAllocString(pathW); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); ++ lstrcpyW(buffW1,pathW); ++ lstrcatW(buffW1,L"\\foo1"); ++ lstrcpyW(buffW2,pathW); ++ lstrcatW(buffW2,L"\\foo2"); ++ ok(RemoveDirectoryW(buffW1), "can't remove %s directory\n", wine_dbgstr_w(buffW1)); ++ ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); ++ ok(RemoveDirectoryW(pathW), "can't remove %s directory\n", wine_dbgstr_w(pathW)); + } + + static void test_DoOpenPipeStream(void) +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0008-scrrun-Move-directories-only-in-MoveFolder.patch b/patches/scrrun_move_folder/0008-scrrun-Move-directories-only-in-MoveFolder.patch new file mode 100644 index 00000000..bf98a850 --- /dev/null +++ b/patches/scrrun_move_folder/0008-scrrun-Move-directories-only-in-MoveFolder.patch @@ -0,0 +1,81 @@ +From 58989b73e856ab5c757991fc61e4690afc70c59d Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Mon, 18 Jul 2022 11:53:08 +0200 +Subject: [PATCH] scrrun: Move directories only in MoveFolder(). + +Signed-off-by: Robert Wilhelm +--- + dlls/scrrun/filesystem.c | 8 ++++++-- + dlls/scrrun/tests/filesystem.c | 10 +++++++++- + 2 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index 749a06739c7..79cd3439ea2 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3860,14 +3860,18 @@ static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR + + do { + name_len = lstrlenW(ffd.cFileName); +- if(src_len+name_len+1 >= MAX_PATH || dst_len+name_len+1 >= MAX_PATH) { ++ if(src_len+name_len+2 >= MAX_PATH || dst_len+name_len+1 >= MAX_PATH) { + FindClose(f); + return E_FAIL; + } + memcpy(filename, ffd.cFileName, (name_len+1)*sizeof(WCHAR)); ++ wcscat(filename, L"\\"); + memcpy(dst_path + dst_len, ffd.cFileName, (name_len+1)*sizeof(WCHAR)); + TRACE("move %s to %s\n", debugstr_w(src_path), debugstr_w(dst_path)); +- if (!MoveFileW(src_path, dst_path)) return create_error(GetLastError()); ++ if (!MoveFileW(src_path, dst_path)) { ++ if (GetLastError() == ERROR_INVALID_NAME) continue; ++ return create_movefolder_error(GetLastError()); ++ } + } while(FindNextFileW(f, &ffd)); + FindClose(f); + +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index 4f5f1b0a7b8..1d6e7da921b 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2642,7 +2642,7 @@ static void test_MoveFile(void) + static void test_MoveFolder(void) + { + BSTR src, dst, str, empty; +- WCHAR buffW1[MAX_PATH], buffW2[MAX_PATH], pathW[MAX_PATH], srcW[MAX_PATH]; ++ WCHAR buffW1[MAX_PATH], buffW2[MAX_PATH], buffW3[MAX_PATH], pathW[MAX_PATH], srcW[MAX_PATH]; + HRESULT hr; + HANDLE file; + +@@ -2742,6 +2742,8 @@ static void test_MoveFolder(void) + lstrcatW(buffW1,L"foo1"); + GetTempPathW(MAX_PATH, buffW2); + lstrcatW(buffW2,L"foo2"); ++ GetTempPathW(MAX_PATH, buffW3); ++ lstrcatW(buffW3,L"foo3"); + GetTempPathW(MAX_PATH, srcW); + lstrcatW(srcW,L"foo?"); + GetTempPathW(MAX_PATH, pathW); +@@ -2749,6 +2751,11 @@ static void test_MoveFolder(void) + ok(CreateDirectoryW(buffW1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW1)); + ok(CreateDirectoryW(buffW2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW2)); + ok(CreateDirectoryW(pathW, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(pathW)); ++ /* create a file, should not be moved by MoveFolder() */ ++ file = CreateFileW(buffW3, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, ++ FILE_ATTRIBUTE_NORMAL, NULL); ++ ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n"); ++ CloseHandle(file); + src = SysAllocString(srcW); + dst = SysAllocString(pathW); + hr = IFileSystem3_MoveFolder(fs3, src, dst); +@@ -2762,6 +2769,7 @@ static void test_MoveFolder(void) + ok(RemoveDirectoryW(buffW1), "can't remove %s directory\n", wine_dbgstr_w(buffW1)); + ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); + ok(RemoveDirectoryW(pathW), "can't remove %s directory\n", wine_dbgstr_w(pathW)); ++ ok(DeleteFileW(buffW3), "can't remove %s\n", wine_dbgstr_w(buffW3)); + } + + static void test_DoOpenPipeStream(void) +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0009-scrrun-return-path-not-found-error-if-source-ends-wi.patch b/patches/scrrun_move_folder/0009-scrrun-return-path-not-found-error-if-source-ends-wi.patch new file mode 100644 index 00000000..986634cc --- /dev/null +++ b/patches/scrrun_move_folder/0009-scrrun-return-path-not-found-error-if-source-ends-wi.patch @@ -0,0 +1,57 @@ +From c76079238f5cd3d4d2baf2ec037b4af38dcc084c Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Tue, 2 Aug 2022 22:19:10 +0200 +Subject: [PATCH] scrrun: return path not found error if source ends with path + separator in MoveFolder(). + +--- + dlls/scrrun/filesystem.c | 4 ++++ + dlls/scrrun/tests/filesystem.c | 17 +++++++++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index 79cd3439ea2..dd1c18ed406 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3832,6 +3832,10 @@ static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR + if(!source || !source[0] || !destination || !destination[0]) + return E_INVALIDARG; + ++ src_len = SysStringLen(source); ++ if (source[src_len-1] == '\\' || source[src_len-1] == '/') ++ return CTL_E_PATHNOTFOUND; ++ + if (!GetFullPathNameW(source, MAX_PATH, src_path, &filename)) + return E_FAIL; + +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index 1d6e7da921b..a5bc7964f2a 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2720,6 +2720,23 @@ static void test_MoveFolder(void) + ok(RemoveDirectoryW(pathW), "can't remove %s directory\n", wine_dbgstr_w(pathW)); + ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); + ++ GetTempPathW(MAX_PATH, buffW1); ++ lstrcatW(buffW1,L"foo"); ++ GetTempPathW(MAX_PATH, buffW2); ++ lstrcatW(buffW2,L"bar"); ++ ok(CreateDirectoryW(buffW1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW1)); ++ ok(CreateDirectoryW(buffW2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(buffW2)); ++ lstrcpyW(pathW,buffW1); ++ lstrcatW(pathW,L"\\"); ++ src = SysAllocString(pathW); ++ dst = SysAllocString(buffW2); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); ++ ok(hr == CTL_E_PATHNOTFOUND, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); ++ ok(RemoveDirectoryW(buffW1), "can't remove %s directory\n", wine_dbgstr_w(buffW1)); ++ ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); ++ + GetTempPathW(MAX_PATH, buffW1); + lstrcatW(buffW1,L"foo"); + GetTempPathW(MAX_PATH, buffW2); +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/0010-scrrun-Return-path-not-found-error-if-no-folders-wer.patch b/patches/scrrun_move_folder/0010-scrrun-Return-path-not-found-error-if-no-folders-wer.patch new file mode 100644 index 00000000..6078133b --- /dev/null +++ b/patches/scrrun_move_folder/0010-scrrun-Return-path-not-found-error-if-no-folders-wer.patch @@ -0,0 +1,79 @@ +From 435f38808b5812571fa17f1da3f387c52d206b11 Mon Sep 17 00:00:00 2001 +From: Robert Wilhelm +Date: Tue, 2 Aug 2022 22:31:17 +0200 +Subject: [PATCH] scrrun: Return path not found error if no folders were moved + in MoveFolder(). + +--- + dlls/scrrun/filesystem.c | 5 +++-- + dlls/scrrun/tests/filesystem.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 31 insertions(+), 2 deletions(-) + +diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c +index dd1c18ed406..af4521898a7 100644 +--- a/dlls/scrrun/filesystem.c ++++ b/dlls/scrrun/filesystem.c +@@ -3825,7 +3825,7 @@ static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR + WCHAR *filename; + WIN32_FIND_DATAW ffd; + HANDLE f; +- BOOL wildcard = FALSE, separator = FALSE; ++ BOOL wildcard = FALSE, separator = FALSE, success = FALSE; + + TRACE("%p %s %s\n", iface, debugstr_w(source), debugstr_w(destination)); + +@@ -3876,10 +3876,11 @@ static HRESULT WINAPI filesys_MoveFolder(IFileSystem3 *iface, BSTR source, BSTR + if (GetLastError() == ERROR_INVALID_NAME) continue; + return create_movefolder_error(GetLastError()); + } ++ success = TRUE; + } while(FindNextFileW(f, &ffd)); + FindClose(f); + +- return S_OK; ++ return success ? S_OK : CTL_E_PATHNOTFOUND; + } + + static inline HRESULT copy_file(const WCHAR *source, DWORD source_len, +diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c +index a5bc7964f2a..8cd465f1454 100644 +--- a/dlls/scrrun/tests/filesystem.c ++++ b/dlls/scrrun/tests/filesystem.c +@@ -2787,6 +2787,34 @@ static void test_MoveFolder(void) + ok(RemoveDirectoryW(buffW2), "can't remove %s directory\n", wine_dbgstr_w(buffW2)); + ok(RemoveDirectoryW(pathW), "can't remove %s directory\n", wine_dbgstr_w(pathW)); + ok(DeleteFileW(buffW3), "can't remove %s\n", wine_dbgstr_w(buffW3)); ++ ++ GetTempPathW(MAX_PATH, buffW1); ++ lstrcatW(buffW1,L"foo1"); ++ GetTempPathW(MAX_PATH, buffW2); ++ lstrcatW(buffW2,L"foo2"); ++ GetTempPathW(MAX_PATH, srcW); ++ lstrcatW(srcW,L"foo*"); ++ GetTempPathW(MAX_PATH, pathW); ++ lstrcatW(pathW,L"bar"); ++ ok(CreateDirectoryW(pathW, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(pathW)); ++ /* create two files, should not be moved by MoveFolder() */ ++ file = CreateFileW(buffW1, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, ++ FILE_ATTRIBUTE_NORMAL, NULL); ++ ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n"); ++ CloseHandle(file); ++ file = CreateFileW(buffW2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, ++ FILE_ATTRIBUTE_NORMAL, NULL); ++ ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n"); ++ CloseHandle(file); ++ src = SysAllocString(srcW); ++ dst = SysAllocString(pathW); ++ hr = IFileSystem3_MoveFolder(fs3, src, dst); ++ ok(hr == CTL_E_PATHNOTFOUND, "Unexpected hr %#lx.\n", hr); ++ SysFreeString(src); ++ SysFreeString(dst); ++ ok(RemoveDirectoryW(pathW), "can't remove %s directory\n", wine_dbgstr_w(pathW)); ++ ok(DeleteFileW(buffW1), "can't remove %s\n", wine_dbgstr_w(buffW1)); ++ ok(DeleteFileW(buffW2), "can't remove %s\n", wine_dbgstr_w(buffW2)); + } + + static void test_DoOpenPipeStream(void) +-- +2.43.0 + diff --git a/patches/scrrun_move_folder/definition b/patches/scrrun_move_folder/definition new file mode 100644 index 00000000..0654555c --- /dev/null +++ b/patches/scrrun_move_folder/definition @@ -0,0 +1,5 @@ +Fixes: [52128] scrrun: Implement IFileSystem3 MoveFolder. + +# MR: https://gitlab.winehq.org/wine/wine/-/merge_requests/391/commits +# Other Reference +# https://gitlab.winehq.org/wine/wine/-/merge_requests/343