path.c 39.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Unit test suite for Get*PathNamesA and (Get|Set)CurrentDirectoryA.
 *
 * Copyright 2002 Geoffrey Hausheer
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

21
#include <stdarg.h>
22 23
#include <stdio.h>
#include "wine/test.h"
24
#include "windef.h"
25 26 27
#include "winbase.h"
#include "winuser.h"
#include "winerror.h"
28
#include "winnls.h"
29 30 31 32 33 34 35 36

#define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')

#define LONGFILE "Long File test.path"
#define SHORTFILE "pathtest.pth"
#define SHORTDIR "shortdir"
#define LONGDIR "Long Directory"
#define NONFILE_SHORT "noexist.pth"
37
#define NONFILE_LONG "NonExistent File"
38
#define NONDIR_SHORT "notadir"
39
#define NONDIR_LONG "NonExistent Directory"
40

41 42
#define NOT_A_VALID_DRIVE '@'

43 44 45 46
/* the following characters don't work well with GetFullPathNameA
   in Win98.  I don't know if this is a FAT thing, or if it is an OS thing
   but I don't test these characters now.
   NOTE: Win2k allows GetFullPathNameA to work with them though
47
      |<>"
48
*/
49 50
static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
static const CHAR is_char_ok[] ="11111110111111111011";
51 52

static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

/* a structure to deal with wine todos somewhat cleanly */
typedef struct {
  DWORD shortlen;
  DWORD shorterror;
  DWORD s2llen;
  DWORD s2lerror;
  DWORD longlen;
  DWORD longerror;
} SLpassfail;

/* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
/* NOTE: the passfail structure is used to allow cutomizeable todo checking
         for wine.  It is not very pretty, but it sure beats duplicating this
         function lots of times
*/
69 70 71
static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
                         CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
{
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
  CHAR tmpstr[MAX_PATH],
       fullpath[MAX_PATH],      /*full path to the file (not short/long) */
       subpath[MAX_PATH],       /*relative path to the file */
       fullpathshort[MAX_PATH], /*absolue path to the file (short format) */
       fullpathlong[MAX_PATH],  /*absolute path to the file (long format) */
       curdirshort[MAX_PATH],   /*absolute path to the current dir (short) */
       curdirlong[MAX_PATH];    /*absolute path to the current dir (long) */
  LPSTR strptr;                 /*ptr to the filename portion of the path */
  DWORD len;
/* if passfail is NULL, we can perform all checks within this function,
   otherwise, we will return the relevant data in the passfail struct, so
   we must initialize it first
*/
  if(passfail!=NULL) {
    passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
    passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
  }
/* GetLongPathNameA is only supported on Win2k+ and Win98+ */
90 91
  if(pGetLongPathNameA) {
    ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
92
       "%s: GetLongPathNameA failed\n",errstr);
93 94
/*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
    ok(! HAS_TRAIL_SLASH_A(curdirlong),
95
       "%s: GetLongPathNameA should not have a trailing \\\n",errstr);
96 97
  }
  ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
98
     "%s: GetShortPathNameA failed\n",errstr);
99 100
/*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
  ok(! HAS_TRAIL_SLASH_A(curdirshort),
101
     "%s: GetShortPathNameA should not have a trailing \\\n",errstr);
102 103 104 105 106 107 108 109 110 111 112
/* build relative and absolute paths from inputs */
  if(lstrlenA(subdir)) {
    sprintf(subpath,"%s\\%s",subdir,filename);
  } else {
    lstrcpyA(subpath,filename);
  }
  sprintf(fullpath,"%s\\%s",curdir,subpath);
  sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
  sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
/* Test GetFullPathNameA functionality */
  len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
113
  ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
114
  if(HAS_TRAIL_SLASH_A(subpath)) {
115
    ok(strptr==NULL,
116
       "%s: GetFullPathNameA should not return a filename ptr\n",errstr);
117
    ok(lstrcmpiA(fullpath,tmpstr)==0,
118
       "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
119
       errstr,tmpstr,fullpath);
120
  } else {
121
    ok(lstrcmpiA(strptr,filename)==0,
122
       "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
123 124
       errstr,strptr,filename);
    ok(lstrcmpiA(fullpath,tmpstr)==0,
125
       "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
126 127 128 129 130 131
       errstr,tmpstr,fullpath);
  }
/* Test GetShortPathNameA functionality */
  SetLastError(0);
  len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
  if(passfail==NULL) {
132
    ok(len, "%s: GetShortPathNameA failed\n",errstr);
133 134 135 136
  } else {
    passfail->shortlen=len;
    passfail->shorterror=GetLastError();
  }
137
/* Test GetLongPathNameA functionality
138 139
   We test both conversion from GetFullPathNameA and from GetShortPathNameA
*/
140
  if(pGetLongPathNameA) {
141
    if(len!=0) {
142
      SetLastError(0);
143
      len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
144
      if(passfail==NULL) {
145
        ok(len,
146
          "%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
147
        ok(lstrcmpiA(fullpathlong,tmpstr)==0,
148
           "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
149 150 151 152 153 154 155
           errstr,tmpstr,fullpathlong);
      } else {
        passfail->s2llen=len;
        passfail->s2lerror=GetLastError();
      }
    }
    SetLastError(0);
156
    len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
157
    if(passfail==NULL) {
158
      ok(len, "%s: GetLongPathNameA failed\n",errstr);
159
      if(HAS_TRAIL_SLASH_A(fullpath)) {
160
        ok(lstrcmpiA(fullpathlong,tmpstr)==0,
161
           "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
162 163 164
           errstr,tmpstr,fullpathlong);
      } else {
        ok(lstrcmpiA(fullpathlong,tmpstr)==0,
165
          "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
166 167 168 169 170 171 172 173 174 175 176
          errstr,tmpstr,fullpathlong);
      }
    } else {
      passfail->longlen=len;
      passfail->longerror=GetLastError();
    }
  }
}

/* split path into leading directory, and 8.3 filename */
static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
177 178 179
  int done,error;
  int ext,fil;
  int len,i;
180 181
  len=lstrlenA(path);
  ext=len; fil=len; done=0; error=0;
Francois Gouget's avatar
Francois Gouget committed
182
/* walk backwards over path looking for '.' or '\\' separators */
183
  for(i=len-1;(i>=0) && (!done);i--) {
184
    if(path[i]=='.')
185 186 187 188 189 190 191 192 193 194 195
      if(ext!=len) error=1; else ext=i;
    else if(path[i]=='\\') {
      if(i==len-1) {
        error=1;
      } else {
        fil=i;
        done=1;
      }
    }
  }
/* Check that we didn't find a trailing '\\' or multiple '.' */
196
  ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
197
/* Separate dir, root, and extension */
198 199 200 201 202 203 204 205 206 207
  if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
  if(fil!=len) {
    lstrcpynA(eight,path+fil+1,ext-fil);
    lstrcpynA(dir,path,fil+1);
  } else {
    lstrcpynA(eight,path,ext+1);
    lstrcpyA(dir,"");
  }
/* Validate that root and extension really are 8.3 */
  ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
208
     "GetShortPathNAmeA did not return an 8.3 path\n");
209 210 211
}

/* Check that GetShortPathNameA returns a valid 8.3 path */
212 213
static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
                              const CHAR *ext,const CHAR *errstr) {
214 215 216 217
  CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];

  test_SplitShortPathA(teststr,dir,eight,three);
  ok(lstrcmpiA(dir,goodstr)==0,
218
     "GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
219
  ok(lstrcmpiA(three,ext)==0,
220
     "GetShortPathNameA returned '%s' with incorrect extension\n",three);
221 222 223 224 225
}

/* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
   characters in the filename.
     'valid' indicates whether this would be an allowed filename
226
     'todo' indicates that wine doesn't get this right yet.
227
   NOTE: We always call this routine with a nonexistent filename, so
228 229 230
         Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
         should.
*/
231
static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
232
{
233
  CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
234 235 236 237
  SLpassfail passfail;

  test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
  if(valid) {
238
    sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
239
      ok((passfail.shortlen==0 &&
240
          (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
241
         (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
242
         "%s: GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
243
         errstr,passfail.shortlen,passfail.shorterror,tmpstr);
244
  } else {
245
      ok(passfail.shortlen==0 &&
246
         (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
247
         "%s: GetShortPathA should have failed len=%ld, error=%ld\n",
248
         errstr,passfail.shortlen,passfail.shorterror);
249
  }
250
  if(pGetLongPathNameA) {
251
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
252 253
    if(valid) {
      ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
254
         "%s: GetLongPathA returned %ld and not %d\n",
255 256 257 258
         errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
    } else {
      ok(passfail.longerror==ERROR_INVALID_NAME ||
         passfail.longerror==ERROR_FILE_NOT_FOUND,
259
         "%s: GetLongPathA returned %ld and not %d or %d'\n",
260 261 262 263 264 265 266
         errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
    }
  }
}

/* Routine to test that SetCurrentDirectory behaves as expected. */
static void test_setdir(CHAR *olddir,CHAR *newdir,
267
                        CHAR *cmprstr, INT pass, const CHAR *errstr)
268 269 270 271 272 273 274 275 276 277
{
  CHAR tmppath[MAX_PATH], *dirptr;
  DWORD val,len,chklen;

  val=SetCurrentDirectoryA(newdir);
  len=GetCurrentDirectoryA(MAX_PATH,tmppath);
/* if 'pass' then the SetDirectoryA was supposed to pass */
  if(pass) {
    dirptr=(cmprstr==NULL) ? newdir : cmprstr;
    chklen=lstrlenA(dirptr);
278
    ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
279
    ok(len==chklen,
280
       "%s: SetCurrentDirectory did not change the directory, though it passed\n",
281 282
       errstr);
    ok(lstrcmpiA(dirptr,tmppath)==0,
283
       "%s: SetCurrentDirectory did not change the directory, though it passed\n",
284 285
       errstr);
    ok(SetCurrentDirectoryA(olddir),
286
       "%s: Couldn't set directory to it's original value\n",errstr);
287 288 289 290
  } else {
/* else thest that it fails correctly */
    chklen=lstrlenA(olddir);
    ok(val==0,
291
       "%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
292
    ok(len==chklen,
293
       "%s: SetCurrentDirectory changed the directory, though it failed\n",
294 295
       errstr);
    ok(lstrcmpiA(olddir,tmppath)==0,
296
       "%s: SetCurrentDirectory changed the directory, though it failed\n",
297 298 299
       errstr);
  }
}
300
static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
301 302 303 304
{
  CHAR tmppath[MAX_PATH], /*path to TEMP */
       tmpstr[MAX_PATH],
       tmpstr1[MAX_PATH];
305
  DWORD len,len1,drives;
306 307
  INT id;
  HANDLE hndl;
308
  BOOL bRes;
309

310 311 312 313 314 315 316 317
  *curDrive = *otherDrive = NOT_A_VALID_DRIVE;

/* Get the current drive letter */
  if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
    *curDrive = tmpstr[0];
  else
    trace( "Unable to discover current drive, some tests will not be conducted.\n");

318 319
/* Test GetTempPathA */
  len=GetTempPathA(MAX_PATH,tmppath);
320
  ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
321
  ok(HAS_TRAIL_SLASH_A(tmppath),
322
     "GetTempPathA returned a path that did not end in '\\'\n");
323 324 325
  lstrcpyA(tmpstr,"aaaaaaaa");
  len1=GetTempPathA(len,tmpstr);
  ok(len1==len+1,
326
     "GetTempPathA should return string length %ld instead of %ld\n",len+1,len1);
327

328
/* Test GetTmpFileNameA
329 330 331 332
   The only test we do here is whether GetTempFileNameA passes or not.
   We do not thoroughly test this function yet (specifically, whether
   it behaves correctly when 'unique' is non zero)
*/
333
  ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
334 335 336 337
  sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
  sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
  ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
     lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
338
     "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
339
     newdir,tmpstr,tmpstr1,id);
340

341 342 343 344 345 346 347 348 349
  ok((id=GetTempFileNameA(tmppath,NULL,0,newdir)),"GetTempFileNameA failed\n");
  sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
  sprintf(tmpstr1,"%x.tmp",id & 0xffff);
  ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
     lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
     "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
     newdir,tmpstr,tmpstr1,id);


350 351 352 353 354 355 356 357 358
/* Find first valid drive letter that is neither newdir[0] nor curDrive */
  drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
  if( *curDrive != NOT_A_VALID_DRIVE)
    drives &= ~(1<<(*curDrive-'A'));
  if( drives)
    for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
  else
    trace( "Could not find alternative drive, some tests will not be conducted.\n");

359 360 361 362 363 364
/* Do some CreateDirectoryA tests */
/* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
   really understand how they work.
   More formal tests should be done along with CreateFile tests
*/
  ok(CreateDirectoryA(newdir,NULL)==0,
365 366 367
     "CreateDirectoryA succeeded even though a file of the same name exists\n");
  ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
  ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
368 369 370 371
/* Create some files to test other functions.  Note, we will test CreateFileA
   at some later point
*/
  sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
372
  ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
373
  sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
374
  ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
375
  bRes = CreateDirectoryA("c:",NULL);
376 377
  ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  || 
               GetLastError() == ERROR_ALREADY_EXISTS),
378 379
     "CreateDirectoryA(\"c:\" should have failed (%ld)\n", GetLastError());
  bRes = CreateDirectoryA("c:\\",NULL);
380 381
  ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  ||
               GetLastError() == ERROR_ALREADY_EXISTS),
382
     "CreateDirectoryA(\"c:\\\" should have failed (%ld)\n", GetLastError());
383 384
  sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
  hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
385
                   CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
386 387
  ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
  ok(CloseHandle(hndl),"CloseHandle failed\n");
388 389
  sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
  hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
390
                   CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
391 392
  ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
  ok(CloseHandle(hndl),"CloseHandle failed\n");
393 394
  sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
  hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
395
                   CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
396 397
  ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
  ok(CloseHandle(hndl),"CloseHandle failed\n");
398 399
  sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
  hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
400
                   CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
401 402
  ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
  ok(CloseHandle(hndl),"CloseHandle failed\n");
403 404 405 406 407 408 409 410 411 412 413
}

/* Test GetCurrentDirectory & SetCurrentDirectory */
static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
{
  CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
  DWORD len,len1;
/* Save the original directory, so that we can return to it at the end
   of the test
*/
  len=GetCurrentDirectoryA(MAX_PATH,origdir);
414
  ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
415 416 417 418 419
/* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
   buffer size is too small to hold the current directory
*/
  lstrcpyA(tmpstr,"aaaaaaa");
  len1=GetCurrentDirectoryA(len,tmpstr);
420
  ok(len1==len+1, "GetCurrentDirectoryA returned %ld instead of %ld\n",len1,len+1);
421
  ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
422
     "GetCurrentDirectoryA should not have modified the buffer\n");
423
/* SetCurrentDirectoryA shouldn't care whether the string has a
424 425 426 427 428
   trailing '\\' or not
*/
  sprintf(tmpstr,"%s\\",newdir);
  test_setdir(origdir,tmpstr,newdir,1,"check 1");
  test_setdir(origdir,newdir,NULL,1,"check 2");
429
/* Set the directory to the working area.  We just tested that this works,
430 431 432
   so why check it again.
*/
  SetCurrentDirectoryA(newdir);
433
/* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
434 435
  sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
  test_setdir(newdir,tmpstr,NULL,0,"check 3");
436
/* Check that SetCurrentDirectory fails for a nonexistent lond directory */
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
  sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
  test_setdir(newdir,tmpstr,NULL,0,"check 4");
/* Check that SetCurrentDirectory passes with a long directory */
  sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
  test_setdir(newdir,tmpstr,NULL,1,"check 5");
/* Check that SetCurrentDirectory passes with a short relative directory */
  sprintf(tmpstr,"%s",SHORTDIR);
  sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
  test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
/* starting with a '.' */
  sprintf(tmpstr,".\\%s",SHORTDIR);
  test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
/* Check that SetCurrentDirectory passes with a short relative directory */
  sprintf(tmpstr,"%s",LONGDIR);
  sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
  test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
/* starting with a '.' */
  sprintf(tmpstr,".\\%s",LONGDIR);
  test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
}

/* Cleanup the mess we made while executing these tests */
static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
{
  CHAR tmpstr[MAX_PATH];
  sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
463
  ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
464
  sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
465
  ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
466
  sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
467
  ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
468
  sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
469
  ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
470
  sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
471
  ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
472
  sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
473 474 475
  ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
  ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
  ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
476 477 478
}

/* This routine will test Get(Full|Short|Long)PathNameA */
479
static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
480 481 482
{
  CHAR curdir_short[MAX_PATH],
       longdir_short[MAX_PATH];
483
  CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
484
  LPSTR strptr;                 /*ptr to the filename portion of the path */
485 486 487 488 489 490 491
  DWORD len;
  INT i;
  CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
  SLpassfail passfail;

/* Get the short form of the current directory */
  ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
492
     "GetShortPathNameA failed\n");
493
  ok(!HAS_TRAIL_SLASH_A(curdir_short),
494
     "GetShortPathNameA should not have a trailing \\\n");
495 496 497
/* Get the short form of the absolute-path to LONGDIR */
  sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
  ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
498
     "GetShortPathNameA failed\n");
499
  ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
500
     "GetShortPathNameA should not have a trailing \\\n");
501

502
  if (pGetLongPathNameA) {
503
    DWORD rc1,rc2;
504
    sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
505 506 507
    rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
    rc2=(*pGetLongPathNameA)(curdir,NULL,0);
    ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
508
       "GetLongPathNameA: wrong return code, %ld instead of %d\n",
509
       rc1, strlen(tmpstr)+1);
510

511 512 513
    sprintf(dir,"%c:",curDrive);
    rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
    ok(strcmp(dir,tmpstr)==0,
514
       "GetLongPathNameA: returned '%s' instead of '%s' (rc=%ld)\n",
515
       tmpstr,dir,rc1);
516 517
  }

518 519 520 521 522
/* Check the cases where both file and directory exist first */
/* Start with a 8.3 directory, 8.3 filename */
  test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
  sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
  ok(lstrcmpiA(tmpstr,tmpstr1)==0,
523
     "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
524 525 526 527 528 529 530 531
/* Now try a 8.3 directory, long file name */
  test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
  sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
  test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
/* Next is a long directory, 8.3 file */
  test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
  sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
  ok(lstrcmpiA(tmpstr,tmpstr1)==0,
532
     "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
533 534 535 536
/*Lastly a long directory, long file */
  test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
  test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");

537
/* Now check all of the invalid file w/ valid directory combinations */
538 539
/* Start with a 8.3 directory, 8.3 filename */
  test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
540 541 542 543 544
  sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
  ok((passfail.shortlen==0 &&
      (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
       passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
     (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
545
     "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
546
     passfail.shortlen,passfail.shorterror,tmpstr);
547
  if(pGetLongPathNameA) {
548
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
549
    ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
550
       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
551 552 553
  }
/* Now try a 8.3 directory, long file name */
  test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
554
  ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
555
  ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
556 557
     passfail.shorterror==ERROR_FILE_NOT_FOUND ||
     !passfail.shorterror,
558
     "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
559
  if(pGetLongPathNameA) {
560
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
561
    ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
562
       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
563 564 565
  }
/* Next is a long directory, 8.3 file */
  test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
566 567 568 569 570 571 572
  sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
  GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
  strcat(tmpstr1,"\\" NONFILE_SHORT);
  ok((passfail.shortlen==0 &&
      (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
       passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
     (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
573
     "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
574
     passfail.shortlen,passfail.shorterror,tmpstr);
575
  if(pGetLongPathNameA) {
576
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
577
    ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
578
      "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
579 580 581
  }
/*Lastly a long directory, long file */
  test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
582
  ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
583
  ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
584 585
     passfail.shorterror==ERROR_FILE_NOT_FOUND ||
     !passfail.shorterror,
586
     "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
587
  if(pGetLongPathNameA) {
588
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
589
    ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
590
       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
591 592 593 594
  }
/* Now try again with directories that don't exist */
/* 8.3 directory, 8.3 filename */
  test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
595 596 597 598 599
  sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
  ok((passfail.shortlen==0 &&
      (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
       passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
     (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
600
     "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
601
     passfail.shortlen,passfail.shorterror,tmpstr);
602
  if(pGetLongPathNameA) {
603
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
604 605
    ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
       passfail.longerror==ERROR_FILE_NOT_FOUND,
606
       "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
607 608 609 610
       passfail.longerror);
  }
/* Now try a 8.3 directory, long file name */
  test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
611
  ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
612
  ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
613 614
     passfail.shorterror==ERROR_FILE_NOT_FOUND ||
     !passfail.shorterror,
615
     "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
616
      passfail.shorterror);
617
  if(pGetLongPathNameA) {
618
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
619 620
    ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
       passfail.longerror==ERROR_FILE_NOT_FOUND,
621
       "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
622 623 624 625
       passfail.longerror);
  }
/* Next is a long directory, 8.3 file */
  test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
626
  ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
627
  ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
628 629
     passfail.shorterror==ERROR_FILE_NOT_FOUND ||
     !passfail.shorterror,
630
     "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
631
      passfail.shorterror);
632
  if(pGetLongPathNameA) {
633
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
634 635
    ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
       passfail.longerror==ERROR_FILE_NOT_FOUND,
636
       "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
637 638 639 640
       passfail.longerror);
  }
/*Lastly a long directory, long file */
  test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
641
  ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
642
  ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
643 644
     passfail.shorterror==ERROR_FILE_NOT_FOUND ||
     !passfail.shorterror,
645
     "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
646
      passfail.shorterror);
647
  if(pGetLongPathNameA) {
648
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
649 650
    ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
       passfail.longerror==ERROR_FILE_NOT_FOUND,
651
       "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
652 653 654 655 656 657 658 659
       passfail.longerror);
  }
/* Next try directories ending with '\\' */
/* Existing Directories */
  sprintf(tmpstr,"%s\\",SHORTDIR);
  test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
  sprintf(tmpstr,"%s\\",LONGDIR);
  test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
660
/* Nonexistent directories */
661 662
  sprintf(tmpstr,"%s\\",NONDIR_SHORT);
  test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
663
  sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
664 665 666 667
  ok((passfail.shortlen==0 &&
      (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
       passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
     (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
668
     "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
669
     passfail.shortlen,passfail.shorterror,tmpstr);
670
  if(pGetLongPathNameA) {
671
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
672
    ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
673
       "GetLongPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
674 675 676 677
       passfail.longerror);
  }
  sprintf(tmpstr,"%s\\",NONDIR_LONG);
  test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
678
  ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
679
  ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
680 681
     passfail.shorterror==ERROR_FILE_NOT_FOUND ||
     !passfail.shorterror,
682
     "GetShortPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
683
      passfail.shorterror);
684
  if(pGetLongPathNameA) {
685
    ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
686
    ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
687
       "GetLongPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
688 689
       passfail.longerror);
  }
690
/* Test GetFullPathNameA with drive letters */
691
  if( curDrive != NOT_A_VALID_DRIVE) {
692 693
    sprintf(tmpstr,"%c:",curdir[0]);
    ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
694
       "GetFullPathNameA(%c:) failed\n", curdir[0]);
695 696 697
    GetCurrentDirectoryA(MAX_PATH,tmpstr);
    sprintf(tmpstr1,"%s\\",tmpstr);
    ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
698
       "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
699 700
       curdir[0],tmpstr2,tmpstr,tmpstr1);

701
    sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
702
    ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
703
    ok(lstrcmpiA(tmpstr,tmpstr1)==0,
704
       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
705
    ok(lstrcmpiA(SHORTFILE,strptr)==0,
706
       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
707
  }
708 709
/* Without a leading slash, insert the current directory if on the current drive */
  sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
710
  ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
711 712
  sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
  ok(lstrcmpiA(tmpstr,tmpstr1)==0,
713
      "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
714
  ok(lstrcmpiA(SHORTFILE,strptr)==0,
715
      "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
716
/* Otherwise insert the missing leading slash */
717 718
  if( otherDrive != NOT_A_VALID_DRIVE) {
    sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
719
    ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
720 721
    sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
    ok(lstrcmpiA(tmpstr,tmpstr1)==0,
722
       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
723
    ok(lstrcmpiA(SHORTFILE,strptr)==0,
724
       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
725
  }
726 727
/* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
   So test for them. */
728 729
  if( curDrive != NOT_A_VALID_DRIVE) {
    sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
730
    ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
731 732
    sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
    ok(lstrcmpiA(tmpstr,tmpstr1)==0,
733
       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
734
    ok(lstrcmpiA(SHORTFILE,strptr)==0,
735
       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
736
  }
737 738
/**/
  sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
739
  ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
740 741
  sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
  ok(lstrcmpiA(tmpstr,tmpstr1)==0,
742
      "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
743
  ok(lstrcmpiA(SHORTFILE,strptr)==0,
744
      "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
745
/* Windows will insert a drive letter in front of an absolute UNIX path */
746
  sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
747
  ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
748 749 750
  sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
  ok(lstrcmpiA(tmpstr,tmpstr1)==0,
     "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
751 752
/* This passes in Wine because it still contains the pointer from the previous test */
  ok(lstrcmpiA(SHORTFILE,strptr)==0,
753
      "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
754

755
/* Now try some relative paths */
756
  ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
757
  test_SplitShortPathA(tmpstr,dir,eight,three);
758
  if(pGetLongPathNameA) {
759
    ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
760
    ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
761
       "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
762 763
  }
  sprintf(tmpstr,".\\%s",LONGDIR);
764
  ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
765
  test_SplitShortPathA(tmpstr1,dir,eight,three);
766
  ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
767
     "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
768
  if(pGetLongPathNameA) {
769
    ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
770 771
       tmpstr);
    ok(lstrcmpiA(tmpstr1,tmpstr)==0,
772
       "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
773 774 775
  }
/* Check out Get*PathNameA on some funny characters */
  for(i=0;i<lstrlenA(funny_chars);i++) {
776
    INT valid;
777 778 779
    valid=(is_char_ok[i]=='0') ? 0 : 1;
    sprintf(tmpstr1,"check%d-1",i);
    sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
780
    test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
781 782
    sprintf(tmpstr1,"check%d-2",i);
    sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
783
    test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
784 785
    sprintf(tmpstr1,"check%d-3",i);
    sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
786
    test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
787 788
    sprintf(tmpstr1,"check%d-4",i);
    sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
789
    test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
790 791
    sprintf(tmpstr1,"check%d-5",i);
    sprintf(tmpstr,"Long %c File",funny_chars[i]);
792
    test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
793 794
    sprintf(tmpstr1,"check%d-6",i);
    sprintf(tmpstr,"%c Long File",funny_chars[i]);
795
    test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
796 797
    sprintf(tmpstr1,"check%d-7",i);
    sprintf(tmpstr,"Long File %c",funny_chars[i]);
798
    test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
799 800 801
  }
}

802
static void test_GetTempPathA(char* tmp_dir)
803
{
804
    DWORD len, len_with_null;
805 806
    char buf[MAX_PATH];

807 808
    len_with_null = strlen(tmp_dir) + 1;

809 810
    lstrcpyA(buf, "foo");
    len = GetTempPathA(MAX_PATH, buf);
811 812 813
    ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
    ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
    ok(len == strlen(buf), "returned length should be equal to the length of string\n");
814

815 816 817 818 819 820
    /* Some versions of Windows touch the buffer, some don't so we don't
     * test that. Also, NT sometimes exagerates the required buffer size
     * so we cannot test for an exact match. Finally, the
     * 'len_with_null - 1' case is so buggy on Windows it's not testable.
     * For instance in some cases Win98 returns len_with_null - 1 instead
     * of len_with_null.
821 822
     */
    len = GetTempPathA(1, buf);
823
    ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
824

825
    len = GetTempPathA(0, NULL);
826
    ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
827

828 829 830
    /* The call above gave us the buffer size that Windows thinks is needed
     * so the next call should work
     */
831
    lstrcpyA(buf, "foo");
832
    len = GetTempPathA(len, buf);
833 834
    ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
    ok(len == strlen(buf), "returned length should be equal to the length of string\n");
835 836
}

837
static void test_GetTempPathW(char* tmp_dir)
838
{
839
    DWORD len, len_with_null;
840
    WCHAR buf[MAX_PATH];
841
    WCHAR tmp_dirW[MAX_PATH];
842 843
    static const WCHAR fooW[] = {'f','o','o',0};

844 845 846 847 848 849 850 851 852 853 854 855
    MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
    len_with_null = lstrlenW(tmp_dirW) + 1;

    /* This one is different from ANSI version: ANSI version doesn't
     * touch the buffer, unicode version usually truncates the buffer
     * to zero size. NT still exagerates the required buffer size
     * sometimes so we cannot test for an exact match. Finally, the
     * 'len_with_null - 1' case is so buggy on Windows it's not testable.
     * For instance on NT4 it will sometimes return a path without the
     * trailing '\\' and sometimes return an error.
     */

856 857
    lstrcpyW(buf, fooW);
    len = GetTempPathW(MAX_PATH, buf);
858 859
    if (len==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
        return;
860 861
    ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
    ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
862 863 864

    lstrcpyW(buf, fooW);
    len = GetTempPathW(1, buf);
865 866
    ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
    ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
867

868
    len = GetTempPathW(0, NULL);
869
    ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
870 871

    lstrcpyW(buf, fooW);
872
    len = GetTempPathW(len, buf);
873 874
    ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
    ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
875 876 877 878 879 880 881 882 883 884 885 886
}

static void test_GetTempPath(void)
{
    char save_TMP[MAX_PATH];
    char windir[MAX_PATH];
    char buf[MAX_PATH];

    GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP));

    /* test default configuration */
    trace("TMP=%s\n", save_TMP);
887 888 889 890 891
    strcpy(buf,save_TMP);
    if (buf[strlen(buf)-1]!='\\')
        strcat(buf,"\\");
    test_GetTempPathA(buf);
    test_GetTempPathW(buf);
892 893 894 895 896 897

    /* TMP=C:\WINDOWS */
    GetWindowsDirectoryA(windir, sizeof(windir));
    SetEnvironmentVariableA("TMP", windir);
    GetEnvironmentVariableA("TMP", buf, sizeof(buf));
    trace("TMP=%s\n", buf);
898 899 900
    strcat(windir,"\\");
    test_GetTempPathA(windir);
    test_GetTempPathW(windir);
901 902 903 904 905 906 907

    /* TMP=C:\ */
    GetWindowsDirectoryA(windir, sizeof(windir));
    windir[3] = 0;
    SetEnvironmentVariableA("TMP", windir);
    GetEnvironmentVariableA("TMP", buf, sizeof(buf));
    trace("TMP=%s\n", buf);
908 909
    test_GetTempPathA(windir);
    test_GetTempPathW(windir);
910 911 912 913 914 915 916 917

    /* TMP=C: i.e. use current working directory of the specified drive */
    GetWindowsDirectoryA(windir, sizeof(windir));
    SetCurrentDirectoryA(windir);
    windir[2] = 0;
    SetEnvironmentVariableA("TMP", windir);
    GetEnvironmentVariableA("TMP", buf, sizeof(buf));
    trace("TMP=%s\n", buf);
918 919 920 921
    GetWindowsDirectoryA(windir, sizeof(windir));
    strcat(windir,"\\");
    test_GetTempPathA(windir);
    test_GetTempPathW(windir);
922 923 924 925

    SetEnvironmentVariableA("TMP", save_TMP);
}

926 927
START_TEST(path)
{
928
    CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
929 930
    pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
                                               "GetLongPathNameA" );
931
    test_InitPathA(curdir, &curDrive, &otherDrive);
932
    test_CurrentDirectoryA(origdir,curdir);
933
    test_PathNameA(curdir, curDrive, otherDrive);
934
    test_CleanupPathA(origdir,curdir);
935
    test_GetTempPath();
936
}