Hi,

I have written a patch to add basic UNC pathname support which tries
to handle UNC pathnames according to the MSDN spec.

The patch satisfies some of the UNC pathname tests for GetLongPathNameA,
but is actually intended to fix GetLongPathNameW.

I am not entirely satisfied with the patch, and would appreciate some
comments.

Some issues:

1) Paths prefixed by '\\?\' require GetLongPathName to handle
strings of length 32767. I don't like the fact that the patch creates two
such large strings on the local stack, should the memory be dynamically
allocated only when needed?

2) The handling of shares \\hostname\C$ is implemented, but no other
shares are handled. And even in this case, only the host on which wine
is executed is handled, no other hosts are handled. I have read that
Windows 7 disables this share by default. So should wine be handling this
particular URL, or should more general sharing be implemented?

The patch is included as an attachment to this message.

Kind regards
Alexandre


-- 
--------------------------------------------------
Alexandre Hardy
http://www.ahardy.za.net
From b013419f366c83248704f444cbbb6976df740fc9 Mon Sep 17 00:00:00 2001
From: Alexandre Hardy <alexandre.ha...@gmail.com>
Date: Fri, 11 Dec 2009 09:49:59 +0200
Subject: Add partial UNC pathname support

---
 dlls/kernel32/path.c       |   54 +++++++++++++++++++++++++++++++++++++++++--
 dlls/kernel32/tests/path.c |    4 ---
 2 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index e9463bb..54d9403 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -44,6 +44,7 @@
 WINE_DEFAULT_DEBUG_CHANNEL(file);
 
 #define MAX_PATHNAME_LEN        1024
+#define MAX_LONGPATHNAME_LEN    32767
 
 
 /* check if a file name is for an executable file (.exe or .com) */
@@ -290,19 +291,29 @@ DWORD WINAPI GetFullPathNameA( LPCSTR name, DWORD len, LPSTR buffer,
  */
 DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen )
 {
-    WCHAR               tmplongpath[MAX_PATHNAME_LEN];
+    WCHAR               tmplongpath[MAX_LONGPATHNAME_LEN];
+    WCHAR               sharename[MAX_LONGPATHNAME_LEN];
     LPCWSTR             p;
     DWORD               sp = 0, lp = 0;
     DWORD               tmplen;
+    DWORD               hostlen;
     BOOL                unixabsolute;
     WIN32_FIND_DATAW    wfd;
     HANDLE              goit;
+    WCHAR               cdollar[4] = { '\\', 'C', '$', 0 };
+    WCHAR               c_colon[3] = { 'C', ':', 0 };
+    BOOL                ret;
 
     if (!shortpath)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return 0;
     }
+    if (!longpath && longlen)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
     if (!shortpath[0])
     {
         SetLastError(ERROR_PATH_NOT_FOUND);
@@ -314,8 +325,45 @@ DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen
     if (shortpath[0] == '\\' && shortpath[1] == '\\')
     {
         ERR("UNC pathname %s\n", debugstr_w(shortpath));
-        lstrcpynW( longpath, shortpath, longlen );
-        return strlenW(longpath);
+ 
+        /* Handle extended length path */
+        if (shortpath[2] == '?' && shortpath[3] == '\\') {
+            tmplen = GetLongPathNameW(shortpath + 4, tmplongpath, MAX_LONGPATHNAME_LEN);
+            if (tmplen + 5 <= longlen) {
+                lstrcpynW(longpath, shortpath, 5);
+                lstrcatW(longpath, tmplongpath);
+                return tmplen + 4;
+            } else 
+                return tmplen + 5;
+        }
+
+        /* Handle only our host name\C$ for network shares*/
+        hostlen = MAX_COMPUTERNAME_LENGTH + 1;
+        ret = GetComputerNameW(sharename, &hostlen);
+        if (ret) {
+            lstrcatW(sharename, cdollar);
+            if (strncmpW(sharename, shortpath + 2, hostlen + 3) == 0) {
+                lstrcpyW(sharename, c_colon);
+                lstrcatW(sharename, shortpath + 5 + hostlen);
+                tmplen = GetLongPathNameW(sharename, tmplongpath, MAX_LONGPATHNAME_LEN);
+                if (tmplen + hostlen + 4 <= longlen) {
+                    lstrcpynW(longpath, shortpath, hostlen + 4);
+                    lstrcatW(longpath, tmplongpath);
+                    longpath[hostlen + 4] = '$';
+                    return tmplen + hostlen + 2;
+                } else 
+                    return tmplen + hostlen + 3;
+            }
+        }
+
+        /* Can't handle shares at the moment, just copy the filename
+         * But only if there is enough space in the buffer */
+        tmplen = strlenW(shortpath);
+        if (longlen >= tmplen + 1) {
+            lstrcpynW( longpath, shortpath, longlen );
+            return tmplen;
+        }
+        return tmplen + 1;
     }
 
     unixabsolute = (shortpath[0] == '/');
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c
index 104a48c..86207ce 100644
--- a/dlls/kernel32/tests/path.c
+++ b/dlls/kernel32/tests/path.c
@@ -1036,17 +1036,14 @@ static void test_GetLongPathNameA(void)
         return;
     }
     explength = lstrlenA(longpath) + 1;
-    todo_wine
     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
 
     length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
-    todo_wine
     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
 
     memset(unc_long, 0, MAX_PATH);
     length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
     /* length will include terminating '0' on failure */
-    todo_wine
     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
     ok(unc_long[0] == 0, "Buffer should not have been touched\n");
 
@@ -1054,7 +1051,6 @@ static void test_GetLongPathNameA(void)
     length = pGetLongPathNameA(unc_short, unc_long, length);
     /* length doesn't include terminating '0' on success */
     explength--;
-    todo_wine
     {
     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
     ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
-- 
1.6.2.1



Reply via email to