From 511bdd9de8ceade99951d227060ad7fc417a9315 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Wed, 8 Aug 2007 18:42:30 -0700 Subject: [PATCH] msi: Simplify MsiQueryComponentState, with more tests. --- dlls/msi/msi.c | 122 +++++++++++++++++++++++++++------------ dlls/msi/msipriv.h | 2 + dlls/msi/registry.c | 64 ++++++++++++++++++++ dlls/msi/tests/install.c | 15 ++--- dlls/msi/tests/msi.c | 82 +++++++++++++++++++++++++- 5 files changed, 239 insertions(+), 46 deletions(-) diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index 1b01a4de480..61d4e45ad01 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -760,20 +760,87 @@ UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode, return r; } +static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context) +{ + UINT r; + HKEY hkey; + + if (context == MSIINSTALLCONTEXT_MACHINE) + r = MSIREG_OpenLocalClassesProductKey(prodcode, &hkey, FALSE); + else if (context == MSIINSTALLCONTEXT_USERUNMANAGED) + r = MSIREG_OpenUserProductsKey(prodcode, &hkey, FALSE); + else + r = MSIREG_OpenLocalManagedProductKey(prodcode, &hkey, FALSE); + + RegCloseKey(hkey); + return (r == ERROR_SUCCESS); +} + +static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context) +{ + LPCWSTR package; + HKEY hkey; + DWORD sz; + LONG res; + UINT r; + + static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0}; + static const WCHAR managed_local_package[] = { + 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0 + }; + + if (context == MSIINSTALLCONTEXT_MACHINE) + r = MSIREG_OpenLocalSystemProductKey(prodcode, &hkey, FALSE); + else + r = MSIREG_OpenInstallPropertiesKey(prodcode, &hkey, FALSE); + + if (r != ERROR_SUCCESS) + return FALSE; + + if (context == MSIINSTALLCONTEXT_USERMANAGED) + package = managed_local_package; + else + package = local_package; + + sz = 0; + res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz); + RegCloseKey(hkey); + + return (res == ERROR_SUCCESS); +} + +static BOOL msi_comp_find_prodcode(LPCWSTR prodcode, LPWSTR squished_pc, + MSIINSTALLCONTEXT context, + LPCWSTR comp, DWORD *sz) +{ + HKEY hkey; + LONG res; + UINT r; + + if (context == MSIINSTALLCONTEXT_MACHINE) + r = MSIREG_OpenLocalSystemComponentKey(comp, &hkey, FALSE); + else + r = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE); + + if (r != ERROR_SUCCESS) + return FALSE; + + *sz = 0; + res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, NULL, sz); + if (res != ERROR_SUCCESS) + return FALSE; + + RegCloseKey(hkey); + return TRUE; +} + UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode, LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCWSTR szComponent, INSTALLSTATE *pdwState) { WCHAR squished_pc[GUID_SIZE]; - HKEY hkey; - LONG res; + BOOL found; DWORD sz; - UINT r; - - static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0}; - static const WCHAR managed_local_package[] = { - 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0 - }; TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState); @@ -787,41 +854,24 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode, if (!squash_guid(szProductCode, squished_pc)) return ERROR_INVALID_PARAMETER; - if (dwContext == MSIINSTALLCONTEXT_MACHINE) - r = MSIREG_OpenLocalSystemProductKey(szProductCode, &hkey, FALSE); - else - r = MSIREG_OpenInstallPropertiesKey(szProductCode, &hkey, FALSE); + found = msi_comp_find_prod_key(szProductCode, dwContext); + + if (!msi_comp_find_package(szProductCode, dwContext)) + { + if (found) + { + *pdwState = INSTALLSTATE_UNKNOWN; + return ERROR_UNKNOWN_COMPONENT; + } - if (r != ERROR_SUCCESS) return ERROR_UNKNOWN_PRODUCT; + } - sz = 0; - if (dwContext != MSIINSTALLCONTEXT_USERMANAGED) - res = RegQueryValueExW(hkey, local_package, NULL, NULL, NULL, &sz); - else - res = RegQueryValueExW(hkey, managed_local_package, NULL, NULL, NULL, &sz); - - if (res != ERROR_SUCCESS) - return ERROR_UNKNOWN_PRODUCT; - - RegCloseKey(hkey); *pdwState = INSTALLSTATE_UNKNOWN; - if (dwContext == MSIINSTALLCONTEXT_MACHINE) - r = MSIREG_OpenLocalSystemComponentKey(szComponent, &hkey, FALSE); - else - r = MSIREG_OpenUserDataComponentKey(szComponent, &hkey, FALSE); - - if (r != ERROR_SUCCESS) + if (!msi_comp_find_prodcode(szProductCode, squished_pc, dwContext, szComponent, &sz)) return ERROR_UNKNOWN_COMPONENT; - sz = 0; - res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, NULL, &sz); - if (res != ERROR_SUCCESS) - return ERROR_UNKNOWN_COMPONENT; - - RegCloseKey(hkey); - if (sz == 0) *pdwState = INSTALLSTATE_NOTUSED; else diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 799e90a0bca..a5bb7b67cdd 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -749,6 +749,8 @@ extern UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct); extern UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct); extern UINT MSIREG_OpenLocalSystemProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create); extern UINT MSIREG_OpenLocalSystemComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create); +extern UINT MSIREG_OpenLocalClassesProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create); +extern UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create); 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 67eae4b5b8c..fd00786fb2f 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -215,6 +215,21 @@ static const WCHAR szInstaller_LocalSystemComponent_fmt[] = { 'S','-','1','-','5','-','1','8','\\', 'C','o','m','p','o','n','e','n','t','s','\\','%','s',0}; +static const WCHAR szInstaller_LocalClassesProd_fmt[] = { +'S','o','f','t','w','a','r','e','\\', +'C','l','a','s','s','e','s','\\', +'I','n','s','t','a','l','l','e','r','\\', +'P','r','o','d','u','c','t','s','\\','%','s',0}; + +static const WCHAR szInstaller_LocalManagedProd_fmt[] = { +'S','o','f','t','w','a','r','e','\\', +'M','i','c','r','o','s','o','f','t','\\', +'W','i','n','d','o','w','s','\\', +'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', +'I','n','s','t','a','l','l','e','r','\\', +'M','a','n','a','g','e','d','\\','%','s','\\', +'I','n','s','t','a','l','l','e','r','\\', +'P','r','o','d','u','c','t','s','\\','%','s',0}; #define SQUISH_GUID_SIZE 33 @@ -929,6 +944,55 @@ UINT MSIREG_OpenLocalSystemComponentKey(LPCWSTR szComponent, HKEY *key, BOOL cre return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); } +UINT MSIREG_OpenLocalClassesProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n", debugstr_w(szProductCode)); + + if (!squash_guid(szProductCode, squished_pc)) + return ERROR_FUNCTION_FAILED; + + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath, szInstaller_LocalClassesProd_fmt, squished_pc); + + if (create) + return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); +} + +UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + LPWSTR usersid; + UINT r; + + TRACE("%s\n", debugstr_w(szProductCode)); + + if (!squash_guid(szProductCode, squished_pc)) + return ERROR_FUNCTION_FAILED; + + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + r = get_user_sid(&usersid); + if (r != ERROR_SUCCESS || !usersid) + { + ERR("Failed to retrieve user SID: %d\n", r); + return r; + } + + sprintfW(keypath, szInstaller_LocalManagedProd_fmt, usersid, squished_pc); + msi_free(usersid); + + if (create) + return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); +} /************************************************************************* * MsiDecomposeDescriptorW [MSI.@] diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index be54cdb3c29..0e99d34e6e1 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -1783,10 +1783,7 @@ static void test_publish(void) r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state); - todo_wine - { - ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); - } + ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); /* try to uninstall after PublishProduct */ @@ -1826,10 +1823,7 @@ static void test_publish(void) r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state); - todo_wine - { - ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); - } + ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); /* try it again */ @@ -1852,7 +1846,10 @@ static void test_publish(void) r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state); - ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + todo_wine + { + ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + } ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); /* uninstall has a problem with this */ diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index f654aabe0d5..867eb421513 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -698,6 +698,25 @@ static void test_MsiQueryComponentState(void) ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state); + state = 0xdeadbeef; + r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state); + ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state); + + lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = 0xdeadbeef; + r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state); + ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + /* create local system product key */ lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\"); lstrcatA(keypath, prod_squashed); @@ -706,10 +725,16 @@ static void test_MsiQueryComponentState(void) res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + /* local system product key exists */ + state = 0xdeadbeef; + r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state); + ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state); + res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - /* local system product key exists */ + /* LocalPackage value exists */ state = 0xdeadbeef; r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state); ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); @@ -758,6 +783,20 @@ static void test_MsiQueryComponentState(void) ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state); + lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = 0xdeadbeef; + r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state); + ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); lstrcatA(keypath, usersid); lstrcatA(keypath, "\\Products\\"); @@ -770,6 +809,8 @@ static void test_MsiQueryComponentState(void) res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + RegCloseKey(prodkey); + state = 0xdeadbeef; r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state); ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); @@ -813,6 +854,45 @@ static void test_MsiQueryComponentState(void) ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state); + lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = 0xdeadbeef; + r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state); + ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state); + + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = 0xdeadbeef; + r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state); + ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r); + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Products\\"); + lstrcatA(keypath, prod_squashed); + lstrcatA(keypath, "\\InstallProperties"); + + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);