diff --git a/dlls/msi/automation.c b/dlls/msi/automation.c index 1c717baec75..4cd7ba9efd5 100644 --- a/dlls/msi/automation.c +++ b/dlls/msi/automation.c @@ -1400,6 +1400,55 @@ static HRESULT WINAPI InstallerImpl_Invoke( else return DISP_E_MEMBERNOTFOUND; break; + case DISPID_INSTALLER_RELATEDPRODUCTS: + if (wFlags & DISPATCH_PROPERTYGET) + { + StringListData *sldata = NULL; + int idx = 0; + WCHAR szProductBuf[GUID_SIZE]; + + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) return hr; + + /* Find number of related products */ + do { + ret = MsiEnumRelatedProductsW(V_BSTR(&varg0), 0, idx, szProductBuf); + if (ret == ERROR_SUCCESS) idx++; + } while (ret == ERROR_SUCCESS); + + if (ret != ERROR_SUCCESS && ret != ERROR_NO_MORE_ITEMS) + { + VariantClear(&varg0); + ERR("MsiEnumRelatedProducts returned %d\n", ret); + return DISP_E_EXCEPTION; + } + + V_VT(pVarResult) = VT_DISPATCH; + if (SUCCEEDED(hr = create_automation_object(0, NULL, (LPVOID*)&pDispatch, &DIID_StringList, StringListImpl_Invoke, StringListImpl_Free, sizeof(StringListData)))) + { + IDispatch_AddRef(pDispatch); + V_DISPATCH(pVarResult) = pDispatch; + + /* Save product strings */ + sldata = (StringListData *)private_data((AutomationObject *)pDispatch); + if (!(sldata->pszStrings = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LPWSTR)*sldata->iCount))) + ERR("Out of memory\n"); + else + { + sldata->iCount = idx; + for (idx = 0; idx < sldata->iCount; idx++) + { + ret = MsiEnumRelatedProductsW(V_BSTR(&varg0), 0, idx, szProductBuf); + sldata->pszStrings[idx] = SysAllocString(szProductBuf); + } + } + } + else + ERR("Failed to create StringList object, hresult 0x%08x\n", hr); + } + else return DISP_E_MEMBERNOTFOUND; + break; + default: return DISP_E_MEMBERNOTFOUND; } diff --git a/dlls/msi/msiserver.idl b/dlls/msi/msiserver.idl index d453d7b6f41..5721319eddb 100644 --- a/dlls/msi/msiserver.idl +++ b/dlls/msi/msiserver.idl @@ -79,6 +79,9 @@ library WindowsInstaller [in] BSTR Product); [id(DISPID_INSTALLER_PRODUCTS), propget] StringList *Products(); + [id(DISPID_INSTALLER_RELATEDPRODUCTS), propget] + StringList *RelatedProducts( + [in] BSTR UpgradeCode); } [ uuid(000C1093-0000-0000-C000-000000000046) ] diff --git a/dlls/msi/msiserver_dispids.h b/dlls/msi/msiserver_dispids.h index ee18a44ac0e..92c342930e5 100644 --- a/dlls/msi/msiserver_dispids.h +++ b/dlls/msi/msiserver_dispids.h @@ -22,6 +22,7 @@ #define DISPID_INSTALLER_REGISTRYVALUE 11 #define DISPID_INSTALLER_PRODUCTSTATE 17 #define DISPID_INSTALLER_PRODUCTS 35 +#define DISPID_INSTALLER_RELATEDPRODUCTS 40 #define DISPID_RECORD_FIELDCOUNT 0 #define DISPID_RECORD_STRINGDATA 1 diff --git a/dlls/msi/tests/automation.c b/dlls/msi/tests/automation.c index a9da690b1ba..267d7567128 100644 --- a/dlls/msi/tests/automation.c +++ b/dlls/msi/tests/automation.c @@ -466,7 +466,9 @@ static void test_dispid(void) ok( get_dispid( pInstaller, "Components" ) == 37, "dispid wrong\n"); ok( get_dispid( pInstaller, "ComponentClients" ) == 38, "dispid wrong\n"); ok( get_dispid( pInstaller, "Patches" ) == 39, "dispid wrong\n"); + } ok( get_dispid( pInstaller, "RelatedProducts" ) == 40, "dispid wrong\n"); + todo_wine { ok( get_dispid( pInstaller, "PatchInfo" ) == 41, "dispid wrong\n"); ok( get_dispid( pInstaller, "PatchTransforms" ) == 42, "dispid wrong\n"); ok( get_dispid( pInstaller, "AddSource" ) == 43, "dispid wrong\n"); @@ -1667,24 +1669,22 @@ static void test_Installer_InstallProduct(LPCWSTR szPath) ok(iValue == INSTALLSTATE_DEFAULT, "Installer_ProductState returned %d, expected %d\n", iValue, INSTALLSTATE_DEFAULT); /* Installer::RelatedProducts for our upgrade code */ - todo_wine { - hr = Installer_RelatedProducts(szUpgradeCode, &pStringList); - ok(SUCCEEDED(hr), "Installer_RelatedProducts failed, hresult 0x%08x\n", hr); - if (SUCCEEDED(hr)) - { - /* StringList::Count */ - hr = StringList_Count(pStringList, &iCount); - ok(SUCCEEDED(hr), "StringList_Count failed, hresult 0x%08x\n", hr); - ok(iCount == 1, "Expected one related product but found %d\n", iCount); + hr = Installer_RelatedProducts(szUpgradeCode, &pStringList); + ok(SUCCEEDED(hr), "Installer_RelatedProducts failed, hresult 0x%08x\n", hr); + if (SUCCEEDED(hr)) + { + /* StringList::Count */ + hr = StringList_Count(pStringList, &iCount); + ok(SUCCEEDED(hr), "StringList_Count failed, hresult 0x%08x\n", hr); + todo_wine ok(iCount == 1, "Expected one related product but found %d\n", iCount); - /* StringList::Item */ - memset(szString, 0, sizeof(szString)); - hr = StringList_Item(pStringList, 0, szString); - ok(SUCCEEDED(hr), "StringList_Item failed (idx 0, count %d), hresult 0x%08x\n", iCount, hr); - ok_w2("StringList_Item returned %s but expected %s\n", szString, szProductCode); + /* StringList::Item */ + memset(szString, 0, sizeof(szString)); + hr = StringList_Item(pStringList, 0, szString); + todo_wine ok(SUCCEEDED(hr), "StringList_Item failed (idx 0, count %d), hresult 0x%08x\n", iCount, hr); + todo_wine ok_w2("StringList_Item returned %s but expected %s\n", szString, szProductCode); - IDispatch_Release(pStringList); - } + IDispatch_Release(pStringList); } /* Check & clean up installed files & registry keys */ @@ -1889,18 +1889,16 @@ static void test_Installer(void) ok(iValue == INSTALLSTATE_UNKNOWN, "Installer_ProductState returned %d, expected %d\n", iValue, INSTALLSTATE_UNKNOWN); /* Installer::RelatedProducts for our upgrade code, should not find anything */ - todo_wine { - hr = Installer_RelatedProducts(szUpgradeCode, &pStringList); - ok(SUCCEEDED(hr), "Installer_RelatedProducts failed, hresult 0x%08x\n", hr); - if (SUCCEEDED(hr)) - { - /* StringList::Count */ - hr = StringList_Count(pStringList, &iCount); - ok(SUCCEEDED(hr), "StringList_Count failed, hresult 0x%08x\n", hr); - ok(!iCount, "Expected no related products but found %d\n", iCount); + hr = Installer_RelatedProducts(szUpgradeCode, &pStringList); + ok(SUCCEEDED(hr), "Installer_RelatedProducts failed, hresult 0x%08x\n", hr); + if (SUCCEEDED(hr)) + { + /* StringList::Count */ + hr = StringList_Count(pStringList, &iCount); + ok(SUCCEEDED(hr), "StringList_Count failed, hresult 0x%08x\n", hr); + ok(!iCount, "Expected no related products but found %d\n", iCount); - IDispatch_Release(pStringList); - } + IDispatch_Release(pStringList); } /* Installer::Version */