From: Thomas Csovcsity <thc.fr13nd@gmail.com> --- dlls/kernelbase/path.c | 63 ++++++++++++++++++++++----------------- dlls/shlwapi/tests/path.c | 10 +++---- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index ece259ebe7b..bd7c96bf6dc 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -1280,15 +1280,15 @@ BOOL WINAPI PathCanonicalizeW(WCHAR *buffer, const WCHAR *path) TRACE("%p, %s\n", buffer, wine_dbgstr_w(path)); - if (dst) - *dst = '\0'; - if (!dst || !path) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } + if (dst) + *dst = '\0'; + if (!*path) { *buffer++ = '\\'; @@ -1315,42 +1315,51 @@ BOOL WINAPI PathCanonicalizeW(WCHAR *buffer, const WCHAR *path) { if (*src == '.') { + /* Skip './' if at beginning of path and always ':./', '/./' */ if (src[1] == '\\' && (src == path || src[-1] == '\\' || src[-1] == ':')) { src += 2; /* Skip .\ */ } - else if (src[1] == '.' && dst != buffer && dst[-1] == '\\') + else if ( src[1] == '.' && src[2] != '.' ) { - /* \.. backs up a directory, over the root if it has no \ following X:. - * .. is ignored if it would remove a UNC server name or initial \\ - */ - if (dst != buffer) + if (dst != buffer && dst[-1] == '\\') { - *dst = '\0'; /* Allow PathIsUNCServerShareA test on lpszBuf */ - if (dst > buffer + 1 && dst[-1] == '\\' && (dst[-2] != '\\' || dst > buffer + 2)) + /* \.. backs up a directory, over the root if it has no \ following X:. + * .. is ignored if it would remove a UNC server name or initial \\ + */ + if (dst != buffer) { - if (dst[-2] == ':' && (dst > buffer + 3 || dst[-3] == ':')) + *dst = '\0'; /* Allow PathIsUNCServerShareA test on lpszBuf */ + if ((src[2] == '\\' || src[2] == ':' || src[2] == '\0' ) && dst > buffer + 1 && dst[-1] == '\\' && (dst[-2] != '\\' || dst > buffer + 2)) { - dst -= 2; - while (dst > buffer && *dst != '\\') - dst--; - if (*dst == '\\') - dst++; /* Reset to last '\' */ - else - dst = buffer; /* Start path again from new root */ + if (dst[-2] == ':' && (dst > buffer + 3 || dst[-3] == ':')) + { + dst -= 2; + while (dst > buffer && *dst != '\\') + dst--; + if (*dst == '\\') + dst++; /* Reset to last '\' */ + else + dst = buffer; /* Start path again from new root */ + } + else if (dst[-2] != ':' && !PathIsUNCServerShareW(buffer)) { + dst -= 2; + } + } + while (dst > buffer && *dst != '\\') + dst--; + if (dst == buffer) + { + *dst++ = '\\'; + src++; } - else if (dst[-2] != ':' && !PathIsUNCServerShareW(buffer)) - dst -= 2; } - while (dst > buffer && *dst != '\\') - dst--; - if (dst == buffer) - { + if (*dst != '\\') *dst++ = '\\'; - src++; - } + src += 2; /* Skip .. in src path */ } - src += 2; /* Skip .. in src path */ + else + *dst++ = *src++; } else *dst++ = *src++; diff --git a/dlls/shlwapi/tests/path.c b/dlls/shlwapi/tests/path.c index fc09db9cd6c..4d32948db23 100644 --- a/dlls/shlwapi/tests/path.c +++ b/dlls/shlwapi/tests/path.c @@ -706,7 +706,7 @@ static void test_PathCombineA(void) lstrcpyA(dest, "control"); str = PathCombineA(dest, "C:\\", "...xx"); ok(str == dest, "Expected str == dest, got %p\n", str); - todo_wine ok(!lstrcmpA(str, "C:\\...xx"), "Expected C:\\...xx, got %s\n", str); + ok(!lstrcmpA(str, "C:\\...xx"), "Expected C:\\...xx, got %s\n", str); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError()); /* try relative paths */ @@ -1102,7 +1102,7 @@ static void test_PathCanonicalizeA(void) res = PathCanonicalizeA(dest, "C:\\...x"); ok(res, "Expected success\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError()); - todo_wine ok(!lstrcmpA(dest, "C:\\...x"), "C:\\...x, got %s\n", dest); + ok(!lstrcmpA(dest, "C:\\...x"), "C:\\...x, got %s\n", dest); /* try C:\test\...x */ memset(dest, 0, LONG_LEN + MAX_PATH); @@ -1111,7 +1111,7 @@ static void test_PathCanonicalizeA(void) res = PathCanonicalizeA(dest, "C:\\test\\...x"); ok(res, "Expected success\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError()); - todo_wine ok(!lstrcmpA(dest, "C:\\test\\...x"), "C:\\test\\...x, got %s\n", dest); + ok(!lstrcmpA(dest, "C:\\test\\...x"), "C:\\test\\...x, got %s\n", dest); /* try C:\test\...\x */ memset(dest, 0, LONG_LEN + MAX_PATH); @@ -1120,7 +1120,7 @@ static void test_PathCanonicalizeA(void) res = PathCanonicalizeA(dest, "C:\\test\\...\\x"); ok(res, "Expected success\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError()); - todo_wine ok(!lstrcmpA(dest, "C:\\test\\...\\x"), "C:\\test\\...\\x, got %s\n", dest); + ok(!lstrcmpA(dest, "C:\\test\\...\\x"), "C:\\test\\...\\x, got %s\n", dest); /* try C:\test\...\x */ memset(dest, 0, LONG_LEN + MAX_PATH); @@ -1129,7 +1129,7 @@ static void test_PathCanonicalizeA(void) res = PathCanonicalizeA(dest, "C:\\test\\....\\x"); ok(res, "Expected success\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError()); - todo_wine ok(!lstrcmpA(dest, "C:\\test\\....\\x"), "C:\\test\\....\\x, got %s\n", dest); + ok(!lstrcmpA(dest, "C:\\test\\....\\x"), "C:\\test\\....\\x, got %s\n", dest); /* try C:\\..\\something */ memset(dest, 0, LONG_LEN + MAX_PATH); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9414