📄 path.c
字号:
/*
* 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
*/
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winerror.h"
#include "winnls.h"
#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"
#define NONFILE_LONG "NonExistent File"
#define NONDIR_SHORT "notadir"
#define NONDIR_LONG "NonExistent Directory"
#define NOT_A_VALID_DRIVE '@'
/* 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
|<>"
*/
static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
static const CHAR is_char_ok[] ="11111110111111111011";
static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
/* 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
*/
static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
{
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+ */
if(pGetLongPathNameA) {
ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
"%s: GetLongPathNameA failed\n",errstr);
/*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
ok(! HAS_TRAIL_SLASH_A(curdirlong),
"%s: GetLongPathNameA should not have a trailing \\\n",errstr);
}
ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
"%s: GetShortPathNameA failed\n",errstr);
/*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
ok(! HAS_TRAIL_SLASH_A(curdirshort),
"%s: GetShortPathNameA should not have a trailing \\\n",errstr);
/* 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);
ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
if(HAS_TRAIL_SLASH_A(subpath)) {
ok(strptr==NULL,
"%s: GetFullPathNameA should not return a filename ptr\n",errstr);
ok(lstrcmpiA(fullpath,tmpstr)==0,
"%s: GetFullPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpath);
} else {
ok(lstrcmpiA(strptr,filename)==0,
"%s: GetFullPathNameA returned '%s' instead of '%s'\n",
errstr,strptr,filename);
ok(lstrcmpiA(fullpath,tmpstr)==0,
"%s: GetFullPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpath);
}
/* Test GetShortPathNameA functionality */
SetLastError(0);
len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
if(passfail==NULL) {
ok(len, "%s: GetShortPathNameA failed\n",errstr);
} else {
passfail->shortlen=len;
passfail->shorterror=GetLastError();
}
/* Test GetLongPathNameA functionality
We test both conversion from GetFullPathNameA and from GetShortPathNameA
*/
if(pGetLongPathNameA) {
if(len!=0) {
SetLastError(0);
len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
if(passfail==NULL) {
ok(len,
"%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
"%s: GetLongPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpathlong);
} else {
passfail->s2llen=len;
passfail->s2lerror=GetLastError();
}
}
SetLastError(0);
len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
if(passfail==NULL) {
ok(len, "%s: GetLongPathNameA failed\n",errstr);
if(HAS_TRAIL_SLASH_A(fullpath)) {
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
"%s: GetLongPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpathlong);
} else {
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
"%s: GetLongPathNameA returned '%s' instead of '%s'\n",
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) {
int done,error;
int ext,fil;
int len,i;
len=lstrlenA(path);
ext=len; fil=len; done=0; error=0;
/* walk backwards over path looking for '.' or '\\' separators */
for(i=len-1;(i>=0) && (!done);i--) {
if(path[i]=='.')
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 '.' */
ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
/* Separate dir, root, and extension */
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,
"GetShortPathNAmeA did not return an 8.3 path\n");
}
/* Check that GetShortPathNameA returns a valid 8.3 path */
static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
const CHAR *ext,const CHAR *errstr) {
CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
test_SplitShortPathA(teststr,dir,eight,three);
ok(lstrcmpiA(dir,goodstr)==0,
"GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
ok(lstrcmpiA(three,ext)==0,
"GetShortPathNameA returned '%s' with incorrect extension\n",three);
}
/* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
characters in the filename.
'valid' indicates whether this would be an allowed filename
'todo' indicates that wine doesn't get this right yet.
NOTE: We always call this routine with a nonexistent filename, so
Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
should.
*/
static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
{
CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
SLpassfail passfail;
test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
if(valid) {
sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
ok((passfail.shortlen==0 &&
(passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
(passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
"%s: GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
errstr,passfail.shortlen,passfail.shorterror,tmpstr);
} else {
ok(passfail.shortlen==0 &&
(passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
"%s: GetShortPathA should have failed len=%ld, error=%ld\n",
errstr,passfail.shortlen,passfail.shorterror);
}
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
if(valid) {
ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
"%s: GetLongPathA returned %ld and not %ld\n",
errstr,passfail.longerror,(DWORD) ERROR_FILE_NOT_FOUND);
} else {
ok(passfail.longerror==ERROR_INVALID_NAME ||
passfail.longerror==ERROR_FILE_NOT_FOUND,
"%s: GetLongPathA returned %ld and not %ld or %ld'\n",
errstr, passfail.longerror,(DWORD) ERROR_INVALID_NAME,(DWORD)ERROR_FILE_NOT_FOUND);
}
}
}
/* Routine to test that SetCurrentDirectory behaves as expected. */
static void test_setdir(CHAR *olddir,CHAR *newdir,
CHAR *cmprstr, INT pass, const CHAR *errstr)
{
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);
ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
ok(len==chklen,
"%s: SetCurrentDirectory did not change the directory, though it passed\n",
errstr);
ok(lstrcmpiA(dirptr,tmppath)==0,
"%s: SetCurrentDirectory did not change the directory, though it passed\n",
errstr);
ok(SetCurrentDirectoryA(olddir),
"%s: Couldn't set directory to it's original value\n",errstr);
} else {
/* else thest that it fails correctly */
chklen=lstrlenA(olddir);
ok(val==0,
"%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
ok(len==chklen,
"%s: SetCurrentDirectory changed the directory, though it failed\n",
errstr);
ok(lstrcmpiA(olddir,tmppath)==0,
"%s: SetCurrentDirectory changed the directory, though it failed\n",
errstr);
}
}
static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
{
CHAR tmppath[MAX_PATH], /*path to TEMP */
tmpstr[MAX_PATH],
tmpstr1[MAX_PATH];
DWORD len,len1,drives;
INT id;
HANDLE hndl;
BOOL bRes;
*curDrive = *otherDrive = NOT_A_VALID_DRIVE;
/* Get the current drive letter */
if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -