[PATCH 2/5] kernelbase: Implement PathCchStripPrefix.

Zhiyi Zhang zzhang at codeweavers.com
Thu Nov 22 00:46:29 CST 2018


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 .../api-ms-win-core-path-l1-1-0.spec          |  2 +-
 dlls/kernelbase/kernelbase.spec               |  2 +-
 dlls/kernelbase/path.c                        | 30 +++++++
 dlls/kernelbase/tests/path.c                  | 78 +++++++++++++++++++
 include/pathcch.h                             |  1 +
 5 files changed, 111 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 d874f8c802..53f7b987ca 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
@@ -17,6 +17,6 @@
 @ stub PathCchRemoveFileSpec
 @ stdcall PathCchRenameExtension(wstr long wstr) kernelbase.PathCchRenameExtension
 @ stub PathCchSkipRoot
-@ stub PathCchStripPrefix
+@ stdcall PathCchStripPrefix(wstr long) kernelbase.PathCchStripPrefix
 @ stub PathCchStripToRoot
 @ stdcall PathIsUNCEx(wstr ptr) kernelbase.PathIsUNCEx
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index b3b28872af..8f4136eb6b 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -1046,7 +1046,7 @@
 # @ stub PathCchRemoveFileSpec
 @ stdcall PathCchRenameExtension(wstr long wstr)
 # @ stub PathCchSkipRoot
-# @ stub PathCchStripPrefix
+@ stdcall PathCchStripPrefix(wstr long)
 # @ stub PathCchStripToRoot
 @ stdcall PathCombineA(ptr str str) shlwapi.PathCombineA
 @ stdcall PathCombineW(ptr wstr wstr) shlwapi.PathCombineW
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c
index 5f11e11962..366efa41e1 100644
--- a/dlls/kernelbase/path.c
+++ b/dlls/kernelbase/path.c
@@ -44,6 +44,12 @@ static BOOL is_prefixed_unc(const WCHAR *string)
     return !memicmpW(string, prefixed_unc, ARRAY_SIZE(prefixed_unc));
 }
 
+static BOOL is_prefixed_disk(const WCHAR *string)
+{
+    static const WCHAR prefix[] = {'\\', '\\', '?', '\\'};
+    return !memcmp(string, prefix, sizeof(prefix)) && isalphaW(string[4]) && string[5] == ':';
+}
+
 HRESULT WINAPI PathCchAddBackslash(WCHAR *path, SIZE_T size)
 {
     return PathCchAddBackslashEx(path, size, NULL, NULL);
@@ -190,6 +196,30 @@ HRESULT WINAPI PathCchRenameExtension(WCHAR *path, SIZE_T size, const WCHAR *ext
     return FAILED(hr) ? hr : S_OK;
 }
 
+HRESULT WINAPI PathCchStripPrefix(WCHAR *path, SIZE_T size)
+{
+    TRACE("%s %lu\n", wine_dbgstr_w(path), size);
+
+    if (!path || !size || size > PATHCCH_MAX_CCH) return E_INVALIDARG;
+
+    if (is_prefixed_unc(path))
+    {
+        /* \\?\UNC\a -> \\a */
+        if (size < strlenW(path + 8) + 3) return E_INVALIDARG;
+        strcpyW(path + 2, path + 8);
+        return S_OK;
+    }
+    else if (is_prefixed_disk(path))
+    {
+        /* \\?\C:\ -> C:\ */
+        if (size < strlenW(path + 4) + 1) return E_INVALIDARG;
+        strcpyW(path, path + 4);
+        return S_OK;
+    }
+    else
+        return S_FALSE;
+}
+
 BOOL WINAPI PathIsUNCEx(const WCHAR *path, const WCHAR **server)
 {
     const WCHAR *result = NULL;
diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c
index 8bd23191b0..af15e83d60 100644
--- a/dlls/kernelbase/tests/path.c
+++ b/dlls/kernelbase/tests/path.c
@@ -37,6 +37,7 @@ HRESULT (WINAPI *pPathCchCombineEx)(WCHAR *out, SIZE_T size, const WCHAR *path1,
 HRESULT (WINAPI *pPathCchFindExtension)(const WCHAR *path, SIZE_T size, const WCHAR **extension);
 HRESULT (WINAPI *pPathCchRemoveExtension)(WCHAR *path, SIZE_T size);
 HRESULT (WINAPI *pPathCchRenameExtension)(WCHAR *path, SIZE_T size, const WCHAR *extension);
+HRESULT (WINAPI *pPathCchStripPrefix)(WCHAR *path, SIZE_T size);
 BOOL    (WINAPI *pPathIsUNCEx)(const WCHAR *path, const WCHAR **server);
 
 static const struct
@@ -633,6 +634,81 @@ static void test_PathCchRenameExtension(void)
     }
 }
 
+struct stripprefix_test
+{
+    const CHAR *path;
+    const CHAR *stripped_path;
+    HRESULT hr;
+    SIZE_T size;
+};
+
+static const struct stripprefix_test stripprefix_tests[] =
+{
+    {"\\\\?\\UNC\\", "\\\\", S_OK},
+    {"\\\\?\\UNC\\a", "\\\\a", S_OK},
+    {"\\\\?\\C:", "C:", S_OK},
+    {"\\\\?\\C:\\", "C:\\", S_OK},
+    {"\\\\?\\C:\\a", "C:\\a", S_OK},
+    {"\\\\?\\unc\\", "\\\\", S_OK},
+    {"\\\\?\\c:\\", "c:\\", S_OK},
+
+    {"\\", "\\", S_FALSE},
+    {"\\\\", "\\\\", S_FALSE},
+    {"\\\\a", "\\\\a", S_FALSE},
+    {"\\\\a\\", "\\\\a\\", S_FALSE},
+    {"\\\\?\\a", "\\\\?\\a", S_FALSE},
+    {"\\\\?\\UNC", "\\\\?\\UNC", S_FALSE},
+    {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\",
+     "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_FALSE},
+
+    /* Size Tests */
+    {"C:\\", NULL, E_INVALIDARG, PATHCCH_MAX_CCH + 1},
+    {"C:\\", "C:\\", S_FALSE, PATHCCH_MAX_CCH},
+    /* Size < original path actual length + 1, read beyond size */
+    {"\\\\?\\C:\\", "C:\\", S_OK, ARRAY_SIZE("\\\\?\\C:\\") - 1},
+    /* Size < stripped path length + 1 */
+    {"\\\\?\\C:\\", NULL, E_INVALIDARG, ARRAY_SIZE("C:\\") - 1},
+    {"\\\\?\\UNC\\", NULL, E_INVALIDARG, ARRAY_SIZE("\\\\") - 1}
+};
+
+static void test_PathCchStripPrefix(void)
+{
+    WCHAR pathW[PATHCCH_MAX_CCH + 1] = {0};
+    CHAR stripped_pathA[PATHCCH_MAX_CCH];
+    SIZE_T size;
+    HRESULT hr;
+    INT i;
+
+    if (!pPathCchStripPrefix)
+    {
+        win_skip("PathCchStripPrefix(() is not available.\n");
+        return;
+    }
+
+    /* Null arguments */
+    hr = pPathCchStripPrefix(NULL, PATHCCH_MAX_CCH);
+    ok(hr == E_INVALIDARG, "expect %#x, got %#x\n", E_INVALIDARG, hr);
+
+    hr = pPathCchStripPrefix(pathW, 0);
+    ok(hr == E_INVALIDARG, "expect %#x, got %#x\n", E_INVALIDARG, hr);
+
+    for (i = 0; i < ARRAY_SIZE(stripprefix_tests); i++)
+    {
+        const struct stripprefix_test *t = stripprefix_tests + i;
+
+        MultiByteToWideChar(CP_ACP, 0, t->path, -1, pathW, ARRAY_SIZE(pathW));
+        size = t->size ? t->size : PATHCCH_MAX_CCH;
+        hr = pPathCchStripPrefix(pathW, size);
+        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, stripped_pathA, ARRAY_SIZE(stripped_pathA), NULL, NULL);
+            ok(!lstrcmpA(stripped_pathA, t->stripped_path), "path %s expect stripped path %s, got %s\n", t->path,
+               t->stripped_path, stripped_pathA);
+        }
+    }
+}
+
 struct isuncex_test
 {
     const CHAR *path;
@@ -713,6 +789,7 @@ START_TEST(path)
     pPathCchFindExtension = (void *)GetProcAddress(hmod, "PathCchFindExtension");
     pPathCchRemoveExtension = (void *)GetProcAddress(hmod, "PathCchRemoveExtension");
     pPathCchRenameExtension = (void *)GetProcAddress(hmod, "PathCchRenameExtension");
+    pPathCchStripPrefix = (void *)GetProcAddress(hmod, "PathCchStripPrefix");
     pPathIsUNCEx = (void *)GetProcAddress(hmod, "PathIsUNCEx");
 
     test_PathCchCombineEx();
@@ -722,5 +799,6 @@ START_TEST(path)
     test_PathCchFindExtension();
     test_PathCchRemoveExtension();
     test_PathCchRenameExtension();
+    test_PathCchStripPrefix();
     test_PathIsUNCEx();
 }
diff --git a/include/pathcch.h b/include/pathcch.h
index 6973d6dda2..1ff9e24648 100644
--- a/include/pathcch.h
+++ b/include/pathcch.h
@@ -32,4 +32,5 @@ HRESULT WINAPI PathCchCombineEx(WCHAR *out, SIZE_T size, const WCHAR *path1, con
 HRESULT WINAPI PathCchFindExtension(const WCHAR *path, SIZE_T size, const WCHAR **extension);
 HRESULT WINAPI PathCchRemoveExtension(WCHAR *path, SIZE_T size);
 HRESULT WINAPI PathCchRenameExtension(WCHAR *path, SIZE_T size, const WCHAR *extension);
+HRESULT WINAPI PathCchStripPrefix(WCHAR *path, SIZE_T size);
 BOOL    WINAPI PathIsUNCEx(const WCHAR *path, const WCHAR **server);
-- 
2.19.1





More information about the wine-devel mailing list