From 9ccb73a8d701a6810e3f41dbcdea4b2ed4db2bd5 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Thu, 15 Jan 2004 00:20:46 +0000 Subject: [PATCH] Reimplemented Get{Short|Long}PathName and updated the regression tests. --- dlls/kernel/Makefile.in | 1 + dlls/kernel/path.c | 352 +++++++++++++++++++++++++++++++++++++++ dlls/kernel/tests/path.c | 38 ++--- dlls/ntdll/path.c | 3 +- files/dos_fs.c | 272 ------------------------------ 5 files changed, 370 insertions(+), 296 deletions(-) create mode 100644 dlls/kernel/path.c diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in index a32b1fe1d04..081a1245671 100644 --- a/dlls/kernel/Makefile.in +++ b/dlls/kernel/Makefile.in @@ -51,6 +51,7 @@ C_SRCS = \ module.c \ ne_module.c \ ne_segment.c \ + path.c \ powermgnt.c \ process.c \ profile.c \ diff --git a/dlls/kernel/path.c b/dlls/kernel/path.c new file mode 100644 index 00000000000..08f1ed4ff0d --- /dev/null +++ b/dlls/kernel/path.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 + +#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; +} diff --git a/dlls/kernel/tests/path.c b/dlls/kernel/tests/path.c index 53852178ed1..ffe4dff01bd 100644 --- a/dlls/kernel/tests/path.c +++ b/dlls/kernel/tests/path.c @@ -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;iBuffer[i])) return FALSE; break; } } diff --git a/files/dos_fs.c b/files/dos_fs.c index 04c9b557358..fe6e00df647 100644 --- a/files/dos_fs.c +++ b/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 *