[PATCH 5/5] kernelbase: Implement PathCchIsRoot.
Zhiyi Zhang
zzhang at codeweavers.com
Thu Nov 22 00:47:09 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 | 38 ++++++++++
dlls/kernelbase/tests/path.c | 69 +++++++++++++++++++
include/pathcch.h | 1 +
5 files changed, 110 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 a09889f415..61eb22031e 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
@@ -10,7 +10,7 @@
@ stub PathCchCombine
@ stub PathCchCombineEx
@ stdcall PathCchFindExtension(wstr long ptr) kernelbase.PathCchFindExtension
-@ stub PathCchIsRoot
+@ stdcall PathCchIsRoot(wstr) kernelbase.PathCchIsRoot
@ stub PathCchRemoveBackslash
@ stub PathCchRemoveBackslashEx
@ stdcall PathCchRemoveExtension(wstr long) kernelbase.PathCchRemoveExtension
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index aefc63e54c..ffb5a95721 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -1039,7 +1039,7 @@
# @ stub PathCchCombine
# @ stub PathCchCombineEx
@ stdcall PathCchFindExtension(wstr long ptr)
-# @ stub PathCchIsRoot
+@ stdcall PathCchIsRoot(wstr)
# @ stub PathCchRemoveBackslash
# @ stub PathCchRemoveBackslashEx
@ stdcall PathCchRemoveExtension(wstr long)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c
index c59fba8d3e..ff8e0dddd1 100644
--- a/dlls/kernelbase/path.c
+++ b/dlls/kernelbase/path.c
@@ -242,6 +242,44 @@ HRESULT WINAPI PathCchFindExtension(const WCHAR *path, SIZE_T size, const WCHAR
return S_OK;
}
+BOOL WINAPI PathCchIsRoot(const WCHAR *path)
+{
+ const WCHAR *root_end;
+ const WCHAR *next;
+ BOOL is_unc;
+
+ TRACE("%s\n", wine_dbgstr_w(path));
+
+ if (!path || !*path) return FALSE;
+
+ root_end = get_root_end(path);
+ if (!root_end) return FALSE;
+
+ if ((is_unc = is_prefixed_unc(path)) || (path[0] == '\\' && path[1] == '\\' && path[2] != '?'))
+ {
+ next = root_end + 1;
+ /* No extra segments */
+ if ((is_unc && !*next) || (!is_unc && !*next)) return TRUE;
+
+ /* Has first segment with an ending backslash but no remaining characters */
+ if (get_next_segment(next, &next) && !*next) return FALSE;
+ /* Has first segment with no ending backslash */
+ else if (!*next)
+ return TRUE;
+ /* Has first segment with an ending backslash and has remaining characters*/
+ else
+ {
+ next++;
+ /* Second segment must have no backslash and no remaining characters */
+ return !get_next_segment(next, &next) && !*next;
+ }
+ }
+ else if (*root_end == '\\' && !root_end[1])
+ return TRUE;
+ else
+ return FALSE;
+}
+
HRESULT WINAPI PathCchRemoveExtension(WCHAR *path, SIZE_T size)
{
const WCHAR *extension;
diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c
index 5b47b84831..6d37bbf8ef 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);
+BOOL (WINAPI *pPathCchIsRoot)(const WCHAR *path);
HRESULT (WINAPI *pPathCchRemoveExtension)(WCHAR *path, SIZE_T size);
HRESULT (WINAPI *pPathCchRenameExtension)(WCHAR *path, SIZE_T size, const WCHAR *extension);
HRESULT (WINAPI *pPathCchSkipRoot)(const WCHAR *path, const WCHAR **root_end);
@@ -477,6 +478,72 @@ static void test_PathCchFindExtension(void)
}
}
+struct isroot_test
+{
+ const CHAR *path;
+ BOOL ret;
+};
+
+static const struct isroot_test isroot_tests[] =
+{
+ {"", FALSE},
+ {"a", FALSE},
+ {"C:", FALSE},
+ {"C:\\", TRUE},
+ {"C:\\a", FALSE},
+ {"\\\\?\\C:\\", TRUE},
+ {"\\\\?\\C:", FALSE},
+ {"\\\\?\\C:\\a", FALSE},
+ {"\\", TRUE},
+ {"\\a\\", FALSE},
+ {"\\a\\b", FALSE},
+ {"\\\\", TRUE},
+ {"\\\\a", TRUE},
+ {"\\\\a\\", FALSE},
+ {"\\\\a\\b", TRUE},
+ {"\\\\a\\b\\", FALSE},
+ {"\\\\a\\b\\c", FALSE},
+ {"\\\\?\\UNC\\", TRUE},
+ {"\\\\?\\UNC\\a", TRUE},
+ {"\\\\?\\UNC\\a\\", FALSE},
+ {"\\\\?\\UNC\\a\\b", TRUE},
+ {"\\\\?\\UNC\\a\\b\\", FALSE},
+ {"\\\\?\\UNC\\a\\b\\c", FALSE},
+ {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", FALSE},
+ {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", TRUE},
+ {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", FALSE},
+ {"..\\a", FALSE},
+
+ /* Wrong MSDN examples */
+ {"\\a", FALSE},
+ {"X:", FALSE},
+ {"\\server", FALSE}
+};
+
+static void test_PathCchIsRoot(void)
+{
+ WCHAR pathW[MAX_PATH];
+ BOOL ret;
+ INT i;
+
+ if (!pPathCchIsRoot)
+ {
+ win_skip("PathCchIsRoot() is not available.\n");
+ return;
+ }
+
+ ret = pPathCchIsRoot(NULL);
+ ok(ret == FALSE, "expect return FALSE\n");
+
+ for (i = 0; i < ARRAY_SIZE(isroot_tests); i++)
+ {
+ const struct isroot_test *t = isroot_tests + i;
+ MultiByteToWideChar(CP_ACP, 0, t->path, -1, pathW, ARRAY_SIZE(pathW));
+ ret = pPathCchIsRoot(pathW);
+ ok(ret == t->ret, "path %s expect return %d, got %d\n", t->path, t->ret, ret);
+ }
+}
+
struct removeextension_test
{
const CHAR *path;
@@ -1039,6 +1106,7 @@ START_TEST(path)
pPathCchAddBackslashEx = (void *)GetProcAddress(hmod, "PathCchAddBackslashEx");
pPathCchAddExtension = (void *)GetProcAddress(hmod, "PathCchAddExtension");
pPathCchFindExtension = (void *)GetProcAddress(hmod, "PathCchFindExtension");
+ pPathCchIsRoot = (void *)GetProcAddress(hmod, "PathCchIsRoot");
pPathCchRemoveExtension = (void *)GetProcAddress(hmod, "PathCchRemoveExtension");
pPathCchRenameExtension = (void *)GetProcAddress(hmod, "PathCchRenameExtension");
pPathCchSkipRoot = (void *)GetProcAddress(hmod, "PathCchSkipRoot");
@@ -1051,6 +1119,7 @@ START_TEST(path)
test_PathCchAddBackslashEx();
test_PathCchAddExtension();
test_PathCchFindExtension();
+ test_PathCchIsRoot();
test_PathCchRemoveExtension();
test_PathCchRenameExtension();
test_PathCchSkipRoot();
diff --git a/include/pathcch.h b/include/pathcch.h
index 56920b3444..443ccd3a4f 100644
--- a/include/pathcch.h
+++ b/include/pathcch.h
@@ -30,6 +30,7 @@ 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);
+BOOL WINAPI PathCchIsRoot(const WCHAR *path);
HRESULT WINAPI PathCchRemoveExtension(WCHAR *path, SIZE_T size);
HRESULT WINAPI PathCchRenameExtension(WCHAR *path, SIZE_T size, const WCHAR *extension);
HRESULT WINAPI PathCchSkipRoot(const WCHAR *path, const WCHAR **root_end);
--
2.19.1
More information about the wine-devel
mailing list