Try2 msi: Correct the setting of environment variables

Jason Edmeades jason.edmeades at googlemail.com
Wed Jan 20 03:49:08 CST 2010


Same fix as earlier patch but with corrected test results (last patch
had one more result than test as I removed a test which did not add
benefit for now)

Jason
-------------- next part --------------
From d12a162f7f5de0d9cbee78d41e36b59a5db8ef82 Mon Sep 17 00:00:00 2001
From: Jason Edmeades <us at edmeades.me.uk>
Date: Wed, 20 Jan 2010 09:40:37 +0000
Subject: [PATCH] Try2 msi: Correct the setting of environment variables

Contrary to the MSDN, you can 'create only' whilst using a previous value
(ie +-variable and [~];value). This breaks the install of an application
I was debugging who uses that throughout for all their variables. In
addition whilst adding some tests I've also cleaned up invalid prefix
syntax handling and semicolon removal if the original string is empty.
---
 dlls/msi/action.c        |   36 ++++++++++++++++++++++--------
 dlls/msi/tests/install.c |   53 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 50f2007..fef8eae 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -4924,16 +4924,30 @@ static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
         LPCWSTR ptr = *value;
         if (!strncmpW(ptr, prefix, prefix_len))
         {
-            *flags |= ENV_MOD_APPEND;
-            *value += lstrlenW(prefix);
+            if (ptr[prefix_len] == szSemiColon[0])
+            {
+                *flags |= ENV_MOD_APPEND;
+                *value += lstrlenW(prefix);
+            }
+            else
+            {
+                *value = NULL;
+            }
         }
         else if (lstrlenW(*value) >= prefix_len)
         {
             ptr += lstrlenW(ptr) - prefix_len;
             if (!lstrcmpW(ptr, prefix))
             {
-                *flags |= ENV_MOD_PREFIX;
-                /* the "[~]" will be removed by deformat_string */;
+                if ((ptr-1) > *value && *(ptr-1) == szSemiColon[0])
+                {
+                    *flags |= ENV_MOD_PREFIX;
+                    /* the "[~]" will be removed by deformat_string */;
+                }
+                else
+                {
+                    *value = NULL;
+                }
             }
         }
     }
@@ -4979,7 +4993,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
     TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value));
 
     res = env_set_flags(&name, &value, &flags);
-    if (res != ERROR_SUCCESS)
+    if (res != ERROR_SUCCESS || !value)
        goto done;
 
     if (value && !deformat_string(package, value, &deformatted))
@@ -5025,6 +5039,9 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
             goto done;
         }
 
+        /* If we are appending but the string was empty, strip ; */
+        if ((flags & ENV_MOD_APPEND) && (value[0] == szSemiColon[0])) value++;
+
         size = (lstrlenW(value) + 1) * sizeof(WCHAR);
         newval = strdupW(value);
         if (!newval)
@@ -5035,7 +5052,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
     }
     else
     {
-        if (flags & ENV_ACT_SETABSENT)
+        /* Contrary to MSDN, +-variable to [~];path works */
+        if (flags & ENV_ACT_SETABSENT && !(flags & ENV_MOD_MASK))
         {
             res = ERROR_SUCCESS;
             goto done;
@@ -5065,7 +5083,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
             int multiplier = 0;
             if (flags & ENV_MOD_APPEND) multiplier++;
             if (flags & ENV_MOD_PREFIX) multiplier++;
-            mod_size = (lstrlenW(value) + 1) * multiplier;
+            mod_size = lstrlenW(value) * multiplier;
             size += mod_size * sizeof(WCHAR);
         }
 
@@ -5080,15 +5098,13 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
         if (flags & ENV_MOD_PREFIX)
         {
             lstrcpyW(newval, value);
-            lstrcatW(newval, szSemiColon);
-            ptr = newval + lstrlenW(value) + 1;
+            ptr = newval + lstrlenW(value);
         }
 
         lstrcpyW(ptr, data);
 
         if (flags & ENV_MOD_APPEND)
         {
-            lstrcatW(newval, szSemiColon);
             lstrcatW(newval, value);
         }
     }
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c
index c1e0afc..701192b 100644
--- a/dlls/msi/tests/install.c
+++ b/dlls/msi/tests/install.c
@@ -226,7 +226,36 @@ static const CHAR environment_dat[] = "Environment\tName\tValue\tComponent_\n"
                                       "Var7\t!-MSITESTVAR7\t\tOne\n"
                                       "Var8\t!-*MSITESTVAR8\t\tOne\n"
                                       "Var9\t=-MSITESTVAR9\t\tOne\n"
-                                      "Var10\t=MSITESTVAR10\t\tOne\n";
+                                      "Var10\t=MSITESTVAR10\t\tOne\n"
+                                      "Var11\t+-MSITESTVAR11\t[~];1\tOne\n"
+                                      "Var12\t+-MSITESTVAR11\t[~];2\tOne\n"
+                                      "Var13\t+-MSITESTVAR12\t[~];1\tOne\n"
+                                      "Var14\t=MSITESTVAR13\t[~];1\tOne\n"
+                                      "Var15\t=MSITESTVAR13\t[~];2\tOne\n"
+                                      "Var16\t=MSITESTVAR14\t;1;\tOne\n"
+                                      "Var17\t=MSITESTVAR15\t;;1;;\tOne\n"
+                                      "Var18\t=MSITESTVAR16\t 1 \tOne\n"
+                                      "Var19\t+-MSITESTVAR17\t1\tOne\n"
+                                      "Var20\t+-MSITESTVAR17\t;;2;;[~]\tOne\n"
+                                      "Var21\t+-MSITESTVAR18\t1\tOne\n"
+                                      "Var22\t+-MSITESTVAR18\t[~];;2;;\tOne\n"
+                                      "Var23\t+-MSITESTVAR19\t1\tOne\n"
+                                      "Var24\t+-MSITESTVAR19\t[~]2\tOne\n"
+                                      "Var25\t+-MSITESTVAR20\t1\tOne\n"
+                                      "Var26\t+-MSITESTVAR20\t2[~]\tOne\n";
+
+/* Expected results, starting from MSITESTVAR11 onwards */
+static const CHAR *environment_dat_results[] = {"1;2",    /*MSITESTVAR11*/
+                                                "1",      /*MSITESTVAR12*/
+                                                "1;2",    /*MSITESTVAR13*/
+                                                ";1;",    /*MSITESTVAR14*/
+                                                ";;1;;",  /*MSITESTVAR15*/
+                                                " 1 ",    /*MSITESTVAR16*/
+                                                ";;2;;1", /*MSITESTVAR17*/
+                                                "1;;2;;", /*MSITESTVAR18*/
+                                                "1",      /*MSITESTVAR19*/
+                                                "1",      /*MSITESTVAR20*/
+                                                NULL};
 
 static const CHAR condition_dat[] = "Feature_\tLevel\tCondition\n"
                                     "s38\ti2\tS255\n"
@@ -6732,6 +6761,7 @@ static void test_envvar(void)
     LONG res;
     DWORD type, size;
     char buffer[16];
+    UINT i;
 
     if (on_win9x)
     {
@@ -6800,8 +6830,27 @@ static void test_envvar(void)
     res = RegDeleteValueA(env, "MSITESTVAR10");
     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
 
-    RegCloseKey(env);
+    i = 11;
+    while (environment_dat_results[(i-11)]) {
+        char name[20];
+        sprintf(name, "MSITESTVAR%d", i);
+
+        type = REG_NONE;
+        size = sizeof(buffer);
+        buffer[0] = 0;
+        res = RegQueryValueExA(env, name, NULL, &type, (LPBYTE)buffer, &size);
+        ok(res == ERROR_SUCCESS, "%d: Expected ERROR_SUCCESS, got %d\n", i, res);
+        ok(type == REG_SZ, "%d: Expected REG_SZ, got %u\n", i, type);
+        ok(!lstrcmp(buffer, environment_dat_results[(i-11)]), "%d: Expected %s, got %s\n",
+           i, environment_dat_results[(i-11)], buffer);
+
+        res = RegDeleteValueA(env, name);
+        ok(res == ERROR_SUCCESS, "%d: Expected ERROR_SUCCESS, got %d\n", i, res);
+        i++;
+    }
 
+
+    RegCloseKey(env);
     delete_pf("msitest\\cabout\\new\\five.txt", TRUE);
     delete_pf("msitest\\cabout\\new", FALSE);
     delete_pf("msitest\\cabout\\four.txt", TRUE);
-- 
1.6.3.3



More information about the wine-patches mailing list