From: yaoyongjie yaoyongjie@uniontech.com
In CopyFileEx, and DeleteFile functions, 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 | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 68b9f53700e..7743b408bed 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -910,6 +910,10 @@ static void test_CopyFileW(void) WCHAR source[MAX_PATH], dest[MAX_PATH]; static const WCHAR prefix[] = {'p','f','x',0}; DWORD ret; + // long file name, 247 charactors + const WCHAR *long_name = L"e2345678lsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfie.txt"; + // long file path is %TEMP%/%long_name% + WCHAR long_dest[MAX_PATH * 2] = { 0 };
ret = GetTempPathW(MAX_PATH, temp_path); if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) @@ -942,6 +946,25 @@ static void test_CopyFileW(void) ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* some win8 machines */, "Unexpected error %lu.\n", GetLastError());
+ // test long file path, the length of the long_dest is larger than MAX_PATH. + wcscpy(long_dest, temp_path); + wcscat(long_dest, long_name); + SetLastError(0xdeadbeef); + ret = CopyFileExW(source, long_dest, NULL, NULL, NULL, 0); + 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_dest)); + ret = DeleteFileW(long_dest); + ok(!ret, "Unexpected DeleteFileW successed\n"); + + // test long file name prepend "\?" + wcscpy(long_dest, L"\\?\"); + wcscat(long_dest, temp_path); + wcscat(long_dest, long_name); + SetLastError(0xdeadbeef); + ret = CopyFileExW(source, long_dest, NULL, NULL, NULL, 0); + ok(ret, "CopyFileExW failed, got %ld, copy %s -> %s failed\n", GetLastError(), wine_dbgstr_w(source), wine_dbgstr_w(long_dest)); + + ret = DeleteFileW(long_dest); + ok(ret, "DeleteFileW: error %ld\n", GetLastError()); ret = DeleteFileW(source); ok(ret, "DeleteFileW: error %ld\n", GetLastError()); ret = DeleteFileW(dest); @@ -1194,6 +1217,10 @@ static void test_CopyFileEx(void) HANDLE hfile; DWORD ret; BOOL retok; + // long file name, 247 charactors + const char *long_name = "d2345678lsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfielfelfjellsfalfielsfleflsfie.txt"; + // long file path is %TEMP%/%long_name% + char long_dest[MAX_PATH * 2];
ret = GetTempPathA(MAX_PATH, temp_path); ok(ret != 0, "GetTempPathA error %ld\n", GetLastError()); @@ -1235,6 +1262,25 @@ static void test_CopyFileEx(void) ok(!retok, "CopyFileExA unexpectedly succeeded\n"); ok(GetLastError() == ERROR_PATH_NOT_FOUND, "expected ERROR_PATH_NOT_FOUND, got %ld\n", GetLastError());
+ // test long file path, the length of the long_dest is larger than MAX_PATH. + strcpy(long_dest, temp_path); + strcat(long_dest, long_name); + SetLastError(0xdeadbeef); + retok = CopyFileExA(source, long_dest, NULL, NULL, NULL, 0); + ok(!retok && GetLastError() == ERROR_PATH_NOT_FOUND, "Expected CopyFileExW failed with ERROR_PATH_NOT_FOUND, but got %ld, copy %s -> %s\n", GetLastError(), source, long_dest); + retok = DeleteFileA(long_dest); + ok(!retok, "Unexpected DeleteFileA successed\n"); + + // test long file name prepend "\?" + strcpy(long_dest, "\\?\"); + strcat(long_dest, temp_path); + strcat(long_dest, long_name); + SetLastError(0xdeadbeef); + retok = CopyFileExA(source, long_dest, NULL, NULL, NULL, 0); + ok(retok, "CopyFileExA failed, got %ld, copy %s -> %s failed\n", GetLastError(), source, long_dest); + + ret = DeleteFileA(long_dest); + ok(ret, "DeleteFileA failed with error %ld\n", GetLastError()); ret = DeleteFileA(source); ok(ret, "DeleteFileA failed with error %ld\n", GetLastError()); ret = DeleteFileA(dest);