2 * Unit test suite for dir functions
4 * Copyright 2006 CodeWeavers, Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/test.h"
34 static int (__cdecl
*p_makepath_s
)(char *, size_t, const char *, const char *, const char *, const char *);
35 static int (__cdecl
*p_wmakepath_s
)(wchar_t *, size_t, const wchar_t *,const wchar_t *, const wchar_t *, const wchar_t *);
37 static void init(void)
39 HMODULE hmod
= GetModuleHandleA("msvcrt.dll");
41 p_makepath_s
= (void *)GetProcAddress(hmod
, "_makepath_s");
42 p_wmakepath_s
= (void *)GetProcAddress(hmod
, "_wmakepath_s");
55 #define USE_BUFF ((char*)~0ul)
56 static const makepath_case makepath_cases
[] =
58 { NULL
, NULL
, NULL
, NULL
, NULL
, "" }, /* 0 */
59 { NULL
, "c", NULL
, NULL
, NULL
, "c:" },
60 { NULL
, "c:", NULL
, NULL
, NULL
, "c:" },
61 { NULL
, "c:\\", NULL
, NULL
, NULL
, "c:" },
62 { NULL
, NULL
, "dir", NULL
, NULL
, "dir\\" },
63 { NULL
, NULL
, "dir\\", NULL
, NULL
, "dir\\" },
64 { NULL
, NULL
, "\\dir", NULL
, NULL
, "\\dir\\" },
65 { NULL
, NULL
, NULL
, "file", NULL
, "file" },
66 { NULL
, NULL
, NULL
, "\\file", NULL
, "\\file" },
67 { NULL
, NULL
, NULL
, "file", NULL
, "file" },
68 { NULL
, NULL
, NULL
, NULL
, "ext", ".ext" }, /* 10 */
69 { NULL
, NULL
, NULL
, NULL
, ".ext", ".ext" },
70 { "foo", NULL
, NULL
, NULL
, NULL
, "" },
71 { "foo", USE_BUFF
, NULL
, NULL
, NULL
, "f:" },
72 { "foo", NULL
, USE_BUFF
, NULL
, NULL
, "foo\\" },
73 { "foo", NULL
, NULL
, USE_BUFF
, NULL
, "foo" },
74 { "foo", NULL
, USE_BUFF
, "file", NULL
, "foo\\file" },
75 { "foo", NULL
, USE_BUFF
, "file", "ext", "foo\\file.ext" },
76 { "foo", NULL
, NULL
, USE_BUFF
, "ext", "foo.ext" },
77 /* remaining combinations of USE_BUFF crash native */
78 { NULL
, "c", "dir", "file", "ext", "c:dir\\file.ext" },
79 { NULL
, "c:", "dir", "file", "ext", "c:dir\\file.ext" }, /* 20 */
80 { NULL
, "c:\\", "dir", "file", "ext", "c:dir\\file.ext" }
83 static void test_makepath(void)
85 WCHAR driveW
[MAX_PATH
];
87 WCHAR fileW
[MAX_PATH
];
89 WCHAR bufferW
[MAX_PATH
];
90 char buffer
[MAX_PATH
];
94 for (i
= 0; i
< sizeof(makepath_cases
)/sizeof(makepath_cases
[0]); ++i
)
96 const makepath_case
* p
= &makepath_cases
[i
];
98 memset(buffer
, 'X', MAX_PATH
);
100 strcpy(buffer
, p
->buffer
);
104 p
->drive
== USE_BUFF
? buffer
: p
->drive
,
105 p
->dir
== USE_BUFF
? buffer
: p
->dir
,
106 p
->file
== USE_BUFF
? buffer
: p
->file
,
107 p
->ext
== USE_BUFF
? buffer
: p
->ext
);
109 buffer
[MAX_PATH
- 1] = '\0';
110 ok(!strcmp(p
->expected
, buffer
), "got '%s' for case %d\n", buffer
, i
);
113 if (p
->drive
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->drive
, -1, driveW
, MAX_PATH
);
114 if (p
->dir
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->dir
, -1, dirW
, MAX_PATH
);
115 if (p
->file
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->file
, -1, fileW
, MAX_PATH
);
116 if (p
->ext
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->ext
, -1, extW
, MAX_PATH
);
118 memset(buffer
, 0, MAX_PATH
);
119 for (n
= 0; n
< MAX_PATH
; ++n
)
121 if (p
->buffer
) MultiByteToWideChar( CP_ACP
, 0, p
->buffer
, -1, bufferW
, MAX_PATH
);
124 p
->drive
== USE_BUFF
? bufferW
: p
->drive
? driveW
: NULL
,
125 p
->dir
== USE_BUFF
? bufferW
: p
->dir
? dirW
: NULL
,
126 p
->file
== USE_BUFF
? bufferW
: p
->file
? fileW
: NULL
,
127 p
->ext
== USE_BUFF
? bufferW
: p
->ext
? extW
: NULL
);
129 bufferW
[MAX_PATH
- 1] = '\0';
130 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, buffer
, MAX_PATH
, NULL
, NULL
);
131 ok(!strcmp(p
->expected
, buffer
), "got '%s' for unicode case %d\n", buffer
, i
);
135 static const WCHAR expected0
[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X'};
136 static const WCHAR expected1
[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X'};
137 static const WCHAR expected2
[] = {'\0',':','X','X','X','X','X','X','X','X','X','X','X'};
138 static const WCHAR expected3
[] = {'\0',':','d','X','X','X','X','X','X','X','X','X','X'};
139 static const WCHAR expected4
[] = {'\0',':','d','\\','X','X','X','X','X','X','X','X','X'};
140 static const WCHAR expected5
[] = {'\0',':','d','\\','f','X','X','X','X','X','X','X','X'};
141 static const WCHAR expected6
[] = {'\0',':','d','\\','f','i','X','X','X','X','X','X','X'};
142 static const WCHAR expected7
[] = {'\0',':','d','\\','f','i','l','X','X','X','X','X','X'};
143 static const WCHAR expected8
[] = {'\0',':','d','\\','f','i','l','e','X','X','X','X','X'};
144 static const WCHAR expected9
[] = {'\0',':','d','\\','f','i','l','e','.','X','X','X','X'};
145 static const WCHAR expected10
[] = {'\0',':','d','\\','f','i','l','e','.','e','X','X','X'};
146 static const WCHAR expected11
[] = {'\0',':','d','\\','f','i','l','e','.','e','x','X','X'};
148 static const WCHAR expected12
[] = {'\0',':','X','X','X','X','X','X','X','X'};
149 static const WCHAR expected13
[] = {'\0',':','d','X','X','X','X','X','X','X'};
150 static const WCHAR expected14
[] = {'\0',':','d','i','X','X','X','X','X','X'};
151 static const WCHAR expected15
[] = {'\0',':','d','i','r','X','X','X','X','X'};
152 static const WCHAR expected16
[] = {'\0',':','d','i','r','\\','X','X','X','X'};
154 static const WCHAR expected17
[] = {'\0','o','o'};
155 static const WCHAR expected18
[] = {'\0','o','o','\0','X'};
156 static const WCHAR expected19
[] = {'\0','o','o','\0'};
157 static const WCHAR expected20
[] = {'\0','o','o','\0','X','X','X','X','X'};
158 static const WCHAR expected21
[] = {'\0','o','o','\\','f','i','l','X','X'};
159 static const WCHAR expected22
[] = {'\0','o','o','\0','X','X','X','X','X','X','X','X','X'};
160 static const WCHAR expected23
[] = {'\0','o','o','\\','f','i','l','X','X','X','X','X','X'};
161 static const WCHAR expected24
[] = {'\0','o','o','\\','f','i','l','e','.','e','x','X','X'};
162 static const WCHAR expected25
[] = {'\0','o','o','\0','X','X','X','X'};
163 static const WCHAR expected26
[] = {'\0','o','o','.','e','x','X','X'};
173 const char* expected
;
174 const WCHAR
*expected_unicode
;
175 size_t expected_length
;
178 static const makepath_s_case makepath_s_cases
[] =
180 /* Behavior with directory parameter containing backslash. */
181 {NULL
, 1, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", expected0
, 13},
182 {NULL
, 2, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", expected1
, 13},
183 {NULL
, 3, "c:", "d\\", "file", "ext", "\0:XXXXXXXXXXX", expected2
, 13},
184 {NULL
, 4, "c:", "d\\", "file", "ext", "\0:dXXXXXXXXXX", expected3
, 13},
185 {NULL
, 5, "c:", "d\\", "file", "ext", "\0:d\\XXXXXXXXX", expected4
, 13},
186 {NULL
, 6, "c:", "d\\", "file", "ext", "\0:d\\fXXXXXXXX", expected5
, 13},
187 {NULL
, 7, "c:", "d\\", "file", "ext", "\0:d\\fiXXXXXXX", expected6
, 13},
188 {NULL
, 8, "c:", "d\\", "file", "ext", "\0:d\\filXXXXXX", expected7
, 13},
189 {NULL
, 9, "c:", "d\\", "file", "ext", "\0:d\\fileXXXXX", expected8
, 13},
190 {NULL
, 10, "c:", "d\\", "file", "ext", "\0:d\\file.XXXX", expected9
, 13},
191 {NULL
, 11, "c:", "d\\", "file", "ext", "\0:d\\file.eXXX", expected10
, 13},
192 {NULL
, 12, "c:", "d\\", "file", "ext", "\0:d\\file.exXX", expected11
, 13},
193 /* Behavior with directory parameter lacking backslash. */
194 {NULL
, 3, "c:", "dir", "f", "ext", "\0:XXXXXXXX", expected12
, 10},
195 {NULL
, 4, "c:", "dir", "f", "ext", "\0:dXXXXXXX", expected13
, 10},
196 {NULL
, 5, "c:", "dir", "f", "ext", "\0:diXXXXXX", expected14
, 10},
197 {NULL
, 6, "c:", "dir", "f", "ext", "\0:dirXXXXX", expected15
, 10},
198 {NULL
, 7, "c:", "dir", "f", "ext", "\0:dir\\XXXX", expected16
, 10},
199 /* Behavior with overlapped buffer. */
200 {"foo", 2, USE_BUFF
, NULL
, NULL
, NULL
, "\0oo", expected17
, 3},
201 {"foo", 4, NULL
, USE_BUFF
, NULL
, NULL
, "\0oo\0X", expected18
, 5},
202 {"foo", 3, NULL
, NULL
, USE_BUFF
, NULL
, "\0oo\0", expected19
, 4},
203 {"foo", 4, NULL
, USE_BUFF
, "file", NULL
, "\0oo\0XXXXX", expected20
, 9},
204 {"foo", 8, NULL
, USE_BUFF
, "file", NULL
, "\0oo\\filXX", expected21
, 9},
205 {"foo", 4, NULL
, USE_BUFF
, "file", "ext", "\0oo\0XXXXXXXXX", expected22
, 13},
206 {"foo", 8, NULL
, USE_BUFF
, "file", "ext", "\0oo\\filXXXXXX", expected23
, 13},
207 {"foo", 12, NULL
, USE_BUFF
, "file", "ext", "\0oo\\file.exXX", expected24
, 13},
208 {"foo", 4, NULL
, NULL
, USE_BUFF
, "ext", "\0oo\0XXXX", expected25
, 8},
209 {"foo", 7, NULL
, NULL
, USE_BUFF
, "ext", "\0oo.exXX", expected26
, 8},
212 static void test_makepath_s(void)
214 WCHAR driveW
[MAX_PATH
];
215 WCHAR dirW
[MAX_PATH
];
216 WCHAR fileW
[MAX_PATH
];
217 WCHAR extW
[MAX_PATH
];
218 WCHAR bufferW
[MAX_PATH
];
219 char buffer
[MAX_PATH
];
223 if (!p_makepath_s
|| !p_wmakepath_s
)
225 win_skip("Safe makepath functions are not available\n");
230 ret
= p_makepath_s(NULL
, 0, NULL
, NULL
, NULL
, NULL
);
231 ok(ret
== EINVAL
, "Expected _makepath_s to return EINVAL, got %d\n", ret
);
232 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
235 ret
= p_makepath_s(buffer
, 0, NULL
, NULL
, NULL
, NULL
);
236 ok(ret
== EINVAL
, "Expected _makepath_s to return EINVAL, got %d\n", ret
);
237 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
240 ret
= p_wmakepath_s(NULL
, 0, NULL
, NULL
, NULL
, NULL
);
241 ok(ret
== EINVAL
, "Expected _wmakepath_s to return EINVAL, got %d\n", ret
);
242 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
245 ret
= p_wmakepath_s(bufferW
, 0, NULL
, NULL
, NULL
, NULL
);
246 ok(ret
== EINVAL
, "Expected _wmakepath_s to return EINVAL, got %d\n", ret
);
247 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
249 /* Test with the normal _makepath cases. */
250 for (i
= 0; i
< sizeof(makepath_cases
)/sizeof(makepath_cases
[0]); i
++)
252 const makepath_case
*p
= makepath_cases
+ i
;
254 memset(buffer
, 'X', MAX_PATH
);
256 strcpy(buffer
, p
->buffer
);
259 ret
= p_makepath_s(buffer
, MAX_PATH
,
260 p
->drive
== USE_BUFF
? buffer
: p
->drive
,
261 p
->dir
== USE_BUFF
? buffer
: p
->dir
,
262 p
->file
== USE_BUFF
? buffer
: p
->file
,
263 p
->ext
== USE_BUFF
? buffer
: p
->ext
);
264 ok(ret
== 0, "[%d] Expected _makepath_s to return 0, got %d\n", i
, ret
);
266 buffer
[MAX_PATH
- 1] = '\0';
267 ok(!strcmp(p
->expected
, buffer
), "got '%s' for case %d\n", buffer
, i
);
270 if (p
->drive
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->drive
, -1, driveW
, MAX_PATH
);
271 if (p
->dir
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->dir
, -1, dirW
, MAX_PATH
);
272 if (p
->file
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->file
, -1, fileW
, MAX_PATH
);
273 if (p
->ext
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->ext
, -1, extW
, MAX_PATH
);
275 memset(buffer
, 0, MAX_PATH
);
276 for (n
= 0; n
< MAX_PATH
; ++n
)
278 if (p
->buffer
) MultiByteToWideChar( CP_ACP
, 0, p
->buffer
, -1, bufferW
, MAX_PATH
);
280 ret
= p_wmakepath_s(bufferW
, MAX_PATH
,
281 p
->drive
== USE_BUFF
? bufferW
: p
->drive
? driveW
: NULL
,
282 p
->dir
== USE_BUFF
? bufferW
: p
->dir
? dirW
: NULL
,
283 p
->file
== USE_BUFF
? bufferW
: p
->file
? fileW
: NULL
,
284 p
->ext
== USE_BUFF
? bufferW
: p
->ext
? extW
: NULL
);
285 ok(ret
== 0, "[%d] Expected _wmakepath_s to return 0, got %d\n", i
, ret
);
287 bufferW
[MAX_PATH
- 1] = '\0';
288 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, buffer
, MAX_PATH
, NULL
, NULL
);
289 ok(!strcmp(p
->expected
, buffer
), "got '%s' for unicode case %d\n", buffer
, i
);
292 /* Try insufficient length cases. */
293 for (i
= 0; i
< sizeof(makepath_s_cases
)/sizeof(makepath_s_cases
[0]); i
++)
295 const makepath_s_case
*p
= makepath_s_cases
+ i
;
297 memset(buffer
, 'X', MAX_PATH
);
299 strcpy(buffer
, p
->buffer
);
303 ret
= p_makepath_s(buffer
, p
->length
,
304 p
->drive
== USE_BUFF
? buffer
: p
->drive
,
305 p
->dir
== USE_BUFF
? buffer
: p
->dir
,
306 p
->file
== USE_BUFF
? buffer
: p
->file
,
307 p
->ext
== USE_BUFF
? buffer
: p
->ext
);
308 ok(ret
== ERANGE
, "[%d] Expected _makepath_s to return ERANGE, got %d\n", i
, ret
);
309 ok(errno
== ERANGE
, "[%d] Expected errno to be ERANGE, got %d\n", i
, errno
);
310 ok(!memcmp(p
->expected
, buffer
, p
->expected_length
), "unexpected output for case %d\n", i
);
313 if (p
->drive
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->drive
, -1, driveW
, MAX_PATH
);
314 if (p
->dir
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->dir
, -1, dirW
, MAX_PATH
);
315 if (p
->file
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->file
, -1, fileW
, MAX_PATH
);
316 if (p
->ext
!= USE_BUFF
) MultiByteToWideChar(CP_ACP
, 0, p
->ext
, -1, extW
, MAX_PATH
);
318 memset(buffer
, 0, MAX_PATH
);
319 for (n
= 0; n
< MAX_PATH
; ++n
)
321 if (p
->buffer
) MultiByteToWideChar( CP_ACP
, 0, p
->buffer
, -1, bufferW
, MAX_PATH
);
324 ret
= p_wmakepath_s(bufferW
, p
->length
,
325 p
->drive
== USE_BUFF
? bufferW
: p
->drive
? driveW
: NULL
,
326 p
->dir
== USE_BUFF
? bufferW
: p
->dir
? dirW
: NULL
,
327 p
->file
== USE_BUFF
? bufferW
: p
->file
? fileW
: NULL
,
328 p
->ext
== USE_BUFF
? bufferW
: p
->ext
? extW
: NULL
);
329 ok(ret
== ERANGE
, "[%d] Expected _wmakepath_s to return ERANGE, got %d\n", i
, ret
);
330 ok(errno
== ERANGE
, "[%d] Expected errno to be ERANGE, got %d\n", i
, errno
);
332 ok(!memcmp(p
->expected_unicode
, bufferW
, p
->expected_length
* sizeof(WCHAR
)), "unexpected output for case %d\n", i
);
336 static void test_fullpath(void)
339 char tmppath
[MAX_PATH
];
340 char prevpath
[MAX_PATH
];
341 char level1
[MAX_PATH
];
342 char level2
[MAX_PATH
];
343 char teststring
[MAX_PATH
];
348 GetCurrentDirectory(MAX_PATH
, prevpath
);
349 GetTempPath(MAX_PATH
,tmppath
);
350 strcpy(level1
,tmppath
);
351 strcat(level1
,"msvcrt-test\\");
353 rc
= CreateDirectory(level1
,NULL
);
354 if (!rc
&& GetLastError()==ERROR_ALREADY_EXISTS
)
357 strcpy(level2
,level1
);
358 strcat(level2
,"nextlevel\\");
359 rc
= CreateDirectory(level2
,NULL
);
360 if (!rc
&& GetLastError()==ERROR_ALREADY_EXISTS
)
362 SetCurrentDirectory(level2
);
364 ok(_fullpath(full
,"test", MAX_PATH
)!=NULL
,"_fullpath failed\n");
365 strcpy(teststring
,level2
);
366 strcat(teststring
,"test");
367 ok(strcmp(full
,teststring
)==0,"Invalid Path returned %s\n",full
);
368 ok(_fullpath(full
,"\\test", MAX_PATH
)!=NULL
,"_fullpath failed\n");
369 strncpy(teststring
,level2
,3);
371 strcat(teststring
,"test");
372 ok(strcmp(full
,teststring
)==0,"Invalid Path returned %s\n",full
);
373 ok(_fullpath(full
,"..\\test", MAX_PATH
)!=NULL
,"_fullpath failed\n");
374 strcpy(teststring
,level1
);
375 strcat(teststring
,"test");
376 ok(strcmp(full
,teststring
)==0,"Invalid Path returned %s\n",full
);
377 ok(_fullpath(full
,"..\\test", 10)==NULL
,"_fullpath failed to generate error\n");
379 freeme
= _fullpath(NULL
,"test", 0);
380 ok(freeme
!=NULL
,"No path returned\n");
381 strcpy(teststring
,level2
);
382 strcat(teststring
,"test");
383 ok(strcmp(freeme
,teststring
)==0,"Invalid Path returned %s\n",freeme
);
386 SetCurrentDirectory(prevpath
);
388 RemoveDirectory(level2
);
390 RemoveDirectory(level1
);