Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- .../api-ms-win-core-path-l1-1-0.spec | 2 +- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/path.c | 19 +++++ dlls/kernelbase/tests/path.c | 74 +++++++++++++++++++ include/pathcch.h | 1 + 5 files changed, 96 insertions(+), 2 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 fed23cbac1..57e0a67792 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 @@ -13,7 +13,7 @@ @ stub PathCchIsRoot @ stub PathCchRemoveBackslash @ stub PathCchRemoveBackslashEx -@ stub PathCchRemoveExtension +@ stdcall PathCchRemoveExtension(wstr long) kernelbase.PathCchRemoveExtension @ stub PathCchRemoveFileSpec @ stub PathCchRenameExtension @ stub PathCchSkipRoot diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 27d10ce731..ffe7be20df 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1042,7 +1042,7 @@ # @ stub PathCchIsRoot # @ stub PathCchRemoveBackslash # @ stub PathCchRemoveBackslashEx -# @ stub PathCchRemoveExtension +@ stdcall PathCchRemoveExtension(wstr long) # @ stub PathCchRemoveFileSpec # @ stub PathCchRenameExtension # @ stub PathCchSkipRoot diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 2ddc708f07..001c6828a6 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -151,3 +151,22 @@ HRESULT WINAPI PathCchFindExtension(const WCHAR *path, SIZE_T size, const WCHAR *extension = lastpoint ? lastpoint : path; return S_OK; } + +HRESULT WINAPI PathCchRemoveExtension(WCHAR *path, SIZE_T size) +{ + const WCHAR *extension; + WCHAR *next; + HRESULT hr; + + TRACE("%s %lu\n", wine_dbgstr_w(path), size); + + if (!path || !size || size > PATHCCH_MAX_CCH) return E_INVALIDARG; + + hr = PathCchFindExtension(path, size, &extension); + if (FAILED(hr)) return hr; + + next = path + (extension - path); + while (next - path < size && *next) *next++ = 0; + + return next == extension ? S_FALSE : S_OK; +} diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c index e6ead730d5..93579a8b3d 100644 --- a/dlls/kernelbase/tests/path.c +++ b/dlls/kernelbase/tests/path.c @@ -35,6 +35,7 @@ HRESULT (WINAPI *pPathCchAddBackslashEx)(WCHAR *out, SIZE_T size, WCHAR **endptr HRESULT (WINAPI *pPathCchAddExtension)(WCHAR *path, SIZE_T size, const WCHAR *extension); HRESULT (WINAPI *pPathCchCombineEx)(WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2, DWORD flags); HRESULT (WINAPI *pPathCchFindExtension)(const WCHAR *path, SIZE_T size, const WCHAR **extension); +HRESULT (WINAPI *pPathCchRemoveExtension)(WCHAR *path, SIZE_T size);
static const struct { @@ -447,6 +448,77 @@ static void test_PathCchFindExtension(void) } }
+struct removeextension_test +{ + const CHAR *path; + const CHAR *expected; + HRESULT hr; +}; + +static const struct removeextension_test removeextension_tests[] = +{ + {"1.exe", "1", S_OK}, + {"C:1.exe", "C:1", S_OK}, + {"C:\1.exe", "C:\1", S_OK}, + {"\1.exe", "\1", S_OK}, + {"\\1.exe", "\\1", S_OK}, + {"\\?\C:1.exe", "\\?\C:1", S_OK}, + {"\\?\C:\1.exe", "\\?\C:\1", S_OK}, + {"\\?\UNC\1.exe", "\\?\UNC\1", S_OK}, + {"\\?\UNC\192.168.1.1\1.exe", "\\?\UNC\192.168.1.1\1", S_OK}, + {"\\?\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\1.exe", + "\\?\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\1", S_OK}, + + /* Malformed */ + {"", "", S_FALSE}, + {" ", " ", S_FALSE}, + {".", "", S_OK}, + {"..", ".", S_OK}, + {"a", "a", S_FALSE}, + {"a.", "a", S_OK}, + {".a.b.", ".a.b", S_OK}, + {"a. ", "a. ", S_FALSE}, + {"a.\", "a.\", S_FALSE}, + {"\\?\UNC\192.168.1.1", "\\?\UNC\192.168.1", S_OK}, + {"\\?\UNC\192.168.1.1\", "\\?\UNC\192.168.1.1\", S_FALSE}, + {"\\?\UNC\192.168.1.1\a", "\\?\UNC\192.168.1.1\a", S_FALSE} +}; + +static void test_PathCchRemoveExtension(void) +{ + WCHAR pathW[PATHCCH_MAX_CCH] = {0}; + CHAR pathA[PATHCCH_MAX_CCH]; + HRESULT hr; + INT i; + + /* Arguments check */ + hr = pPathCchRemoveExtension(NULL, PATHCCH_MAX_CCH); + ok(hr == E_INVALIDARG, "expect %#x, got %#x\n", S_OK, hr); + + hr = pPathCchRemoveExtension(pathW, 0); + ok(hr == E_INVALIDARG, "expect %#x, got %#x\n", S_OK, hr); + + hr = pPathCchRemoveExtension(pathW, PATHCCH_MAX_CCH + 1); + ok(hr == E_INVALIDARG, "expect %#x, got %#x\n", S_OK, hr); + + hr = pPathCchRemoveExtension(pathW, PATHCCH_MAX_CCH); + ok(hr == S_FALSE, "expect %#x, got %#x\n", S_OK, hr); + + for (i = 0; i < ARRAY_SIZE(removeextension_tests); i++) + { + const struct removeextension_test *t = removeextension_tests + i; + + MultiByteToWideChar(CP_ACP, 0, t->path, -1, pathW, ARRAY_SIZE(pathW)); + hr = pPathCchRemoveExtension(pathW, ARRAY_SIZE(pathW)); + ok(hr == t->hr, "path %s expect result %#x, got %#x\n", t->path, t->hr, hr); + if (SUCCEEDED(hr)) + { + WideCharToMultiByte(CP_ACP, 0, pathW, -1, pathA, ARRAY_SIZE(pathA), NULL, NULL); + ok(!lstrcmpA(pathA, t->expected), "path %s expect stripped path %s, got %s\n", t->path, t->expected, pathA); + } + } +} + START_TEST(path) { HMODULE hmod = LoadLibraryA("kernelbase.dll"); @@ -461,10 +533,12 @@ START_TEST(path) pPathCchAddBackslashEx = (void *)GetProcAddress(hmod, "PathCchAddBackslashEx"); pPathCchAddExtension = (void *)GetProcAddress(hmod, "PathCchAddExtension"); pPathCchFindExtension = (void *)GetProcAddress(hmod, "PathCchFindExtension"); + pPathCchRemoveExtension = (void *)GetProcAddress(hmod, "PathCchRemoveExtension");
test_PathCchCombineEx(); test_PathCchAddBackslash(); test_PathCchAddBackslashEx(); test_PathCchAddExtension(); test_PathCchFindExtension(); + test_PathCchRemoveExtension(); } diff --git a/include/pathcch.h b/include/pathcch.h index 5a189bc0e7..2f125bb9ed 100644 --- a/include/pathcch.h +++ b/include/pathcch.h @@ -30,3 +30,4 @@ HRESULT WINAPI PathCchAddBackslashEx(WCHAR *path, SIZE_T size, WCHAR **end, SIZE HRESULT WINAPI PathCchAddExtension(WCHAR *path, SIZE_T size, const WCHAR *extension); HRESULT WINAPI PathCchCombineEx(WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2, DWORD flags); HRESULT WINAPI PathCchFindExtension(const WCHAR *path, SIZE_T size, const WCHAR **extension); +HRESULT WINAPI PathCchRemoveExtension(WCHAR *path, SIZE_T size);
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=44592
Your paranoid android.
=== w7u (32 bit report) ===
kernelbase: 0ce0:path: unhandled exception c0000005 at 00000000
=== w7pro64 (32 bit report) ===
kernelbase: 0aa8:path: unhandled exception c0000005 at 00000000
=== w7pro64 (64 bit report) ===
kernelbase: 0a7c:path: unhandled exception c0000005 at 0000000000000000