Remove unnecessary executable bits
[reactos.git] / modules / rostests / winetests / kernel32 / path.c
1 /*
2 * Unit test suite for various Path and Directory Functions
3 *
4 * Copyright 2002 Geoffrey Hausheer
5 * Copyright 2006 Detlef Riekenberg
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <assert.h>
25 #include "wine/test.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winerror.h"
30 #include "winnls.h"
31
32 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
33
34 #define LONGFILE "Long File test.path"
35 #define SHORTFILE "pathtest.pth"
36 #define SHORTDIR "shortdir"
37 #define LONGDIR "Long Directory"
38 #define NONFILE_SHORT "noexist.pth"
39 #define NONFILE_LONG "NonExistent File"
40 #define NONDIR_SHORT "notadir"
41 #define NONDIR_LONG "NonExistent Directory"
42
43 #define NOT_A_VALID_DRIVE '@'
44
45 #ifdef __i386__
46 #define ARCH "x86"
47 #elif defined __x86_64__
48 #define ARCH "amd64"
49 #elif defined __arm__
50 #define ARCH "arm"
51 #elif defined __aarch64__
52 #define ARCH "arm64"
53 #else
54 #define ARCH "none"
55 #endif
56
57 /* the following characters don't work well with GetFullPathNameA
58 in Win98. I don't know if this is a FAT thing, or if it is an OS thing
59 but I don't test these characters now.
60 NOTE: Win2k allows GetFullPathNameA to work with them though
61 |<>"
62 */
63 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
64 static const CHAR is_char_ok[] ="11111110111111111011";
65
66 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
67 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD);
68
69 /* Present in Win2003+ */
70 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
71 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
72
73 static DWORD (WINAPI *pSearchPathA)(LPCSTR,LPCSTR,LPCSTR,DWORD,LPSTR,LPSTR*);
74 static DWORD (WINAPI *pSearchPathW)(LPCWSTR,LPCWSTR,LPCWSTR,DWORD,LPWSTR,LPWSTR*);
75 static BOOL (WINAPI *pSetSearchPathMode)(DWORD);
76
77 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
78 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
79 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
80 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
81 static void (WINAPI *pReleaseActCtx)(HANDLE);
82
83 static BOOL (WINAPI *pCheckNameLegalDOS8Dot3W)(const WCHAR *, char *, DWORD, BOOL *, BOOL *);
84 static BOOL (WINAPI *pCheckNameLegalDOS8Dot3A)(const char *, char *, DWORD, BOOL *, BOOL *);
85
86 /* a structure to deal with wine todos somewhat cleanly */
87 typedef struct {
88 DWORD shortlen;
89 DWORD shorterror;
90 DWORD s2llen;
91 DWORD s2lerror;
92 DWORD longlen;
93 DWORD longerror;
94 } SLpassfail;
95
96 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
97 /* NOTE: the passfail structure is used to allow customizable todo checking
98 for wine. It is not very pretty, but it sure beats duplicating this
99 function lots of times
100 */
101 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
102 CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
103 {
104 CHAR tmpstr[MAX_PATH],
105 fullpath[MAX_PATH], /*full path to the file (not short/long) */
106 subpath[MAX_PATH], /*relative path to the file */
107 fullpathshort[MAX_PATH], /*absolute path to the file (short format) */
108 fullpathlong[MAX_PATH], /*absolute path to the file (long format) */
109 curdirshort[MAX_PATH], /*absolute path to the current dir (short) */
110 curdirlong[MAX_PATH]; /*absolute path to the current dir (long) */
111 LPSTR strptr; /*ptr to the filename portion of the path */
112 DWORD len;
113 /* if passfail is NULL, we can perform all checks within this function,
114 otherwise, we will return the relevant data in the passfail struct, so
115 we must initialize it first
116 */
117 if(passfail!=NULL) {
118 passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
119 passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
120 }
121 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
122 if(pGetLongPathNameA) {
123 ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
124 "%s: GetLongPathNameA failed\n",errstr);
125 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
126 ok(! HAS_TRAIL_SLASH_A(curdirlong),
127 "%s: GetLongPathNameA should not have a trailing \\\n",errstr);
128 }
129 ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
130 "%s: GetShortPathNameA failed\n",errstr);
131 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
132 ok(! HAS_TRAIL_SLASH_A(curdirshort),
133 "%s: GetShortPathNameA should not have a trailing \\\n",errstr);
134 /* build relative and absolute paths from inputs */
135 if(lstrlenA(subdir)) {
136 sprintf(subpath,"%s\\%s",subdir,filename);
137 } else {
138 lstrcpyA(subpath,filename);
139 }
140 sprintf(fullpath,"%s\\%s",curdir,subpath);
141 sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
142 sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
143 /* Test GetFullPathNameA functionality */
144 len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
145 ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
146 if(HAS_TRAIL_SLASH_A(subpath)) {
147 ok(strptr==NULL,
148 "%s: GetFullPathNameA should not return a filename ptr\n",errstr);
149 ok(lstrcmpiA(fullpath,tmpstr)==0,
150 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
151 errstr,tmpstr,fullpath);
152 } else {
153 ok(lstrcmpiA(strptr,filename)==0,
154 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
155 errstr,strptr,filename);
156 ok(lstrcmpiA(fullpath,tmpstr)==0,
157 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
158 errstr,tmpstr,fullpath);
159 }
160 /* Test GetShortPathNameA functionality */
161 SetLastError(0);
162 len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
163 if(passfail==NULL) {
164 ok(len, "%s: GetShortPathNameA failed\n",errstr);
165 } else {
166 passfail->shortlen=len;
167 passfail->shorterror=GetLastError();
168 }
169 /* Test GetLongPathNameA functionality
170 We test both conversion from GetFullPathNameA and from GetShortPathNameA
171 */
172 if(pGetLongPathNameA) {
173 if(len!=0) {
174 SetLastError(0);
175 len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
176 if(passfail==NULL) {
177 ok(len,
178 "%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
179 ok(lstrcmpiA(fullpathlong,tmpstr)==0,
180 "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
181 errstr,tmpstr,fullpathlong);
182 } else {
183 passfail->s2llen=len;
184 passfail->s2lerror=GetLastError();
185 }
186 }
187 SetLastError(0);
188 len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
189 if(passfail==NULL) {
190 ok(len, "%s: GetLongPathNameA failed\n",errstr);
191 ok(!lstrcmpiA(fullpathlong, tmpstr), "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
192 errstr, tmpstr, fullpathlong);
193 } else {
194 passfail->longlen=len;
195 passfail->longerror=GetLastError();
196 }
197 }
198 }
199
200 /* split path into leading directory, and 8.3 filename */
201 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
202 BOOL done = FALSE, error = FALSE;
203 int ext,fil;
204 int len,i;
205 len=lstrlenA(path);
206 ext=len;
207 fil=len;
208 /* walk backwards over path looking for '.' or '\\' separators */
209 for(i=len-1;(i>=0) && (!done);i--) {
210 if(path[i]=='.')
211 if(ext!=len) error=TRUE; else ext=i;
212 else if(path[i]=='\\') {
213 if(i==len-1) {
214 error=TRUE;
215 } else {
216 fil=i;
217 done=TRUE;
218 }
219 }
220 }
221 /* Check that we didn't find a trailing '\\' or multiple '.' */
222 ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
223 /* Separate dir, root, and extension */
224 if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
225 if(fil!=len) {
226 lstrcpynA(eight,path+fil+1,ext-fil);
227 lstrcpynA(dir,path,fil+1);
228 } else {
229 lstrcpynA(eight,path,ext+1);
230 lstrcpyA(dir,"");
231 }
232 /* Validate that root and extension really are 8.3 */
233 ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
234 "GetShortPathNAmeA did not return an 8.3 path\n");
235 }
236
237 /* Check that GetShortPathNameA returns a valid 8.3 path */
238 static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
239 const CHAR *ext,const CHAR *errstr) {
240 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
241
242 test_SplitShortPathA(teststr,dir,eight,three);
243 ok(lstrcmpiA(dir,goodstr)==0,
244 "GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
245 ok(lstrcmpiA(three,ext)==0,
246 "GetShortPathNameA returned '%s' with incorrect extension\n",three);
247 }
248
249 /* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
250 characters in the filename.
251 'valid' indicates whether this would be an allowed filename
252 'todo' indicates that wine doesn't get this right yet.
253 NOTE: We always call this routine with a nonexistent filename, so
254 Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
255 should.
256 */
257 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
258 {
259 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
260 SLpassfail passfail;
261
262 test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
263 if(valid) {
264 sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
265 ok((passfail.shortlen==0 &&
266 (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
267 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
268 "%s: GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
269 errstr,passfail.shortlen,passfail.shorterror,tmpstr);
270 } else {
271 ok(passfail.shortlen==0 &&
272 (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
273 "%s: GetShortPathA should have failed len=%d, error=%d\n",
274 errstr,passfail.shortlen,passfail.shorterror);
275 }
276 if(pGetLongPathNameA) {
277 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
278 if(valid) {
279 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
280 "%s: GetLongPathA returned %d and not %d\n",
281 errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
282 } else {
283 ok(passfail.longerror==ERROR_INVALID_NAME ||
284 passfail.longerror==ERROR_FILE_NOT_FOUND,
285 "%s: GetLongPathA returned %d and not %d or %d'\n",
286 errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
287 }
288 }
289 }
290
291 /* Routine to test that SetCurrentDirectory behaves as expected. */
292 static void test_setdir(CHAR *olddir,CHAR *newdir,
293 CHAR *cmprstr, INT pass, const CHAR *errstr)
294 {
295 CHAR tmppath[MAX_PATH], *dirptr;
296 DWORD val,len,chklen;
297
298 val=SetCurrentDirectoryA(newdir);
299 len=GetCurrentDirectoryA(MAX_PATH,tmppath);
300 /* if 'pass' then the SetDirectoryA was supposed to pass */
301 if(pass) {
302 dirptr=(cmprstr==NULL) ? newdir : cmprstr;
303 chklen=lstrlenA(dirptr);
304 ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
305 ok(len==chklen,
306 "%s: SetCurrentDirectory did not change the directory, though it passed\n",
307 errstr);
308 ok(lstrcmpiA(dirptr,tmppath)==0,
309 "%s: SetCurrentDirectory did not change the directory, though it passed\n",
310 errstr);
311 ok(SetCurrentDirectoryA(olddir),
312 "%s: Couldn't set directory to its original value\n",errstr);
313 } else {
314 /* else thest that it fails correctly */
315 chklen=lstrlenA(olddir);
316 ok(val==0,
317 "%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
318 ok(len==chklen,
319 "%s: SetCurrentDirectory changed the directory, though it failed\n",
320 errstr);
321 ok(lstrcmpiA(olddir,tmppath)==0,
322 "%s: SetCurrentDirectory changed the directory, though it failed\n",
323 errstr);
324 }
325 }
326 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
327 {
328 CHAR tmppath[MAX_PATH], /*path to TEMP */
329 tmpstr[MAX_PATH],
330 tmpstr1[MAX_PATH],
331 invalid_dir[MAX_PATH];
332
333 DWORD len,len1,drives;
334 INT id;
335 HANDLE hndl;
336 BOOL bRes;
337 UINT unique;
338
339 *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
340
341 /* Get the current drive letter */
342 if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
343 *curDrive = tmpstr[0];
344 else
345 trace( "Unable to discover current drive, some tests will not be conducted.\n");
346
347 /* Test GetTempPathA */
348 len=GetTempPathA(MAX_PATH,tmppath);
349 ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
350 ok(HAS_TRAIL_SLASH_A(tmppath),
351 "GetTempPathA returned a path that did not end in '\\'\n");
352 lstrcpyA(tmpstr,"aaaaaaaa");
353 len1=GetTempPathA(len,tmpstr);
354 ok(len1==len+1 || broken(len1 == len), /* WinME */
355 "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
356
357 /* Test GetTmpFileNameA */
358 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
359 sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
360 sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
361 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
362 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
363 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
364 newdir,tmpstr,tmpstr1,id);
365 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
366
367 id=GetTempFileNameA(tmppath,NULL,0,newdir);
368 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
369 if (id)
370 {
371 sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
372 sprintf(tmpstr1,"%x.tmp",id & 0xffff);
373 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
374 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
375 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
376 newdir,tmpstr,tmpstr1,id);
377 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
378 }
379
380 for(unique=0;unique<3;unique++) {
381 /* Nonexistent path */
382 sprintf(invalid_dir, "%s\\%s",tmppath,"non_existent_dir_1jwj3y32nb3");
383 SetLastError(0xdeadbeef);
384 ok(!GetTempFileNameA(invalid_dir,"tfn",unique,newdir),"GetTempFileNameA should have failed\n");
385 ok(GetLastError()==ERROR_DIRECTORY || broken(GetLastError()==ERROR_PATH_NOT_FOUND)/*win98*/,
386 "got %d, expected ERROR_DIRECTORY\n", GetLastError());
387
388 /* Check return value for unique !=0 */
389 if(unique) {
390 ok((GetTempFileNameA(tmppath,"tfn",unique,newdir) == unique),"GetTempFileNameA unexpectedly failed\n");
391 /* if unique != 0, the actual temp files are not created: */
392 ok(!DeleteFileA(newdir) && GetLastError() == ERROR_FILE_NOT_FOUND,"Deleted a file that shouldn't exist!\n");
393 }
394 }
395
396 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
397 drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
398 if( *curDrive != NOT_A_VALID_DRIVE)
399 drives &= ~(1<<(*curDrive-'A'));
400 if( drives)
401 for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
402 else
403 trace( "Could not find alternative drive, some tests will not be conducted.\n");
404
405 /* Do some CreateDirectoryA tests */
406 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
407 really understand how they work.
408 More formal tests should be done along with CreateFile tests
409 */
410 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
411 ok(CreateDirectoryA(newdir,NULL)==0,
412 "CreateDirectoryA succeeded even though a file of the same name exists\n");
413 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
414 ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
415 /* Create some files to test other functions. Note, we will test CreateFileA
416 at some later point
417 */
418 sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
419 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
420 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
421 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
422 sprintf(tmpstr,"%c:", *curDrive);
423 bRes = CreateDirectoryA(tmpstr,NULL);
424 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
425 GetLastError() == ERROR_ALREADY_EXISTS),
426 "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
427 sprintf(tmpstr,"%c:\\", *curDrive);
428 bRes = CreateDirectoryA(tmpstr,NULL);
429 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
430 GetLastError() == ERROR_ALREADY_EXISTS),
431 "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
432 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
433 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
434 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
435 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
436 ok(CloseHandle(hndl),"CloseHandle failed\n");
437 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
438 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
439 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
440 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
441 ok(CloseHandle(hndl),"CloseHandle failed\n");
442 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
443 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
444 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
445 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
446 ok(CloseHandle(hndl),"CloseHandle failed\n");
447 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
448 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
449 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
450 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
451 ok(CloseHandle(hndl),"CloseHandle failed\n");
452 }
453
454 /* Test GetCurrentDirectory & SetCurrentDirectory */
455 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
456 {
457 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
458 char *buffer;
459 DWORD len,len1;
460 /* Save the original directory, so that we can return to it at the end
461 of the test
462 */
463 len=GetCurrentDirectoryA(MAX_PATH,origdir);
464 ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
465 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
466 buffer size is too small to hold the current directory
467 */
468 lstrcpyA(tmpstr,"aaaaaaa");
469 len1=GetCurrentDirectoryA(len,tmpstr);
470 ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
471 ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
472 "GetCurrentDirectoryA should not have modified the buffer\n");
473
474 buffer = HeapAlloc( GetProcessHeap(), 0, 2 * 65536 );
475 SetLastError( 0xdeadbeef );
476 strcpy( buffer, "foo" );
477 len = GetCurrentDirectoryA( 32767, buffer );
478 ok( len != 0 && len < MAX_PATH, "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
479 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
480 SetLastError( 0xdeadbeef );
481 strcpy( buffer, "foo" );
482 len = GetCurrentDirectoryA( 32768, buffer );
483 ok( len != 0 && len < MAX_PATH, "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
484 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
485 SetLastError( 0xdeadbeef );
486 strcpy( buffer, "foo" );
487 len = GetCurrentDirectoryA( 65535, buffer );
488 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4, win2k, xp */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
489 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
490 SetLastError( 0xdeadbeef );
491 strcpy( buffer, "foo" );
492 len = GetCurrentDirectoryA( 65536, buffer );
493 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4 */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
494 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
495 SetLastError( 0xdeadbeef );
496 strcpy( buffer, "foo" );
497 len = GetCurrentDirectoryA( 2 * 65536, buffer );
498 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4 */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
499 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
500 HeapFree( GetProcessHeap(), 0, buffer );
501
502 /* Check for crash prevention on swapped args. Crashes all but Win9x.
503 */
504 if (0)
505 {
506 GetCurrentDirectoryA( 42, (LPSTR)(MAX_PATH + 42) );
507 }
508
509 /* SetCurrentDirectoryA shouldn't care whether the string has a
510 trailing '\\' or not
511 */
512 sprintf(tmpstr,"%s\\",newdir);
513 test_setdir(origdir,tmpstr,newdir,1,"check 1");
514 test_setdir(origdir,newdir,NULL,1,"check 2");
515 /* Set the directory to the working area. We just tested that this works,
516 so why check it again.
517 */
518 SetCurrentDirectoryA(newdir);
519 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
520 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
521 test_setdir(newdir,tmpstr,NULL,0,"check 3");
522 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
523 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
524 test_setdir(newdir,tmpstr,NULL,0,"check 4");
525 /* Check that SetCurrentDirectory passes with a long directory */
526 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
527 test_setdir(newdir,tmpstr,NULL,1,"check 5");
528 /* Check that SetCurrentDirectory passes with a short relative directory */
529 sprintf(tmpstr,"%s",SHORTDIR);
530 sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
531 test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
532 /* starting with a '.' */
533 sprintf(tmpstr,".\\%s",SHORTDIR);
534 test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
535 /* Check that SetCurrentDirectory passes with a short relative directory */
536 sprintf(tmpstr,"%s",LONGDIR);
537 sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
538 test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
539 /* starting with a '.' */
540 sprintf(tmpstr,".\\%s",LONGDIR);
541 test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
542 /* change to root without a trailing backslash. The function call succeeds
543 but the directory is not changed.
544 */
545 sprintf(tmpstr, "%c:", newdir[0]);
546 test_setdir(newdir,tmpstr,newdir,1,"check 10");
547 /* works however with a trailing backslash */
548 sprintf(tmpstr, "%c:\\", newdir[0]);
549 test_setdir(newdir,tmpstr,NULL,1,"check 11");
550 }
551
552 /* Cleanup the mess we made while executing these tests */
553 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
554 {
555 CHAR tmpstr[MAX_PATH];
556 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
557 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
558 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
559 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
560 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
561 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
562 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
563 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
564 sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
565 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
566 sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
567 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
568 ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
569 ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
570 }
571
572 /* test that short path name functions work regardless of case */
573 static void test_ShortPathCase(const char *tmpdir, const char *dirname,
574 const char *filename)
575 {
576 char buf[MAX_PATH], shortbuf[MAX_PATH];
577 HANDLE hndl;
578 size_t i;
579
580 assert(strlen(tmpdir) + strlen(dirname) + strlen(filename) + 2 < sizeof(buf));
581 sprintf(buf,"%s\\%s\\%s",tmpdir,dirname,filename);
582 GetShortPathNameA(buf,shortbuf,sizeof(shortbuf));
583 hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
584 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
585 CloseHandle(hndl);
586 /* Now for the real test */
587 for(i=0;i<strlen(shortbuf);i++)
588 if (i % 2)
589 shortbuf[i] = tolower(shortbuf[i]);
590 hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
591 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
592 CloseHandle(hndl);
593 }
594
595 /* This routine will test Get(Full|Short|Long)PathNameA */
596 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
597 {
598 CHAR curdir_short[MAX_PATH],
599 longdir_short[MAX_PATH];
600 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
601 LPSTR strptr; /*ptr to the filename portion of the path */
602 DWORD len;
603 INT i;
604 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
605 SLpassfail passfail;
606
607 /* Get the short form of the current directory */
608 ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
609 "GetShortPathNameA failed\n");
610 ok(!HAS_TRAIL_SLASH_A(curdir_short),
611 "GetShortPathNameA should not have a trailing \\\n");
612 /* Get the short form of the absolute-path to LONGDIR */
613 sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
614 ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
615 "GetShortPathNameA failed\n");
616 ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
617 "GetShortPathNameA should not have a trailing \\\n");
618
619 if (pGetLongPathNameA) {
620 DWORD rc1,rc2;
621 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
622 rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
623 rc2=(*pGetLongPathNameA)(curdir,NULL,0);
624 ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
625 "GetLongPathNameA: wrong return code, %d instead of %d\n",
626 rc1, lstrlenA(tmpstr)+1);
627
628 sprintf(dir,"%c:",curDrive);
629 rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
630 ok(strcmp(dir,tmpstr)==0,
631 "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
632 tmpstr,dir,rc1);
633 }
634
635 /* Check the cases where both file and directory exist first */
636 /* Start with a 8.3 directory, 8.3 filename */
637 test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
638 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
639 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
640 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
641 /* Now try a 8.3 directory, long file name */
642 test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
643 sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
644 test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
645 /* Next is a long directory, 8.3 file */
646 test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
647 sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
648 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
649 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
650 /*Lastly a long directory, long file */
651 test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
652 test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
653
654 /* Now check all of the invalid file w/ valid directory combinations */
655 /* Start with a 8.3 directory, 8.3 filename */
656 test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
657 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
658 ok((passfail.shortlen==0 &&
659 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
660 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
661 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
662 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
663 passfail.shortlen,passfail.shorterror,tmpstr);
664 if(pGetLongPathNameA) {
665 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
666 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
667 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
668 }
669 /* Now try a 8.3 directory, long file name */
670 test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
671 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
672 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
673 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
674 !passfail.shorterror,
675 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
676 if(pGetLongPathNameA) {
677 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
678 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
679 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
680 }
681 /* Next is a long directory, 8.3 file */
682 test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
683 sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
684 GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
685 strcat(tmpstr1,"\\" NONFILE_SHORT);
686 ok((passfail.shortlen==0 &&
687 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
688 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
689 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
690 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
691 passfail.shortlen,passfail.shorterror,tmpstr);
692 if(pGetLongPathNameA) {
693 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
694 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
695 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
696 }
697 /*Lastly a long directory, long file */
698 test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
699 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
700 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
701 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
702 !passfail.shorterror,
703 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
704 if(pGetLongPathNameA) {
705 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
706 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
707 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
708 }
709 /* Now try again with directories that don't exist */
710 /* 8.3 directory, 8.3 filename */
711 test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
712 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
713 ok((passfail.shortlen==0 &&
714 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
715 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
716 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
717 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
718 passfail.shortlen,passfail.shorterror,tmpstr);
719 if(pGetLongPathNameA) {
720 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
721 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
722 passfail.longerror==ERROR_FILE_NOT_FOUND,
723 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
724 passfail.longerror);
725 }
726 /* Now try a 8.3 directory, long file name */
727 test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
728 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
729 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
730 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
731 !passfail.shorterror,
732 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
733 passfail.shorterror);
734 if(pGetLongPathNameA) {
735 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
736 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
737 passfail.longerror==ERROR_FILE_NOT_FOUND,
738 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
739 passfail.longerror);
740 }
741 /* Next is a long directory, 8.3 file */
742 test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
743 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
744 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
745 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
746 !passfail.shorterror,
747 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
748 passfail.shorterror);
749 if(pGetLongPathNameA) {
750 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
751 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
752 passfail.longerror==ERROR_FILE_NOT_FOUND,
753 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
754 passfail.longerror);
755 }
756 /*Lastly a long directory, long file */
757 test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
758 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
759 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
760 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
761 !passfail.shorterror,
762 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
763 passfail.shorterror);
764 if(pGetLongPathNameA) {
765 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
766 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
767 passfail.longerror==ERROR_FILE_NOT_FOUND,
768 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
769 passfail.longerror);
770 }
771 /* Next try directories ending with '\\' */
772 /* Existing Directories */
773 sprintf(tmpstr,"%s\\",SHORTDIR);
774 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
775 sprintf(tmpstr,"%s\\",LONGDIR);
776 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
777 /* Nonexistent directories */
778 sprintf(tmpstr,"%s\\",NONDIR_SHORT);
779 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
780 sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
781 ok((passfail.shortlen==0 &&
782 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
783 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
784 (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
785 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
786 passfail.shortlen,passfail.shorterror,tmpstr);
787 if(pGetLongPathNameA) {
788 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
789 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
790 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
791 passfail.longerror);
792 }
793 sprintf(tmpstr,"%s\\",NONDIR_LONG);
794 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
795 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
796 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
797 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
798 !passfail.shorterror,
799 "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
800 passfail.shorterror);
801 if(pGetLongPathNameA) {
802 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
803 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
804 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
805 passfail.longerror);
806 }
807 /* Test GetFullPathNameA with drive letters */
808 if( curDrive != NOT_A_VALID_DRIVE) {
809 sprintf(tmpstr,"%c:",curdir[0]);
810 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
811 "GetFullPathNameA(%c:) failed\n", curdir[0]);
812 GetCurrentDirectoryA(MAX_PATH,tmpstr);
813 sprintf(tmpstr1,"%s\\",tmpstr);
814 ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
815 "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
816 curdir[0],tmpstr2,tmpstr,tmpstr1);
817
818 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
819 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
820 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
821 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
822 ok(lstrcmpiA(SHORTFILE,strptr)==0,
823 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
824 }
825 /* Without a leading slash, insert the current directory if on the current drive */
826 sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
827 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
828 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
829 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
830 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
831 ok(lstrcmpiA(SHORTFILE,strptr)==0,
832 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
833 /* Otherwise insert the missing leading slash */
834 if( otherDrive != NOT_A_VALID_DRIVE) {
835 /* FIXME: this test assumes that current directory on other drive is root */
836 sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
837 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
838 sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
839 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
840 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
841 ok(lstrcmpiA(SHORTFILE,strptr)==0,
842 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
843 }
844 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
845 So test for them. */
846 if( curDrive != NOT_A_VALID_DRIVE) {
847 sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
848 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
849 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
850 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
851 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
852 ok(lstrcmpiA(SHORTFILE,strptr)==0,
853 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
854 }
855 /* Don't Starve relies on GetLongPathName returning the passed in filename,
856 even if the actual file on disk has a different case or separator */
857 if (pGetLongPathNameA) {
858 int len = lstrlenA(LONGDIR) + 1;
859 sprintf(tmpstr,"%s/%s",LONGDIR,LONGFILE);
860 ok(GetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
861 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
862 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
863 tmpstr[len] = tolower(tmpstr[len]);
864 ok(GetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
865 ok(lstrcmpA(tmpstr,tmpstr1)==0,
866 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
867 sprintf(tmpstr,"%s/%s",SHORTDIR,SHORTFILE);
868 ok(GetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
869 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
870 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
871 len = lstrlenA(SHORTDIR) + 1;
872 tmpstr[len] = toupper(tmpstr[len]);
873 ok(GetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
874 ok(lstrcmpiA(tmpstr,tmpstr1)==0 && lstrcmpA(tmpstr,tmpstr1) != 0,
875 "GetLongPathNameA returned '%s' instead of '%s/%s'\n",tmpstr1,SHORTDIR,SHORTFILE);
876 }
877 sprintf(tmpstr,"%s/%s",SHORTDIR,SHORTFILE);
878 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
879 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
880 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
881
882 /**/
883 sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
884 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
885 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
886 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
887 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
888 ok(lstrcmpiA(SHORTFILE,strptr)==0,
889 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
890 /* Windows will insert a drive letter in front of an absolute UNIX path */
891 sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
892 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
893 sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
894 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
895 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
896 /* This passes in Wine because it still contains the pointer from the previous test */
897 ok(lstrcmpiA(SHORTFILE,strptr)==0,
898 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
899
900 /* Now try some relative paths */
901 ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
902 test_SplitShortPathA(tmpstr,dir,eight,three);
903 if(pGetLongPathNameA) {
904 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
905 ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
906 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
907 }
908 sprintf(tmpstr,".\\%s",LONGDIR);
909 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
910 test_SplitShortPathA(tmpstr1,dir,eight,three);
911 ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
912 "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
913 if(pGetLongPathNameA) {
914 ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
915 tmpstr);
916 ok(lstrcmpiA(tmpstr1,tmpstr)==0,
917 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
918 }
919 /* Check out Get*PathNameA on some funny characters */
920 for(i=0;i<lstrlenA(funny_chars);i++) {
921 INT valid;
922 valid=(is_char_ok[i]=='0') ? 0 : 1;
923 sprintf(tmpstr1,"check%d-1",i);
924 sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
925 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
926 sprintf(tmpstr1,"check%d-2",i);
927 sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
928 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
929 sprintf(tmpstr1,"check%d-3",i);
930 sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
931 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
932 sprintf(tmpstr1,"check%d-4",i);
933 sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
934 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
935 sprintf(tmpstr1,"check%d-5",i);
936 sprintf(tmpstr,"Long %c File",funny_chars[i]);
937 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
938 sprintf(tmpstr1,"check%d-6",i);
939 sprintf(tmpstr,"%c Long File",funny_chars[i]);
940 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
941 sprintf(tmpstr1,"check%d-7",i);
942 sprintf(tmpstr,"Long File %c",funny_chars[i]);
943 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
944 }
945 /* Now try it on mixed case short names */
946 test_ShortPathCase(curdir,SHORTDIR,LONGFILE);
947 test_ShortPathCase(curdir,LONGDIR,SHORTFILE);
948 test_ShortPathCase(curdir,LONGDIR,LONGFILE);
949
950 /* test double delimiters */
951 sprintf(tmpstr,"%s\\\\%s", SHORTDIR,SHORTFILE);
952 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
953 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
954 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
955 sprintf(tmpstr,".\\\\%s\\\\%s", SHORTDIR,SHORTFILE);
956 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
957 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
958 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
959
960 if (pGetLongPathNameA) {
961 sprintf(tmpstr,"%s\\\\%s",LONGDIR,LONGFILE);
962 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
963 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
964 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
965
966 sprintf(tmpstr,".\\\\%s\\\\%s",LONGDIR,LONGFILE);
967 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
968 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
969 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
970 }
971 }
972
973 static void test_GetTempPathA(char* tmp_dir)
974 {
975 DWORD len, slen, len_with_null;
976 char buf[MAX_PATH];
977
978 len_with_null = strlen(tmp_dir) + 1;
979
980 lstrcpyA(buf, "foo");
981 len = GetTempPathA(MAX_PATH, buf);
982 ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
983 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
984 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
985
986 /* Some versions of Windows touch the buffer, some don't so we don't
987 * test that. Also, NT sometimes exaggerates the required buffer size
988 * so we cannot test for an exact match. Finally, the
989 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
990 * For instance in some cases Win98 returns len_with_null - 1 instead
991 * of len_with_null.
992 */
993 len = GetTempPathA(1, buf);
994 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
995
996 len = GetTempPathA(0, NULL);
997 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
998
999 /* The call above gave us the buffer size that Windows thinks is needed
1000 * so the next call should work
1001 */
1002 lstrcpyA(buf, "foo");
1003 len = GetTempPathA(len, buf);
1004 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
1005 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
1006
1007 memset(buf, 'a', sizeof(buf));
1008 len = GetTempPathA(sizeof(buf), buf);
1009 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
1010 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
1011 /* The rest of the buffer remains untouched */
1012 slen = len + 1;
1013 for(len++; len < sizeof(buf); len++)
1014 ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
1015
1016 /* When the buffer is not long enough it remains untouched */
1017 memset(buf, 'a', sizeof(buf));
1018 len = GetTempPathA(slen / 2, buf);
1019 ok(len == slen || broken(len == slen + 1) /* read the big comment above */ ,
1020 "expected %d, got %d\n", slen, len);
1021 for(len = 0; len < sizeof(buf) / sizeof(buf[0]); len++)
1022 ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
1023 }
1024
1025 static void test_GetTempPathW(char* tmp_dir)
1026 {
1027 DWORD len, slen, len_with_null;
1028 WCHAR buf[MAX_PATH], *long_buf;
1029 WCHAR tmp_dirW[MAX_PATH];
1030 static const WCHAR fooW[] = {'f','o','o',0};
1031
1032 MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
1033 len_with_null = lstrlenW(tmp_dirW) + 1;
1034
1035 /* This one is different from ANSI version: ANSI version doesn't
1036 * touch the buffer, unicode version usually truncates the buffer
1037 * to zero size. NT still exaggerates the required buffer size
1038 * sometimes so we cannot test for an exact match. Finally, the
1039 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
1040 * For instance on NT4 it will sometimes return a path without the
1041 * trailing '\\' and sometimes return an error.
1042 */
1043
1044 lstrcpyW(buf, fooW);
1045 len = GetTempPathW(MAX_PATH, buf);
1046 if (len == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1047 {
1048 win_skip("GetTempPathW is not available\n");
1049 return;
1050 }
1051 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
1052 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
1053
1054 lstrcpyW(buf, fooW);
1055 len = GetTempPathW(1, buf);
1056 ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
1057 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
1058
1059 len = GetTempPathW(0, NULL);
1060 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
1061
1062 lstrcpyW(buf, fooW);
1063 len = GetTempPathW(len, buf);
1064 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
1065 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
1066
1067 for(len = 0; len < sizeof(buf) / sizeof(buf[0]); len++)
1068 buf[len] = 'a';
1069 len = GetTempPathW(len, buf);
1070 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
1071 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
1072 /* The rest of the buffer must be zeroed */
1073 slen = len + 1;
1074 for(len++; len < sizeof(buf) / sizeof(buf[0]); len++)
1075 ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]);
1076
1077 /* When the buffer is not long enough the length passed is zeroed */
1078 for(len = 0; len < sizeof(buf) / sizeof(buf[0]); len++)
1079 buf[len] = 'a';
1080 len = GetTempPathW(slen / 2, buf);
1081 ok(len == slen || broken(len == slen + 1) /* read the big comment above */ ,
1082 "expected %d, got %d\n", slen, len);
1083
1084 {
1085 /* In Windows 8 when TMP var points to a drive only (like C:) instead of a
1086 * full directory the behavior changes. It will start filling the path but
1087 * will later truncate the buffer before returning. So the generic test
1088 * below will fail for this Windows 8 corner case.
1089 */
1090 char tmp_var[64];
1091 DWORD version = GetVersion();
1092 GetEnvironmentVariableA("TMP", tmp_var, sizeof(tmp_var));
1093 if (strlen(tmp_var) == 2 && version >= 0x00060002)
1094 return;
1095 }
1096
1097 for(len = 0; len < slen / 2; len++)
1098 ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]);
1099 for(; len < sizeof(buf) / sizeof(buf[0]); len++)
1100 ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
1101
1102 /* bogus application from bug 38220 passes the count value in sizeof(buffer)
1103 * instead the correct count of WCHAR, this test catches this case. */
1104 slen = 65534;
1105 long_buf = HeapAlloc(GetProcessHeap(), 0, slen * sizeof(WCHAR));
1106 if (!long_buf)
1107 {
1108 skip("Could not allocate memory for the test\n");
1109 return;
1110 }
1111 for(len = 0; len < slen; len++)
1112 long_buf[len] = 0xCC;
1113 len = GetTempPathW(slen, long_buf);
1114 ok(lstrcmpiW(long_buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
1115 ok(len == lstrlenW(long_buf), "returned length should be equal to the length of string\n");
1116 /* the remaining buffer must be zeroed up to different values in different OS versions.
1117 * <= XP - 32766
1118 * > XP - 32767
1119 * to simplify testing we will test only until XP.
1120 */
1121 for(; len < 32767; len++)
1122 ok(long_buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, long_buf[len]);
1123 /* we will know skip the test that is in the middle of the OS difference by
1124 * incrementing len and then resume the test for the untouched part. */
1125 for(len++; len < slen; len++)
1126 ok(long_buf[len] == 0xcc, "expected 0xcc at [%d], got 0x%x\n", len, long_buf[len]);
1127
1128 HeapFree(GetProcessHeap(), 0, long_buf);
1129 }
1130
1131 static void test_GetTempPath(void)
1132 {
1133 char save_TMP[MAX_PATH];
1134 char windir[MAX_PATH];
1135 char buf[MAX_PATH];
1136 WCHAR curdir[MAX_PATH];
1137
1138 if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
1139
1140 /* test default configuration */
1141 trace("TMP=%s\n", save_TMP);
1142 if (save_TMP[0])
1143 {
1144 strcpy(buf,save_TMP);
1145 if (buf[strlen(buf)-1]!='\\')
1146 strcat(buf,"\\");
1147 test_GetTempPathA(buf);
1148 test_GetTempPathW(buf);
1149 }
1150
1151 /* TMP=C:\WINDOWS */
1152 GetWindowsDirectoryA(windir, sizeof(windir));
1153 SetEnvironmentVariableA("TMP", windir);
1154 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1155 trace("TMP=%s\n", buf);
1156 strcat(windir,"\\");
1157 test_GetTempPathA(windir);
1158 test_GetTempPathW(windir);
1159
1160 /* TMP=C:\ */
1161 GetWindowsDirectoryA(windir, sizeof(windir));
1162 windir[3] = 0;
1163 SetEnvironmentVariableA("TMP", windir);
1164 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1165 trace("TMP=%s\n", buf);
1166 test_GetTempPathA(windir);
1167 test_GetTempPathW(windir);
1168
1169 GetCurrentDirectoryW(MAX_PATH, curdir);
1170 /* TMP=C: i.e. use current working directory of the specified drive */
1171 GetWindowsDirectoryA(windir, sizeof(windir));
1172 SetCurrentDirectoryA(windir);
1173 windir[2] = 0;
1174 SetEnvironmentVariableA("TMP", windir);
1175 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1176 trace("TMP=%s\n", buf);
1177 GetWindowsDirectoryA(windir, sizeof(windir));
1178 strcat(windir,"\\");
1179 test_GetTempPathA(windir);
1180 test_GetTempPathW(windir);
1181
1182 SetEnvironmentVariableA("TMP", save_TMP);
1183 SetCurrentDirectoryW(curdir);
1184 }
1185
1186 static void test_GetLongPathNameA(void)
1187 {
1188 DWORD length, explength, hostsize;
1189 char tempfile[MAX_PATH], *name;
1190 char longpath[MAX_PATH];
1191 char unc_prefix[MAX_PATH];
1192 char unc_short[MAX_PATH], unc_long[MAX_PATH];
1193 char temppath[MAX_PATH], temppath2[MAX_PATH];
1194 HANDLE file;
1195
1196 if (!pGetLongPathNameA)
1197 return;
1198
1199 GetTempPathA(MAX_PATH, tempfile);
1200 name = tempfile + strlen(tempfile);
1201
1202 strcpy(name, "*");
1203 SetLastError(0xdeadbeef);
1204 length = pGetLongPathNameA(tempfile, temppath, MAX_PATH);
1205 ok(!length, "GetLongPathNameA should fail\n");
1206 ok(GetLastError() == ERROR_INVALID_NAME, "wrong error %d\n", GetLastError());
1207
1208 strcpy(name, "longfilename.longext");
1209
1210 file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1211 CloseHandle(file);
1212
1213 /* Test a normal path with a small buffer size */
1214 memset(temppath, 0, MAX_PATH);
1215 length = pGetLongPathNameA(tempfile, temppath, 4);
1216 /* We have a failure so length should be the minimum plus the terminating '0' */
1217 ok(length >= strlen(tempfile) + 1, "Wrong length\n");
1218 ok(temppath[0] == 0, "Buffer should not have been touched\n");
1219
1220 /* Some UNC syntax tests */
1221
1222 memset(temppath, 0, MAX_PATH);
1223 memset(temppath2, 0, MAX_PATH);
1224 lstrcpyA(temppath2, "\\\\?\\");
1225 lstrcatA(temppath2, tempfile);
1226 explength = length + 4;
1227
1228 SetLastError(0xdeadbeef);
1229 length = pGetLongPathNameA(temppath2, NULL, 0);
1230 if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME)
1231 {
1232 win_skip("UNC syntax tests don't work on Win98/WinMe\n");
1233 DeleteFileA(tempfile);
1234 return;
1235 }
1236 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1237
1238 length = pGetLongPathNameA(temppath2, NULL, MAX_PATH);
1239 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1240
1241 length = pGetLongPathNameA(temppath2, temppath, 4);
1242 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1243 ok(temppath[0] == 0, "Buffer should not have been touched\n");
1244
1245 /* Now an UNC path with the computername */
1246 lstrcpyA(unc_prefix, "\\\\");
1247 hostsize = sizeof(unc_prefix) - 2;
1248 GetComputerNameA(unc_prefix + 2, &hostsize);
1249 lstrcatA(unc_prefix, "\\");
1250
1251 /* Create a short syntax for the whole unc path */
1252 memset(unc_short, 0, MAX_PATH);
1253 GetShortPathNameA(tempfile, temppath, MAX_PATH);
1254 lstrcpyA(unc_short, unc_prefix);
1255 unc_short[lstrlenA(unc_short)] = temppath[0];
1256 lstrcatA(unc_short, "$\\");
1257 lstrcatA(unc_short, strchr(temppath, '\\') + 1);
1258
1259 /* Create a long syntax for reference */
1260 memset(longpath, 0, MAX_PATH);
1261 pGetLongPathNameA(tempfile, temppath, MAX_PATH);
1262 lstrcpyA(longpath, unc_prefix);
1263 longpath[lstrlenA(longpath)] = temppath[0];
1264 lstrcatA(longpath, "$\\");
1265 lstrcatA(longpath, strchr(temppath, '\\') + 1);
1266
1267 /* NULL test */
1268 SetLastError(0xdeadbeef);
1269 length = pGetLongPathNameA(unc_short, NULL, 0);
1270 if (length == 0 && GetLastError() == ERROR_BAD_NETPATH)
1271 {
1272 /* Seen on Window XP Home */
1273 win_skip("UNC with computername is not supported\n");
1274 DeleteFileA(tempfile);
1275 return;
1276 }
1277 explength = lstrlenA(longpath) + 1;
1278 todo_wine
1279 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1280
1281 length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
1282 todo_wine
1283 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1284
1285 memset(unc_long, 0, MAX_PATH);
1286 length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
1287 /* length will include terminating '0' on failure */
1288 todo_wine
1289 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1290 ok(unc_long[0] == 0, "Buffer should not have been touched\n");
1291
1292 memset(unc_long, 0, MAX_PATH);
1293 length = pGetLongPathNameA(unc_short, unc_long, length);
1294 /* length doesn't include terminating '0' on success */
1295 explength--;
1296 todo_wine
1297 {
1298 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1299 ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
1300 }
1301
1302 DeleteFileA(tempfile);
1303 }
1304
1305 static void test_GetLongPathNameW(void)
1306 {
1307 DWORD length, expanded;
1308 BOOL ret;
1309 HANDLE file;
1310 WCHAR empty[MAX_PATH];
1311 WCHAR tempdir[MAX_PATH], name[200];
1312 WCHAR dirpath[4 + MAX_PATH + 200]; /* To ease removal */
1313 WCHAR shortpath[4 + MAX_PATH + 200 + 1 + 200];
1314 static const WCHAR prefix[] = { '\\','\\','?','\\', 0};
1315 static const WCHAR backslash[] = { '\\', 0};
1316 static const WCHAR letterX[] = { 'X', 0};
1317
1318 if (!pGetLongPathNameW)
1319 return;
1320
1321 SetLastError(0xdeadbeef);
1322 length = pGetLongPathNameW(NULL,NULL,0);
1323 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1324 {
1325 win_skip("GetLongPathNameW is not implemented\n");
1326 return;
1327 }
1328 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1329 ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
1330
1331 SetLastError(0xdeadbeef);
1332 empty[0]=0;
1333 length = pGetLongPathNameW(empty,NULL,0);
1334 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1335 ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
1336
1337 /* Create a long path name. The path needs to exist for these tests to
1338 * succeed so we need the "\\?\" prefix when creating directories and
1339 * files.
1340 */
1341 name[0] = 0;
1342 while (lstrlenW(name) < (sizeof(name)/sizeof(WCHAR) - 1))
1343 lstrcatW(name, letterX);
1344
1345 GetTempPathW(MAX_PATH, tempdir);
1346
1347 lstrcpyW(shortpath, prefix);
1348 lstrcatW(shortpath, tempdir);
1349 lstrcatW(shortpath, name);
1350 lstrcpyW(dirpath, shortpath);
1351 ret = CreateDirectoryW(shortpath, NULL);
1352 ok(ret, "Could not create the temporary directory : %d\n", GetLastError());
1353 lstrcatW(shortpath, backslash);
1354 lstrcatW(shortpath, name);
1355
1356 /* Path does not exist yet and we know it overruns MAX_PATH */
1357
1358 /* No prefix */
1359 SetLastError(0xdeadbeef);
1360 length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1361 ok(length == 0, "Expected 0, got %d\n", length);
1362 todo_wine
1363 ok(GetLastError() == ERROR_PATH_NOT_FOUND,
1364 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1365 /* With prefix */
1366 SetLastError(0xdeadbeef);
1367 length = pGetLongPathNameW(shortpath, NULL, 0);
1368 todo_wine
1369 {
1370 ok(length == 0, "Expected 0, got %d\n", length);
1371 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1372 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1373 }
1374
1375 file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1376 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1377 ok(file != INVALID_HANDLE_VALUE,
1378 "Could not create the temporary file : %d.\n", GetLastError());
1379 CloseHandle(file);
1380
1381 /* Path exists */
1382
1383 /* No prefix */
1384 SetLastError(0xdeadbeef);
1385 length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1386 todo_wine
1387 {
1388 ok(length == 0, "Expected 0, got %d\n", length);
1389 ok(GetLastError() == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1390 }
1391 /* With prefix */
1392 expanded = 4 + (pGetLongPathNameW(tempdir, NULL, 0) - 1) + lstrlenW(name) + 1 + lstrlenW(name) + 1;
1393 SetLastError(0xdeadbeef);
1394 length = pGetLongPathNameW(shortpath, NULL, 0);
1395 ok(length == expanded, "Expected %d, got %d\n", expanded, length);
1396
1397 /* NULL buffer with length crashes on Windows */
1398 if (0)
1399 pGetLongPathNameW(shortpath, NULL, 20);
1400
1401 ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
1402 ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
1403 }
1404
1405 static void test_GetShortPathNameW(void)
1406 {
1407 static const WCHAR extended_prefix[] = {'\\','\\','?','\\',0};
1408 static const WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e', 0 };
1409 static const WCHAR name[] = { 't', 'e', 's', 't', 0 };
1410 static const WCHAR backSlash[] = { '\\', 0 };
1411 static const WCHAR a_bcdeW[] = {'a','.','b','c','d','e',0};
1412 static const WCHAR wildW[] = { '*',0 };
1413 WCHAR path[MAX_PATH], tmppath[MAX_PATH], *ptr;
1414 WCHAR short_path[MAX_PATH];
1415 DWORD length;
1416 HANDLE file;
1417 int ret;
1418
1419 SetLastError(0xdeadbeef);
1420 GetTempPathW( MAX_PATH, tmppath );
1421 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1422 {
1423 win_skip("GetTempPathW is not implemented\n");
1424 return;
1425 }
1426
1427 lstrcpyW( path, tmppath );
1428 lstrcatW( path, test_path );
1429 lstrcatW( path, backSlash );
1430 ret = CreateDirectoryW( path, NULL );
1431 ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
1432
1433 /* Starting a main part of test */
1434
1435 /* extended path \\?\C:\path\ */
1436 lstrcpyW( path, extended_prefix );
1437 lstrcatW( path, tmppath );
1438 lstrcatW( path, test_path );
1439 lstrcatW( path, backSlash );
1440 short_path[0] = 0;
1441 length = GetShortPathNameW( path, short_path, sizeof(short_path) / sizeof(*short_path) );
1442 ok( length, "GetShortPathNameW returned 0.\n" );
1443
1444 lstrcpyW( path, tmppath );
1445 lstrcatW( path, test_path );
1446 lstrcatW( path, backSlash );
1447 length = GetShortPathNameW( path, short_path, 0 );
1448 ok( length, "GetShortPathNameW returned 0.\n" );
1449 ret = GetShortPathNameW( path, short_path, length );
1450 ok( ret && ret == length-1, "GetShortPathNameW returned 0.\n" );
1451
1452 lstrcatW( short_path, name );
1453
1454 /* GetShortPathName for a non-existent short file name should fail */
1455 SetLastError(0xdeadbeef);
1456 length = GetShortPathNameW( short_path, path, 0 );
1457 ok(!length, "GetShortPathNameW should fail\n");
1458 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1459
1460 file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1461 ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1462 CloseHandle( file );
1463 ret = DeleteFileW( short_path );
1464 ok( ret, "Cannot delete file.\n" );
1465
1466 ptr = path + lstrlenW(path);
1467 lstrcpyW( ptr, a_bcdeW);
1468 file = CreateFileW( path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1469 ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1470 CloseHandle( file );
1471
1472 length = GetShortPathNameW( path, short_path, sizeof(short_path)/sizeof(*short_path) );
1473 ok( length, "GetShortPathNameW failed: %u.\n", GetLastError() );
1474
1475 lstrcpyW(ptr, wildW);
1476 SetLastError(0xdeadbeef);
1477 length = GetShortPathNameW( path, short_path, sizeof(short_path)/sizeof(*short_path) );
1478 ok(!length, "GetShortPathNameW should fail\n");
1479 ok(GetLastError() == ERROR_INVALID_NAME, "wrong error %d\n", GetLastError());
1480
1481 lstrcpyW(ptr, a_bcdeW);
1482 ret = DeleteFileW( path );
1483 ok( ret, "Cannot delete file.\n" );
1484 *ptr = 0;
1485
1486 /* End test */
1487 ret = RemoveDirectoryW( path );
1488 ok( ret, "Cannot delete directory.\n" );
1489 }
1490
1491 static void test_GetSystemDirectory(void)
1492 {
1493 CHAR buffer[MAX_PATH + 4];
1494 DWORD res;
1495 DWORD total;
1496
1497 SetLastError(0xdeadbeef);
1498 res = GetSystemDirectoryA(NULL, 0);
1499 /* res includes the terminating Zero */
1500 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1501
1502 total = res;
1503
1504 /* this crashes on XP */
1505 if (0)
1506 GetSystemDirectoryA(NULL, total);
1507
1508 SetLastError(0xdeadbeef);
1509 res = GetSystemDirectoryA(NULL, total-1);
1510 /* 95+NT: total (includes the terminating Zero)
1511 98+ME: 0 with ERROR_INVALID_PARAMETER */
1512 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1513 "returned %d with %d (expected '%d' or: '0' with "
1514 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1515
1516 if (total > MAX_PATH) return;
1517
1518 buffer[0] = '\0';
1519 SetLastError(0xdeadbeef);
1520 res = GetSystemDirectoryA(buffer, total);
1521 /* res does not include the terminating Zero */
1522 ok( (res == (total-1)) && (buffer[0]),
1523 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1524 res, GetLastError(), buffer, total-1);
1525
1526 buffer[0] = '\0';
1527 SetLastError(0xdeadbeef);
1528 res = GetSystemDirectoryA(buffer, total + 1);
1529 /* res does not include the terminating Zero */
1530 ok( (res == (total-1)) && (buffer[0]),
1531 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1532 res, GetLastError(), buffer, total-1);
1533
1534 memset(buffer, '#', total + 1);
1535 buffer[total + 2] = '\0';
1536 SetLastError(0xdeadbeef);
1537 res = GetSystemDirectoryA(buffer, total-1);
1538 /* res includes the terminating Zero) */
1539 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1540 res, GetLastError(), buffer, total);
1541
1542 memset(buffer, '#', total + 1);
1543 buffer[total + 2] = '\0';
1544 SetLastError(0xdeadbeef);
1545 res = GetSystemDirectoryA(buffer, total-2);
1546 /* res includes the terminating Zero) */
1547 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1548 res, GetLastError(), buffer, total);
1549 }
1550
1551 static void test_GetWindowsDirectory(void)
1552 {
1553 CHAR buffer[MAX_PATH + 4];
1554 DWORD res;
1555 DWORD total;
1556
1557 SetLastError(0xdeadbeef);
1558 res = GetWindowsDirectoryA(NULL, 0);
1559 /* res includes the terminating Zero */
1560 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1561
1562 total = res;
1563 /* this crashes on XP */
1564 if (0)
1565 GetWindowsDirectoryA(NULL, total);
1566
1567 SetLastError(0xdeadbeef);
1568 res = GetWindowsDirectoryA(NULL, total-1);
1569 /* 95+NT: total (includes the terminating Zero)
1570 98+ME: 0 with ERROR_INVALID_PARAMETER */
1571 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1572 "returned %d with %d (expected '%d' or: '0' with "
1573 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1574
1575 if (total > MAX_PATH) return;
1576
1577 buffer[0] = '\0';
1578 SetLastError(0xdeadbeef);
1579 res = GetWindowsDirectoryA(buffer, total);
1580 /* res does not include the terminating Zero */
1581 ok( (res == (total-1)) && (buffer[0]),
1582 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1583 res, GetLastError(), buffer, total-1);
1584
1585 buffer[0] = '\0';
1586 SetLastError(0xdeadbeef);
1587 res = GetWindowsDirectoryA(buffer, total + 1);
1588 /* res does not include the terminating Zero */
1589 ok( (res == (total-1)) && (buffer[0]),
1590 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1591 res, GetLastError(), buffer, total-1);
1592
1593 memset(buffer, '#', total + 1);
1594 buffer[total + 2] = '\0';
1595 SetLastError(0xdeadbeef);
1596 res = GetWindowsDirectoryA(buffer, total-1);
1597 /* res includes the terminating Zero) */
1598 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1599 res, GetLastError(), buffer, total);
1600
1601 memset(buffer, '#', total + 1);
1602 buffer[total + 2] = '\0';
1603 SetLastError(0xdeadbeef);
1604 res = GetWindowsDirectoryA(buffer, total-2);
1605 /* res includes the terminating Zero) */
1606 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1607 res, GetLastError(), buffer, total);
1608 }
1609
1610 static void test_NeedCurrentDirectoryForExePathA(void)
1611 {
1612 if (!pNeedCurrentDirectoryForExePathA)
1613 {
1614 win_skip("NeedCurrentDirectoryForExePathA is not available\n");
1615 return;
1616 }
1617
1618 /* Crashes in Windows */
1619 if (0)
1620 pNeedCurrentDirectoryForExePathA(NULL);
1621
1622 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1623 ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1624 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1625 ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1626
1627 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1628 ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1629 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1630 ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1631 }
1632
1633 static void test_NeedCurrentDirectoryForExePathW(void)
1634 {
1635 const WCHAR thispath[] = {'.', 0};
1636 const WCHAR fullpath[] = {'c', ':', '\\', 0};
1637 const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1638
1639 if (!pNeedCurrentDirectoryForExePathW)
1640 {
1641 win_skip("NeedCurrentDirectoryForExePathW is not available\n");
1642 return;
1643 }
1644
1645 /* Crashes in Windows */
1646 if (0)
1647 pNeedCurrentDirectoryForExePathW(NULL);
1648
1649 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1650 ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1651 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1652 ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1653
1654 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1655 ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1656 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1657 ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1658 }
1659
1660 /* Call various path/file name retrieving APIs and check the case of
1661 * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1662 * installer) depend on the drive letter being in upper case.
1663 */
1664 static void test_drive_letter_case(void)
1665 {
1666 UINT ret;
1667 char buf[MAX_PATH];
1668
1669 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1670
1671 memset(buf, 0, sizeof(buf));
1672 SetLastError(0xdeadbeef);
1673 ret = GetWindowsDirectoryA(buf, sizeof(buf));
1674 ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
1675 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1676 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1677 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1678
1679 /* re-use the buffer returned by GetFullPathName */
1680 buf[2] = '/';
1681 SetLastError(0xdeadbeef);
1682 ret = GetFullPathNameA(buf + 2, sizeof(buf), buf, NULL);
1683 ok(ret, "GetFullPathName error %u\n", GetLastError());
1684 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1685 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1686 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1687
1688 memset(buf, 0, sizeof(buf));
1689 SetLastError(0xdeadbeef);
1690 ret = GetSystemDirectoryA(buf, sizeof(buf));
1691 ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1692 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1693 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1694 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1695
1696 memset(buf, 0, sizeof(buf));
1697 SetLastError(0xdeadbeef);
1698 ret = GetCurrentDirectoryA(sizeof(buf), buf);
1699 ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1700 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1701 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1702 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1703
1704 /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
1705 memset(buf, 0, sizeof(buf));
1706 SetLastError(0xdeadbeef);
1707 ret = GetTempPathA(sizeof(buf), buf);
1708 ok(ret, "GetTempPath error %u\n", GetLastError());
1709 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1710 if (buf[0])
1711 {
1712 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1713 ok(buf[strlen(buf)-1] == '\\', "Temporary path (%s) doesn't end in a slash\n", buf);
1714 }
1715
1716 memset(buf, 0, sizeof(buf));
1717 SetLastError(0xdeadbeef);
1718 ret = GetFullPathNameA(".", sizeof(buf), buf, NULL);
1719 ok(ret, "GetFullPathName error %u\n", GetLastError());
1720 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1721 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1722 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1723
1724 /* re-use the buffer returned by GetFullPathName */
1725 SetLastError(0xdeadbeef);
1726 ret = GetShortPathNameA(buf, buf, sizeof(buf));
1727 ok(ret, "GetShortPathName error %u\n", GetLastError());
1728 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1729 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1730 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1731
1732 if (pGetLongPathNameA)
1733 {
1734 /* re-use the buffer returned by GetShortPathName */
1735 SetLastError(0xdeadbeef);
1736 ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1737 ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1738 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1739 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1740 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1741 }
1742 #undef is_upper_case_letter
1743 }
1744
1745 static const char manifest_dep[] =
1746 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1747 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
1748 " <file name=\"testdep.dll\" />"
1749 " <file name=\"ole32\" />"
1750 " <file name=\"kernel32.dll\" />"
1751 "</assembly>";
1752
1753 static const char manifest_main[] =
1754 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1755 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1756 "<dependency>"
1757 " <dependentAssembly>"
1758 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
1759 " </dependentAssembly>"
1760 "</dependency>"
1761 "</assembly>";
1762
1763 static void create_manifest_file(const char *filename, const char *manifest)
1764 {
1765 WCHAR path[MAX_PATH], manifest_path[MAX_PATH];
1766 HANDLE file;
1767 DWORD size;
1768
1769 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
1770
1771 GetTempPathW(sizeof(manifest_path)/sizeof(WCHAR), manifest_path);
1772 lstrcatW(manifest_path, path);
1773
1774 file = CreateFileW(manifest_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1775 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
1776 WriteFile(file, manifest, strlen(manifest), &size, NULL);
1777 CloseHandle(file);
1778 }
1779
1780 static void delete_manifest_file(const char *filename)
1781 {
1782 CHAR path[MAX_PATH];
1783
1784 GetTempPathA(sizeof(path), path);
1785 strcat(path, filename);
1786 DeleteFileA(path);
1787 }
1788
1789 static HANDLE test_create(const char *file)
1790 {
1791 WCHAR path[MAX_PATH], manifest_path[MAX_PATH];
1792 ACTCTXW actctx;
1793 HANDLE handle;
1794
1795 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
1796 GetTempPathW(sizeof(manifest_path)/sizeof(WCHAR), manifest_path);
1797 lstrcatW(manifest_path, path);
1798
1799 memset(&actctx, 0, sizeof(ACTCTXW));
1800 actctx.cbSize = sizeof(ACTCTXW);
1801 actctx.lpSource = manifest_path;
1802
1803 handle = pCreateActCtxW(&actctx);
1804 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
1805
1806 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
1807 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
1808 ok(actctx.lpSource == manifest_path, "lpSource=%p\n", actctx.lpSource);
1809 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
1810 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
1811 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
1812 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
1813 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
1814 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
1815
1816 return handle;
1817 }
1818
1819 static void test_SearchPathA(void)
1820 {
1821 static const CHAR testdepA[] = "testdep.dll";
1822 static const CHAR testdeprelA[] = "./testdep.dll";
1823 static const CHAR kernel32A[] = "kernel32.dll";
1824 static const CHAR fileA[] = "";
1825 CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH], path3A[MAX_PATH], curdirA[MAX_PATH];
1826 CHAR tmpdirA[MAX_PATH], *ptrA = NULL;
1827 ULONG_PTR cookie;
1828 HANDLE handle;
1829 BOOL bret;
1830 DWORD ret;
1831
1832 if (!pSearchPathA)
1833 {
1834 win_skip("SearchPathA isn't available\n");
1835 return;
1836 }
1837
1838 GetWindowsDirectoryA(pathA, sizeof(pathA)/sizeof(CHAR));
1839
1840 /* NULL filename */
1841 SetLastError(0xdeadbeef);
1842 ret = pSearchPathA(pathA, NULL, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
1843 ok(ret == 0, "Expected failure, got %d\n", ret);
1844 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1845 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1846
1847 /* empty filename */
1848 SetLastError(0xdeadbeef);
1849 ret = pSearchPathA(pathA, fileA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
1850 ok(ret == 0, "Expected failure, got %d\n", ret);
1851 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1852 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1853
1854 if (!pActivateActCtx)
1855 return;
1856
1857 create_manifest_file("testdep1.manifest", manifest_dep);
1858 create_manifest_file("main.manifest", manifest_main);
1859
1860 handle = test_create("main.manifest");
1861 delete_manifest_file("testdep1.manifest");
1862 delete_manifest_file("main.manifest");
1863
1864 /* search fails without active context */
1865 ret = pSearchPathA(NULL, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1866 ok(ret == 0, "got %d\n", ret);
1867
1868 ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(path2A)/sizeof(CHAR), path2A, NULL);
1869 ok(ret && ret == strlen(path2A), "got %d\n", ret);
1870
1871 ret = pActivateActCtx(handle, &cookie);
1872 ok(ret, "failed to activate context, %u\n", GetLastError());
1873
1874 /* works when activated */
1875 ret = pSearchPathA(NULL, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1876 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1877
1878 ret = pSearchPathA(NULL, "testdep.dll", ".ext", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1879 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1880
1881 ret = pSearchPathA(NULL, "testdep", ".dll", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1882 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1883
1884 ret = pSearchPathA(NULL, "testdep", ".ext", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1885 ok(!ret, "got %d\n", ret);
1886
1887 /* name contains path */
1888 ret = pSearchPathA(NULL, testdeprelA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1889 ok(!ret, "got %d\n", ret);
1890
1891 /* fails with specified path that doesn't contain this file */
1892 ret = pSearchPathA(pathA, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1893 ok(!ret, "got %d\n", ret);
1894
1895 /* path is redirected for wellknown names too */
1896 ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1897 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1898 ok(strcmp(buffA, path2A), "got wrong path %s, %s\n", buffA, path2A);
1899
1900 ret = pDeactivateActCtx(0, cookie);
1901 ok(ret, "failed to deactivate context, %u\n", GetLastError());
1902 pReleaseActCtx(handle);
1903
1904 /* test the search path priority of the working directory */
1905 GetTempPathA(sizeof(tmpdirA), tmpdirA);
1906 ret = GetCurrentDirectoryA(MAX_PATH, curdirA);
1907 ok(ret, "failed to obtain working directory.\n");
1908 sprintf(pathA, "%s\\%s", tmpdirA, kernel32A);
1909 ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(path2A)/sizeof(CHAR), path2A, NULL);
1910 ok(ret && ret == strlen(path2A), "got %d\n", ret);
1911 bret = CopyFileA(path2A, pathA, FALSE);
1912 ok(bret != 0, "failed to copy test executable to temp directory, %u\n", GetLastError());
1913 sprintf(path3A, "%s%s%s", curdirA, curdirA[strlen(curdirA)-1] != '\\' ? "\\" : "", kernel32A);
1914 bret = CopyFileA(path2A, path3A, FALSE);
1915 ok(bret != 0, "failed to copy test executable to launch directory, %u\n", GetLastError());
1916 bret = SetCurrentDirectoryA(tmpdirA);
1917 ok(bret, "failed to change working directory\n");
1918 ret = pSearchPathA(NULL, kernel32A, ".exe", sizeof(buffA), buffA, NULL);
1919 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1920 ok(strcmp(buffA, path3A) == 0, "expected %s, got %s\n", path3A, buffA);
1921 bret = SetCurrentDirectoryA(curdirA);
1922 ok(bret, "failed to reset working directory\n");
1923 DeleteFileA(path3A);
1924 DeleteFileA(pathA);
1925 }
1926
1927 static void test_SearchPathW(void)
1928 {
1929 static const WCHAR testdeprelW[] = {'.','/','t','e','s','t','d','e','p','.','d','l','l',0};
1930 static const WCHAR testdepW[] = {'t','e','s','t','d','e','p','.','d','l','l',0};
1931 static const WCHAR testdep1W[] = {'t','e','s','t','d','e','p',0};
1932 static const WCHAR kernel32dllW[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
1933 static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2',0};
1934 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1935 static const WCHAR extW[] = {'.','e','x','t',0};
1936 static const WCHAR dllW[] = {'.','d','l','l',0};
1937 static const WCHAR fileW[] = { 0 };
1938 WCHAR pathW[MAX_PATH], buffW[MAX_PATH], path2W[MAX_PATH];
1939 WCHAR *ptrW = NULL;
1940 ULONG_PTR cookie;
1941 HANDLE handle;
1942 DWORD ret;
1943
1944 if (!pSearchPathW)
1945 {
1946 win_skip("SearchPathW isn't available\n");
1947 return;
1948 }
1949
1950 if (0)
1951 {
1952 /* NULL filename, crashes on nt4 */
1953 pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
1954 }
1955
1956 GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
1957
1958 /* empty filename */
1959 SetLastError(0xdeadbeef);
1960 ret = pSearchPathW(pathW, fileW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
1961 ok(ret == 0, "Expected failure, got %d\n", ret);
1962 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1963 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1964
1965 if (!pActivateActCtx)
1966 return;
1967
1968 create_manifest_file("testdep1.manifest", manifest_dep);
1969 create_manifest_file("main.manifest", manifest_main);
1970
1971 handle = test_create("main.manifest");
1972 delete_manifest_file("testdep1.manifest");
1973 delete_manifest_file("main.manifest");
1974
1975 /* search fails without active context */
1976 ret = pSearchPathW(NULL, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1977 ok(ret == 0, "got %d\n", ret);
1978
1979 ret = pSearchPathW(NULL, kernel32dllW, NULL, sizeof(path2W)/sizeof(WCHAR), path2W, NULL);
1980 ok(ret && ret == lstrlenW(path2W), "got %d\n", ret);
1981
1982 /* full path, name without 'dll' extension */
1983 GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
1984 ret = pSearchPathW(pathW, kernel32W, NULL, sizeof(path2W)/sizeof(WCHAR), path2W, NULL);
1985 ok(ret == 0, "got %d\n", ret);
1986
1987 GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
1988
1989 ret = pActivateActCtx(handle, &cookie);
1990 ok(ret, "failed to activate context, %u\n", GetLastError());
1991
1992 /* works when activated */
1993 ret = pSearchPathW(NULL, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1994 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1995
1996 ret = pSearchPathW(NULL, testdepW, extW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1997 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1998
1999 ret = pSearchPathW(NULL, testdep1W, dllW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
2000 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
2001
2002 ret = pSearchPathW(NULL, testdep1W, extW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
2003 ok(!ret, "got %d\n", ret);
2004
2005 /* name contains path */
2006 ret = pSearchPathW(NULL, testdeprelW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
2007 ok(!ret, "got %d\n", ret);
2008
2009 /* fails with specified path that doesn't contain this file */
2010 ret = pSearchPathW(pathW, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
2011 ok(!ret, "got %d\n", ret);
2012
2013 /* path is redirected for wellknown names too, meaning it takes precedence over normal search order */
2014 ret = pSearchPathW(NULL, kernel32dllW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
2015 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
2016 ok(lstrcmpW(buffW, path2W), "got wrong path %s, %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(path2W));
2017
2018 /* path is built using on manifest file name */
2019 ret = pSearchPathW(NULL, ole32W, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
2020 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
2021
2022 ret = pDeactivateActCtx(0, cookie);
2023 ok(ret, "failed to deactivate context, %u\n", GetLastError());
2024 pReleaseActCtx(handle);
2025 }
2026
2027 static void test_GetFullPathNameA(void)
2028 {
2029 char output[MAX_PATH], *filepart;
2030 DWORD ret;
2031 int i;
2032 UINT acp;
2033
2034 const struct
2035 {
2036 LPCSTR name;
2037 DWORD len;
2038 LPSTR buffer;
2039 LPSTR *lastpart;
2040 } invalid_parameters[] =
2041 {
2042 {NULL, 0, NULL, NULL},
2043 {NULL, MAX_PATH, NULL, NULL},
2044 {NULL, MAX_PATH, output, NULL},
2045 {NULL, MAX_PATH, output, &filepart},
2046 {"", 0, NULL, NULL},
2047 {"", MAX_PATH, NULL, NULL},
2048 {"", MAX_PATH, output, NULL},
2049 {"", MAX_PATH, output, &filepart},
2050 };
2051
2052 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
2053 {
2054 SetLastError(0xdeadbeef);
2055 strcpy(output, "deadbeef");
2056 filepart = (char *)0xdeadbeef;
2057 ret = GetFullPathNameA(invalid_parameters[i].name,
2058 invalid_parameters[i].len,
2059 invalid_parameters[i].buffer,
2060 invalid_parameters[i].lastpart);
2061 ok(!ret, "[%d] Expected GetFullPathNameA to return 0, got %u\n", i, ret);
2062 ok(!strcmp(output, "deadbeef"), "[%d] Expected the output buffer to be unchanged, got \"%s\"\n", i, output);
2063 ok(filepart == (char *)0xdeadbeef, "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
2064 ok(GetLastError() == 0xdeadbeef ||
2065 GetLastError() == ERROR_INVALID_NAME, /* Win7 */
2066 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
2067 i, GetLastError());
2068 }
2069
2070 acp = GetACP();
2071 if (acp != 932)
2072 skip("Skipping DBCS(Japanese) GetFullPathNameA test in this codepage (%d)\n", acp);
2073 else {
2074 const struct dbcs_case {
2075 const char *input;
2076 const char *expected;
2077 } testset[] = {
2078 { "c:\\a\\\x95\x5c\x97\xa0.txt", "\x95\x5c\x97\xa0.txt" },
2079 { "c:\\\x83\x8f\x83\x43\x83\x93\\wine.c", "wine.c" },
2080 { "c:\\demo\\\x97\xa0\x95\x5c", "\x97\xa0\x95\x5c" }
2081 };
2082 for (i = 0; i < sizeof(testset)/sizeof(testset[0]); i++) {
2083 ret = GetFullPathNameA(testset[i].input, sizeof(output),
2084 output, &filepart);
2085 ok(ret, "[%d] GetFullPathName error %u\n", i, GetLastError());
2086 ok(!lstrcmpA(filepart, testset[i].expected),
2087 "[%d] expected %s got %s\n", i, testset[i].expected, filepart);
2088 }
2089 }
2090 }
2091
2092 static void test_GetFullPathNameW(void)
2093 {
2094 static const WCHAR emptyW[] = {0};
2095 static const WCHAR deadbeefW[] = {'d','e','a','d','b','e','e','f',0};
2096
2097 WCHAR output[MAX_PATH], *filepart;
2098 DWORD ret;
2099 int i;
2100
2101 const struct
2102 {
2103 LPCWSTR name;
2104 DWORD len;
2105 LPWSTR buffer;
2106 LPWSTR *lastpart;
2107 int win7_expect;
2108 } invalid_parameters[] =
2109 {
2110 {NULL, 0, NULL, NULL},
2111 {NULL, 0, NULL, &filepart, 1},
2112 {NULL, MAX_PATH, NULL, NULL},
2113 {NULL, MAX_PATH, output, NULL},
2114 {NULL, MAX_PATH, output, &filepart, 1},
2115 {emptyW, 0, NULL, NULL},
2116 {emptyW, 0, NULL, &filepart, 1},
2117 {emptyW, MAX_PATH, NULL, NULL},
2118 {emptyW, MAX_PATH, output, NULL},
2119 {emptyW, MAX_PATH, output, &filepart, 1},
2120 };
2121
2122 SetLastError(0xdeadbeef);
2123 ret = GetFullPathNameW(NULL, 0, NULL, NULL);
2124 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2125 {
2126 win_skip("GetFullPathNameW is not available\n");
2127 return;
2128 }
2129
2130 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
2131 {
2132 SetLastError(0xdeadbeef);
2133 lstrcpyW(output, deadbeefW);
2134 filepart = (WCHAR *)0xdeadbeef;
2135 ret = GetFullPathNameW(invalid_parameters[i].name,
2136 invalid_parameters[i].len,
2137 invalid_parameters[i].buffer,
2138 invalid_parameters[i].lastpart);
2139 ok(!ret, "[%d] Expected GetFullPathNameW to return 0, got %u\n", i, ret);
2140 ok(!lstrcmpW(output, deadbeefW), "[%d] Expected the output buffer to be unchanged, got %s\n", i, wine_dbgstr_w(output));
2141 ok(filepart == (WCHAR *)0xdeadbeef ||
2142 (invalid_parameters[i].win7_expect && filepart == NULL),
2143 "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
2144 ok(GetLastError() == 0xdeadbeef ||
2145 GetLastError() == ERROR_INVALID_NAME, /* Win7 */
2146 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
2147 i, GetLastError());
2148 }
2149 }
2150
2151 static void init_pointers(void)
2152 {
2153 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
2154
2155 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f))
2156 MAKEFUNC(GetLongPathNameA);
2157 MAKEFUNC(GetLongPathNameW);
2158 MAKEFUNC(NeedCurrentDirectoryForExePathA);
2159 MAKEFUNC(NeedCurrentDirectoryForExePathW);
2160 MAKEFUNC(SearchPathA);
2161 MAKEFUNC(SearchPathW);
2162 MAKEFUNC(SetSearchPathMode);
2163 MAKEFUNC(ActivateActCtx);
2164 MAKEFUNC(CreateActCtxW);
2165 MAKEFUNC(DeactivateActCtx);
2166 MAKEFUNC(GetCurrentActCtx);
2167 MAKEFUNC(ReleaseActCtx);
2168 MAKEFUNC(CheckNameLegalDOS8Dot3W);
2169 MAKEFUNC(CheckNameLegalDOS8Dot3A);
2170 #undef MAKEFUNC
2171 }
2172
2173 static void test_relative_path(void)
2174 {
2175 char path[MAX_PATH], buf[MAX_PATH];
2176 HANDLE file;
2177 int ret;
2178 WCHAR curdir[MAX_PATH];
2179
2180 if (!pGetLongPathNameA) return;
2181
2182 GetCurrentDirectoryW(MAX_PATH, curdir);
2183 GetTempPathA(MAX_PATH, path);
2184 ret = SetCurrentDirectoryA(path);
2185 ok(ret, "SetCurrentDirectory error %d\n", GetLastError());
2186
2187 ret = CreateDirectoryA("foo", NULL);
2188 ok(ret, "CreateDirectory error %d\n", GetLastError());
2189 file = CreateFileA("foo\\file", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2190 ok(file != INVALID_HANDLE_VALUE, "failed to create temp file\n");
2191 CloseHandle(file);
2192 ret = CreateDirectoryA("bar", NULL);
2193 ok(ret, "CreateDirectory error %d\n", GetLastError());
2194 ret = SetCurrentDirectoryA("bar");
2195 ok(ret, "SetCurrentDirectory error %d\n", GetLastError());
2196
2197 ret = GetFileAttributesA("..\\foo\\file");
2198 ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributes error %d\n", GetLastError());
2199
2200 strcpy(buf, "deadbeef");
2201 ret = pGetLongPathNameA(".", buf, MAX_PATH);
2202 ok(ret, "GetLongPathName error %d\n", GetLastError());
2203 ok(!strcmp(buf, "."), "expected ., got %s\n", buf);
2204 strcpy(buf, "deadbeef");
2205 ret = GetShortPathNameA(".", buf, MAX_PATH);
2206 ok(ret, "GetShortPathName error %d\n", GetLastError());
2207 ok(!strcmp(buf, "."), "expected ., got %s\n", buf);
2208
2209 strcpy(buf, "deadbeef");
2210 ret = pGetLongPathNameA("..", buf, MAX_PATH);
2211 ok(ret, "GetLongPathName error %d\n", GetLastError());
2212 ok(!strcmp(buf, ".."), "expected .., got %s\n", buf);
2213 strcpy(buf, "deadbeef");
2214 ret = GetShortPathNameA("..", buf, MAX_PATH);
2215 ok(ret, "GetShortPathName error %d\n", GetLastError());
2216 ok(!strcmp(buf, ".."), "expected .., got %s\n", buf);
2217
2218 strcpy(buf, "deadbeef");
2219 ret = pGetLongPathNameA("..\\foo\\file", buf, MAX_PATH);
2220 ok(ret, "GetLongPathName error %d\n", GetLastError());
2221 ok(!strcmp(buf, "..\\foo\\file"), "expected ..\\foo\\file, got %s\n", buf);
2222 strcpy(buf, "deadbeef");
2223 ret = GetShortPathNameA("..\\foo\\file", buf, MAX_PATH);
2224 ok(ret, "GetShortPathName error %d\n", GetLastError());
2225 ok(!strcmp(buf, "..\\foo\\file"), "expected ..\\foo\\file, got %s\n", buf);
2226
2227 strcpy(buf, "deadbeef");
2228 ret = pGetLongPathNameA(".\\..\\foo\\file", buf, MAX_PATH);
2229 ok(ret, "GetLongPathName error %d\n", GetLastError());
2230 ok(!strcmp(buf, ".\\..\\foo\\file"), "expected .\\..\\foo\\file, got %s\n", buf);
2231 strcpy(buf, "deadbeef");
2232 ret = GetShortPathNameA(".\\..\\foo\\file", buf, MAX_PATH);
2233 ok(ret, "GetShortPathName error %d\n", GetLastError());
2234 ok(!strcmp(buf, ".\\..\\foo\\file"), "expected .\\..\\foo\\file, got %s\n", buf);
2235
2236 /* test double delimiters */
2237 strcpy(buf, "deadbeef");
2238 ret = pGetLongPathNameA("..\\\\foo\\file", buf, MAX_PATH);
2239 ok(ret, "GetLongPathName error %d\n", GetLastError());
2240 ok(!strcmp(buf, "..\\\\foo\\file"), "expected ..\\\\foo\\file, got %s\n", buf);
2241 strcpy(buf, "deadbeef");
2242 ret = GetShortPathNameA("..\\\\foo\\file", buf, MAX_PATH);
2243 ok(ret, "GetShortPathName error %d\n", GetLastError());
2244 ok(!strcmp(buf, "..\\\\foo\\file"), "expected ..\\\\foo\\file, got %s\n", buf);
2245
2246 SetCurrentDirectoryA("..");
2247 DeleteFileA("foo\\file");
2248 RemoveDirectoryA("foo");
2249 RemoveDirectoryA("bar");
2250 SetCurrentDirectoryW(curdir);
2251 }
2252
2253 static void test_CheckNameLegalDOS8Dot3(void)
2254 {
2255 static const WCHAR has_driveW[] = {'C',':','\\','a','.','t','x','t',0};
2256 static const WCHAR has_pathW[] = {'b','\\','a','.','t','x','t',0};
2257 static const WCHAR too_longW[] = {'a','l','o','n','g','f','i','l','e','n','a','m','e','.','t','x','t',0};
2258 static const WCHAR twodotsW[] = {'t','e','s','t','.','e','s','t','.','t','x','t',0};
2259 static const WCHAR longextW[] = {'t','e','s','t','.','t','x','t','t','x','t',0};
2260 static const WCHAR emptyW[] = {0};
2261 static const WCHAR funnycharsW[] = {'!','#','$','%','&','\'','(',')','.','-','@','^',0};
2262 static const WCHAR length8W[] = {'t','e','s','t','t','e','s','t','.','t','x','t',0};
2263 static const WCHAR length1W[] = {'t',0};
2264 static const WCHAR withspaceW[] = {'t','e','s','t',' ','e','s','t','.','t','x','t',0};
2265
2266 static const struct {
2267 const WCHAR *name;
2268 BOOL should_be_legal, has_space;
2269 } cases[] = {
2270 {has_driveW, FALSE, FALSE},
2271 {has_pathW, FALSE, FALSE},
2272 {too_longW, FALSE, FALSE},
2273 {twodotsW, FALSE, FALSE},
2274 {longextW, FALSE, FALSE},
2275 {emptyW, TRUE /* ! */, FALSE},
2276 {funnycharsW, TRUE, FALSE},
2277 {length8W, TRUE, FALSE},
2278 {length1W, TRUE, FALSE},
2279 {withspaceW, TRUE, TRUE},
2280 };
2281
2282 BOOL br, is_legal, has_space;
2283 char astr[64];
2284 DWORD i;
2285
2286 if(!pCheckNameLegalDOS8Dot3W){
2287 win_skip("Missing CheckNameLegalDOS8Dot3, skipping tests\n");
2288 return;
2289 }
2290
2291 br = pCheckNameLegalDOS8Dot3W(NULL, NULL, 0, NULL, &is_legal);
2292 ok(br == FALSE, "CheckNameLegalDOS8Dot3W should have failed\n");
2293
2294 br = pCheckNameLegalDOS8Dot3A(NULL, NULL, 0, NULL, &is_legal);
2295 ok(br == FALSE, "CheckNameLegalDOS8Dot3A should have failed\n");
2296
2297 br = pCheckNameLegalDOS8Dot3W(length8W, NULL, 0, NULL, NULL);
2298 ok(br == FALSE, "CheckNameLegalDOS8Dot3W should have failed\n");
2299
2300 br = pCheckNameLegalDOS8Dot3A("testtest.txt", NULL, 0, NULL, NULL);
2301 ok(br == FALSE, "CheckNameLegalDOS8Dot3A should have failed\n");
2302
2303 for(i = 0; i < sizeof(cases)/sizeof(*cases); ++i){
2304 br = pCheckNameLegalDOS8Dot3W(cases[i].name, NULL, 0, &has_space, &is_legal);
2305 ok(br == TRUE, "CheckNameLegalDOS8Dot3W failed for %s\n", wine_dbgstr_w(cases[i].name));
2306 ok(is_legal == cases[i].should_be_legal, "Got wrong legality for %s\n", wine_dbgstr_w(cases[i].name));
2307 if(is_legal)
2308 ok(has_space == cases[i].has_space, "Got wrong space for %s\n", wine_dbgstr_w(cases[i].name));
2309
2310 WideCharToMultiByte(CP_ACP, 0, cases[i].name, -1, astr, sizeof(astr), NULL, NULL);
2311
2312 br = pCheckNameLegalDOS8Dot3A(astr, NULL, 0, &has_space, &is_legal);
2313 ok(br == TRUE, "CheckNameLegalDOS8Dot3W failed for %s\n", astr);
2314 ok(is_legal == cases[i].should_be_legal, "Got wrong legality for %s\n", astr);
2315 if(is_legal)
2316 ok(has_space == cases[i].has_space, "Got wrong space for %s\n", wine_dbgstr_w(cases[i].name));
2317 }
2318 }
2319
2320 static void test_SetSearchPathMode(void)
2321 {
2322 BOOL ret;
2323 char orig[MAX_PATH], buf[MAX_PATH], dir[MAX_PATH], expect[MAX_PATH];
2324 HANDLE handle;
2325
2326 if (!pSetSearchPathMode)
2327 {
2328 win_skip( "SetSearchPathMode isn't available\n" );
2329 return;
2330 }
2331 GetCurrentDirectoryA( MAX_PATH, orig );
2332 GetTempPathA( MAX_PATH, buf );
2333 GetTempFileNameA( buf, "path", 0, dir );
2334 DeleteFileA( dir );
2335 CreateDirectoryA( dir, NULL );
2336 ret = SetCurrentDirectoryA( dir );
2337 ok( ret, "failed to switch to %s\n", dir );
2338 if (!ret)
2339 {
2340 RemoveDirectoryA( dir );
2341 return;
2342 }
2343
2344 handle = CreateFileA( "kernel32.dll", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2345 CloseHandle( handle );
2346
2347 SetLastError( 0xdeadbeef );
2348 ret = pSetSearchPathMode( 0 );
2349 ok( !ret, "SetSearchPathMode succeeded\n" );
2350 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2351
2352 SetLastError( 0xdeadbeef );
2353 ret = pSetSearchPathMode( 0x80 );
2354 ok( !ret, "SetSearchPathMode succeeded\n" );
2355 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2356
2357 SetLastError( 0xdeadbeef );
2358 ret = pSetSearchPathMode( BASE_SEARCH_PATH_PERMANENT );
2359 ok( !ret, "SetSearchPathMode succeeded\n" );
2360 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2361
2362 SetLastError( 0xdeadbeef );
2363 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL );
2364 ok( ret, "SearchPathA failed err %u\n", GetLastError() );
2365 GetCurrentDirectoryA( MAX_PATH, expect );
2366 strcat( expect, "\\kernel32.dll" );
2367 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect );
2368
2369 SetLastError( 0xdeadbeef );
2370 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE );
2371 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() );
2372
2373 SetLastError( 0xdeadbeef );
2374 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL );
2375 ok( ret, "SearchPathA failed err %u\n", GetLastError() );
2376 GetSystemDirectoryA( expect, MAX_PATH );
2377 strcat( expect, "\\kernel32.dll" );
2378 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect );
2379
2380 SetLastError( 0xdeadbeef );
2381 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE );
2382 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() );
2383
2384 SetLastError( 0xdeadbeef );
2385 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL );
2386 ok( ret, "SearchPathA failed err %u\n", GetLastError() );
2387 GetCurrentDirectoryA( MAX_PATH, expect );
2388 strcat( expect, "\\kernel32.dll" );
2389 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect );
2390
2391 SetLastError( 0xdeadbeef );
2392 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
2393 ok( !ret, "SetSearchPathMode succeeded\n" );
2394 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2395
2396 SetLastError( 0xdeadbeef );
2397 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
2398 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() );
2399
2400 SetLastError( 0xdeadbeef );
2401 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE );
2402 ok( !ret, "SetSearchPathMode succeeded\n" );
2403 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
2404
2405 SetLastError( 0xdeadbeef );
2406 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE );
2407 ok( !ret, "SetSearchPathMode succeeded\n" );
2408 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
2409
2410 SetLastError( 0xdeadbeef );
2411 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
2412 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() );
2413
2414 SetLastError( 0xdeadbeef );
2415 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL );
2416 ok( ret, "SearchPathA failed err %u\n", GetLastError() );
2417 GetSystemDirectoryA( expect, MAX_PATH );
2418 strcat( expect, "\\kernel32.dll" );
2419 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect );
2420
2421 DeleteFileA( "kernel32.dll" );
2422 SetCurrentDirectoryA( orig );
2423 RemoveDirectoryA( dir );
2424 }
2425
2426 START_TEST(path)
2427 {
2428 CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
2429
2430 init_pointers();
2431
2432 /* Report only once */
2433 if (!pGetLongPathNameA)
2434 win_skip("GetLongPathNameA is not available\n");
2435 if (!pGetLongPathNameW)
2436 win_skip("GetLongPathNameW is not available\n");
2437 if (!pActivateActCtx)
2438 win_skip("Activation contexts not supported, some tests will be skipped\n");
2439
2440 test_relative_path();
2441 test_InitPathA(curdir, &curDrive, &otherDrive);
2442 test_CurrentDirectoryA(origdir,curdir);
2443 test_PathNameA(curdir, curDrive, otherDrive);
2444 test_CleanupPathA(origdir,curdir);
2445 test_GetTempPath();
2446 test_GetLongPathNameA();
2447 test_GetLongPathNameW();
2448 test_GetShortPathNameW();
2449 test_GetSystemDirectory();
2450 test_GetWindowsDirectory();
2451 test_NeedCurrentDirectoryForExePathA();
2452 test_NeedCurrentDirectoryForExePathW();
2453 test_drive_letter_case();
2454 test_SearchPathA();
2455 test_SearchPathW();
2456 test_GetFullPathNameA();
2457 test_GetFullPathNameW();
2458 test_CheckNameLegalDOS8Dot3();
2459 test_SetSearchPathMode();
2460 }