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