2 * Path tests for kernelbase.dll
4 * Copyright 2017 Michael Müller
5 * Copyright 2018 Zhiyi Zhang
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/test.h"
33 HRESULT (WINAPI
*pPathAllocCanonicalize
)(const WCHAR
*path_in
, DWORD flags
, WCHAR
**path_out
);
34 HRESULT (WINAPI
*pPathAllocCombine
)(const WCHAR
*path1
, const WCHAR
*path2
, DWORD flags
, WCHAR
**out
);
35 HRESULT (WINAPI
*pPathCchAddBackslash
)(WCHAR
*out
, SIZE_T size
);
36 HRESULT (WINAPI
*pPathCchAddBackslashEx
)(WCHAR
*out
, SIZE_T size
, WCHAR
**endptr
, SIZE_T
*remaining
);
37 HRESULT (WINAPI
*pPathCchAddExtension
)(WCHAR
*path
, SIZE_T size
, const WCHAR
*extension
);
38 HRESULT (WINAPI
*pPathCchAppend
)(WCHAR
*path1
, SIZE_T size
, const WCHAR
*path2
);
39 HRESULT (WINAPI
*pPathCchAppendEx
)(WCHAR
*path1
, SIZE_T size
, const WCHAR
*path2
, DWORD flags
);
40 HRESULT (WINAPI
*pPathCchCanonicalize
)(WCHAR
*out
, SIZE_T size
, const WCHAR
*in
);
41 HRESULT (WINAPI
*pPathCchCanonicalizeEx
)(WCHAR
*out
, SIZE_T size
, const WCHAR
*in
, DWORD flags
);
42 HRESULT (WINAPI
*pPathCchCombine
)(WCHAR
*out
, SIZE_T size
, const WCHAR
*path1
, const WCHAR
*path2
);
43 HRESULT (WINAPI
*pPathCchCombineEx
)(WCHAR
*out
, SIZE_T size
, const WCHAR
*path1
, const WCHAR
*path2
, DWORD flags
);
44 HRESULT (WINAPI
*pPathCchFindExtension
)(const WCHAR
*path
, SIZE_T size
, const WCHAR
**extension
);
45 BOOL (WINAPI
*pPathCchIsRoot
)(const WCHAR
*path
);
46 HRESULT (WINAPI
*pPathCchRemoveBackslash
)(WCHAR
*path
, SIZE_T path_size
);
47 HRESULT (WINAPI
*pPathCchRemoveBackslashEx
)(WCHAR
*path
, SIZE_T path_size
, WCHAR
**path_end
, SIZE_T
*free_size
);
48 HRESULT (WINAPI
*pPathCchRemoveExtension
)(WCHAR
*path
, SIZE_T size
);
49 HRESULT (WINAPI
*pPathCchRemoveFileSpec
)(WCHAR
*path
, SIZE_T size
);
50 HRESULT (WINAPI
*pPathCchRenameExtension
)(WCHAR
*path
, SIZE_T size
, const WCHAR
*extension
);
51 HRESULT (WINAPI
*pPathCchSkipRoot
)(const WCHAR
*path
, const WCHAR
**root_end
);
52 HRESULT (WINAPI
*pPathCchStripPrefix
)(WCHAR
*path
, SIZE_T size
);
53 HRESULT (WINAPI
*pPathCchStripToRoot
)(WCHAR
*path
, SIZE_T size
);
54 BOOL (WINAPI
*pPathIsUNCEx
)(const WCHAR
*path
, const WCHAR
**server
);
56 struct alloccanonicalize_test
64 static const struct alloccanonicalize_test alloccanonicalize_tests
[] =
67 {"C:a", "C:a", 0, S_OK
},
68 {"\\\\?\\C:", "C:\\", 0, S_OK
},
69 {"\\\\?C:\\a", "\\\\?C:\\a", 0, S_OK
},
70 {"\\\\?UNC\\a", "\\\\?UNC\\a", 0, S_OK
},
71 {"\\\\?\\UNCa", "\\\\?\\UNCa", 0, S_OK
},
72 {"\\\\?C:a", "\\\\?C:a", 0, S_OK
},
77 {"C:", "C:", 0, S_OK
},
78 {"C:\\", "C:\\", 0, S_OK
},
79 {"\\\\?\\C:\\a", "C:\\a", 0, S_OK
},
80 {"\\\\?\\UNC\\a", "\\\\a", 0, S_OK
},
84 {"..", "\\", 0, S_OK
},
85 {"...", "\\", 0, S_OK
},
86 {"*.", "*.", 0, S_OK
},
87 {"*.\\", "*.\\", 0, S_OK
},
88 {"*.\\", "*.\\", 0, S_OK
},
89 {"*..", "*.", 0, S_OK
},
90 {"*..\\", "*..\\", 0, S_OK
},
91 {"*...", "*.", 0, S_OK
},
92 {"*...\\", "*...\\", 0, S_OK
},
93 {"*....", "*.", 0, S_OK
},
94 {"*....\\", "*....\\", 0, S_OK
},
95 {".a", ".a", 0, S_OK
},
96 {".a\\", ".a\\", 0, S_OK
},
98 {"a.\\", "a.\\", 0, S_OK
},
99 {".a.", ".a", 0, S_OK
},
100 {"a.b", "a.b", 0, S_OK
},
101 {".a.b.", ".a.b", 0, S_OK
},
102 {"a\\.", "a", 0, S_OK
},
103 {"a\\.\\b", "a\\b", 0, S_OK
},
104 {"a\\.b", "a\\.b", 0, S_OK
},
105 {"a\\.b\\", "a\\.b\\", 0, S_OK
},
106 {":.", ":", 0, S_OK
},
107 {"::.", "::\\", 0, S_OK
},
108 {":::.", ":::", 0, S_OK
},
109 {"C:.", "C:\\", 0, S_OK
},
110 {"C:.\\", "C:.\\", 0, S_OK
},
111 {"C:.\\.", "C:\\", 0, S_OK
},
112 {"C:\\.", "C:\\", 0, S_OK
},
113 {"C:\\.\\", "C:\\", 0, S_OK
},
114 {"C:\\a.", "C:\\a", 0, S_OK
},
115 {"C:\\a.\\", "C:\\a.\\", 0, S_OK
},
116 {"C:\\.a", "C:\\.a", 0, S_OK
},
117 {"C:\\.a\\", "C:\\.a\\", 0, S_OK
},
118 {"C:\\a\\.", "C:\\a", 0, S_OK
},
119 {"C:\\a\\\\.", "C:\\a\\", 0, S_OK
},
120 {"C:\\a\\\\\\.", "C:\\a\\\\", 0, S_OK
},
121 {".\\", "\\", 0, S_OK
},
122 {"\\.", "\\", 0, S_OK
},
123 {"\\\\.", "\\\\", 0, S_OK
},
124 {"\\\\.\\", "\\\\", 0, S_OK
},
125 {"\\\\\\.", "\\\\", 0, S_OK
},
126 {"\\\\.\\\\", "\\\\\\", 0, S_OK
},
127 {"\\\\\\\\.", "\\\\\\", 0, S_OK
},
128 {"\\?\\.", "\\?", 0, S_OK
},
129 {"\\\\?\\.", "\\\\?", 0, S_OK
},
130 {"\\192.168.1.1\\a", "\\192.168.1.1\\a", 0, S_OK
},
131 {"\\a.168.1.1\\a", "\\a.168.1.1\\a", 0, S_OK
},
132 {"\\\\192.168.1.1\\a", "\\\\192.168.1.1\\a", 0, S_OK
},
133 {"\\\\a.168.1.1\\b", "\\\\a.168.1.1\\b", 0, S_OK
},
134 {"\\\\?\\C:.", "C:\\", 0, S_OK
},
135 {"\\\\?\\C:\\.", "C:\\", 0, S_OK
},
136 {"\\\\?\\UNC\\.", "\\\\", 0, S_OK
},
137 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\.",
138 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", 0, S_OK
},
141 {"..a", "..a", 0, S_OK
},
142 {"..a\\", "..a\\", 0, S_OK
},
143 {"...a", "...a", 0, S_OK
},
144 {"...a\\", "...a\\", 0, S_OK
},
145 {"....a", "....a", 0, S_OK
},
146 {"a..", "a", 0, S_OK
},
147 {"a..\\", "a..\\", 0, S_OK
},
148 {"a...", "a", 0, S_OK
},
149 {"a...\\", "a...\\", 0, S_OK
},
150 {"a....", "a", 0, S_OK
},
151 {"a....\\", "a....\\", 0, S_OK
},
152 {"..a..", "..a", 0, S_OK
},
153 {"a..b", "a..b", 0, S_OK
},
154 {"..a..b..", "..a..b", 0, S_OK
},
155 {"a\\..", "\\", 0, S_OK
},
156 {"a\\..\\", "\\", 0, S_OK
},
157 {"a\\..\\b", "\\b", 0, S_OK
},
158 {":..", ":", 0, S_OK
},
159 {"::..", "::\\", 0, S_OK
},
160 {":::..", ":::", 0, S_OK
},
161 {"C:..", "C:\\", 0, S_OK
},
162 {"C:...", "C:\\", 0, S_OK
},
163 {"C:..\\", "C:..\\", 0, S_OK
},
164 {"C:..\\\\", "C:..\\\\", 0, S_OK
},
165 {"C:...\\", "C:...\\", 0, S_OK
},
166 {"C:\\..", "C:\\", 0, S_OK
},
167 {"C:\\..a", "C:\\..a", 0, S_OK
},
168 {"C:\\..a\\", "C:\\..a\\", 0, S_OK
},
169 {"C:\\...a", "C:\\...a", 0, S_OK
},
170 {"C:\\...a\\", "C:\\...a\\", 0, S_OK
},
171 {"C:\\....a", "C:\\....a", 0, S_OK
},
172 {"C:\\....a\\", "C:\\....a\\", 0, S_OK
},
173 {"C:\\a..", "C:\\a", 0, S_OK
},
174 {"C:\\a..\\", "C:\\a..\\", 0, S_OK
},
175 {"C:\\\\..", "C:\\", 0, S_OK
},
176 {"C:\\..\\", "C:\\", 0, S_OK
},
177 {"C:\\...\\", "C:\\...\\", 0, S_OK
},
178 {"C:\\a\\..", "C:\\", 0, S_OK
},
179 {"C:\\a\\b..", "C:\\a\\b", 0, S_OK
},
180 {"C:\\a\\\\..", "C:\\a", 0, S_OK
},
181 {"C:\\a\\\\\\..", "C:\\a\\", 0, S_OK
},
182 {"C:\\a\\..\\b", "C:\\b", 0, S_OK
},
183 {"C:\\a\\..\\\\b", "C:\\\\b", 0, S_OK
},
184 {"..\\", "\\", 0, S_OK
},
185 {"...\\", "...\\", 0, S_OK
},
186 {"\\..", "\\", 0, S_OK
},
187 {"\\...", "\\", 0, S_OK
},
188 {"\\\\..", "\\\\", 0, S_OK
},
189 {"\\\\\\..", "\\", 0, S_OK
},
190 {"\\\\..\\", "\\\\", 0, S_OK
},
191 {"\\\\\\..", "\\", 0, S_OK
},
192 {"\\\\..\\\\", "\\\\\\", 0, S_OK
},
193 {"\\\\\\\\..", "\\\\", 0, S_OK
},
194 {"\\?\\..", "\\", 0, S_OK
},
195 {"\\a\\..", "\\", 0, S_OK
},
196 {"\\\\?\\..", "\\", 0, S_OK
},
197 {"\\\\a\\..", "\\", 0, S_OK
},
198 {"\\a\\..\\b", "\\b", 0, S_OK
},
199 {"\\a\\b\\..", "\\a", 0, S_OK
},
200 {"\\?\\UNC\\..", "\\?", 0, S_OK
},
201 {"\\?\\C:\\..", "\\?", 0, S_OK
},
202 {"\\\\?\\C:..", "C:\\", 0, S_OK
},
203 {"\\\\?\\C:\\..", "C:\\", 0, S_OK
},
204 {"\\\\?\\UNC\\..", "\\\\", 0, S_OK
},
205 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}..",
206 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", 0, S_OK
},
207 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\..",
208 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", 0, S_OK
},
209 {"\\\\?\\UNC\\a\\b\\..", "\\\\a", 0, S_OK
},
210 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\b\\..",
211 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", 0, S_OK
},
214 {"C:\\a\\.\\b\\..\\", "C:\\a\\", 0, S_OK
},
215 {"\\a\\.\\b\\..\\", "\\a\\", 0, S_OK
},
216 {"\\?\\a\\.\\b\\..\\", "\\?\\a\\", 0, S_OK
},
217 {"\\\\.\\a\\.\\b\\..\\", "\\\\a\\", 0, S_OK
},
218 {"\\\\?\\a\\.\\b\\..\\", "\\\\?\\a\\", 0, S_OK
},
219 {"\\\\.\\..", "\\\\", 0, S_OK
},
221 /* PATHCCH_ALLOW_LONG_PATHS */
222 /* Input path with prefix \\?\ and length of MAXPATH + 1, HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) = 0x800700ce */
223 {"\\\\?\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
224 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
225 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", NULL
, 0, 0x800700ce},
226 /* Input path with prefix C:\ and length of MAXPATH + 1 */
227 {"C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
228 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
229 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", NULL
, 0, 0x800700ce},
230 {"C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
231 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
232 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\\\\?\\C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
233 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
234 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", PATHCCH_ALLOW_LONG_PATHS
, S_OK
},
235 /* Input path with prefix C: and length of MAXPATH + 1 */
236 {"C:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
237 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
238 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\\\\?\\C:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
239 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
240 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", PATHCCH_ALLOW_LONG_PATHS
, S_OK
},
241 /* Input path with prefix C:\ and length of MAXPATH + 1 and with .. */
242 {"C:\\..\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
243 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
244 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
245 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
246 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", PATHCCH_ALLOW_LONG_PATHS
, S_OK
},
247 /* Input path with prefix \\?\ and length of MAXPATH + 1 */
248 {"\\\\?\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
249 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
250 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\\\\?\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
251 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
252 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", PATHCCH_ALLOW_LONG_PATHS
, S_OK
},
253 /* Input path with prefix \ and length of MAXPATH + 1 */
254 {"\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
255 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
256 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
257 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
258 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", PATHCCH_ALLOW_LONG_PATHS
, S_OK
},
259 /* Input path with length of MAXPATH with PATHCCH_ALLOW_LONG_PATHS disabled*/
260 {"C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
261 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
262 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
263 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
264 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, S_OK
},
265 /* Input path with length of MAXPATH */
266 {"C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
267 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
268 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
269 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
270 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", PATHCCH_ALLOW_LONG_PATHS
, S_OK
},
272 /* Flags added after Windows 10 1709 */
273 /* PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS */
274 /* PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS without PATHCCH_ALLOW_LONG_PATHS */
275 {"", NULL
, PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS
, E_INVALIDARG
},
276 /* Input path with prefix C:\ and length of MAXPATH + 1 and PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS */
277 {"C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
278 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
279 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
280 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
281 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
282 PATHCCH_ALLOW_LONG_PATHS
| PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS
, S_OK
},
284 /* PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS */
285 /* PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS without PATHCCH_ALLOW_LONG_PATHS */
286 {"", NULL
, PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS
, E_INVALIDARG
},
287 /* Both PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS and PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS */
288 {"", "\\", PATHCCH_ALLOW_LONG_PATHS
| PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS
| PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS
,
290 /* Input path with prefix C:\ and length of MAXPATH + 1 and PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS */
291 {"C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
292 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
293 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\\\\?\\C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
294 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
295 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
296 PATHCCH_ALLOW_LONG_PATHS
| PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS
, S_OK
},
297 /* Input path with prefix C:\ and length of MAXPATH and PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS */
298 {"C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
299 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
300 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
301 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
302 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
303 PATHCCH_ALLOW_LONG_PATHS
| PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS
, S_OK
},
305 /* PATHCCH_DO_NOT_NORMALIZE_SEGMENTS */
306 /* No effect for spaces */
307 {"a ", "a ", 0, S_OK
},
308 {"C:\\a ", "C:\\a ", 0, S_OK
},
309 {"C:\\a \\", "C:\\a \\", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
310 {"C:\\a\\ ", "C:\\a\\ ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
311 {"C:\\a ", "C:\\a ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
312 {"C:\\a ", "C:\\a ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
313 {"C:\\a. ", "C:\\a. ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
314 {"\\a \\", "\\a \\", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
315 {"\\a\\ ", "\\a\\ ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
316 {"\\\\a \\", "\\\\a \\", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
317 {"\\\\a\\ ", "\\\\a\\ ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
318 {"\\\\?\\ ", "\\\\?\\ ", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
319 /* Keep trailing dot */
320 {"*..", "*..", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
321 {".", "\\", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
322 {"..", "\\", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
323 {":.", ":.", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
324 {"::.", "::.", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
325 {":::.", ":::.", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
326 {":..", ":..", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
327 {"::..", "::..", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
328 {":::..", ":::..", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
329 {"C:.", "C:.", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
330 {"C:..", "C:..", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
331 {"C:...", "C:...", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
332 {"C:\\a\\.", "C:\\a", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
333 {"C:\\a\\..", "C:\\", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
334 {"C:\\a.", "C:\\a.", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
335 {"C:\\a..", "C:\\a..", PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
, S_OK
},
337 /* PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH */
338 {"C:\\a\\", "\\\\?\\C:\\a\\", PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH
, S_OK
},
339 {"", NULL
, PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH
| PATHCCH_ALLOW_LONG_PATHS
, E_INVALIDARG
},
340 {"\\a\\", "\\a\\", PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH
, S_OK
},
341 {"\\\\?\\C:\\a\\", "\\\\?\\C:\\a\\", PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH
, S_OK
},
342 /* Implication of PATHCCH_DO_NOT_NORMALIZE_SEGMENTS by PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH */
343 {"\\a.", "\\a.", PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH
, S_OK
},
345 /* PATHCCH_ENSURE_TRAILING_SLASH */
346 {"\\", "\\", PATHCCH_ENSURE_TRAILING_SLASH
, S_OK
},
347 {"C:\\", "C:\\", PATHCCH_ENSURE_TRAILING_SLASH
, S_OK
},
348 {"C:\\a\\.", "C:\\a\\", PATHCCH_ENSURE_TRAILING_SLASH
, S_OK
},
349 {"C:\\a", "C:\\a\\", PATHCCH_ENSURE_TRAILING_SLASH
, S_OK
}
352 static void test_PathAllocCanonicalize(void)
354 WCHAR path_inW
[1024], path_maxW
[PATHCCH_MAX_CCH
+ 1];
356 CHAR path_outA
[1024];
357 BOOL skip_new_flags
= TRUE
;
361 if (!pPathAllocCanonicalize
)
363 win_skip("PathAllocCanonicalize() is not available.\n");
367 /* No NULL check for path on Windows */
370 hr
= pPathAllocCanonicalize(NULL
, 0, &path_outW
);
371 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
374 MultiByteToWideChar(CP_ACP
, 0, "C:\\", -1, path_inW
, ARRAY_SIZE(path_inW
));
375 hr
= pPathAllocCanonicalize(path_inW
, 0, NULL
);
376 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
378 /* Test longest path */
379 for (i
= 0; i
< ARRAY_SIZE(path_maxW
) - 1; i
++) path_maxW
[i
] = 'a';
380 path_maxW
[PATHCCH_MAX_CCH
] = '\0';
381 path_outW
= (WCHAR
*)0xdeadbeef;
382 hr
= pPathAllocCanonicalize(path_maxW
, PATHCCH_ALLOW_LONG_PATHS
, &path_outW
);
383 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), "expect hr %#x, got %#x\n",
384 HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), hr
);
385 ok(path_outW
== NULL
, "expect path_outW null, got %p\n", path_outW
);
387 path_maxW
[PATHCCH_MAX_CCH
- 1] = '\0';
388 hr
= pPathAllocCanonicalize(path_maxW
, PATHCCH_ALLOW_LONG_PATHS
, &path_outW
);
389 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
390 LocalFree(path_outW
);
392 /* Check if flags added after Windows 10 1709 are supported */
393 MultiByteToWideChar(CP_ACP
, 0, "C:\\", -1, path_inW
, ARRAY_SIZE(path_inW
));
394 hr
= pPathAllocCanonicalize(path_inW
, PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS
, &path_outW
);
395 if (hr
== E_INVALIDARG
) skip_new_flags
= FALSE
;
397 for (i
= 0; i
< ARRAY_SIZE(alloccanonicalize_tests
); i
++)
399 const struct alloccanonicalize_test
*t
= alloccanonicalize_tests
+ i
;
401 if (((PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS
| PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS
402 | PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
| PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH
403 | PATHCCH_ENSURE_TRAILING_SLASH
)
407 win_skip("Skip testing new flags added after Windows 10 1709\n");
411 MultiByteToWideChar(CP_ACP
, 0, t
->path_in
, -1, path_inW
, ARRAY_SIZE(path_inW
));
412 hr
= pPathAllocCanonicalize(path_inW
, t
->flags
, &path_outW
);
413 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path_in
, t
->hr
, hr
);
416 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
417 ok(!lstrcmpA(path_outA
, t
->path_out
), "path \"%s\" expect output path \"%s\", got \"%s\"\n", t
->path_in
,
418 t
->path_out
, path_outA
);
419 LocalFree(path_outW
);
431 static const struct combine_test combine_tests
[] =
434 {"C:\\", "a", "C:\\a" },
435 {"C:\\b", "..\\a", "C:\\a" },
436 {"C:", "a", "C:\\a" },
437 {"C:\\", ".", "C:\\" },
438 {"C:\\", "..", "C:\\" },
439 {"C:\\a", "", "C:\\a" },
441 {"\\a", "b", "\\a\\b" },
443 /* normal UNC paths */
444 {"\\\\192.168.1.1\\test", "a", "\\\\192.168.1.1\\test\\a" },
445 {"\\\\192.168.1.1\\test", "..", "\\\\192.168.1.1" },
446 {"\\\\", "a", "\\\\a"},
447 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", "a",
448 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a"},
451 {"\\\\?\\C:\\", "a", "C:\\a" },
452 {"\\\\?\\C:\\", "..", "C:\\" },
453 {"\\\\?\\C:", "a", "C:\\a"},
456 {"\\\\?\\UNC\\", "a", "\\\\a"},
457 {"\\\\?\\UNC\\192.168.1.1\\test", "a", "\\\\192.168.1.1\\test\\a" },
458 {"\\\\?\\UNC\\192.168.1.1\\test", "..", "\\\\192.168.1.1" },
460 /* Second path begins with a single backslash */
461 {"C:a\\b", "\\1", "C:\\1"},
462 {"C:\\a\\b", "\\1", "C:\\1"},
463 {"\\a\\b", "\\1", "\\1"},
464 {"\\\\a\\b", "\\1", "\\\\a\\b\\1"},
465 {"\\\\a\\b\\c", "\\1", "\\\\a\\b\\1"},
466 {"\\\\?\\UNC\\a", "\\1", "\\\\a\\1"},
467 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a", "\\1",
468 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1"},
469 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", "\\1",
470 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1"},
471 {"C:\\a\\b", "\\", "C:\\"},
473 /* Second path is fully qualified */
474 {"X:\\", "C:", "C:\\"},
475 {"X:\\", "C:\\", "C:\\"},
476 {"X:\\", "\\\\", "\\\\"},
477 {"X:\\", "\\\\?\\C:", "C:\\"},
478 {"X:\\", "\\\\?\\C:\\", "C:\\"},
479 {"X:\\", "\\\\?\\UNC\\", "\\\\"},
480 {"X:\\", "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\",
481 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\"},
483 /* Canonicalization */
484 {"C:\\a", ".\\b", "C:\\a\\b"},
485 {"C:\\a", "..\\b", "C:\\b"},
492 static void test_PathAllocCombine(void)
494 WCHAR path1W
[PATHCCH_MAX_CCH
];
495 WCHAR path2W
[PATHCCH_MAX_CCH
];
497 CHAR resultA
[PATHCCH_MAX_CCH
];
501 if (!pPathAllocCombine
)
503 win_skip("PathAllocCombine() is not available.\n");
507 resultW
= (WCHAR
*)0xdeadbeef;
508 hr
= pPathAllocCombine(NULL
, NULL
, 0, &resultW
);
509 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
510 ok(resultW
== NULL
, "expect resultW null, got %p\n", resultW
);
512 MultiByteToWideChar(CP_ACP
, 0, "\\a", -1, path1W
, ARRAY_SIZE(path1W
));
513 hr
= pPathAllocCombine(path1W
, NULL
, 0, &resultW
);
514 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
515 WideCharToMultiByte(CP_ACP
, 0, resultW
, -1, resultA
, ARRAY_SIZE(resultA
), NULL
, NULL
);
516 ok(!lstrcmpA(resultA
, "\\a"), "expect \\a, got %s\n", resultA
);
519 MultiByteToWideChar(CP_ACP
, 0, "\\b", -1, path2W
, ARRAY_SIZE(path2W
));
520 hr
= pPathAllocCombine(NULL
, path2W
, 0, &resultW
);
521 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
522 WideCharToMultiByte(CP_ACP
, 0, resultW
, -1, resultA
, ARRAY_SIZE(resultA
), NULL
, NULL
);
523 ok(!lstrcmpA(resultA
, "\\b"), "expect \\b, got %s\n", resultA
);
526 hr
= pPathAllocCombine(path1W
, path2W
, 0, NULL
);
527 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
529 for (i
= 0; i
< ARRAY_SIZE(combine_tests
); i
++)
531 const struct combine_test
*t
= combine_tests
+ i
;
533 MultiByteToWideChar(CP_ACP
, 0, t
->path1
, -1, path1W
, ARRAY_SIZE(path1W
));
534 MultiByteToWideChar(CP_ACP
, 0, t
->path2
, -1, path2W
, ARRAY_SIZE(path2W
));
535 hr
= pPathAllocCombine(path1W
, path2W
, 0, &resultW
);
536 ok(hr
== S_OK
, "combine %s %s expect hr %#x, got %#x\n", t
->path1
, t
->path2
, S_OK
, hr
);
539 WideCharToMultiByte(CP_ACP
, 0, resultW
, -1, resultA
, ARRAY_SIZE(resultA
), NULL
, NULL
);
540 ok(!lstrcmpA(resultA
, t
->result
), "combine %s %s expect result %s, got %s\n", t
->path1
, t
->path2
, t
->result
,
547 static void test_PathCchCombine(void)
549 WCHAR expected
[PATHCCH_MAX_CCH
] = {'C', ':', '\\', 'a', 0};
550 WCHAR p1
[PATHCCH_MAX_CCH
] = {'C', ':', '\\', 0};
551 WCHAR p2
[PATHCCH_MAX_CCH
] = {'a', 0};
552 WCHAR output
[PATHCCH_MAX_CCH
];
556 if (!pPathCchCombine
)
558 win_skip("PathCchCombine() is not available.\n");
562 hr
= pPathCchCombine(output
, 5, NULL
, NULL
);
563 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
565 hr
= pPathCchCombine(NULL
, 2, p1
, p2
);
566 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
568 memset(output
, 0xff, sizeof(output
));
569 hr
= pPathCchCombine(output
, 0, p1
, p2
);
570 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
571 ok(output
[0] == 0xffff, "Expected output buffer to be unchanged\n");
573 memset(output
, 0xff, sizeof(output
));
574 hr
= pPathCchCombine(output
, 1, p1
, p2
);
575 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "Expected STRSAFE_E_INSUFFICIENT_BUFFER, got %08x\n", hr
);
576 ok(output
[0] == 0, "Expected output buffer to contain NULL string\n");
578 memset(output
, 0xff, sizeof(output
));
579 hr
= pPathCchCombine(output
, 4, p1
, p2
);
580 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "Expected STRSAFE_E_INSUFFICIENT_BUFFER, got %08x\n", hr
);
581 ok(output
[0] == 0x0, "Expected output buffer to contain NULL string\n");
583 memset(output
, 0xff, sizeof(output
));
584 hr
= pPathCchCombine(output
, 5, p1
, p2
);
585 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
586 ok(!lstrcmpW(output
, expected
), "Combination of %s + %s returned %s, expected %s\n", wine_dbgstr_w(p1
),
587 wine_dbgstr_w(p2
), wine_dbgstr_w(output
), wine_dbgstr_w(expected
));
589 hr
= pPathCchCombine(output
, PATHCCH_MAX_CCH
+ 1, p1
, p2
);
590 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
592 hr
= pPathCchCombine(output
, PATHCCH_MAX_CCH
, p1
, p2
);
593 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
595 for (i
= 0; i
< ARRAY_SIZE(combine_tests
); i
++)
597 MultiByteToWideChar(CP_ACP
, 0, combine_tests
[i
].path1
, -1, p1
, ARRAY_SIZE(p1
));
598 MultiByteToWideChar(CP_ACP
, 0, combine_tests
[i
].path2
, -1, p2
, ARRAY_SIZE(p2
));
599 MultiByteToWideChar(CP_ACP
, 0, combine_tests
[i
].result
, -1, expected
, ARRAY_SIZE(expected
));
601 hr
= pPathCchCombine(output
, ARRAY_SIZE(output
), p1
, p2
);
602 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
603 ok(!lstrcmpW(output
, expected
), "Combining %s with %s returned %s, expected %s\n", wine_dbgstr_w(p1
),
604 wine_dbgstr_w(p2
), wine_dbgstr_w(output
), wine_dbgstr_w(expected
));
608 static void test_PathCchCombineEx(void)
610 WCHAR expected
[MAX_PATH
] = {'C',':','\\','a',0};
611 WCHAR p1
[MAX_PATH
] = {'C',':','\\',0};
612 WCHAR p2
[MAX_PATH
] = {'a',0};
613 WCHAR output
[MAX_PATH
];
617 if (!pPathCchCombineEx
)
619 win_skip("PathCchCombineEx() is not available.\n");
624 hr
= pPathCchCombineEx(output
, 5, NULL
, NULL
, 0);
625 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
626 ok(output
[0] == 0, "Expected output buffer to be empty\n");
629 hr
= pPathCchCombineEx(NULL
, 2, p1
, p2
, 0);
630 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
631 ok(output
[0] == 0xff, "Expected output buffer to be unchanged\n");
633 memset(output
, 0xff, sizeof(output
));
634 hr
= pPathCchCombineEx(output
, 0, p1
, p2
, 0);
635 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
636 ok(output
[0] == 0xffff, "Expected output buffer to be unchanged\n");
638 memset(output
, 0xff, sizeof(output
));
639 hr
= pPathCchCombineEx(output
, 1, p1
, p2
, 0);
640 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "Expected STRSAFE_E_INSUFFICIENT_BUFFER, got %08x\n", hr
);
641 ok(output
[0] == 0, "Expected output buffer to contain NULL string\n");
643 memset(output
, 0xff, sizeof(output
));
644 hr
= pPathCchCombineEx(output
, 4, p1
, p2
, 0);
645 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "Expected STRSAFE_E_INSUFFICIENT_BUFFER, got %08x\n", hr
);
646 ok(output
[0] == 0x0, "Expected output buffer to contain NULL string\n");
649 hr
= pPathCchCombineEx(output
, PATHCCH_MAX_CCH
+ 1, p1
, p2
, 0);
650 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
651 ok(output
[0] == 0xff, "Expected output buffer to be 0xff\n");
653 hr
= pPathCchCombineEx(output
, PATHCCH_MAX_CCH
, p1
, p2
, 0);
654 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
656 memset(output
, 0xff, sizeof(output
));
657 hr
= pPathCchCombineEx(output
, 5, p1
, p2
, 0);
658 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
659 ok(!lstrcmpW(output
, expected
),
660 "Combination of %s + %s returned %s, expected %s\n",
661 wine_dbgstr_w(p1
), wine_dbgstr_w(p2
), wine_dbgstr_w(output
), wine_dbgstr_w(expected
));
663 for (i
= 0; i
< ARRAY_SIZE(combine_tests
); i
++)
665 MultiByteToWideChar(CP_ACP
, 0, combine_tests
[i
].path1
, -1, p1
, MAX_PATH
);
666 MultiByteToWideChar(CP_ACP
, 0, combine_tests
[i
].path2
, -1, p2
, MAX_PATH
);
667 MultiByteToWideChar(CP_ACP
, 0, combine_tests
[i
].result
, -1, expected
, MAX_PATH
);
669 hr
= pPathCchCombineEx(output
, MAX_PATH
, p1
, p2
, 0);
670 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
671 ok(!lstrcmpW(output
, expected
), "Combining %s with %s returned %s, expected %s\n",
672 wine_dbgstr_w(p1
), wine_dbgstr_w(p2
), wine_dbgstr_w(output
), wine_dbgstr_w(expected
));
676 struct addbackslash_test
685 static const struct addbackslash_test addbackslash_tests
[] =
687 { "C:", "C:\\", S_OK
, MAX_PATH
, MAX_PATH
- 3 },
688 { "a.txt", "a.txt\\", S_OK
, MAX_PATH
, MAX_PATH
- 6 },
689 { "a/b", "a/b\\", S_OK
, MAX_PATH
, MAX_PATH
- 4 },
691 { "C:\\", "C:\\", S_FALSE
, MAX_PATH
, MAX_PATH
- 3 },
692 { "C:\\", "C:\\", S_FALSE
, 4, 1 },
694 { "C:", "C:", STRSAFE_E_INSUFFICIENT_BUFFER
, 2, 0 },
695 { "C:", "C:", STRSAFE_E_INSUFFICIENT_BUFFER
, 3, 1 },
696 { "C:\\", "C:\\", STRSAFE_E_INSUFFICIENT_BUFFER
, 2, 0 },
697 { "C:\\", "C:\\", STRSAFE_E_INSUFFICIENT_BUFFER
, 3, 0 },
698 { "C:\\", "C:\\", STRSAFE_E_INSUFFICIENT_BUFFER
, 0, 0 },
699 { "C:", "C:", STRSAFE_E_INSUFFICIENT_BUFFER
, 0, 0 },
702 static void test_PathCchAddBackslash(void)
704 WCHAR pathW
[MAX_PATH
];
708 if (!pPathCchAddBackslash
)
710 win_skip("PathCchAddBackslash() is not available.\n");
715 hr
= pPathCchAddBackslash(pathW
, 0);
716 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
717 ok(pathW
[0] == 0, "Unexpected path.\n");
720 hr
= pPathCchAddBackslash(pathW
, 1);
721 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
722 ok(pathW
[0] == 0, "Unexpected path.\n");
725 hr
= pPathCchAddBackslash(pathW
, 2);
726 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
727 ok(pathW
[0] == 0, "Unexpected path.\n");
729 for (i
= 0; i
< ARRAY_SIZE(addbackslash_tests
); i
++)
731 const struct addbackslash_test
*test
= &addbackslash_tests
[i
];
734 MultiByteToWideChar(CP_ACP
, 0, test
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
735 hr
= pPathCchAddBackslash(pathW
, test
->size
);
736 ok(hr
== test
->hr
, "%u: unexpected return value %#x.\n", i
, hr
);
738 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, path
, ARRAY_SIZE(path
), NULL
, NULL
);
739 ok(!strcmp(path
, test
->result
), "%u: unexpected resulting path %s.\n", i
, path
);
743 static void test_PathCchAddBackslashEx(void)
745 WCHAR pathW
[MAX_PATH
];
751 if (!pPathCchAddBackslashEx
)
753 win_skip("PathCchAddBackslashEx() is not available.\n");
758 hr
= pPathCchAddBackslashEx(pathW
, 0, NULL
, NULL
);
759 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "Unexpected hr %#x.\n", hr
);
760 ok(pathW
[0] == 0, "Unexpected path.\n");
763 ptrW
= (void *)0xdeadbeef;
765 hr
= pPathCchAddBackslashEx(pathW
, 1, &ptrW
, &remaining
);
766 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
767 ok(pathW
[0] == 0, "Unexpected path.\n");
768 ok(ptrW
== pathW
, "Unexpected endptr %p.\n", ptrW
);
769 ok(remaining
== 1, "Unexpected remaining size.\n");
772 hr
= pPathCchAddBackslashEx(pathW
, 2, NULL
, NULL
);
773 ok(hr
== S_FALSE
, "Unexpected hr %#x.\n", hr
);
774 ok(pathW
[0] == 0, "Unexpected path.\n");
776 for (i
= 0; i
< ARRAY_SIZE(addbackslash_tests
); i
++)
778 const struct addbackslash_test
*test
= &addbackslash_tests
[i
];
781 MultiByteToWideChar(CP_ACP
, 0, test
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
782 hr
= pPathCchAddBackslashEx(pathW
, test
->size
, NULL
, NULL
);
783 ok(hr
== test
->hr
, "%u: unexpected return value %#x.\n", i
, hr
);
785 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, path
, ARRAY_SIZE(path
), NULL
, NULL
);
786 ok(!strcmp(path
, test
->result
), "%u: unexpected resulting path %s.\n", i
, path
);
788 ptrW
= (void *)0xdeadbeef;
790 MultiByteToWideChar(CP_ACP
, 0, test
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
791 hr
= pPathCchAddBackslashEx(pathW
, test
->size
, &ptrW
, &remaining
);
792 ok(hr
== test
->hr
, "%u: unexpected return value %#x.\n", i
, hr
);
795 ok(ptrW
== (pathW
+ lstrlenW(pathW
)), "%u: unexpected end pointer.\n", i
);
796 ok(remaining
== test
->remaining
, "%u: unexpected remaining buffer length.\n", i
);
800 ok(ptrW
== NULL
, "%u: unexpected end pointer.\n", i
);
801 ok(remaining
== 0, "%u: unexpected remaining buffer length.\n", i
);
806 struct addextension_test
809 const CHAR
*extension
;
810 const CHAR
*expected
;
814 static const struct addextension_test addextension_tests
[] =
817 {"", ".exe", ".exe", S_OK
},
818 {"C:\\", "", "C:\\", S_OK
},
819 {"C:", ".exe", "C:.exe", S_OK
},
820 {"C:\\", ".exe", "C:\\.exe", S_OK
},
821 {"\\", ".exe", "\\.exe", S_OK
},
822 {"\\\\", ".exe", "\\\\.exe", S_OK
},
823 {"\\\\?\\C:", ".exe", "\\\\?\\C:.exe", S_OK
},
824 {"\\\\?\\C:\\", ".exe", "\\\\?\\C:\\.exe", S_OK
},
825 {"\\\\?\\UNC\\", ".exe", "\\\\?\\UNC\\.exe", S_OK
},
826 {"\\\\?\\UNC\\192.168.1.1\\", ".exe", "\\\\?\\UNC\\192.168.1.1\\.exe", S_OK
},
827 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", ".exe",
828 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\.exe", S_OK
},
829 {"C:\\", "exe", "C:\\.exe", S_OK
},
830 {"C:\\", ".", "C:\\", S_OK
},
831 {"C:\\1.exe", ".txt", "C:\\1.exe", S_FALSE
},
833 /* Extension contains invalid characters but valid for PathCchAddExtension */
834 {"C:\\", "./", "C:\\./", S_OK
},
835 {"C:\\", ".?", "C:\\.?", S_OK
},
836 {"C:\\", ".%", "C:\\.%", S_OK
},
837 {"C:\\", ".*", "C:\\.*", S_OK
},
838 {"C:\\", ".:", "C:\\.:", S_OK
},
839 {"C:\\", ".|", "C:\\.|", S_OK
},
840 {"C:\\", ".\"", "C:\\.\"", S_OK
},
841 {"C:\\", ".<", "C:\\.<", S_OK
},
842 {"C:\\", ".>", "C:\\.>", S_OK
},
844 /* Invalid argument for extension */
845 {"C:\\", " exe", NULL
, E_INVALIDARG
},
846 {"C:\\", ". exe", NULL
, E_INVALIDARG
},
847 {"C:\\", " ", NULL
, E_INVALIDARG
},
848 {"C:\\", "\\", NULL
, E_INVALIDARG
},
849 {"C:\\", "..", NULL
, E_INVALIDARG
},
850 {"C:\\", ". ", NULL
, E_INVALIDARG
},
851 {"C:\\", ".\\", NULL
, E_INVALIDARG
},
852 {"C:\\", ".a.", NULL
, E_INVALIDARG
},
853 {"C:\\", ".a ", NULL
, E_INVALIDARG
},
854 {"C:\\", ".a\\", NULL
, E_INVALIDARG
},
855 {"C:\\1.exe", " ", NULL
, E_INVALIDARG
}
865 static const struct append_test append_tests
[] =
868 {"C:\\", "a", "C:\\a"},
869 {"C:\\b", "..\\a", "C:\\a"},
870 {"C:", "a", "C:\\a"},
871 {"C:\\", ".", "C:\\"},
872 {"C:\\", "..", "C:\\"},
873 {"C:\\a", "", "C:\\a"},
875 /* normal UNC paths */
876 {"\\\\192.168.1.1\\test", "a", "\\\\192.168.1.1\\test\\a"},
877 {"\\\\192.168.1.1\\test", "..", "\\\\192.168.1.1"},
878 {"\\a", "b", "\\a\\b"},
880 {"\\\\", "a", "\\\\a"},
881 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", "a",
882 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a"},
885 {"\\\\?\\C:\\", "a", "C:\\a"},
886 {"\\\\?\\C:\\", "..", "C:\\"},
887 {"\\\\?\\C:", "a", "C:\\a"},
890 {"\\\\?\\UNC\\", "a", "\\\\a"},
891 {"\\\\?\\UNC\\192.168.1.1\\test", "a", "\\\\192.168.1.1\\test\\a"},
892 {"\\\\?\\UNC\\192.168.1.1\\test", "..", "\\\\192.168.1.1"},
894 /* Second path begins with a single backslash */
895 {"C:a\\b", "\\1", "C:a\\b\\1"},
896 {"C:\\a\\b", "\\1", "C:\\a\\b\\1"},
897 {"\\a\\b", "\\1", "\\a\\b\\1"},
898 {"\\\\a\\b", "\\1", "\\\\a\\b\\1"},
899 {"\\\\a\\b\\c", "\\1", "\\\\a\\b\\c\\1"},
900 {"\\\\?\\UNC\\a", "\\1", "\\\\a\\1"},
901 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a", "\\1",
902 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a\\1"},
903 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", "\\1",
904 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\1"},
905 {"C:\\a\\b", "\\", "C:\\a\\b"},
907 /* Second path is fully qualified */
908 {"X:\\", "C:", "C:\\"},
909 {"X:\\", "C:\\", "C:\\"},
910 {"X:\\", "\\\\", "\\\\"},
911 {"X:\\", "\\\\?\\C:", "C:\\"},
912 {"X:\\", "\\\\?\\C:\\", "C:\\"},
913 {"X:\\", "\\\\?\\UNC\\", "\\\\"},
914 {"X:\\", "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\",
915 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\"},
917 /* Canonicalization */
918 {"C:\\a", ".\\b", "C:\\a\\b"},
919 {"C:\\a", "..\\b", "C:\\b"},
926 static void test_PathCchAppend(void)
928 WCHAR path1W
[PATHCCH_MAX_CCH
];
929 WCHAR path2W
[PATHCCH_MAX_CCH
];
930 CHAR path1A
[PATHCCH_MAX_CCH
];
936 win_skip("PathCchAppend() is not available.\n");
940 MultiByteToWideChar(CP_ACP
, 0, "\\a", -1, path1W
, ARRAY_SIZE(path1W
));
941 MultiByteToWideChar(CP_ACP
, 0, "\\b", -1, path2W
, ARRAY_SIZE(path2W
));
942 hr
= pPathCchAppend(NULL
, PATHCCH_MAX_CCH
, path2W
);
943 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
945 hr
= pPathCchAppend(path1W
, 0, path2W
);
946 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
948 hr
= pPathCchAppend(path1W
, PATHCCH_MAX_CCH
+ 1, path2W
);
949 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
951 hr
= pPathCchAppend(path1W
, PATHCCH_MAX_CCH
, NULL
);
952 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
953 WideCharToMultiByte(CP_ACP
, 0, path1W
, -1, path1A
, ARRAY_SIZE(path1A
), NULL
, NULL
);
954 ok(!lstrcmpA(path1A
, "\\a"), "expect \\a, got %s\n", path1A
);
956 for (i
= 0; i
< ARRAY_SIZE(append_tests
); i
++)
958 const struct append_test
*t
= append_tests
+ i
;
960 MultiByteToWideChar(CP_ACP
, 0, t
->path1
, -1, path1W
, ARRAY_SIZE(path1W
));
961 MultiByteToWideChar(CP_ACP
, 0, t
->path2
, -1, path2W
, ARRAY_SIZE(path2W
));
962 hr
= pPathCchAppend(path1W
, PATHCCH_MAX_CCH
, path2W
);
963 ok(hr
== S_OK
, "append \"%s\" \"%s\" expect hr %#x, got %#x\n", t
->path1
, t
->path2
, S_OK
, hr
);
966 WideCharToMultiByte(CP_ACP
, 0, path1W
, -1, path1A
, ARRAY_SIZE(path1A
), NULL
, NULL
);
967 ok(!lstrcmpA(path1A
, t
->result
), "append \"%s\" \"%s\" expect result \"%s\", got \"%s\"\n", t
->path1
,
968 t
->path2
, t
->result
, path1A
);
973 static void test_PathCchAppendEx(void)
975 WCHAR path1W
[PATHCCH_MAX_CCH
];
976 WCHAR path2W
[PATHCCH_MAX_CCH
];
977 CHAR path1A
[PATHCCH_MAX_CCH
];
981 if (!pPathCchAppendEx
)
983 win_skip("PathCchAppendEx() is not available.\n");
987 MultiByteToWideChar(CP_ACP
, 0, "\\a", -1, path1W
, ARRAY_SIZE(path1W
));
988 MultiByteToWideChar(CP_ACP
, 0, "\\b", -1, path2W
, ARRAY_SIZE(path2W
));
989 hr
= pPathCchAppendEx(NULL
, ARRAY_SIZE(path1W
), path2W
, 0);
990 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
992 hr
= pPathCchAppendEx(path1W
, 0, path2W
, 0);
993 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
994 ok(path1W
[0] == '\\', "expect path1 unchanged\n");
996 hr
= pPathCchAppendEx(path1W
, PATHCCH_MAX_CCH
+ 1, path2W
, 0);
997 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
998 ok(path1W
[0] == '\\', "expect path1 unchanged\n");
1000 hr
= pPathCchAppendEx(path1W
, ARRAY_SIZE(path1W
), NULL
, 0);
1001 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
1002 WideCharToMultiByte(CP_ACP
, 0, path1W
, -1, path1A
, ARRAY_SIZE(path1A
), NULL
, NULL
);
1003 ok(!lstrcmpA(path1A
, "\\a"), "expect \\a, got %s\n", path1A
);
1005 hr
= pPathCchAppendEx(path1W
, PATHCCH_MAX_CCH
, path2W
, 0);
1006 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
1008 for (i
= 0; i
< ARRAY_SIZE(append_tests
); i
++)
1010 const struct append_test
*t
= append_tests
+ i
;
1012 MultiByteToWideChar(CP_ACP
, 0, t
->path1
, -1, path1W
, ARRAY_SIZE(path1W
));
1013 MultiByteToWideChar(CP_ACP
, 0, t
->path2
, -1, path2W
, ARRAY_SIZE(path2W
));
1014 hr
= pPathCchAppendEx(path1W
, PATHCCH_MAX_CCH
, path2W
, 0);
1015 ok(hr
== S_OK
, "append \"%s\" \"%s\" expect hr %#x, got %#x\n", t
->path1
, t
->path2
, S_OK
, hr
);
1018 WideCharToMultiByte(CP_ACP
, 0, path1W
, -1, path1A
, ARRAY_SIZE(path1A
), NULL
, NULL
);
1019 ok(!lstrcmpA(path1A
, t
->result
), "append \"%s\" \"%s\" expect result \"%s\", got \"%s\"\n", t
->path1
,
1020 t
->path2
, t
->result
, path1A
);
1025 static void test_PathCchAddExtension(void)
1027 WCHAR pathW
[PATHCCH_MAX_CCH
+ 1];
1028 CHAR pathA
[PATHCCH_MAX_CCH
+ 1];
1029 WCHAR extensionW
[MAX_PATH
];
1033 if (!pPathCchAddExtension
)
1035 win_skip("PathCchAddExtension() is not available.\n");
1039 /* Arguments check */
1040 MultiByteToWideChar(CP_ACP
, 0, "C:\\", -1, pathW
, ARRAY_SIZE(pathW
));
1041 MultiByteToWideChar(CP_ACP
, 0, ".exe", -1, extensionW
, ARRAY_SIZE(extensionW
));
1043 hr
= pPathCchAddExtension(NULL
, PATHCCH_MAX_CCH
, extensionW
);
1044 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1046 hr
= pPathCchAddExtension(pathW
, 0, extensionW
);
1047 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1049 hr
= pPathCchAddExtension(pathW
, PATHCCH_MAX_CCH
, NULL
);
1050 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1052 /* Path length check */
1053 hr
= pPathCchAddExtension(pathW
, ARRAY_SIZE("C:\\.exe") - 1, extensionW
);
1054 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "expect result %#x, got %#x\n", STRSAFE_E_INSUFFICIENT_BUFFER
, hr
);
1056 hr
= pPathCchAddExtension(pathW
, PATHCCH_MAX_CCH
+ 1, extensionW
);
1057 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1059 hr
= pPathCchAddExtension(pathW
, PATHCCH_MAX_CCH
, extensionW
);
1060 ok(hr
== S_OK
, "expect result %#x, got %#x\n", S_OK
, hr
);
1062 for (i
= 0; i
< ARRAY_SIZE(addextension_tests
); i
++)
1064 const struct addextension_test
*t
= addextension_tests
+ i
;
1065 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
1066 MultiByteToWideChar(CP_ACP
, 0, t
->extension
, -1, extensionW
, ARRAY_SIZE(extensionW
));
1067 hr
= pPathCchAddExtension(pathW
, PATHCCH_MAX_CCH
, extensionW
);
1068 ok(hr
== t
->hr
, "path %s extension %s expect result %#x, got %#x\n", t
->path
, t
->extension
, t
->hr
, hr
);
1071 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, pathA
, ARRAY_SIZE(pathA
), NULL
, NULL
);
1072 ok(!lstrcmpA(pathA
, t
->expected
), "path %s extension %s expect output path %s, got %s\n", t
->path
,
1073 t
->extension
, t
->expected
, pathA
);
1078 static void test_PathCchCanonicalize(void)
1080 WCHAR path_inW
[MAX_PATH
], path_outW
[MAX_PATH
];
1081 CHAR path_outA
[MAX_PATH
];
1085 if (!pPathCchCanonicalize
)
1087 win_skip("PathCchCanonicalize() is not available.\n");
1091 /* No NULL check for path pointers on Windows */
1094 hr
= pPathCchCanonicalize(NULL
, ARRAY_SIZE(path_outW
), path_inW
);
1095 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1097 /* MSDN says NULL path_in result in a backslash added to path_out, but the fact is that it would crash */
1098 hr
= pPathCchCanonicalize(path_outW
, ARRAY_SIZE(path_outW
), NULL
);
1099 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1103 hr
= pPathCchCanonicalize(path_outW
, 0, path_inW
);
1104 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1106 /* Test path length */
1107 for (i
= 0; i
< MAX_PATH
- 3; i
++) path_inW
[i
] = 'a';
1108 path_inW
[MAX_PATH
- 3] = '\0';
1109 memset(path_outW
, 0, sizeof(path_outW
));
1110 hr
= pPathCchCanonicalize(path_outW
, ARRAY_SIZE(path_outW
), path_inW
);
1111 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), "expect hr %#x, got %#x %s\n",
1112 HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), hr
, wine_dbgstr_w(path_outW
));
1113 ok(!*path_outW
, "got %d\n", lstrlenW(path_outW
));
1118 hr
= pPathCchCanonicalize(path_outW
, ARRAY_SIZE(path_outW
), path_inW
);
1119 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
1121 path_inW
[MAX_PATH
- 4] = '\0';
1122 hr
= pPathCchCanonicalize(path_outW
, ARRAY_SIZE(path_outW
), path_inW
);
1123 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
1125 /* Insufficient buffer size handling */
1126 hr
= pPathCchCanonicalize(path_outW
, 1, path_inW
);
1127 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "expect hr %#x, got %#x\n", STRSAFE_E_INSUFFICIENT_BUFFER
, hr
);
1129 for (i
= 0; i
< ARRAY_SIZE(alloccanonicalize_tests
); i
++)
1131 const struct alloccanonicalize_test
*t
= alloccanonicalize_tests
+ i
;
1133 /* Skip testing X: path input, this case is different compared to PathAllocCanonicalize */
1134 /* Skip test cases where a flag is used */
1135 if (!lstrcmpA("C:", t
->path_in
) || t
->flags
) continue;
1137 MultiByteToWideChar(CP_ACP
, 0, t
->path_in
, -1, path_inW
, ARRAY_SIZE(path_inW
));
1138 hr
= pPathCchCanonicalize(path_outW
, ARRAY_SIZE(path_outW
), path_inW
);
1139 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path_in
, t
->hr
, hr
);
1142 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
1143 ok(!lstrcmpA(path_outA
, t
->path_out
), "path \"%s\" expect output path \"%s\", got \"%s\"\n", t
->path_in
,
1144 t
->path_out
, path_outA
);
1149 /* Fill a \ at the end of X: if there is enough space */
1150 MultiByteToWideChar(CP_ACP
, 0, "C:", -1, path_inW
, ARRAY_SIZE(path_inW
));
1151 hr
= pPathCchCanonicalize(path_outW
, ARRAY_SIZE(path_outW
), path_inW
);
1152 ok(hr
== S_OK
, "path %s expect result %#x, got %#x\n", "C:", S_OK
, hr
);
1155 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
1156 ok(!lstrcmpA(path_outA
, "C:\\"), "path \"%s\" expect output path \"%s\", got \"%s\"\n", "C:", "C:\\",
1160 /* Don't fill a \ at the end of X: if there isn't enough space */
1161 MultiByteToWideChar(CP_ACP
, 0, "C:", -1, path_inW
, ARRAY_SIZE(path_inW
));
1162 hr
= pPathCchCanonicalize(path_outW
, 3, path_inW
);
1163 ok(hr
== S_OK
, "path %s expect result %#x, got %#x\n", "C:", S_OK
, hr
);
1166 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
1167 ok(!lstrcmpA(path_outA
, "C:"), "path \"%s\" expect output path \"%s\", got \"%s\"\n", "C:", "C:\\", path_outA
);
1170 /* Don't fill a \ at the end of X: if there is character following X: */
1171 MultiByteToWideChar(CP_ACP
, 0, "C:a", -1, path_inW
, ARRAY_SIZE(path_inW
));
1172 hr
= pPathCchCanonicalize(path_outW
, ARRAY_SIZE(path_outW
), path_inW
);
1173 ok(hr
== S_OK
, "path %s expect result %#x, got %#x\n", "C:a", S_OK
, hr
);
1176 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
1177 ok(!lstrcmpA(path_outA
, "C:a"), "path \"%s\" expect output path \"%s\", got \"%s\"\n", "C:a", "C:a", path_outA
);
1181 static void test_PathCchCanonicalizeEx(void)
1183 WCHAR path_inW
[PATHCCH_MAX_CCH
+ 1], path_outW
[PATHCCH_MAX_CCH
];
1184 CHAR path_outA
[4096];
1185 BOOL skip_new_flags
= TRUE
;
1189 if (!pPathCchCanonicalizeEx
)
1191 win_skip("PathCchCanonicalizeEx() is not available.\n");
1195 /* No NULL check for path pointers on Windows */
1198 hr
= pPathCchCanonicalizeEx(NULL
, ARRAY_SIZE(path_outW
), path_inW
, 0);
1199 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1201 /* MSDN says NULL path_in result in a backslash added to path_out, but the fact is that it would crash */
1202 hr
= pPathCchCanonicalizeEx(path_outW
, ARRAY_SIZE(path_outW
), NULL
, 0);
1203 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1206 path_outW
[0] = 0xff;
1207 hr
= pPathCchCanonicalizeEx(path_outW
, 0, path_inW
, 0);
1208 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1209 ok(path_outW
[0] = 0xff, "expect path_outW unchanged\n");
1211 /* Test path length */
1212 for (i
= 0; i
< ARRAY_SIZE(path_inW
) - 1; i
++) path_inW
[i
] = 'a';
1213 path_inW
[PATHCCH_MAX_CCH
] = '\0';
1214 hr
= pPathCchCanonicalizeEx(path_outW
, ARRAY_SIZE(path_outW
), path_inW
, PATHCCH_ALLOW_LONG_PATHS
);
1215 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), "expect hr %#x, got %#x\n",
1216 HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), hr
);
1218 path_inW
[PATHCCH_MAX_CCH
- 1] = '\0';
1219 hr
= pPathCchCanonicalizeEx(path_outW
, ARRAY_SIZE(path_outW
), path_inW
, PATHCCH_ALLOW_LONG_PATHS
);
1220 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
1222 hr
= pPathCchCanonicalizeEx(path_outW
, 1, path_inW
, PATHCCH_ALLOW_LONG_PATHS
);
1223 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), "expect hr %#x, got %#x\n",
1224 HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), hr
);
1226 /* No root and path > MAX_PATH - 4, return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) */
1227 path_inW
[MAX_PATH
- 3] = '\0';
1228 hr
= pPathCchCanonicalizeEx(path_outW
, 1, path_inW
, 0);
1229 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), "expect hr %#x, got %#x\n",
1230 HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE
), hr
);
1232 /* Has root and path > MAX_PATH - 4 */
1236 hr
= pPathCchCanonicalizeEx(path_outW
, 1, path_inW
, 0);
1237 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "expect hr %#x, got %#x\n", STRSAFE_E_INSUFFICIENT_BUFFER
, hr
);
1240 path_inW
[1] = path_inW
[2] = 'a';
1241 hr
= pPathCchCanonicalizeEx(path_outW
, 1, path_inW
, 0);
1242 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "expect hr %#x, got %#x\n", STRSAFE_E_INSUFFICIENT_BUFFER
, hr
);
1244 path_inW
[0] = path_inW
[1] = '\\';
1246 hr
= pPathCchCanonicalizeEx(path_outW
, 1, path_inW
, 0);
1247 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "expect hr %#x, got %#x\n", STRSAFE_E_INSUFFICIENT_BUFFER
, hr
);
1249 /* path <= MAX_PATH - 4 */
1250 path_inW
[0] = path_inW
[1] = path_inW
[2] = 'a';
1251 path_inW
[MAX_PATH
- 4] = '\0';
1252 hr
= pPathCchCanonicalizeEx(path_outW
, 1, path_inW
, 0);
1253 ok(hr
== STRSAFE_E_INSUFFICIENT_BUFFER
, "expect hr %#x, got %#x\n", STRSAFE_E_INSUFFICIENT_BUFFER
, hr
);
1255 /* Check if flags added after Windows 10 1709 are supported */
1256 MultiByteToWideChar(CP_ACP
, 0, "C:\\", -1, path_inW
, ARRAY_SIZE(path_inW
));
1257 hr
= pPathCchCanonicalizeEx(path_outW
, ARRAY_SIZE(path_outW
), path_inW
, PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS
);
1258 if (hr
== E_INVALIDARG
) skip_new_flags
= FALSE
;
1260 for (i
= 0; i
< ARRAY_SIZE(alloccanonicalize_tests
); i
++)
1262 const struct alloccanonicalize_test
*t
= alloccanonicalize_tests
+ i
;
1264 /* Skip testing X: path input, this case is different compared to PathAllocCanonicalize */
1265 if (!lstrcmpA("C:", t
->path_in
)) continue;
1267 if (((PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS
| PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS
1268 | PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
| PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH
1269 | PATHCCH_ENSURE_TRAILING_SLASH
)
1273 win_skip("Skip testing new flags added after Windows 10 1709\n");
1277 MultiByteToWideChar(CP_ACP
, 0, t
->path_in
, -1, path_inW
, ARRAY_SIZE(path_inW
));
1278 hr
= pPathCchCanonicalizeEx(path_outW
, ARRAY_SIZE(path_outW
), path_inW
, t
->flags
);
1279 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path_in
, t
->hr
, hr
);
1282 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
1283 ok(!lstrcmpA(path_outA
, t
->path_out
), "path \"%s\" expect output path \"%s\", got \"%s\"\n", t
->path_in
,
1284 t
->path_out
, path_outA
);
1289 /* Fill a \ at the end of X: if there is enough space */
1290 MultiByteToWideChar(CP_ACP
, 0, "C:", -1, path_inW
, ARRAY_SIZE(path_inW
));
1291 hr
= pPathCchCanonicalizeEx(path_outW
, ARRAY_SIZE(path_outW
), path_inW
, 0);
1292 ok(hr
== S_OK
, "path %s expect result %#x, got %#x\n", "C:", S_OK
, hr
);
1295 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
1296 ok(!lstrcmpA(path_outA
, "C:\\"), "path \"%s\" expect output path \"%s\", got \"%s\"\n", "C:", "C:\\",
1300 /* Don't fill a \ at the end of X: if there isn't enough space */
1301 MultiByteToWideChar(CP_ACP
, 0, "C:", -1, path_inW
, ARRAY_SIZE(path_inW
));
1302 hr
= pPathCchCanonicalizeEx(path_outW
, 3, path_inW
, 0);
1303 ok(hr
== S_OK
, "path %s expect result %#x, got %#x\n", "C:", S_OK
, hr
);
1306 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
1307 ok(!lstrcmpA(path_outA
, "C:"), "path \"%s\" expect output path \"%s\", got \"%s\"\n", "C:", "C:\\", path_outA
);
1310 /* Don't fill a \ at the end of X: if there is character following X: */
1311 MultiByteToWideChar(CP_ACP
, 0, "C:a", -1, path_inW
, ARRAY_SIZE(path_inW
));
1312 hr
= pPathCchCanonicalizeEx(path_outW
, ARRAY_SIZE(path_outW
), path_inW
, 0);
1313 ok(hr
== S_OK
, "path %s expect result %#x, got %#x\n", "C:a", S_OK
, hr
);
1316 WideCharToMultiByte(CP_ACP
, 0, path_outW
, -1, path_outA
, ARRAY_SIZE(path_outA
), NULL
, NULL
);
1317 ok(!lstrcmpA(path_outA
, "C:a"), "path \"%s\" expect output path \"%s\", got \"%s\"\n", "C:a", "C:a", path_outA
);
1321 struct findextension_test
1324 INT extension_offset
;
1327 static const struct findextension_test findextension_tests
[] =
1335 {"\\\\?\\C:1.exe", 7},
1336 {"\\\\?\\C:\\1.exe", 8},
1337 {"\\\\?\\UNC\\1.exe", 9},
1338 {"\\\\?\\UNC\\192.168.1.1\\1.exe", 21},
1339 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1.exe", 50},
1341 /* Contains forward slash */
1345 {"C:\\a/b/1.exe", 8},
1359 {"\\\\?\\UNC\\192.168.1.1", 17},
1360 {"\\\\?\\UNC\\192.168.1.1\\", 20},
1361 {"\\\\?\\UNC\\192.168.1.1\\a", 21}
1364 static void test_PathCchFindExtension(void)
1366 WCHAR pathW
[PATHCCH_MAX_CCH
+ 1] = {0};
1367 const WCHAR
*extension
;
1371 if (!pPathCchFindExtension
)
1373 win_skip("PathCchFindExtension() is not available.\n");
1377 /* Arguments check */
1378 extension
= (const WCHAR
*)0xdeadbeef;
1379 hr
= pPathCchFindExtension(NULL
, PATHCCH_MAX_CCH
, &extension
);
1380 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1381 ok(extension
== NULL
, "Expect extension null, got %p\n", extension
);
1383 extension
= (const WCHAR
*)0xdeadbeef;
1384 hr
= pPathCchFindExtension(pathW
, 0, &extension
);
1385 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1386 ok(extension
== NULL
, "Expect extension null, got %p\n", extension
);
1388 /* Crashed on Windows */
1391 hr
= pPathCchFindExtension(pathW
, PATHCCH_MAX_CCH
, NULL
);
1392 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1395 /* Path length check */
1396 /* size == PATHCCH_MAX_CCH + 1 */
1397 MultiByteToWideChar(CP_ACP
, 0, "C:\\1.exe", -1, pathW
, ARRAY_SIZE(pathW
));
1398 hr
= pPathCchFindExtension(pathW
, PATHCCH_MAX_CCH
+ 1, &extension
);
1399 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1401 /* Size == path length + 1*/
1402 hr
= pPathCchFindExtension(pathW
, ARRAY_SIZE("C:\\1.exe"), &extension
);
1403 ok(hr
== S_OK
, "expect result %#x, got %#x\n", S_OK
, hr
);
1404 ok(*extension
== '.', "wrong extension value\n");
1406 /* Size < path length + 1 */
1407 extension
= (const WCHAR
*)0xdeadbeef;
1408 hr
= pPathCchFindExtension(pathW
, ARRAY_SIZE("C:\\1.exe") - 1, &extension
);
1409 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1410 ok(extension
== NULL
, "Expect extension null, got %p\n", extension
);
1412 /* Size == PATHCCH_MAX_CCH */
1413 hr
= pPathCchFindExtension(pathW
, PATHCCH_MAX_CCH
, &extension
);
1414 ok(hr
== S_OK
, "expect result %#x, got %#x\n", S_OK
, hr
);
1416 /* Path length + 1 > PATHCCH_MAX_CCH */
1417 for (i
= 0; i
< ARRAY_SIZE(pathW
) - 1; i
++) pathW
[i
] = 'a';
1418 pathW
[PATHCCH_MAX_CCH
] = 0;
1419 hr
= pPathCchFindExtension(pathW
, PATHCCH_MAX_CCH
, &extension
);
1420 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1422 /* Path length + 1 == PATHCCH_MAX_CCH */
1423 pathW
[PATHCCH_MAX_CCH
- 1] = 0;
1424 hr
= pPathCchFindExtension(pathW
, PATHCCH_MAX_CCH
, &extension
);
1425 ok(hr
== S_OK
, "expect result %#x, got %#x\n", S_OK
, hr
);
1427 for (i
= 0; i
< ARRAY_SIZE(findextension_tests
); i
++)
1429 const struct findextension_test
*t
= findextension_tests
+ i
;
1430 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
1431 hr
= pPathCchFindExtension(pathW
, PATHCCH_MAX_CCH
, &extension
);
1432 ok(hr
== S_OK
, "path %s expect result %#x, got %#x\n", t
->path
, S_OK
, hr
);
1434 ok(extension
- pathW
== t
->extension_offset
, "path %s expect extension offset %d, got %ld\n", t
->path
,
1435 t
->extension_offset
, (UINT_PTR
)(extension
- pathW
));
1445 static const struct isroot_test isroot_tests
[] =
1452 {"\\\\?\\C:\\", TRUE
},
1453 {"\\\\?\\C:", FALSE
},
1454 {"\\\\?\\C:\\a", FALSE
},
1462 {"\\\\a\\b\\", FALSE
},
1463 {"\\\\a\\b\\c", FALSE
},
1464 {"\\\\?\\UNC\\", TRUE
},
1465 {"\\\\?\\UNC\\a", TRUE
},
1466 {"\\\\?\\UNC\\a\\", FALSE
},
1467 {"\\\\?\\UNC\\a\\b", TRUE
},
1468 {"\\\\?\\UNC\\a\\b\\", FALSE
},
1469 {"\\\\?\\UNC\\a\\b\\c", FALSE
},
1470 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", FALSE
},
1471 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", TRUE
},
1472 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", FALSE
},
1475 /* Wrong MSDN examples */
1481 static void test_PathCchIsRoot(void)
1483 WCHAR pathW
[MAX_PATH
];
1487 if (!pPathCchIsRoot
)
1489 win_skip("PathCchIsRoot() is not available.\n");
1493 ret
= pPathCchIsRoot(NULL
);
1494 ok(ret
== FALSE
, "expect return FALSE\n");
1496 for (i
= 0; i
< ARRAY_SIZE(isroot_tests
); i
++)
1498 const struct isroot_test
*t
= isroot_tests
+ i
;
1499 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
1500 ret
= pPathCchIsRoot(pathW
);
1501 ok(ret
== t
->ret
, "path %s expect return %d, got %d\n", t
->path
, t
->ret
, ret
);
1505 struct removebackslashex_test
1507 const CHAR
*path_in
;
1508 const CHAR
*path_out
;
1514 static const struct removebackslashex_test removebackslashex_tests
[] =
1516 {"", "", 0, 1, S_FALSE
},
1517 {"C", "C", 1, 1, S_FALSE
},
1518 {"C\\", "C", 1, 2, S_OK
},
1519 {"C:", "C:", 2, 1, S_FALSE
},
1520 {"C:\\", "C:\\", 2, 2, S_FALSE
},
1521 {"C:\\\\", "C:\\", 3, 2, S_OK
},
1522 {"C:\\a\\", "C:\\a", 4, 2, S_OK
},
1523 {"C:\\a\\\\", "C:\\a\\", 5, 2, S_OK
},
1524 {"\\", "\\", 0, 2, S_FALSE
},
1525 {"\\\\", "\\\\", 1, 2, S_FALSE
},
1526 {"\\?\\", "\\?", 2, 2, S_OK
},
1527 {"\\?\\\\", "\\?\\", 3, 2, S_OK
},
1528 {"\\a\\", "\\a", 2, 2, S_OK
},
1529 {"\\a\\\\", "\\a\\", 3, 2, S_OK
},
1530 {"\\\\a\\", "\\\\a", 3, 2, S_OK
},
1531 {"\\\\a\\b\\", "\\\\a\\b", 5, 2, S_OK
},
1532 {"\\\\a\\\\", "\\\\a\\", 4, 2, S_OK
},
1533 {"\\\\?\\", "\\\\?", 3, 2, S_OK
},
1534 {"\\\\?\\\\", "\\\\?\\", 4, 2, S_OK
},
1535 {"\\\\?\\C:", "\\\\?\\C:", 6, 1, S_FALSE
},
1536 {"\\\\?\\C:\\", "\\\\?\\C:\\", 6, 2, S_FALSE
},
1537 {"\\?\\UNC\\", "\\?\\UNC", 6, 2, S_OK
},
1538 {"\\\\?\\UNC", "\\\\?\\UNC", 7, 1, S_FALSE
},
1539 {"\\\\?\\UNC\\", "\\\\?\\UNC\\", 7, 2, S_FALSE
},
1540 {"\\\\?\\UNC\\a", "\\\\?\\UNC\\a", 9, 1, S_FALSE
},
1541 {"\\\\?\\UNC\\a\\", "\\\\?\\UNC\\a", 9, 2, S_OK
},
1542 {"\\\\?\\UNC\\a\\b\\", "\\\\?\\UNC\\a\\b", 11, 2, S_OK
},
1543 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}",
1544 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", 48, 1, S_FALSE
},
1545 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\",
1546 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", 48, 2, S_FALSE
},
1547 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a",
1548 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", 50, 1, S_FALSE
},
1549 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\",
1550 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", 50, 2, S_OK
}
1553 static void test_PathCchRemoveBackslash(void)
1555 WCHAR pathW
[PATHCCH_MAX_CCH
];
1556 CHAR pathA
[PATHCCH_MAX_CCH
];
1561 if (!pPathCchRemoveBackslash
)
1563 win_skip("PathCchRemoveBackslash() is not available.\n");
1567 /* No NULL check for path on Windows */
1570 hr
= pPathCchRemoveBackslash(NULL
, PATHCCH_MAX_CCH
);
1571 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1574 MultiByteToWideChar(CP_ACP
, 0, "C:\\a\\", -1, pathW
, ARRAY_SIZE(pathW
));
1575 hr
= pPathCchRemoveBackslash(pathW
, 0);
1576 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1578 hr
= pPathCchRemoveBackslash(pathW
, PATHCCH_MAX_CCH
+ 1);
1579 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
1581 hr
= pPathCchRemoveBackslash(pathW
, PATHCCH_MAX_CCH
);
1582 ok(hr
== S_FALSE
, "expect hr %#x, got %#x\n", S_FALSE
, hr
);
1584 for (i
= 0; i
< ARRAY_SIZE(removebackslashex_tests
); i
++)
1586 const struct removebackslashex_test
*t
= removebackslashex_tests
+ i
;
1587 path_size
= MultiByteToWideChar(CP_ACP
, 0, t
->path_in
, -1, pathW
, ARRAY_SIZE(pathW
));
1588 hr
= pPathCchRemoveBackslash(pathW
, path_size
);
1589 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path_in
, t
->hr
, hr
);
1592 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, pathA
, ARRAY_SIZE(pathA
), NULL
, NULL
);
1593 ok(!lstrcmpA(pathA
, t
->path_out
), "path %s expect output path %s, got %s\n", t
->path_in
, t
->path_out
,
1599 static void test_PathCchRemoveBackslashEx(void)
1601 WCHAR pathW
[PATHCCH_MAX_CCH
];
1602 CHAR pathA
[PATHCCH_MAX_CCH
];
1604 SIZE_T path_size
, free_size
;
1608 if (!pPathCchRemoveBackslashEx
)
1610 win_skip("PathCchRemoveBackslashEx() is not available.\n");
1614 /* No NULL check for path on Windows */
1617 hr
= pPathCchRemoveBackslashEx(NULL
, 0, &path_end
, &path_size
);
1618 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1621 path_size
= MultiByteToWideChar(CP_ACP
, 0, "C:\\a\\", -1, pathW
, ARRAY_SIZE(pathW
));
1622 hr
= pPathCchRemoveBackslashEx(pathW
, 0, &path_end
, &path_size
);
1623 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1625 free_size
= 0xdeadbeef;
1626 hr
= pPathCchRemoveBackslashEx(pathW
, path_size
, NULL
, &free_size
);
1627 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1628 ok(free_size
== 0, "expect %d, got %lu\n", 0, free_size
);
1630 path_end
= (WCHAR
*)0xdeadbeef;
1631 hr
= pPathCchRemoveBackslashEx(pathW
, path_size
, &path_end
, NULL
);
1632 ok(hr
== E_INVALIDARG
, "expect hr %#x, got %#x\n", E_INVALIDARG
, hr
);
1633 ok(path_end
== NULL
, "expect null, got %p\n", path_end
);
1635 hr
= pPathCchRemoveBackslashEx(pathW
, PATHCCH_MAX_CCH
+ 1, &path_end
, &free_size
);
1636 ok(hr
== S_OK
, "expect hr %#x, got %#x\n", S_OK
, hr
);
1638 hr
= pPathCchRemoveBackslashEx(pathW
, PATHCCH_MAX_CCH
, &path_end
, &free_size
);
1639 ok(hr
== S_FALSE
, "expect hr %#x, got %#x\n", S_FALSE
, hr
);
1641 /* Size < original path length + 1, don't read beyond size */
1642 MultiByteToWideChar(CP_ACP
, 0, "C:\\a", -1, pathW
, ARRAY_SIZE(pathW
));
1643 hr
= pPathCchRemoveBackslashEx(pathW
, ARRAY_SIZE("C:\\a") - 1, &path_end
, &free_size
);
1644 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1646 for (i
= 0; i
< ARRAY_SIZE(removebackslashex_tests
); i
++)
1648 const struct removebackslashex_test
*t
= removebackslashex_tests
+ i
;
1649 path_size
= MultiByteToWideChar(CP_ACP
, 0, t
->path_in
, -1, pathW
, ARRAY_SIZE(pathW
));
1650 hr
= pPathCchRemoveBackslashEx(pathW
, path_size
, &path_end
, &free_size
);
1651 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path_in
, t
->hr
, hr
);
1654 ok(path_end
- pathW
== t
->end_offset
, "path %s expect end offset %d, got %ld\n", t
->path_in
, t
->end_offset
,
1655 (INT_PTR
)(path_end
- pathW
));
1656 ok(free_size
== t
->free_size
, "path %s expect free size %lu, got %lu\n", t
->path_in
, t
->free_size
, free_size
);
1657 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, pathA
, ARRAY_SIZE(pathA
), NULL
, NULL
);
1658 ok(!lstrcmpA(pathA
, t
->path_out
), "path %s expect output path %s, got %s\n", t
->path_in
, t
->path_out
,
1664 struct removeextension_test
1667 const CHAR
*expected
;
1671 static const struct removeextension_test removeextension_tests
[] =
1673 {"1.exe", "1", S_OK
},
1674 {"C:1.exe", "C:1", S_OK
},
1675 {"C:\\1.exe", "C:\\1", S_OK
},
1676 {"\\1.exe", "\\1", S_OK
},
1677 {"\\\\1.exe", "\\\\1", S_OK
},
1678 {"\\\\?\\C:1.exe", "\\\\?\\C:1", S_OK
},
1679 {"\\\\?\\C:\\1.exe", "\\\\?\\C:\\1", S_OK
},
1680 {"\\\\?\\UNC\\1.exe", "\\\\?\\UNC\\1", S_OK
},
1681 {"\\\\?\\UNC\\192.168.1.1\\1.exe", "\\\\?\\UNC\\192.168.1.1\\1", S_OK
},
1682 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1.exe",
1683 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1", S_OK
},
1687 {" ", " ", S_FALSE
},
1690 {"a", "a", S_FALSE
},
1692 {".a.b.", ".a.b", S_OK
},
1693 {"a. ", "a. ", S_FALSE
},
1694 {"a.\\", "a.\\", S_FALSE
},
1695 {"\\\\?\\UNC\\192.168.1.1", "\\\\?\\UNC\\192.168.1", S_OK
},
1696 {"\\\\?\\UNC\\192.168.1.1\\", "\\\\?\\UNC\\192.168.1.1\\", S_FALSE
},
1697 {"\\\\?\\UNC\\192.168.1.1\\a", "\\\\?\\UNC\\192.168.1.1\\a", S_FALSE
}
1700 static void test_PathCchRemoveExtension(void)
1702 WCHAR pathW
[PATHCCH_MAX_CCH
] = {0};
1703 CHAR pathA
[PATHCCH_MAX_CCH
];
1707 if (!pPathCchRemoveExtension
)
1709 win_skip("PathCchRemoveExtension() is not available.\n");
1713 /* Arguments check */
1714 hr
= pPathCchRemoveExtension(NULL
, PATHCCH_MAX_CCH
);
1715 ok(hr
== E_INVALIDARG
, "expect %#x, got %#x\n", E_INVALIDARG
, hr
);
1717 hr
= pPathCchRemoveExtension(pathW
, 0);
1718 ok(hr
== E_INVALIDARG
, "expect %#x, got %#x\n", E_INVALIDARG
, hr
);
1720 hr
= pPathCchRemoveExtension(pathW
, PATHCCH_MAX_CCH
+ 1);
1721 ok(hr
== E_INVALIDARG
, "expect %#x, got %#x\n", E_INVALIDARG
, hr
);
1723 hr
= pPathCchRemoveExtension(pathW
, PATHCCH_MAX_CCH
);
1724 ok(hr
== S_FALSE
, "expect %#x, got %#x\n", S_FALSE
, hr
);
1726 /* Size < original path length + 1 */
1727 MultiByteToWideChar(CP_ACP
, 0, "C:\\1.exe", -1, pathW
, ARRAY_SIZE(pathW
));
1728 hr
= pPathCchRemoveExtension(pathW
, ARRAY_SIZE("C:\\1.exe") - 1);
1729 ok(hr
== E_INVALIDARG
, "expect %#x, got %#x\n", E_INVALIDARG
, hr
);
1731 for (i
= 0; i
< ARRAY_SIZE(removeextension_tests
); i
++)
1733 const struct removeextension_test
*t
= removeextension_tests
+ i
;
1735 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
1736 hr
= pPathCchRemoveExtension(pathW
, ARRAY_SIZE(pathW
));
1737 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path
, t
->hr
, hr
);
1740 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, pathA
, ARRAY_SIZE(pathA
), NULL
, NULL
);
1741 ok(!lstrcmpA(pathA
, t
->expected
), "path %s expect stripped path %s, got %s\n", t
->path
, t
->expected
, pathA
);
1746 struct removefilespec_test
1749 const CHAR
*expected
;
1754 static const struct removefilespec_test removefilespec_tests
[] =
1759 {"a\\b", "a", S_OK
},
1761 {"\\", "\\", S_FALSE
},
1762 {"\\a", "\\", S_OK
},
1763 {"\\a\\", "\\a", S_OK
},
1764 {"\\a\\b", "\\a", S_OK
},
1766 {"\\\\", "\\\\", S_FALSE
},
1767 {"\\\\a", "\\\\a", S_FALSE
},
1768 {"\\\\a\\", "\\\\a", S_OK
},
1769 {"\\\\a\\b", "\\\\a\\b", S_FALSE
},
1770 {"\\\\a\\b\\", "\\\\a\\b", S_OK
},
1771 {"\\\\a\\b\\c", "\\\\a\\b", S_OK
},
1773 {"C:", "C:", S_FALSE
},
1774 {"C:a", "C:", S_OK
},
1775 {"C:a\\", "C:a", S_OK
},
1776 {"C:a\\b", "C:a", S_OK
},
1778 {"C:\\", "C:\\", S_FALSE
},
1779 {"C:\\a", "C:\\", S_OK
},
1780 {"C:\\a\\", "C:\\a", S_OK
},
1781 {"C:\\a\\b", "C:\\a", S_OK
},
1783 {"\\\\?\\", "\\\\?", S_OK
},
1784 {"\\\\?\\a", "\\\\?", S_OK
},
1785 {"\\\\?\\a\\", "\\\\?\\a", S_OK
},
1786 {"\\\\?\\a\\b", "\\\\?\\a", S_OK
},
1788 {"\\\\?\\C:", "\\\\?\\C:", S_FALSE
},
1789 {"\\\\?\\C:a", "\\\\?\\C:", S_OK
},
1790 {"\\\\?\\C:a\\", "\\\\?\\C:a", S_OK
},
1791 {"\\\\?\\C:a\\b", "\\\\?\\C:a", S_OK
},
1793 {"\\\\?\\C:\\", "\\\\?\\C:\\", S_FALSE
},
1794 {"\\\\?\\C:\\a", "\\\\?\\C:\\", S_OK
},
1795 {"\\\\?\\C:\\a\\", "\\\\?\\C:\\a", S_OK
},
1796 {"\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", S_OK
},
1798 {"\\\\?\\UNC\\", "\\\\?\\UNC\\", S_FALSE
},
1799 {"\\\\?\\UNC\\a", "\\\\?\\UNC\\a", S_FALSE
},
1800 {"\\\\?\\UNC\\a\\", "\\\\?\\UNC\\a", S_OK
},
1801 {"\\\\?\\UNC\\a\\b", "\\\\?\\UNC\\a\\b", S_FALSE
},
1802 {"\\\\?\\UNC\\a\\b\\", "\\\\?\\UNC\\a\\b", S_OK
},
1803 {"\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\b", S_OK
},
1805 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}",
1806 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_FALSE
},
1807 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a",
1808 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_OK
},
1809 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a\\",
1810 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a", S_OK
},
1811 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a\\b",
1812 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a", S_OK
},
1814 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\",
1815 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_FALSE
},
1816 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a",
1817 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_OK
},
1818 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\",
1819 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", S_OK
},
1820 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\b",
1821 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", S_OK
},
1824 {"C:\\a", NULL
, E_INVALIDARG
, PATHCCH_MAX_CCH
+ 1},
1825 {"C:\\a", "C:\\", S_OK
, PATHCCH_MAX_CCH
},
1826 /* Size < original path length + 1, read beyond size */
1827 {"C:\\a", "C:\\", S_OK
, ARRAY_SIZE("C:\\a") - 1},
1828 /* Size < result path length + 1 */
1829 {"C:\\a", NULL
, E_INVALIDARG
, ARRAY_SIZE("C:\\") - 1}
1832 static void test_PathCchRemoveFileSpec(void)
1834 WCHAR pathW
[PATHCCH_MAX_CCH
] = {0};
1835 CHAR pathA
[PATHCCH_MAX_CCH
];
1840 if (!pPathCchRemoveFileSpec
)
1842 win_skip("PathCchRemoveFileSpec() is not available.\n");
1846 /* Null arguments */
1847 hr
= pPathCchRemoveFileSpec(NULL
, ARRAY_SIZE(pathW
));
1848 ok(hr
== E_INVALIDARG
, "expect %#x, got %#x\n", E_INVALIDARG
, hr
);
1850 hr
= pPathCchRemoveFileSpec(pathW
, 0);
1851 ok(hr
== E_INVALIDARG
, "expect %#x, got %#x\n", E_INVALIDARG
, hr
);
1853 for (i
= 0; i
< ARRAY_SIZE(removefilespec_tests
); i
++)
1855 const struct removefilespec_test
*t
= removefilespec_tests
+ i
;
1857 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
1858 size
= t
->size
? t
->size
: ARRAY_SIZE(pathW
);
1859 hr
= pPathCchRemoveFileSpec(pathW
, size
);
1860 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path
, t
->hr
, hr
);
1863 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, pathA
, ARRAY_SIZE(pathA
), NULL
, NULL
);
1864 ok(!lstrcmpA(pathA
, t
->expected
), "path %s expect stripped path %s, got %s\n", t
->path
, t
->expected
, pathA
);
1869 struct renameextension_test
1872 const CHAR
*extension
;
1873 const CHAR
*expected
;
1876 static const struct renameextension_test renameextension_tests
[] =
1878 {"1.exe", ".txt", "1.txt"},
1879 {"C:1.exe", ".txt", "C:1.txt"},
1880 {"C:\\1.exe", ".txt", "C:\\1.txt"},
1881 {"\\1.exe", ".txt", "\\1.txt"},
1882 {"\\\\1.exe", ".txt", "\\\\1.txt"},
1883 {"\\\\?\\C:1.exe", ".txt", "\\\\?\\C:1.txt"},
1884 {"\\\\?\\C:\\1.exe", ".txt", "\\\\?\\C:\\1.txt"},
1885 {"\\\\?\\UNC\\1.exe", ".txt", "\\\\?\\UNC\\1.txt"},
1886 {"\\\\?\\UNC\\192.168.1.1\\1.exe", ".txt", "\\\\?\\UNC\\192.168.1.1\\1.txt"},
1887 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1.exe", ".txt",
1888 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\1.txt"},
1889 {"C:\\1.exe", "", "C:\\1"},
1890 {"C:\\1.exe", "txt", "C:\\1.txt"}
1893 static void test_PathCchRenameExtension(void)
1895 WCHAR pathW
[PATHCCH_MAX_CCH
+ 1];
1896 CHAR pathA
[PATHCCH_MAX_CCH
+ 1];
1897 WCHAR extensionW
[MAX_PATH
];
1901 if (!pPathCchRenameExtension
)
1903 win_skip("PathCchRenameExtension() is not available.\n");
1907 /* Invalid arguments */
1908 MultiByteToWideChar(CP_ACP
, 0, "C:\\1.txt", -1, pathW
, ARRAY_SIZE(pathW
));
1909 MultiByteToWideChar(CP_ACP
, 0, ".exe", -1, extensionW
, ARRAY_SIZE(extensionW
));
1911 hr
= pPathCchRenameExtension(NULL
, PATHCCH_MAX_CCH
, extensionW
);
1912 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1914 hr
= pPathCchRenameExtension(pathW
, 0, extensionW
);
1915 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1917 hr
= pPathCchRenameExtension(pathW
, PATHCCH_MAX_CCH
, NULL
);
1918 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1921 hr
= pPathCchRenameExtension(pathW
, ARRAY_SIZE("C:\\1.exe") - 1, extensionW
);
1922 ok(E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1924 hr
= pPathCchRenameExtension(pathW
, PATHCCH_MAX_CCH
+ 1, extensionW
);
1925 ok(hr
== E_INVALIDARG
, "expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
1927 hr
= pPathCchRenameExtension(pathW
, PATHCCH_MAX_CCH
, extensionW
);
1928 ok(hr
== S_OK
, "expect result %#x, got %#x\n", S_OK
, hr
);
1930 for (i
= 0; i
< ARRAY_SIZE(renameextension_tests
); i
++)
1932 const struct renameextension_test
*t
= renameextension_tests
+ i
;
1933 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
1934 MultiByteToWideChar(CP_ACP
, 0, t
->extension
, -1, extensionW
, ARRAY_SIZE(extensionW
));
1935 hr
= pPathCchRenameExtension(pathW
, PATHCCH_MAX_CCH
, extensionW
);
1936 ok(hr
== S_OK
, "path %s extension %s expect result %#x, got %#x\n", t
->path
, t
->extension
, S_OK
, hr
);
1939 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, pathA
, ARRAY_SIZE(pathA
), NULL
, NULL
);
1940 ok(!lstrcmpA(pathA
, t
->expected
), "path %s extension %s expect output path %s, got %s\n", t
->path
,
1941 t
->extension
, t
->expected
, pathA
);
1946 struct skiproot_test
1953 static const struct skiproot_test skiproot_tests
[] =
1955 /* Basic combination */
1956 {"", 0, E_INVALIDARG
},
1959 {"\\\\.\\", 4, S_OK
},
1960 {"\\\\?\\UNC\\", 8, S_OK
},
1961 {"\\\\?\\C:\\", 7, S_OK
},
1964 {"C:\\\\", 3, S_OK
},
1966 {"\\\\.\\\\", 4, S_OK
},
1967 {"\\\\?\\UNC\\\\", 9, S_OK
},
1968 {"\\\\?\\C:\\\\", 7, S_OK
},
1971 {"a", 0, E_INVALIDARG
},
1974 {"\\\\.\\a", 5, S_OK
},
1975 {"\\\\?\\UNC\\a", 9, S_OK
},
1979 {"C:\\\\a", 3, S_OK
},
1981 {"\\\\.\\\\a", 4, S_OK
},
1982 {"\\\\?\\UNC\\\\a", 10, S_OK
},
1983 {"\\\\?\\C:\\\\a", 7, S_OK
},
1986 {"a\\", 0, E_INVALIDARG
},
1987 {"C:\\a\\", 3, S_OK
},
1989 {"\\\\.\\a\\", 6, S_OK
},
1990 {"\\\\?\\UNC\\a\\", 10, S_OK
},
1991 {"\\\\?\\C:\\a\\", 7, S_OK
},
1994 {"\\\\\\\\", 3, S_OK
},
1995 {"\\\\a\\", 4, S_OK
},
1996 {"\\\\a\\b", 5, S_OK
},
1997 {"\\\\a\\b\\", 6, S_OK
},
1998 {"\\\\a\\b\\\\", 6, S_OK
},
1999 {"\\\\a\\b\\\\c", 6, S_OK
},
2000 {"\\\\a\\b\\c", 6, S_OK
},
2001 {"\\\\a\\b\\c\\", 6, S_OK
},
2002 {"\\\\a\\b\\c\\d", 6, S_OK
},
2003 {"\\\\a\\\\b\\c\\", 4, S_OK
},
2004 {"\\\\aa\\bb\\cc\\", 8, S_OK
},
2007 {"\\\\?\\UNC\\\\", 9, S_OK
},
2008 {"\\\\?\\UNC\\a\\b", 11, S_OK
},
2009 {"\\\\?\\UNC\\a\\b", 11, S_OK
},
2010 {"\\\\?\\UNC\\a\\b\\", 12, S_OK
},
2011 {"\\\\?\\UNC\\a\\b\\c", 12, S_OK
},
2012 {"\\\\?\\UNC\\a\\b\\c\\", 12, S_OK
},
2013 {"\\\\?\\UNC\\a\\b\\c\\d", 12, S_OK
},
2014 {"\\\\?\\C:", 6, S_OK
},
2015 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", 48, S_OK
},
2016 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", 49, S_OK
},
2017 {"\\\\?\\unc\\a\\b", 11, S_OK
},
2018 {"\\\\?\\volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", 49, S_OK
},
2019 {"\\\\?\\volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a", 49, S_OK
},
2023 {":", 0, E_INVALIDARG
},
2024 {":\\", 0, E_INVALIDARG
},
2025 {"C\\", 0, E_INVALIDARG
},
2027 {"\\?\\UNC", 1, S_OK
},
2028 {"\\\\?\\", 0, E_INVALIDARG
},
2029 {"\\\\?\\UNC", 0, E_INVALIDARG
},
2030 {"\\\\?\\::\\", 0, E_INVALIDARG
},
2031 {"\\\\?\\Volume", 0, E_INVALIDARG
},
2033 {"\\\\..", 4, S_OK
},
2034 {"\\\\..a", 5, S_OK
}
2037 static void test_PathCchSkipRoot(void)
2039 WCHAR pathW
[MAX_PATH
];
2040 const WCHAR
*root_end
;
2044 if (!pPathCchSkipRoot
)
2046 win_skip("PathCchSkipRoot() is not available.\n");
2050 root_end
= (const WCHAR
*)0xdeadbeef;
2051 hr
= pPathCchSkipRoot(NULL
, &root_end
);
2052 ok(hr
== E_INVALIDARG
, "Expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
2053 ok(root_end
== (const WCHAR
*)0xdeadbeef, "Expect root_end 0xdeadbeef, got %p\n", root_end
);
2055 MultiByteToWideChar(CP_ACP
, 0, "C:\\", -1, pathW
, ARRAY_SIZE(pathW
));
2056 hr
= pPathCchSkipRoot(pathW
, NULL
);
2057 ok(hr
== E_INVALIDARG
, "Expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
2059 for (i
= 0; i
< ARRAY_SIZE(skiproot_tests
); i
++)
2061 const struct skiproot_test
*t
= skiproot_tests
+ i
;
2062 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
2063 hr
= pPathCchSkipRoot(pathW
, &root_end
);
2064 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path
, t
->hr
, hr
);
2066 ok(root_end
- pathW
== t
->root_offset
, "path %s expect root offset %d, got %ld\n", t
->path
, t
->root_offset
,
2067 (INT_PTR
)(root_end
- pathW
));
2071 struct stripprefix_test
2074 const CHAR
*stripped_path
;
2079 static const struct stripprefix_test stripprefix_tests
[] =
2081 {"\\\\?\\UNC\\", "\\\\", S_OK
},
2082 {"\\\\?\\UNC\\a", "\\\\a", S_OK
},
2083 {"\\\\?\\C:", "C:", S_OK
},
2084 {"\\\\?\\C:\\", "C:\\", S_OK
},
2085 {"\\\\?\\C:\\a", "C:\\a", S_OK
},
2086 {"\\\\?\\unc\\", "\\\\", S_OK
},
2087 {"\\\\?\\c:\\", "c:\\", S_OK
},
2089 {"\\", "\\", S_FALSE
},
2090 {"\\\\", "\\\\", S_FALSE
},
2091 {"\\\\a", "\\\\a", S_FALSE
},
2092 {"\\\\a\\", "\\\\a\\", S_FALSE
},
2093 {"\\\\?\\a", "\\\\?\\a", S_FALSE
},
2094 {"\\\\?\\UNC", "\\\\?\\UNC", S_FALSE
},
2095 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\",
2096 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_FALSE
},
2099 {"C:\\", NULL
, E_INVALIDARG
, PATHCCH_MAX_CCH
+ 1},
2100 {"C:\\", "C:\\", S_FALSE
, PATHCCH_MAX_CCH
},
2101 /* Size < original path actual length + 1, read beyond size */
2102 {"\\\\?\\C:\\", "C:\\", S_OK
, ARRAY_SIZE("\\\\?\\C:\\") - 1},
2103 /* Size < stripped path length + 1 */
2104 {"\\\\?\\C:\\", NULL
, E_INVALIDARG
, ARRAY_SIZE("C:\\") - 1},
2105 {"\\\\?\\UNC\\", NULL
, E_INVALIDARG
, ARRAY_SIZE("\\\\") - 1}
2108 static void test_PathCchStripPrefix(void)
2110 WCHAR pathW
[PATHCCH_MAX_CCH
+ 1] = {0};
2111 CHAR stripped_pathA
[PATHCCH_MAX_CCH
];
2116 if (!pPathCchStripPrefix
)
2118 win_skip("PathCchStripPrefix(() is not available.\n");
2122 /* Null arguments */
2123 hr
= pPathCchStripPrefix(NULL
, PATHCCH_MAX_CCH
);
2124 ok(hr
== E_INVALIDARG
, "expect %#x, got %#x\n", E_INVALIDARG
, hr
);
2126 hr
= pPathCchStripPrefix(pathW
, 0);
2127 ok(hr
== E_INVALIDARG
, "expect %#x, got %#x\n", E_INVALIDARG
, hr
);
2129 for (i
= 0; i
< ARRAY_SIZE(stripprefix_tests
); i
++)
2131 const struct stripprefix_test
*t
= stripprefix_tests
+ i
;
2133 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
2134 size
= t
->size
? t
->size
: PATHCCH_MAX_CCH
;
2135 hr
= pPathCchStripPrefix(pathW
, size
);
2136 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path
, t
->hr
, hr
);
2139 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, stripped_pathA
, ARRAY_SIZE(stripped_pathA
), NULL
, NULL
);
2140 ok(!lstrcmpA(stripped_pathA
, t
->stripped_path
), "path %s expect stripped path %s, got %s\n", t
->path
,
2141 t
->stripped_path
, stripped_pathA
);
2146 struct striptoroot_test
2154 static const struct striptoroot_test striptoroot_tests
[] =
2157 {"", "", E_INVALIDARG
},
2158 {"C", NULL
, E_INVALIDARG
},
2159 {"\\\\?\\UNC", NULL
, E_INVALIDARG
},
2162 {"C:\\", NULL
, E_INVALIDARG
, PATHCCH_MAX_CCH
+ 1},
2163 {"C:\\", "C:\\", S_FALSE
, PATHCCH_MAX_CCH
},
2164 /* Size < original path length + 1, read beyond size */
2165 {"C:\\a", "C:\\", S_OK
, ARRAY_SIZE("C:\\a") - 1},
2166 /* Size < stripped path length + 1 */
2167 {"C:\\a", "C:\\", E_INVALIDARG
, ARRAY_SIZE("C:\\") - 1},
2168 {"\\\\a\\b\\c", NULL
, E_INVALIDARG
, ARRAY_SIZE("\\\\a\\b") - 1},
2171 {"C:", "C:", S_FALSE
},
2172 {"C:a", "C:", S_OK
},
2173 {"C:a\\b", "C:", S_OK
},
2174 {"C:a\\b\\c", "C:", S_OK
},
2177 {"C:\\", "C:\\", S_FALSE
},
2178 {"C:\\a", "C:\\", S_OK
},
2179 {"C:\\a\\b", "C:\\", S_OK
},
2180 {"C:\\a\\b\\c", "C:\\", S_OK
},
2183 {"\\", "\\", S_FALSE
},
2184 {"\\a", "\\", S_OK
},
2185 {"\\a\\b", "\\", S_OK
},
2186 {"\\a\\b\\c", "\\", S_OK
},
2189 {"\\\\", "\\\\", S_FALSE
},
2190 {"\\\\a", "\\\\a", S_FALSE
},
2191 {"\\\\a\\b", "\\\\a\\b", S_FALSE
},
2192 {"\\\\a\\b\\c", "\\\\a\\b", S_OK
},
2195 {"\\\\?\\UNC\\", "\\\\?\\UNC\\", S_FALSE
},
2196 {"\\\\?\\UNC\\a", "\\\\?\\UNC\\a", S_FALSE
},
2197 {"\\\\?\\UNC\\a\\b", "\\\\?\\UNC\\a\\b", S_FALSE
},
2198 {"\\\\?\\UNC\\a\\b\\", "\\\\?\\UNC\\a\\b", S_OK
},
2199 {"\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\b", S_OK
},
2202 {"\\\\?\\C:", "\\\\?\\C:", S_FALSE
},
2203 {"\\\\?\\C:a", "\\\\?\\C:", S_OK
},
2204 {"\\\\?\\C:a\\b", "\\\\?\\C:", S_OK
},
2205 {"\\\\?\\C:a\\b\\c", "\\\\?\\C:", S_OK
},
2208 {"\\\\?\\C:\\", "\\\\?\\C:\\", S_FALSE
},
2209 {"\\\\?\\C:\\a", "\\\\?\\C:\\", S_OK
},
2210 {"\\\\?\\C:\\a\\b", "\\\\?\\C:\\", S_OK
},
2211 {"\\\\?\\C:\\a\\b\\c", "\\\\?\\C:\\", S_OK
},
2214 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}",
2215 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_FALSE
},
2216 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a",
2217 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_OK
},
2218 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a\\b",
2219 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_OK
},
2220 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}a\\b\\c",
2221 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}", S_OK
},
2223 /* UNC Volume with backslash */
2224 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\",
2225 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_FALSE
},
2226 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a",
2227 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_OK
},
2228 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\b",
2229 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_OK
},
2230 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\a\\b\\c",
2231 "\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", S_OK
},
2234 static void test_PathCchStripToRoot(void)
2236 WCHAR pathW
[PATHCCH_MAX_CCH
];
2237 CHAR rootA
[PATHCCH_MAX_CCH
];
2242 if (!pPathCchStripToRoot
)
2244 win_skip("PathCchStripToRoot() is not available.\n");
2248 /* Null arguments */
2249 hr
= pPathCchStripToRoot(NULL
, ARRAY_SIZE(pathW
));
2250 ok(hr
== E_INVALIDARG
, "Expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
2252 MultiByteToWideChar(CP_ACP
, 0, "C:\\a", -1, pathW
, ARRAY_SIZE(pathW
));
2253 hr
= pPathCchStripToRoot(pathW
, 0);
2254 ok(hr
== E_INVALIDARG
, "Expect result %#x, got %#x\n", E_INVALIDARG
, hr
);
2256 for (i
= 0; i
< ARRAY_SIZE(striptoroot_tests
); i
++)
2258 const struct striptoroot_test
*t
= striptoroot_tests
+ i
;
2259 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
2260 size
= t
->size
? t
->size
: ARRAY_SIZE(pathW
);
2261 hr
= pPathCchStripToRoot(pathW
, size
);
2262 ok(hr
== t
->hr
, "path %s expect result %#x, got %#x\n", t
->path
, t
->hr
, hr
);
2265 WideCharToMultiByte(CP_ACP
, 0, pathW
, -1, rootA
, ARRAY_SIZE(rootA
), NULL
, NULL
);
2266 ok(!lstrcmpA(rootA
, t
->root
), "path %s expect stripped path %s, got %s\n", t
->path
, t
->root
, rootA
);
2278 static const struct isuncex_test isuncex_tests
[] =
2281 {"\\\\a\\", 2, TRUE
},
2282 {"\\\\.\\", 2, TRUE
},
2283 {"\\\\?\\UNC\\", 8, TRUE
},
2284 {"\\\\?\\UNC\\a", 8, TRUE
},
2285 {"\\\\?\\unc\\", 8, TRUE
},
2286 {"\\\\?\\unc\\a", 8, TRUE
},
2291 {"\\??\\", 0, FALSE
},
2292 {"\\\\?\\", 0, FALSE
},
2293 {"\\\\?\\UNC", 0, FALSE
},
2294 {"\\\\?\\C:", 0, FALSE
},
2295 {"\\\\?\\C:\\", 0, FALSE
},
2296 {"\\\\?\\C:\\a", 0, FALSE
},
2297 {"\\\\?\\Volume{e51a1864-6f2d-4019-b73d-f4e60e600c26}\\", 0, FALSE
}
2300 static void test_PathIsUNCEx(void)
2302 WCHAR pathW
[MAX_PATH
];
2303 const WCHAR
*server
;
2309 win_skip("PathIsUNCEx(() is not available.\n");
2313 /* No NULL check for path pointers on Windows */
2316 ret
= pPathIsUNCEx(NULL
, &server
);
2317 ok(ret
== FALSE
, "expect FALSE\n");
2320 MultiByteToWideChar(CP_ACP
, 0, "C:\\", -1, pathW
, ARRAY_SIZE(pathW
));
2321 ret
= pPathIsUNCEx(pathW
, NULL
);
2322 ok(ret
== FALSE
, "expect FALSE\n");
2324 for (i
= 0; i
< ARRAY_SIZE(isuncex_tests
); i
++)
2326 const struct isuncex_test
*t
= isuncex_tests
+ i
;
2328 MultiByteToWideChar(CP_ACP
, 0, t
->path
, -1, pathW
, ARRAY_SIZE(pathW
));
2329 server
= (const WCHAR
*)0xdeadbeef;
2330 ret
= pPathIsUNCEx(pathW
, &server
);
2331 ok(ret
== t
->ret
, "path \"%s\" expect return %d, got %d\n", t
->path
, t
->ret
, ret
);
2333 ok(server
== pathW
+ t
->server_offset
, "path \"%s\" expect server offset %d, got %ld\n", t
->path
,
2334 t
->server_offset
, (INT_PTR
)(server
- pathW
));
2336 ok(!server
, "expect server is null, got %p\n", server
);
2340 static void test_actctx(void)
2342 ACTCTX_SECTION_KEYED_DATA data
= { sizeof(data
) };
2343 WCHAR exe_path
[MAX_PATH
];
2345 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*info
= (void *)buf
;
2349 b
= FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
, NULL
, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
, L
"testdll.dll", &data
);
2350 ok(b
, "FindActCtxSectionString failed: %u\n", GetLastError());
2352 b
= QueryActCtxW(0, data
.hActCtx
, &data
.ulAssemblyRosterIndex
, AssemblyDetailedInformationInActivationContext
, buf
, sizeof(buf
), &size
);
2353 ok(b
, "QueryActCtx failed: %u\n", GetLastError());
2355 GetModuleFileNameW(NULL
, exe_path
, ARRAY_SIZE(exe_path
));
2356 ok(!lstrcmpW(info
->lpAssemblyManifestPath
, exe_path
), "lpAssemblyManifestPath = %s expected %s\n", debugstr_w(info
->lpAssemblyManifestPath
), debugstr_w(exe_path
));
2357 ok(!info
->lpAssemblyDirectoryName
, "lpAssemblyDirectoryName = %s\n", wine_dbgstr_w(info
->lpAssemblyDirectoryName
));
2362 HMODULE hmod
= LoadLibraryA("kernelbase.dll");
2364 pPathAllocCanonicalize
= (void *)GetProcAddress(hmod
, "PathAllocCanonicalize");
2365 pPathAllocCombine
= (void *)GetProcAddress(hmod
, "PathAllocCombine");
2366 pPathCchAddBackslash
= (void *)GetProcAddress(hmod
, "PathCchAddBackslash");
2367 pPathCchAddBackslashEx
= (void *)GetProcAddress(hmod
, "PathCchAddBackslashEx");
2368 pPathCchAddExtension
= (void *)GetProcAddress(hmod
, "PathCchAddExtension");
2369 pPathCchAppend
= (void *)GetProcAddress(hmod
, "PathCchAppend");
2370 pPathCchAppendEx
= (void *)GetProcAddress(hmod
, "PathCchAppendEx");
2371 pPathCchCanonicalize
= (void *)GetProcAddress(hmod
, "PathCchCanonicalize");
2372 pPathCchCanonicalizeEx
= (void *)GetProcAddress(hmod
, "PathCchCanonicalizeEx");
2373 pPathCchCombine
= (void *)GetProcAddress(hmod
, "PathCchCombine");
2374 pPathCchCombineEx
= (void *)GetProcAddress(hmod
, "PathCchCombineEx");
2375 pPathCchFindExtension
= (void *)GetProcAddress(hmod
, "PathCchFindExtension");
2376 pPathCchIsRoot
= (void *)GetProcAddress(hmod
, "PathCchIsRoot");
2377 pPathCchRemoveBackslash
= (void *)GetProcAddress(hmod
, "PathCchRemoveBackslash");
2378 pPathCchRemoveBackslashEx
= (void *)GetProcAddress(hmod
, "PathCchRemoveBackslashEx");
2379 pPathCchRemoveExtension
= (void *)GetProcAddress(hmod
, "PathCchRemoveExtension");
2380 pPathCchRemoveFileSpec
= (void *)GetProcAddress(hmod
, "PathCchRemoveFileSpec");
2381 pPathCchRenameExtension
= (void *)GetProcAddress(hmod
, "PathCchRenameExtension");
2382 pPathCchSkipRoot
= (void *)GetProcAddress(hmod
, "PathCchSkipRoot");
2383 pPathCchStripPrefix
= (void *)GetProcAddress(hmod
, "PathCchStripPrefix");
2384 pPathCchStripToRoot
= (void *)GetProcAddress(hmod
, "PathCchStripToRoot");
2385 pPathIsUNCEx
= (void *)GetProcAddress(hmod
, "PathIsUNCEx");
2387 test_PathAllocCanonicalize();
2388 test_PathAllocCombine();
2389 test_PathCchAddBackslash();
2390 test_PathCchAddBackslashEx();
2391 test_PathCchAddExtension();
2392 test_PathCchAppend();
2393 test_PathCchAppendEx();
2394 test_PathCchCanonicalize();
2395 test_PathCchCanonicalizeEx();
2396 test_PathCchCombine();
2397 test_PathCchCombineEx();
2398 test_PathCchFindExtension();
2399 test_PathCchIsRoot();
2400 test_PathCchRemoveBackslash();
2401 test_PathCchRemoveBackslashEx();
2402 test_PathCchRemoveExtension();
2403 test_PathCchRemoveFileSpec();
2404 test_PathCchRenameExtension();
2405 test_PathCchSkipRoot();
2406 test_PathCchStripPrefix();
2407 test_PathCchStripToRoot();