kernelbase: Implement PathCchStripPrefix.

Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Zhiyi Zhang 2018-11-22 14:46:29 +08:00 committed by Alexandre Julliard
parent c02419ed36
commit 2ec414c8a1
5 changed files with 111 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -44,6 +44,12 @@ static BOOL is_prefixed_unc(const WCHAR *string)
return !strncmpiW(string, prefixed_unc, ARRAY_SIZE(prefixed_unc));
}
static BOOL is_prefixed_disk(const WCHAR *string)
{
static const WCHAR prefix[] = {'\\', '\\', '?', '\\'};
return !strncmpW(string, prefix, ARRAY_SIZE(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;

View File

@ -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();
}

View File

@ -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);