From 05de3b03deb12c2d5cc901cd0510e021f8dd93ba Mon Sep 17 00:00:00 2001 From: Misha Koshelev Date: Mon, 7 May 2007 17:50:30 -0500 Subject: [PATCH] msi: automation: Implement Installer::Products and Installer::ProductState. --- dlls/msi/automation.c | 106 +++++++++++++++++++++++++++++++++++ dlls/msi/msiserver.idl | 41 ++++++++------ dlls/msi/msiserver_dispids.h | 5 ++ dlls/msi/tests/automation.c | 79 +++++++++++++------------- 4 files changed, 176 insertions(+), 55 deletions(-) diff --git a/dlls/msi/automation.c b/dlls/msi/automation.c index d14fefb3e6b..dc85eadfb1c 100644 --- a/dlls/msi/automation.c +++ b/dlls/msi/automation.c @@ -82,6 +82,11 @@ interface AutomationObject { * Structures for additional data required by specific automation objects */ +typedef struct { + int iCount; + LPWSTR *pszStrings; +} StringListData; + typedef struct { /* The parent Installer object */ IDispatch *pInstaller; @@ -559,6 +564,60 @@ static HRESULT WINAPI RecordImpl_Invoke( return S_OK; } +static HRESULT WINAPI StringListImpl_Invoke( + AutomationObject* This, + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + StringListData *data = (StringListData *)private_data(This); + HRESULT hr; + VARIANTARG varg0; + + VariantInit(&varg0); + + switch (dispIdMember) + { + case DISPID_STRINGLIST_ITEM: + if (wFlags & DISPATCH_PROPERTYGET) { + hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); + if (FAILED(hr)) return hr; + if (V_I4(&varg0) < 0 || V_I4(&varg0) >= data->iCount) + return DISP_E_BADINDEX; + V_VT(pVarResult) = VT_BSTR; + V_BSTR(pVarResult) = SysAllocString(data->pszStrings[V_I4(&varg0)]); + } + break; + + case DISPID_STRINGLIST_COUNT: + if (wFlags & DISPATCH_PROPERTYGET) { + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = data->iCount; + } + break; + + default: + return DISP_E_MEMBERNOTFOUND; + } + + return S_OK; +} + +static void WINAPI StringListImpl_Free(AutomationObject *This) +{ + StringListData *data = private_data(This); + int idx; + + for (idx=0; idxiCount; idx++) + SysFreeString(data->pszStrings[idx]); + HeapFree(GetProcessHeap(), 0, data->pszStrings); +} + static HRESULT WINAPI ViewImpl_Invoke( AutomationObject* This, DISPID dispIdMember, @@ -940,6 +999,53 @@ static HRESULT WINAPI InstallerImpl_Invoke( } break; + case DISPID_INSTALLER_PRODUCTSTATE: + if (wFlags & DISPATCH_PROPERTYGET) { + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) return hr; + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0)); + } + break; + + case DISPID_INSTALLER_PRODUCTS: + if (wFlags & DISPATCH_PROPERTYGET) + { + StringListData *sldata = NULL; + int idx = 0; + WCHAR szProductBuf[GUID_SIZE]; + + /* Find number of products */ + do { + ret = MsiEnumProductsW(idx, szProductBuf); + if (ret == ERROR_SUCCESS) idx++; + } while (ret == ERROR_SUCCESS && ret != ERROR_NO_MORE_ITEMS); + + if (ret != ERROR_SUCCESS && ret != ERROR_NO_MORE_ITEMS) + { + ERR("MsiEnumProducts returned %d\n", ret); + return DISP_E_EXCEPTION; + } + + V_VT(pVarResult) = VT_DISPATCH; + if (SUCCEEDED(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); + sldata->iCount = idx; + sldata->pszStrings = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LPWSTR)*sldata->iCount); + for (idx = 0; idx < sldata->iCount; idx++) + { + ret = MsiEnumProductsW(idx, szProductBuf); + sldata->pszStrings[idx] = SysAllocString(szProductBuf); + } + } + } + break; + default: return DISP_E_MEMBERNOTFOUND; } diff --git a/dlls/msi/msiserver.idl b/dlls/msi/msiserver.idl index 7b14feb3287..e9f6169d2a6 100644 --- a/dlls/msi/msiserver.idl +++ b/dlls/msi/msiserver.idl @@ -38,6 +38,22 @@ library WindowsInstaller dispinterface Product; dispinterface Patch; + typedef enum { + msiInstallStateNotUsed = -7, + msiInstallStateBadConfig = -6, + msiInstallStateIncomplete = -5, + msiInstallStateSourceAbsent = -4, + msiInstallStateInvalidArg = -2, + msiInstallStateUnknown = -1, + msiInstallStateBroken = 0, + msiInstallStateAdvertised = 1, + msiInstallStateRemoved = 1, + msiInstallStateAbsent = 2, + msiInstallStateLocal = 3, + msiInstallStateSource = 4, + msiInstallStateDefault = 5 + } MsiInstallState; + [ uuid(000C1090-0000-0000-C000-000000000046) ] dispinterface Installer { @@ -47,6 +63,11 @@ library WindowsInstaller Session* OpenPackage( [in] VARIANT PackagePath, [in, optional, defaultvalue(0)] long Options); + [id(DISPID_INSTALLER_PRODUCTSTATE), propget] + MsiInstallState ProductState( + [in] BSTR Product); + [id(DISPID_INSTALLER_PRODUCTS), propget] + StringList *Products(); } [ uuid(000C1093-0000-0000-C000-000000000046) ] @@ -67,6 +88,10 @@ library WindowsInstaller { properties: methods: + [id(DISPID_STRINGLIST_ITEM), propget] + BSTR Item(long Index); + [id(DISPID_STRINGLIST_COUNT), propget] + long Count(); } [ uuid(000C1096-0000-0000-C000-000000000046) ] @@ -142,22 +167,6 @@ library WindowsInstaller msiRunModeCommit = 18 } MsiRunMode; - typedef enum { - msiInstallStateNotUsed = -7, - msiInstallStateBadConfig = -6, - msiInstallStateIncomplete = -5, - msiInstallStateSourceAbsent = -4, - msiInstallStateInvalidArg = -2, - msiInstallStateUnknown = -1, - msiInstallStateBroken = 0, - msiInstallStateAdvertised = 1, - msiInstallStateRemoved = 1, - msiInstallStateAbsent = 2, - msiInstallStateLocal = 3, - msiInstallStateSource = 4, - msiInstallStateDefault = 5 - } MsiInstallState; - [ uuid(000C109E-0000-0000-C000-000000000046) ] dispinterface Session { diff --git a/dlls/msi/msiserver_dispids.h b/dlls/msi/msiserver_dispids.h index e5efa3eedcd..daca2789d32 100644 --- a/dlls/msi/msiserver_dispids.h +++ b/dlls/msi/msiserver_dispids.h @@ -17,9 +17,14 @@ */ #define DISPID_INSTALLER_OPENPACKAGE 2 +#define DISPID_INSTALLER_PRODUCTSTATE 17 +#define DISPID_INSTALLER_PRODUCTS 35 #define DISPID_RECORD_STRINGDATA 1 +#define DISPID_STRINGLIST_ITEM 0 +#define DISPID_STRINGLIST_COUNT 1 + #define DISPID_VIEW_EXECUTE 1 #define DISPID_VIEW_FETCH 2 #define DISPID_VIEW_CLOSE 4 diff --git a/dlls/msi/tests/automation.c b/dlls/msi/tests/automation.c index cd32efd4fc2..b5ce43417da 100644 --- a/dlls/msi/tests/automation.c +++ b/dlls/msi/tests/automation.c @@ -325,10 +325,11 @@ static DISPID get_dispid( IDispatch *disp, const char *name ) static void test_dispid(void) { - ok( get_dispid( pInstaller, "OpenPackage" ) == 2, "dispid wrong\n"); - todo_wine { ok( get_dispid( pInstaller, "CreateRecord" ) == 1, "dispid wrong\n"); + } + ok( get_dispid( pInstaller, "OpenPackage" ) == 2, "dispid wrong\n"); + todo_wine { ok( get_dispid( pInstaller, "OpenProduct" ) == 3, "dispid wrong\n"); ok( get_dispid( pInstaller, "OpenDatabase" ) == 4, "dispid wrong\n"); ok( get_dispid( pInstaller, "SummaryInformation" ) == 5, "dispid wrong\n"); @@ -343,7 +344,9 @@ static void test_dispid(void) ok( get_dispid( pInstaller, "FileSize" ) == 15, "dispid wrong\n"); ok( get_dispid( pInstaller, "FileVersion" ) == 16, "dispid wrong\n"); + } ok( get_dispid( pInstaller, "ProductState" ) == 17, "dispid wrong\n"); + todo_wine { ok( get_dispid( pInstaller, "ProductInfo" ) == 18, "dispid wrong\n"); ok( get_dispid( pInstaller, "ConfigureProduct" ) == 19, "dispid wrong\n"); ok( get_dispid( pInstaller, "ReinstallProduct" ) == 20 , "dispid wrong\n"); @@ -361,7 +364,9 @@ static void test_dispid(void) ok( get_dispid( pInstaller, "ProvideQualifiedComponent" ) == 32, "dispid wrong\n"); ok( get_dispid( pInstaller, "QualifierDescription" ) == 33, "dispid wrong\n"); ok( get_dispid( pInstaller, "ComponentQualifiers" ) == 34, "dispid wrong\n"); + } ok( get_dispid( pInstaller, "Products" ) == 35, "dispid wrong\n"); + todo_wine { ok( get_dispid( pInstaller, "Features" ) == 36, "dispid wrong\n"); ok( get_dispid( pInstaller, "Components" ) == 37, "dispid wrong\n"); ok( get_dispid( pInstaller, "ComponentClients" ) == 38, "dispid wrong\n"); @@ -1100,50 +1105,46 @@ static void test_Installer(void) DeleteFileA(msifile); /* Installer::Products */ - todo_wine { - hr = Installer_Products(&pStringList); - ok(SUCCEEDED(hr), "Installer_Products failed, hresult 0x%08x\n", hr); - if (SUCCEEDED(hr)) + hr = Installer_Products(&pStringList); + ok(SUCCEEDED(hr), "Installer_Products failed, hresult 0x%08x\n", hr); + if (SUCCEEDED(hr)) + { + int iCount = 0, idx; + + /* StringList::Count */ + hr = StringList_Count(pStringList, &iCount); + ok(SUCCEEDED(hr), "StringList_Count failed, hresult 0x%08x\n", hr); + + for (idx=0; idx