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.
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_database(MSIHANDLE, IDispatch**);
84 static HRESULT create_list_enumerator(ListObject*, void**);
85 static HRESULT create_summaryinfo(MSIHANDLE, IDispatch**);
86 static HRESULT create_view(MSIHANDLE, IDispatch**);
88 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
90 IEnumVARIANT IEnumVARIANT_iface;
93 /* Current position and pointer to AutomationObject that stores actual data */
99 AutomationObject autoobj;
100 IDispatch *installer;
103 static inline AutomationObject *impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo *iface )
105 return CONTAINING_RECORD(iface, AutomationObject, IProvideMultipleClassInfo_iface);
108 static inline AutomationObject *impl_from_IDispatch( IDispatch *iface )
110 return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface);
113 /* Load type info so we don't have to process GetIDsOfNames */
114 HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid)
116 static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
117 ITypeInfo *ti = NULL;
118 ITypeLib *lib = NULL;
121 TRACE("(%p)->(%s, %d)\n", iface, debugstr_guid(clsid), lcid);
123 /* Load registered type library */
124 hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, lcid, &lib);
126 hr = LoadTypeLib(msiserverW, &lib);
128 ERR("Could not load msiserver.tlb\n");
133 /* Get type information for object */
134 hr = ITypeLib_GetTypeInfoOfGuid(lib, clsid, &ti);
135 ITypeLib_Release(lib);
137 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid));
144 /* AutomationObject methods */
145 static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject)
147 AutomationObject *This = impl_from_IDispatch(iface);
149 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
151 if (ppvObject == NULL)
156 if (IsEqualGUID(riid, &IID_IUnknown) ||
157 IsEqualGUID(riid, &IID_IDispatch) ||
158 IsEqualGUID(riid, This->clsid))
159 *ppvObject = &This->IDispatch_iface;
160 else if (IsEqualGUID(riid, &IID_IProvideClassInfo) ||
161 IsEqualGUID(riid, &IID_IProvideClassInfo2) ||
162 IsEqualGUID(riid, &IID_IProvideMultipleClassInfo))
163 *ppvObject = &This->IProvideMultipleClassInfo_iface;
166 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid));
167 return E_NOINTERFACE;
170 IDispatch_AddRef(iface);
175 static ULONG WINAPI AutomationObject_AddRef(IDispatch* iface)
177 AutomationObject *This = impl_from_IDispatch(iface);
179 TRACE("(%p/%p)\n", iface, This);
181 return InterlockedIncrement(&This->ref);
184 static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
186 AutomationObject *This = impl_from_IDispatch(iface);
187 ULONG ref = InterlockedDecrement(&This->ref);
189 TRACE("(%p/%p)\n", iface, This);
193 if (This->funcFree) This->funcFree(This);
194 ITypeInfo_Release(This->iTypeInfo);
195 MsiCloseHandle(This->msiHandle);
202 static HRESULT WINAPI AutomationObject_GetTypeInfoCount(
206 AutomationObject *This = impl_from_IDispatch(iface);
208 TRACE("(%p/%p)->(%p)\n", iface, This, pctinfo);
213 static HRESULT WINAPI AutomationObject_GetTypeInfo(
219 AutomationObject *This = impl_from_IDispatch(iface);
220 TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo);
222 ITypeInfo_AddRef(This->iTypeInfo);
223 *ppTInfo = This->iTypeInfo;
227 static HRESULT WINAPI AutomationObject_GetIDsOfNames(
235 AutomationObject *This = impl_from_IDispatch(iface);
237 TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId);
239 if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG;
240 hr = ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
241 if (hr == DISP_E_UNKNOWNNAME)
244 for (idx=0; idx<cNames; idx++)
246 if (rgDispId[idx] == DISPID_UNKNOWN)
247 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(This->clsid));
253 /* Maximum number of allowed function parameters+1 */
254 #define MAX_FUNC_PARAMS 20
256 /* Some error checking is done here to simplify individual object function invocation */
257 static HRESULT WINAPI AutomationObject_Invoke(
263 DISPPARAMS* pDispParams,
265 EXCEPINFO* pExcepInfo,
268 AutomationObject *This = impl_from_IDispatch(iface);
270 unsigned int uArgErr;
271 VARIANT varResultDummy;
272 BSTR bstrName = NULL;
274 TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface, This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
276 if (!IsEqualIID(riid, &IID_NULL))
278 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
279 return DISP_E_UNKNOWNNAME;
282 if (wFlags & DISPATCH_PROPERTYGET && !pVarResult)
284 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
285 return DISP_E_PARAMNOTOPTIONAL;
288 /* This simplifies our individual object invocation functions */
289 if (puArgErr == NULL) puArgErr = &uArgErr;
290 if (pVarResult == NULL) pVarResult = &varResultDummy;
292 /* Assume return type is void unless determined otherwise */
293 VariantInit(pVarResult);
295 /* If we are tracing, we want to see the name of the member we are invoking */
298 ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL);
299 TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName));
302 hr = This->funcInvoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
304 if (hr == DISP_E_MEMBERNOTFOUND) {
305 if (bstrName == NULL) ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL);
306 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, debugstr_guid(This->clsid));
308 else if (pExcepInfo &&
309 (hr == DISP_E_PARAMNOTFOUND ||
310 hr == DISP_E_EXCEPTION)) {
311 static const WCHAR szComma[] = { ',',0 };
312 static const WCHAR szExceptionSource[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
313 WCHAR szExceptionDescription[MAX_PATH];
314 BSTR bstrParamNames[MAX_FUNC_PARAMS];
318 if (FAILED(ITypeInfo_GetNames(This->iTypeInfo, dispIdMember, bstrParamNames,
319 MAX_FUNC_PARAMS, &namesNo)))
321 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember);
325 memset(szExceptionDescription, 0, sizeof(szExceptionDescription));
326 for (i=0; i<namesNo; i++)
328 if (bFirst) bFirst = FALSE;
330 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], szComma);
332 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], bstrParamNames[i]);
333 SysFreeString(bstrParamNames[i]);
336 memset(pExcepInfo, 0, sizeof(EXCEPINFO));
337 pExcepInfo->wCode = 1000;
338 pExcepInfo->bstrSource = SysAllocString(szExceptionSource);
339 pExcepInfo->bstrDescription = SysAllocString(szExceptionDescription);
340 hr = DISP_E_EXCEPTION;
344 /* Make sure we free the return variant if it is our dummy variant */
345 if (pVarResult == &varResultDummy) VariantClear(pVarResult);
347 /* Free function name if we retrieved it */
348 SysFreeString(bstrName);
350 TRACE("Returning 0x%08x, %s\n", hr, SUCCEEDED(hr) ? "ok" : "not ok");
355 static const struct IDispatchVtbl AutomationObjectVtbl =
357 AutomationObject_QueryInterface,
358 AutomationObject_AddRef,
359 AutomationObject_Release,
360 AutomationObject_GetTypeInfoCount,
361 AutomationObject_GetTypeInfo,
362 AutomationObject_GetIDsOfNames,
363 AutomationObject_Invoke
367 * IProvideMultipleClassInfo methods
370 static HRESULT WINAPI ProvideMultipleClassInfo_QueryInterface(
371 IProvideMultipleClassInfo* iface,
375 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
376 return IDispatch_QueryInterface(&This->IDispatch_iface, riid, ppvoid);
379 static ULONG WINAPI ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo* iface)
381 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
382 return IDispatch_AddRef(&This->IDispatch_iface);
385 static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo* iface)
387 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
388 return IDispatch_Release(&This->IDispatch_iface);
391 static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI)
393 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
394 TRACE("(%p/%p)->(%p)\n", iface, This, ppTI);
395 return load_type_info(&This->IDispatch_iface, ppTI, This->clsid, 0);
398 static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID)
400 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
401 TRACE("(%p/%p)->(%d,%s)\n", iface, This, dwGuidKind, debugstr_guid(pGUID));
403 if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
406 *pGUID = *This->clsid;
411 static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo* iface, ULONG* pcti)
413 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
415 TRACE("(%p/%p)->(%p)\n", iface, This, pcti);
420 static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface,
423 ITypeInfo** pptiCoClass,
425 ULONG* pcdispidReserved,
429 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
431 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, pptiCoClass, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource);
436 if (dwFlags & MULTICLASSINFO_GETTYPEINFO)
437 load_type_info(&This->IDispatch_iface, pptiCoClass, This->clsid, 0);
439 if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
442 *pcdispidReserved = 0;
445 if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY){
446 *piidPrimary = *This->clsid;
449 if (dwFlags & MULTICLASSINFO_GETIIDSOURCE){
450 *piidSource = *This->clsid;
456 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl =
458 ProvideMultipleClassInfo_QueryInterface,
459 ProvideMultipleClassInfo_AddRef,
460 ProvideMultipleClassInfo_Release,
461 ProvideMultipleClassInfo_GetClassInfo,
462 ProvideMultipleClassInfo_GetGUID,
463 ProvideMultipleClassInfo_GetMultiTypeInfoCount,
464 ProvideMultipleClassInfo_GetInfoOfIndex
467 static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, REFIID clsid,
468 autoInvokeFunc invokeFunc, autoFreeFunc freeFunc)
470 TRACE("(%p, %d, %s, %p, %p)\n", This, msiHandle, debugstr_guid(clsid), invokeFunc, freeFunc);
472 This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
473 This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
476 This->msiHandle = msiHandle;
477 This->clsid = (LPCLSID)clsid;
478 This->funcInvoke = invokeFunc;
479 This->funcFree = freeFunc;
481 /* Load our TypeInfo so we don't have to process GetIDsOfNames */
482 This->iTypeInfo = NULL;
483 return load_type_info(&This->IDispatch_iface, &This->iTypeInfo, clsid, 0);
487 * ListEnumerator methods
490 static inline ListEnumerator *impl_from_IEnumVARIANT(IEnumVARIANT* iface)
492 return CONTAINING_RECORD(iface, ListEnumerator, IEnumVARIANT_iface);
495 static HRESULT WINAPI ListEnumerator_QueryInterface(IEnumVARIANT* iface, REFIID riid,
498 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
500 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
502 if (ppvObject == NULL)
507 if (IsEqualGUID(riid, &IID_IUnknown) ||
508 IsEqualGUID(riid, &IID_IEnumVARIANT))
510 *ppvObject = &This->IEnumVARIANT_iface;
514 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid));
515 return E_NOINTERFACE;
518 IEnumVARIANT_AddRef(iface);
522 static ULONG WINAPI ListEnumerator_AddRef(IEnumVARIANT* iface)
524 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
526 TRACE("(%p/%p)\n", iface, This);
528 return InterlockedIncrement(&This->ref);
531 static ULONG WINAPI ListEnumerator_Release(IEnumVARIANT* iface)
533 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
534 ULONG ref = InterlockedDecrement(&This->ref);
536 TRACE("(%p/%p)\n", iface, This);
540 if (This->list) IDispatch_Release(&This->list->autoobj.IDispatch_iface);
547 static HRESULT WINAPI ListEnumerator_Next(IEnumVARIANT* iface, ULONG celt, VARIANT* rgVar,
550 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
553 TRACE("(%p, %uld, %p, %p)\n", iface, celt, rgVar, fetched);
555 if (fetched) *fetched = 0;
560 for (local = 0; local < celt; local++)
561 VariantInit(&rgVar[local]);
563 for (i = This->pos, local = 0; i < This->list->count && local < celt; i++, local++)
564 VariantCopy(&rgVar[local], &This->list->data[i]);
566 if (fetched) *fetched = local;
569 return (local < celt) ? S_FALSE : S_OK;
572 static HRESULT WINAPI ListEnumerator_Skip(IEnumVARIANT* iface, ULONG celt)
574 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
576 TRACE("(%p,%uld)\n", iface, celt);
579 if (This->pos >= This->list->count)
581 This->pos = This->list->count;
588 static HRESULT WINAPI ListEnumerator_Reset(IEnumVARIANT* iface)
590 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
592 TRACE("(%p)\n", iface);
598 static HRESULT WINAPI ListEnumerator_Clone(IEnumVARIANT* iface, IEnumVARIANT **ppEnum)
600 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
603 TRACE("(%p,%p)\n", iface, ppEnum);
609 hr = create_list_enumerator(This->list, (LPVOID *)ppEnum);
613 IUnknown_Release(*ppEnum);
620 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
622 ListEnumerator_QueryInterface,
623 ListEnumerator_AddRef,
624 ListEnumerator_Release,
627 ListEnumerator_Reset,
631 /* Create a list enumerator, placing the result in the pointer ppObj. */
632 static HRESULT create_list_enumerator(ListObject *list, void **ppObj)
634 ListEnumerator *object;
636 TRACE("(%p, %p)\n", list, ppObj);
638 object = msi_alloc(sizeof(ListEnumerator));
640 /* Set all the VTable references */
641 object->IEnumVARIANT_iface.lpVtbl = &ListEnumerator_Vtbl;
644 /* Store data that was passed */
647 if (list) IDispatch_AddRef(&list->autoobj.IDispatch_iface);
654 * Individual Object Invocation Functions
657 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
658 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
659 using DispGetParam/VariantChangeType. */
660 static HRESULT DispGetParam_CopyOnly(
661 DISPPARAMS *pdispparams, /* [in] Parameter list */
662 UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
663 VARIANT *pvarResult) /* [out] Destination for resulting variant */
665 /* position is counted backwards */
668 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
669 *position, pdispparams->cArgs, pdispparams->cNamedArgs);
670 if (*position < pdispparams->cArgs) {
671 /* positional arg? */
672 pos = pdispparams->cArgs - *position - 1;
674 /* FIXME: is this how to handle named args? */
675 for (pos=0; pos<pdispparams->cNamedArgs; pos++)
676 if (pdispparams->rgdispidNamedArgs[pos] == *position) break;
678 if (pos==pdispparams->cNamedArgs)
679 return DISP_E_PARAMNOTFOUND;
682 return VariantCopyInd(pvarResult,
683 &pdispparams->rgvarg[pos]);
686 static HRESULT SummaryInfoImpl_Invoke(
687 AutomationObject* This,
692 DISPPARAMS* pDispParams,
694 EXCEPINFO* pExcepInfo,
698 VARIANTARG varg0, varg1;
699 FILETIME ft, ftlocal;
706 switch (dispIdMember)
708 case DISPID_SUMMARYINFO_PROPERTY:
709 if (wFlags & DISPATCH_PROPERTYGET)
717 static WCHAR szEmpty[] = {0};
719 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
720 if (FAILED(hr)) return hr;
721 ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, &value,
722 &ft, szEmpty, &size);
723 if (ret != ERROR_SUCCESS &&
724 ret != ERROR_MORE_DATA)
726 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
727 return DISP_E_EXCEPTION;
737 V_VT(pVarResult) = VT_I4;
738 V_I4(pVarResult) = value;
742 if (!(str = msi_alloc(++size * sizeof(WCHAR))))
743 ERR("Out of memory\n");
744 else if ((ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, NULL,
745 NULL, str, &size)) != ERROR_SUCCESS)
746 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
749 V_VT(pVarResult) = VT_BSTR;
750 V_BSTR(pVarResult) = SysAllocString(str);
756 FileTimeToLocalFileTime(&ft, &ftlocal);
757 FileTimeToSystemTime(&ftlocal, &st);
758 SystemTimeToVariantTime(&st, &date);
760 V_VT(pVarResult) = VT_DATE;
761 V_DATE(pVarResult) = date;
765 ERR("Unhandled variant type %d\n", type);
768 else if (wFlags & DISPATCH_PROPERTYPUT)
770 UINT posValue = DISPID_PROPERTYPUT;
772 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
773 if (FAILED(hr)) return hr;
774 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg1);
777 *puArgErr = posValue;
781 switch (V_VT(&varg1))
785 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), V_VT(&varg1), V_I4(&varg1), NULL, NULL);
789 VariantTimeToSystemTime(V_DATE(&varg1), &st);
790 SystemTimeToFileTime(&st, &ftlocal);
791 LocalFileTimeToFileTime(&ftlocal, &ft);
792 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_FILETIME, 0, &ft, NULL);
796 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_LPSTR, 0, NULL, V_BSTR(&varg1));
800 FIXME("Unhandled variant type %d\n", V_VT(&varg1));
801 VariantClear(&varg1);
802 return DISP_E_EXCEPTION;
805 if (ret != ERROR_SUCCESS)
807 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret);
808 return DISP_E_EXCEPTION;
811 else return DISP_E_MEMBERNOTFOUND;
814 case DISPID_SUMMARYINFO_PROPERTYCOUNT:
815 if (wFlags & DISPATCH_PROPERTYGET) {
817 if ((ret = MsiSummaryInfoGetPropertyCount(This->msiHandle, &count)) != ERROR_SUCCESS)
818 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret);
821 V_VT(pVarResult) = VT_I4;
822 V_I4(pVarResult) = count;
825 else return DISP_E_MEMBERNOTFOUND;
829 return DISP_E_MEMBERNOTFOUND;
832 VariantClear(&varg1);
833 VariantClear(&varg0);
838 static HRESULT RecordImpl_Invoke(
839 AutomationObject* This,
844 DISPPARAMS* pDispParams,
846 EXCEPINFO* pExcepInfo,
852 VARIANTARG varg0, varg1;
858 switch (dispIdMember)
860 case DISPID_RECORD_FIELDCOUNT:
861 if (wFlags & DISPATCH_PROPERTYGET) {
862 V_VT(pVarResult) = VT_I4;
863 V_I4(pVarResult) = MsiRecordGetFieldCount(This->msiHandle);
865 else return DISP_E_MEMBERNOTFOUND;
868 case DISPID_RECORD_STRINGDATA:
869 if (wFlags & DISPATCH_PROPERTYGET) {
870 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
871 if (FAILED(hr)) return hr;
872 V_VT(pVarResult) = VT_BSTR;
873 V_BSTR(pVarResult) = NULL;
874 if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
876 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
877 ERR("Out of memory\n");
878 else if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
879 V_BSTR(pVarResult) = SysAllocString(szString);
882 if (ret != ERROR_SUCCESS)
883 ERR("MsiRecordGetString returned %d\n", ret);
884 } else if (wFlags & DISPATCH_PROPERTYPUT) {
885 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
886 if (FAILED(hr)) return hr;
887 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_BSTR, &varg1, puArgErr);
888 if (FAILED(hr)) return hr;
889 if ((ret = MsiRecordSetStringW(This->msiHandle, V_I4(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
891 VariantClear(&varg1);
892 ERR("MsiRecordSetString returned %d\n", ret);
893 return DISP_E_EXCEPTION;
896 else return DISP_E_MEMBERNOTFOUND;
899 case DISPID_RECORD_INTEGERDATA:
900 if (wFlags & DISPATCH_PROPERTYGET) {
901 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
902 if (FAILED(hr)) return hr;
903 V_VT(pVarResult) = VT_I4;
904 V_I4(pVarResult) = MsiRecordGetInteger(This->msiHandle, V_I4(&varg0));
905 } else if (wFlags & DISPATCH_PROPERTYPUT) {
906 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
907 if (FAILED(hr)) return hr;
908 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_I4, &varg1, puArgErr);
909 if (FAILED(hr)) return hr;
910 if ((ret = MsiRecordSetInteger(This->msiHandle, V_I4(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
912 ERR("MsiRecordSetInteger returned %d\n", ret);
913 return DISP_E_EXCEPTION;
916 else return DISP_E_MEMBERNOTFOUND;
920 return DISP_E_MEMBERNOTFOUND;
923 VariantClear(&varg1);
924 VariantClear(&varg0);
929 HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
931 AutomationObject *record;
934 record = msi_alloc(sizeof(*record));
935 if (!record) return E_OUTOFMEMORY;
937 hr = init_automation_object(record, msiHandle, &DIID_Record, RecordImpl_Invoke, NULL);
944 *disp = &record->IDispatch_iface;
949 static HRESULT ListImpl_Invoke(
950 AutomationObject* This,
955 DISPPARAMS* pDispParams,
957 EXCEPINFO* pExcepInfo,
960 ListObject *list = (ListObject*)This;
961 IUnknown *pUnk = NULL;
964 switch (dispIdMember)
966 case DISPID_LIST__NEWENUM:
967 if (wFlags & DISPATCH_METHOD) {
968 V_VT(pVarResult) = VT_UNKNOWN;
969 if (SUCCEEDED(hr = create_list_enumerator(list, (LPVOID *)&pUnk)))
970 V_UNKNOWN(pVarResult) = pUnk;
972 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr);
974 else return DISP_E_MEMBERNOTFOUND;
977 case DISPID_LIST_ITEM:
978 if (wFlags & DISPATCH_PROPERTYGET) {
982 hr = DispGetParam(pDispParams, 0, VT_I4, &index, puArgErr);
983 if (FAILED(hr)) return hr;
984 if (V_I4(&index) < 0 || V_I4(&index) >= list->count)
985 return DISP_E_BADINDEX;
986 VariantCopy(pVarResult, &list->data[V_I4(&index)]);
988 else return DISP_E_MEMBERNOTFOUND;
991 case DISPID_LIST_COUNT:
992 if (wFlags & DISPATCH_PROPERTYGET) {
993 V_VT(pVarResult) = VT_I4;
994 V_I4(pVarResult) = list->count;
996 else return DISP_E_MEMBERNOTFOUND;
1000 return DISP_E_MEMBERNOTFOUND;
1006 static void ListImpl_Free(AutomationObject *This)
1008 ListObject *list = (ListObject*)This;
1011 for (i = 0; i < list->count; i++)
1012 VariantClear(&list->data[i]);
1013 msi_free(list->data);
1016 static HRESULT get_products_count(const WCHAR *product, int *len)
1022 WCHAR dataW[GUID_SIZE];
1025 /* all or related only */
1027 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1029 ret = MsiEnumProductsW(i, dataW);
1031 if (ret == ERROR_NO_MORE_ITEMS) break;
1033 if (ret != ERROR_SUCCESS)
1034 return DISP_E_EXCEPTION;
1044 static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
1050 list = msi_alloc_zero(sizeof(ListObject));
1051 if (!list) return E_OUTOFMEMORY;
1053 hr = init_automation_object(&list->autoobj, 0, &DIID_StringList, ListImpl_Invoke, ListImpl_Free);
1060 *dispatch = &list->autoobj.IDispatch_iface;
1062 hr = get_products_count(product, &list->count);
1065 IDispatch_Release(*dispatch);
1069 list->data = msi_alloc(list->count*sizeof(VARIANT));
1072 IDispatch_Release(*dispatch);
1073 return E_OUTOFMEMORY;
1076 for (i = 0; i < list->count; i++)
1078 WCHAR dataW[GUID_SIZE];
1081 /* all or related only */
1083 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1085 ret = MsiEnumProductsW(i, dataW);
1087 if (ret == ERROR_NO_MORE_ITEMS) break;
1089 V_VT(&list->data[i]) = VT_BSTR;
1090 V_BSTR(&list->data[i]) = SysAllocString(dataW);
1096 static HRESULT ViewImpl_Invoke(
1097 AutomationObject* This,
1098 DISPID dispIdMember,
1102 DISPPARAMS* pDispParams,
1103 VARIANT* pVarResult,
1104 EXCEPINFO* pExcepInfo,
1107 MSIHANDLE msiHandle;
1109 VARIANTARG varg0, varg1;
1112 VariantInit(&varg0);
1113 VariantInit(&varg1);
1115 switch (dispIdMember)
1117 case DISPID_VIEW_EXECUTE:
1118 if (wFlags & DISPATCH_METHOD)
1120 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &varg0, puArgErr);
1121 if (SUCCEEDED(hr) && V_DISPATCH(&varg0) != NULL)
1122 MsiViewExecute(This->msiHandle, ((AutomationObject *)V_DISPATCH(&varg0))->msiHandle);
1124 MsiViewExecute(This->msiHandle, 0);
1126 else return DISP_E_MEMBERNOTFOUND;
1129 case DISPID_VIEW_FETCH:
1130 if (wFlags & DISPATCH_METHOD)
1132 V_VT(pVarResult) = VT_DISPATCH;
1133 if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS)
1135 IDispatch *dispatch = NULL;
1137 if (SUCCEEDED(hr = create_record(msiHandle, &dispatch)))
1138 V_DISPATCH(pVarResult) = dispatch;
1140 ERR("Failed to create Record object, hresult 0x%08x\n", hr);
1142 else if (ret == ERROR_NO_MORE_ITEMS)
1143 V_DISPATCH(pVarResult) = NULL;
1146 ERR("MsiViewFetch returned %d\n", ret);
1147 return DISP_E_EXCEPTION;
1150 else return DISP_E_MEMBERNOTFOUND;
1153 case DISPID_VIEW_MODIFY:
1154 if (wFlags & DISPATCH_METHOD)
1156 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1157 if (FAILED(hr)) return hr;
1158 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1159 if (FAILED(hr)) return hr;
1160 if (!V_DISPATCH(&varg1)) return DISP_E_EXCEPTION;
1161 if ((ret = MsiViewModify(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle)) != ERROR_SUCCESS)
1163 VariantClear(&varg1);
1164 ERR("MsiViewModify returned %d\n", ret);
1165 return DISP_E_EXCEPTION;
1168 else return DISP_E_MEMBERNOTFOUND;
1171 case DISPID_VIEW_CLOSE:
1172 if (wFlags & DISPATCH_METHOD)
1174 MsiViewClose(This->msiHandle);
1176 else return DISP_E_MEMBERNOTFOUND;
1180 return DISP_E_MEMBERNOTFOUND;
1183 VariantClear(&varg1);
1184 VariantClear(&varg0);
1189 static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
1190 DISPPARAMS* pDispParams,
1191 VARIANT* pVarResult,
1192 EXCEPINFO* pExcepInfo,
1195 if (!(wFlags & DISPATCH_METHOD))
1196 return DISP_E_MEMBERNOTFOUND;
1200 VariantInit(pVarResult);
1204 static HRESULT DatabaseImpl_Invoke(
1205 AutomationObject* This,
1206 DISPID dispIdMember,
1210 DISPPARAMS* pDispParams,
1211 VARIANT* pVarResult,
1212 EXCEPINFO* pExcepInfo,
1215 IDispatch *dispatch = NULL;
1216 MSIHANDLE msiHandle;
1218 VARIANTARG varg0, varg1;
1221 VariantInit(&varg0);
1222 VariantInit(&varg1);
1224 switch (dispIdMember)
1226 case DISPID_DATABASE_SUMMARYINFORMATION:
1227 if (wFlags & DISPATCH_PROPERTYGET)
1229 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1233 V_VT(pVarResult) = VT_DISPATCH;
1234 if ((ret = MsiGetSummaryInformationW(This->msiHandle, NULL, V_I4(&varg0), &msiHandle)) == ERROR_SUCCESS)
1236 hr = create_summaryinfo(msiHandle, &dispatch);
1238 V_DISPATCH(pVarResult) = dispatch;
1240 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr);
1244 ERR("MsiGetSummaryInformation returned %d\n", ret);
1245 return DISP_E_EXCEPTION;
1248 else return DISP_E_MEMBERNOTFOUND;
1251 case DISPID_DATABASE_OPENVIEW:
1252 if (wFlags & DISPATCH_METHOD)
1254 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1255 if (FAILED(hr)) return hr;
1256 V_VT(pVarResult) = VT_DISPATCH;
1257 if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS)
1259 if (SUCCEEDED(hr = create_view(msiHandle, &dispatch)))
1260 V_DISPATCH(pVarResult) = dispatch;
1262 ERR("Failed to create View object, hresult 0x%08x\n", hr);
1266 VariantClear(&varg0);
1267 ERR("MsiDatabaseOpenView returned %d\n", ret);
1268 return DISP_E_EXCEPTION;
1271 else return DISP_E_MEMBERNOTFOUND;
1274 case DISPID_INSTALLER_LASTERRORRECORD:
1275 return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
1276 pVarResult, pExcepInfo,
1280 return DISP_E_MEMBERNOTFOUND;
1283 VariantClear(&varg1);
1284 VariantClear(&varg0);
1289 static HRESULT SessionImpl_Invoke(
1290 AutomationObject* This,
1291 DISPID dispIdMember,
1295 DISPPARAMS* pDispParams,
1296 VARIANT* pVarResult,
1297 EXCEPINFO* pExcepInfo,
1300 SessionObject *session = (SessionObject*)This;
1303 MSIHANDLE msiHandle;
1306 INSTALLSTATE iInstalled, iAction;
1307 VARIANTARG varg0, varg1;
1310 VariantInit(&varg0);
1311 VariantInit(&varg1);
1313 switch (dispIdMember)
1315 case DISPID_SESSION_INSTALLER:
1316 if (wFlags & DISPATCH_PROPERTYGET) {
1317 V_VT(pVarResult) = VT_DISPATCH;
1318 IDispatch_AddRef(session->installer);
1319 V_DISPATCH(pVarResult) = session->installer;
1321 else return DISP_E_MEMBERNOTFOUND;
1324 case DISPID_SESSION_PROPERTY:
1325 if (wFlags & DISPATCH_PROPERTYGET) {
1326 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1327 if (FAILED(hr)) return hr;
1328 V_VT(pVarResult) = VT_BSTR;
1329 V_BSTR(pVarResult) = NULL;
1330 if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
1332 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
1333 ERR("Out of memory\n");
1334 else if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
1335 V_BSTR(pVarResult) = SysAllocString(szString);
1338 if (ret != ERROR_SUCCESS)
1339 ERR("MsiGetProperty returned %d\n", ret);
1340 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1341 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1342 if (FAILED(hr)) return hr;
1343 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_BSTR, &varg1, puArgErr);
1345 VariantClear(&varg0);
1348 if ((ret = MsiSetPropertyW(This->msiHandle, V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
1350 VariantClear(&varg0);
1351 VariantClear(&varg1);
1352 ERR("MsiSetProperty returned %d\n", ret);
1353 return DISP_E_EXCEPTION;
1356 else return DISP_E_MEMBERNOTFOUND;
1359 case DISPID_SESSION_LANGUAGE:
1360 if (wFlags & DISPATCH_PROPERTYGET) {
1361 langId = MsiGetLanguage(This->msiHandle);
1362 V_VT(pVarResult) = VT_I4;
1363 V_I4(pVarResult) = langId;
1365 else return DISP_E_MEMBERNOTFOUND;
1368 case DISPID_SESSION_MODE:
1369 if (wFlags & DISPATCH_PROPERTYGET) {
1370 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1371 if (FAILED(hr)) return hr;
1372 V_VT(pVarResult) = VT_BOOL;
1373 V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0));
1374 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1375 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1376 if (FAILED(hr)) return hr;
1377 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_BOOL, &varg1, puArgErr);
1378 if (FAILED(hr)) return hr;
1379 if ((ret = MsiSetMode(This->msiHandle, V_I4(&varg0), V_BOOL(&varg1))) != ERROR_SUCCESS)
1381 ERR("MsiSetMode returned %d\n", ret);
1382 return DISP_E_EXCEPTION;
1385 else return DISP_E_MEMBERNOTFOUND;
1388 case DISPID_SESSION_DATABASE:
1389 if (wFlags & DISPATCH_PROPERTYGET) {
1390 V_VT(pVarResult) = VT_DISPATCH;
1391 if ((msiHandle = MsiGetActiveDatabase(This->msiHandle)))
1393 IDispatch *dispatch;
1395 if (SUCCEEDED(hr = create_database(msiHandle, &dispatch)))
1396 V_DISPATCH(pVarResult) = dispatch;
1398 ERR("Failed to create Database object, hresult 0x%08x\n", hr);
1402 ERR("MsiGetActiveDatabase failed\n");
1403 return DISP_E_EXCEPTION;
1406 else return DISP_E_MEMBERNOTFOUND;
1409 case DISPID_SESSION_DOACTION:
1410 if (wFlags & DISPATCH_METHOD) {
1411 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1412 if (FAILED(hr)) return hr;
1413 ret = MsiDoActionW(This->msiHandle, V_BSTR(&varg0));
1414 V_VT(pVarResult) = VT_I4;
1417 case ERROR_FUNCTION_NOT_CALLED:
1418 V_I4(pVarResult) = msiDoActionStatusNoAction;
1421 V_I4(pVarResult) = msiDoActionStatusSuccess;
1423 case ERROR_INSTALL_USEREXIT:
1424 V_I4(pVarResult) = msiDoActionStatusUserExit;
1426 case ERROR_INSTALL_FAILURE:
1427 V_I4(pVarResult) = msiDoActionStatusFailure;
1429 case ERROR_INSTALL_SUSPEND:
1430 V_I4(pVarResult) = msiDoActionStatusSuspend;
1432 case ERROR_MORE_DATA:
1433 V_I4(pVarResult) = msiDoActionStatusFinished;
1435 case ERROR_INVALID_HANDLE_STATE:
1436 V_I4(pVarResult) = msiDoActionStatusWrongState;
1438 case ERROR_INVALID_DATA:
1439 V_I4(pVarResult) = msiDoActionStatusBadActionData;
1442 VariantClear(&varg0);
1443 FIXME("MsiDoAction returned unhandled value %d\n", ret);
1444 return DISP_E_EXCEPTION;
1447 else return DISP_E_MEMBERNOTFOUND;
1450 case DISPID_SESSION_EVALUATECONDITION:
1451 if (wFlags & DISPATCH_METHOD) {
1452 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1453 if (FAILED(hr)) return hr;
1454 V_VT(pVarResult) = VT_I4;
1455 V_I4(pVarResult) = MsiEvaluateConditionW(This->msiHandle, V_BSTR(&varg0));
1457 else return DISP_E_MEMBERNOTFOUND;
1460 case DISPID_SESSION_MESSAGE:
1461 if(!(wFlags & DISPATCH_METHOD))
1462 return DISP_E_MEMBERNOTFOUND;
1464 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1465 if (FAILED(hr)) return hr;
1466 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1467 if (FAILED(hr)) return hr;
1469 V_VT(pVarResult) = VT_I4;
1471 MsiProcessMessage(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle);
1474 case DISPID_SESSION_SETINSTALLLEVEL:
1475 if (wFlags & DISPATCH_METHOD) {
1476 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1477 if (FAILED(hr)) return hr;
1478 if ((ret = MsiSetInstallLevel(This->msiHandle, V_I4(&varg0))) != ERROR_SUCCESS)
1480 ERR("MsiSetInstallLevel returned %d\n", ret);
1481 return DISP_E_EXCEPTION;
1484 else return DISP_E_MEMBERNOTFOUND;
1487 case DISPID_SESSION_FEATURECURRENTSTATE:
1488 if (wFlags & DISPATCH_PROPERTYGET) {
1489 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1490 if (FAILED(hr)) return hr;
1491 V_VT(pVarResult) = VT_I4;
1492 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1493 V_I4(pVarResult) = iInstalled;
1496 ERR("MsiGetFeatureState returned %d\n", ret);
1497 V_I4(pVarResult) = msiInstallStateUnknown;
1500 else return DISP_E_MEMBERNOTFOUND;
1503 case DISPID_SESSION_FEATUREREQUESTSTATE:
1504 if (wFlags & DISPATCH_PROPERTYGET) {
1505 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1506 if (FAILED(hr)) return hr;
1507 V_VT(pVarResult) = VT_I4;
1508 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1509 V_I4(pVarResult) = iAction;
1512 ERR("MsiGetFeatureState returned %d\n", ret);
1513 V_I4(pVarResult) = msiInstallStateUnknown;
1515 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1516 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1517 if (FAILED(hr)) return hr;
1518 hr = DispGetParam(pDispParams, DISPID_PROPERTYPUT, VT_I4, &varg1, puArgErr);
1520 VariantClear(&varg0);
1523 if ((ret = MsiSetFeatureStateW(This->msiHandle, V_BSTR(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
1525 VariantClear(&varg0);
1526 ERR("MsiSetFeatureState returned %d\n", ret);
1527 return DISP_E_EXCEPTION;
1530 else return DISP_E_MEMBERNOTFOUND;
1534 return DISP_E_MEMBERNOTFOUND;
1537 VariantClear(&varg1);
1538 VariantClear(&varg0);
1543 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1544 * registry value type. Used by Installer::RegistryValue. */
1545 static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize)
1547 static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1548 static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 };
1549 WCHAR *szString = (WCHAR *)lpData;
1550 LPWSTR szNewString = NULL;
1551 DWORD dwNewSize = 0;
1556 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1557 case REG_MULTI_SZ: /* Multi SZ change internal null characters to newlines */
1558 idx = (dwSize/sizeof(WCHAR))-1;
1559 while (idx >= 0 && !szString[idx]) idx--;
1560 for (; idx >= 0; idx--)
1561 if (!szString[idx]) szString[idx] = '\n';
1564 V_VT(pVarResult) = VT_BSTR;
1565 V_BSTR(pVarResult) = SysAllocStringByteLen((LPCSTR)szString, dwSize);
1569 if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1570 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1571 else if (!(szNewString = msi_alloc(dwNewSize * sizeof(WCHAR))))
1572 ERR("Out of memory\n");
1573 else if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1574 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1577 V_VT(pVarResult) = VT_BSTR;
1578 V_BSTR(pVarResult) = SysAllocStringLen(szNewString, dwNewSize);
1580 msi_free(szNewString);
1584 V_VT(pVarResult) = VT_I4;
1585 V_I4(pVarResult) = *((DWORD *)lpData);
1589 V_VT(pVarResult) = VT_BSTR;
1590 V_BSTR(pVarResult) = SysAllocString(szREG_); /* Weird string, don't know why native returns it */
1594 V_VT(pVarResult) = VT_BSTR;
1595 V_BSTR(pVarResult) = SysAllocString(szREG_BINARY);
1599 V_VT(pVarResult) = VT_EMPTY;
1603 FIXME("Unhandled registry value type %d\n", dwType);
1607 static HRESULT InstallerImpl_CreateRecord(WORD wFlags,
1608 DISPPARAMS* pDispParams,
1609 VARIANT* pVarResult,
1610 EXCEPINFO* pExcepInfo,
1616 IDispatch* dispatch;
1618 if (!(wFlags & DISPATCH_METHOD))
1619 return DISP_E_MEMBERNOTFOUND;
1621 VariantInit(&varg0);
1622 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1626 V_VT(pVarResult) = VT_DISPATCH;
1628 hrec = MsiCreateRecord(V_I4(&varg0));
1630 return DISP_E_EXCEPTION;
1632 hr = create_record(hrec, &dispatch);
1634 V_DISPATCH(pVarResult) = dispatch;
1639 static HRESULT InstallerImpl_OpenPackage(AutomationObject* This,
1641 DISPPARAMS* pDispParams,
1642 VARIANT* pVarResult,
1643 EXCEPINFO* pExcepInfo,
1649 IDispatch* dispatch;
1650 VARIANTARG varg0, varg1;
1652 if (!(wFlags & DISPATCH_METHOD))
1653 return DISP_E_MEMBERNOTFOUND;
1655 if (pDispParams->cArgs == 0)
1656 return DISP_E_TYPEMISMATCH;
1658 if (V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1]) != VT_BSTR)
1659 return DISP_E_TYPEMISMATCH;
1661 VariantInit(&varg0);
1662 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1666 VariantInit(&varg1);
1667 if (pDispParams->cArgs == 2)
1669 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1675 V_VT(&varg1) = VT_I4;
1679 V_VT(pVarResult) = VT_DISPATCH;
1681 ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &hpkg);
1682 if (ret != ERROR_SUCCESS)
1684 hr = DISP_E_EXCEPTION;
1688 hr = create_session(hpkg, &This->IDispatch_iface, &dispatch);
1690 V_DISPATCH(pVarResult) = dispatch;
1693 VariantClear(&varg0);
1694 VariantClear(&varg1);
1698 static HRESULT InstallerImpl_OpenProduct(WORD wFlags,
1699 DISPPARAMS* pDispParams,
1700 VARIANT* pVarResult,
1701 EXCEPINFO* pExcepInfo,
1707 if (!(wFlags & DISPATCH_METHOD))
1708 return DISP_E_MEMBERNOTFOUND;
1710 VariantInit(&varg0);
1711 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1715 FIXME("%s\n", debugstr_w(V_BSTR(&varg0)));
1717 VariantInit(pVarResult);
1719 VariantClear(&varg0);
1723 static HRESULT InstallerImpl_OpenDatabase(WORD wFlags,
1724 DISPPARAMS* pDispParams,
1725 VARIANT* pVarResult,
1726 EXCEPINFO* pExcepInfo,
1732 IDispatch* dispatch;
1733 VARIANTARG varg0, varg1;
1735 if (!(wFlags & DISPATCH_METHOD))
1736 return DISP_E_MEMBERNOTFOUND;
1738 VariantInit(&varg0);
1739 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1743 VariantInit(&varg1);
1744 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1748 V_VT(pVarResult) = VT_DISPATCH;
1750 ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &hdb);
1751 if (ret != ERROR_SUCCESS)
1753 hr = DISP_E_EXCEPTION;
1757 hr = create_database(hdb, &dispatch);
1759 V_DISPATCH(pVarResult) = dispatch;
1762 VariantClear(&varg0);
1763 VariantClear(&varg1);
1767 static HRESULT InstallerImpl_SummaryInformation(WORD wFlags,
1768 DISPPARAMS* pDispParams,
1769 VARIANT* pVarResult,
1770 EXCEPINFO* pExcepInfo,
1773 if (!(wFlags & DISPATCH_METHOD))
1774 return DISP_E_MEMBERNOTFOUND;
1778 VariantInit(pVarResult);
1782 static HRESULT InstallerImpl_UILevel(WORD wFlags,
1783 DISPPARAMS* pDispParams,
1784 VARIANT* pVarResult,
1785 EXCEPINFO* pExcepInfo,
1792 if (!(wFlags & DISPATCH_PROPERTYPUT) && !(wFlags & DISPATCH_PROPERTYGET))
1793 return DISP_E_MEMBERNOTFOUND;
1795 if (wFlags & DISPATCH_PROPERTYPUT)
1797 VariantInit(&varg0);
1798 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1802 ui = MsiSetInternalUI(V_I4(&varg0), NULL);
1803 if (ui == INSTALLUILEVEL_NOCHANGE)
1804 return DISP_E_EXCEPTION;
1806 else if (wFlags & DISPATCH_PROPERTYGET)
1808 ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
1809 if (ui == INSTALLUILEVEL_NOCHANGE)
1810 return DISP_E_EXCEPTION;
1812 V_VT(pVarResult) = VT_I4;
1813 V_I4(pVarResult) = ui;
1819 static HRESULT InstallerImpl_EnableLog(WORD wFlags,
1820 DISPPARAMS* pDispParams,
1821 VARIANT* pVarResult,
1822 EXCEPINFO* pExcepInfo,
1825 if (!(wFlags & DISPATCH_METHOD))
1826 return DISP_E_MEMBERNOTFOUND;
1830 VariantInit(pVarResult);
1834 static HRESULT InstallerImpl_InstallProduct(WORD wFlags,
1835 DISPPARAMS* pDispParams,
1836 VARIANT* pVarResult,
1837 EXCEPINFO* pExcepInfo,
1842 VARIANTARG varg0, varg1;
1844 if (!(wFlags & DISPATCH_METHOD))
1845 return DISP_E_MEMBERNOTFOUND;
1847 VariantInit(&varg0);
1848 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1852 VariantInit(&varg1);
1853 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1857 ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1));
1858 if (ret != ERROR_SUCCESS)
1860 hr = DISP_E_EXCEPTION;
1865 VariantClear(&varg0);
1866 VariantClear(&varg1);
1870 static HRESULT InstallerImpl_Version(WORD wFlags,
1871 VARIANT* pVarResult,
1872 EXCEPINFO* pExcepInfo,
1876 DLLVERSIONINFO verinfo;
1877 WCHAR version[MAX_PATH];
1879 static const WCHAR format[] = {
1880 '%','d','.','%','d','.','%','d','.','%','d',0};
1882 if (!(wFlags & DISPATCH_PROPERTYGET))
1883 return DISP_E_MEMBERNOTFOUND;
1885 verinfo.cbSize = sizeof(DLLVERSIONINFO);
1886 hr = DllGetVersion(&verinfo);
1890 sprintfW(version, format, verinfo.dwMajorVersion, verinfo.dwMinorVersion,
1891 verinfo.dwBuildNumber, verinfo.dwPlatformID);
1893 V_VT(pVarResult) = VT_BSTR;
1894 V_BSTR(pVarResult) = SysAllocString(version);
1898 static HRESULT InstallerImpl_LastErrorRecord(WORD wFlags,
1899 DISPPARAMS* pDispParams,
1900 VARIANT* pVarResult,
1901 EXCEPINFO* pExcepInfo,
1904 if (!(wFlags & DISPATCH_METHOD))
1905 return DISP_E_MEMBERNOTFOUND;
1909 VariantInit(pVarResult);
1913 static HRESULT InstallerImpl_RegistryValue(WORD wFlags,
1914 DISPPARAMS* pDispParams,
1915 VARIANT* pVarResult,
1916 EXCEPINFO* pExcepInfo,
1924 LPWSTR szString = NULL;
1925 VARIANTARG varg0, varg1, varg2;
1927 if (!(wFlags & DISPATCH_METHOD))
1928 return DISP_E_MEMBERNOTFOUND;
1930 VariantInit(&varg0);
1931 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1935 VariantInit(&varg1);
1936 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1940 /* Save valuePos so we can save puArgErr if we are unable to do our type
1944 VariantInit(&varg2);
1945 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2);
1949 if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT &&
1950 V_I4(&varg0) <= REG_INDEX_DYN_DATA)
1952 V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT;
1955 ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey);
1957 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
1958 if (ret != ERROR_SUCCESS && V_VT(&varg2) != VT_EMPTY)
1960 hr = DISP_E_BADINDEX;
1964 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
1965 switch (V_VT(&varg2))
1967 /* Return VT_BOOL clarifying whether registry key exists or not. */
1969 V_VT(pVarResult) = VT_BOOL;
1970 V_BOOL(pVarResult) = (ret == ERROR_SUCCESS);
1973 /* Return the value of specified key if it exists. */
1975 ret = RegQueryValueExW(hkey, V_BSTR(&varg2),
1976 NULL, NULL, NULL, &size);
1977 if (ret != ERROR_SUCCESS)
1979 hr = DISP_E_BADINDEX;
1983 szString = msi_alloc(size);
1990 ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL,
1991 &type, (LPBYTE)szString, &size);
1992 if (ret != ERROR_SUCCESS)
1995 hr = DISP_E_BADINDEX;
1999 variant_from_registry_value(pVarResult, type,
2000 (LPBYTE)szString, size);
2004 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2006 hr = VariantChangeType(&varg2, &varg2, 0, VT_I4);
2009 if (hr == DISP_E_TYPEMISMATCH)
2010 *puArgErr = posValue;
2015 /* Retrieve class name or maximum value name or subkey name size. */
2017 ret = RegQueryInfoKeyW(hkey, NULL, &size, NULL, NULL, NULL,
2018 NULL, NULL, NULL, NULL, NULL, NULL);
2019 else if (V_I4(&varg2) > 0)
2020 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL,
2021 NULL, NULL, &size, NULL, NULL, NULL);
2022 else /* V_I4(&varg2) < 0 */
2023 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &size,
2024 NULL, NULL, NULL, NULL, NULL, NULL);
2026 if (ret != ERROR_SUCCESS)
2029 szString = msi_alloc(++size * sizeof(WCHAR));
2037 ret = RegQueryInfoKeyW(hkey, szString, &size,NULL, NULL, NULL,
2038 NULL, NULL, NULL, NULL, NULL, NULL);
2039 else if (V_I4(&varg2) > 0)
2040 ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString,
2041 &size, 0, 0, NULL, NULL);
2042 else /* V_I4(&varg2) < 0 */
2043 ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, size);
2045 if (ret == ERROR_SUCCESS)
2047 V_VT(pVarResult) = VT_BSTR;
2048 V_BSTR(pVarResult) = SysAllocString(szString);
2055 VariantClear(&varg0);
2056 VariantClear(&varg1);
2057 VariantClear(&varg2);
2062 static HRESULT InstallerImpl_Environment(WORD wFlags,
2063 DISPPARAMS* pDispParams,
2064 VARIANT* pVarResult,
2065 EXCEPINFO* pExcepInfo,
2068 if (!(wFlags & DISPATCH_METHOD))
2069 return DISP_E_MEMBERNOTFOUND;
2073 VariantInit(pVarResult);
2077 static HRESULT InstallerImpl_FileAttributes(WORD wFlags,
2078 DISPPARAMS* pDispParams,
2079 VARIANT* pVarResult,
2080 EXCEPINFO* pExcepInfo,
2083 if (!(wFlags & DISPATCH_METHOD))
2084 return DISP_E_MEMBERNOTFOUND;
2088 VariantInit(pVarResult);
2092 static HRESULT InstallerImpl_FileSize(WORD wFlags,
2093 DISPPARAMS* pDispParams,
2094 VARIANT* pVarResult,
2095 EXCEPINFO* pExcepInfo,
2098 if (!(wFlags & DISPATCH_METHOD))
2099 return DISP_E_MEMBERNOTFOUND;
2103 VariantInit(pVarResult);
2107 static HRESULT InstallerImpl_FileVersion(WORD wFlags,
2108 DISPPARAMS* pDispParams,
2109 VARIANT* pVarResult,
2110 EXCEPINFO* pExcepInfo,
2113 if (!(wFlags & DISPATCH_METHOD))
2114 return DISP_E_MEMBERNOTFOUND;
2118 VariantInit(pVarResult);
2122 static HRESULT InstallerImpl_ProductState(WORD wFlags,
2123 DISPPARAMS* pDispParams,
2124 VARIANT* pVarResult,
2125 EXCEPINFO* pExcepInfo,
2131 if (!(wFlags & DISPATCH_PROPERTYGET))
2132 return DISP_E_MEMBERNOTFOUND;
2134 VariantInit(&varg0);
2135 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2139 V_VT(pVarResult) = VT_I4;
2140 V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0));
2142 VariantClear(&varg0);
2146 static HRESULT InstallerImpl_ProductInfo(WORD wFlags,
2147 DISPPARAMS* pDispParams,
2148 VARIANT* pVarResult,
2149 EXCEPINFO* pExcepInfo,
2156 VARIANTARG varg0, varg1;
2158 if (!(wFlags & DISPATCH_PROPERTYGET))
2159 return DISP_E_MEMBERNOTFOUND;
2161 VariantInit(&varg0);
2162 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2166 VariantInit(&varg1);
2167 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
2171 V_VT(pVarResult) = VT_BSTR;
2172 V_BSTR(pVarResult) = NULL;
2174 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &size);
2175 if (ret != ERROR_SUCCESS)
2177 hr = DISP_E_EXCEPTION;
2181 str = msi_alloc(++size * sizeof(WCHAR));
2188 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), str, &size);
2189 if (ret != ERROR_SUCCESS)
2191 hr = DISP_E_EXCEPTION;
2195 V_BSTR(pVarResult) = SysAllocString(str);
2200 VariantClear(&varg0);
2201 VariantClear(&varg1);
2205 static HRESULT InstallerImpl_Products(WORD flags,
2206 DISPPARAMS* pDispParams,
2208 EXCEPINFO* pExcepInfo,
2211 IDispatch *dispatch;
2214 if (!(flags & DISPATCH_PROPERTYGET))
2215 return DISP_E_MEMBERNOTFOUND;
2217 hr = create_list(NULL, &dispatch);
2221 V_VT(result) = VT_DISPATCH;
2222 V_DISPATCH(result) = dispatch;
2227 static HRESULT InstallerImpl_RelatedProducts(WORD flags,
2228 DISPPARAMS* pDispParams,
2230 EXCEPINFO* pExcepInfo,
2233 IDispatch* dispatch;
2237 if (!(flags & DISPATCH_PROPERTYGET))
2238 return DISP_E_MEMBERNOTFOUND;
2240 VariantInit(&related);
2241 hr = DispGetParam(pDispParams, 0, VT_BSTR, &related, puArgErr);
2245 hr = create_list(V_BSTR(&related), &dispatch);
2246 VariantClear(&related);
2248 V_VT(result) = VT_DISPATCH;
2249 V_DISPATCH(result) = dispatch;
2254 static HRESULT InstallerImpl_Invoke(
2255 AutomationObject* This,
2256 DISPID dispIdMember,
2260 DISPPARAMS* pDispParams,
2261 VARIANT* pVarResult,
2262 EXCEPINFO* pExcepInfo,
2265 switch (dispIdMember)
2267 case DISPID_INSTALLER_CREATERECORD:
2268 return InstallerImpl_CreateRecord(wFlags, pDispParams,
2269 pVarResult, pExcepInfo, puArgErr);
2271 case DISPID_INSTALLER_OPENPACKAGE:
2272 return InstallerImpl_OpenPackage(This, wFlags, pDispParams,
2273 pVarResult, pExcepInfo, puArgErr);
2275 case DISPID_INSTALLER_OPENPRODUCT:
2276 return InstallerImpl_OpenProduct(wFlags, pDispParams,
2277 pVarResult, pExcepInfo, puArgErr);
2279 case DISPID_INSTALLER_OPENDATABASE:
2280 return InstallerImpl_OpenDatabase(wFlags, pDispParams,
2281 pVarResult, pExcepInfo, puArgErr);
2283 case DISPID_INSTALLER_SUMMARYINFORMATION:
2284 return InstallerImpl_SummaryInformation(wFlags, pDispParams,
2285 pVarResult, pExcepInfo,
2288 case DISPID_INSTALLER_UILEVEL:
2289 return InstallerImpl_UILevel(wFlags, pDispParams,
2290 pVarResult, pExcepInfo, puArgErr);
2292 case DISPID_INSTALLER_ENABLELOG:
2293 return InstallerImpl_EnableLog(wFlags, pDispParams,
2294 pVarResult, pExcepInfo, puArgErr);
2296 case DISPID_INSTALLER_INSTALLPRODUCT:
2297 return InstallerImpl_InstallProduct(wFlags, pDispParams,
2298 pVarResult, pExcepInfo,
2301 case DISPID_INSTALLER_VERSION:
2302 return InstallerImpl_Version(wFlags, pVarResult,
2303 pExcepInfo, puArgErr);
2305 case DISPID_INSTALLER_LASTERRORRECORD:
2306 return InstallerImpl_LastErrorRecord(wFlags, pDispParams,
2307 pVarResult, pExcepInfo,
2310 case DISPID_INSTALLER_REGISTRYVALUE:
2311 return InstallerImpl_RegistryValue(wFlags, pDispParams,
2312 pVarResult, pExcepInfo,
2315 case DISPID_INSTALLER_ENVIRONMENT:
2316 return InstallerImpl_Environment(wFlags, pDispParams,
2317 pVarResult, pExcepInfo, puArgErr);
2319 case DISPID_INSTALLER_FILEATTRIBUTES:
2320 return InstallerImpl_FileAttributes(wFlags, pDispParams,
2321 pVarResult, pExcepInfo,
2324 case DISPID_INSTALLER_FILESIZE:
2325 return InstallerImpl_FileSize(wFlags, pDispParams,
2326 pVarResult, pExcepInfo, puArgErr);
2328 case DISPID_INSTALLER_FILEVERSION:
2329 return InstallerImpl_FileVersion(wFlags, pDispParams,
2330 pVarResult, pExcepInfo, puArgErr);
2332 case DISPID_INSTALLER_PRODUCTSTATE:
2333 return InstallerImpl_ProductState(wFlags, pDispParams,
2334 pVarResult, pExcepInfo, puArgErr);
2336 case DISPID_INSTALLER_PRODUCTINFO:
2337 return InstallerImpl_ProductInfo(wFlags, pDispParams,
2338 pVarResult, pExcepInfo, puArgErr);
2340 case DISPID_INSTALLER_PRODUCTS:
2341 return InstallerImpl_Products(wFlags, pDispParams,
2342 pVarResult, pExcepInfo, puArgErr);
2344 case DISPID_INSTALLER_RELATEDPRODUCTS:
2345 return InstallerImpl_RelatedProducts(wFlags, pDispParams,
2346 pVarResult, pExcepInfo,
2350 return DISP_E_MEMBERNOTFOUND;
2354 HRESULT create_msiserver(IUnknown *outer, void **ppObj)
2356 AutomationObject *installer;
2359 TRACE("(%p %p)\n", outer, ppObj);
2362 return CLASS_E_NOAGGREGATION;
2364 installer = msi_alloc(sizeof(AutomationObject));
2365 if (!installer) return E_OUTOFMEMORY;
2367 hr = init_automation_object(installer, 0, &DIID_Installer, InstallerImpl_Invoke, NULL);
2370 msi_free(installer);
2374 *ppObj = &installer->IDispatch_iface;
2379 HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **disp)
2381 SessionObject *session;
2384 session = msi_alloc(sizeof(SessionObject));
2385 if (!session) return E_OUTOFMEMORY;
2387 hr = init_automation_object(&session->autoobj, msiHandle, &DIID_Session, SessionImpl_Invoke, NULL);
2394 session->installer = installer;
2395 *disp = &session->autoobj.IDispatch_iface;
2400 static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
2402 AutomationObject *database;
2405 TRACE("(%d %p)\n", msiHandle, dispatch);
2407 database = msi_alloc(sizeof(AutomationObject));
2408 if (!database) return E_OUTOFMEMORY;
2410 hr = init_automation_object(database, msiHandle, &DIID_Database, DatabaseImpl_Invoke, NULL);
2417 *dispatch = &database->IDispatch_iface;
2422 static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch)
2424 AutomationObject *view;
2427 TRACE("(%d %p)\n", msiHandle, dispatch);
2429 view = msi_alloc(sizeof(AutomationObject));
2430 if (!view) return E_OUTOFMEMORY;
2432 hr = init_automation_object(view, msiHandle, &DIID_View, ViewImpl_Invoke, NULL);
2439 *dispatch = &view->IDispatch_iface;
2444 static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp)
2446 AutomationObject *info;
2449 info = msi_alloc(sizeof(*info));
2450 if (!info) return E_OUTOFMEMORY;
2452 hr = init_automation_object(info, msiHandle, &DIID_SummaryInfo, SummaryInfoImpl_Invoke, NULL);
2459 *disp = &info->IDispatch_iface;