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 \
|
||||
ne_module.c \
|
||||
ne_segment.c \
|
||||
path.c \
|
||||
powermgnt.c \
|
||||
process.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
|
||||
*/
|
||||
if(pGetLongPathNameA) {
|
||||
if(len==0) {
|
||||
if(len!=0) {
|
||||
SetLastError(0);
|
||||
len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
|
||||
if(passfail==NULL) {
|
||||
|
@ -160,12 +160,9 @@ static void test_ValidPathA(CHAR *curdir, CHAR *subdir, CHAR *filename,
|
|||
if(passfail==NULL) {
|
||||
ok(len, "%s: GetLongPathNameA failed",errstr);
|
||||
if(HAS_TRAIL_SLASH_A(fullpath)) {
|
||||
/* Wine strips off the trailing '\\' Neither Win98 nor Win2k do this */
|
||||
todo_wine {
|
||||
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
|
||||
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
|
||||
"%s: GetLongPathNameA returned '%s' instead of '%s'",
|
||||
errstr,tmpstr,fullpathlong);
|
||||
}
|
||||
} else {
|
||||
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
|
||||
"%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
|
||||
characters in the 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
|
||||
Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
|
||||
should.
|
||||
|
@ -518,13 +515,11 @@ static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
|
|||
"GetLongPathNameA: wrong return code, %ld instead of %d",
|
||||
rc1, strlen(tmpstr)+1);
|
||||
|
||||
todo_wine {
|
||||
sprintf(dir,"%c:",curDrive);
|
||||
rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
|
||||
ok(strcmp(dir,tmpstr)==0,
|
||||
"GetLongPathNameA: returned '%s' instead of '%s' (rc=%ld)",
|
||||
tmpstr,dir,rc1);
|
||||
}
|
||||
sprintf(dir,"%c:",curDrive);
|
||||
rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
|
||||
ok(strcmp(dir,tmpstr)==0,
|
||||
"GetLongPathNameA: returned '%s' instead of '%s' (rc=%ld)",
|
||||
tmpstr,dir,rc1);
|
||||
}
|
||||
|
||||
/* 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");
|
||||
test_SplitShortPathA(tmpstr,dir,eight,three);
|
||||
if(pGetLongPathNameA) {
|
||||
ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
|
||||
todo_wine {
|
||||
ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
|
||||
"GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,LONGDIR);
|
||||
}
|
||||
ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed");
|
||||
ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
|
||||
"GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,LONGDIR);
|
||||
}
|
||||
sprintf(tmpstr,".\\%s",LONGDIR);
|
||||
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',
|
||||
"GetShortPathNameA did not keep relative directory [%s]",tmpstr1);
|
||||
if(pGetLongPathNameA) {
|
||||
ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
|
||||
todo_wine {
|
||||
ok(lstrcmpiA(tmpstr1,tmpstr)==0,
|
||||
"GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
|
||||
}
|
||||
ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s",
|
||||
tmpstr);
|
||||
ok(lstrcmpiA(tmpstr1,tmpstr)==0,
|
||||
"GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
|
||||
}
|
||||
/* Check out Get*PathNameA on some funny characters */
|
||||
for(i=0;i<lstrlenA(funny_chars);i++) {
|
||||
|
|
|
@ -615,6 +615,7 @@ DWORD WINAPI RtlGetLongestNtPathLength(void)
|
|||
BOOLEAN WINAPI RtlIsNameLegalDOS8Dot3( const UNICODE_STRING *unicode,
|
||||
OEM_STRING *oem, BOOLEAN *spaces )
|
||||
{
|
||||
static const char* illegal = "*?<>|\"+=,;[]:/\\\345";
|
||||
int dot = -1;
|
||||
unsigned int i;
|
||||
char buffer[12];
|
||||
|
@ -655,7 +656,7 @@ BOOLEAN WINAPI RtlIsNameLegalDOS8Dot3( const UNICODE_STRING *unicode,
|
|||
dot = i;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: check for invalid chars */
|
||||
if (strchr(illegal, oem->Buffer[i])) return FALSE;
|
||||
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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue