From 0dc009c4320a9cb72dc96bb60bd55970cf6d4345 Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Wed, 4 Jul 2018 22:35:16 +0200 Subject: [PATCH] kernelbase: Implement PathCchRemoveBackslash()/PathCchRemoveBackslashEx(). --- .../api-ms-win-core-path-l1-1-0.spec | 4 +- dlls/kernelbase/kernelbase.spec | 4 +- dlls/kernelbase/path.c | 31 +++++ dlls/kernelbase/tests/path.c | 127 ++++++++++++++++++ include/pathcch.h | 2 + 5 files changed, 164 insertions(+), 4 deletions(-) diff --git a/dlls/api-ms-win-core-path-l1-1-0/api-ms-win-core-path-l1-1-0.spec b/dlls/api-ms-win-core-path-l1-1-0/api-ms-win-core-path-l1-1-0.spec index 9895b1b8e23..591ee7d882f 100644 --- a/dlls/api-ms-win-core-path-l1-1-0/api-ms-win-core-path-l1-1-0.spec +++ b/dlls/api-ms-win-core-path-l1-1-0/api-ms-win-core-path-l1-1-0.spec @@ -11,8 +11,8 @@ @ stdcall PathCchCombineEx(ptr long ptr ptr long) kernelbase.PathCchCombineEx @ stub PathCchFindExtension @ stub PathCchIsRoot -@ stub PathCchRemoveBackslash -@ stub PathCchRemoveBackslashEx +@ stdcall PathCchRemoveBackslash(wstr long) kernelbase.PathCchRemoveBackslash +@ stdcall PathCchRemoveBackslashEx(wstr long ptr ptr) kernelbase.PathCchRemoveBackslashEx @ stub PathCchRemoveExtension @ stub PathCchRemoveFileSpec @ stub PathCchRenameExtension diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 1f75b080378..c4a75bc1694 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1040,8 +1040,8 @@ @ stdcall PathCchCombineEx(ptr long ptr ptr long) # @ stub PathCchFindExtension # @ stub PathCchIsRoot -# @ stub PathCchRemoveBackslash -# @ stub PathCchRemoveBackslashEx +@ stdcall PathCchRemoveBackslash(wstr long) +@ stdcall PathCchRemoveBackslashEx(wstr long ptr ptr) # @ stub PathCchRemoveExtension # @ stub PathCchRemoveFileSpec # @ stub PathCchRenameExtension diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 52ef7d97654..3113bfe1255 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -91,3 +91,34 @@ HRESULT WINAPI PathCchCombineEx(WCHAR *out, SIZE_T size, const WCHAR *path1, con strcpyW(out, result); return S_OK; } + +HRESULT WINAPI PathCchRemoveBackslash(WCHAR *path, SIZE_T size) +{ + return PathCchRemoveBackslashEx(path, size, NULL, NULL); +} + +HRESULT WINAPI PathCchRemoveBackslashEx(WCHAR *path, SIZE_T size, WCHAR **endptr, SIZE_T *remaining) +{ + BOOL needs_trim; + SIZE_T length; + + TRACE("%s, %lu, %p, %p\n", debugstr_w(path), size, endptr, remaining); + + if (!path) return E_INVALIDARG; + length = strlenW(path); + needs_trim = size && length && path[length - 1] == '\\'; + + if (needs_trim && (length > 1) && path[length - 2] == ':') + needs_trim = 0; + + if (needs_trim) + { + path[length - 1] = 0; + --length; + } + + if (endptr) *endptr = path + length; + if (remaining) *remaining = size - length; + + return needs_trim ? S_OK : S_FALSE; +} diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c index cdba51bf3f6..20f8852faca 100644 --- a/dlls/kernelbase/tests/path.c +++ b/dlls/kernelbase/tests/path.c @@ -31,6 +31,8 @@ HRESULT (WINAPI *pPathCchAddBackslash)(WCHAR *out, SIZE_T size); HRESULT (WINAPI *pPathCchAddBackslashEx)(WCHAR *out, SIZE_T size, WCHAR **endptr, SIZE_T *remaining); +HRESULT (WINAPI *pPathCchRemoveBackslash)(WCHAR *out, SIZE_T size); +HRESULT (WINAPI *pPathCchRemoveBackslashEx)(WCHAR *out, SIZE_T size, WCHAR **endptr, SIZE_T *remaining); HRESULT (WINAPI *pPathCchCombineEx)(WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2, DWORD flags); static const struct @@ -245,6 +247,127 @@ static void test_PathCchAddBackslashEx(void) } } +struct removebackslash_test +{ + const char *path; + const char *result; + HRESULT hr; + SIZE_T size; + SIZE_T remaining; +}; + +static const struct removebackslash_test removebackslash_tests[] = +{ + { "C:\\", "C:\\", S_FALSE, MAX_PATH, MAX_PATH - 3 }, + { "a.txt\\", "a.txt", S_OK, MAX_PATH, MAX_PATH - 5 }, + { "a/b\\", "a/b", S_OK, MAX_PATH, MAX_PATH - 3 }, + { "C:\\temp\\wine.txt", "C:\\temp\\wine.txt", S_FALSE, MAX_PATH, MAX_PATH - 16 }, +}; + +static void test_PathCchRemoveBackslash(void) +{ + WCHAR pathW[MAX_PATH]; + unsigned int i; + HRESULT hr; + + if (!pPathCchRemoveBackslash) + { + win_skip("PathCchRemoveBackslash() is not available.\n"); + return; + } + + pathW[0] = 0; + hr = pPathCchRemoveBackslash(0, 0); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + ok(pathW[0] == 0, "Unexpected path.\n"); + + pathW[0] = 0; + hr = pPathCchRemoveBackslash(pathW, 1); + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + ok(pathW[0] == 0, "Unexpected path.\n"); + + pathW[0] = 0; + hr = pPathCchRemoveBackslash(pathW, 2); + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + ok(pathW[0] == 0, "Unexpected path.\n"); + + for (i = 0; i < ARRAY_SIZE(removebackslash_tests); i++) + { + const struct removebackslash_test *test = &removebackslash_tests[i]; + char path[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, test->path, -1, pathW, ARRAY_SIZE(pathW)); + hr = pPathCchRemoveBackslash(pathW, test->size); + ok(hr == test->hr, "%u: unexpected return value %#x.\n", i, hr); + + WideCharToMultiByte(CP_ACP, 0, pathW, -1, path, ARRAY_SIZE(path), NULL, NULL); + ok(!strcmp(path, test->result), "%u: unexpected resulting path %s.\n", i, path); + } +} + +static void test_PathCchRemoveBackslashEx(void) +{ + WCHAR pathW[MAX_PATH]; + SIZE_T remaining; + unsigned int i; + HRESULT hr; + WCHAR *ptrW; + + if (!pPathCchRemoveBackslashEx) + { + win_skip("PathCchRemoveBackslashEx() is not available.\n"); + return; + } + + pathW[0] = 0; + hr = pPathCchRemoveBackslashEx(0, 0, NULL, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + ok(pathW[0] == 0, "Unexpected path.\n"); + + pathW[0] = 0; + ptrW = (void *)0xdeadbeef; + remaining = 123; + hr = pPathCchRemoveBackslashEx(pathW, 1, &ptrW, &remaining); + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + ok(pathW[0] == 0, "Unexpected path.\n"); + ok(ptrW == pathW, "Unexpected endptr %p.\n", ptrW); + ok(remaining == 1, "Unexpected remaining size.\n"); + + pathW[0] = 0; + hr = pPathCchRemoveBackslashEx(pathW, 2, NULL, NULL); + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + ok(pathW[0] == 0, "Unexpected path.\n"); + + for (i = 0; i < ARRAY_SIZE(removebackslash_tests); i++) + { + const struct removebackslash_test *test = &removebackslash_tests[i]; + char path[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, test->path, -1, pathW, ARRAY_SIZE(pathW)); + hr = pPathCchRemoveBackslashEx(pathW, test->size, NULL, NULL); + ok(hr == test->hr, "%u: unexpected return value %#x.\n", i, hr); + + WideCharToMultiByte(CP_ACP, 0, pathW, -1, path, ARRAY_SIZE(path), NULL, NULL); + ok(!strcmp(path, test->result), "%u: unexpected resulting path %s.\n", i, path); + + ptrW = (void *)0xdeadbeef; + remaining = 123; + MultiByteToWideChar(CP_ACP, 0, test->path, -1, pathW, ARRAY_SIZE(pathW)); + hr = pPathCchRemoveBackslashEx(pathW, test->size, &ptrW, &remaining); + ok(hr == test->hr, "%u: unexpected return value %#x.\n", i, hr); + if (SUCCEEDED(hr)) + { + ok(ptrW == (pathW + lstrlenW(pathW)), "%u: unexpected end pointer.\n", i); + ok(remaining == test->remaining, "%u: unexpected remaining buffer length.\n", i); + } + else + { + ok(ptrW == NULL, "%u: unexpecred end pointer.\n", i); + ok(remaining == 0, "%u: unexpected remaining buffer length.\n", i); + } + } +} + START_TEST(path) { HMODULE hmod = LoadLibraryA("kernelbase.dll"); @@ -252,8 +375,12 @@ START_TEST(path) pPathCchCombineEx = (void *)GetProcAddress(hmod, "PathCchCombineEx"); pPathCchAddBackslash = (void *)GetProcAddress(hmod, "PathCchAddBackslash"); pPathCchAddBackslashEx = (void *)GetProcAddress(hmod, "PathCchAddBackslashEx"); + pPathCchRemoveBackslash = (void *)GetProcAddress(hmod, "PathCchRemoveBackslash"); + pPathCchRemoveBackslashEx = (void *)GetProcAddress(hmod, "PathCchRemoveBackslashEx"); test_PathCchCombineEx(); test_PathCchAddBackslash(); test_PathCchAddBackslashEx(); + test_PathCchRemoveBackslash(); + test_PathCchRemoveBackslashEx(); } diff --git a/include/pathcch.h b/include/pathcch.h index 2b2aed4c8f9..c19ed1d9306 100644 --- a/include/pathcch.h +++ b/include/pathcch.h @@ -25,4 +25,6 @@ HRESULT WINAPI PathCchAddBackslash(WCHAR *path, SIZE_T size); HRESULT WINAPI PathCchAddBackslashEx(WCHAR *path, SIZE_T size, WCHAR **end, SIZE_T *remaining); +HRESULT WINAPI PathCchRemoveBackslash(WCHAR *path, SIZE_T size); +HRESULT WINAPI PathCchRemoveBackslashEx(WCHAR *path, SIZE_T size, WCHAR **end, SIZE_T *remaining); HRESULT WINAPI PathCchCombineEx(WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2, DWORD flags); -- 2.18.0