1 /* 2 * Unit test suite for dir functions 3 * 4 * Copyright 2006 CodeWeavers, Aric Stewart 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #include "wine/test.h" 22 #include <stdarg.h> 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <fcntl.h> 26 #include <direct.h> 27 #include <sys/stat.h> 28 #include <io.h> 29 #include <mbctype.h> 30 #include <windef.h> 31 #include <winbase.h> 32 #include <winnls.h> 33 #include <process.h> 34 #include <errno.h> 35 36 static int (__cdecl *p_makepath_s)(char *, size_t, const char *, const char *, const char *, const char *); 37 static int (__cdecl *p_wmakepath_s)(wchar_t *, size_t, const wchar_t *,const wchar_t *, const wchar_t *, const wchar_t *); 38 static int (__cdecl *p_searchenv_s)(const char*, const char*, char*, size_t); 39 static int (__cdecl *p_wsearchenv_s)(const wchar_t*, const wchar_t*, wchar_t*, size_t); 40 41 static void init(void) 42 { 43 HMODULE hmod = GetModuleHandleA("msvcrt.dll"); 44 45 p_makepath_s = (void *)GetProcAddress(hmod, "_makepath_s"); 46 p_wmakepath_s = (void *)GetProcAddress(hmod, "_wmakepath_s"); 47 p_searchenv_s = (void *)GetProcAddress(hmod, "_searchenv_s"); 48 p_wsearchenv_s = (void *)GetProcAddress(hmod, "_wsearchenv_s"); 49 } 50 51 typedef struct 52 { 53 const char* buffer; 54 const char* drive; 55 const char* dir; 56 const char* file; 57 const char* ext; 58 const char* expected; 59 } makepath_case; 60 61 #define USE_BUFF ((char*)~0ul) 62 static const makepath_case makepath_cases[] = 63 { 64 { NULL, NULL, NULL, NULL, NULL, "" }, /* 0 */ 65 { NULL, "c", NULL, NULL, NULL, "c:" }, 66 { NULL, "c:", NULL, NULL, NULL, "c:" }, 67 { NULL, "c:\\", NULL, NULL, NULL, "c:" }, 68 { NULL, NULL, "dir", NULL, NULL, "dir\\" }, 69 { NULL, NULL, "dir\\", NULL, NULL, "dir\\" }, 70 { NULL, NULL, "\\dir", NULL, NULL, "\\dir\\" }, 71 { NULL, NULL, NULL, "file", NULL, "file" }, 72 { NULL, NULL, NULL, "\\file", NULL, "\\file" }, 73 { NULL, NULL, NULL, "file", NULL, "file" }, 74 { NULL, NULL, NULL, NULL, "ext", ".ext" }, /* 10 */ 75 { NULL, NULL, NULL, NULL, ".ext", ".ext" }, 76 { "foo", NULL, NULL, NULL, NULL, "" }, 77 { "foo", USE_BUFF, NULL, NULL, NULL, "f:" }, 78 { "foo", NULL, USE_BUFF, NULL, NULL, "foo\\" }, 79 { "foo", NULL, NULL, USE_BUFF, NULL, "foo" }, 80 { "foo", NULL, USE_BUFF, "file", NULL, "foo\\file" }, 81 { "foo", NULL, USE_BUFF, "file", "ext", "foo\\file.ext" }, 82 { "foo", NULL, NULL, USE_BUFF, "ext", "foo.ext" }, 83 /* remaining combinations of USE_BUFF crash native */ 84 { NULL, "c", "dir", "file", "ext", "c:dir\\file.ext" }, 85 { NULL, "c:", "dir", "file", "ext", "c:dir\\file.ext" }, /* 20 */ 86 { NULL, "c:\\", "dir", "file", "ext", "c:dir\\file.ext" } 87 }; 88 89 static void test_makepath(void) 90 { 91 WCHAR driveW[MAX_PATH]; 92 WCHAR dirW[MAX_PATH]; 93 WCHAR fileW[MAX_PATH]; 94 WCHAR extW[MAX_PATH]; 95 WCHAR bufferW[MAX_PATH]; 96 char buffer[MAX_PATH]; 97 98 unsigned int i, n; 99 100 for (i = 0; i < ARRAY_SIZE(makepath_cases); ++i) 101 { 102 const makepath_case* p = &makepath_cases[i]; 103 104 memset(buffer, 'X', MAX_PATH); 105 if (p->buffer) 106 strcpy(buffer, p->buffer); 107 108 /* Ascii */ 109 _makepath(buffer, 110 p->drive == USE_BUFF ? buffer : p->drive, 111 p->dir == USE_BUFF ? buffer : p->dir, 112 p->file == USE_BUFF? buffer : p->file, 113 p->ext == USE_BUFF ? buffer : p->ext); 114 115 buffer[MAX_PATH - 1] = '\0'; 116 ok(!strcmp(p->expected, buffer), "got '%s' for case %d\n", buffer, i); 117 118 /* Unicode */ 119 if (p->drive != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->drive, -1, driveW, MAX_PATH); 120 if (p->dir != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->dir, -1, dirW, MAX_PATH); 121 if (p->file != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->file, -1, fileW, MAX_PATH); 122 if (p->ext != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->ext, -1, extW, MAX_PATH); 123 124 memset(buffer, 0, MAX_PATH); 125 for (n = 0; n < MAX_PATH; ++n) 126 bufferW[n] = 'X'; 127 if (p->buffer) MultiByteToWideChar( CP_ACP, 0, p->buffer, -1, bufferW, MAX_PATH); 128 129 _wmakepath(bufferW, 130 p->drive == USE_BUFF ? bufferW : p->drive ? driveW : NULL, 131 p->dir == USE_BUFF ? bufferW : p->dir ? dirW : NULL, 132 p->file == USE_BUFF? bufferW : p->file ? fileW : NULL, 133 p->ext == USE_BUFF ? bufferW : p->ext ? extW : NULL); 134 135 bufferW[MAX_PATH - 1] = '\0'; 136 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL); 137 ok(!strcmp(p->expected, buffer), "got '%s' for unicode case %d\n", buffer, i); 138 } 139 } 140 141 static const WCHAR expected0[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X'}; 142 static const WCHAR expected1[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X'}; 143 static const WCHAR expected2[] = {'\0',':','X','X','X','X','X','X','X','X','X','X','X'}; 144 static const WCHAR expected3[] = {'\0',':','d','X','X','X','X','X','X','X','X','X','X'}; 145 static const WCHAR expected4[] = {'\0',':','d','\\','X','X','X','X','X','X','X','X','X'}; 146 static const WCHAR expected5[] = {'\0',':','d','\\','f','X','X','X','X','X','X','X','X'}; 147 static const WCHAR expected6[] = {'\0',':','d','\\','f','i','X','X','X','X','X','X','X'}; 148 static const WCHAR expected7[] = {'\0',':','d','\\','f','i','l','X','X','X','X','X','X'}; 149 static const WCHAR expected8[] = {'\0',':','d','\\','f','i','l','e','X','X','X','X','X'}; 150 static const WCHAR expected9[] = {'\0',':','d','\\','f','i','l','e','.','X','X','X','X'}; 151 static const WCHAR expected10[] = {'\0',':','d','\\','f','i','l','e','.','e','X','X','X'}; 152 static const WCHAR expected11[] = {'\0',':','d','\\','f','i','l','e','.','e','x','X','X'}; 153 154 static const WCHAR expected12[] = {'\0',':','X','X','X','X','X','X','X','X'}; 155 static const WCHAR expected13[] = {'\0',':','d','X','X','X','X','X','X','X'}; 156 static const WCHAR expected14[] = {'\0',':','d','i','X','X','X','X','X','X'}; 157 static const WCHAR expected15[] = {'\0',':','d','i','r','X','X','X','X','X'}; 158 static const WCHAR expected16[] = {'\0',':','d','i','r','\\','X','X','X','X'}; 159 160 static const WCHAR expected17[] = {'\0','o','o'}; 161 static const WCHAR expected18[] = {'\0','o','o','\0','X'}; 162 static const WCHAR expected19[] = {'\0','o','o','\0'}; 163 static const WCHAR expected20[] = {'\0','o','o','\0','X','X','X','X','X'}; 164 static const WCHAR expected21[] = {'\0','o','o','\\','f','i','l','X','X'}; 165 static const WCHAR expected22[] = {'\0','o','o','\0','X','X','X','X','X','X','X','X','X'}; 166 static const WCHAR expected23[] = {'\0','o','o','\\','f','i','l','X','X','X','X','X','X'}; 167 static const WCHAR expected24[] = {'\0','o','o','\\','f','i','l','e','.','e','x','X','X'}; 168 static const WCHAR expected25[] = {'\0','o','o','\0','X','X','X','X'}; 169 static const WCHAR expected26[] = {'\0','o','o','.','e','x','X','X'}; 170 171 typedef struct 172 { 173 const char* buffer; 174 size_t length; 175 const char* drive; 176 const char* dir; 177 const char* file; 178 const char* ext; 179 const char* expected; 180 const WCHAR *expected_unicode; 181 size_t expected_length; 182 } makepath_s_case; 183 184 static const makepath_s_case makepath_s_cases[] = 185 { 186 /* Behavior with directory parameter containing backslash. */ 187 {NULL, 1, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", expected0, 13}, 188 {NULL, 2, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", expected1, 13}, 189 {NULL, 3, "c:", "d\\", "file", "ext", "\0:XXXXXXXXXXX", expected2, 13}, 190 {NULL, 4, "c:", "d\\", "file", "ext", "\0:dXXXXXXXXXX", expected3, 13}, 191 {NULL, 5, "c:", "d\\", "file", "ext", "\0:d\\XXXXXXXXX", expected4, 13}, 192 {NULL, 6, "c:", "d\\", "file", "ext", "\0:d\\fXXXXXXXX", expected5, 13}, 193 {NULL, 7, "c:", "d\\", "file", "ext", "\0:d\\fiXXXXXXX", expected6, 13}, 194 {NULL, 8, "c:", "d\\", "file", "ext", "\0:d\\filXXXXXX", expected7, 13}, 195 {NULL, 9, "c:", "d\\", "file", "ext", "\0:d\\fileXXXXX", expected8, 13}, 196 {NULL, 10, "c:", "d\\", "file", "ext", "\0:d\\file.XXXX", expected9, 13}, 197 {NULL, 11, "c:", "d\\", "file", "ext", "\0:d\\file.eXXX", expected10, 13}, 198 {NULL, 12, "c:", "d\\", "file", "ext", "\0:d\\file.exXX", expected11, 13}, 199 /* Behavior with directory parameter lacking backslash. */ 200 {NULL, 3, "c:", "dir", "f", "ext", "\0:XXXXXXXX", expected12, 10}, 201 {NULL, 4, "c:", "dir", "f", "ext", "\0:dXXXXXXX", expected13, 10}, 202 {NULL, 5, "c:", "dir", "f", "ext", "\0:diXXXXXX", expected14, 10}, 203 {NULL, 6, "c:", "dir", "f", "ext", "\0:dirXXXXX", expected15, 10}, 204 {NULL, 7, "c:", "dir", "f", "ext", "\0:dir\\XXXX", expected16, 10}, 205 /* Behavior with overlapped buffer. */ 206 {"foo", 2, USE_BUFF, NULL, NULL, NULL, "\0oo", expected17, 3}, 207 {"foo", 4, NULL, USE_BUFF, NULL, NULL, "\0oo\0X", expected18, 5}, 208 {"foo", 3, NULL, NULL, USE_BUFF, NULL, "\0oo\0", expected19, 4}, 209 {"foo", 4, NULL, USE_BUFF, "file", NULL, "\0oo\0XXXXX", expected20, 9}, 210 {"foo", 8, NULL, USE_BUFF, "file", NULL, "\0oo\\filXX", expected21, 9}, 211 {"foo", 4, NULL, USE_BUFF, "file", "ext", "\0oo\0XXXXXXXXX", expected22, 13}, 212 {"foo", 8, NULL, USE_BUFF, "file", "ext", "\0oo\\filXXXXXX", expected23, 13}, 213 {"foo", 12, NULL, USE_BUFF, "file", "ext", "\0oo\\file.exXX", expected24, 13}, 214 {"foo", 4, NULL, NULL, USE_BUFF, "ext", "\0oo\0XXXX", expected25, 8}, 215 {"foo", 7, NULL, NULL, USE_BUFF, "ext", "\0oo.exXX", expected26, 8}, 216 }; 217 218 static void test_makepath_s(void) 219 { 220 WCHAR driveW[MAX_PATH]; 221 WCHAR dirW[MAX_PATH]; 222 WCHAR fileW[MAX_PATH]; 223 WCHAR extW[MAX_PATH]; 224 WCHAR bufferW[MAX_PATH]; 225 char buffer[MAX_PATH]; 226 int ret; 227 unsigned int i, n; 228 229 if (!p_makepath_s || !p_wmakepath_s) 230 { 231 win_skip("Safe makepath functions are not available\n"); 232 return; 233 } 234 235 errno = EBADF; 236 ret = p_makepath_s(NULL, 0, NULL, NULL, NULL, NULL); 237 ok(ret == EINVAL, "Expected _makepath_s to return EINVAL, got %d\n", ret); 238 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); 239 240 errno = EBADF; 241 ret = p_makepath_s(buffer, 0, NULL, NULL, NULL, NULL); 242 ok(ret == EINVAL, "Expected _makepath_s to return EINVAL, got %d\n", ret); 243 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); 244 245 errno = EBADF; 246 ret = p_wmakepath_s(NULL, 0, NULL, NULL, NULL, NULL); 247 ok(ret == EINVAL, "Expected _wmakepath_s to return EINVAL, got %d\n", ret); 248 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); 249 250 errno = EBADF; 251 ret = p_wmakepath_s(bufferW, 0, NULL, NULL, NULL, NULL); 252 ok(ret == EINVAL, "Expected _wmakepath_s to return EINVAL, got %d\n", ret); 253 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); 254 255 /* Test with the normal _makepath cases. */ 256 for (i = 0; i < ARRAY_SIZE(makepath_cases); i++) 257 { 258 const makepath_case *p = makepath_cases + i; 259 260 memset(buffer, 'X', MAX_PATH); 261 if (p->buffer) 262 strcpy(buffer, p->buffer); 263 264 /* Ascii */ 265 ret = p_makepath_s(buffer, MAX_PATH, 266 p->drive == USE_BUFF ? buffer : p->drive, 267 p->dir == USE_BUFF ? buffer : p->dir, 268 p->file == USE_BUFF? buffer : p->file, 269 p->ext == USE_BUFF ? buffer : p->ext); 270 ok(ret == 0, "[%d] Expected _makepath_s to return 0, got %d\n", i, ret); 271 272 buffer[MAX_PATH - 1] = '\0'; 273 ok(!strcmp(p->expected, buffer), "got '%s' for case %d\n", buffer, i); 274 275 /* Unicode */ 276 if (p->drive != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->drive, -1, driveW, MAX_PATH); 277 if (p->dir != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->dir, -1, dirW, MAX_PATH); 278 if (p->file != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->file, -1, fileW, MAX_PATH); 279 if (p->ext != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->ext, -1, extW, MAX_PATH); 280 281 memset(buffer, 0, MAX_PATH); 282 for (n = 0; n < MAX_PATH; ++n) 283 bufferW[n] = 'X'; 284 if (p->buffer) MultiByteToWideChar( CP_ACP, 0, p->buffer, -1, bufferW, MAX_PATH); 285 286 ret = p_wmakepath_s(bufferW, MAX_PATH, 287 p->drive == USE_BUFF ? bufferW : p->drive ? driveW : NULL, 288 p->dir == USE_BUFF ? bufferW : p->dir ? dirW : NULL, 289 p->file == USE_BUFF? bufferW : p->file ? fileW : NULL, 290 p->ext == USE_BUFF ? bufferW : p->ext ? extW : NULL); 291 ok(ret == 0, "[%d] Expected _wmakepath_s to return 0, got %d\n", i, ret); 292 293 bufferW[MAX_PATH - 1] = '\0'; 294 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL); 295 ok(!strcmp(p->expected, buffer), "got '%s' for unicode case %d\n", buffer, i); 296 } 297 298 /* Try insufficient length cases. */ 299 for (i = 0; i < ARRAY_SIZE(makepath_s_cases); i++) 300 { 301 const makepath_s_case *p = makepath_s_cases + i; 302 303 memset(buffer, 'X', MAX_PATH); 304 if (p->buffer) 305 strcpy(buffer, p->buffer); 306 307 /* Ascii */ 308 errno = EBADF; 309 ret = p_makepath_s(buffer, p->length, 310 p->drive == USE_BUFF ? buffer : p->drive, 311 p->dir == USE_BUFF ? buffer : p->dir, 312 p->file == USE_BUFF? buffer : p->file, 313 p->ext == USE_BUFF ? buffer : p->ext); 314 ok(ret == ERANGE, "[%d] Expected _makepath_s to return ERANGE, got %d\n", i, ret); 315 ok(errno == ERANGE, "[%d] Expected errno to be ERANGE, got %d\n", i, errno); 316 ok(!memcmp(p->expected, buffer, p->expected_length), "unexpected output for case %d\n", i); 317 318 /* Unicode */ 319 if (p->drive != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->drive, -1, driveW, MAX_PATH); 320 if (p->dir != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->dir, -1, dirW, MAX_PATH); 321 if (p->file != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->file, -1, fileW, MAX_PATH); 322 if (p->ext != USE_BUFF) MultiByteToWideChar(CP_ACP, 0, p->ext, -1, extW, MAX_PATH); 323 324 memset(buffer, 0, MAX_PATH); 325 for (n = 0; n < MAX_PATH; ++n) 326 bufferW[n] = 'X'; 327 if (p->buffer) MultiByteToWideChar( CP_ACP, 0, p->buffer, -1, bufferW, MAX_PATH); 328 329 errno = EBADF; 330 ret = p_wmakepath_s(bufferW, p->length, 331 p->drive == USE_BUFF ? bufferW : p->drive ? driveW : NULL, 332 p->dir == USE_BUFF ? bufferW : p->dir ? dirW : NULL, 333 p->file == USE_BUFF? bufferW : p->file ? fileW : NULL, 334 p->ext == USE_BUFF ? bufferW : p->ext ? extW : NULL); 335 ok(ret == ERANGE, "[%d] Expected _wmakepath_s to return ERANGE, got %d\n", i, ret); 336 ok(errno == ERANGE, "[%d] Expected errno to be ERANGE, got %d\n", i, errno); 337 338 ok(!memcmp(p->expected_unicode, bufferW, p->expected_length * sizeof(WCHAR)), "unexpected output for case %d\n", i); 339 } 340 } 341 342 static void test_fullpath(void) 343 { 344 char full[MAX_PATH]; 345 char tmppath[MAX_PATH]; 346 char prevpath[MAX_PATH]; 347 char level1[MAX_PATH]; 348 char level2[MAX_PATH]; 349 char teststring[MAX_PATH]; 350 char *freeme; 351 BOOL rc,free1,free2; 352 353 free1=free2=TRUE; 354 GetCurrentDirectoryA(MAX_PATH, prevpath); 355 GetTempPathA(MAX_PATH,tmppath); 356 strcpy(level1,tmppath); 357 strcat(level1,"msvcrt-test\\"); 358 359 rc = CreateDirectoryA(level1,NULL); 360 if (!rc && GetLastError()==ERROR_ALREADY_EXISTS) 361 free1=FALSE; 362 363 strcpy(level2,level1); 364 strcat(level2,"nextlevel\\"); 365 rc = CreateDirectoryA(level2,NULL); 366 if (!rc && GetLastError()==ERROR_ALREADY_EXISTS) 367 free2=FALSE; 368 SetCurrentDirectoryA(level2); 369 370 ok(_fullpath(full,"test", MAX_PATH)!=NULL,"_fullpath failed\n"); 371 strcpy(teststring,level2); 372 strcat(teststring,"test"); 373 ok(strcmp(full,teststring)==0,"Invalid Path returned %s\n",full); 374 ok(_fullpath(full,"\\test", MAX_PATH)!=NULL,"_fullpath failed\n"); 375 memcpy(teststring,level2,3); 376 teststring[3]=0; 377 strcat(teststring,"test"); 378 ok(strcmp(full,teststring)==0,"Invalid Path returned %s\n",full); 379 ok(_fullpath(full,"..\\test", MAX_PATH)!=NULL,"_fullpath failed\n"); 380 strcpy(teststring,level1); 381 strcat(teststring,"test"); 382 ok(strcmp(full,teststring)==0,"Invalid Path returned %s\n",full); 383 ok(_fullpath(full,"..\\test", 10)==NULL,"_fullpath failed to generate error\n"); 384 385 freeme = _fullpath(NULL,"test", 0); 386 ok(freeme!=NULL,"No path returned\n"); 387 strcpy(teststring,level2); 388 strcat(teststring,"test"); 389 ok(strcmp(freeme,teststring)==0,"Invalid Path returned %s\n",freeme); 390 free(freeme); 391 392 SetCurrentDirectoryA(prevpath); 393 if (free2) 394 RemoveDirectoryA(level2); 395 if (free1) 396 RemoveDirectoryA(level1); 397 } 398 399 static void test_splitpath(void) 400 { 401 const char* path = "c:\\\x83\x5c\x83\x74\x83\x67.bin"; 402 char drive[3], dir[MAX_PATH], fname[MAX_PATH], ext[MAX_PATH]; 403 int prev_cp = _getmbcp(); 404 405 /* SBCS codepage */ 406 _setmbcp(1252); 407 _splitpath(path, drive, dir, fname, ext); 408 ok(!strcmp(drive, "c:"), "got %s\n", drive); 409 ok(!strcmp(dir, "\\\x83\x5c"), "got %s\n", dir); 410 ok(!strcmp(fname, "\x83\x74\x83\x67"), "got %s\n", fname); 411 ok(!strcmp(ext, ".bin"), "got %s\n", ext); 412 413 /* MBCS (Japanese) codepage */ 414 _setmbcp(932); 415 _splitpath(path, drive, dir, fname, ext); 416 ok(!strcmp(drive, "c:"), "got %s\n", drive); 417 ok(!strcmp(dir, "\\"), "got %s\n", dir); 418 ok(!strcmp(fname, "\x83\x5c\x83\x74\x83\x67"), "got %s\n", fname); 419 ok(!strcmp(ext, ".bin"), "got %s\n", ext); 420 421 _setmbcp(prev_cp); 422 } 423 424 static void test_searchenv(void) 425 { 426 const char *dirs[] = { 427 "\\search_env_test", 428 "\\search_env_test\\dir1", 429 "\\search_env_test\\dir2", 430 "\\search_env_test\\dir3longer" 431 }; 432 433 const char *files[] = { 434 "\\search_env_test\\dir1\\1.dat", 435 "\\search_env_test\\dir1\\2.dat", 436 "\\search_env_test\\dir2\\1.dat", 437 "\\search_env_test\\dir2\\3.dat", 438 "\\search_env_test\\dir3longer\\3.dat" 439 }; 440 441 const WCHAR env_w[] = {'T','E','S','T','_','P','A','T','H',0}; 442 const WCHAR dat1_w[] = {'1','.','d','a','t',0}; 443 const WCHAR dat3_w[] = {'3','.','d','a','t',0}; 444 445 char env1[4*MAX_PATH], env2[4*MAX_PATH], tmppath[MAX_PATH], path[2*MAX_PATH]; 446 char result[MAX_PATH], exp[2*MAX_PATH]; 447 WCHAR result_w[MAX_PATH]; 448 int i, path_len; 449 FILE *tmp_file; 450 451 if (getenv("TEST_PATH")) { 452 skip("TEST_PATH environment variable already set\n"); 453 return; 454 } 455 456 path_len = GetTempPathA(MAX_PATH, tmppath); 457 ok(path_len, "GetTempPath failed\n"); 458 memcpy(path, tmppath, path_len); 459 460 for (i=0; i<ARRAY_SIZE(dirs); i++) { 461 strcpy(path+path_len, dirs[i]); 462 ok(!mkdir(path), "mkdir failed (dir = %s)\n", path); 463 } 464 465 for (i=0; i<ARRAY_SIZE(files); i++) { 466 strcpy(path+path_len, files[i]); 467 tmp_file = fopen(path, "wb"); 468 ok(tmp_file != NULL, "fopen failed (file = %s)\n", path); 469 fclose(tmp_file); 470 } 471 472 strcpy(env1, "TEST_PATH="); 473 strcpy(env2, "TEST_PATH=;"); 474 for (i=1; i<ARRAY_SIZE(dirs); i++) { 475 strcat(env1, tmppath); 476 strcat(env1, dirs[i]); 477 strcat(env1, ";"); 478 479 strcat(env2, tmppath); 480 strcat(env2, dirs[i]); 481 strcat(env2, ";;"); 482 } 483 484 if (!p_searchenv_s || !p_wsearchenv_s) 485 win_skip("searchenv_s or wsearchenv_s function is not available\n"); 486 487 putenv(env1); 488 memset(result, 'x', sizeof(result)); 489 _searchenv("fail", "TEST_PATH", result); 490 ok(!result[0], "got %s, expected ''\n", result); 491 492 if (p_searchenv_s) { 493 memset(result, 'x', sizeof(result)); 494 i = p_searchenv_s("fail", "TEST_PATH", result, MAX_PATH); 495 ok(i == ENOENT, "searchenv_s returned %d\n", i); 496 ok(!result[0], "got %s, expected ''\n", result); 497 } 498 499 memset(result, 'x', sizeof(result)); 500 strcpy(exp, tmppath); 501 strcat(exp, files[0]); 502 _searchenv("1.dat", "TEST_PATH", result); 503 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 504 505 if (p_searchenv_s) { 506 memset(result, 'x', sizeof(result)); 507 i = p_searchenv_s("1.dat", "TEST_PATH", result, MAX_PATH); 508 ok(!i, "searchenv_s returned %d\n", i); 509 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 510 } 511 512 memset(result_w, 'x', sizeof(result_w)); 513 _wsearchenv(dat1_w, env_w, result_w); 514 WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL); 515 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 516 517 if (p_wsearchenv_s) { 518 memset(result_w, 'x', sizeof(result_w)); 519 i = p_wsearchenv_s(dat1_w, env_w, result_w, MAX_PATH); 520 ok(!i, "wsearchenv_s returned %d\n", i); 521 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 522 } 523 524 memset(result, 'x', sizeof(result)); 525 strcpy(exp, tmppath); 526 strcat(exp, files[3]); 527 _searchenv("3.dat", "TEST_PATH", result); 528 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 529 530 if (p_searchenv_s) { 531 memset(result, 'x', sizeof(result)); 532 i = p_searchenv_s("3.dat", "TEST_PATH", result, MAX_PATH); 533 ok(!i, "searchenv_s returned %d\n", i); 534 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 535 } 536 537 memset(result_w, 'x', sizeof(result_w)); 538 _wsearchenv(dat3_w, env_w, result_w); 539 WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL); 540 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 541 542 if (p_wsearchenv_s) { 543 memset(result_w, 'x', sizeof(result_w)); 544 i = p_wsearchenv_s(dat3_w, env_w, result_w, MAX_PATH); 545 ok(!i, "wsearchenv_s returned %d\n", i); 546 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 547 } 548 549 putenv(env2); 550 memset(result, 'x', sizeof(result)); 551 strcpy(exp, tmppath); 552 strcat(exp, files[0]); 553 _searchenv("1.dat", "TEST_PATH", result); 554 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 555 556 if (p_searchenv_s) { 557 memset(result, 'x', sizeof(result)); 558 i = p_searchenv_s("1.dat", "TEST_PATH", result, MAX_PATH); 559 ok(!i, "searchenv_s returned %d\n", i); 560 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 561 } 562 563 memset(result_w, 'x', sizeof(result_w)); 564 _wsearchenv(dat1_w, env_w, result_w); 565 WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL); 566 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 567 568 if (p_wsearchenv_s) { 569 memset(result_w, 'x', sizeof(result_w)); 570 i = p_wsearchenv_s(dat1_w, env_w, result_w, MAX_PATH); 571 ok(!i, "wsearchenv_s returned %d\n", i); 572 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 573 } 574 575 memset(result, 'x', sizeof(result)); 576 strcpy(exp, tmppath); 577 strcat(exp, files[3]); 578 _searchenv("3.dat", "TEST_PATH", result); 579 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 580 581 if (p_searchenv_s) { 582 memset(result, 'x', sizeof(result)); 583 i = p_searchenv_s("3.dat", "TEST_PATH", result, MAX_PATH); 584 ok(!i, "searchenv_s returned %d\n", i); 585 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 586 } 587 588 memset(result_w, 'x', sizeof(result_w)); 589 _wsearchenv(dat3_w, env_w, result_w); 590 WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL); 591 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 592 593 if (p_wsearchenv_s) { 594 memset(result_w, 'x', sizeof(result_w)); 595 i = p_wsearchenv_s(dat3_w, env_w, result_w, MAX_PATH); 596 ok(!i, "wsearchenv_s returned %d\n", i); 597 ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); 598 } 599 600 putenv("TEST_PATH="); 601 602 for (i=ARRAY_SIZE(files)-1; i>=0; i--) { 603 strcpy(path+path_len, files[i]); 604 ok(!remove(path), "remove failed (file = %s)\n", path); 605 } 606 607 for (i=ARRAY_SIZE(dirs)-1; i>=0; i--) { 608 strcpy(path+path_len, dirs[i]); 609 ok(!rmdir(path), "rmdir failed (dir = %s)\n", path); 610 } 611 } 612 613 START_TEST(dir) 614 { 615 init(); 616 617 test_fullpath(); 618 test_makepath(); 619 test_makepath_s(); 620 test_splitpath(); 621 test_searchenv(); 622 } 623