Hmm I don't remember that one, it may have gotten lost in the vacation
backlog. Could you please resend?
here we go
A+
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel38/Makefile.in dlls/kernel/Makefile.in
--- dlls/kernel38/Makefile.in 2003-12-06 16:09:08.000000000 +0100
+++ dlls/kernel/Makefile.in 2003-12-12 21:33:31.000000000 +0100
@@ -51,6 +51,7 @@
module.c \
ne_module.c \
ne_segment.c \
+ path.c \
powermgnt.c \
process.c \
profile.c \
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel38/path.c dlls/kernel/path.c
--- dlls/kernel38/path.c 1970-01-01 01:00:00.000000000 +0100
+++ dlls/kernel/path.c 2003-12-13 10:30:11.000000000 +0100
@@ -0,0 +1,440 @@
+/*
+ * 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 "wincon.h"
+#include "wine/winbase16.h"
+#include "kernel_private.h"
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+#include "async.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(file);
+
+#define MAX_PATHNAME_LEN 1024
+
+
+/***********************************************************************
+ * GetFullPathNameW (KERNEL32.@)
+ * NOTES
+ * if the path closed with '\', *lastpart is 0
+ */
+DWORD WINAPI GetFullPathNameW( LPCWSTR name, DWORD len, LPWSTR buffer,
+ LPWSTR *lastpart )
+{
+ LPWSTR dst = HeapAlloc(GetProcessHeap(), 0, len * sizeof(buffer));
+ DWORD ret;
+
+ if (!dst) return 0;
+ ret = RtlGetFullPathName_U(name, len * sizeof(WCHAR), dst, lastpart) /
sizeof(WCHAR);
+ if (ret < len)
+ {
+ strcpyW(buffer, dst);
+ if (lastpart && *lastpart) *lastpart = buffer + (*lastpart - dst);
+ }
+ HeapFree(GetProcessHeap(), 0, dst);
+ return ret;
+}
+
+/***********************************************************************
+ * GetFullPathNameA (KERNEL32.@)
+ * NOTES
+ * if the path closed with '\', *lastpart is 0
+ */
+DWORD WINAPI GetFullPathNameA( LPCSTR name, DWORD len, LPSTR buffer,
+ LPSTR *lastpart )
+{
+ UNICODE_STRING nameW;
+ WCHAR bufferW[MAX_PATH];
+ DWORD ret, retW;
+
+ if (!name)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ if (!RtlCreateUnicodeStringFromAsciiz(&nameW, name))
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+
+ retW = GetFullPathNameW( nameW.Buffer, MAX_PATH, bufferW, NULL);
+
+ if (!retW)
+ ret = 0;
+ else if (retW > MAX_PATH)
+ {
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ ret = 0;
+ }
+ else
+ {
+ ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
+ if (ret && ret <= len)
+ {
+ WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, len, NULL, NULL);
+ ret--; /* length without 0 */
+
+ if (lastpart)
+ {
+ LPSTR p = buffer + strlen(buffer) - 1;
+
+ if (*p != '\\')
+ {
+ while ((p > buffer + 2) && (*p != '\\')) p--;
+ *lastpart = p + 1;
+ }
+ else *lastpart = NULL;
+ }
+ }
+ }
+
+ RtlFreeUnicodeString(&nameW);
+ 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 )
+{
+ 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 -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel38/tests/path.c
dlls/kernel/tests/path.c
--- dlls/kernel38/tests/path.c 2003-12-06 16:08:32.000000000 +0100
+++ dlls/kernel/tests/path.c 2003-12-13 10:53:55.000000000 +0100
@@ -112,14 +112,11 @@
len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
ok(len, "GetFullPathNameA failed for: '%s'",subpath);
if(HAS_TRAIL_SLASH_A(subpath)) {
-/* Wine strips off the trailing '\\'. Neither Win98 nor Win2k do this. */
- todo_wine {
- ok(strptr==NULL,
- "%s: GetFullPathNameA should not return a filename ptr",errstr);
- ok(lstrcmpiA(fullpath,tmpstr)==0,
- "%s: GetFullPathNameA returned '%s' instead of '%s'",
- errstr,tmpstr,fullpath);
- }
+ ok(strptr==NULL,
+ "%s: GetFullPathNameA should not return a filename ptr
%s=>%s",subpath,strptr,errstr);
+ ok(lstrcmpiA(fullpath,tmpstr)==0,
+ "%s: GetFullPathNameA returned '%s' instead of '%s'",
+ errstr,tmpstr,fullpath);
} else {
ok(lstrcmpiA(strptr,filename)==0,
"%s: GetFullPathNameA returned '%s' instead of '%s'",
@@ -141,7 +138,7 @@
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 +157,9 @@
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 +223,7 @@
/* 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 +512,11 @@
"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 +765,9 @@
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 +775,10 @@
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++) {
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll38/path.c dlls/ntdll/path.c
--- dlls/ntdll38/path.c 2003-12-06 16:08:36.000000000 +0100
+++ dlls/ntdll/path.c 2003-12-13 10:52:49.000000000 +0100
@@ -614,6 +614,7 @@
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];
@@ -654,7 +655,7 @@
dot = i;
break;
default:
- /* FIXME: check for invalid chars */
+ if (strchr(illegal, oem->Buffer[i])) return FALSE;
break;
}
}
diff -u -N -r -x '*~' -x '.#*' -x CVS files38/dos_fs.c files/dos_fs.c
--- files38/dos_fs.c 2003-12-07 11:24:07.000000000 +0100
+++ files/dos_fs.c 2003-12-13 10:23:45.000000000 +0100
@@ -1173,527 +1173,6 @@
/***********************************************************************
- * 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
- *
- * Implementation of GetFullPathNameA/W.
- *
- * [EMAIL PROTECTED] 000331:
- * A test for GetFullPathName with many pathological cases
- * now gives identical output for Wine and OSR2
- */
-static DWORD DOSFS_DoGetFullPathName( LPCWSTR name, DWORD len, LPWSTR result )
-{
- DWORD ret;
- DOS_FULL_NAME full_name;
- LPWSTR p, q;
- char *p_l;
- const char * root;
- WCHAR drivecur[] = {'C',':','.',0};
- WCHAR driveletter=0;
- int namelen,drive=0;
- static const WCHAR bkslashW[] = {'\\',0};
- static const WCHAR dotW[] = {'.',0};
- static const WCHAR updir_slashW[] = {'\\','.','.','\\',0};
- static const WCHAR curdirW[] = {'\\','.','\\',0};
- static const WCHAR updirW[] = {'\\','.','.',0};
-
- if (!name[0])
- {
- SetLastError(ERROR_BAD_PATHNAME);
- return 0;
- }
-
- TRACE("passed %s\n", debugstr_w(name));
-
- if (name[1]==':')
- /*drive letter given */
- {
- driveletter = name[0];
- }
- if ((name[1]==':') && ((name[2]=='\\') || (name[2]=='/')))
- /*absolute path given */
- {
- strncpyW(full_name.short_name, name, MAX_PATHNAME_LEN);
- full_name.short_name[MAX_PATHNAME_LEN - 1] = 0; /* ensure 0 termination */
- drive = toupperW(name[0]) - 'A';
- }
- else
- {
- if (driveletter)
- drivecur[0]=driveletter;
- else if ((name[0]=='\\') || (name[0]=='/'))
- strcpyW(drivecur, bkslashW);
- else
- strcpyW(drivecur, dotW);
-
- if (!DOSFS_GetFullName( drivecur, FALSE, &full_name ))
- {
- FIXME("internal: error getting drive/path\n");
- return 0;
- }
- /* find path that drive letter substitutes*/
- drive = toupperW(full_name.short_name[0]) - 'A';
- root= DRIVE_GetRoot(drive);
- if (!root)
- {
- FIXME("internal: error getting DOS Drive Root\n");
- return 0;
- }
- if (!strcmp(root,"/"))
- {
- /* we have just the last / and we need it. */
- p_l = full_name.long_name;
- }
- else
- {
- p_l = full_name.long_name + strlen(root);
- }
- /* append long name (= unix name) to drive */
- MultiByteToWideChar(CP_UNIXCP, 0, p_l, -1, full_name.short_name + 2,
MAX_PATHNAME_LEN - 3);
- /* append name to treat */
- namelen= strlenW(full_name.short_name);
- p = (LPWSTR)name;
- if (driveletter)
- p += 2; /* skip drive name when appending */
- if (namelen + 2 + strlenW(p) > MAX_PATHNAME_LEN)
- {
- FIXME("internal error: buffer too small\n");
- return 0;
- }
- full_name.short_name[namelen++] ='\\';
- full_name.short_name[namelen] = 0;
- strncpyW(full_name.short_name + namelen, p, MAX_PATHNAME_LEN - namelen);
- full_name.short_name[MAX_PATHNAME_LEN - 1] = 0; /* ensure 0 termination */
- }
- /* reverse all slashes */
- for (p=full_name.short_name;
- p < full_name.short_name + strlenW(full_name.short_name);
- p++)
- {
- if ( *p == '/' )
- *p = '\\';
- }
- /* Use memmove, as areas overlap */
- /* Delete .. */
- while ((p = strstrW(full_name.short_name, updir_slashW)))
- {
- if (p > full_name.short_name+2)
- {
- *p = 0;
- q = strrchrW(full_name.short_name, '\\');
- memmove(q+1, p+4, (strlenW(p+4)+1) * sizeof(WCHAR));
- }
- else
- {
- memmove(full_name.short_name+3, p+4, (strlenW(p+4)+1) * sizeof(WCHAR));
- }
- }
- if ((full_name.short_name[2]=='.')&&(full_name.short_name[3]=='.'))
- {
- /* This case istn't treated yet : c:..\test */
- memmove(full_name.short_name+2,full_name.short_name+4,
- (strlenW(full_name.short_name+4)+1) * sizeof(WCHAR));
- }
- /* Delete . */
- while ((p = strstrW(full_name.short_name, curdirW)))
- {
- *(p+1) = 0;
- memmove(p+1, p+3, (strlenW(p+3)+1) * sizeof(WCHAR));
- }
- if (!(DRIVE_GetFlags(drive) & DRIVE_CASE_PRESERVING))
- for (p = full_name.short_name; *p; p++) *p = toupperW(*p);
- namelen = strlenW(full_name.short_name);
- if (!strcmpW(full_name.short_name+namelen-3, updirW))
- {
- /* one more strange case: "c:\test\test1\.."
- return "c:\test" */
- *(full_name.short_name+namelen-3)=0;
- q = strrchrW(full_name.short_name, '\\');
- *q =0;
- }
- if (full_name.short_name[namelen-1]=='.')
- full_name.short_name[(namelen--)-1] =0;
- if (!driveletter)
- if (full_name.short_name[namelen-1]=='\\')
- full_name.short_name[(namelen--)-1] =0;
- TRACE("got %s\n", debugstr_w(full_name.short_name));
-
- /* If the lpBuffer buffer is too small, the return value is the
- size of the buffer, in characters, required to hold the path
- plus the terminating \0 (tested against win95osr2, bon 001118)
- . */
- ret = strlenW(full_name.short_name);
- if (ret >= len )
- {
- /* don't touch anything when the buffer is not large enough */
- SetLastError( ERROR_INSUFFICIENT_BUFFER );
- return ret+1;
- }
- if (result)
- {
- strncpyW( result, full_name.short_name, len );
- result[len - 1] = 0; /* ensure 0 termination */
- }
-
- TRACE("returning %s\n", debugstr_w(full_name.short_name) );
- return ret;
-}
-
-
-/***********************************************************************
- * GetFullPathNameA (KERNEL32.@)
- * NOTES
- * if the path closed with '\', *lastpart is 0
- */
-DWORD WINAPI GetFullPathNameA( LPCSTR name, DWORD len, LPSTR buffer,
- LPSTR *lastpart )
-{
- UNICODE_STRING nameW;
- WCHAR bufferW[MAX_PATH];
- DWORD ret, retW;
-
- if (!name)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- if (!RtlCreateUnicodeStringFromAsciiz(&nameW, name))
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return 0;
- }
-
- retW = GetFullPathNameW( nameW.Buffer, MAX_PATH, bufferW, NULL);
-
- if (!retW)
- ret = 0;
- else if (retW > MAX_PATH)
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- ret = 0;
- }
- else
- {
- ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
- if (ret <= len)
- {
- WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, len, NULL, NULL);
- ret--; /* length without 0 */
-
- if (lastpart)
- {
- LPSTR p = buffer + strlen(buffer);
-
- if (*p != '\\')
- {
- while ((p > buffer + 2) && (*p != '\\')) p--;
- *lastpart = p + 1;
- }
- else *lastpart = NULL;
- }
- }
- }
-
- RtlFreeUnicodeString(&nameW);
- return ret;
-}
-
-
-/***********************************************************************
- * GetFullPathNameW (KERNEL32.@)
- */
-DWORD WINAPI GetFullPathNameW( LPCWSTR name, DWORD len, LPWSTR buffer,
- LPWSTR *lastpart )
-{
- DWORD ret = DOSFS_DoGetFullPathName( name, len, buffer );
- if (ret && (ret<=len) && buffer && lastpart)
- {
- LPWSTR p = buffer + strlenW(buffer);
- if (*p != (WCHAR)'\\')
- {
- while ((p > buffer + 2) && (*p != (WCHAR)'\\')) p--;
- *lastpart = p + 1;
- }
- else *lastpart = NULL;
- }
- return ret;
-}
-
-
-/***********************************************************************
* wine_get_unix_file_name (KERNEL32.@) Not a Windows API
*
* Return the full Unix file name for a given path.