Reimplemented Get{Short|Long}PathName and updated the regression
tests.
This commit is contained in:
parent
8732357912
commit
9ccb73a8d7
|
@ -51,6 +51,7 @@ C_SRCS = \
|
||||||
module.c \
|
module.c \
|
||||||
ne_module.c \
|
ne_module.c \
|
||||||
ne_segment.c \
|
ne_segment.c \
|
||||||
|
path.c \
|
||||||
powermgnt.c \
|
powermgnt.c \
|
||||||
process.c \
|
process.c \
|
||||||
profile.c \
|
profile.c \
|
||||||
|
|
|
@ -0,0 +1,352 @@
|
||||||
|
/*
|
||||||
|
* File handling functions
|
||||||
|
*
|
||||||
|
* Copyright 1993 Erik Bos
|
||||||
|
* Copyright 1996 Alexandre Julliard
|
||||||
|
* Copyright 2003 Eric Pouech
|
||||||
|
*
|
||||||
|
* 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 "config.h"
|
||||||
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
|
#define NONAMELESSSTRUCT
|
||||||
|
#include "winerror.h"
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(file);
|
||||||
|
|
||||||
|
#define MAX_PATHNAME_LEN 1024
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetLongPathNameW (KERNEL32.@)
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* observed (Win2000):
|
||||||
|
* shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
|
||||||
|
* shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0
|
||||||
|
*/
|
||||||
|
DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen )
|
||||||
|
{
|
||||||
|
WCHAR tmplongpath[MAX_PATHNAME_LEN];
|
||||||
|
LPCWSTR p;
|
||||||
|
DWORD sp = 0, lp = 0;
|
||||||
|
DWORD tmplen;
|
||||||
|
BOOL unixabsolute = (shortpath[0] == '/');
|
||||||
|
WIN32_FIND_DATAW wfd;
|
||||||
|
HANDLE goit;
|
||||||
|
|
||||||
|
if (!shortpath)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!shortpath[0])
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("%s,%p,%ld\n", debugstr_w(shortpath), longpath, longlen);
|
||||||
|
|
||||||
|
if (shortpath[0] == '\\' && shortpath[1] == '\\')
|
||||||
|
{
|
||||||
|
ERR("UNC pathname %s\n", debugstr_w(shortpath));
|
||||||
|
lstrcpynW( longpath, shortpath, longlen );
|
||||||
|
return strlenW(longpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for drive letter */
|
||||||
|
if (!unixabsolute && shortpath[1] == ':' )
|
||||||
|
{
|
||||||
|
tmplongpath[0] = shortpath[0];
|
||||||
|
tmplongpath[1] = ':';
|
||||||
|
lp = sp = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (shortpath[sp])
|
||||||
|
{
|
||||||
|
/* check for path delimiters and reproduce them */
|
||||||
|
if (shortpath[sp] == '\\' || shortpath[sp] == '/')
|
||||||
|
{
|
||||||
|
if (!lp || tmplongpath[lp-1] != '\\')
|
||||||
|
{
|
||||||
|
/* strip double "\\" */
|
||||||
|
tmplongpath[lp++] = '\\';
|
||||||
|
}
|
||||||
|
tmplongpath[lp] = 0; /* terminate string */
|
||||||
|
sp++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = shortpath + sp;
|
||||||
|
if (sp == 0 && p[0] == '.' && (p[1] == '/' || p[1] == '\\'))
|
||||||
|
{
|
||||||
|
tmplongpath[lp++] = *p++;
|
||||||
|
tmplongpath[lp++] = *p++;
|
||||||
|
}
|
||||||
|
for (; *p && *p != '/' && *p != '\\'; p++);
|
||||||
|
tmplen = p - (shortpath + sp);
|
||||||
|
lstrcpynW(tmplongpath + lp, shortpath + sp, tmplen + 1);
|
||||||
|
/* Check if the file exists and use the existing file name */
|
||||||
|
goit = FindFirstFileW(tmplongpath, &wfd);
|
||||||
|
if (goit == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
TRACE("not found %s!\n", debugstr_w(tmplongpath));
|
||||||
|
SetLastError ( ERROR_FILE_NOT_FOUND );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
FindClose(goit);
|
||||||
|
strcpyW(tmplongpath + lp, wfd.cFileName);
|
||||||
|
lp += strlenW(tmplongpath + lp);
|
||||||
|
sp += tmplen;
|
||||||
|
}
|
||||||
|
tmplen = strlenW(shortpath) - 1;
|
||||||
|
if ((shortpath[tmplen] == '/' || shortpath[tmplen] == '\\') &&
|
||||||
|
(tmplongpath[lp - 1] != '/' && tmplongpath[lp - 1] != '\\'))
|
||||||
|
tmplongpath[lp++] = shortpath[tmplen];
|
||||||
|
tmplongpath[lp] = 0;
|
||||||
|
|
||||||
|
tmplen = strlenW(tmplongpath) + 1;
|
||||||
|
if (tmplen <= longlen)
|
||||||
|
{
|
||||||
|
strcpyW(longpath, tmplongpath);
|
||||||
|
TRACE("returning %s\n", debugstr_w(longpath));
|
||||||
|
tmplen--; /* length without 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmplen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetLongPathNameA (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen )
|
||||||
|
{
|
||||||
|
UNICODE_STRING shortpathW;
|
||||||
|
WCHAR longpathW[MAX_PATH];
|
||||||
|
DWORD ret, retW;
|
||||||
|
|
||||||
|
if (!shortpath)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("%s\n", debugstr_a(shortpath));
|
||||||
|
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz(&shortpathW, shortpath))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
retW = GetLongPathNameW(shortpathW.Buffer, longpathW, MAX_PATH);
|
||||||
|
|
||||||
|
if (!retW)
|
||||||
|
ret = 0;
|
||||||
|
else if (retW > MAX_PATH)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = WideCharToMultiByte(CP_ACP, 0, longpathW, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (ret <= longlen)
|
||||||
|
{
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, longpathW, -1, longpath, longlen, NULL, NULL);
|
||||||
|
ret--; /* length without 0 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlFreeUnicodeString(&shortpathW);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetShortPathNameW (KERNEL32.@)
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* observed:
|
||||||
|
* longpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
|
||||||
|
* longpath="" or invalid: LastError=ERROR_BAD_PATHNAME, ret=0
|
||||||
|
*
|
||||||
|
* more observations ( with NT 3.51 (WinDD) ):
|
||||||
|
* longpath <= 8.3 -> just copy longpath to shortpath
|
||||||
|
* longpath > 8.3 ->
|
||||||
|
* a) file does not exist -> return 0, LastError = ERROR_FILE_NOT_FOUND
|
||||||
|
* b) file does exist -> set the short filename.
|
||||||
|
* - trailing slashes are reproduced in the short name, even if the
|
||||||
|
* file is not a directory
|
||||||
|
* - the absolute/relative path of the short name is reproduced like found
|
||||||
|
* in the long name
|
||||||
|
* - longpath and shortpath may have the same address
|
||||||
|
* Peter Ganten, 1999
|
||||||
|
*/
|
||||||
|
DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortlen )
|
||||||
|
{
|
||||||
|
WCHAR tmpshortpath[MAX_PATHNAME_LEN];
|
||||||
|
LPCWSTR p;
|
||||||
|
DWORD sp = 0, lp = 0;
|
||||||
|
DWORD tmplen;
|
||||||
|
BOOL unixabsolute = (longpath[0] == '/');
|
||||||
|
WIN32_FIND_DATAW wfd;
|
||||||
|
HANDLE goit;
|
||||||
|
UNICODE_STRING ustr;
|
||||||
|
WCHAR ustr_buf[8+1+3+1];
|
||||||
|
|
||||||
|
TRACE("%s\n", debugstr_w(longpath));
|
||||||
|
|
||||||
|
if (!longpath)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!longpath[0])
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_BAD_PATHNAME);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for drive letter */
|
||||||
|
if (!unixabsolute && longpath[1] == ':' )
|
||||||
|
{
|
||||||
|
tmpshortpath[0] = longpath[0];
|
||||||
|
tmpshortpath[1] = ':';
|
||||||
|
sp = lp = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ustr.Buffer = ustr_buf;
|
||||||
|
ustr.Length = 0;
|
||||||
|
ustr.MaximumLength = sizeof(ustr_buf);
|
||||||
|
|
||||||
|
while (longpath[lp])
|
||||||
|
{
|
||||||
|
/* check for path delimiters and reproduce them */
|
||||||
|
if (longpath[lp] == '\\' || longpath[lp] == '/')
|
||||||
|
{
|
||||||
|
if (!sp || tmpshortpath[sp-1] != '\\')
|
||||||
|
{
|
||||||
|
/* strip double "\\" */
|
||||||
|
tmpshortpath[sp] = '\\';
|
||||||
|
sp++;
|
||||||
|
}
|
||||||
|
tmpshortpath[sp] = 0; /* terminate string */
|
||||||
|
lp++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = longpath + lp; *p && *p != '/' && *p != '\\'; p++);
|
||||||
|
tmplen = p - (longpath + lp);
|
||||||
|
lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
|
||||||
|
if (tmplen <= 8+1+3+1)
|
||||||
|
{
|
||||||
|
memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR));
|
||||||
|
ustr_buf[tmplen] = '\0';
|
||||||
|
ustr.Length = tmplen * sizeof(WCHAR);
|
||||||
|
/* Check, if the current element is a valid dos name */
|
||||||
|
if (!RtlIsNameLegalDOS8Dot3(&ustr, NULL, NULL))
|
||||||
|
goto notfound;
|
||||||
|
sp += tmplen;
|
||||||
|
lp += tmplen;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the file exists and use the existing file name */
|
||||||
|
goit = FindFirstFileW(tmpshortpath, &wfd);
|
||||||
|
if (goit == INVALID_HANDLE_VALUE) goto notfound;
|
||||||
|
FindClose(goit);
|
||||||
|
strcpyW(tmpshortpath + sp, wfd.cAlternateFileName);
|
||||||
|
sp += strlenW(tmpshortpath + sp);
|
||||||
|
lp += tmplen;
|
||||||
|
}
|
||||||
|
tmpshortpath[sp] = 0;
|
||||||
|
|
||||||
|
tmplen = strlenW(tmpshortpath) + 1;
|
||||||
|
if (tmplen <= shortlen)
|
||||||
|
{
|
||||||
|
strcpyW(shortpath, tmpshortpath);
|
||||||
|
TRACE("returning %s\n", debugstr_w(shortpath));
|
||||||
|
tmplen--; /* length without 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmplen;
|
||||||
|
|
||||||
|
notfound:
|
||||||
|
TRACE("not found!\n" );
|
||||||
|
SetLastError ( ERROR_FILE_NOT_FOUND );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetShortPathNameA (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
|
||||||
|
{
|
||||||
|
UNICODE_STRING longpathW;
|
||||||
|
WCHAR shortpathW[MAX_PATH];
|
||||||
|
DWORD ret, retW;
|
||||||
|
|
||||||
|
if (!longpath)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("%s\n", debugstr_a(longpath));
|
||||||
|
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz(&longpathW, longpath))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
retW = GetShortPathNameW(longpathW.Buffer, shortpathW, MAX_PATH);
|
||||||
|
|
||||||
|
if (!retW)
|
||||||
|
ret = 0;
|
||||||
|
else if (retW > MAX_PATH)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = WideCharToMultiByte(CP_ACP, 0, shortpathW, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (ret <= shortlen)
|
||||||
|
{
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, shortpathW, -1, shortpath, shortlen, NULL, NULL);
|
||||||
|
ret--; /* length without 0 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlFreeUnicodeString(&longpathW);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -141,7 +141,7 @@ static void test_ValidPathA(CHAR *curdir, CHAR *subdir, CHAR *filename,
|
||||||
We test both conversion from GetFullPathNameA and from GetShortPathNameA
|
We test both conversion from GetFullPathNameA and from GetShortPathNameA
|
||||||
*/
|
*/
|
||||||
if(pGetLongPathNameA) {
|
if(pGetLongPathNameA) {
|
||||||
if(len==0) {
|
if(len!=0) {
|
||||||
SetLastError(0);
|
SetLastError(0);
|
||||||
len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
|
len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
|
||||||
if(passfail==NULL) {
|
if(passfail==NULL) {
|
||||||
|
@ -160,12 +160,9 @@ static void test_ValidPathA(CHAR *curdir, CHAR *subdir, CHAR *filename,
|
||||||
if(passfail==NULL) {
|
if(passfail==NULL) {
|
||||||
ok(len, "%s: GetLongPathNameA failed",errstr);
|
ok(len, "%s: GetLongPathNameA failed",errstr);
|
||||||
if(HAS_TRAIL_SLASH_A(fullpath)) {
|
if(HAS_TRAIL_SLASH_A(fullpath)) {
|
||||||
/* Wine strips off the trailing '\\' Neither Win98 nor Win2k do this */
|
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
|
||||||
todo_wine {
|
|
||||||
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
|
|
||||||
"%s: GetLongPathNameA returned '%s' instead of '%s'",
|
"%s: GetLongPathNameA returned '%s' instead of '%s'",
|
||||||
errstr,tmpstr,fullpathlong);
|
errstr,tmpstr,fullpathlong);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
|
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
|
||||||
"%s: GetLongPathNameA returned '%s' instead of '%s'",
|
"%s: GetLongPathNameA returned '%s' instead of '%s'",
|
||||||
|
@ -229,7 +226,7 @@ static void test_LongtoShortA(CHAR *teststr,CHAR *goodstr,
|
||||||
/* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
|
/* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
|
||||||
characters in the filename.
|
characters in the filename.
|
||||||
'valid' indicates whether this would be an allowed filename
|
'valid' indicates whether this would be an allowed filename
|
||||||
'todo' indictaes that wine doesn't get this right yet.
|
'todo' indicates that wine doesn't get this right yet.
|
||||||
NOTE: We always call this routine with a non-existent filename, so
|
NOTE: We always call this routine with a non-existent filename, so
|
||||||
Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
|
Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
|
||||||
should.
|
should.
|
||||||
|
@ -518,13 +515,11 @@ static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
|
||||||
"GetLongPathNameA: wrong return code, %ld instead of %d",
|
"GetLongPathNameA: wrong return code, %ld instead of %d",
|
||||||
rc1, strlen(tmpstr)+1);
|
rc1, strlen(tmpstr)+1);
|
||||||
|
|
||||||
todo_wine {
|
sprintf(dir,"%c:",curDrive);
|
||||||
sprintf(dir,"%c:",curDrive);
|
rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
|
||||||
rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
|
ok(strcmp(dir,tmpstr)==0,
|
||||||
ok(strcmp(dir,tmpstr)==0,
|
"GetLongPathNameA: returned '%s' instead of '%s' (rc=%ld)",
|
||||||
"GetLongPathNameA: returned '%s' instead of '%s' (rc=%ld)",
|
tmpstr,dir,rc1);
|
||||||
tmpstr,dir,rc1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the cases where both file and directory exist first */
|
/* Check the cases where both file and directory exist first */
|
||||||
|
@ -773,11 +768,9 @@ static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
|
||||||
ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed");
|
ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed");
|
||||||
test_SplitShortPathA(tmpstr,dir,eight,three);
|
test_SplitShortPathA(tmpstr,dir,eight,three);
|
||||||
if(pGetLongPathNameA) {
|
if(pGetLongPathNameA) {
|
||||||
ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
|
ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed");
|
||||||
todo_wine {
|
ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
|
||||||
ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
|
"GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,LONGDIR);
|
||||||
"GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,LONGDIR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sprintf(tmpstr,".\\%s",LONGDIR);
|
sprintf(tmpstr,".\\%s",LONGDIR);
|
||||||
ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
|
ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
|
||||||
|
@ -785,11 +778,10 @@ static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
|
||||||
ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
|
ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
|
||||||
"GetShortPathNameA did not keep relative directory [%s]",tmpstr1);
|
"GetShortPathNameA did not keep relative directory [%s]",tmpstr1);
|
||||||
if(pGetLongPathNameA) {
|
if(pGetLongPathNameA) {
|
||||||
ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
|
ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s",
|
||||||
todo_wine {
|
tmpstr);
|
||||||
ok(lstrcmpiA(tmpstr1,tmpstr)==0,
|
ok(lstrcmpiA(tmpstr1,tmpstr)==0,
|
||||||
"GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
|
"GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Check out Get*PathNameA on some funny characters */
|
/* Check out Get*PathNameA on some funny characters */
|
||||||
for(i=0;i<lstrlenA(funny_chars);i++) {
|
for(i=0;i<lstrlenA(funny_chars);i++) {
|
||||||
|
|
|
@ -615,6 +615,7 @@ DWORD WINAPI RtlGetLongestNtPathLength(void)
|
||||||
BOOLEAN WINAPI RtlIsNameLegalDOS8Dot3( const UNICODE_STRING *unicode,
|
BOOLEAN WINAPI RtlIsNameLegalDOS8Dot3( const UNICODE_STRING *unicode,
|
||||||
OEM_STRING *oem, BOOLEAN *spaces )
|
OEM_STRING *oem, BOOLEAN *spaces )
|
||||||
{
|
{
|
||||||
|
static const char* illegal = "*?<>|\"+=,;[]:/\\\345";
|
||||||
int dot = -1;
|
int dot = -1;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
char buffer[12];
|
char buffer[12];
|
||||||
|
@ -655,7 +656,7 @@ BOOLEAN WINAPI RtlIsNameLegalDOS8Dot3( const UNICODE_STRING *unicode,
|
||||||
dot = i;
|
dot = i;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* FIXME: check for invalid chars */
|
if (strchr(illegal, oem->Buffer[i])) return FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
272
files/dos_fs.c
272
files/dos_fs.c
|
@ -1172,278 +1172,6 @@ BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last, DOS_FULL_NAME *full )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* GetShortPathNameW (KERNEL32.@)
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* observed:
|
|
||||||
* longpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
|
|
||||||
* longpath="" or invalid: LastError=ERROR_BAD_PATHNAME, ret=0
|
|
||||||
*
|
|
||||||
* more observations ( with NT 3.51 (WinDD) ):
|
|
||||||
* longpath <= 8.3 -> just copy longpath to shortpath
|
|
||||||
* longpath > 8.3 ->
|
|
||||||
* a) file does not exist -> return 0, LastError = ERROR_FILE_NOT_FOUND
|
|
||||||
* b) file does exist -> set the short filename.
|
|
||||||
* - trailing slashes are reproduced in the short name, even if the
|
|
||||||
* file is not a directory
|
|
||||||
* - the absolute/relative path of the short name is reproduced like found
|
|
||||||
* in the long name
|
|
||||||
* - longpath and shortpath may have the same address
|
|
||||||
* Peter Ganten, 1999
|
|
||||||
*/
|
|
||||||
DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortlen )
|
|
||||||
{
|
|
||||||
DOS_FULL_NAME full_name;
|
|
||||||
WCHAR tmpshortpath[MAX_PATHNAME_LEN];
|
|
||||||
const WCHAR *p;
|
|
||||||
DWORD sp = 0, lp = 0;
|
|
||||||
int drive;
|
|
||||||
DWORD tmplen;
|
|
||||||
UINT flags;
|
|
||||||
BOOL unixabsolute = *longpath == '/';
|
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_w(longpath));
|
|
||||||
|
|
||||||
if (!longpath) {
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!longpath[0]) {
|
|
||||||
SetLastError(ERROR_BAD_PATHNAME);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for drive letter */
|
|
||||||
if (!unixabsolute && longpath[1] == ':' ) {
|
|
||||||
tmpshortpath[0] = longpath[0];
|
|
||||||
tmpshortpath[1] = ':';
|
|
||||||
sp = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ( drive = DOSFS_GetPathDrive ( &longpath )) == -1 ) return 0;
|
|
||||||
flags = DRIVE_GetFlags ( drive );
|
|
||||||
|
|
||||||
if (unixabsolute && drive != DRIVE_GetCurrentDrive()) {
|
|
||||||
tmpshortpath[0] = drive + 'A';
|
|
||||||
tmpshortpath[1] = ':';
|
|
||||||
sp = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( longpath[lp] ) {
|
|
||||||
|
|
||||||
/* check for path delimiters and reproduce them */
|
|
||||||
if ( longpath[lp] == '\\' || longpath[lp] == '/' ) {
|
|
||||||
if (!sp || tmpshortpath[sp-1]!= '\\')
|
|
||||||
{
|
|
||||||
/* strip double "\\" */
|
|
||||||
tmpshortpath[sp] = '\\';
|
|
||||||
sp++;
|
|
||||||
}
|
|
||||||
tmpshortpath[sp]=0;/*terminate string*/
|
|
||||||
lp++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmplen = 0;
|
|
||||||
for(p = longpath + lp; *p && *p != '/' && *p != '\\'; p++)
|
|
||||||
tmplen++;
|
|
||||||
lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
|
|
||||||
|
|
||||||
/* Check, if the current element is a valid dos name */
|
|
||||||
if ( DOSFS_ValidDOSName ( longpath + lp, !(flags & DRIVE_CASE_SENSITIVE) ) ) {
|
|
||||||
sp += tmplen;
|
|
||||||
lp += tmplen;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the file exists and use the existing file name */
|
|
||||||
if ( DOSFS_GetFullName ( tmpshortpath, TRUE, &full_name ) ) {
|
|
||||||
strcpyW(tmpshortpath + sp, strrchrW(full_name.short_name, '\\') + 1);
|
|
||||||
sp += strlenW(tmpshortpath + sp);
|
|
||||||
lp += tmplen;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("not found!\n" );
|
|
||||||
SetLastError ( ERROR_FILE_NOT_FOUND );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
tmpshortpath[sp] = 0;
|
|
||||||
|
|
||||||
tmplen = strlenW(tmpshortpath) + 1;
|
|
||||||
if (tmplen <= shortlen)
|
|
||||||
{
|
|
||||||
strcpyW(shortpath, tmpshortpath);
|
|
||||||
TRACE("returning %s\n", debugstr_w(shortpath));
|
|
||||||
tmplen--; /* length without 0 */
|
|
||||||
}
|
|
||||||
|
|
||||||
return tmplen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* GetShortPathNameA (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
|
|
||||||
{
|
|
||||||
UNICODE_STRING longpathW;
|
|
||||||
WCHAR shortpathW[MAX_PATH];
|
|
||||||
DWORD ret, retW;
|
|
||||||
|
|
||||||
if (!longpath)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_a(longpath));
|
|
||||||
|
|
||||||
if (!RtlCreateUnicodeStringFromAsciiz(&longpathW, longpath))
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
retW = GetShortPathNameW(longpathW.Buffer, shortpathW, MAX_PATH);
|
|
||||||
|
|
||||||
if (!retW)
|
|
||||||
ret = 0;
|
|
||||||
else if (retW > MAX_PATH)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = WideCharToMultiByte(CP_ACP, 0, shortpathW, -1, NULL, 0, NULL, NULL);
|
|
||||||
if (ret <= shortlen)
|
|
||||||
{
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, shortpathW, -1, shortpath, shortlen, NULL, NULL);
|
|
||||||
ret--; /* length without 0 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlFreeUnicodeString(&longpathW);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* GetLongPathNameW (KERNEL32.@)
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* observed (Win2000):
|
|
||||||
* shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
|
|
||||||
* shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0
|
|
||||||
*/
|
|
||||||
DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen )
|
|
||||||
{
|
|
||||||
DOS_FULL_NAME full_name;
|
|
||||||
const char *root;
|
|
||||||
LPWSTR p;
|
|
||||||
int drive;
|
|
||||||
DWORD ret, len = 0;
|
|
||||||
|
|
||||||
if (!shortpath) {
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!shortpath[0]) {
|
|
||||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("%s,%p,%ld\n", debugstr_w(shortpath), longpath, longlen);
|
|
||||||
|
|
||||||
if(shortpath[0]=='\\' && shortpath[1]=='\\')
|
|
||||||
{
|
|
||||||
ERR("UNC pathname %s\n",debugstr_w(shortpath));
|
|
||||||
lstrcpynW( longpath, full_name.short_name, longlen );
|
|
||||||
return strlenW(longpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DOSFS_GetFullName( shortpath, TRUE, &full_name )) return 0;
|
|
||||||
|
|
||||||
root = full_name.long_name;
|
|
||||||
drive = DRIVE_FindDriveRoot(&root);
|
|
||||||
|
|
||||||
ret = MultiByteToWideChar(CP_UNIXCP, 0, root, -1, NULL, 0);
|
|
||||||
ret += 3; /* A:\ */
|
|
||||||
/* reproduce terminating slash */
|
|
||||||
if (ret > 4) /* if not drive root */
|
|
||||||
{
|
|
||||||
len = strlenW(shortpath);
|
|
||||||
if (shortpath[len - 1] == '\\' || shortpath[len - 1] == '/')
|
|
||||||
len = 1;
|
|
||||||
}
|
|
||||||
ret += len;
|
|
||||||
if (ret <= longlen)
|
|
||||||
{
|
|
||||||
longpath[0] = 'A' + drive;
|
|
||||||
longpath[1] = ':';
|
|
||||||
MultiByteToWideChar(CP_UNIXCP, 0, root, -1, longpath + 2, longlen - 2);
|
|
||||||
for (p = longpath; *p; p++) if (*p == '/') *p = '\\';
|
|
||||||
if (len)
|
|
||||||
{
|
|
||||||
longpath[ret - 2] = '\\';
|
|
||||||
longpath[ret - 1] = 0;
|
|
||||||
}
|
|
||||||
TRACE("returning %s\n", debugstr_w(longpath));
|
|
||||||
ret--; /* length without 0 */
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* GetLongPathNameA (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
DWORD WINAPI GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen )
|
|
||||||
{
|
|
||||||
UNICODE_STRING shortpathW;
|
|
||||||
WCHAR longpathW[MAX_PATH];
|
|
||||||
DWORD ret, retW;
|
|
||||||
|
|
||||||
if (!shortpath)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_a(shortpath));
|
|
||||||
|
|
||||||
if (!RtlCreateUnicodeStringFromAsciiz(&shortpathW, shortpath))
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
retW = GetLongPathNameW(shortpathW.Buffer, longpathW, MAX_PATH);
|
|
||||||
|
|
||||||
if (!retW)
|
|
||||||
ret = 0;
|
|
||||||
else if (retW > MAX_PATH)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = WideCharToMultiByte(CP_ACP, 0, longpathW, -1, NULL, 0, NULL, NULL);
|
|
||||||
if (ret <= longlen)
|
|
||||||
{
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, longpathW, -1, longpath, longlen, NULL, NULL);
|
|
||||||
ret--; /* length without 0 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlFreeUnicodeString(&shortpathW);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* DOSFS_DoGetFullPathName
|
* DOSFS_DoGetFullPathName
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue