2 * Implementation of OLE Automation for Microsoft Installer (msi.dll)
4 * Copyright 2007 Misha Koshelev
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #include "msiserver.h"
38 #include "msiserver_dispids.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42 #define REG_INDEX_CLASSES_ROOT 0
43 #define REG_INDEX_DYN_DATA 6
46 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
47 * called from AutomationObject::Invoke, and pass this function to create_automation_object.
50 typedef struct AutomationObject AutomationObject;
52 typedef HRESULT (*autoInvokeFunc)(AutomationObject* This,
53 DISPID dispIdMember, REFIID riid, LCID lcid, WORD flags, DISPPARAMS* pDispParams,
54 VARIANT* result, EXCEPINFO* ei, UINT* arg_err);
56 typedef void (*autoFreeFunc)(AutomationObject* This);
58 struct AutomationObject {
59 IDispatch IDispatch_iface;
60 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface;
63 /* Clsid for this class and it's appropriate ITypeInfo object */
67 /* The MSI handle of the current object */
70 /* A function that is called from AutomationObject::Invoke, specific to this type of object. */
71 autoInvokeFunc funcInvoke;
72 /* A function that is called from AutomationObject::Release when the object is being freed to free any private
73 * data structures (or NULL) */
74 autoFreeFunc funcFree;
78 AutomationObject autoobj;
83 static HRESULT create_list_enumerator(ListObject*, void**);
85 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
87 IEnumVARIANT IEnumVARIANT_iface;
90 /* Current position and pointer to AutomationObject that stores actual data */
96 AutomationObject autoobj;
100 static inline AutomationObject *impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo *iface )
102 return CONTAINING_RECORD(iface, AutomationObject, IProvideMultipleClassInfo_iface);
105 static inline AutomationObject *impl_from_IDispatch( IDispatch *iface )
107 return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface);
110 /* Load type info so we don't have to process GetIDsOfNames */
111 HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid)
113 static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
114 ITypeInfo *ti = NULL;
115 ITypeLib *lib = NULL;
118 TRACE("(%p)->(%s, %d)\n", iface, debugstr_guid(clsid), lcid);
120 /* Load registered type library */
121 hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, lcid, &lib);
123 hr = LoadTypeLib(msiserverW, &lib);
125 ERR("Could not load msiserver.tlb\n");
130 /* Get type information for object */
131 hr = ITypeLib_GetTypeInfoOfGuid(lib, clsid, &ti);
132 ITypeLib_Release(lib);
134 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid));
141 /* AutomationObject methods */
142 static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject)
144 AutomationObject *This = impl_from_IDispatch(iface);
146 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
148 if (ppvObject == NULL)
153 if (IsEqualGUID(riid, &IID_IUnknown) ||
154 IsEqualGUID(riid, &IID_IDispatch) ||
155 IsEqualGUID(riid, This->clsid))
156 *ppvObject = &This->IDispatch_iface;
157 else if (IsEqualGUID(riid, &IID_IProvideClassInfo) ||
158 IsEqualGUID(riid, &IID_IProvideClassInfo2) ||
159 IsEqualGUID(riid, &IID_IProvideMultipleClassInfo))
160 *ppvObject = &This->IProvideMultipleClassInfo_iface;
163 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid));
164 return E_NOINTERFACE;
167 IDispatch_AddRef(iface);
172 static ULONG WINAPI AutomationObject_AddRef(IDispatch* iface)
174 AutomationObject *This = impl_from_IDispatch(iface);
176 TRACE("(%p/%p)\n", iface, This);
178 return InterlockedIncrement(&This->ref);
181 static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
183 AutomationObject *This = impl_from_IDispatch(iface);
184 ULONG ref = InterlockedDecrement(&This->ref);
186 TRACE("(%p/%p)\n", iface, This);
190 if (This->funcFree) This->funcFree(This);
191 ITypeInfo_Release(This->iTypeInfo);
192 MsiCloseHandle(This->msiHandle);
199 static HRESULT WINAPI AutomationObject_GetTypeInfoCount(
203 AutomationObject *This = impl_from_IDispatch(iface);
205 TRACE("(%p/%p)->(%p)\n", iface, This, pctinfo);
210 static HRESULT WINAPI AutomationObject_GetTypeInfo(
216 AutomationObject *This = impl_from_IDispatch(iface);
217 TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo);
219 ITypeInfo_AddRef(This->iTypeInfo);
220 *ppTInfo = This->iTypeInfo;
224 static HRESULT WINAPI AutomationObject_GetIDsOfNames(
232 AutomationObject *This = impl_from_IDispatch(iface);
234 TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId);
236 if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG;
237 hr = ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
238 if (hr == DISP_E_UNKNOWNNAME)
241 for (idx=0; idx<cNames; idx++)
243 if (rgDispId[idx] == DISPID_UNKNOWN)
244 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(This->clsid));
250 /* Maximum number of allowed function parameters+1 */
251 #define MAX_FUNC_PARAMS 20
253 /* Some error checking is done here to simplify individual object function invocation */
254 static HRESULT WINAPI AutomationObject_Invoke(
260 DISPPARAMS* pDispParams,
262 EXCEPINFO* pExcepInfo,
265 AutomationObject *This = impl_from_IDispatch(iface);
267 unsigned int uArgErr;
268 VARIANT varResultDummy;
269 BSTR bstrName = NULL;
271 TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface, This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
273 if (!IsEqualIID(riid, &IID_NULL))
275 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
276 return DISP_E_UNKNOWNNAME;
279 if (wFlags & DISPATCH_PROPERTYGET && !pVarResult)
281 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
282 return DISP_E_PARAMNOTOPTIONAL;
285 /* This simplifies our individual object invocation functions */
286 if (puArgErr == NULL) puArgErr = &uArgErr;
287 if (pVarResult == NULL) pVarResult = &varResultDummy;
289 /* Assume return type is void unless determined otherwise */
290 VariantInit(pVarResult);
292 /* If we are tracing, we want to see the name of the member we are invoking */
295 ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL);
296 TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName));
299 hr = This->funcInvoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
301 if (hr == DISP_E_MEMBERNOTFOUND) {
302 if (bstrName == NULL) ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL);
303 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, debugstr_guid(This->clsid));
305 else if (pExcepInfo &&
306 (hr == DISP_E_PARAMNOTFOUND ||
307 hr == DISP_E_EXCEPTION)) {
308 static const WCHAR szComma[] = { ',',0 };
309 static const WCHAR szExceptionSource[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
310 WCHAR szExceptionDescription[MAX_PATH];
311 BSTR bstrParamNames[MAX_FUNC_PARAMS];
315 if (FAILED(ITypeInfo_GetNames(This->iTypeInfo, dispIdMember, bstrParamNames,
316 MAX_FUNC_PARAMS, &namesNo)))
318 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember);
322 memset(szExceptionDescription, 0, sizeof(szExceptionDescription));
323 for (i=0; i<namesNo; i++)
325 if (bFirst) bFirst = FALSE;
327 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], szComma);
329 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], bstrParamNames[i]);
330 SysFreeString(bstrParamNames[i]);
333 memset(pExcepInfo, 0, sizeof(EXCEPINFO));
334 pExcepInfo->wCode = 1000;
335 pExcepInfo->bstrSource = SysAllocString(szExceptionSource);
336 pExcepInfo->bstrDescription = SysAllocString(szExceptionDescription);
337 hr = DISP_E_EXCEPTION;
341 /* Make sure we free the return variant if it is our dummy variant */
342 if (pVarResult == &varResultDummy) VariantClear(pVarResult);
344 /* Free function name if we retrieved it */
345 SysFreeString(bstrName);
347 TRACE("Returning 0x%08x, %s\n", hr, SUCCEEDED(hr) ? "ok" : "not ok");
352 static const struct IDispatchVtbl AutomationObjectVtbl =
354 AutomationObject_QueryInterface,
355 AutomationObject_AddRef,
356 AutomationObject_Release,
357 AutomationObject_GetTypeInfoCount,
358 AutomationObject_GetTypeInfo,
359 AutomationObject_GetIDsOfNames,
360 AutomationObject_Invoke
364 * IProvideMultipleClassInfo methods
367 static HRESULT WINAPI ProvideMultipleClassInfo_QueryInterface(
368 IProvideMultipleClassInfo* iface,
372 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
373 return IDispatch_QueryInterface(&This->IDispatch_iface, riid, ppvoid);
376 static ULONG WINAPI ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo* iface)
378 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
379 return IDispatch_AddRef(&This->IDispatch_iface);
382 static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo* iface)
384 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
385 return IDispatch_Release(&This->IDispatch_iface);
388 static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI)
390 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
391 TRACE("(%p/%p)->(%p)\n", iface, This, ppTI);
392 return load_type_info(&This->IDispatch_iface, ppTI, This->clsid, 0);
395 static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID)
397 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
398 TRACE("(%p/%p)->(%d,%s)\n", iface, This, dwGuidKind, debugstr_guid(pGUID));
400 if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
403 *pGUID = *This->clsid;
408 static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo* iface, ULONG* pcti)
410 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
412 TRACE("(%p/%p)->(%p)\n", iface, This, pcti);
417 static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface,
420 ITypeInfo** pptiCoClass,
422 ULONG* pcdispidReserved,
426 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
428 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, pptiCoClass, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource);
433 if (dwFlags & MULTICLASSINFO_GETTYPEINFO)
434 load_type_info(&This->IDispatch_iface, pptiCoClass, This->clsid, 0);
436 if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
439 *pcdispidReserved = 0;
442 if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY){
443 *piidPrimary = *This->clsid;
446 if (dwFlags & MULTICLASSINFO_GETIIDSOURCE){
447 *piidSource = *This->clsid;
453 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl =
455 ProvideMultipleClassInfo_QueryInterface,
456 ProvideMultipleClassInfo_AddRef,
457 ProvideMultipleClassInfo_Release,
458 ProvideMultipleClassInfo_GetClassInfo,
459 ProvideMultipleClassInfo_GetGUID,
460 ProvideMultipleClassInfo_GetMultiTypeInfoCount,
461 ProvideMultipleClassInfo_GetInfoOfIndex
464 /* Create the automation object, placing the result in the pointer ppObj. The automation object is created
465 * with the appropriate clsid and invocation function. */
466 static HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, void **ppObj, REFIID clsid,
467 autoInvokeFunc invokeFunc, autoFreeFunc freeFunc)
469 AutomationObject *object;
472 TRACE("(%d,%p,%p,%s,%p,%p)\n", msiHandle, pUnkOuter, ppObj, debugstr_guid(clsid), invokeFunc, freeFunc);
475 return CLASS_E_NOAGGREGATION;
477 object = msi_alloc_zero(sizeof(AutomationObject));
479 object->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
480 object->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
483 object->msiHandle = msiHandle;
484 object->clsid = (LPCLSID)clsid;
485 object->funcInvoke = invokeFunc;
486 object->funcFree = freeFunc;
488 /* Load our TypeInfo so we don't have to process GetIDsOfNames */
489 object->iTypeInfo = NULL;
490 hr = load_type_info(&object->IDispatch_iface, &object->iTypeInfo, clsid, 0x0);
501 static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, REFIID clsid,
502 autoInvokeFunc invokeFunc, autoFreeFunc freeFunc)
504 TRACE("(%p, %d, %s, %p, %p)\n", This, msiHandle, debugstr_guid(clsid), invokeFunc, freeFunc);
506 This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
507 This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
510 This->msiHandle = msiHandle;
511 This->clsid = (LPCLSID)clsid;
512 This->funcInvoke = invokeFunc;
513 This->funcFree = freeFunc;
515 /* Load our TypeInfo so we don't have to process GetIDsOfNames */
516 This->iTypeInfo = NULL;
517 return load_type_info(&This->IDispatch_iface, &This->iTypeInfo, clsid, 0);
521 * ListEnumerator methods
524 static inline ListEnumerator *impl_from_IEnumVARIANT(IEnumVARIANT* iface)
526 return CONTAINING_RECORD(iface, ListEnumerator, IEnumVARIANT_iface);
529 static HRESULT WINAPI ListEnumerator_QueryInterface(IEnumVARIANT* iface, REFIID riid,
532 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
534 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
536 if (ppvObject == NULL)
541 if (IsEqualGUID(riid, &IID_IUnknown) ||
542 IsEqualGUID(riid, &IID_IEnumVARIANT))
544 *ppvObject = &This->IEnumVARIANT_iface;
548 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid));
549 return E_NOINTERFACE;
552 IEnumVARIANT_AddRef(iface);
556 static ULONG WINAPI ListEnumerator_AddRef(IEnumVARIANT* iface)
558 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
560 TRACE("(%p/%p)\n", iface, This);
562 return InterlockedIncrement(&This->ref);
565 static ULONG WINAPI ListEnumerator_Release(IEnumVARIANT* iface)
567 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
568 ULONG ref = InterlockedDecrement(&This->ref);
570 TRACE("(%p/%p)\n", iface, This);
574 if (This->list) IDispatch_Release(&This->list->autoobj.IDispatch_iface);
581 static HRESULT WINAPI ListEnumerator_Next(IEnumVARIANT* iface, ULONG celt, VARIANT* rgVar,
584 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
587 TRACE("(%p, %uld, %p, %p)\n", iface, celt, rgVar, fetched);
589 if (fetched) *fetched = 0;
594 for (local = 0; local < celt; local++)
595 VariantInit(&rgVar[local]);
597 for (i = This->pos, local = 0; i < This->list->count && local < celt; i++, local++)
598 VariantCopy(&rgVar[local], &This->list->data[i]);
600 if (fetched) *fetched = local;
603 return (local < celt) ? S_FALSE : S_OK;
606 static HRESULT WINAPI ListEnumerator_Skip(IEnumVARIANT* iface, ULONG celt)
608 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
610 TRACE("(%p,%uld)\n", iface, celt);
613 if (This->pos >= This->list->count)
615 This->pos = This->list->count;
622 static HRESULT WINAPI ListEnumerator_Reset(IEnumVARIANT* iface)
624 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
626 TRACE("(%p)\n", iface);
632 static HRESULT WINAPI ListEnumerator_Clone(IEnumVARIANT* iface, IEnumVARIANT **ppEnum)
634 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
637 TRACE("(%p,%p)\n", iface, ppEnum);
643 hr = create_list_enumerator(This->list, (LPVOID *)ppEnum);
647 IUnknown_Release(*ppEnum);
654 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
656 ListEnumerator_QueryInterface,
657 ListEnumerator_AddRef,
658 ListEnumerator_Release,
661 ListEnumerator_Reset,
665 /* Create a list enumerator, placing the result in the pointer ppObj. */
666 static HRESULT create_list_enumerator(ListObject *list, void **ppObj)
668 ListEnumerator *object;
670 TRACE("(%p, %p)\n", list, ppObj);
672 object = msi_alloc(sizeof(ListEnumerator));
674 /* Set all the VTable references */
675 object->IEnumVARIANT_iface.lpVtbl = &ListEnumerator_Vtbl;
678 /* Store data that was passed */
681 if (list) IDispatch_AddRef(&list->autoobj.IDispatch_iface);
688 * Individual Object Invocation Functions
691 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
692 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
693 using DispGetParam/VariantChangeType. */
694 static HRESULT DispGetParam_CopyOnly(
695 DISPPARAMS *pdispparams, /* [in] Parameter list */
696 UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
697 VARIANT *pvarResult) /* [out] Destination for resulting variant */
699 /* position is counted backwards */
702 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
703 *position, pdispparams->cArgs, pdispparams->cNamedArgs);
704 if (*position < pdispparams->cArgs) {
705 /* positional arg? */
706 pos = pdispparams->cArgs - *position - 1;
708 /* FIXME: is this how to handle named args? */
709 for (pos=0; pos<pdispparams->cNamedArgs; pos++)
710 if (pdispparams->rgdispidNamedArgs[pos] == *position) break;
712 if (pos==pdispparams->cNamedArgs)
713 return DISP_E_PARAMNOTFOUND;
716 return VariantCopyInd(pvarResult,
717 &pdispparams->rgvarg[pos]);
720 static HRESULT SummaryInfoImpl_Invoke(
721 AutomationObject* This,
726 DISPPARAMS* pDispParams,
728 EXCEPINFO* pExcepInfo,
732 VARIANTARG varg0, varg1;
733 FILETIME ft, ftlocal;
740 switch (dispIdMember)
742 case DISPID_SUMMARYINFO_PROPERTY:
743 if (wFlags & DISPATCH_PROPERTYGET)
751 static WCHAR szEmpty[] = {0};
753 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
754 if (FAILED(hr)) return hr;
755 ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, &value,
756 &ft, szEmpty, &size);
757 if (ret != ERROR_SUCCESS &&
758 ret != ERROR_MORE_DATA)
760 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
761 return DISP_E_EXCEPTION;
771 V_VT(pVarResult) = VT_I4;
772 V_I4(pVarResult) = value;
776 if (!(str = msi_alloc(++size * sizeof(WCHAR))))
777 ERR("Out of memory\n");
778 else if ((ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, NULL,
779 NULL, str, &size)) != ERROR_SUCCESS)
780 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
783 V_VT(pVarResult) = VT_BSTR;
784 V_BSTR(pVarResult) = SysAllocString(str);
790 FileTimeToLocalFileTime(&ft, &ftlocal);
791 FileTimeToSystemTime(&ftlocal, &st);
792 SystemTimeToVariantTime(&st, &date);
794 V_VT(pVarResult) = VT_DATE;
795 V_DATE(pVarResult) = date;
799 ERR("Unhandled variant type %d\n", type);
802 else if (wFlags & DISPATCH_PROPERTYPUT)
804 UINT posValue = DISPID_PROPERTYPUT;
806 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
807 if (FAILED(hr)) return hr;
808 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg1);
811 *puArgErr = posValue;
815 switch (V_VT(&varg1))
819 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), V_VT(&varg1), V_I4(&varg1), NULL, NULL);
823 VariantTimeToSystemTime(V_DATE(&varg1), &st);
824 SystemTimeToFileTime(&st, &ftlocal);
825 LocalFileTimeToFileTime(&ftlocal, &ft);
826 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_FILETIME, 0, &ft, NULL);
830 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_LPSTR, 0, NULL, V_BSTR(&varg1));
834 FIXME("Unhandled variant type %d\n", V_VT(&varg1));
835 VariantClear(&varg1);
836 return DISP_E_EXCEPTION;
839 if (ret != ERROR_SUCCESS)
841 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret);
842 return DISP_E_EXCEPTION;
845 else return DISP_E_MEMBERNOTFOUND;
848 case DISPID_SUMMARYINFO_PROPERTYCOUNT:
849 if (wFlags & DISPATCH_PROPERTYGET) {
851 if ((ret = MsiSummaryInfoGetPropertyCount(This->msiHandle, &count)) != ERROR_SUCCESS)
852 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret);
855 V_VT(pVarResult) = VT_I4;
856 V_I4(pVarResult) = count;
859 else return DISP_E_MEMBERNOTFOUND;
863 return DISP_E_MEMBERNOTFOUND;
866 VariantClear(&varg1);
867 VariantClear(&varg0);
872 static HRESULT RecordImpl_Invoke(
873 AutomationObject* This,
878 DISPPARAMS* pDispParams,
880 EXCEPINFO* pExcepInfo,
886 VARIANTARG varg0, varg1;
892 switch (dispIdMember)
894 case DISPID_RECORD_FIELDCOUNT:
895 if (wFlags & DISPATCH_PROPERTYGET) {
896 V_VT(pVarResult) = VT_I4;
897 V_I4(pVarResult) = MsiRecordGetFieldCount(This->msiHandle);
899 else return DISP_E_MEMBERNOTFOUND;
902 case DISPID_RECORD_STRINGDATA:
903 if (wFlags & DISPATCH_PROPERTYGET) {
904 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
905 if (FAILED(hr)) return hr;
906 V_VT(pVarResult) = VT_BSTR;
907 V_BSTR(pVarResult) = NULL;
908 if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
910 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
911 ERR("Out of memory\n");
912 else if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
913 V_BSTR(pVarResult) = SysAllocString(szString);
916 if (ret != ERROR_SUCCESS)
917 ERR("MsiRecordGetString returned %d\n", ret);
918 } else if (wFlags & DISPATCH_PROPERTYPUT) {
919 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
920 if (FAILED(hr)) return hr;
921 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_BSTR, &varg1, puArgErr);
922 if (FAILED(hr)) return hr;
923 if ((ret = MsiRecordSetStringW(This->msiHandle, V_I4(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
925 VariantClear(&varg1);
926 ERR("MsiRecordSetString returned %d\n", ret);
927 return DISP_E_EXCEPTION;
930 else return DISP_E_MEMBERNOTFOUND;
933 case DISPID_RECORD_INTEGERDATA:
934 if (wFlags & DISPATCH_PROPERTYGET) {
935 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
936 if (FAILED(hr)) return hr;
937 V_VT(pVarResult) = VT_I4;
938 V_I4(pVarResult) = MsiRecordGetInteger(This->msiHandle, V_I4(&varg0));
939 } else if (wFlags & DISPATCH_PROPERTYPUT) {
940 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
941 if (FAILED(hr)) return hr;
942 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_I4, &varg1, puArgErr);
943 if (FAILED(hr)) return hr;
944 if ((ret = MsiRecordSetInteger(This->msiHandle, V_I4(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
946 ERR("MsiRecordSetInteger returned %d\n", ret);
947 return DISP_E_EXCEPTION;
950 else return DISP_E_MEMBERNOTFOUND;
954 return DISP_E_MEMBERNOTFOUND;
957 VariantClear(&varg1);
958 VariantClear(&varg0);
963 static HRESULT ListImpl_Invoke(
964 AutomationObject* This,
969 DISPPARAMS* pDispParams,
971 EXCEPINFO* pExcepInfo,
974 ListObject *list = (ListObject*)This;
975 IUnknown *pUnk = NULL;
978 switch (dispIdMember)
980 case DISPID_LIST__NEWENUM:
981 if (wFlags & DISPATCH_METHOD) {
982 V_VT(pVarResult) = VT_UNKNOWN;
983 if (SUCCEEDED(hr = create_list_enumerator(list, (LPVOID *)&pUnk)))
984 V_UNKNOWN(pVarResult) = pUnk;
986 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr);
988 else return DISP_E_MEMBERNOTFOUND;
991 case DISPID_LIST_ITEM:
992 if (wFlags & DISPATCH_PROPERTYGET) {
996 hr = DispGetParam(pDispParams, 0, VT_I4, &index, puArgErr);
997 if (FAILED(hr)) return hr;
998 if (V_I4(&index) < 0 || V_I4(&index) >= list->count)
999 return DISP_E_BADINDEX;
1000 VariantCopy(pVarResult, &list->data[V_I4(&index)]);
1002 else return DISP_E_MEMBERNOTFOUND;
1005 case DISPID_LIST_COUNT:
1006 if (wFlags & DISPATCH_PROPERTYGET) {
1007 V_VT(pVarResult) = VT_I4;
1008 V_I4(pVarResult) = list->count;
1010 else return DISP_E_MEMBERNOTFOUND;
1014 return DISP_E_MEMBERNOTFOUND;
1020 static void ListImpl_Free(AutomationObject *This)
1022 ListObject *list = (ListObject*)This;
1025 for (i = 0; i < list->count; i++)
1026 VariantClear(&list->data[i]);
1027 msi_free(list->data);
1030 static HRESULT get_products_count(const WCHAR *product, int *len)
1036 WCHAR dataW[GUID_SIZE];
1039 /* all or related only */
1041 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1043 ret = MsiEnumProductsW(i, dataW);
1045 if (ret == ERROR_NO_MORE_ITEMS) break;
1047 if (ret != ERROR_SUCCESS)
1048 return DISP_E_EXCEPTION;
1058 static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
1064 list = msi_alloc_zero(sizeof(ListObject));
1065 if (!list) return E_OUTOFMEMORY;
1067 hr = init_automation_object(&list->autoobj, 0, &DIID_StringList, ListImpl_Invoke, ListImpl_Free);
1074 *dispatch = &list->autoobj.IDispatch_iface;
1076 hr = get_products_count(product, &list->count);
1079 IDispatch_Release(*dispatch);
1083 list->data = msi_alloc(list->count*sizeof(VARIANT));
1086 IDispatch_Release(*dispatch);
1087 return E_OUTOFMEMORY;
1090 for (i = 0; i < list->count; i++)
1092 WCHAR dataW[GUID_SIZE];
1095 /* all or related only */
1097 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1099 ret = MsiEnumProductsW(i, dataW);
1101 if (ret == ERROR_NO_MORE_ITEMS) break;
1103 V_VT(&list->data[i]) = VT_BSTR;
1104 V_BSTR(&list->data[i]) = SysAllocString(dataW);
1110 static HRESULT ViewImpl_Invoke(
1111 AutomationObject* This,
1112 DISPID dispIdMember,
1116 DISPPARAMS* pDispParams,
1117 VARIANT* pVarResult,
1118 EXCEPINFO* pExcepInfo,
1121 MSIHANDLE msiHandle;
1122 IDispatch *pDispatch = NULL;
1124 VARIANTARG varg0, varg1;
1127 VariantInit(&varg0);
1128 VariantInit(&varg1);
1130 switch (dispIdMember)
1132 case DISPID_VIEW_EXECUTE:
1133 if (wFlags & DISPATCH_METHOD)
1135 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &varg0, puArgErr);
1136 if (SUCCEEDED(hr) && V_DISPATCH(&varg0) != NULL)
1137 MsiViewExecute(This->msiHandle, ((AutomationObject *)V_DISPATCH(&varg0))->msiHandle);
1139 MsiViewExecute(This->msiHandle, 0);
1141 else return DISP_E_MEMBERNOTFOUND;
1144 case DISPID_VIEW_FETCH:
1145 if (wFlags & DISPATCH_METHOD)
1147 V_VT(pVarResult) = VT_DISPATCH;
1148 if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS)
1150 if (SUCCEEDED(hr = create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Record, RecordImpl_Invoke, NULL)))
1151 V_DISPATCH(pVarResult) = pDispatch;
1153 ERR("Failed to create Record object, hresult 0x%08x\n", hr);
1155 else if (ret == ERROR_NO_MORE_ITEMS)
1156 V_DISPATCH(pVarResult) = NULL;
1159 ERR("MsiViewFetch returned %d\n", ret);
1160 return DISP_E_EXCEPTION;
1163 else return DISP_E_MEMBERNOTFOUND;
1166 case DISPID_VIEW_MODIFY:
1167 if (wFlags & DISPATCH_METHOD)
1169 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1170 if (FAILED(hr)) return hr;
1171 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1172 if (FAILED(hr)) return hr;
1173 if (!V_DISPATCH(&varg1)) return DISP_E_EXCEPTION;
1174 if ((ret = MsiViewModify(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle)) != ERROR_SUCCESS)
1176 VariantClear(&varg1);
1177 ERR("MsiViewModify returned %d\n", ret);
1178 return DISP_E_EXCEPTION;
1181 else return DISP_E_MEMBERNOTFOUND;
1184 case DISPID_VIEW_CLOSE:
1185 if (wFlags & DISPATCH_METHOD)
1187 MsiViewClose(This->msiHandle);
1189 else return DISP_E_MEMBERNOTFOUND;
1193 return DISP_E_MEMBERNOTFOUND;
1196 VariantClear(&varg1);
1197 VariantClear(&varg0);
1202 static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
1203 DISPPARAMS* pDispParams,
1204 VARIANT* pVarResult,
1205 EXCEPINFO* pExcepInfo,
1208 if (!(wFlags & DISPATCH_METHOD))
1209 return DISP_E_MEMBERNOTFOUND;
1213 VariantInit(pVarResult);
1217 static HRESULT DatabaseImpl_Invoke(
1218 AutomationObject* This,
1219 DISPID dispIdMember,
1223 DISPPARAMS* pDispParams,
1224 VARIANT* pVarResult,
1225 EXCEPINFO* pExcepInfo,
1228 MSIHANDLE msiHandle;
1229 IDispatch *pDispatch = NULL;
1231 VARIANTARG varg0, varg1;
1234 VariantInit(&varg0);
1235 VariantInit(&varg1);
1237 switch (dispIdMember)
1239 case DISPID_DATABASE_SUMMARYINFORMATION:
1240 if (wFlags & DISPATCH_PROPERTYGET)
1242 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1246 V_VT(pVarResult) = VT_DISPATCH;
1247 if ((ret = MsiGetSummaryInformationW(This->msiHandle, NULL, V_I4(&varg0), &msiHandle)) == ERROR_SUCCESS)
1249 hr = create_automation_object(msiHandle, NULL, (LPVOID *)&pDispatch, &DIID_SummaryInfo, SummaryInfoImpl_Invoke, NULL);
1251 V_DISPATCH(pVarResult) = pDispatch;
1253 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr);
1257 ERR("MsiGetSummaryInformation returned %d\n", ret);
1258 return DISP_E_EXCEPTION;
1261 else return DISP_E_MEMBERNOTFOUND;
1264 case DISPID_DATABASE_OPENVIEW:
1265 if (wFlags & DISPATCH_METHOD)
1267 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1268 if (FAILED(hr)) return hr;
1269 V_VT(pVarResult) = VT_DISPATCH;
1270 if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS)
1272 if (SUCCEEDED(hr = create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_View, ViewImpl_Invoke, NULL)))
1273 V_DISPATCH(pVarResult) = pDispatch;
1275 ERR("Failed to create View object, hresult 0x%08x\n", hr);
1279 VariantClear(&varg0);
1280 ERR("MsiDatabaseOpenView returned %d\n", ret);
1281 return DISP_E_EXCEPTION;
1284 else return DISP_E_MEMBERNOTFOUND;
1287 case DISPID_INSTALLER_LASTERRORRECORD:
1288 return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
1289 pVarResult, pExcepInfo,
1293 return DISP_E_MEMBERNOTFOUND;
1296 VariantClear(&varg1);
1297 VariantClear(&varg0);
1302 static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
1304 AutomationObject *database;
1307 TRACE("(%d %p)\n", msiHandle, dispatch);
1309 database = msi_alloc(sizeof(AutomationObject));
1310 if (!database) return E_OUTOFMEMORY;
1312 hr = init_automation_object(database, msiHandle, &DIID_Database, DatabaseImpl_Invoke, NULL);
1319 *dispatch = &database->IDispatch_iface;
1324 static HRESULT SessionImpl_Invoke(
1325 AutomationObject* This,
1326 DISPID dispIdMember,
1330 DISPPARAMS* pDispParams,
1331 VARIANT* pVarResult,
1332 EXCEPINFO* pExcepInfo,
1335 SessionObject *session = (SessionObject*)This;
1338 MSIHANDLE msiHandle;
1341 INSTALLSTATE iInstalled, iAction;
1342 VARIANTARG varg0, varg1;
1345 VariantInit(&varg0);
1346 VariantInit(&varg1);
1348 switch (dispIdMember)
1350 case DISPID_SESSION_INSTALLER:
1351 if (wFlags & DISPATCH_PROPERTYGET) {
1352 V_VT(pVarResult) = VT_DISPATCH;
1353 IDispatch_AddRef(session->installer);
1354 V_DISPATCH(pVarResult) = session->installer;
1356 else return DISP_E_MEMBERNOTFOUND;
1359 case DISPID_SESSION_PROPERTY:
1360 if (wFlags & DISPATCH_PROPERTYGET) {
1361 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1362 if (FAILED(hr)) return hr;
1363 V_VT(pVarResult) = VT_BSTR;
1364 V_BSTR(pVarResult) = NULL;
1365 if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
1367 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
1368 ERR("Out of memory\n");
1369 else if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
1370 V_BSTR(pVarResult) = SysAllocString(szString);
1373 if (ret != ERROR_SUCCESS)
1374 ERR("MsiGetProperty returned %d\n", ret);
1375 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1376 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1377 if (FAILED(hr)) return hr;
1378 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_BSTR, &varg1, puArgErr);
1380 VariantClear(&varg0);
1383 if ((ret = MsiSetPropertyW(This->msiHandle, V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
1385 VariantClear(&varg0);
1386 VariantClear(&varg1);
1387 ERR("MsiSetProperty returned %d\n", ret);
1388 return DISP_E_EXCEPTION;
1391 else return DISP_E_MEMBERNOTFOUND;
1394 case DISPID_SESSION_LANGUAGE:
1395 if (wFlags & DISPATCH_PROPERTYGET) {
1396 langId = MsiGetLanguage(This->msiHandle);
1397 V_VT(pVarResult) = VT_I4;
1398 V_I4(pVarResult) = langId;
1400 else return DISP_E_MEMBERNOTFOUND;
1403 case DISPID_SESSION_MODE:
1404 if (wFlags & DISPATCH_PROPERTYGET) {
1405 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1406 if (FAILED(hr)) return hr;
1407 V_VT(pVarResult) = VT_BOOL;
1408 V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0));
1409 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1410 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1411 if (FAILED(hr)) return hr;
1412 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_BOOL, &varg1, puArgErr);
1413 if (FAILED(hr)) return hr;
1414 if ((ret = MsiSetMode(This->msiHandle, V_I4(&varg0), V_BOOL(&varg1))) != ERROR_SUCCESS)
1416 ERR("MsiSetMode returned %d\n", ret);
1417 return DISP_E_EXCEPTION;
1420 else return DISP_E_MEMBERNOTFOUND;
1423 case DISPID_SESSION_DATABASE:
1424 if (wFlags & DISPATCH_PROPERTYGET) {
1425 V_VT(pVarResult) = VT_DISPATCH;
1426 if ((msiHandle = MsiGetActiveDatabase(This->msiHandle)))
1428 IDispatch *dispatch;
1430 if (SUCCEEDED(hr = create_database(msiHandle, &dispatch)))
1431 V_DISPATCH(pVarResult) = dispatch;
1433 ERR("Failed to create Database object, hresult 0x%08x\n", hr);
1437 ERR("MsiGetActiveDatabase failed\n");
1438 return DISP_E_EXCEPTION;
1441 else return DISP_E_MEMBERNOTFOUND;
1444 case DISPID_SESSION_DOACTION:
1445 if (wFlags & DISPATCH_METHOD) {
1446 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1447 if (FAILED(hr)) return hr;
1448 ret = MsiDoActionW(This->msiHandle, V_BSTR(&varg0));
1449 V_VT(pVarResult) = VT_I4;
1452 case ERROR_FUNCTION_NOT_CALLED:
1453 V_I4(pVarResult) = msiDoActionStatusNoAction;
1456 V_I4(pVarResult) = msiDoActionStatusSuccess;
1458 case ERROR_INSTALL_USEREXIT:
1459 V_I4(pVarResult) = msiDoActionStatusUserExit;
1461 case ERROR_INSTALL_FAILURE:
1462 V_I4(pVarResult) = msiDoActionStatusFailure;
1464 case ERROR_INSTALL_SUSPEND:
1465 V_I4(pVarResult) = msiDoActionStatusSuspend;
1467 case ERROR_MORE_DATA:
1468 V_I4(pVarResult) = msiDoActionStatusFinished;
1470 case ERROR_INVALID_HANDLE_STATE:
1471 V_I4(pVarResult) = msiDoActionStatusWrongState;
1473 case ERROR_INVALID_DATA:
1474 V_I4(pVarResult) = msiDoActionStatusBadActionData;
1477 VariantClear(&varg0);
1478 FIXME("MsiDoAction returned unhandled value %d\n", ret);
1479 return DISP_E_EXCEPTION;
1482 else return DISP_E_MEMBERNOTFOUND;
1485 case DISPID_SESSION_EVALUATECONDITION:
1486 if (wFlags & DISPATCH_METHOD) {
1487 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1488 if (FAILED(hr)) return hr;
1489 V_VT(pVarResult) = VT_I4;
1490 V_I4(pVarResult) = MsiEvaluateConditionW(This->msiHandle, V_BSTR(&varg0));
1492 else return DISP_E_MEMBERNOTFOUND;
1495 case DISPID_SESSION_MESSAGE:
1496 if(!(wFlags & DISPATCH_METHOD))
1497 return DISP_E_MEMBERNOTFOUND;
1499 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1500 if (FAILED(hr)) return hr;
1501 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1502 if (FAILED(hr)) return hr;
1504 V_VT(pVarResult) = VT_I4;
1506 MsiProcessMessage(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle);
1509 case DISPID_SESSION_SETINSTALLLEVEL:
1510 if (wFlags & DISPATCH_METHOD) {
1511 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1512 if (FAILED(hr)) return hr;
1513 if ((ret = MsiSetInstallLevel(This->msiHandle, V_I4(&varg0))) != ERROR_SUCCESS)
1515 ERR("MsiSetInstallLevel returned %d\n", ret);
1516 return DISP_E_EXCEPTION;
1519 else return DISP_E_MEMBERNOTFOUND;
1522 case DISPID_SESSION_FEATURECURRENTSTATE:
1523 if (wFlags & DISPATCH_PROPERTYGET) {
1524 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1525 if (FAILED(hr)) return hr;
1526 V_VT(pVarResult) = VT_I4;
1527 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1528 V_I4(pVarResult) = iInstalled;
1531 ERR("MsiGetFeatureState returned %d\n", ret);
1532 V_I4(pVarResult) = msiInstallStateUnknown;
1535 else return DISP_E_MEMBERNOTFOUND;
1538 case DISPID_SESSION_FEATUREREQUESTSTATE:
1539 if (wFlags & DISPATCH_PROPERTYGET) {
1540 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1541 if (FAILED(hr)) return hr;
1542 V_VT(pVarResult) = VT_I4;
1543 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1544 V_I4(pVarResult) = iAction;
1547 ERR("MsiGetFeatureState returned %d\n", ret);
1548 V_I4(pVarResult) = msiInstallStateUnknown;
1550 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1551 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1552 if (FAILED(hr)) return hr;
1553 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_I4, &varg1, puArgErr);
1555 VariantClear(&varg0);
1558 if ((ret = MsiSetFeatureStateW(This->msiHandle, V_BSTR(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
1560 VariantClear(&varg0);
1561 ERR("MsiSetFeatureState returned %d\n", ret);
1562 return DISP_E_EXCEPTION;
1565 else return DISP_E_MEMBERNOTFOUND;
1569 return DISP_E_MEMBERNOTFOUND;
1572 VariantClear(&varg1);
1573 VariantClear(&varg0);
1578 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1579 * registry value type. Used by Installer::RegistryValue. */
1580 static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize)
1582 static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1583 static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 };
1584 WCHAR *szString = (WCHAR *)lpData;
1585 LPWSTR szNewString = NULL;
1586 DWORD dwNewSize = 0;
1591 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1592 case REG_MULTI_SZ: /* Multi SZ change internal null characters to newlines */
1593 idx = (dwSize/sizeof(WCHAR))-1;
1594 while (idx >= 0 && !szString[idx]) idx--;
1595 for (; idx >= 0; idx--)
1596 if (!szString[idx]) szString[idx] = '\n';
1599 V_VT(pVarResult) = VT_BSTR;
1600 V_BSTR(pVarResult) = SysAllocStringByteLen((LPCSTR)szString, dwSize);
1604 if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1605 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1606 else if (!(szNewString = msi_alloc(dwNewSize * sizeof(WCHAR))))
1607 ERR("Out of memory\n");
1608 else if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1609 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1612 V_VT(pVarResult) = VT_BSTR;
1613 V_BSTR(pVarResult) = SysAllocStringLen(szNewString, dwNewSize);
1615 msi_free(szNewString);
1619 V_VT(pVarResult) = VT_I4;
1620 V_I4(pVarResult) = *((DWORD *)lpData);
1624 V_VT(pVarResult) = VT_BSTR;
1625 V_BSTR(pVarResult) = SysAllocString(szREG_); /* Weird string, don't know why native returns it */
1629 V_VT(pVarResult) = VT_BSTR;
1630 V_BSTR(pVarResult) = SysAllocString(szREG_BINARY);
1634 V_VT(pVarResult) = VT_EMPTY;
1638 FIXME("Unhandled registry value type %d\n", dwType);
1642 static HRESULT InstallerImpl_CreateRecord(WORD wFlags,
1643 DISPPARAMS* pDispParams,
1644 VARIANT* pVarResult,
1645 EXCEPINFO* pExcepInfo,
1651 IDispatch* dispatch;
1653 if (!(wFlags & DISPATCH_METHOD))
1654 return DISP_E_MEMBERNOTFOUND;
1656 VariantInit(&varg0);
1657 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1661 V_VT(pVarResult) = VT_DISPATCH;
1663 hrec = MsiCreateRecord(V_I4(&varg0));
1665 return DISP_E_EXCEPTION;
1667 hr = create_automation_object(hrec, NULL, (LPVOID*)&dispatch,
1668 &DIID_Record, RecordImpl_Invoke, NULL);
1670 V_DISPATCH(pVarResult) = dispatch;
1675 static HRESULT InstallerImpl_OpenPackage(AutomationObject* This,
1677 DISPPARAMS* pDispParams,
1678 VARIANT* pVarResult,
1679 EXCEPINFO* pExcepInfo,
1685 IDispatch* dispatch;
1686 VARIANTARG varg0, varg1;
1688 if (!(wFlags & DISPATCH_METHOD))
1689 return DISP_E_MEMBERNOTFOUND;
1691 if (pDispParams->cArgs == 0)
1692 return DISP_E_TYPEMISMATCH;
1694 if (V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1]) != VT_BSTR)
1695 return DISP_E_TYPEMISMATCH;
1697 VariantInit(&varg0);
1698 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1702 VariantInit(&varg1);
1703 if (pDispParams->cArgs == 2)
1705 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1711 V_VT(&varg1) = VT_I4;
1715 V_VT(pVarResult) = VT_DISPATCH;
1717 ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &hpkg);
1718 if (ret != ERROR_SUCCESS)
1720 hr = DISP_E_EXCEPTION;
1724 hr = create_session(hpkg, &This->IDispatch_iface, &dispatch);
1726 V_DISPATCH(pVarResult) = dispatch;
1729 VariantClear(&varg0);
1730 VariantClear(&varg1);
1734 static HRESULT InstallerImpl_OpenProduct(WORD wFlags,
1735 DISPPARAMS* pDispParams,
1736 VARIANT* pVarResult,
1737 EXCEPINFO* pExcepInfo,
1743 if (!(wFlags & DISPATCH_METHOD))
1744 return DISP_E_MEMBERNOTFOUND;
1746 VariantInit(&varg0);
1747 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1751 FIXME("%s\n", debugstr_w(V_BSTR(&varg0)));
1753 VariantInit(pVarResult);
1755 VariantClear(&varg0);
1759 static HRESULT InstallerImpl_OpenDatabase(WORD wFlags,
1760 DISPPARAMS* pDispParams,
1761 VARIANT* pVarResult,
1762 EXCEPINFO* pExcepInfo,
1768 IDispatch* dispatch;
1769 VARIANTARG varg0, varg1;
1771 if (!(wFlags & DISPATCH_METHOD))
1772 return DISP_E_MEMBERNOTFOUND;
1774 VariantInit(&varg0);
1775 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1779 VariantInit(&varg1);
1780 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1784 V_VT(pVarResult) = VT_DISPATCH;
1786 ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &hdb);
1787 if (ret != ERROR_SUCCESS)
1789 hr = DISP_E_EXCEPTION;
1793 hr = create_database(hdb, &dispatch);
1795 V_DISPATCH(pVarResult) = dispatch;
1798 VariantClear(&varg0);
1799 VariantClear(&varg1);
1803 static HRESULT InstallerImpl_SummaryInformation(WORD wFlags,
1804 DISPPARAMS* pDispParams,
1805 VARIANT* pVarResult,
1806 EXCEPINFO* pExcepInfo,
1809 if (!(wFlags & DISPATCH_METHOD))
1810 return DISP_E_MEMBERNOTFOUND;
1814 VariantInit(pVarResult);
1818 static HRESULT InstallerImpl_UILevel(WORD wFlags,
1819 DISPPARAMS* pDispParams,
1820 VARIANT* pVarResult,
1821 EXCEPINFO* pExcepInfo,
1828 if (!(wFlags & DISPATCH_PROPERTYPUT) && !(wFlags & DISPATCH_PROPERTYGET))
1829 return DISP_E_MEMBERNOTFOUND;
1831 if (wFlags & DISPATCH_PROPERTYPUT)
1833 VariantInit(&varg0);
1834 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1838 ui = MsiSetInternalUI(V_I4(&varg0), NULL);
1839 if (ui == INSTALLUILEVEL_NOCHANGE)
1840 return DISP_E_EXCEPTION;
1842 else if (wFlags & DISPATCH_PROPERTYGET)
1844 ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
1845 if (ui == INSTALLUILEVEL_NOCHANGE)
1846 return DISP_E_EXCEPTION;
1848 V_VT(pVarResult) = VT_I4;
1849 V_I4(pVarResult) = ui;
1855 static HRESULT InstallerImpl_EnableLog(WORD wFlags,
1856 DISPPARAMS* pDispParams,
1857 VARIANT* pVarResult,
1858 EXCEPINFO* pExcepInfo,
1861 if (!(wFlags & DISPATCH_METHOD))
1862 return DISP_E_MEMBERNOTFOUND;
1866 VariantInit(pVarResult);
1870 static HRESULT InstallerImpl_InstallProduct(WORD wFlags,
1871 DISPPARAMS* pDispParams,
1872 VARIANT* pVarResult,
1873 EXCEPINFO* pExcepInfo,
1878 VARIANTARG varg0, varg1;
1880 if (!(wFlags & DISPATCH_METHOD))
1881 return DISP_E_MEMBERNOTFOUND;
1883 VariantInit(&varg0);
1884 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1888 VariantInit(&varg1);
1889 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1893 ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1));
1894 if (ret != ERROR_SUCCESS)
1896 hr = DISP_E_EXCEPTION;
1901 VariantClear(&varg0);
1902 VariantClear(&varg1);
1906 static HRESULT InstallerImpl_Version(WORD wFlags,
1907 VARIANT* pVarResult,
1908 EXCEPINFO* pExcepInfo,
1912 DLLVERSIONINFO verinfo;
1913 WCHAR version[MAX_PATH];
1915 static const WCHAR format[] = {
1916 '%','d','.','%','d','.','%','d','.','%','d',0};
1918 if (!(wFlags & DISPATCH_PROPERTYGET))
1919 return DISP_E_MEMBERNOTFOUND;
1921 verinfo.cbSize = sizeof(DLLVERSIONINFO);
1922 hr = DllGetVersion(&verinfo);
1926 sprintfW(version, format, verinfo.dwMajorVersion, verinfo.dwMinorVersion,
1927 verinfo.dwBuildNumber, verinfo.dwPlatformID);
1929 V_VT(pVarResult) = VT_BSTR;
1930 V_BSTR(pVarResult) = SysAllocString(version);
1934 static HRESULT InstallerImpl_LastErrorRecord(WORD wFlags,
1935 DISPPARAMS* pDispParams,
1936 VARIANT* pVarResult,
1937 EXCEPINFO* pExcepInfo,
1940 if (!(wFlags & DISPATCH_METHOD))
1941 return DISP_E_MEMBERNOTFOUND;
1945 VariantInit(pVarResult);
1949 static HRESULT InstallerImpl_RegistryValue(WORD wFlags,
1950 DISPPARAMS* pDispParams,
1951 VARIANT* pVarResult,
1952 EXCEPINFO* pExcepInfo,
1960 LPWSTR szString = NULL;
1961 VARIANTARG varg0, varg1, varg2;
1963 if (!(wFlags & DISPATCH_METHOD))
1964 return DISP_E_MEMBERNOTFOUND;
1966 VariantInit(&varg0);
1967 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1971 VariantInit(&varg1);
1972 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1976 /* Save valuePos so we can save puArgErr if we are unable to do our type
1980 VariantInit(&varg2);
1981 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2);
1985 if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT &&
1986 V_I4(&varg0) <= REG_INDEX_DYN_DATA)
1988 V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT;
1991 ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey);
1993 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
1994 if (ret != ERROR_SUCCESS && V_VT(&varg2) != VT_EMPTY)
1996 hr = DISP_E_BADINDEX;
2000 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2001 switch (V_VT(&varg2))
2003 /* Return VT_BOOL clarifying whether registry key exists or not. */
2005 V_VT(pVarResult) = VT_BOOL;
2006 V_BOOL(pVarResult) = (ret == ERROR_SUCCESS);
2009 /* Return the value of specified key if it exists. */
2011 ret = RegQueryValueExW(hkey, V_BSTR(&varg2),
2012 NULL, NULL, NULL, &size);
2013 if (ret != ERROR_SUCCESS)
2015 hr = DISP_E_BADINDEX;
2019 szString = msi_alloc(size);
2026 ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL,
2027 &type, (LPBYTE)szString, &size);
2028 if (ret != ERROR_SUCCESS)
2031 hr = DISP_E_BADINDEX;
2035 variant_from_registry_value(pVarResult, type,
2036 (LPBYTE)szString, size);
2040 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2042 hr = VariantChangeType(&varg2, &varg2, 0, VT_I4);
2045 if (hr == DISP_E_TYPEMISMATCH)
2046 *puArgErr = posValue;
2051 /* Retrieve class name or maximum value name or subkey name size. */
2053 ret = RegQueryInfoKeyW(hkey, NULL, &size, NULL, NULL, NULL,
2054 NULL, NULL, NULL, NULL, NULL, NULL);
2055 else if (V_I4(&varg2) > 0)
2056 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL,
2057 NULL, NULL, &size, NULL, NULL, NULL);
2058 else /* V_I4(&varg2) < 0 */
2059 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &size,
2060 NULL, NULL, NULL, NULL, NULL, NULL);
2062 if (ret != ERROR_SUCCESS)
2065 szString = msi_alloc(++size * sizeof(WCHAR));
2073 ret = RegQueryInfoKeyW(hkey, szString, &size,NULL, NULL, NULL,
2074 NULL, NULL, NULL, NULL, NULL, NULL);
2075 else if (V_I4(&varg2) > 0)
2076 ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString,
2077 &size, 0, 0, NULL, NULL);
2078 else /* V_I4(&varg2) < 0 */
2079 ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, size);
2081 if (ret == ERROR_SUCCESS)
2083 V_VT(pVarResult) = VT_BSTR;
2084 V_BSTR(pVarResult) = SysAllocString(szString);
2091 VariantClear(&varg0);
2092 VariantClear(&varg1);
2093 VariantClear(&varg2);
2098 static HRESULT InstallerImpl_Environment(WORD wFlags,
2099 DISPPARAMS* pDispParams,
2100 VARIANT* pVarResult,
2101 EXCEPINFO* pExcepInfo,
2104 if (!(wFlags & DISPATCH_METHOD))
2105 return DISP_E_MEMBERNOTFOUND;
2109 VariantInit(pVarResult);
2113 static HRESULT InstallerImpl_FileAttributes(WORD wFlags,
2114 DISPPARAMS* pDispParams,
2115 VARIANT* pVarResult,
2116 EXCEPINFO* pExcepInfo,
2119 if (!(wFlags & DISPATCH_METHOD))
2120 return DISP_E_MEMBERNOTFOUND;
2124 VariantInit(pVarResult);
2128 static HRESULT InstallerImpl_FileSize(WORD wFlags,
2129 DISPPARAMS* pDispParams,
2130 VARIANT* pVarResult,
2131 EXCEPINFO* pExcepInfo,
2134 if (!(wFlags & DISPATCH_METHOD))
2135 return DISP_E_MEMBERNOTFOUND;
2139 VariantInit(pVarResult);
2143 static HRESULT InstallerImpl_FileVersion(WORD wFlags,
2144 DISPPARAMS* pDispParams,
2145 VARIANT* pVarResult,
2146 EXCEPINFO* pExcepInfo,
2149 if (!(wFlags & DISPATCH_METHOD))
2150 return DISP_E_MEMBERNOTFOUND;
2154 VariantInit(pVarResult);
2158 static HRESULT InstallerImpl_ProductState(WORD wFlags,
2159 DISPPARAMS* pDispParams,
2160 VARIANT* pVarResult,
2161 EXCEPINFO* pExcepInfo,
2167 if (!(wFlags & DISPATCH_PROPERTYGET))
2168 return DISP_E_MEMBERNOTFOUND;
2170 VariantInit(&varg0);
2171 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2175 V_VT(pVarResult) = VT_I4;
2176 V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0));
2178 VariantClear(&varg0);
2182 static HRESULT InstallerImpl_ProductInfo(WORD wFlags,
2183 DISPPARAMS* pDispParams,
2184 VARIANT* pVarResult,
2185 EXCEPINFO* pExcepInfo,
2192 VARIANTARG varg0, varg1;
2194 if (!(wFlags & DISPATCH_PROPERTYGET))
2195 return DISP_E_MEMBERNOTFOUND;
2197 VariantInit(&varg0);
2198 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2202 VariantInit(&varg1);
2203 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
2207 V_VT(pVarResult) = VT_BSTR;
2208 V_BSTR(pVarResult) = NULL;
2210 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &size);
2211 if (ret != ERROR_SUCCESS)
2213 hr = DISP_E_EXCEPTION;
2217 str = msi_alloc(++size * sizeof(WCHAR));
2224 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), str, &size);
2225 if (ret != ERROR_SUCCESS)
2227 hr = DISP_E_EXCEPTION;
2231 V_BSTR(pVarResult) = SysAllocString(str);
2236 VariantClear(&varg0);
2237 VariantClear(&varg1);
2241 static HRESULT InstallerImpl_Products(WORD flags,
2242 DISPPARAMS* pDispParams,
2244 EXCEPINFO* pExcepInfo,
2247 IDispatch *dispatch;
2250 if (!(flags & DISPATCH_PROPERTYGET))
2251 return DISP_E_MEMBERNOTFOUND;
2253 hr = create_list(NULL, &dispatch);
2257 V_VT(result) = VT_DISPATCH;
2258 V_DISPATCH(result) = dispatch;
2263 static HRESULT InstallerImpl_RelatedProducts(WORD flags,
2264 DISPPARAMS* pDispParams,
2266 EXCEPINFO* pExcepInfo,
2269 IDispatch* dispatch;
2273 if (!(flags & DISPATCH_PROPERTYGET))
2274 return DISP_E_MEMBERNOTFOUND;
2276 VariantInit(&related);
2277 hr = DispGetParam(pDispParams, 0, VT_BSTR, &related, puArgErr);
2281 hr = create_list(V_BSTR(&related), &dispatch);
2282 VariantClear(&related);
2284 V_VT(result) = VT_DISPATCH;
2285 V_DISPATCH(result) = dispatch;
2290 static HRESULT InstallerImpl_Invoke(
2291 AutomationObject* This,
2292 DISPID dispIdMember,
2296 DISPPARAMS* pDispParams,
2297 VARIANT* pVarResult,
2298 EXCEPINFO* pExcepInfo,
2301 switch (dispIdMember)
2303 case DISPID_INSTALLER_CREATERECORD:
2304 return InstallerImpl_CreateRecord(wFlags, pDispParams,
2305 pVarResult, pExcepInfo, puArgErr);
2307 case DISPID_INSTALLER_OPENPACKAGE:
2308 return InstallerImpl_OpenPackage(This, wFlags, pDispParams,
2309 pVarResult, pExcepInfo, puArgErr);
2311 case DISPID_INSTALLER_OPENPRODUCT:
2312 return InstallerImpl_OpenProduct(wFlags, pDispParams,
2313 pVarResult, pExcepInfo, puArgErr);
2315 case DISPID_INSTALLER_OPENDATABASE:
2316 return InstallerImpl_OpenDatabase(wFlags, pDispParams,
2317 pVarResult, pExcepInfo, puArgErr);
2319 case DISPID_INSTALLER_SUMMARYINFORMATION:
2320 return InstallerImpl_SummaryInformation(wFlags, pDispParams,
2321 pVarResult, pExcepInfo,
2324 case DISPID_INSTALLER_UILEVEL:
2325 return InstallerImpl_UILevel(wFlags, pDispParams,
2326 pVarResult, pExcepInfo, puArgErr);
2328 case DISPID_INSTALLER_ENABLELOG:
2329 return InstallerImpl_EnableLog(wFlags, pDispParams,
2330 pVarResult, pExcepInfo, puArgErr);
2332 case DISPID_INSTALLER_INSTALLPRODUCT:
2333 return InstallerImpl_InstallProduct(wFlags, pDispParams,
2334 pVarResult, pExcepInfo,
2337 case DISPID_INSTALLER_VERSION:
2338 return InstallerImpl_Version(wFlags, pVarResult,
2339 pExcepInfo, puArgErr);
2341 case DISPID_INSTALLER_LASTERRORRECORD:
2342 return InstallerImpl_LastErrorRecord(wFlags, pDispParams,
2343 pVarResult, pExcepInfo,
2346 case DISPID_INSTALLER_REGISTRYVALUE:
2347 return InstallerImpl_RegistryValue(wFlags, pDispParams,
2348 pVarResult, pExcepInfo,
2351 case DISPID_INSTALLER_ENVIRONMENT:
2352 return InstallerImpl_Environment(wFlags, pDispParams,
2353 pVarResult, pExcepInfo, puArgErr);
2355 case DISPID_INSTALLER_FILEATTRIBUTES:
2356 return InstallerImpl_FileAttributes(wFlags, pDispParams,
2357 pVarResult, pExcepInfo,
2360 case DISPID_INSTALLER_FILESIZE:
2361 return InstallerImpl_FileSize(wFlags, pDispParams,
2362 pVarResult, pExcepInfo, puArgErr);
2364 case DISPID_INSTALLER_FILEVERSION:
2365 return InstallerImpl_FileVersion(wFlags, pDispParams,
2366 pVarResult, pExcepInfo, puArgErr);
2368 case DISPID_INSTALLER_PRODUCTSTATE:
2369 return InstallerImpl_ProductState(wFlags, pDispParams,
2370 pVarResult, pExcepInfo, puArgErr);
2372 case DISPID_INSTALLER_PRODUCTINFO:
2373 return InstallerImpl_ProductInfo(wFlags, pDispParams,
2374 pVarResult, pExcepInfo, puArgErr);
2376 case DISPID_INSTALLER_PRODUCTS:
2377 return InstallerImpl_Products(wFlags, pDispParams,
2378 pVarResult, pExcepInfo, puArgErr);
2380 case DISPID_INSTALLER_RELATEDPRODUCTS:
2381 return InstallerImpl_RelatedProducts(wFlags, pDispParams,
2382 pVarResult, pExcepInfo,
2386 return DISP_E_MEMBERNOTFOUND;
2390 HRESULT create_msiserver(IUnknown *outer, void **ppObj)
2392 AutomationObject *installer;
2395 TRACE("(%p %p)\n", outer, ppObj);
2398 return CLASS_E_NOAGGREGATION;
2400 installer = msi_alloc(sizeof(AutomationObject));
2401 if (!installer) return E_OUTOFMEMORY;
2403 hr = init_automation_object(installer, 0, &DIID_Installer, InstallerImpl_Invoke, NULL);
2406 msi_free(installer);
2410 *ppObj = &installer->IDispatch_iface;
2415 HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **disp)
2417 SessionObject *session;
2420 session = msi_alloc(sizeof(SessionObject));
2421 if (!session) return E_OUTOFMEMORY;
2423 hr = init_automation_object(&session->autoobj, msiHandle, &DIID_Session, SessionImpl_Invoke, NULL);
2430 session->installer = installer;
2431 *disp = &session->autoobj.IDispatch_iface;