From 7001c84457753319b37f79b077d7fa765a2a9a3d Mon Sep 17 00:00:00 2001 From: Nightwalker743 Date: Thu, 30 Jul 2026 23:47:27 -0500 Subject: [PATCH 1/3] Fix Open Container file copy crashes --- app/src/main/assets/wfm/LICENSE.WFM.txt | 21 + app/src/main/assets/wfm/NOTICE.txt | 23 ++ app/src/main/assets/wfm/copy-hardening.patch | 364 ++++++++++++++++++ app/src/main/assets/wfm/native-copy.patch | 139 +++++++ .../assets/wfm/replace-all-conflicts.patch | 52 +++ app/src/main/assets/wfm/wfm.exe | Bin 0 -> 302592 bytes .../ui/screen/xserver/XServerScreen.kt | 5 + .../java/app/gamenative/utils/WfmInstaller.kt | 107 +++++ 8 files changed, 711 insertions(+) create mode 100644 app/src/main/assets/wfm/LICENSE.WFM.txt create mode 100644 app/src/main/assets/wfm/NOTICE.txt create mode 100644 app/src/main/assets/wfm/copy-hardening.patch create mode 100644 app/src/main/assets/wfm/native-copy.patch create mode 100644 app/src/main/assets/wfm/replace-all-conflicts.patch create mode 100644 app/src/main/assets/wfm/wfm.exe create mode 100644 app/src/main/java/app/gamenative/utils/WfmInstaller.kt diff --git a/app/src/main/assets/wfm/LICENSE.WFM.txt b/app/src/main/assets/wfm/LICENSE.WFM.txt new file mode 100644 index 0000000000..46aea4107a --- /dev/null +++ b/app/src/main/assets/wfm/LICENSE.WFM.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 BrunoSX + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/app/src/main/assets/wfm/NOTICE.txt b/app/src/main/assets/wfm/NOTICE.txt new file mode 100644 index 0000000000..3badad2987 --- /dev/null +++ b/app/src/main/assets/wfm/NOTICE.txt @@ -0,0 +1,23 @@ +Winlator File Manager - GameNative native-copy patch +==================================================== + +The wfm.exe payload is built from the original Winlator File Manager: +https://github.com/brunodev85/wfm + +Source commit: +cb1d078cef36d3d61eec822882febcde828f09e7 + +Only the copy/paste implementation and its conflict prompts are changed. The +patches are included alongside this notice as native-copy.patch, +replace-all-conflicts.patch, and copy-hardening.patch, in that application +order. The zero-context hardening patch is applied with +`git apply --unidiff-zero copy-hardening.patch`. Together they replace +ACTION_COPY's shell32 SHFileOperation call with direct +Win32 file-copy calls; offer Replace All, Review Each, or Cancel on the first +conflict; and add safe handling for read-only files, reparse points, type +conflicts, copy errors, path limits, and basic directory metadata. The original +WFM user interface, directory enumeration, move behavior, and delete behavior +are retained. + +Winlator File Manager is licensed under the MIT License. Its copyright and +permission notice are included in LICENSE.WFM.txt. diff --git a/app/src/main/assets/wfm/copy-hardening.patch b/app/src/main/assets/wfm/copy-hardening.patch new file mode 100644 index 0000000000..573482b511 --- /dev/null +++ b/app/src/main/assets/wfm/copy-hardening.patch @@ -0,0 +1,364 @@ +From: GameNative local compatibility build +Subject: [PATCH] Harden native WFM copies for filesystem edge cases + +Apply with `git apply --unidiff-zero` after native-copy.patch and +replace-all-conflicts.patch. + +Refuse reparse-point traversal, handle read-only replacements, report +file/directory collisions and Win32 failures, validate fixed-size paths, +and preserve basic metadata on newly created directories. + +diff --git a/src/file_actions.c b/src/file_actions.c +--- a/src/file_actions.c ++++ b/src/file_actions.c +@@ -143 +143,128 @@ static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath); +-static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { ++static enum CopyResult failCopy( ++ const wchar_t* srcPath, ++ const wchar_t* dstPath, ++ DWORD error, ++ const wchar_t* detail ++) { ++ wchar_t systemMessage[256] = {0}; ++ DWORD messageLength = FormatMessage( ++ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, ++ NULL, ++ error, ++ 0, ++ systemMessage, ++ sizeof(systemMessage) / sizeof(systemMessage[0]), ++ NULL ++ ); ++ if (messageLength == 0) { ++ wcscpy_s(systemMessage, 256, L"Unknown Windows error."); ++ } ++ ++ wchar_t message[MAX_PATH * 2 + 768] = {0}; ++ int result = swprintf_s( ++ message, ++ sizeof(message) / sizeof(message[0]), ++ L"%ls\n\nFrom:\n%ls\n\nTo:\n%ls\n\n%ls (error %lu)", ++ detail, ++ srcPath, ++ dstPath, ++ systemMessage, ++ error ++ ); ++ if (result < 0) { ++ swprintf_s( ++ message, ++ sizeof(message) / sizeof(message[0]), ++ L"%ls\n\nThe affected path is too long to display.\n\nError %lu", ++ detail, ++ error ++ ); ++ } ++ ++ MessageBox(hwndDlg, message, L"Copy Failed", MB_OK | MB_ICONERROR); ++ SetLastError(error); ++ return COPY_RESULT_FAILED; ++} ++ ++static bool joinCopyPath( ++ const wchar_t* directory, ++ const wchar_t* name, ++ wchar_t* destination, ++ size_t destinationSize ++) { ++ int length = swprintf_s( ++ destination, ++ destinationSize, ++ L"%ls\\%ls", ++ directory, ++ name ++ ); ++ return length >= 0 && (size_t)length < destinationSize; ++} ++ ++static enum CopyResult overwriteFileNative( ++ wchar_t* srcPath, ++ wchar_t* dstPath ++) { ++ DWORD dstAttributes = GetFileAttributes(dstPath); ++ if (dstAttributes == INVALID_FILE_ATTRIBUTES) { ++ DWORD error = GetLastError(); ++ if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) { ++ return CopyFile(srcPath, dstPath, TRUE) ++ ? COPY_RESULT_OK ++ : failCopy( ++ srcPath, ++ dstPath, ++ GetLastError(), ++ L"The destination disappeared before it could be replaced." ++ ); ++ } ++ return failCopy( ++ srcPath, ++ dstPath, ++ error, ++ L"The existing destination could not be inspected." ++ ); ++ } ++ ++ if (dstAttributes & FILE_ATTRIBUTE_DIRECTORY) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ ERROR_ALREADY_EXISTS, ++ L"A folder exists where the copied file needs to be created." ++ ); ++ } ++ if (dstAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ ERROR_NOT_SUPPORTED, ++ L"Replacing symbolic links and other reparse points is not supported." ++ ); ++ } ++ ++ bool clearedReadOnly = (dstAttributes & FILE_ATTRIBUTE_READONLY) != 0; ++ DWORD writableAttributes = dstAttributes & ~FILE_ATTRIBUTE_READONLY; ++ if (writableAttributes == 0) writableAttributes = FILE_ATTRIBUTE_NORMAL; ++ if (clearedReadOnly && ++ !SetFileAttributes(dstPath, writableAttributes)) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ GetLastError(), ++ L"The existing file is read-only and could not be made writable." ++ ); ++ } ++ ++ if (CopyFile(srcPath, dstPath, FALSE)) return COPY_RESULT_OK; ++ ++ DWORD error = GetLastError(); ++ if (clearedReadOnly) SetFileAttributes(dstPath, dstAttributes); ++ return failCopy(srcPath, dstPath, error, L"The existing file could not be replaced."); ++} ++ ++static enum CopyResult confirmAndCopyFile( ++ wchar_t* srcPath, ++ wchar_t* dstPath ++) { +@@ -147,2 +274,24 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { +- if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) { +- return COPY_RESULT_FAILED; ++ DWORD dstAttributes = GetFileAttributes(dstPath); ++ if (dstAttributes == INVALID_FILE_ATTRIBUTES) { ++ return failCopy(srcPath, dstPath, error, L"The file could not be copied."); ++ } ++ if (dstAttributes & FILE_ATTRIBUTE_DIRECTORY) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ ERROR_ALREADY_EXISTS, ++ L"A folder exists where the copied file needs to be created." ++ ); ++ } ++ if (dstAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ ERROR_NOT_SUPPORTED, ++ L"Replacing symbolic links and other reparse points is not supported." ++ ); ++ } ++ if (error != ERROR_FILE_EXISTS && ++ error != ERROR_ALREADY_EXISTS && ++ error != ERROR_ACCESS_DENIED) { ++ return failCopy(srcPath, dstPath, error, L"The file could not be copied."); +@@ -174,3 +323 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { +- return CopyFile(srcPath, dstPath, FALSE) +- ? COPY_RESULT_OK +- : COPY_RESULT_FAILED; ++ return overwriteFileNative(srcPath, dstPath); +@@ -201,3 +348,47 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { +- return CopyFile(srcPath, dstPath, FALSE) +- ? COPY_RESULT_OK +- : COPY_RESULT_FAILED; ++ return overwriteFileNative(srcPath, dstPath); ++} ++ ++static void preserveDirectoryMetadata(const wchar_t* srcPath, const wchar_t* dstPath) { ++ HANDLE srcHandle = CreateFile( ++ srcPath, ++ FILE_READ_ATTRIBUTES, ++ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, ++ NULL, ++ OPEN_EXISTING, ++ FILE_FLAG_BACKUP_SEMANTICS, ++ NULL ++ ); ++ HANDLE dstHandle = CreateFile( ++ dstPath, ++ FILE_WRITE_ATTRIBUTES, ++ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, ++ NULL, ++ OPEN_EXISTING, ++ FILE_FLAG_BACKUP_SEMANTICS, ++ NULL ++ ); ++ ++ if (srcHandle != INVALID_HANDLE_VALUE && dstHandle != INVALID_HANDLE_VALUE) { ++ FILETIME creationTime; ++ FILETIME accessTime; ++ FILETIME writeTime; ++ if (GetFileTime(srcHandle, &creationTime, &accessTime, &writeTime)) { ++ SetFileTime(dstHandle, &creationTime, &accessTime, &writeTime); ++ } ++ } ++ if (srcHandle != INVALID_HANDLE_VALUE) CloseHandle(srcHandle); ++ if (dstHandle != INVALID_HANDLE_VALUE) CloseHandle(dstHandle); ++ ++ DWORD srcAttributes = GetFileAttributes(srcPath); ++ if (srcAttributes != INVALID_FILE_ATTRIBUTES) { ++ DWORD basicAttributes = srcAttributes & ( ++ FILE_ATTRIBUTE_READONLY | ++ FILE_ATTRIBUTE_HIDDEN | ++ FILE_ATTRIBUTE_SYSTEM | ++ FILE_ATTRIBUTE_ARCHIVE ++ ); ++ SetFileAttributes( ++ dstPath, ++ basicAttributes == 0 ? FILE_ATTRIBUTE_NORMAL : basicAttributes ++ ); ++ } +@@ -206 +397,5 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { +-static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { ++static enum CopyResult copyDirectoryNative( ++ wchar_t* srcPath, ++ wchar_t* dstPath ++) { ++ bool createdDestination = false; +@@ -209 +404,8 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +- if (error != ERROR_ALREADY_EXISTS) return COPY_RESULT_FAILED; ++ if (error != ERROR_ALREADY_EXISTS) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ error, ++ L"The destination folder could not be created." ++ ); ++ } +@@ -212,3 +414,23 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +- if (dstAttributes == INVALID_FILE_ATTRIBUTES || +- !(dstAttributes & FILE_ATTRIBUTE_DIRECTORY)) { +- return COPY_RESULT_FAILED; ++ if (dstAttributes == INVALID_FILE_ATTRIBUTES) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ GetLastError(), ++ L"The existing destination could not be inspected." ++ ); ++ } ++ if (!(dstAttributes & FILE_ATTRIBUTE_DIRECTORY)) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ ERROR_ALREADY_EXISTS, ++ L"A file exists where the copied folder needs to be created." ++ ); ++ } ++ if (dstAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ ERROR_NOT_SUPPORTED, ++ L"Copying into symbolic links and other reparse points is not supported." ++ ); +@@ -216,0 +439 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { ++ else createdDestination = true; +@@ -219 +442,8 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +- swprintf_s(pattern, MAX_PATH, L"%ls\\*", srcPath); ++ if (!joinCopyPath(srcPath, L"*", pattern, MAX_PATH)) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ ERROR_FILENAME_EXCED_RANGE, ++ L"The source folder path is too long." ++ ); ++ } +@@ -224,3 +454,11 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +- return GetLastError() == ERROR_FILE_NOT_FOUND +- ? COPY_RESULT_OK +- : COPY_RESULT_FAILED; ++ DWORD error = GetLastError(); ++ if (error == ERROR_FILE_NOT_FOUND) { ++ if (createdDestination) preserveDirectoryMetadata(srcPath, dstPath); ++ return COPY_RESULT_OK; ++ } ++ return failCopy( ++ srcPath, ++ dstPath, ++ error, ++ L"The source folder could not be enumerated." ++ ); +@@ -238,2 +476,10 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +- swprintf_s(childSrc, MAX_PATH, L"%ls\\%ls", srcPath, wfd.cFileName); +- swprintf_s(childDst, MAX_PATH, L"%ls\\%ls", dstPath, wfd.cFileName); ++ if (!joinCopyPath(srcPath, wfd.cFileName, childSrc, MAX_PATH) || ++ !joinCopyPath(dstPath, wfd.cFileName, childDst, MAX_PATH)) { ++ result = failCopy( ++ srcPath, ++ dstPath, ++ ERROR_FILENAME_EXCED_RANGE, ++ L"A path inside this folder is too long." ++ ); ++ break; ++ } +@@ -246,0 +493,10 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { ++ if (result == COPY_RESULT_OK && ++ !actionData->cancel && ++ GetLastError() != ERROR_NO_MORE_FILES) { ++ result = failCopy( ++ srcPath, ++ dstPath, ++ GetLastError(), ++ L"The source folder could not be fully enumerated." ++ ); ++ } +@@ -248 +504,5 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +- return actionData->cancel ? COPY_RESULT_CANCELLED : result; ++ if (actionData->cancel) return COPY_RESULT_CANCELLED; ++ if (result == COPY_RESULT_OK && createdDestination) { ++ preserveDirectoryMetadata(srcPath, dstPath); ++ } ++ return result; +@@ -251,0 +512,2 @@ static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath) { ++ if (actionData->cancel) return COPY_RESULT_CANCELLED; ++ +@@ -253 +515,16 @@ static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath) { +- if (attributes == INVALID_FILE_ATTRIBUTES) return COPY_RESULT_FAILED; ++ if (attributes == INVALID_FILE_ATTRIBUTES) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ GetLastError(), ++ L"The source item could not be inspected." ++ ); ++ } ++ if (attributes & FILE_ATTRIBUTE_REPARSE_POINT) { ++ return failCopy( ++ srcPath, ++ dstPath, ++ ERROR_NOT_SUPPORTED, ++ L"Copying symbolic links and other reparse points is not supported." ++ ); ++ } +@@ -281 +558,9 @@ static DWORD WINAPI fileActionTask(void* param) { +- swprintf_s(dstPath, MAX_PATH, L"%ls\\%ls", actionData->dstPath, basename); ++ if (!joinCopyPath(actionData->dstPath, basename, dstPath, MAX_PATH)) { ++ failCopy( ++ actionData->srcPaths[i], ++ actionData->dstPath, ++ ERROR_FILENAME_EXCED_RANGE, ++ L"The destination path is too long." ++ ); ++ break; ++ } +@@ -450 +735 @@ void createDesktopShortcuts(struct FileNode** nodes, int count) { +-} +\ No newline at end of file ++} diff --git a/app/src/main/assets/wfm/native-copy.patch b/app/src/main/assets/wfm/native-copy.patch new file mode 100644 index 0000000000..6861697abb --- /dev/null +++ b/app/src/main/assets/wfm/native-copy.patch @@ -0,0 +1,139 @@ +From: GameNative local compatibility build +Subject: [PATCH] Avoid shell32 for WFM copy operations + +Apply to https://github.com/brunodev85/wfm at commit +cb1d078cef36d3d61eec822882febcde828f09e7. + +This intentionally changes only ACTION_COPY. The original WFM UI, directory +enumeration, move behavior, and delete behavior remain unchanged. + +diff --git a/src/file_actions.c b/src/file_actions.c +index 4961edb..0f03c6e 100644 +--- a/src/file_actions.c ++++ b/src/file_actions.c +@@ -128,1 +128,99 @@ static DWORD WINAPI fileActionTask(void* param) { ++enum CopyResult { ++ COPY_RESULT_FAILED, ++ COPY_RESULT_OK, ++ COPY_RESULT_CANCELLED ++}; ++ ++static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath); ++ ++static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { ++ if (CopyFile(srcPath, dstPath, TRUE)) return COPY_RESULT_OK; ++ ++ DWORD error = GetLastError(); ++ if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) { ++ return COPY_RESULT_FAILED; ++ } ++ ++ wchar_t basename[MAX_PATH] = {0}; ++ getBasenameFromPath(dstPath, basename, false); ++ ++ wchar_t msg[MAX_PATH + 96] = {0}; ++ swprintf_s( ++ msg, ++ MAX_PATH + 96, ++ L"\"%ls\" already exists.\n\nDo you want to replace it?", ++ basename ++ ); ++ ++ int response = MessageBox( ++ hwndDlg, ++ msg, ++ L"Confirm File Replace", ++ MB_YESNOCANCEL | MB_ICONQUESTION ++ ); ++ if (response == IDCANCEL) { ++ actionData->cancel = true; ++ return COPY_RESULT_CANCELLED; ++ } ++ if (response == IDNO) return COPY_RESULT_OK; ++ ++ return CopyFile(srcPath, dstPath, FALSE) ++ ? COPY_RESULT_OK ++ : COPY_RESULT_FAILED; ++} ++ ++static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { ++ if (!CreateDirectory(dstPath, NULL)) { ++ DWORD error = GetLastError(); ++ if (error != ERROR_ALREADY_EXISTS) return COPY_RESULT_FAILED; ++ ++ DWORD dstAttributes = GetFileAttributes(dstPath); ++ if (dstAttributes == INVALID_FILE_ATTRIBUTES || ++ !(dstAttributes & FILE_ATTRIBUTE_DIRECTORY)) { ++ return COPY_RESULT_FAILED; ++ } ++ } ++ ++ wchar_t pattern[MAX_PATH] = {0}; ++ swprintf_s(pattern, MAX_PATH, L"%ls\\*", srcPath); ++ ++ WIN32_FIND_DATA wfd = {0}; ++ HANDLE handle = FindFirstFile(pattern, &wfd); ++ if (handle == INVALID_HANDLE_VALUE) { ++ return GetLastError() == ERROR_FILE_NOT_FOUND ++ ? COPY_RESULT_OK ++ : COPY_RESULT_FAILED; ++ } ++ ++ enum CopyResult result = COPY_RESULT_OK; ++ do { ++ if (wcscmp(wfd.cFileName, L".") == 0 || ++ wcscmp(wfd.cFileName, L"..") == 0) { ++ continue; ++ } ++ ++ wchar_t childSrc[MAX_PATH] = {0}; ++ wchar_t childDst[MAX_PATH] = {0}; ++ swprintf_s(childSrc, MAX_PATH, L"%ls\\%ls", srcPath, wfd.cFileName); ++ swprintf_s(childDst, MAX_PATH, L"%ls\\%ls", dstPath, wfd.cFileName); ++ ++ result = copyPathNative(childSrc, childDst); ++ } ++ while (result == COPY_RESULT_OK && ++ !actionData->cancel && ++ FindNextFile(handle, &wfd)); ++ ++ FindClose(handle); ++ return actionData->cancel ? COPY_RESULT_CANCELLED : result; ++} ++ ++static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath) { ++ DWORD attributes = GetFileAttributes(srcPath); ++ if (attributes == INVALID_FILE_ATTRIBUTES) return COPY_RESULT_FAILED; ++ ++ return attributes & FILE_ATTRIBUTE_DIRECTORY ++ ? copyDirectoryNative(srcPath, dstPath) ++ : confirmAndCopyFile(srcPath, dstPath); ++} ++ + static DWORD WINAPI fileActionTask(void* param) { +@@ -142,11 +240,23 @@ static DWORD WINAPI fileActionTask(void* param) { + int res = SHFileOperation(&sfo); + if (res != 0) break; + } +- else if (actionData->action == ACTION_COPY || actionData->action == ACTION_MOVE) { ++ else if (actionData->action == ACTION_COPY) { ++ wchar_t basename[MAX_PATH] = {0}; ++ wchar_t dstPath[MAX_PATH] = {0}; ++ getBasenameFromPath(actionData->srcPaths[i], basename, false); ++ swprintf_s(dstPath, MAX_PATH, L"%ls\\%ls", actionData->dstPath, basename); ++ ++ // Copying an item onto itself is a no-op. ++ if (wcsicmp(actionData->srcPaths[i], dstPath) == 0) continue; ++ ++ enum CopyResult result = copyPathNative(actionData->srcPaths[i], dstPath); ++ if (result != COPY_RESULT_OK) break; ++ } ++ else if (actionData->action == ACTION_MOVE) { + SHFILEOPSTRUCT sfo; + memset(&sfo, 0, sizeof(sfo)); + sfo.hwnd = hwndDlg; +- sfo.wFunc = actionData->action == ACTION_COPY ? FO_COPY : FO_MOVE; ++ sfo.wFunc = FO_MOVE; + sfo.fFlags = FOF_SILENT; + sfo.pTo = actionData->dstPath; + sfo.pFrom = actionData->srcPaths[i]; diff --git a/app/src/main/assets/wfm/replace-all-conflicts.patch b/app/src/main/assets/wfm/replace-all-conflicts.patch new file mode 100644 index 0000000000..2a7a59d4d7 --- /dev/null +++ b/app/src/main/assets/wfm/replace-all-conflicts.patch @@ -0,0 +1,52 @@ +From: GameNative local compatibility build +Subject: [PATCH] Offer replace-all policy on the first copy conflict + +Apply after native-copy.patch. + +diff --git a/src/file_actions.c b/src/file_actions.c +index 0f03c6e..03644bc 100644 +--- a/src/file_actions.c ++++ b/src/file_actions.c +@@ -18,1 +18,7 @@ struct ActionData { ++enum ConflictPolicy { ++ CONFLICT_POLICY_ASK, ++ CONFLICT_POLICY_REPLACE_ALL, ++ CONFLICT_POLICY_REVIEW_EACH ++}; ++ + struct ActionData { +@@ -24,1 +30,2 @@ struct ActionData { ++ enum ConflictPolicy conflictPolicy; + }; +@@ -144,1 +151,28 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { ++ ++ if (actionData->conflictPolicy == CONFLICT_POLICY_ASK) { ++ int response = MessageBox( ++ hwndDlg, ++ L"Existing files were found.\n\n" ++ L"Yes: Replace all conflicts during this paste\n" ++ L"No: Review each conflict\n" ++ L"Cancel: Stop copying", ++ L"File Conflicts", ++ MB_YESNOCANCEL | MB_ICONQUESTION ++ ); ++ ++ if (response == IDCANCEL) { ++ actionData->cancel = true; ++ return COPY_RESULT_CANCELLED; ++ } ++ ++ actionData->conflictPolicy = response == IDYES ++ ? CONFLICT_POLICY_REPLACE_ALL ++ : CONFLICT_POLICY_REVIEW_EACH; ++ } ++ ++ if (actionData->conflictPolicy == CONFLICT_POLICY_REPLACE_ALL) { ++ return CopyFile(srcPath, dstPath, FALSE) ++ ? COPY_RESULT_OK ++ : COPY_RESULT_FAILED; ++ } + wchar_t basename[MAX_PATH] = {0}; +@@ -349,1 +383,2 @@ void pasteFiles(wchar_t* dstDir) { ++ actionData->conflictPolicy = CONFLICT_POLICY_ASK; + SetTimer(hwndDlg, ID_EVENT_PRELOADER, PRELOADER_PERIOD, NULL); diff --git a/app/src/main/assets/wfm/wfm.exe b/app/src/main/assets/wfm/wfm.exe new file mode 100644 index 0000000000000000000000000000000000000000..3ce6784aaea779b50f389963c9834af87544ab26 GIT binary patch literal 302592 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�-vDOa5#krEPyxv+}cEPTY4+av#wR=YKXu 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 literal 0 HcmV?d00001 diff --git a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt index c713b9b97f..bad56ef8f4 100644 --- a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt @@ -131,6 +131,7 @@ import app.gamenative.utils.SteamTokenLogin import app.gamenative.utils.SteamUtils import app.gamenative.utils.downloader.WinComponentDownloader import app.gamenative.utils.WineProcessSnapshotHelper +import app.gamenative.utils.WfmInstaller import com.posthog.PostHog import com.winlator.alsaserver.ALSAClient import com.winlator.container.Container @@ -4010,6 +4011,10 @@ private fun getWineStartCommand( } } + if (bootToContainer && !WfmInstaller.install(context, container)) { + Timber.tag("XServerScreen").e("Could not install the Open Container file manager update") + } + val args = if (testGraphics) { "\"Z:/opt/apps/TestD3D.exe\"" } else if (bootToContainer) { diff --git a/app/src/main/java/app/gamenative/utils/WfmInstaller.kt b/app/src/main/java/app/gamenative/utils/WfmInstaller.kt new file mode 100644 index 0000000000..85521e0e29 --- /dev/null +++ b/app/src/main/java/app/gamenative/utils/WfmInstaller.kt @@ -0,0 +1,107 @@ +package app.gamenative.utils + +import android.content.Context +import com.winlator.container.Container +import com.winlator.core.FileUtils +import timber.log.Timber +import java.io.File +import java.io.InputStream +import java.nio.file.AtomicMoveNotSupportedException +import java.nio.file.Files +import java.nio.file.StandardCopyOption +import java.security.MessageDigest + +/** + * Installs the minimally patched original file manager used by Open Container. + * + * Only WFM's copy operation bypasses Wine's crashing SHFileOperation implementation. Keep this + * payload separate from the container pattern so app updates can repair existing containers + * without rebuilding ImageFS or deleting user data. + */ +object WfmInstaller { + private const val ASSET_DIRECTORY = "wfm" + private val payloads = listOf( + Payload( + filename = "wfm.exe", + sha256 = "cc7b5b77d7e11b1b337fc53c5766176b670c09d23c9a2390a776de389ea014b1", + ), + ) + + fun install(context: Context, container: Container): Boolean { + val windowsDirectory = File(container.rootDir, ".wine/drive_c/windows") + if (!windowsDirectory.isDirectory && !windowsDirectory.mkdirs()) { + Timber.e("Could not create WFM destination: %s", windowsDirectory) + return false + } + + return payloads.all { payload -> + installPayload(context, windowsDirectory, payload) + } + } + + private fun installPayload( + context: Context, + destinationDirectory: File, + payload: Payload, + ): Boolean { + val destination = File(destinationDirectory, payload.filename) + if (destination.isFile && + runCatching { sha256(destination) }.getOrNull() == payload.sha256 + ) { + return true + } + + val temporary = File(destinationDirectory, ".${payload.filename}.installing") + return try { + Files.deleteIfExists(temporary.toPath()) + context.assets.open("$ASSET_DIRECTORY/${payload.filename}").use { input -> + Files.copy(input, temporary.toPath(), StandardCopyOption.REPLACE_EXISTING) + } + + check(sha256(temporary) == payload.sha256) { + "Bundled ${payload.filename} failed integrity verification" + } + + try { + Files.move( + temporary.toPath(), + destination.toPath(), + StandardCopyOption.ATOMIC_MOVE, + StandardCopyOption.REPLACE_EXISTING, + ) + } catch (_: AtomicMoveNotSupportedException) { + Files.move( + temporary.toPath(), + destination.toPath(), + StandardCopyOption.REPLACE_EXISTING, + ) + } + FileUtils.chmod(destination, 493) + Timber.i("Installed minimally patched %s", payload.filename) + true + } catch (error: Exception) { + Timber.e(error, "Failed to install %s", payload.filename) + runCatching { Files.deleteIfExists(temporary.toPath()) } + false + } + } + + private fun sha256(file: File): String = + file.inputStream().buffered().use(::sha256) + + private fun sha256(input: InputStream): String { + val digest = MessageDigest.getInstance("SHA-256") + val buffer = ByteArray(DEFAULT_BUFFER_SIZE) + while (true) { + val count = input.read(buffer) + if (count < 0) break + digest.update(buffer, 0, count) + } + return digest.digest().joinToString(separator = "") { byte -> "%02x".format(byte) } + } + + private data class Payload( + val filename: String, + val sha256: String, + ) +} From 35e31e5c8ac0797babea2b753fd6b832449db437 Mon Sep 17 00:00:00 2001 From: Nightwalker743 Date: Fri, 31 Jul 2026 00:30:28 -0500 Subject: [PATCH 2/3] Harden WFM copy handling and build provenance --- app/src/main/assets/wfm/NOTICE.txt | 12 +- app/src/main/assets/wfm/README.md | 37 ++++ app/src/main/assets/wfm/copy-hardening.patch | 203 +++++++++++++++--- app/src/main/assets/wfm/native-copy.patch | 19 +- .../assets/wfm/replace-all-conflicts.patch | 39 +++- app/src/main/assets/wfm/wfm.exe | Bin 302592 -> 304128 bytes .../ui/screen/xserver/XServerScreen.kt | 26 ++- .../java/app/gamenative/utils/WfmInstaller.kt | 2 +- app/src/main/res/values/strings.xml | 1 + 9 files changed, 273 insertions(+), 66 deletions(-) create mode 100644 app/src/main/assets/wfm/README.md diff --git a/app/src/main/assets/wfm/NOTICE.txt b/app/src/main/assets/wfm/NOTICE.txt index 3badad2987..6010e5197a 100644 --- a/app/src/main/assets/wfm/NOTICE.txt +++ b/app/src/main/assets/wfm/NOTICE.txt @@ -10,12 +10,12 @@ cb1d078cef36d3d61eec822882febcde828f09e7 Only the copy/paste implementation and its conflict prompts are changed. The patches are included alongside this notice as native-copy.patch, replace-all-conflicts.patch, and copy-hardening.patch, in that application -order. The zero-context hardening patch is applied with -`git apply --unidiff-zero copy-hardening.patch`. Together they replace -ACTION_COPY's shell32 SHFileOperation call with direct -Win32 file-copy calls; offer Replace All, Review Each, or Cancel on the first -conflict; and add safe handling for read-only files, reparse points, type -conflicts, copy errors, path limits, and basic directory metadata. The original +order using standard `git apply` commands. Together they replace ACTION_COPY's +shell32 SHFileOperation call with direct Win32 file-copy calls; offer Replace +All, Review Each, or Cancel on the first conflict; and add safe handling for +read-only files, reparse points, type conflicts, copy errors, path limits, +copying a folder into its descendant, and basic directory metadata. Unsupported +reparse-point entries are skipped and summarized after the copy. The original WFM user interface, directory enumeration, move behavior, and delete behavior are retained. diff --git a/app/src/main/assets/wfm/README.md b/app/src/main/assets/wfm/README.md new file mode 100644 index 0000000000..625c8629f6 --- /dev/null +++ b/app/src/main/assets/wfm/README.md @@ -0,0 +1,37 @@ +# Rebuilding `wfm.exe` + +The payload is built from Winlator File Manager commit +`cb1d078cef36d3d61eec822882febcde828f09e7`. + +Use the 64-bit w64devkit 2.9.0 archive +`w64devkit-x64-2.9.0.7z.exe`: + +- Archive SHA-256: + `bff1d13fc2718eebd93548cf37f8d0332d925458d5e99506cff8f46eb5a9de5a` +- GCC: 16.1.0 +- GNU binutils/windres: 2.47.20260726 + +Clone the upstream source, check out the pinned commit, copy the three patch +files from this directory into the checkout, and apply them in order: + +```sh +git clone https://github.com/brunodev85/wfm.git +cd wfm +git checkout cb1d078cef36d3d61eec822882febcde828f09e7 +git apply native-copy.patch +git apply replace-all-conflicts.patch +git apply copy-hardening.patch +``` + +From a w64devkit shell in that clean checkout, run this exact build command. +The object order is intentional and is required for a byte-identical result: + +```sh +make CC=gcc RC=windres "INCLUDE_DIR=-I./include" "OBJS=obj/file_actions.o obj/main.o obj/content_view.o obj/toolbar.o obj/navbar.o obj/treeview.o obj/sizebar.o obj/statusbar.o obj/file_node.o obj/file_utils.o obj/input_dialog.o obj/resource.o" "CFLAGS=-O3 -std=c99 -DUNICODE -D_UNICODE -DCOBJMACROS -D_CRT_NON_CONFORMING_WCSTOK -D_WIN32_IE=0x0500 -DWINVER=0x500 -Wall -Wno-error=incompatible-pointer-types -Wno-error=int-conversion" "LDFLAGS=-s -lcomctl32 -lgdi32 -lole32 -luuid -Wl,--subsystem,windows" +``` + +The expected output is 304,128 bytes with SHA-256: + +```text +9c7799513a07730884fdc3b27f7b3168fd7fa5db764cc5f468f63c30b33e65e2 +``` diff --git a/app/src/main/assets/wfm/copy-hardening.patch b/app/src/main/assets/wfm/copy-hardening.patch index 573482b511..65726e7ae4 100644 --- a/app/src/main/assets/wfm/copy-hardening.patch +++ b/app/src/main/assets/wfm/copy-hardening.patch @@ -1,17 +1,35 @@ -From: GameNative local compatibility build +From 921d9322fb904d6c3d39dfbbabe1ae8e341f3028 Mon Sep 17 00:00:00 2001 +From: Nightwalker743 +Date: Fri, 31 Jul 2026 00:13:24 -0500 Subject: [PATCH] Harden native WFM copies for filesystem edge cases -Apply with `git apply --unidiff-zero` after native-copy.patch and -replace-all-conflicts.patch. - -Refuse reparse-point traversal, handle read-only replacements, report -file/directory collisions and Win32 failures, validate fixed-size paths, -and preserve basic metadata on newly created directories. +--- + src/file_actions.c | 390 ++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 366 insertions(+), 24 deletions(-) diff --git a/src/file_actions.c b/src/file_actions.c +index 45a2c60..d657bd8 100644 --- a/src/file_actions.c +++ b/src/file_actions.c -@@ -143 +143,128 @@ static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath); +@@ -28,6 +28,7 @@ struct ActionData { + wchar_t* dstPath; + bool cancel; + enum ConflictPolicy conflictPolicy; ++ int skippedCount; + }; + + static HWND hwndDlg; +@@ -135,17 +136,202 @@ INT_PTR CALLBACK FileActionDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPA + enum CopyResult { + COPY_RESULT_FAILED, + COPY_RESULT_OK, +- COPY_RESULT_CANCELLED ++ COPY_RESULT_CANCELLED, ++ COPY_RESULT_SKIPPED + }; + + static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath); + -static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { +static enum CopyResult failCopy( + const wchar_t* srcPath, @@ -34,9 +52,10 @@ diff --git a/src/file_actions.c b/src/file_actions.c + } + + wchar_t message[MAX_PATH * 2 + 768] = {0}; -+ int result = swprintf_s( ++ int result = _snwprintf_s( + message, + sizeof(message) / sizeof(message[0]), ++ _TRUNCATE, + L"%ls\n\nFrom:\n%ls\n\nTo:\n%ls\n\n%ls (error %lu)", + detail, + srcPath, @@ -45,9 +64,10 @@ diff --git a/src/file_actions.c b/src/file_actions.c + error + ); + if (result < 0) { -+ swprintf_s( ++ _snwprintf_s( + message, + sizeof(message) / sizeof(message[0]), ++ _TRUNCATE, + L"%ls\n\nThe affected path is too long to display.\n\nError %lu", + detail, + error @@ -65,9 +85,10 @@ diff --git a/src/file_actions.c b/src/file_actions.c + wchar_t* destination, + size_t destinationSize +) { -+ int length = swprintf_s( ++ int length = _snwprintf_s( + destination, + destinationSize, ++ _TRUNCATE, + L"%ls\\%ls", + directory, + name @@ -75,6 +96,38 @@ diff --git a/src/file_actions.c b/src/file_actions.c + return length >= 0 && (size_t)length < destinationSize; +} + ++static bool isCopyDestinationDescendant( ++ const wchar_t* srcPath, ++ const wchar_t* dstPath ++) { ++ wchar_t fullSrc[MAX_PATH] = {0}; ++ wchar_t fullDst[MAX_PATH] = {0}; ++ DWORD srcLength = GetFullPathName(srcPath, MAX_PATH, fullSrc, NULL); ++ DWORD dstLength = GetFullPathName(dstPath, MAX_PATH, fullDst, NULL); ++ if (srcLength == 0 || srcLength >= MAX_PATH || ++ dstLength == 0 || dstLength >= MAX_PATH) { ++ return false; ++ } ++ ++ while (srcLength > 3 && ++ (fullSrc[srcLength - 1] == L'\\' || fullSrc[srcLength - 1] == L'/')) { ++ fullSrc[--srcLength] = L'\0'; ++ } ++ while (dstLength > 3 && ++ (fullDst[dstLength - 1] == L'\\' || fullDst[dstLength - 1] == L'/')) { ++ fullDst[--dstLength] = L'\0'; ++ } ++ ++ if (dstLength <= srcLength || ++ _wcsnicmp(fullSrc, fullDst, srcLength) != 0) { ++ return false; ++ } ++ if (fullSrc[srcLength - 1] == L'\\' || fullSrc[srcLength - 1] == L'/') { ++ return true; ++ } ++ return fullDst[srcLength] == L'\\' || fullDst[srcLength] == L'/'; ++} ++ +static enum CopyResult overwriteFileNative( + wchar_t* srcPath, + wchar_t* dstPath @@ -141,7 +194,9 @@ diff --git a/src/file_actions.c b/src/file_actions.c + wchar_t* srcPath, + wchar_t* dstPath +) { -@@ -147,2 +274,24 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { + if (CopyFile(srcPath, dstPath, TRUE)) return COPY_RESULT_OK; + + DWORD error = GetLastError(); - if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) { - return COPY_RESULT_FAILED; + DWORD dstAttributes = GetFileAttributes(dstPath); @@ -168,18 +223,31 @@ diff --git a/src/file_actions.c b/src/file_actions.c + error != ERROR_ALREADY_EXISTS && + error != ERROR_ACCESS_DENIED) { + return failCopy(srcPath, dstPath, error, L"The file could not be copied."); -@@ -174,3 +323 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { + } + + +@@ -171,9 +357,7 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { + } + + if (actionData->conflictPolicy == CONFLICT_POLICY_REPLACE_ALL) { - return CopyFile(srcPath, dstPath, FALSE) - ? COPY_RESULT_OK - : COPY_RESULT_FAILED; + return overwriteFileNative(srcPath, dstPath); -@@ -201,3 +348,47 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { + } + wchar_t basename[MAX_PATH] = {0}; + getBasenameFromPath(dstPath, basename, false); +@@ -198,32 +382,123 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { + } + if (response == IDNO) return COPY_RESULT_OK; + - return CopyFile(srcPath, dstPath, FALSE) - ? COPY_RESULT_OK - : COPY_RESULT_FAILED; + return overwriteFileNative(srcPath, dstPath); -+} -+ + } + +-static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +static void preserveDirectoryMetadata(const wchar_t* srcPath, const wchar_t* dstPath) { + HANDLE srcHandle = CreateFile( + srcPath, @@ -224,14 +292,15 @@ diff --git a/src/file_actions.c b/src/file_actions.c + basicAttributes == 0 ? FILE_ATTRIBUTE_NORMAL : basicAttributes + ); + } -@@ -206 +397,5 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { --static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { ++} ++ +static enum CopyResult copyDirectoryNative( + wchar_t* srcPath, + wchar_t* dstPath +) { + bool createdDestination = false; -@@ -209 +404,8 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + if (!CreateDirectory(dstPath, NULL)) { + DWORD error = GetLastError(); - if (error != ERROR_ALREADY_EXISTS) return COPY_RESULT_FAILED; + if (error != ERROR_ALREADY_EXISTS) { + return failCopy( @@ -241,7 +310,8 @@ diff --git a/src/file_actions.c b/src/file_actions.c + L"The destination folder could not be created." + ); + } -@@ -212,3 +414,23 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + + DWORD dstAttributes = GetFileAttributes(dstPath); - if (dstAttributes == INVALID_FILE_ATTRIBUTES || - !(dstAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - return COPY_RESULT_FAILED; @@ -268,9 +338,11 @@ diff --git a/src/file_actions.c b/src/file_actions.c + ERROR_NOT_SUPPORTED, + L"Copying into symbolic links and other reparse points is not supported." + ); -@@ -216,0 +439 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + } + } + else createdDestination = true; -@@ -219 +442,8 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + + wchar_t pattern[MAX_PATH] = {0}; - swprintf_s(pattern, MAX_PATH, L"%ls\\*", srcPath); + if (!joinCopyPath(srcPath, L"*", pattern, MAX_PATH)) { + return failCopy( @@ -280,7 +352,10 @@ diff --git a/src/file_actions.c b/src/file_actions.c + L"The source folder path is too long." + ); + } -@@ -224,3 +454,11 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + + WIN32_FIND_DATA wfd = {0}; + HANDLE handle = FindFirstFile(pattern, &wfd); + if (handle == INVALID_HANDLE_VALUE) { - return GetLastError() == ERROR_FILE_NOT_FOUND - ? COPY_RESULT_OK - : COPY_RESULT_FAILED; @@ -295,7 +370,13 @@ diff --git a/src/file_actions.c b/src/file_actions.c + error, + L"The source folder could not be enumerated." + ); -@@ -238,2 +476,10 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + } + + enum CopyResult result = COPY_RESULT_OK; +@@ -235,22 +510,67 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + + wchar_t childSrc[MAX_PATH] = {0}; + wchar_t childDst[MAX_PATH] = {0}; - swprintf_s(childSrc, MAX_PATH, L"%ls\\%ls", srcPath, wfd.cFileName); - swprintf_s(childDst, MAX_PATH, L"%ls\\%ls", dstPath, wfd.cFileName); + if (!joinCopyPath(srcPath, wfd.cFileName, childSrc, MAX_PATH) || @@ -308,7 +389,14 @@ diff --git a/src/file_actions.c b/src/file_actions.c + ); + break; + } -@@ -246,0 +493,10 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + + result = copyPathNative(childSrc, childDst); ++ if (result == COPY_RESULT_SKIPPED) result = COPY_RESULT_OK; + } + while (result == COPY_RESULT_OK && + !actionData->cancel && + FindNextFile(handle, &wfd)); + + if (result == COPY_RESULT_OK && + !actionData->cancel && + GetLastError() != ERROR_NO_MORE_FILES) { @@ -319,17 +407,19 @@ diff --git a/src/file_actions.c b/src/file_actions.c + L"The source folder could not be fully enumerated." + ); + } -@@ -248 +504,5 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { + FindClose(handle); - return actionData->cancel ? COPY_RESULT_CANCELLED : result; + if (actionData->cancel) return COPY_RESULT_CANCELLED; + if (result == COPY_RESULT_OK && createdDestination) { + preserveDirectoryMetadata(srcPath, dstPath); + } + return result; -@@ -251,0 +512,2 @@ static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath) { + } + + static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath) { + if (actionData->cancel) return COPY_RESULT_CANCELLED; + -@@ -253 +515,16 @@ static enum CopyResult copyPathNative(wchar_t* srcPath, wchar_t* dstPath) { + DWORD attributes = GetFileAttributes(srcPath); - if (attributes == INVALID_FILE_ATTRIBUTES) return COPY_RESULT_FAILED; + if (attributes == INVALID_FILE_ATTRIBUTES) { + return failCopy( @@ -340,14 +430,25 @@ diff --git a/src/file_actions.c b/src/file_actions.c + ); + } + if (attributes & FILE_ATTRIBUTE_REPARSE_POINT) { ++ actionData->skippedCount++; ++ return COPY_RESULT_SKIPPED; ++ } ++ if ((attributes & FILE_ATTRIBUTE_DIRECTORY) && ++ isCopyDestinationDescendant(srcPath, dstPath)) { + return failCopy( + srcPath, + dstPath, -+ ERROR_NOT_SUPPORTED, -+ L"Copying symbolic links and other reparse points is not supported." ++ ERROR_INVALID_PARAMETER, ++ L"A folder cannot be copied into itself or one of its subfolders." + ); + } -@@ -281 +558,9 @@ static DWORD WINAPI fileActionTask(void* param) { + + return attributes & FILE_ATTRIBUTE_DIRECTORY + ? copyDirectoryNative(srcPath, dstPath) +@@ -278,12 +598,21 @@ static DWORD WINAPI fileActionTask(void* param) { + wchar_t basename[MAX_PATH] = {0}; + wchar_t dstPath[MAX_PATH] = {0}; + getBasenameFromPath(actionData->srcPaths[i], basename, false); - swprintf_s(dstPath, MAX_PATH, L"%ls\\%ls", actionData->dstPath, basename); + if (!joinCopyPath(actionData->dstPath, basename, dstPath, MAX_PATH)) { + failCopy( @@ -358,7 +459,39 @@ diff --git a/src/file_actions.c b/src/file_actions.c + ); + break; + } -@@ -450 +735 @@ void createDesktopShortcuts(struct FileNode** nodes, int count) { --} -\ No newline at end of file -+} + + // Copying an item onto itself is a no-op. + if (wcsicmp(actionData->srcPaths[i], dstPath) == 0) continue; + + enum CopyResult result = copyPathNative(actionData->srcPaths[i], dstPath); ++ if (result == COPY_RESULT_SKIPPED) continue; + if (result != COPY_RESULT_OK) break; + } + else if (actionData->action == ACTION_MOVE) { +@@ -305,6 +634,18 @@ static DWORD WINAPI fileActionTask(void* param) { + lastTime = currTime; + } + } ++ ++ if (actionData->action == ACTION_COPY && actionData->skippedCount > 0) { ++ wchar_t message[192] = {0}; ++ _snwprintf_s( ++ message, ++ sizeof(message) / sizeof(message[0]), ++ _TRUNCATE, ++ L"Skipped %d symbolic link or reparse point item(s). The copy continued with the remaining items.", ++ actionData->skippedCount ++ ); ++ MessageBox(hwndDlg, message, L"Copy Summary", MB_OK | MB_ICONINFORMATION); ++ } + + SendMessage(hwndDlg, MSG_CLOSE, 0, 0); + return 0; +@@ -378,6 +719,7 @@ void pasteFiles(wchar_t* dstDir) { + actionData->srcPaths = clipboard; + actionData->numSrcPaths = clipboardSize; + actionData->cancel = false; ++ actionData->skippedCount = 0; + + hwndDlg = CreateDialogParam(globalHInstance, MAKEINTRESOURCE(IDD_FILE_ACTION), hwndMain, &FileActionDialogProc, 0); + actionData->conflictPolicy = CONFLICT_POLICY_ASK; diff --git a/app/src/main/assets/wfm/native-copy.patch b/app/src/main/assets/wfm/native-copy.patch index 6861697abb..b044116e95 100644 --- a/app/src/main/assets/wfm/native-copy.patch +++ b/app/src/main/assets/wfm/native-copy.patch @@ -1,17 +1,20 @@ -From: GameNative local compatibility build +From b1e4add200e2a38e1aad33226e2e5af23e32078e Mon Sep 17 00:00:00 2001 +From: Nightwalker743 +Date: Fri, 31 Jul 2026 00:13:24 -0500 Subject: [PATCH] Avoid shell32 for WFM copy operations -Apply to https://github.com/brunodev85/wfm at commit -cb1d078cef36d3d61eec822882febcde828f09e7. - -This intentionally changes only ACTION_COPY. The original WFM UI, directory -enumeration, move behavior, and delete behavior remain unchanged. +--- + src/file_actions.c | 114 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/src/file_actions.c b/src/file_actions.c index 4961edb..0f03c6e 100644 --- a/src/file_actions.c +++ b/src/file_actions.c -@@ -128,1 +128,99 @@ static DWORD WINAPI fileActionTask(void* param) { +@@ -125,6 +125,104 @@ INT_PTR CALLBACK FileActionDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPA + return (INT_PTR)FALSE; + } + +enum CopyResult { + COPY_RESULT_FAILED, + COPY_RESULT_OK, @@ -111,6 +114,8 @@ index 4961edb..0f03c6e 100644 +} + static DWORD WINAPI fileActionTask(void* param) { + struct ActionData* actionData = (struct ActionData*)param; + DWORD lastTime = GetTickCount(); @@ -142,11 +240,23 @@ static DWORD WINAPI fileActionTask(void* param) { int res = SHFileOperation(&sfo); if (res != 0) break; diff --git a/app/src/main/assets/wfm/replace-all-conflicts.patch b/app/src/main/assets/wfm/replace-all-conflicts.patch index 2a7a59d4d7..075ce6224b 100644 --- a/app/src/main/assets/wfm/replace-all-conflicts.patch +++ b/app/src/main/assets/wfm/replace-all-conflicts.patch @@ -1,13 +1,20 @@ -From: GameNative local compatibility build -Subject: [PATCH] Offer replace-all policy on the first copy conflict +From 7df10c642efeaf5c4029d95f890c6c89643431f1 Mon Sep 17 00:00:00 2001 +From: Nightwalker743 +Date: Fri, 31 Jul 2026 00:13:24 -0500 +Subject: [PATCH] Offer replace-all policy on first copy conflict -Apply after native-copy.patch. +--- + src/file_actions.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) diff --git a/src/file_actions.c b/src/file_actions.c -index 0f03c6e..03644bc 100644 +index 0f03c6e..45a2c60 100644 --- a/src/file_actions.c +++ b/src/file_actions.c -@@ -18,1 +18,7 @@ struct ActionData { +@@ -15,12 +15,19 @@ enum FileAction { + ACTION_MOVE + }; + +enum ConflictPolicy { + CONFLICT_POLICY_ASK, + CONFLICT_POLICY_REPLACE_ALL, @@ -15,10 +22,19 @@ index 0f03c6e..03644bc 100644 +}; + struct ActionData { -@@ -24,1 +30,2 @@ struct ActionData { + enum FileAction action; + wchar_t** srcPaths; + int numSrcPaths; + wchar_t* dstPath; + bool cancel; + enum ConflictPolicy conflictPolicy; }; -@@ -144,1 +151,28 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { + + static HWND hwndDlg; +@@ -141,6 +148,33 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { + return COPY_RESULT_FAILED; + } + + + if (actionData->conflictPolicy == CONFLICT_POLICY_ASK) { + int response = MessageBox( @@ -47,6 +63,13 @@ index 0f03c6e..03644bc 100644 + : COPY_RESULT_FAILED; + } wchar_t basename[MAX_PATH] = {0}; -@@ -349,1 +383,2 @@ void pasteFiles(wchar_t* dstDir) { + getBasenameFromPath(dstPath, basename, false); + +@@ -346,6 +380,7 @@ void pasteFiles(wchar_t* dstDir) { + actionData->cancel = false; + + hwndDlg = CreateDialogParam(globalHInstance, MAKEINTRESOURCE(IDD_FILE_ACTION), hwndMain, &FileActionDialogProc, 0); + actionData->conflictPolicy = CONFLICT_POLICY_ASK; SetTimer(hwndDlg, ID_EVENT_PRELOADER, PRELOADER_PERIOD, NULL); + CreateThread(NULL, 0, fileActionTask, actionData, 0, NULL); + ShowWindow(hwndDlg, SW_SHOW); diff --git a/app/src/main/assets/wfm/wfm.exe b/app/src/main/assets/wfm/wfm.exe index 3ce6784aaea779b50f389963c9834af87544ab26..a3389d2eb4b33822f803e59367b7463c5dd60747 100644 GIT binary patch delta 25417 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

O;4oXi#dMVafMyTTuJ$&Fog|&O^H5oQ@su zgb9F7gB{?xwZqZqy9_hXM!+#?Te{(^K~sFWy2DSw4@p`J7&P6Uci+>Gj$WsCXR|> zNin@*=#b-S$5_%Aopn#gSE=~a9#_ye^2w|$rcuDsA}F8l<2Vw1{9s|~ydrieW{CVg z3yy6epJ!>Y&47;pZeWER-x%A$w+wB#3_Z)(x3Qu1wzVP`s3w;&Ij%+0q*+vkD^sm= zrX&?t78KDv3-Xv#oEx;Hd(derbi(B_o;Xc{8Dc~?zsE+zb@0Ve8FCN5!ZyT(*1Lw| z66DT%h3$`PA#Y_r#-+6AMMnml`Sa^>y9h>B>yAUQyAvc%C@oCATgWovW0W6Svf1&` z@#P4`i&7ndiX`VhR(nUTE&>5Q$Q_89xZ%Gx6bl7PObKM4$G0)zDJgBue1T|ryd*l1 z84?;d-a%W3rv!@m@lh~!eVKJiXkxyO&e78Xk_BUaC=x14-4np_6C$5jA3(Q8d?R$3 zu59AH{bv(+D(F z2TLD_w~A7a8XxSayBUqi{V7NEvXB+Gja2GIvUl1BD>W_Iv9`_R!R+U@&0B?{B}Cv^ zvSxF&>8=^6VTaq5A1`ZlfXjIPa~scpI%v~ae7i<*%P_FL9T#nmn=oY`Sly1h6C4?{|J9nZ+3k8OCnDH^cG2=X>{`145kF2t1IY(xT}0&`=$GeG>H%#R zrT%1KxlcoE6|H`l*ufxM@`ZvQ=)~5G z)73MN!&LF9QV$CZ;lnG42gz&Zz~c;9&z|luL}_JahdR7!{1Xv!2A)2p-7+preRc!O z@7TxQwz=mn#t92>s#$(~P4@;s%!|XaLro^qx-6F^t*5KekJOs>B~8a!GQ;rJbuK(J-#qXDa>`MGVxM0$qk%YlT7kjHYBNiyS0#LKTFX938m>G(nKi>z{njwnC)qNw+LtZ@$egnrA6Uo- z>Za*v*+Z*<`RTUu08$c~VzM@a-{vT`z!ma^g!P0PDO}eq%Ou?thH$OuA3tNsSzP&2 z*pQ=}3?b}na{qb>7-{srfiG+SWJ~m7_>-Xx=Y!Vc;|Cfz@C+N%Ih4KiWUw-7B3o%~ zq~g|M+B59ZlOam%Gpjm1sa&1lC7+$c26akQ7SAE_s9JK&9CoQwi1KRz=N=F4#%w@J zVBcj0=mK;vBb`r{;4#T58dSO{2|?6JFF@;P;tHz7b3Jj#iI^5GH5r$PO6*g zG-o?g;_LMT9}P*qE{TnP*&$}xX!N_A|>VXkY zxSgpsAhcQsI};Nn)+F5`_hp^aLtDj<249u>i%v#JRZ@2Wtx`{T38>T8sjk;$wj{kp zn;%9I`~P!^ALDd&sHjz?c0+}e=@IrPL7~7eKwIWviKu01=xxGjxc09Mw@&WCd#CG6 zjYoi2;ZNNpf2teuGj$)ERE%YP7pt;M=VnyM-5baMy z^my&&zu^z_@?Sh7_^UX-{NM23_=n5yj|RRI71r_!U!&l^QfR-YLX_KlTG#0X2&{=? z+Djv$EyZV*Ty1s!KQh~x5iUE~z6_jH|6!*xTKCU=f-e^zNYG8Ykm1kqwc-)vP1I?> z(jy&u<0PmDzvZ~{w=8kzG{Ney@~f^W8Wius)J-iKumPE^8Z7rb2zG{C;E|ZY{x^Fe zv$MRMeVG~lcrb*(0&xwpoc)y<-r%>tc;0FF2?)rom$SHT$qhH)W_gb_pl~pMtcT6O z?O^`1n=7j}u$b9xCU0!WclA_wj0$)*+!oL^Of1PVZADCn%uHmo1sFO^nu%oNMGhQe z51{nE;kf_0^w5@$@jFzAHIza!oQCuFSVH$m<%4_dsqT?>=RJ~gt#CNR{00Rc2}+E+ z)b-#9cEZa0}f`ZhdJHD{Mvn)>o~Kp)?8B)4_{LcUnkti388u5d*GpM zl1j#{zJC|0A`tK^oa>9L?x(Q=wZVw#p#BSYd(q%p(Qh!$T1Wi8S9#>!PgK;a$_^}qg;>?y-( z@C6Z8+z!{nh{Gz(kf*I?!+M4(hbOQFJ^L!_1K1ZmS=isVWj>Rr`zE2gto4>*htV1h zh5}XU%G+#Fukb!IQA8v25{*p$8mGFB2sqOL;H4`(U{{v_?VVfMWAbqtf-G!IX8w?0 z`*9F;gev*I^^G zl6~JrHQi*c&tA@oZd8IpmCZQ)>nx|K8X*`sZxyj~S-r9MMfZLxat~-W=ku03)Clce zy6H=bU<3(k1p$io4STD1cjcRU>{jn2CG2+=)2DN@uW!jx@^NFa8#R}y2azi$O_!e>y~GkcIyQjfiwJw&#%yV;TW4(s=a5(m#_|Vs zRX)7N_6+LV&`FNX$5*O#Y(LEBj_u}ha%{c-Mr$yUe`?^o*72Cla057Za+uu$a&{)& zhvv|51_j_fOTgpYLJ|Ln7nfXWy%Frg!Lj}4T_bbCU8c707+vJ91ba#4!imlWmNe&7 zi!I??W&$1%jAn8(W?;#_nHce=Pj zftSw)A0`wWFMFlJg;&fYdnruqca?oUbaJ!NGM>+k4D!S){7SMns-eyWH_IMoQO>y8 zoMCawD{i)BSgbPI%}x*NtVFt5~O5jXnKT*UT?9nyNPtg!6~{BSs#~ zN;a$q(O8V-CLyx`nS#&o!m_C+_R*SZr)l%g6c!j)wDK&Ymwslqo{Fo3FpEVD&uHRA zOqFo1)QVdbUpYUmhtuC;bM&@pud&6$yW5AOu5S7Qkw}KK_n{1DCT>(~!)pvP!wWMA z$h{l9h_yc?nUxRg$uB>$l1*WdXe{>Q%9{LnW}+waCuA9mU&Z+ME~zfqXDiQ^m~BME zc1L*|nU%U}2t`WH-q&#~4bXaq(hTi598V}qj;7A9&SxUJ=B$W$2c zg(=?fBaO@m(g<$}{>TDHnu6X%nB*>k6x0akTK}M%-a}l~d1Pq6JE&lbK14>Crkn18 zHQ}h%i600-(ZW31Zotiurx(OfX>)w%o{9)XyX+~R?=7x|)OSYCtUnl1J?ptJ^~M#} zW>lo&zQP8L>ZDw`!d8vyZFgP4sM5s~bQ%U6sxQY8hMW*Bfy3%c0|9i?NV1j+x*>9^ z{eXkL71+Jqo%4ft0D3qM<3&1`VH_yh&*>11&3Lss2x5#Sb1=9NuyqlQk=kOm6e(4t zK|c5s!H<(JJ!XBDYB>$ZK!G06sL2nkWOR7X^Ot$M7XbL#{0qvjv$=xPYNPafR<65s z4}@mW75#`abV7fd*HkTN7m?r_v)GN%k;=HstZ7b|JsP3S;jWFOJ%OZ%qmFJm&3ER< z$<4=u*27VW^C1O*jx%tRIm7Y748`q>?zJNuX#`pnmii^MQTxISR@!^W7yOV=U0zsN z2!pwc%VzB9`;D2$b(0G%Ks%}!q(@Am_UNYGX_!Wel3&u!vFe=20nSU@*S5x1k%v$y z;da6~j~7+vp#+x{cpWPq@2Umqr;|fQfn>h|DI)A~`{uT{?@*K;~4OX`P$)@LaNGbcCTk+S^ zVYYZ4WGMCIFJ16jD7RS@xeQ-`re$}AD%?gt>B}zW2FE|gjdKC&du?+C_=IhKlS+yk zED-9k%~=;%n{nYy7tpQ@$ADcKJC`qJl-xcZt4?Q=#+l^>*qd7ipTgdM0!6U>kl(SH z+&_4{d!8L17wk*dXbyGx1vY)c6Uwaf%rGIEC5~@e-#`lBDL^(P4w}YBj!$g23gM41 zS#{TW^bL1?&eXk#?YwpiH8-JvMvcZ{<$3n$_$c40yop8Uc@s0gLld18pYyEegkVv0 z=R00>go>is_6fcnUEgu>p1rjYnc8K6H+I%TKew zi4B#Z=h)v9+xbm`p}-VAxFxfDlbZVPJ15jOe0YvICWbWm6`K@Y&eR1TU=&<94YvIp z+cz;%p29^f{uZLL{k3nsbuWC&hE9r5c7Mz4lj7vboT=h0wa5OP6yhIL%UJ(gW}e)- z<)yQ*_iEabNW6~6hlWs)_{!$*lw&Oqy2)lv9^7{1b(;6o7ctZ}XC|iYc}pScpwr)@ zE42^3OR?S3)@IgzXLlzjD6`J8HdERL9>zl-ZX>vAM>_N8kH#Adxl+}GO-a(Ftt*tCEe8HS2pr#v-0zA%>Hx}#pev$@N{J0xzi6-{`@qn zetMvF4yce;A;Xcu2ICN#B5HvUyikr+(jAvq2+7VM#H0t2>n8BIcoSKhGYOH~SHG}{ zQx_>8oMKm}#s>N))+(O{{R&R8=xLEk)+yG1T3leWQ)vHGt@8e-*s5tq{jDc)e8EF> zXR3aUO`P5;@Np0x=;Plf*yibLT8-zynPJokGz?FNrx1@Lz{L5Z5dmy}@tz?`J;BDz zh*9dFV5Ku!$n)3-Gt&L1qb^;fISm`XVM<cqh49dv`(IZ|w)T|ubaAMzYPf?twBuzK zBw>x4U78tge-jz9ouRtvWiE3s2(sITNu#%@!$~uz!AV@W^s1|yk~r5I5F~dvxM(}D z8u#sYs0%^UO+mc8fTW;H{Q=#7AwuALJn^+w2ZKfS+I=TaCH<1hq4!D1H!{dA!BCgtX6jGY;bIB(b=M~sG8`*i^9mw4-wMzZs9sPYZ+ z#h!dOo<~O_fMEH&Om7W%yq_9QWu|Lfj6p>P^;;64tro-Y2Tkw`DaU81{shtWh_Apb z?oQa5*#QmVHtAtM##zj6L(;Ih(qI~?*f^NST6Dj&{3|Y(W_9AvY;=BOW$+JdZhmWJ z{nzY`{BP|B+(cyI)eses9vn94;kZz9k|?)Yb4tOlco)Iu92G>f(NsH6RFt0dl;)dk z;NM755{Q+eN{!8F#FI!~rMdPNuX0!0EUGlMIlgy~Q&dy>A=ku7jFHepb|UQ%y6~j22A>YokTgArDqHyWgh(8dcL+?`JNU z!cdsuoaoD6{IWUz?18s_MzXZIG0F?a*o?V}^|UBb;H-9$y)(CQ@Da+D=mi=-$nZJ* z5F{F$ci6?bjq0yM4i`=ZH8w}$-=8sMUc9p50&71nJZ1tS9nb4!Dd3?e(ew}%I;Z*| z7@*_4OFb|Q;$5aMhOwe~u}xkApU~?MJkHV1Me@=m!`Nr@IxD{)Wq!{l)$2(_=$FoV zJ=-KB3OT%uSI`yBKYtWr7ahVQd^*h0kDWw_25tn-ydR%%BSAk7Xush3IN8CEZ0oZf z>z||?EO7HuUZvrIlr}X>8nF<7*d9%5$~IF#kzvT@I~ zig?k&rzpdfui~EU5B!t}n>yX#&&3a6^7l}}C0Am@ zL2SrEbI_U=9t~U`4SvF*gfv*lURW3sRE9#Xfwkyo_)f$h)}lXU?JPUAaC_n~?AO%d zS+sbP0sy=vBerT7fo=+fM)c^8W{cZ}Zu<8$+iD-);Z1DIwdVqg-%yio=SF~2yB0v{_N$#u)y=?T51)jAM|I(3&Wbc4XVwtFo^%a1XF^{ zL6o-d&-@m3Fn@P|rZ4eh03M)zhwku@h2FzeFC1byi=L>rf|#n*`3IPN(TFGLSFAUU zqtwYbxZE_hsk~_nP{;RYHx@F`i-#fyt z;lSoGE<3O|s_6klUK2_^zqT~vN39ijUI2BDX$j1yC_~$vs=GML}%jrqReSpb`Tp8q6l?2;uf%1AXElN>fD2@eo2@z z@*qnnX<}>&{t7H?eu0y6kPRz|wa4%Zhk0AWfa7EpM|ZltT>h~A42w;>)r=MiFn;*J zLc?bC3WgicMX>RsN`+_2@Oof50web%zGZt(g$~0Sni!{HIsu321%NDvS_+V{%&_u+ z+zcz79*Eh|2<9&X1@ytrZWzwOmYD2MQRcx{ixVmMa;o*g$sJjh8Ye0pR^tgXMyr8< zm_5A4_rOPwScNUPv{a8+EZ|!LZV+&}fX@op{~NgxuaJ&VjehCOe+d0!8+LR_a9|bf zv#xBs9i8Tjo|U&@x0hJtp{&``&PvyXZ1~cS4gB`gc;?r|vkTl(RH?Ts+3QQY$wOGp z(r8}>6qUEZd_mQSc_bV2FJ z3JTIq-+#gE%fplzpRmo#V}@r^siT)KLU5a7K!9$_|AI!TU>9zVKBtO?I#9uJK+ETL zl!gPoJB&1Rs(z^I9D<*78Me|gc4h*l*ZhPd1L4Q-BV^dq4W z){)jx^h-8A122Be@|`WiXt}9H}g`$1LTDg+sek|A3 zUNJOc>s?RD@3G%q!(at{RxFJ|Fx&G&oP3SBUx<_svB1(sjkea{~`Hfs^} zB{DEVKOC^20nA0hTc`1;@CE1k3jP&dtn5Sf3F~5h!GQK%hPk}R4~^Wf1-aG_S;*=r zdvlU_)L6U^<5Z;@kRv1Go}RlVG*NV~PQkBE^^Xsz?ffem{lux}{De}c=`xY33+5E1 zo(3it9KpOC21dOO#(`o#ybk(+u4&);TzN*G51Edcg;|UDCJ;2Vb zPV$`$f^Mogz?!YuZ?8C6A|tfapi^^&ZK)Gau$}vO}gf+{C(Z9I-7`>+aa8 ztyg5ZE34U%itp%`#>wey#Y@fc{q9R0@crXU+4%0Tv6F0Nvo^lg#!5kL+?iSR@vTll z&RDd*4%(rUB1JSgSu~pyi~~(0t<1V)au?R{m8o)PR``l3 zu(KpRTh~~89Y2DZU>ssP(wY6|mEkB;$~xh@bJ_5SR1B*WhQURTw_P>1>7u#aFu|I1)L?|SONPBn9iYh3YhtgD0Xr4vM5AWg5m$YBFlR%+tNV3Y1cMnAdy8z|$I_&JWwTq%GeTOZ5 zD{t68+vpMTZaA(Ujx)D2EFz?gA_KdLPS4V$HVf}IC&uf(D8j~|G5 zOH18PKZOY5{%7~s82UMfj^Pz6pPN|e*_pFVsRJShM6%JGuYS}9zYtVO^SlN zXw)}L1Eop4HIIh#Kp~9uBP|Prq-VIMlTey3_-CPH8hT1xlqRB#bR{a+OzH|bc@jw+ z06Ej7X}(~e1%kw0-4(erV7IT@DqxVVn~~y?(vY%|a**)!$T0PY1`85YFS_LVC`zu$Rp-%q}3*^8JhS~0;)KH6B#BO~GqXlL5d z2)W5NUEhY3f%G}jcSzTe_HNs`@UvWb(0jUm{J%&y1ug1*U8j_dG;OD@7ylQ@OW%ev zO1*Zn4xfL9TXXpVYsTv6^Kd?G7z_U*)^2{t=(&kMRPE97NAqRwhm2J!J@9Zod*XwO zN|N#(&Nq;jJxq|+u}fdr+u9ycEBlfB&`0t)t=OtBJ2xnO<>A)j*A`v=a`)vgSB4V?5B*jm*Mys@Ps5yO;b2b$B}#i@NB@pk)8)G;jI1x z((Ayl1GdI*kahr%2Q&vu(jnjk2jg1m1n?ZdiOnVH3h+F@XTl}v8t_8E%$E3>trhYC zuSCP)1tD`i8kJkYc>&J>d>?o3?Sa$7g6_Bt$)E~=r;!E%zX)i>+8jr8z}K)pO$ELK za30=HSOB~baBKqZ7l7vhZbe#0Jb>@Fm83G@m2K^kbO{^ZR%EUN{)XLiFX4bAJECX6 za{#|U`W*Oizz*28PXJE?bRm5QycDooGI|6&8_<>_N!Nkr02U%i=}-vpFp>{&xP8eV z(Y>!7nE)VJNCCj%&Lsm*2|+{${1?d#T#rP?Dssid~8a(ipFD z`gVn;fQOL+fMe&CP9g;XzX;fGup|Wo&jAb=B1snD1drqCLKN`>{xt$U1}=@nUBwvm z5_lTme~^X(uLP_@${~Kh560QiV=5RYNmItdaDe9lI*^KimjX_ifRP|N;JS%09N=Yu zi>Bg_b`lTZKs;=#1fBypa5_eaaKP9Zl5_@mJYXTxMc@SAK+=HkumfqDhap174EX0P zEIZ)v@KU?En8OV80MPO*67YDyV@OHBj{~|FU|xY=2Yl%{^bB|z;8vtO;5z{Op_BQ* za{#X*6%#+;tBWxI&l3}ng^ML=Bk)4Nl}N7xF9QrKf-vCmfc=qn0M7xOgj5bZ5AX$~ zy}(NWJ1oIS08ay~UW(oWzX&+jfldN11RS^=s~{6{mSg?@=|V4&kygOcUw~BuCzybg z0z3^cw-m+$JP+{Qm6%uHI{s}VBS0iCbF+JVELOJT2KG=Qf8Zb6Cy zz5}q^X3RbCY`{xMX~3@oUVaUB09<-qlIkF30}lX9K^h1=4X_kxC~$%;-@xCI1#XWA z@+#6)WOe|aN6G_!5isjNFdX37fQ3kNffJOsU`T-n03JaqBz!9xMJgtKz~M-xz!4`( zPa~}co(DJ|X&rFHhmvzE=6@qHr9?z31C9VudK>9=;5z_6M%oIz60pacm>S^OfNQs7 zI*1=|AJSgn<_~aPvm4U^{5s(Fa=2}x@4*jpk&0snNm557ngxROd}O$6bX1gQfHp*w6Qnw|$xoI19TRWwJk|IC9c1r`L zZQNpTHTIJlPs)^xvP<%fe=MhNo|^4bsT`N*lC=J{Ohiux8(eidOf< zri#D)%xp!XzZ-lphZOdFu7h?Qv^x*b0`l?FIcVlF_xZMg7BB&?&5pfKTTq}#NfS{& z_dcx@w8}}S{{XEVv@?^GMpD$c`;3Ki6e(!3vNEiReccof`9A`FAmAYZy}DM5{7;Y2 z{}uTF`aJ|bQ356j=&f%P`N0BC@<6+kF9^#7d{Myv2>6MBrv$t%pf5dv#ix;gEd}f# zpiRK11e_({G67%Yu&X4!B?uJ)o)GXS0dEV~V49~vi-0Kt+SUdJD~;_7M0SIKn+4n< z-~j=v1@sP#Ch|80^qcN!rm27}1#B;1Hvyj#aGVGFNwWlD!P-~Dl;-xWB3mxtApt)Z z@RWcT1=Iw*Dd67%`pod?<1b(%0Ye3h60og+DIRE-G6bQIfI|fwE8tWC=LlFVV5xu` z1>7p&`vUG2@Q8rb0$vbM;}ARJO+olqK<|kA=6QM)ETEU(Mাz1@0T&3kLBMSS zdh72M`D%h_U%Da)w*~Z_>1jAfz*Yiw7O#564K|MAo#)4(I-ei zi-7S0rU;lVV2*&Z1S}MAm4L4cSS}zJj<5UP3?Tu1{x7?;``*kh+|>VFcXr>KCI7EG z;|B1*?(Bcv+5ZpjYyvl?|8aM=8$XF^pw#bHFm-D7nEXk7#!MSOMA|*Rr6Ma$M$ex9 zOx~=?)AJ{c#<5b8Mn97~d-~+uX?eSIqm&=jwZ~%=pS8AF<;dE+SjBgDK%BD5XKDTR z3R0cj_1pUlnbhzijti(+URL&I<(o&|JpSgHH`i|1=#vs#wtdI;%I(LuU)+9uyM(|M j5i#QUfHHGgd|6sqc9~>G1PW5rTX}EIeT#0MLgoJh6Le`a delta 24360 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 T1emyW$JVl~drodpn#%tJW7py7 diff --git a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt index bad56ef8f4..3292382f85 100644 --- a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt @@ -3992,6 +3992,18 @@ private fun getWineStartCommand( val isEpicGame = gameSource == GameSource.EPIC val isSteamGame = gameSource == GameSource.STEAM val gameId = ContainerUtils.extractGameIdFromContainerId(appId) + val wfmInstalled = WfmInstaller.install(context, container) + if (!wfmInstalled) { + Timber.tag("XServerScreen").e("Could not install the Open Container file manager update") + } + + fun wfmCommand(command: String): String { + if (!wfmInstalled) { + SnackbarManager.show(context.getString(R.string.wfm_install_failed)) + throw IllegalStateException("Open Container file manager installation failed") + } + return command + } if (isSteamGame) { // Steam-specific setup @@ -4011,14 +4023,10 @@ private fun getWineStartCommand( } } - if (bootToContainer && !WfmInstaller.install(context, container)) { - Timber.tag("XServerScreen").e("Could not install the Open Container file manager update") - } - val args = if (testGraphics) { "\"Z:/opt/apps/TestD3D.exe\"" } else if (bootToContainer) { - "\"wfm.exe\"" + wfmCommand("\"wfm.exe\"") } else if (isGOGGame) { // For GOG games, use GOGService to get the launch command Timber.tag("XServerScreen").i("Launching GOG game: $gameId") @@ -4308,7 +4316,7 @@ private fun getWineStartCommand( // Attempt auto-detection only when we have the physical folder path if (gameFolderPath == null) { Timber.tag("XServerScreen").e("Could not find A: drive for Custom Game: $appId") - return "winhandler.exe \"wfm.exe\"" + return wfmCommand("winhandler.exe \"wfm.exe\"") } val auto = CustomGameScanner.findUniqueExeRelativeToFolder(gameFolderPath!!) if (auto != null) { @@ -4318,13 +4326,13 @@ private fun getWineStartCommand( container.saveData() } else { Timber.tag("XServerScreen").w("No unique executable found for Custom Game: $appId") - return "winhandler.exe \"wfm.exe\"" + return wfmCommand("winhandler.exe \"wfm.exe\"") } } if (gameFolderPath == null) { Timber.tag("XServerScreen").e("Could not find A: drive for Custom Game: $appId") - return "winhandler.exe \"wfm.exe\"" + return wfmCommand("winhandler.exe \"wfm.exe\"") } // Set working directory to the game folder @@ -4338,7 +4346,7 @@ private fun getWineStartCommand( } else if (container.executablePath.isEmpty()) { // For Steam games, we need appLaunchInfo Timber.tag("XServerScreen").w("appLaunchInfo is null for Steam game: $appId") - "\"wfm.exe\"" + wfmCommand("\"wfm.exe\"") } else { if (container.isLaunchBionicSteam) { // Bionic-Steam mode: launch the game executable directly. diff --git a/app/src/main/java/app/gamenative/utils/WfmInstaller.kt b/app/src/main/java/app/gamenative/utils/WfmInstaller.kt index 85521e0e29..0687dbc823 100644 --- a/app/src/main/java/app/gamenative/utils/WfmInstaller.kt +++ b/app/src/main/java/app/gamenative/utils/WfmInstaller.kt @@ -23,7 +23,7 @@ object WfmInstaller { private val payloads = listOf( Payload( filename = "wfm.exe", - sha256 = "cc7b5b77d7e11b1b337fc53c5766176b670c09d23c9a2390a776de389ea014b1", + sha256 = "9c7799513a07730884fdc3b27f7b3168fd7fa5db764cc5f468f63c30b33e65e2", ), ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index defb0230ff..46641232a7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2175,4 +2175,5 @@ Copied %1$s of %2$s This managed mod has incomplete source information and cannot be retried. Archive needs more memory than Android allows. Retry after updating GameNative or choose a smaller file. + Could not update the container file manager. Open Container was not started. From ec11ed8e11b31a40788176952f19d96f44b3eb49 Mon Sep 17 00:00:00 2001 From: Nightwalker743 Date: Fri, 31 Jul 2026 00:50:25 -0500 Subject: [PATCH 3/3] Resolve WFM mapped-drive copy aliases --- app/src/main/assets/wfm/NOTICE.txt | 8 +- app/src/main/assets/wfm/README.md | 4 +- app/src/main/assets/wfm/copy-hardening.patch | 150 ++++++++++++++---- app/src/main/assets/wfm/native-copy.patch | 12 +- .../assets/wfm/replace-all-conflicts.patch | 11 +- app/src/main/assets/wfm/wfm.exe | Bin 304128 -> 304640 bytes .../java/app/gamenative/utils/WfmInstaller.kt | 2 +- 7 files changed, 136 insertions(+), 51 deletions(-) diff --git a/app/src/main/assets/wfm/NOTICE.txt b/app/src/main/assets/wfm/NOTICE.txt index 6010e5197a..09de3f3067 100644 --- a/app/src/main/assets/wfm/NOTICE.txt +++ b/app/src/main/assets/wfm/NOTICE.txt @@ -14,10 +14,10 @@ order using standard `git apply` commands. Together they replace ACTION_COPY's shell32 SHFileOperation call with direct Win32 file-copy calls; offer Replace All, Review Each, or Cancel on the first conflict; and add safe handling for read-only files, reparse points, type conflicts, copy errors, path limits, -copying a folder into its descendant, and basic directory metadata. Unsupported -reparse-point entries are skipped and summarized after the copy. The original -WFM user interface, directory enumeration, move behavior, and delete behavior -are retained. +copying a folder into its descendant through direct or aliased drive paths, and +basic directory metadata. Unsupported reparse-point entries are skipped and +summarized after the copy. The original WFM user interface, directory +enumeration, move behavior, and delete behavior are retained. Winlator File Manager is licensed under the MIT License. Its copyright and permission notice are included in LICENSE.WFM.txt. diff --git a/app/src/main/assets/wfm/README.md b/app/src/main/assets/wfm/README.md index 625c8629f6..b0736e336c 100644 --- a/app/src/main/assets/wfm/README.md +++ b/app/src/main/assets/wfm/README.md @@ -30,8 +30,8 @@ The object order is intentional and is required for a byte-identical result: make CC=gcc RC=windres "INCLUDE_DIR=-I./include" "OBJS=obj/file_actions.o obj/main.o obj/content_view.o obj/toolbar.o obj/navbar.o obj/treeview.o obj/sizebar.o obj/statusbar.o obj/file_node.o obj/file_utils.o obj/input_dialog.o obj/resource.o" "CFLAGS=-O3 -std=c99 -DUNICODE -D_UNICODE -DCOBJMACROS -D_CRT_NON_CONFORMING_WCSTOK -D_WIN32_IE=0x0500 -DWINVER=0x500 -Wall -Wno-error=incompatible-pointer-types -Wno-error=int-conversion" "LDFLAGS=-s -lcomctl32 -lgdi32 -lole32 -luuid -Wl,--subsystem,windows" ``` -The expected output is 304,128 bytes with SHA-256: +The expected output is 304,640 bytes with SHA-256: ```text -9c7799513a07730884fdc3b27f7b3168fd7fa5db764cc5f468f63c30b33e65e2 +a7bb48aa14c59ece23c011c43c8439869267b13387d4a972f462a06575deebbb ``` diff --git a/app/src/main/assets/wfm/copy-hardening.patch b/app/src/main/assets/wfm/copy-hardening.patch index 65726e7ae4..75f9d5b510 100644 --- a/app/src/main/assets/wfm/copy-hardening.patch +++ b/app/src/main/assets/wfm/copy-hardening.patch @@ -1,14 +1,14 @@ -From 921d9322fb904d6c3d39dfbbabe1ae8e341f3028 Mon Sep 17 00:00:00 2001 -From: Nightwalker743 -Date: Fri, 31 Jul 2026 00:13:24 -0500 +From: GameNative local compatibility build Subject: [PATCH] Harden native WFM copies for filesystem edge cases ---- - src/file_actions.c | 390 ++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 366 insertions(+), 24 deletions(-) +Apply after native-copy.patch and replace-all-conflicts.patch. + +Handle read-only replacements, type conflicts, copy failures, path limits, +directory metadata, unsupported reparse-point entries, and mapped-drive aliases. +Reject destinations that resolve inside the source tree. diff --git a/src/file_actions.c b/src/file_actions.c -index 45a2c60..d657bd8 100644 +index 45a2c60..225c9a1 100644 --- a/src/file_actions.c +++ b/src/file_actions.c @@ -28,6 +28,7 @@ struct ActionData { @@ -19,7 +19,7 @@ index 45a2c60..d657bd8 100644 }; static HWND hwndDlg; -@@ -135,17 +136,202 @@ INT_PTR CALLBACK FileActionDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPA +@@ -135,17 +136,288 @@ INT_PTR CALLBACK FileActionDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPA enum CopyResult { COPY_RESULT_FAILED, COPY_RESULT_OK, @@ -96,6 +96,82 @@ index 45a2c60..d657bd8 100644 + return length >= 0 && (size_t)length < destinationSize; +} + ++#define COPY_RESOLVED_PATH_SIZE 1024 ++ ++static bool isCopyPathSeparator(wchar_t value) { ++ return value == L'\\' || value == L'/'; ++} ++ ++static size_t trimCopyPath(wchar_t* path) { ++ size_t length = wcslen(path); ++ while (length > 3 && isCopyPathSeparator(path[length - 1])) { ++ path[--length] = L'\0'; ++ } ++ return length; ++} ++ ++static bool isSameOrDescendantCopyPath( ++ wchar_t* ancestor, ++ wchar_t* candidate, ++ bool includeSame ++) { ++ size_t ancestorLength = trimCopyPath(ancestor); ++ size_t candidateLength = trimCopyPath(candidate); ++ if (candidateLength < ancestorLength || ++ _wcsnicmp(ancestor, candidate, ancestorLength) != 0) { ++ return false; ++ } ++ if (candidateLength == ancestorLength) return includeSame; ++ if (isCopyPathSeparator(ancestor[ancestorLength - 1])) return true; ++ return isCopyPathSeparator(candidate[ancestorLength]); ++} ++ ++static bool resolveFinalCopyPath( ++ const wchar_t* path, ++ wchar_t* resolvedPath, ++ DWORD resolvedPathSize ++) { ++ HANDLE handle = CreateFile( ++ path, ++ 0, ++ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, ++ NULL, ++ OPEN_EXISTING, ++ FILE_FLAG_BACKUP_SEMANTICS, ++ NULL ++ ); ++ if (handle == INVALID_HANDLE_VALUE) return false; ++ ++ DWORD length = GetFinalPathNameByHandle( ++ handle, ++ resolvedPath, ++ resolvedPathSize, ++ FILE_NAME_NORMALIZED | VOLUME_NAME_DOS ++ ); ++ CloseHandle(handle); ++ return length > 0 && length < resolvedPathSize; ++} ++ ++static bool removeLastCopyPathComponent(wchar_t* path) { ++ size_t length = trimCopyPath(path); ++ if (length <= 3) return false; ++ ++ wchar_t* separator = wcsrchr(path, L'\\'); ++ wchar_t* alternateSeparator = wcsrchr(path, L'/'); ++ if (alternateSeparator != NULL && ++ (separator == NULL || alternateSeparator > separator)) { ++ separator = alternateSeparator; ++ } ++ if (separator == NULL || separator == path) return false; ++ if (separator == path + 2 && path[1] == L':') { ++ separator[1] = L'\0'; ++ } ++ else { ++ *separator = L'\0'; ++ } ++ return true; ++} ++ +static bool isCopyDestinationDescendant( + const wchar_t* srcPath, + const wchar_t* dstPath @@ -109,23 +185,33 @@ index 45a2c60..d657bd8 100644 + return false; + } + -+ while (srcLength > 3 && -+ (fullSrc[srcLength - 1] == L'\\' || fullSrc[srcLength - 1] == L'/')) { -+ fullSrc[--srcLength] = L'\0'; -+ } -+ while (dstLength > 3 && -+ (fullDst[dstLength - 1] == L'\\' || fullDst[dstLength - 1] == L'/')) { -+ fullDst[--dstLength] = L'\0'; -+ } ++ if (isSameOrDescendantCopyPath(fullSrc, fullDst, false)) return true; + -+ if (dstLength <= srcLength || -+ _wcsnicmp(fullSrc, fullDst, srcLength) != 0) { ++ wchar_t resolvedSrc[COPY_RESOLVED_PATH_SIZE] = {0}; ++ if (!resolveFinalCopyPath( ++ fullSrc, ++ resolvedSrc, ++ COPY_RESOLVED_PATH_SIZE)) { + return false; + } -+ if (fullSrc[srcLength - 1] == L'\\' || fullSrc[srcLength - 1] == L'/') { -+ return true; ++ ++ wchar_t candidate[MAX_PATH] = {0}; ++ wcscpy_s(candidate, MAX_PATH, fullDst); ++ do { ++ wchar_t resolvedCandidate[COPY_RESOLVED_PATH_SIZE] = {0}; ++ if (resolveFinalCopyPath( ++ candidate, ++ resolvedCandidate, ++ COPY_RESOLVED_PATH_SIZE)) { ++ return isSameOrDescendantCopyPath( ++ resolvedSrc, ++ resolvedCandidate, ++ true ++ ); ++ } + } -+ return fullDst[srcLength] == L'\\' || fullDst[srcLength] == L'/'; ++ while (removeLastCopyPathComponent(candidate)); ++ return false; +} + +static enum CopyResult overwriteFileNative( @@ -226,7 +312,7 @@ index 45a2c60..d657bd8 100644 } -@@ -171,9 +357,7 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { +@@ -171,9 +443,7 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { } if (actionData->conflictPolicy == CONFLICT_POLICY_REPLACE_ALL) { @@ -237,7 +323,7 @@ index 45a2c60..d657bd8 100644 } wchar_t basename[MAX_PATH] = {0}; getBasenameFromPath(dstPath, basename, false); -@@ -198,32 +382,123 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { +@@ -198,32 +468,123 @@ static enum CopyResult confirmAndCopyFile(wchar_t* srcPath, wchar_t* dstPath) { } if (response == IDNO) return COPY_RESULT_OK; @@ -245,9 +331,8 @@ index 45a2c60..d657bd8 100644 - ? COPY_RESULT_OK - : COPY_RESULT_FAILED; + return overwriteFileNative(srcPath, dstPath); - } - --static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { ++} ++ +static void preserveDirectoryMetadata(const wchar_t* srcPath, const wchar_t* dstPath) { + HANDLE srcHandle = CreateFile( + srcPath, @@ -292,8 +377,9 @@ index 45a2c60..d657bd8 100644 + basicAttributes == 0 ? FILE_ATTRIBUTE_NORMAL : basicAttributes + ); + } -+} -+ + } + +-static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +static enum CopyResult copyDirectoryNative( + wchar_t* srcPath, + wchar_t* dstPath @@ -373,7 +459,7 @@ index 45a2c60..d657bd8 100644 } enum CopyResult result = COPY_RESULT_OK; -@@ -235,22 +510,67 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { +@@ -235,22 +596,67 @@ static enum CopyResult copyDirectoryNative(wchar_t* srcPath, wchar_t* dstPath) { wchar_t childSrc[MAX_PATH] = {0}; wchar_t childDst[MAX_PATH] = {0}; @@ -445,7 +531,7 @@ index 45a2c60..d657bd8 100644 return attributes & FILE_ATTRIBUTE_DIRECTORY ? copyDirectoryNative(srcPath, dstPath) -@@ -278,12 +598,21 @@ static DWORD WINAPI fileActionTask(void* param) { +@@ -278,12 +684,21 @@ static DWORD WINAPI fileActionTask(void* param) { wchar_t basename[MAX_PATH] = {0}; wchar_t dstPath[MAX_PATH] = {0}; getBasenameFromPath(actionData->srcPaths[i], basename, false); @@ -468,7 +554,7 @@ index 45a2c60..d657bd8 100644 if (result != COPY_RESULT_OK) break; } else if (actionData->action == ACTION_MOVE) { -@@ -305,6 +634,18 @@ static DWORD WINAPI fileActionTask(void* param) { +@@ -305,6 +720,18 @@ static DWORD WINAPI fileActionTask(void* param) { lastTime = currTime; } } @@ -487,7 +573,7 @@ index 45a2c60..d657bd8 100644 SendMessage(hwndDlg, MSG_CLOSE, 0, 0); return 0; -@@ -378,6 +719,7 @@ void pasteFiles(wchar_t* dstDir) { +@@ -378,6 +805,7 @@ void pasteFiles(wchar_t* dstDir) { actionData->srcPaths = clipboard; actionData->numSrcPaths = clipboardSize; actionData->cancel = false; diff --git a/app/src/main/assets/wfm/native-copy.patch b/app/src/main/assets/wfm/native-copy.patch index b044116e95..5e432d30eb 100644 --- a/app/src/main/assets/wfm/native-copy.patch +++ b/app/src/main/assets/wfm/native-copy.patch @@ -1,11 +1,11 @@ -From b1e4add200e2a38e1aad33226e2e5af23e32078e Mon Sep 17 00:00:00 2001 -From: Nightwalker743 -Date: Fri, 31 Jul 2026 00:13:24 -0500 +From: GameNative local compatibility build Subject: [PATCH] Avoid shell32 for WFM copy operations ---- - src/file_actions.c | 114 ++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 112 insertions(+), 2 deletions(-) +Apply to https://github.com/brunodev85/wfm at commit +cb1d078cef36d3d61eec822882febcde828f09e7. + +This intentionally changes only ACTION_COPY. The original WFM UI, directory +enumeration, move behavior, and delete behavior remain unchanged. diff --git a/src/file_actions.c b/src/file_actions.c index 4961edb..0f03c6e 100644 diff --git a/app/src/main/assets/wfm/replace-all-conflicts.patch b/app/src/main/assets/wfm/replace-all-conflicts.patch index 075ce6224b..80be99f9ef 100644 --- a/app/src/main/assets/wfm/replace-all-conflicts.patch +++ b/app/src/main/assets/wfm/replace-all-conflicts.patch @@ -1,11 +1,10 @@ -From 7df10c642efeaf5c4029d95f890c6c89643431f1 Mon Sep 17 00:00:00 2001 -From: Nightwalker743 -Date: Fri, 31 Jul 2026 00:13:24 -0500 +From: GameNative local compatibility build Subject: [PATCH] Offer replace-all policy on first copy conflict ---- - src/file_actions.c | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) +Apply after native-copy.patch. + +Offer Replace All, Review Each, or Cancel on the first file conflict and reuse +that policy for the rest of the paste operation. diff --git a/src/file_actions.c b/src/file_actions.c index 0f03c6e..45a2c60 100644 diff --git a/app/src/main/assets/wfm/wfm.exe b/app/src/main/assets/wfm/wfm.exe index a3389d2eb4b33822f803e59367b7463c5dd60747..2ff867bfcc7699d012d3e8ff873dfbf7cc5b9248 100644 GIT binary patch delta 20848 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 IxjXH@0G7*e-2eap diff --git a/app/src/main/java/app/gamenative/utils/WfmInstaller.kt b/app/src/main/java/app/gamenative/utils/WfmInstaller.kt index 0687dbc823..3a0b850cb0 100644 --- a/app/src/main/java/app/gamenative/utils/WfmInstaller.kt +++ b/app/src/main/java/app/gamenative/utils/WfmInstaller.kt @@ -23,7 +23,7 @@ object WfmInstaller { private val payloads = listOf( Payload( filename = "wfm.exe", - sha256 = "9c7799513a07730884fdc3b27f7b3168fd7fa5db764cc5f468f63c30b33e65e2", + sha256 = "a7bb48aa14c59ece23c011c43c8439869267b13387d4a972f462a06575deebbb", ), )