From 624bbbe78a68598003eb906ddc1839a250bed340 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Mon, 2 Jul 2007 20:20:54 -0700 Subject: [PATCH] msi: Unpublish the product when it is entirely removed. --- dlls/msi/action.c | 50 +++++++++++++++++++++++++++++++++++++ dlls/msi/msipriv.h | 3 +++ dlls/msi/registry.c | 53 ++++++++++++++++++++++++++++++++++++++++ dlls/msi/tests/install.c | 40 ++++++------------------------ 4 files changed, 114 insertions(+), 32 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index c9d4fa82682..0911a291cbd 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -3885,10 +3885,60 @@ static UINT ACTION_InstallExecute(MSIPACKAGE *package) return execute_script(package,INSTALL_SCRIPT); } +static UINT msi_unpublish_product(MSIPACKAGE *package) +{ + LPWSTR remove = NULL; + LPWSTR *features = NULL; + BOOL full_uninstall = TRUE; + MSIFEATURE *feature; + + static const WCHAR szRemove[] = {'R','E','M','O','V','E',0}; + static const WCHAR szAll[] = {'A','L','L',0}; + + remove = msi_dup_property(package, szRemove); + if (!remove) + return ERROR_SUCCESS; + + features = msi_split_string(remove, ','); + if (!features) + { + msi_free(remove); + ERR("REMOVE feature list is empty!\n"); + return ERROR_FUNCTION_FAILED; + } + + if (!lstrcmpW(features[0], szAll)) + full_uninstall = TRUE; + else + { + LIST_FOR_EACH_ENTRY(feature, &package->features, MSIFEATURE, entry) + { + if (feature->Action != INSTALLSTATE_ABSENT) + full_uninstall = FALSE; + } + } + + if (!full_uninstall) + goto done; + + MSIREG_DeleteProductKey(package->ProductCode); + MSIREG_DeleteUserProductKey(package->ProductCode); + MSIREG_DeleteUserDataProductKey(package->ProductCode); + +done: + msi_free(remove); + msi_free(features); + return ERROR_SUCCESS; +} + static UINT ACTION_InstallFinalize(MSIPACKAGE *package) { UINT rc; + rc = msi_unpublish_product(package); + if (rc != ERROR_SUCCESS) + return rc; + /* turn off scheduling */ package->script->CurrentlyScripting= FALSE; diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index e5b5ea3db0f..14a365e1d78 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -713,6 +713,9 @@ extern UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create); extern UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szProduct, HKEY* key, BOOL create); +extern UINT MSIREG_DeleteProductKey(LPCWSTR szProduct); +extern UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct); +extern UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct); extern LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name ); extern BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val); diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c index c5572640c09..238cdd13b0f 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -437,6 +437,20 @@ UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create) return rc; } +UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n",debugstr_w(szProduct)); + squash_guid(szProduct,squished_pc); + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath,szUserProduct_fmt,squished_pc); + + return RegDeleteTreeW(HKEY_CURRENT_USER, keypath); +} + UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create) { UINT rc; @@ -593,9 +607,34 @@ UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create) else rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); + msi_free(usersid); return rc; } +UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct) +{ + UINT rc; + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + LPWSTR usersid; + + TRACE("%s\n", debugstr_w(szProduct)); + squash_guid(szProduct, squished_pc); + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + rc = get_user_sid(&usersid); + if (rc != ERROR_SUCCESS || !usersid) + { + ERR("Failed to retrieve user SID: %d\n", rc); + return rc; + } + + sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc); + + msi_free(usersid); + return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath); +} + UINT MSIREG_OpenProducts(HKEY* key) { return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Products,key); @@ -621,6 +660,20 @@ UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create) return rc; } +UINT MSIREG_DeleteProductKey(LPCWSTR szProduct) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n", debugstr_w(szProduct)); + squash_guid(szProduct, squished_pc); + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath, szInstaller_Products_fmt, squished_pc); + + return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath); +} + UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create) { UINT rc; diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index f7df7eb9991..42d41a249fc 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -1706,10 +1706,7 @@ static void test_publish(void) ok(pf_exists("msitest"), "File deleted\n"); state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); - todo_wine - { - ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - } + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); @@ -1952,10 +1949,7 @@ static void test_publish(void) } state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); - todo_wine - { - ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - } + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); todo_wine @@ -1984,10 +1978,7 @@ static void test_publish(void) ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); - todo_wine - { - ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - } + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); todo_wine @@ -2013,16 +2004,10 @@ static void test_publish(void) ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); - todo_wine - { - ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - } + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); - todo_wine - { - ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - } + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state); @@ -2071,10 +2056,7 @@ static void test_publish(void) } state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); - todo_wine - { - ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - } + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); todo_wine @@ -2103,16 +2085,10 @@ static void test_publish(void) ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); - todo_wine - { - ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - } + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo"); - todo_wine - { - ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - } + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);