Hans Leidekker : msi: Implement the RemoveEnvironmentStrings standard action.

Alexandre Julliard julliard at winehq.org
Wed Mar 3 11:15:47 CST 2010


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Mar  3 14:38:06 2010 +0100

msi: Implement the RemoveEnvironmentStrings standard action.

---

 dlls/msi/action.c |  195 +++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 159 insertions(+), 36 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 4441030..08cf975 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -5810,7 +5810,7 @@ static UINT ACTION_RemoveODBC( MSIPACKAGE *package )
 
 #define check_flag_combo(x, y) ((x) & ~(y)) == (y)
 
-static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
+static UINT env_parse_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
 {
     LPCWSTR cptr = *name;
 
@@ -5891,18 +5891,8 @@ static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
     return ERROR_SUCCESS;
 }
 
-static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
+static UINT open_env_key( DWORD flags, HKEY *key )
 {
-    MSIPACKAGE *package = param;
-    LPCWSTR name, value, component;
-    LPWSTR data = NULL, newval = NULL;
-    LPWSTR deformatted = NULL, ptr;
-    DWORD flags, type, size;
-    LONG res;
-    HKEY env = NULL, root;
-    LPCWSTR environment;
-    MSICOMPONENT *comp;
-
     static const WCHAR user_env[] =
         {'E','n','v','i','r','o','n','m','e','n','t',0};
     static const WCHAR machine_env[] =
@@ -5911,6 +5901,42 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
          'C','o','n','t','r','o','l','\\',
          'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\',
          'E','n','v','i','r','o','n','m','e','n','t',0};
+    const WCHAR *env;
+    HKEY root;
+    LONG res;
+
+    if (flags & ENV_MOD_MACHINE)
+    {
+        env = machine_env;
+        root = HKEY_LOCAL_MACHINE;
+    }
+    else
+    {
+        env = user_env;
+        root = HKEY_CURRENT_USER;
+    }
+
+    res = RegOpenKeyExW( root, env, 0, KEY_ALL_ACCESS, key );
+    if (res != ERROR_SUCCESS)
+    {
+        WARN("Failed to open key %s (%d)\n", debugstr_w(env), res);
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
+{
+    MSIPACKAGE *package = param;
+    LPCWSTR name, value, component;
+    LPWSTR data = NULL, newval = NULL, deformatted = NULL, ptr;
+    DWORD flags, type, size;
+    UINT res;
+    HKEY env;
+    MSICOMPONENT *comp;
+    MSIRECORD *uirow;
+    int action = 0;
 
     component = MSI_RecordGetString(rec, 4);
     comp = get_loaded_component(package, component);
@@ -5930,7 +5956,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);
+    res = env_parse_flags(&name, &value, &flags);
     if (res != ERROR_SUCCESS || !value)
        goto done;
 
@@ -5942,24 +5968,12 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
 
     value = deformatted;
 
-    if (flags & ENV_MOD_MACHINE)
-    {
-        environment = machine_env;
-        root = HKEY_LOCAL_MACHINE;
-    }
-    else
-    {
-        environment = user_env;
-        root = HKEY_CURRENT_USER;
-    }
-
-    res = RegCreateKeyExW(root, environment, 0, NULL, 0,
-                          KEY_ALL_ACCESS, NULL, &env, NULL);
+    res = open_env_key( flags, &env );
     if (res != ERROR_SUCCESS)
         goto done;
 
-    if (flags & ENV_ACT_REMOVE)
-        FIXME("Not removing environment variable on uninstall!\n");
+    if (flags & ENV_MOD_MACHINE)
+        action |= 0x20000000;
 
     size = 0;
     type = REG_SZ;
@@ -5970,6 +5984,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
 
     if ((res == ERROR_FILE_NOT_FOUND || !(flags & ENV_MOD_MASK)))
     {
+        action = 0x2;
+
         /* Nothing to do. */
         if (!value)
         {
@@ -5990,6 +6006,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
     }
     else
     {
+        action = 0x1;
+
         /* Contrary to MSDN, +-variable to [~];path works */
         if (flags & ENV_ACT_SETABSENT && !(flags & ENV_MOD_MASK))
         {
@@ -6010,7 +6028,10 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
 
         if (flags & ENV_ACT_REMOVEMATCH && (!value || !lstrcmpW(data, value)))
         {
-            res = RegDeleteKeyW(env, name);
+            action = 0x4;
+            res = RegDeleteValueW(env, name);
+            if (res != ERROR_SUCCESS)
+                WARN("Failed to remove value %s (%d)\n", debugstr_w(name), res);
             goto done;
         }
 
@@ -6037,6 +6058,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
         {
             lstrcpyW(newval, value);
             ptr = newval + lstrlenW(value);
+            action |= 0x80000000;
         }
 
         lstrcpyW(ptr, data);
@@ -6044,12 +6066,24 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
         if (flags & ENV_MOD_APPEND)
         {
             lstrcatW(newval, value);
+            action |= 0x40000000;
         }
     }
     TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
     res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
+    if (res)
+    {
+        WARN("Failed to set %s to %s (%d)\n",  debugstr_w(name), debugstr_w(newval), res);
+    }
 
 done:
+    uirow = MSI_CreateRecord( 3 );
+    MSI_RecordSetStringW( uirow, 1, name );
+    MSI_RecordSetStringW( uirow, 2, newval );
+    MSI_RecordSetInteger( uirow, 3, action );
+    ui_actiondata( package, szWriteEnvironmentStrings, uirow );
+    msiobj_release( &uirow->hdr );
+
     if (env) RegCloseKey(env);
     msi_free(deformatted);
     msi_free(data);
@@ -6074,6 +6108,102 @@ static UINT ACTION_WriteEnvironmentStrings( MSIPACKAGE *package )
     return rc;
 }
 
+static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
+{
+    MSIPACKAGE *package = param;
+    LPCWSTR name, value, component;
+    LPWSTR deformatted = NULL;
+    DWORD flags;
+    HKEY env;
+    MSICOMPONENT *comp;
+    MSIRECORD *uirow;
+    int action = 0;
+    LONG res;
+    UINT r;
+
+    component = MSI_RecordGetString( rec, 4 );
+    comp = get_loaded_component( package, component );
+    if (!comp)
+        return ERROR_SUCCESS;
+
+    if (comp->ActionRequest != INSTALLSTATE_ABSENT)
+    {
+        TRACE("Component not scheduled for removal: %s\n", debugstr_w(component));
+        comp->Action = comp->Installed;
+        return ERROR_SUCCESS;
+    }
+    comp->Action = INSTALLSTATE_ABSENT;
+
+    name = MSI_RecordGetString( rec, 2 );
+    value = MSI_RecordGetString( rec, 3 );
+
+    TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value));
+
+    r = env_parse_flags( &name, &value, &flags );
+    if (r != ERROR_SUCCESS)
+       return r;
+
+    if (!(flags & ENV_ACT_REMOVE))
+    {
+        TRACE("Environment variable %s not marked for removal\n", debugstr_w(name));
+        return ERROR_SUCCESS;
+    }
+
+    if (value && !deformat_string( package, value, &deformatted ))
+        return ERROR_OUTOFMEMORY;
+
+    value = deformatted;
+
+    r = open_env_key( flags, &env );
+    if (r != ERROR_SUCCESS)
+    {
+        r = ERROR_SUCCESS;
+        goto done;
+    }
+
+    if (flags & ENV_MOD_MACHINE)
+        action |= 0x20000000;
+
+    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);
+        r = ERROR_SUCCESS;
+    }
+
+done:
+    uirow = MSI_CreateRecord( 3 );
+    MSI_RecordSetStringW( uirow, 1, name );
+    MSI_RecordSetStringW( uirow, 2, value );
+    MSI_RecordSetInteger( uirow, 3, action );
+    ui_actiondata( package, szRemoveEnvironmentStrings, uirow );
+    msiobj_release( &uirow->hdr );
+
+    if (env) RegCloseKey( env );
+    msi_free( deformatted );
+    return r;
+}
+
+static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
+{
+    UINT rc;
+    MSIQUERY *view;
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','E','n','v','i','r','o','n','m','e','n','t','`',0};
+
+    rc = MSI_DatabaseOpenViewW( package->db, query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveEnvironmentString, package );
+    msiobj_release( &view->hdr );
+
+    return rc;
+}
+
 #define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
 
 typedef struct
@@ -6972,13 +7102,6 @@ static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package )
     return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table );
 }
 
-static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = {
-        'E','n','v','i','r','o','n','m','e','n','t',0 };
-    return msi_unimplemented_action_stub( package, "RemoveEnvironmentStrings", table );
-}
-
 static UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
 {
     static const WCHAR table[] = {




More information about the wine-cvs mailing list