Hans Leidekker : msi: Only remove environment strings that were added on install.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Aug 18 09:22:16 CDT 2015


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Aug 18 10:21:29 2015 +0200

msi: Only remove environment strings that were added on install.

---

 dlls/msi/action.c       | 63 ++++++++++++++++++++++++++++++++++++++-----
 dlls/msi/tests/action.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 126 insertions(+), 8 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index c0ab23d..0fe7d38 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -7103,8 +7103,8 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
 {
     MSIPACKAGE *package = param;
     LPCWSTR name, value, component;
-    LPWSTR deformatted = NULL;
-    DWORD flags;
+    WCHAR *p, *q, *deformatted = NULL, *new_value = NULL;
+    DWORD flags, type, size, len, len_value = 0, len_new_value;
     HKEY env;
     MSICOMPONENT *comp;
     MSIRECORD *uirow;
@@ -7141,7 +7141,20 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
     if (value && !deformat_string( package, value, &deformatted ))
         return ERROR_OUTOFMEMORY;
 
-    value = deformatted;
+    if ((value = deformatted))
+    {
+        if (flags & ENV_MOD_PREFIX)
+        {
+            p = strchrW( value, ';' );
+            len_value = p - value;
+        }
+        else if (flags & ENV_MOD_APPEND)
+        {
+            value = strchrW( value, ';' ) + 1;
+            len_value = strlenW( value );
+        }
+        else len_value = strlenW( value );
+    }
 
     r = open_env_key( flags, &env );
     if (r != ERROR_SUCCESS)
@@ -7153,13 +7166,48 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
     if (flags & ENV_MOD_MACHINE)
         action |= 0x20000000;
 
-    TRACE("Removing %s\n", debugstr_w(name));
+    size = 0;
+    type = REG_SZ;
+    res = RegQueryValueExW( env, name, NULL, &type, NULL, &size );
+    if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
+        goto done;
+
+    if (!(new_value = msi_alloc( size ))) goto done;
 
-    res = RegDeleteValueW( env, name );
+    res = RegQueryValueExW( env, name, NULL, &type, (BYTE *)new_value, &size );
     if (res != ERROR_SUCCESS)
+        goto done;
+
+    len_new_value = size / sizeof(WCHAR) - 1;
+    p = q = new_value;
+    for (;;)
     {
-        WARN("Failed to delete value %s (%d)\n", debugstr_w(name), res);
-        r = ERROR_SUCCESS;
+        while (*q && *q != ';') q++;
+        len = q - p;
+        if (value && len == len_value && !memcmp( value, p, len * sizeof(WCHAR) ))
+        {
+            if (*q == ';') q++;
+            memmove( p, q, (len_new_value - (q - new_value) + 1) * sizeof(WCHAR) );
+            break;
+        }
+        if (!*q) break;
+        p = ++q;
+    }
+
+    if (!new_value[0] || !value)
+    {
+        TRACE("removing %s\n", debugstr_w(name));
+        res = RegDeleteValueW( env, name );
+        if (res != ERROR_SUCCESS)
+            WARN("failed to delete value %s (%d)\n", debugstr_w(name), res);
+    }
+    else
+    {
+        TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(new_value));
+        size = (strlenW( new_value ) + 1) * sizeof(WCHAR);
+        res = RegSetValueExW( env, name, 0, type, (BYTE *)new_value, size );
+        if (res != ERROR_SUCCESS)
+            WARN("failed to set %s to %s (%d)\n", debugstr_w(name), debugstr_w(new_value), res);
     }
 
 done:
@@ -7172,6 +7220,7 @@ done:
 
     if (env) RegCloseKey( env );
     msi_free( deformatted );
+    msi_free( new_value );
     return r;
 }
 
diff --git a/dlls/msi/tests/action.c b/dlls/msi/tests/action.c
index 60562f1..9512410 100644
--- a/dlls/msi/tests/action.c
+++ b/dlls/msi/tests/action.c
@@ -1205,7 +1205,13 @@ static const char res_environment_dat[] =
     "var2\t=+-MSITESTVAR2\t1\tenvvar\n"
     "var3\t=MSITESTVAR3\t1\tenvvar\n"
     "var4\t=-MSITESTVAR4\t\tenvvar\n"
-    "var5\t=MSITESTVAR5\t\tenvvar\n";
+    "var5\t=MSITESTVAR5\t\tenvvar\n"
+    "Var6\t-MSITESTVAR6\t1;[~]\tenvvar\n"
+    "Var7\t-MSITESTVAR7\t[~];1\tenvvar\n"
+    "Var8\t-MSITESTVAR8\t1;[~]\tenvvar\n"
+    "Var9\t-MSITESTVAR9\t[~];1\tenvvar\n"
+    "Var10\t-MSITESTVAR10\t1\tenvvar\n"
+    "Var11\t-MSITESTVAR11\t2\tenvvar\n";
 
 static const char res_install_exec_seq_dat[] =
     "Action\tCondition\tSequence\n"
@@ -6192,6 +6198,12 @@ static void test_remove_env_strings(void)
     RegSetValueExA(key, "MSITESTVAR3", 0, REG_SZ, (const BYTE *)"1", 2);
     RegSetValueExA(key, "MSITESTVAR4", 0, REG_SZ, (const BYTE *)"1", 2);
     RegSetValueExA(key, "MSITESTVAR5", 0, REG_SZ, (const BYTE *)"1", 2);
+    RegSetValueExA(key, "MSITESTVAR6", 0, REG_SZ, (const BYTE *)"1;2", 4);
+    RegSetValueExA(key, "MSITESTVAR7", 0, REG_SZ, (const BYTE *)"1;2", 4);
+    RegSetValueExA(key, "MSITESTVAR8", 0, REG_SZ, (const BYTE *)"2;1;0", 6);
+    RegSetValueExA(key, "MSITESTVAR9", 0, REG_SZ, (const BYTE *)"0;1;2", 6);
+    RegSetValueExA(key, "MSITESTVAR10", 0, REG_SZ, (const BYTE *)"1", 2);
+    RegSetValueExA(key, "MSITESTVAR11", 0, REG_SZ, (const BYTE *)"1", 2);
 
     RegCloseKey(key);
 
@@ -6281,6 +6293,57 @@ static void test_remove_env_strings(void)
     ok(!lstrcmpA(buffer, "1"), "expected \"1\", got \"%s\"\n", buffer);
     RegDeleteValueA(key, "MSITESTVAR5");
 
+    type = REG_NONE;
+    buffer[0] = 0;
+    size = sizeof(buffer);
+    res = RegQueryValueExA(key, "MSITESTVAR6", NULL, &type, (LPBYTE)buffer, &size);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+    ok(type == REG_SZ, "expected REG_SZ, got %u\n", type);
+    ok(!lstrcmpA(buffer, "2"), "expected \"2\", got \"%s\"\n", buffer);
+    RegDeleteValueA(key, "MSITESTVAR6");
+
+    type = REG_NONE;
+    buffer[0] = 0;
+    size = sizeof(buffer);
+    res = RegQueryValueExA(key, "MSITESTVAR7", NULL, &type, (LPBYTE)buffer, &size);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+    ok(type == REG_SZ, "expected REG_SZ, got %u\n", type);
+    ok(!lstrcmpA(buffer, "2"), "expected \"2\", got \"%s\"\n", buffer);
+    RegDeleteValueA(key, "MSITESTVAR7");
+
+    type = REG_NONE;
+    buffer[0] = 0;
+    size = sizeof(buffer);
+    res = RegQueryValueExA(key, "MSITESTVAR8", NULL, &type, (LPBYTE)buffer, &size);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+    ok(type == REG_SZ, "expected REG_SZ, got %u\n", type);
+    ok(!lstrcmpA(buffer, "2;0"), "expected \"2;0\", got \"%s\"\n", buffer);
+    RegDeleteValueA(key, "MSITESTVAR8");
+
+    type = REG_NONE;
+    buffer[0] = 0;
+    size = sizeof(buffer);
+    res = RegQueryValueExA(key, "MSITESTVAR9", NULL, &type, (LPBYTE)buffer, &size);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+    ok(type == REG_SZ, "expected REG_SZ, got %u\n", type);
+    ok(!lstrcmpA(buffer, "0;2"), "expected \"0;2\", got \"%s\"\n", buffer);
+    RegDeleteValueA(key, "MSITESTVAR9");
+
+    type = REG_NONE;
+    buffer[0] = 0;
+    size = sizeof(buffer);
+    res = RegQueryValueExA(key, "MSITESTVAR10", NULL, &type, (LPBYTE)buffer, &size);
+    ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
+
+    type = REG_NONE;
+    buffer[0] = 0;
+    size = sizeof(buffer);
+    res = RegQueryValueExA(key, "MSITESTVAR11", NULL, &type, (LPBYTE)buffer, &size);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+    ok(type == REG_SZ, "expected REG_SZ, got %u\n", type);
+    ok(!lstrcmpA(buffer, "1"), "expected \"1\", got \"%s\"\n", buffer);
+    RegDeleteValueA(key, "MSITESTVAR11");
+
     ok(!delete_pf("msitest\\envvar.txt", TRUE), "file not removed\n");
     ok(!delete_pf("msitest", FALSE), "directory not removed\n");
 
@@ -6290,6 +6353,12 @@ error:
     RegDeleteValueA(key, "MSITESTVAR3");
     RegDeleteValueA(key, "MSITESTVAR4");
     RegDeleteValueA(key, "MSITESTVAR5");
+    RegDeleteValueA(key, "MSITESTVAR6");
+    RegDeleteValueA(key, "MSITESTVAR7");
+    RegDeleteValueA(key, "MSITESTVAR8");
+    RegDeleteValueA(key, "MSITESTVAR9");
+    RegDeleteValueA(key, "MSITESTVAR10");
+    RegDeleteValueA(key, "MSITESTVAR11");
     RegCloseKey(key);
 
     DeleteFileA("msitest\\envvar.txt");




More information about the wine-cvs mailing list