Bruno Jesus : kernel32: In GetTempPathW only copy the path if it fits and zero the buffer when it doesn 't.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Mar 5 09:53:25 CST 2015


Module: wine
Branch: master
Commit: 81598be9cf1299a2a101e43ceca8d463c2c675e2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=81598be9cf1299a2a101e43ceca8d463c2c675e2

Author: Bruno Jesus <00cpxxx at gmail.com>
Date:   Thu Mar  5 02:33:33 2015 -0300

kernel32: In GetTempPathW only copy the path if it fits and zero the buffer when it doesn't.

---

 dlls/kernel32/path.c       | 20 ++++++++++----------
 dlls/kernel32/tests/path.c | 39 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index 1048214..4cc8c1d 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -621,17 +621,17 @@ DWORD WINAPI GetTempPathW( DWORD count, LPWSTR path )
 
     ret++; /* add space for terminating 0 */
 
-    if (count)
+    if (count >= ret)
     {
-        lstrcpynW(path, tmp_path, ret);
-        if (count >= ret)
-        {
-            /* the remaining buffer must be zeroed */
-            memset(path + ret, 0, (count - ret) * sizeof(WCHAR));
-            ret--; /* return length without 0 */
-        }
-        else if (count < 4)
-            path[0] = 0; /* avoid returning ambiguous "X:" */
+        lstrcpynW(path, tmp_path, count);
+        /* the remaining buffer must be zeroed */
+        memset(path + ret, 0, (count - ret) * sizeof(WCHAR));
+        ret--; /* return length without 0 */
+    }
+    else if (count)
+    {
+        /* the buffer must be cleared if contents will not fit */
+        memset(path, 0, count * sizeof(WCHAR));
     }
 
     TRACE("returning %u, %s\n", ret, debugstr_w(path));
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c
index a5c0f41..e97c50c 100644
--- a/dlls/kernel32/tests/path.c
+++ b/dlls/kernel32/tests/path.c
@@ -922,7 +922,7 @@ static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
 
 static void test_GetTempPathA(char* tmp_dir)
 {
-    DWORD len, len_with_null;
+    DWORD len, slen, len_with_null;
     char buf[MAX_PATH];
 
     len_with_null = strlen(tmp_dir) + 1;
@@ -959,13 +959,22 @@ static void test_GetTempPathA(char* tmp_dir)
     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
     /* The rest of the buffer remains untouched */
+    slen = len + 1;
     for(len++; len < sizeof(buf); len++)
         ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
+
+    /* When the buffer is not long enough it remains untouched */
+    memset(buf, 'a', sizeof(buf));
+    len = GetTempPathA(slen / 2, buf);
+    ok(len == slen || broken(len == slen + 1) /* read the big comment above */ ,
+       "expected %d, got %d\n", slen, len);
+    for(len = 0; len < sizeof(buf) / sizeof(buf[0]); len++)
+        ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
 }
 
 static void test_GetTempPathW(char* tmp_dir)
 {
-    DWORD len, len_with_null;
+    DWORD len, slen, len_with_null;
     WCHAR buf[MAX_PATH];
     WCHAR tmp_dirW[MAX_PATH];
     static const WCHAR fooW[] = {'f','o','o',0};
@@ -1011,8 +1020,34 @@ static void test_GetTempPathW(char* tmp_dir)
     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
     /* The rest of the buffer must be zeroed */
+    slen = len + 1;
     for(len++; len < sizeof(buf) / sizeof(buf[0]); len++)
         ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]);
+
+    /* When the buffer is not long enough the length passed is zeroed */
+    for(len = 0; len < sizeof(buf) / sizeof(buf[0]); len++)
+        buf[len] = 'a';
+    len = GetTempPathW(slen / 2, buf);
+    ok(len == slen || broken(len == slen + 1) /* read the big comment above */ ,
+       "expected %d, got %d\n", slen, len);
+
+    {
+        /* In Windows 8 when TMP var points to a drive only (like C:) instead of a
+        * full directory the behavior changes. It will start filling the path but
+        * will later truncate the buffer before returning. So the generic test
+        * below will fail for this Windows 8 corner case.
+        */
+        char tmp_var[64];
+        DWORD version = GetVersion();
+        GetEnvironmentVariableA("TMP", tmp_var, sizeof(tmp_var));
+        if (strlen(tmp_var) == 2 && version >= 0x00060002)
+            return;
+    }
+
+    for(len = 0; len < slen / 2; len++)
+        ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]);
+    for(; len < sizeof(buf) / sizeof(buf[0]); len++)
+        ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
 }
 
 static void test_GetTempPath(void)




More information about the wine-cvs mailing list