From: yaoyongjie yaoyongjie@uniontech.com
In CopyFileEx, by default, the file name and path are limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, need prepend "\\?\" to the path. --- dlls/kernel32/tests/file.c | 8 ++++---- dlls/kernelbase/file.c | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 4b6fbbcf867..987faf7468f 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -953,12 +953,12 @@ static void test_CopyFileW(void) wcscat(long_path_1, long_name_1); SetLastError(0xdeadbeef); ret = CopyFileExW(source, long_path_1, NULL, NULL, NULL, 0); - todo_wine ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExW failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), wine_dbgstr_w(source), wine_dbgstr_w(long_path_1)); + ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExW failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), wine_dbgstr_w(source), wine_dbgstr_w(long_path_1)); wcscpy(long_path_2, temp_path); wcscat(long_path_2, long_name_2); SetLastError(0xdeadbeef); ret = CopyFileExW(long_path_1, long_path_2, NULL, NULL, NULL, 0); - todo_wine ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExW failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), wine_dbgstr_w(long_path_1), wine_dbgstr_w(long_path_2)); + ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExW failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), wine_dbgstr_w(long_path_1), wine_dbgstr_w(long_path_2)); ret = DeleteFileW(long_path_1); todo_wine ok(!ret, "Unexpected DeleteFileW successed\n"); ret = DeleteFileW(long_path_2); @@ -1286,12 +1286,12 @@ static void test_CopyFileEx(void) strcat(long_path_1, long_name_1); SetLastError(0xdeadbeef); retok = CopyFileExA(source, long_path_1, NULL, NULL, NULL, 0); - todo_wine ok(!retok && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExA failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), source, long_path_1); + ok(!retok && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExA failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), source, long_path_1); strcpy(long_path_2, temp_path); strcat(long_path_2, long_name_2); SetLastError(0xdeadbeef); retok = CopyFileExA(long_path_1, long_path_2, NULL, NULL, NULL, 0); - todo_wine ok(!retok && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExA failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), long_path_1, long_path_2); + ok(!retok && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExA failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), long_path_1, long_path_2); retok = DeleteFileA(long_path_1); todo_wine ok(!retok, "Unexpected DeleteFileA successed\n"); retok = DeleteFileA(long_path_2); diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index f0dedfe3b14..c3d87a84fd5 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -512,6 +512,18 @@ static BOOL copy_file( const WCHAR *source, const WCHAR *dest, COPYFILE2_EXTENDE SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } + + if (wcsncmp(source, L"\\?\", 4) && wcslen(source) >= MAX_PATH ) + { + SetLastError( ERROR_PATH_NOT_FOUND ); + return FALSE; + } + if (wcsncmp(dest, L"\\?\", 4) && wcslen(dest) >= MAX_PATH ) + { + SetLastError( ERROR_PATH_NOT_FOUND ); + return FALSE; + } + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size ))) { SetLastError( ERROR_NOT_ENOUGH_MEMORY );