Reimplemented Get{Short|Long}PathName and updated the regression

tests.
This commit is contained in:
Eric Pouech 2004-01-15 00:20:46 +00:00 committed by Alexandre Julliard
parent 8732357912
commit 9ccb73a8d7
5 changed files with 370 additions and 296 deletions

View File

@ -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 \

352
dlls/kernel/path.c Normal file
View File

@ -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;
}

View File

@ -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 */
todo_wine {
ok(lstrcmpiA(fullpathlong,tmpstr)==0, 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,14 +515,12 @@ 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 */
/* Start with a 8.3 directory, 8.3 filename */ /* Start with a 8.3 directory, 8.3 filename */
@ -773,24 +768,21 @@ 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");
test_SplitShortPathA(tmpstr1,dir,eight,three); test_SplitShortPathA(tmpstr1,dir,eight,three);
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++) {
INT valid,todo; INT valid,todo;

View File

@ -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;
} }
} }

View File

@ -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
* *