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 87cfb7f7a8a..a98c48ccd7b 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -1059,13 +1059,13 @@ static void test_CopyFileW(void) wcscat(long_path_1, a); 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, b); 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"); @@ -1423,12 +1423,12 @@ static void test_CopyFileEx(void) strcat(long_path_1, a); 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, b); 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 7d8b6844456..0f70e28063f 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -527,6 +527,18 @@ static BOOL copy_file( const WCHAR *source, const WCHAR *dest, COPYFILE2_EXTENDE SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } + + if (wcslen(source) >= MAX_PATH && wcsncmp(source, L"\\?\", 4) && !RtlGetCurrentPeb()->IsLongPathAwareProcess) + { + SetLastError( ERROR_PATH_NOT_FOUND ); + return FALSE; + } + if (wcslen(dest) >= MAX_PATH && wcsncmp(dest, L"\\?\", 4) && !RtlGetCurrentPeb()->IsLongPathAwareProcess) + { + SetLastError( ERROR_PATH_NOT_FOUND ); + return FALSE; + } + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size ))) { SetLastError( ERROR_NOT_ENOUGH_MEMORY );