kernel32: GetShortPathNameW should accept paths starting with "\\?\".

Rein Klazes wijn at online.nl
Thu Aug 6 06:02:19 CDT 2009


Makes ConvertXtoDVD in bug#17479 proceed a little further.
---
 dlls/kernel32/path.c       |   32 +++++++++++++++++++++++++++-----
 dlls/kernel32/tests/path.c |    7 +++++++
 2 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index 299db1c..47f3168 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -429,6 +429,7 @@ DWORD WINAPI GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen )
  */
 DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortlen )
 {
+    static const WCHAR  LongFileNamePfxW[4] = {'\\','\\','?','\\'};
     WCHAR               tmpshortpath[MAX_PATHNAME_LEN];
     LPCWSTR             p;
     DWORD               sp = 0, lp = 0;
@@ -451,19 +452,27 @@ DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortl
         return 0;
     }
 
+    /* skip "\\?\" */
+    if( !strncmpW( longpath, LongFileNamePfxW, 4))
+    {
+        memcpy( tmpshortpath, longpath, 4 * sizeof(WCHAR));
+        sp = 4;
+        lp = 4;
+    }
+
     /* check for drive letter */
-    if (longpath[0] != '/' && longpath[1] == ':' )
+    if (longpath[lp] != '/' && longpath[lp+1] == ':' )
     {
-        tmpshortpath[0] = longpath[0];
-        tmpshortpath[1] = ':';
-        sp = lp = 2;
+        tmpshortpath[sp++] = longpath[lp];
+        tmpshortpath[sp++] = ':';
+        lp += 2;
     }
 
     ustr.Buffer = ustr_buf;
     ustr.Length = 0;
     ustr.MaximumLength = sizeof(ustr_buf);
 
-    while (longpath[lp])
+    while (longpath[lp] && sp < MAX_PATHNAME_LEN)
     {
         /* check for path delimiters and reproduce them */
         if (longpath[lp] == '\\' || longpath[lp] == '/')
@@ -473,6 +482,7 @@ DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortl
                 /* strip double "\\" */
                 tmpshortpath[sp] = '\\';
                 sp++;
+                if( sp >= MAX_PATHNAME_LEN) continue;
             }
             tmpshortpath[sp] = 0; /* terminate string */
             lp++;
@@ -481,6 +491,12 @@ DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortl
 
         for (p = longpath + lp; *p && *p != '/' && *p != '\\'; p++);
         tmplen = p - (longpath + lp);
+        /* is there enough space for what we are trying to do ? */
+        if( sp + tmplen + 1 >= MAX_PATHNAME_LEN)
+        {
+            sp =  MAX_PATHNAME_LEN;
+            continue;
+        }
         lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
         /* Check, if the current element is a valid dos name */
         if (tmplen <= 8+1+3)
@@ -505,6 +521,12 @@ DWORD WINAPI GetShortPathNameW( LPCWSTR longpath, LPWSTR shortpath, DWORD shortl
         sp += strlenW(tmpshortpath + sp);
         lp += tmplen;
     }
+
+    if( sp >= MAX_PATHNAME_LEN) {
+        ERR("Insufficient space in internal buffer!\n");
+        return 0;
+    }
+
     tmpshortpath[sp] = 0;
 
     tmplen = strlenW(tmpshortpath) + 1;
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c
index de26fc9..585ce73 100644
--- a/dlls/kernel32/tests/path.c
+++ b/dlls/kernel32/tests/path.c
@@ -982,6 +982,7 @@ static void test_GetShortPathNameW(void)
 {
     WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e',  0 };
     WCHAR path[MAX_PATH];
+    WCHAR pathex[MAX_PATH] = { '\\', '\\', '?', '\\', 0};
     WCHAR short_path[MAX_PATH];
     DWORD length;
     HANDLE file;
@@ -1001,6 +1002,7 @@ static void test_GetShortPathNameW(void)
     lstrcatW( path, backSlash );
     ret = CreateDirectoryW( path, NULL );
     ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
+    lstrcatW( pathex, path);
 
     /* Starting a main part of test */
     length = GetShortPathNameW( path, short_path, 0 );
@@ -1010,6 +1012,11 @@ static void test_GetShortPathNameW(void)
     lstrcatW( short_path, name );
     file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
     ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
+    /* test with the path starting with \\?\ */
+    length = GetShortPathNameW( pathex, short_path, MAX_PATH );
+    ok( length, "GetShortPathNameW returned 0.\n" );
+    ok( !wcsncmp( pathex, short_path, 4), "Short path should begin with \"\\\\?\\\"\n");
+    lstrcatW( short_path, name );
 
     /* End test */
     CloseHandle( file );
-- 
1.6.3.3




More information about the wine-patches mailing list