winehq.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
January
2003
December
November
October
September
August
July
June
May
April
March
February
January
2002
December
November
October
September
August
July
June
May
April
March
February
January
2001
December
November
October
September
August
July
June
May
April
March
February
List overview
wine-commits
November 2018
----- 2025 -----
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
January 2004
----- 2003 -----
December 2003
November 2003
October 2003
September 2003
August 2003
July 2003
June 2003
May 2003
April 2003
March 2003
February 2003
January 2003
----- 2002 -----
December 2002
November 2002
October 2002
September 2002
August 2002
July 2002
June 2002
May 2002
April 2002
March 2002
February 2002
January 2002
----- 2001 -----
December 2001
November 2001
October 2001
September 2001
August 2001
July 2001
June 2001
May 2001
April 2001
March 2001
February 2001
wine-commits@winehq.org
2 participants
951 discussions
Start a n
N
ew thread
Nikolay Sivov : dwrite: Add support for memory font resources in CreateFontFaceFromHdc().
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: a0c8f066d402f163c95ee38b940e2533371530a4 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=a0c8f066d402f163c95ee38b…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Thu Nov 22 14:29:14 2018 +0300 dwrite: Add support for memory font resources in CreateFontFaceFromHdc(). Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/dwrite/gdiinterop.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++- dlls/dwrite/tests/font.c | 71 +++++++++++++++-- 2 files changed, 261 insertions(+), 10 deletions(-) Diff:
https://source.winehq.org/git/wine.git/?a=commitdiff;h=a0c8f066d402f163c95e…
1
0
0
0
Zhiyi Zhang : kernelbase: Implement PathCchIsRoot.
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: 5d31184dff1a99a4530713d6e3a40439ad4832f8 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=5d31184dff1a99a4530713d6…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Thu Nov 22 14:47:09 2018 +0800 kernelbase: Implement PathCchIsRoot. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- .../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 a09889f..61eb220 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 aefc63e..ffb5a95 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 88990d1..75faf0b 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -240,6 +240,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 1cbeb8b..2edd49b 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 56920b3..443ccd3 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);
1
0
0
0
Zhiyi Zhang : kernelbase: Implement PathCchStripToRoot.
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: 2afa87bc0c72e3a81cd5845deb1bb84cf2437ffa URL:
https://source.winehq.org/git/wine.git/?a=commit;h=2afa87bc0c72e3a81cd5845d…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Thu Nov 22 14:46:53 2018 +0800 kernelbase: Implement PathCchStripToRoot. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- .../api-ms-win-core-path-l1-1-0.spec | 2 +- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/path.c | 39 +++++++ dlls/kernelbase/tests/path.c | 128 +++++++++++++++++++++ include/pathcch.h | 1 + 5 files changed, 170 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 e07fe02..a09889f 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 @@ -18,5 +18,5 @@ @ stdcall PathCchRenameExtension(wstr long wstr) kernelbase.PathCchRenameExtension @ stdcall PathCchSkipRoot(wstr ptr) kernelbase.PathCchSkipRoot @ stdcall PathCchStripPrefix(wstr long) kernelbase.PathCchStripPrefix -@ stub PathCchStripToRoot +@ stdcall PathCchStripToRoot(wstr long) kernelbase.PathCchStripToRoot @ stdcall PathIsUNCEx(wstr ptr) kernelbase.PathIsUNCEx diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index eae67be..aefc63e 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1047,7 +1047,7 @@ @ stdcall PathCchRenameExtension(wstr long wstr) @ stdcall PathCchSkipRoot(wstr ptr) @ stdcall PathCchStripPrefix(wstr long) -# @ stub PathCchStripToRoot +@ stdcall PathCchStripToRoot(wstr long) @ stdcall PathCombineA(ptr str str) shlwapi.PathCombineA @ stdcall PathCombineW(ptr wstr wstr) shlwapi.PathCombineW @ stdcall PathCommonPrefixA(str str ptr) shlwapi.PathCommonPrefixA diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 0b1eb91..88990d1 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -328,6 +328,45 @@ HRESULT WINAPI PathCchStripPrefix(WCHAR *path, SIZE_T size) return S_FALSE; } +HRESULT WINAPI PathCchStripToRoot(WCHAR *path, SIZE_T size) +{ + const WCHAR *root_end; + WCHAR *segment_end; + BOOL is_unc; + + TRACE("%s %lu\n", wine_dbgstr_w(path), size); + + if (!path || !*path || !size || size > PATHCCH_MAX_CCH) return E_INVALIDARG; + + /* \\\\?\\UNC\\* and \\\\* have to have at least two extra segments to be striped, + * e.g. \\\\?\\UNC\\a\\b\\c -> \\\\?\\UNC\\a\\b + * \\\\a\\b\\c -> \\\\a\\b */ + if ((is_unc = is_prefixed_unc(path)) || (path[0] == '\\' && path[1] == '\\' && path[2] != '?')) + { + root_end = is_unc ? path + 8 : path + 3; + if (!get_next_segment(root_end, &root_end)) return S_FALSE; + if (!get_next_segment(root_end, &root_end)) return S_FALSE; + + if (root_end - path >= size) return E_INVALIDARG; + + segment_end = path + (root_end - path) - 1; + *segment_end = 0; + return S_OK; + } + else if (PathCchSkipRoot(path, &root_end) == S_OK) + { + if (root_end - path >= size) return E_INVALIDARG; + + segment_end = path + (root_end - path); + if (!*segment_end) return S_FALSE; + + *segment_end = 0; + return S_OK; + } + else + return E_INVALIDARG; +} + 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 c4499cc..1cbeb8b 100644 --- a/dlls/kernelbase/tests/path.c +++ b/dlls/kernelbase/tests/path.c @@ -39,6 +39,7 @@ 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); HRESULT (WINAPI *pPathCchStripPrefix)(WCHAR *path, SIZE_T size); +HRESULT (WINAPI *pPathCchStripToRoot)(WCHAR *path, SIZE_T size); BOOL (WINAPI *pPathIsUNCEx)(const WCHAR *path, const WCHAR **server); static const struct @@ -835,6 +836,131 @@ static void test_PathCchStripPrefix(void) } } +struct striptoroot_test +{ + const CHAR *path; + const CHAR *root; + HRESULT hr; + SIZE_T size; +}; + +static const struct striptoroot_test striptoroot_tests[] = +{ + /* Invalid */ + {"", "", E_INVALIDARG}, + {"C", NULL, E_INVALIDARG}, + {"\\\\?\\UNC", NULL, E_INVALIDARG}, + + /* Size */ + {"C:\\", NULL, E_INVALIDARG, PATHCCH_MAX_CCH + 1}, + {"C:\\", "C:\\", S_FALSE, PATHCCH_MAX_CCH}, + /* Size < original path length + 1, read beyond size */ + {"C:\\a", "C:\\", S_OK, ARRAY_SIZE("C:\\a") - 1}, + /* Size < stripped path length + 1 */ + {"C:\\a", "C:\\", E_INVALIDARG, ARRAY_SIZE("C:\\") - 1}, + {"\\\\a\\b\\c", NULL, E_INVALIDARG, ARRAY_SIZE("\\\\a\\b") - 1}, + + /* X: */ + {"C:", "C:", S_FALSE}, + {"C:a", "C:", S_OK}, + {"C:a\\b", "C:", S_OK}, + {"C:a\\b\\c", "C:", S_OK}, + + /* X:\ */ + {"C:\\", "C:\\", S_FALSE}, + {"C:\\a", "C:\\", S_OK}, + {"C:\\a\\b", "C:\\", S_OK}, + {"C:\\a\\b\\c", "C:\\", S_OK}, + + /* \ */ + {"\\", "\\", S_FALSE}, + {"\\a", "\\", S_OK}, + {"\\a\\b", "\\", S_OK}, + {"\\a\\b\\c", "\\", S_OK}, + + /* \\ */ + {"\\\\", "\\\\", S_FALSE}, + {"\\\\a", "\\\\a", S_FALSE}, + {"\\\\a\\b", "\\\\a\\b", S_FALSE}, + {"\\\\a\\b\\c", "\\\\a\\b", S_OK}, + + /* UNC */ + {"\\\\?\\UNC\\", "\\\\?\\UNC\\", S_FALSE}, + {"\\\\?\\UNC\\a", "\\\\?\\UNC\\a", S_FALSE}, + {"\\\\?\\UNC\\a\\b", "\\\\?\\UNC\\a\\b", S_FALSE}, + {"\\\\?\\UNC\\a\\b\\", "\\\\?\\UNC\\a\\b", S_OK}, + {"\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\b", S_OK}, + + /* Prefixed X: */ + {"\\\\?\\C:", "\\\\?\\C:", S_FALSE}, + {"\\\\?\\C:a", "\\\\?\\C:", S_OK}, + {"\\\\?\\C:a\\b", "\\\\?\\C:", S_OK}, + {"\\\\?\\C:a\\b\\c", "\\\\?\\C:", S_OK}, + + /* Prefixed X:\ */ + {"\\\\?\\C:\\", "\\\\?\\C:\\", S_FALSE}, + {"\\\\?\\C:\\a", "\\\\?\\C:\\", S_OK}, + {"\\\\?\\C:\\a\\b", "\\\\?\\C:\\", S_OK}, + {"\\\\?\\C:\\a\\b\\c", "\\\\?\\C:\\", S_OK}, + + /* UNC Volume */ + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_FALSE}, + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_OK}, + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a\\b", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_OK}, + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a\\b\\c", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_OK}, + + /* UNC Volume with backslash */ + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_FALSE}, + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_OK}, + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\b", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_OK}, + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\b\\c", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_OK}, +}; + +static void test_PathCchStripToRoot(void) +{ + WCHAR pathW[PATHCCH_MAX_CCH]; + CHAR rootA[PATHCCH_MAX_CCH]; + SIZE_T size; + HRESULT hr; + INT i; + + if (!pPathCchStripToRoot) + { + win_skip("PathCchStripToRoot() is not available.\n"); + return; + } + + /* Null arguments */ + hr = pPathCchStripToRoot(NULL, ARRAY_SIZE(pathW)); + ok(hr == E_INVALIDARG, "Expect result %#x, got %#x\n", E_INVALIDARG, hr); + + MultiByteToWideChar(CP_ACP, 0, "C:\\a", -1, pathW, ARRAY_SIZE(pathW)); + hr = pPathCchStripToRoot(pathW, 0); + ok(hr == E_INVALIDARG, "Expect result %#x, got %#x\n", E_INVALIDARG, hr); + + for (i = 0; i < ARRAY_SIZE(striptoroot_tests); i++) + { + const struct striptoroot_test *t = striptoroot_tests + i; + MultiByteToWideChar(CP_ACP, 0, t->path, -1, pathW, ARRAY_SIZE(pathW)); + size = t->size ? t->size : ARRAY_SIZE(pathW); + hr = pPathCchStripToRoot(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, rootA, ARRAY_SIZE(rootA), NULL, NULL); + ok(!lstrcmpA(rootA, t->root), "path %s expect stripped path %s, got %s\n", t->path, t->root, rootA); + } + } +} + struct isuncex_test { const CHAR *path; @@ -917,6 +1043,7 @@ START_TEST(path) pPathCchRenameExtension = (void *)GetProcAddress(hmod, "PathCchRenameExtension"); pPathCchSkipRoot = (void *)GetProcAddress(hmod, "PathCchSkipRoot"); pPathCchStripPrefix = (void *)GetProcAddress(hmod, "PathCchStripPrefix"); + pPathCchStripToRoot = (void *)GetProcAddress(hmod, "PathCchStripToRoot"); pPathIsUNCEx = (void *)GetProcAddress(hmod, "PathIsUNCEx"); test_PathCchCombineEx(); @@ -928,5 +1055,6 @@ START_TEST(path) test_PathCchRenameExtension(); test_PathCchSkipRoot(); test_PathCchStripPrefix(); + test_PathCchStripToRoot(); test_PathIsUNCEx(); } diff --git a/include/pathcch.h b/include/pathcch.h index 42bae4e..56920b3 100644 --- a/include/pathcch.h +++ b/include/pathcch.h @@ -34,4 +34,5 @@ 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); HRESULT WINAPI PathCchStripPrefix(WCHAR *path, SIZE_T size); +HRESULT WINAPI PathCchStripToRoot(WCHAR *path, SIZE_T size); BOOL WINAPI PathIsUNCEx(const WCHAR *path, const WCHAR **server);
1
0
0
0
Zhiyi Zhang : kernelbase: Implement PathCchSkipRoot.
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: 03d19f3e255bfd2b99e71a7f22119e1205ce7ed0 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=03d19f3e255bfd2b99e71a7f…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Thu Nov 22 14:46:39 2018 +0800 kernelbase: Implement PathCchSkipRoot. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- .../api-ms-win-core-path-l1-1-0.spec | 2 +- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/path.c | 108 +++++++++++++++++ dlls/kernelbase/tests/path.c | 128 +++++++++++++++++++++ include/pathcch.h | 1 + 5 files changed, 239 insertions(+), 2 deletions(-) Diff:
https://source.winehq.org/git/wine.git/?a=commitdiff;h=03d19f3e255bfd2b99e7…
1
0
0
0
Zhiyi Zhang : kernelbase: Implement PathCchStripPrefix.
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: 2ec414c8a1eef61f93a7ac19ac36ea0bd34154c5 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=2ec414c8a1eef61f93a7ac19…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Thu Nov 22 14:46:29 2018 +0800 kernelbase: Implement PathCchStripPrefix. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- .../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 d874f8c..53f7b98 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 b3b2887..8f4136e 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 4aa39b4..d0ec7e0 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -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; diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c index 3f7925d..5fc3cc8 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 6973d6d..1ff9e24 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);
1
0
0
0
Zhiyi Zhang : kernelbase: Implement PathIsUNCEx.
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: c02419ed360a2c1538e916911cdb55572d877381 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=c02419ed360a2c1538e91691…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Thu Nov 22 14:46:17 2018 +0800 kernelbase: Implement PathIsUNCEx. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- .../api-ms-win-core-path-l1-1-0.spec | 2 +- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/path.c | 21 +++++++ dlls/kernelbase/tests/path.c | 72 ++++++++++++++++++++++ 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 0524e7c..d874f8c 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 @@ -19,4 +19,4 @@ @ stub PathCchSkipRoot @ stub PathCchStripPrefix @ stub PathCchStripToRoot -@ stub PathIsUNCEx +@ stdcall PathIsUNCEx(wstr ptr) kernelbase.PathIsUNCEx diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 286dae0..b3b2887 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1082,7 +1082,7 @@ @ stdcall PathIsSameRootA(str str) shlwapi.PathIsSameRootA @ stdcall PathIsSameRootW(wstr wstr) shlwapi.PathIsSameRootW @ stdcall PathIsUNCA(str) shlwapi.PathIsUNCA -# @ stub PathIsUNCEx +@ stdcall PathIsUNCEx(wstr ptr) @ stdcall PathIsUNCServerA(str) shlwapi.PathIsUNCServerA @ stdcall PathIsUNCServerShareA(str) shlwapi.PathIsUNCServerShareA @ stdcall PathIsUNCServerShareW(wstr) shlwapi.PathIsUNCServerShareW diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 047017e..4aa39b4 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -38,6 +38,12 @@ static SIZE_T strnlenW(const WCHAR *string, SIZE_T maxlen) return i; } +static BOOL is_prefixed_unc(const WCHAR *string) +{ + static const WCHAR prefixed_unc[] = {'\\', '\\', '?', '\\', 'U', 'N', 'C', '\\'}; + return !strncmpiW(string, prefixed_unc, ARRAY_SIZE(prefixed_unc)); +} + HRESULT WINAPI PathCchAddBackslash(WCHAR *path, SIZE_T size) { return PathCchAddBackslashEx(path, size, NULL, NULL); @@ -183,3 +189,18 @@ HRESULT WINAPI PathCchRenameExtension(WCHAR *path, SIZE_T size, const WCHAR *ext hr = PathCchAddExtension(path, size, extension); return FAILED(hr) ? hr : S_OK; } + +BOOL WINAPI PathIsUNCEx(const WCHAR *path, const WCHAR **server) +{ + const WCHAR *result = NULL; + + TRACE("%s %p\n", wine_dbgstr_w(path), server); + + if (is_prefixed_unc(path)) + result = path + 8; + else if (path[0] == '\\' && path[1] == '\\' && path[2] != '?') + result = path + 2; + + if (server) *server = result; + return result ? TRUE : FALSE; +} diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c index 1d6f44e..3f7925d 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); +BOOL (WINAPI *pPathIsUNCEx)(const WCHAR *path, const WCHAR **server); static const struct { @@ -632,6 +633,75 @@ static void test_PathCchRenameExtension(void) } } +struct isuncex_test +{ + const CHAR *path; + INT server_offset; + BOOL ret; +}; + +static const struct isuncex_test isuncex_tests[] = +{ + {"\\\\", 2, TRUE}, + {"\\\\a\\", 2, TRUE}, + {"\\\\.\\", 2, TRUE}, + {"\\\\?\\UNC\\", 8, TRUE}, + {"\\\\?\\UNC\\a", 8, TRUE}, + {"\\\\?\\unc\\", 8, TRUE}, + {"\\\\?\\unc\\a", 8, TRUE}, + + {"", 0, FALSE}, + {"\\", 0, FALSE}, + {"C:\\", 0, FALSE}, + {"\\??\\", 0, FALSE}, + {"\\\\?\\", 0, FALSE}, + {"\\\\?\\UNC", 0, FALSE}, + {"\\\\?\\C:", 0, FALSE}, + {"\\\\?\\C:\\", 0, FALSE}, + {"\\\\?\\C:\\a", 0, FALSE}, + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", 0, FALSE} +}; + +static void test_PathIsUNCEx(void) +{ + WCHAR pathW[MAX_PATH]; + const WCHAR *server; + BOOL ret; + INT i; + + if (!pPathIsUNCEx) + { + win_skip("PathIsUNCEx(() is not available.\n"); + return; + } + + /* No NULL check for path pointers on Windows */ + if (0) + { + ret = pPathIsUNCEx(NULL, &server); + ok(ret == FALSE, "expect FALSE\n"); + } + + MultiByteToWideChar(CP_ACP, 0, "C:\\", -1, pathW, ARRAY_SIZE(pathW)); + ret = pPathIsUNCEx(pathW, NULL); + ok(ret == FALSE, "expect FALSE\n"); + + for (i = 0; i < ARRAY_SIZE(isuncex_tests); i++) + { + const struct isuncex_test *t = isuncex_tests + i; + + MultiByteToWideChar(CP_ACP, 0, t->path, -1, pathW, ARRAY_SIZE(pathW)); + server = (const WCHAR *)0xdeadbeef; + ret = pPathIsUNCEx(pathW, &server); + ok(ret == t->ret, "path \"%s\" expect return %d, got %d\n", t->path, t->ret, ret); + if (ret) + ok(server == pathW + t->server_offset, "path \"%s\" expect server offset %d, got %ld\n", t->path, + t->server_offset, (INT_PTR)(server - pathW)); + else + ok(!server, "expect server is null, got %p\n", server); + } +} + START_TEST(path) { HMODULE hmod = LoadLibraryA("kernelbase.dll"); @@ -643,6 +713,7 @@ START_TEST(path) pPathCchFindExtension = (void *)GetProcAddress(hmod, "PathCchFindExtension"); pPathCchRemoveExtension = (void *)GetProcAddress(hmod, "PathCchRemoveExtension"); pPathCchRenameExtension = (void *)GetProcAddress(hmod, "PathCchRenameExtension"); + pPathIsUNCEx = (void *)GetProcAddress(hmod, "PathIsUNCEx"); test_PathCchCombineEx(); test_PathCchAddBackslash(); @@ -651,4 +722,5 @@ START_TEST(path) test_PathCchFindExtension(); test_PathCchRemoveExtension(); test_PathCchRenameExtension(); + test_PathIsUNCEx(); } diff --git a/include/pathcch.h b/include/pathcch.h index 3057b6c..6973d6d 100644 --- a/include/pathcch.h +++ b/include/pathcch.h @@ -32,3 +32,4 @@ 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); +BOOL WINAPI PathIsUNCEx(const WCHAR *path, const WCHAR **server);
1
0
0
0
Zebediah Figura : setupapi/tests: Remove workarounds in testGetDeviceInterfaceDetail().
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: c9c646e9bb708c4123b44604b9d7cb5772ec726f URL:
https://source.winehq.org/git/wine.git/?a=commit;h=c9c646e9bb708c4123b44604…
Author: Zebediah Figura <z.figura12(a)gmail.com> Date: Wed Nov 21 23:07:35 2018 -0600 setupapi/tests: Remove workarounds in testGetDeviceInterfaceDetail(). Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/setupapi/tests/devinst.c | 172 +++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 102 deletions(-) Diff:
https://source.winehq.org/git/wine.git/?a=commitdiff;h=c9c646e9bb708c4123b4…
1
0
0
0
Zebediah Figura : setupapi/tests: Add more tests for device interfaces.
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: 75a91c4e63358a2bc068009fb130f3377e376296 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=75a91c4e63358a2bc068009f…
Author: Zebediah Figura <z.figura12(a)gmail.com> Date: Wed Nov 21 23:07:34 2018 -0600 setupapi/tests: Add more tests for device interfaces. Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/setupapi/tests/devinst.c | 89 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 15 deletions(-) diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 86af09d..539fe63 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -62,6 +62,7 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); /* This is a unique guid for testing purposes */ static GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}}; +static GUID guid2 = {0x6a55b5a5, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}}; static void init_function_pointers(void) { @@ -603,13 +604,48 @@ todo_wine devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); } +static void check_device_iface_(int line, HDEVINFO set, SP_DEVINFO_DATA *device, + const GUID *class, int index, DWORD flags, const char *path) +{ + char buffer[200]; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buffer; + SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; + BOOL ret; + + detail->cbSize = sizeof(*detail); + + SetLastError(0xdeadbeef); + ret = SetupDiEnumDeviceInterfaces(set, device, class, index, &iface); + if (path) + { + ok_(__FILE__, line)(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); + ok_(__FILE__, line)(IsEqualGUID(&iface.InterfaceClassGuid, class), + "Got unexpected class %s.\n", wine_dbgstr_guid(&iface.InterfaceClassGuid)); +todo_wine_if(flags & SPINT_REMOVED) + ok_(__FILE__, line)(iface.Flags == flags, "Got unexpected flags %#x.\n", iface.Flags); + ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, detail, sizeof(buffer), NULL, NULL); + ok_(__FILE__, line)(ret, "Failed to get interface detail, error %#x.\n", GetLastError()); + ok_(__FILE__, line)(!strcasecmp(detail->DevicePath, path), "Got unexpected path %s.\n", detail->DevicePath); + } + else + { + ok_(__FILE__, line)(!ret, "Expected failure.\n"); + ok_(__FILE__, line)(GetLastError() == ERROR_NO_MORE_ITEMS, + "Got unexpected error %#x.\n", GetLastError()); + } +} +#define check_device_iface(a,b,c,d,e,f) check_device_iface_(__LINE__,a,b,c,d,e,f) + static void test_device_iface(void) { + char buffer[200]; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buffer; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; SP_DEVINFO_DATA device = {0}; BOOL ret; HDEVINFO set; - DWORD i; + + detail->cbSize = sizeof(*detail); SetLastError(0xdeadbeef); ret = SetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL); @@ -638,6 +674,8 @@ static void test_device_iface(void) ret = SetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device); ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + check_device_iface(set, &device, &guid, 0, 0, NULL); + SetLastError(0xdeadbeef); ret = SetupDiCreateDeviceInterfaceA(set, &device, NULL, NULL, 0, NULL); ok(!ret, "Expected failure.\n"); @@ -646,31 +684,52 @@ static void test_device_iface(void) ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, NULL); ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}"); + check_device_iface(set, &device, &guid, 1, 0, NULL); + /* Creating the same interface a second time succeeds */ ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, NULL); ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}"); + check_device_iface(set, &device, &guid, 1, 0, NULL); + ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, "Oogah", 0, NULL); ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); - ret = SetupDiEnumDeviceInterfaces(set, &device, &guid, 0, &iface); - ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); + check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}"); + check_device_iface(set, &device, &guid, 1, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\Oogah"); + check_device_iface(set, &device, &guid, 2, 0, NULL); - i = 0; - while (SetupDiEnumDeviceInterfaces(set, &device, &guid, i, &iface)) - i++; - ok(i == 2, "expected 2 interfaces, got %d\n", i); - ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); + ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, "test", 0, &iface); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + ok(IsEqualGUID(&iface.InterfaceClassGuid, &guid), "Got unexpected class %s.\n", + wine_dbgstr_guid(&iface.InterfaceClassGuid)); + ok(iface.Flags == 0, "Got unexpected flags %#x.\n", iface.Flags); + ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, detail, sizeof(buffer), NULL, NULL); + ok(ret, "Failed to get interface detail, error %#x.\n", GetLastError()); + ok(!strcasecmp(detail->DevicePath, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\test"), + "Got unexpected path %s.\n", detail->DevicePath); + + check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}"); + check_device_iface(set, &device, &guid, 1, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\Oogah"); + check_device_iface(set, &device, &guid, 2, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\test"); + check_device_iface(set, &device, &guid, 3, 0, NULL); + + ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid2, NULL, 0, NULL); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); - for (i = 0; i < 2; i++) - { - ret = SetupDiEnumDeviceInterfaces(set, &device, &guid, i, &iface); - ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); + check_device_iface(set, &device, &guid2, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A5-3F65-11DB-B704-0011955C2BDB}"); + check_device_iface(set, &device, &guid2, 1, 0, NULL); - ret = SetupDiRemoveDeviceInterface(set, &iface); + ret = SetupDiEnumDeviceInterfaces(set, &device, &guid2, 0, &iface); + ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); + ret = SetupDiRemoveDeviceInterface(set, &iface); todo_wine - ok(ret, "Failed to remove interface, error %#x.\n", GetLastError()); - } + ok(ret, "Failed to remove interface, error %#x.\n", GetLastError()); + + check_device_iface(set, &device, &guid2, 0, SPINT_REMOVED, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A5-3F65-11DB-B704-0011955C2BDB}"); + check_device_iface(set, &device, &guid2, 1, 0, NULL); ret = SetupDiDestroyDeviceInfoList(set); ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError());
1
0
0
0
Zebediah Figura : setupapi/tests: Remove workarounds in testCreateDeviceInterface().
by Alexandre Julliard
22 Nov '18
22 Nov '18
Module: wine Branch: master Commit: 72cbe53bd84a01ace158a5f29d45cb6c7397781b URL:
https://source.winehq.org/git/wine.git/?a=commit;h=72cbe53bd84a01ace158a5f2…
Author: Zebediah Figura <z.figura12(a)gmail.com> Date: Wed Nov 21 23:07:33 2018 -0600 setupapi/tests: Remove workarounds in testCreateDeviceInterface(). Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/setupapi/tests/devinst.c | 132 +++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 71 deletions(-) diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 888b247..86af09d 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -603,87 +603,77 @@ todo_wine devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); } -static void testCreateDeviceInterface(void) +static void test_device_iface(void) { + SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; + SP_DEVINFO_DATA device = {0}; BOOL ret; HDEVINFO set; + DWORD i; - if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiEnumDeviceInterfaces) - { - win_skip("SetupDiCreateDeviceInterfaceA and/or SetupDiEnumDeviceInterfaces are not available\n"); - return; - } SetLastError(0xdeadbeef); - ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL); - ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, - "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + ret = SetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError()); + SetLastError(0xdeadbeef); - ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL); - ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, - "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); - set = pSetupDiCreateDeviceInfoList(&guid, NULL); - ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError()); - if (set) - { - SP_DEVINFO_DATA devInfo = { 0 }; - SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), - { 0 } }; - DWORD i; + ret = SetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL); - ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0, - NULL); - ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); - devInfo.cbSize = sizeof(devInfo); - ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, - NULL, NULL, 0, &devInfo); - ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0, - NULL); - ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, - "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); - ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, - NULL); - ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); - /* Creating the same interface a second time succeeds */ - ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, - NULL); - ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); - ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0, - NULL); - ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); - ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0, - &interfaceData); - ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError()); - i = 0; - while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i, - &interfaceData)) - i++; - ok(i == 2, "expected 2 interfaces, got %d\n", i); - ok(GetLastError() == ERROR_NO_MORE_ITEMS, - "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError()); - - for (i = 0; i < 2; i++) - { - ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i, &interfaceData); - ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError()); + set = SetupDiCreateDeviceInfoList(&guid, NULL); + ok(set != NULL, "Failed to create device list, error %#x.\n", GetLastError()); - ret = pSetupDiRemoveDeviceInterface(set, &interfaceData); - todo_wine ok(ret, "SetupDiRemoveDeviceInterface failed: %08x\n", GetLastError()); - } + SetLastError(0xdeadbeef); + ret = SetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError()); - ret = pSetupDiRemoveDevice(set, &devInfo); - todo_wine ok(ret, "got %u\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = SetupDiCreateDeviceInterfaceA(set, &device, NULL, NULL, 0, NULL); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError()); + + device.cbSize = sizeof(device); + ret = SetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device); + ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = SetupDiCreateDeviceInterfaceA(set, &device, NULL, NULL, 0, NULL); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError()); + + ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, NULL); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); - ret = pSetupDiDestroyDeviceInfoList(set); - ok(ret, "SetupDiDestroyDeviceInfoList failed: %08x\n", GetLastError()); + /* Creating the same interface a second time succeeds */ + ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, NULL); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + + ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, "Oogah", 0, NULL); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + + ret = SetupDiEnumDeviceInterfaces(set, &device, &guid, 0, &iface); + ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); + + i = 0; + while (SetupDiEnumDeviceInterfaces(set, &device, &guid, i, &iface)) + i++; + ok(i == 2, "expected 2 interfaces, got %d\n", i); + ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); + + for (i = 0; i < 2; i++) + { + ret = SetupDiEnumDeviceInterfaces(set, &device, &guid, i, &iface); + ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); + + ret = SetupDiRemoveDeviceInterface(set, &iface); +todo_wine + ok(ret, "Failed to remove interface, error %#x.\n", GetLastError()); } + + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); } static void testGetDeviceInterfaceDetail(void) @@ -1538,7 +1528,7 @@ START_TEST(devinst) test_device_info(); test_get_device_instance_id(); test_register_device_info(); - testCreateDeviceInterface(); + test_device_iface(); testGetDeviceInterfaceDetail(); testDevRegKey(); testRegisterAndGetDetail();
1
0
0
0
Zhiyi Zhang : kernelbase: Implement PathCchRenameExtension.
by Alexandre Julliard
21 Nov '18
21 Nov '18
Module: wine Branch: master Commit: 55bcfea8f011c7f31df81a0f05f11a1d5c0d11b1 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=55bcfea8f011c7f31df81a0f…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Tue Nov 20 19:06:41 2018 +0800 kernelbase: Implement PathCchRenameExtension. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- .../api-ms-win-core-path-l1-1-0.spec | 2 +- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/path.c | 13 ++++ dlls/kernelbase/tests/path.c | 80 ++++++++++++++++++++++ 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 57e0a67..0524e7c 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 @@ -15,7 +15,7 @@ @ stub PathCchRemoveBackslashEx @ stdcall PathCchRemoveExtension(wstr long) kernelbase.PathCchRemoveExtension @ stub PathCchRemoveFileSpec -@ stub PathCchRenameExtension +@ stdcall PathCchRenameExtension(wstr long wstr) kernelbase.PathCchRenameExtension @ stub PathCchSkipRoot @ stub PathCchStripPrefix @ stub PathCchStripToRoot diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index ffe7be2..286dae0 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1044,7 +1044,7 @@ # @ stub PathCchRemoveBackslashEx @ stdcall PathCchRemoveExtension(wstr long) # @ stub PathCchRemoveFileSpec -# @ stub PathCchRenameExtension +@ stdcall PathCchRenameExtension(wstr long wstr) # @ stub PathCchSkipRoot # @ stub PathCchStripPrefix # @ stub PathCchStripToRoot diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 9dc2118..047017e 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -170,3 +170,16 @@ HRESULT WINAPI PathCchRemoveExtension(WCHAR *path, SIZE_T size) return next == extension ? S_FALSE : S_OK; } + +HRESULT WINAPI PathCchRenameExtension(WCHAR *path, SIZE_T size, const WCHAR *extension) +{ + HRESULT hr; + + TRACE("%s %lu %s\n", wine_dbgstr_w(path), size, wine_dbgstr_w(extension)); + + hr = PathCchRemoveExtension(path, size); + if (FAILED(hr)) return hr; + + hr = PathCchAddExtension(path, size, extension); + return FAILED(hr) ? hr : S_OK; +} diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c index 9f1f292..1d6f44e 100644 --- a/dlls/kernelbase/tests/path.c +++ b/dlls/kernelbase/tests/path.c @@ -36,6 +36,7 @@ HRESULT (WINAPI *pPathCchAddExtension)(WCHAR *path, SIZE_T size, const WCHAR *ex 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); +HRESULT (WINAPI *pPathCchRenameExtension)(WCHAR *path, SIZE_T size, const WCHAR *extension); static const struct { @@ -554,6 +555,83 @@ static void test_PathCchRemoveExtension(void) } } +struct renameextension_test +{ + const CHAR *path; + const CHAR *extension; + const CHAR *expected; +}; + +static const struct renameextension_test renameextension_tests[] = +{ + {"1.exe", ".txt", "1.txt"}, + {"C:1.exe", ".txt", "C:1.txt"}, + {"C:\\1.exe", ".txt", "C:\\1.txt"}, + {"\\1.exe", ".txt", "\\1.txt"}, + {"\\\\1.exe", ".txt", "\\\\1.txt"}, + {"\\\\?\\C:1.exe", ".txt", "\\\\?\\C:1.txt"}, + {"\\\\?\\C:\\1.exe", ".txt", "\\\\?\\C:\\1.txt"}, + {"\\\\?\\UNC\\1.exe", ".txt", "\\\\?\\UNC\\1.txt"}, + {"\\\\?\\UNC\\192.168.1.1\\1.exe", ".txt", "\\\\?\\UNC\\192.168.1.1\\1.txt"}, + {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1.exe", ".txt", + "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1.txt"}, + {"C:\\1.exe", "", "C:\\1"}, + {"C:\\1.exe", "txt", "C:\\1.txt"} +}; + +static void test_PathCchRenameExtension(void) +{ + WCHAR pathW[PATHCCH_MAX_CCH + 1]; + CHAR pathA[PATHCCH_MAX_CCH + 1]; + WCHAR extensionW[MAX_PATH]; + HRESULT hr; + INT i; + + if (!pPathCchRenameExtension) + { + win_skip("PathCchRenameExtension() is not available.\n"); + return; + } + + /* Invalid arguments */ + MultiByteToWideChar(CP_ACP, 0, "C:\\1.txt", -1, pathW, ARRAY_SIZE(pathW)); + MultiByteToWideChar(CP_ACP, 0, ".exe", -1, extensionW, ARRAY_SIZE(extensionW)); + + hr = pPathCchRenameExtension(NULL, PATHCCH_MAX_CCH, extensionW); + ok(hr == E_INVALIDARG, "expect result %#x, got %#x\n", E_INVALIDARG, hr); + + hr = pPathCchRenameExtension(pathW, 0, extensionW); + ok(hr == E_INVALIDARG, "expect result %#x, got %#x\n", E_INVALIDARG, hr); + + hr = pPathCchRenameExtension(pathW, PATHCCH_MAX_CCH, NULL); + ok(hr == E_INVALIDARG, "expect result %#x, got %#x\n", E_INVALIDARG, hr); + + /* Path length */ + hr = pPathCchRenameExtension(pathW, ARRAY_SIZE("C:\\1.exe") - 1, extensionW); + ok(E_INVALIDARG, "expect result %#x, got %#x\n", E_INVALIDARG, hr); + + hr = pPathCchRenameExtension(pathW, PATHCCH_MAX_CCH + 1, extensionW); + ok(hr == E_INVALIDARG, "expect result %#x, got %#x\n", E_INVALIDARG, hr); + + hr = pPathCchRenameExtension(pathW, PATHCCH_MAX_CCH, extensionW); + ok(hr == S_OK, "expect result %#x, got %#x\n", S_OK, hr); + + for (i = 0; i < ARRAY_SIZE(renameextension_tests); i++) + { + const struct renameextension_test *t = renameextension_tests + i; + MultiByteToWideChar(CP_ACP, 0, t->path, -1, pathW, ARRAY_SIZE(pathW)); + MultiByteToWideChar(CP_ACP, 0, t->extension, -1, extensionW, ARRAY_SIZE(extensionW)); + hr = pPathCchRenameExtension(pathW, PATHCCH_MAX_CCH, extensionW); + ok(hr == S_OK, "path %s extension %s expect result %#x, got %#x\n", t->path, t->extension, S_OK, hr); + if (SUCCEEDED(hr)) + { + WideCharToMultiByte(CP_ACP, 0, pathW, -1, pathA, ARRAY_SIZE(pathA), NULL, NULL); + ok(!lstrcmpA(pathA, t->expected), "path %s extension %s expect output path %s, got %s\n", t->path, + t->extension, t->expected, pathA); + } + } +} + START_TEST(path) { HMODULE hmod = LoadLibraryA("kernelbase.dll"); @@ -564,6 +642,7 @@ START_TEST(path) pPathCchAddExtension = (void *)GetProcAddress(hmod, "PathCchAddExtension"); pPathCchFindExtension = (void *)GetProcAddress(hmod, "PathCchFindExtension"); pPathCchRemoveExtension = (void *)GetProcAddress(hmod, "PathCchRemoveExtension"); + pPathCchRenameExtension = (void *)GetProcAddress(hmod, "PathCchRenameExtension"); test_PathCchCombineEx(); test_PathCchAddBackslash(); @@ -571,4 +650,5 @@ START_TEST(path) test_PathCchAddExtension(); test_PathCchFindExtension(); test_PathCchRemoveExtension(); + test_PathCchRenameExtension(); } diff --git a/include/pathcch.h b/include/pathcch.h index 2f125bb..3057b6c 100644 --- a/include/pathcch.h +++ b/include/pathcch.h @@ -31,3 +31,4 @@ HRESULT WINAPI PathCchAddExtension(WCHAR *path, SIZE_T size, const WCHAR *extens 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); +HRESULT WINAPI PathCchRenameExtension(WCHAR *path, SIZE_T size, const WCHAR *extension);
1
0
0
0
← Newer
1
...
45
46
47
48
49
50
51
...
96
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
Results per page:
10
25
50
100
200