From f22bea0a7600a5a7fb36f7d12dcc30b9c72511f5 Mon Sep 17 00:00:00 2001
From: Peter Ganten <ganten@uni-bremen.de>
Date: Sun, 14 Mar 1999 15:15:14 +0000
Subject: [PATCH] Better implementation of GetShortPathNameA/W.

---
 files/dos_fs.c | 129 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 91 insertions(+), 38 deletions(-)

diff --git a/files/dos_fs.c b/files/dos_fs.c
index 9572a485483..1e3087f51a3 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -870,38 +870,105 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
 
 
 /***********************************************************************
- *           GetShortPathName32A   (KERNEL32.271)
+ *           GetShortPathNameA   (KERNEL32.271)
  *
  * 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 in the 
+ *    same way, like the long name
+ * - longpath and shortpath may have the same adress
+ * Peter Ganten, 1999
  */
 DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath,
                                   DWORD shortlen )
 {
     DOS_FULL_NAME full_name;
-    
-    if (!longpath)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return 0;
+    LPSTR tmpshortpath;
+    DWORD length = 0, pos = 0;
+    INT start=-1, end=-1, tmplen;
+
+    if (!longpath) {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return 0;
+    }
+    if (!longpath[0]) {
+      SetLastError(ERROR_BAD_PATHNAME);
+      return 0;
     }
 
-    if (!longpath[0])
-    {
-        SetLastError(ERROR_BAD_PATHNAME);
-        return 0;
+    tmpshortpath = HeapAlloc( GetProcessHeap(), 0, MAX_PATHNAME_LEN );
+    if ( !tmpshortpath ) {
+      SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+      return 0;
     }
 
-    /* FIXME: is it correct to always return a fully qualified short path? */
-    if (!DOSFS_GetFullName( longpath, TRUE, &full_name )) 
-    {
-        SetLastError(ERROR_BAD_PATHNAME);
-        return 0;
+    /* Check for Drive-Letter */
+    if ( longpath[1] == ':' ) {
+      lstrcpynA ( tmpshortpath, longpath, 3 );
+      length = 2;
+      pos = 2;
+    }
+
+    /* loop over each part of the name */
+    while ( longpath[pos] ) {
+
+      if (( longpath[pos] == '\\' ) || 
+	  ( longpath[pos+1] == '\0' ) ||
+	  ( longpath[pos] == '/')) {
+
+	if ( start != -1 ) {
+	  if ( DOSFS_ValidDOSName ( longpath + start, TRUE )) {
+	    tmplen = end - start + ( (( longpath[pos] == '\\' ) || ( longpath[pos] == '/' )) ? 1 : 2 );
+	    lstrcpynA ( tmpshortpath+length, longpath+start, tmplen );
+	    length += tmplen - 1;
+	  }
+	  else {
+	    DOSFS_Hash ( longpath + start, tmpshortpath+length, FALSE, FALSE );
+	    length = lstrlenA ( tmpshortpath );
+
+	    /* Check if the path, up to this point exists */
+	    if ( !DOSFS_GetFullName ( tmpshortpath, TRUE, &full_name ) ) {
+	      SetLastError ( ERROR_FILE_NOT_FOUND );
+	      return 0;
+	    }
+
+	  }
+	}
+
+	if (( longpath[pos] == '\\' ) || ( longpath[pos] == '/' )) {
+	  tmpshortpath[length] = '\\';
+	  tmpshortpath[length+1]='\0';
+	  length++;
+	}
+	pos++;
+	
+	start = -1;
+	end = -1;
+	continue;
+      }
+
+      if ( start == -1 ) {
+	start = pos;
+      }
+      pos++;
+      end = pos;
     }
-    lstrcpynA( shortpath, full_name.short_name, shortlen );
-    return strlen( full_name.short_name );
+    
+    lstrcpynA ( shortpath, tmpshortpath, shortlen );
+    length = lstrlenA ( tmpshortpath );
+    HeapFree ( GetProcessHeap(), 0, tmpshortpath );
+    
+    return length;
 }
 
 
@@ -911,33 +978,19 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath,
 DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath,
                                   DWORD shortlen )
 {
-    DOS_FULL_NAME full_name;
-    LPSTR longpathA ;
+    LPSTR longpathA, shortpathA;
     DWORD ret = 0;
 
-    if (!longpath)
-    { SetLastError(ERROR_INVALID_PARAMETER);
-      return 0;
-    }
-
-    if (!longpath[0])
-    { SetLastError(ERROR_BAD_PATHNAME);
-      return 0;
-    }
-
-
     longpathA = HEAP_strdupWtoA( GetProcessHeap(), 0, longpath );
+    shortpathA = HEAP_xalloc ( GetProcessHeap(), 0, shortlen );
 
-    /* FIXME: is it correct to always return a fully qualified short path? */
-    if (DOSFS_GetFullName( longpathA, TRUE, &full_name ))
-    {
-        ret = strlen( full_name.short_name );
-        lstrcpynAtoW( shortpath, full_name.short_name, shortlen );
-    }
+    ret = GetShortPathNameA ( longpathA, shortpathA, shortlen );
+    lstrcpynAtoW ( shortpath, shortpathA, shortlen );
 
-    SetLastError(ERROR_BAD_PATHNAME);
     HeapFree( GetProcessHeap(), 0, longpathA );
-    return 0;
+    HeapFree( GetProcessHeap(), 0, shortpathA );
+
+    return ret;
 }
 
 
-- 
GitLab