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 struct AutomationObject
{
54 * VTables - We provide IDispatch, IProvideClassInfo, IProvideClassInfo2, IProvideMultipleClassInfo
56 const IDispatchVtbl
*lpVtbl
;
57 const IProvideMultipleClassInfoVtbl
*lpvtblIProvideMultipleClassInfo
;
59 /* Object reference count */
62 /* Clsid for this class and it's appropriate ITypeInfo object */
66 /* The MSI handle of the current object */
69 /* A function that is called from AutomationObject::Invoke, specific to this type of object. */
70 HRESULT (STDMETHODCALLTYPE
*funcInvoke
)(
71 AutomationObject
* This
,
76 DISPPARAMS
* pDispParams
,
78 EXCEPINFO
* pExcepInfo
,
81 /* A function that is called from AutomationObject::Release when the object is being freed to free any private
82 * data structures (or NULL) */
83 void (STDMETHODCALLTYPE
*funcFree
)(AutomationObject
* This
);
87 * ListEnumerator - IEnumVARIANT implementation for MSI automation lists.
92 const IEnumVARIANTVtbl
*lpVtbl
;
94 /* Object reference count */
97 /* Current position and pointer to AutomationObject that stores actual data */
99 AutomationObject
*pObj
;
103 * Structures for additional data required by specific automation objects
112 /* The parent Installer object */
113 IDispatch
*pInstaller
;
117 static const struct IDispatchVtbl AutomationObject_Vtbl
;
118 static const struct IProvideMultipleClassInfoVtbl AutomationObject_IProvideMultipleClassInfo_Vtbl
;
119 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
;
121 /* Load type info so we don't have to process GetIDsOfNames */
122 HRESULT
load_type_info(IDispatch
*iface
, ITypeInfo
**pptinfo
, REFIID clsid
, LCID lcid
)
125 LPTYPELIB pLib
= NULL
;
126 LPTYPEINFO pInfo
= NULL
;
127 static const WCHAR szMsiServer
[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b'};
129 TRACE("(%p)->(%s,%d)\n", iface
, debugstr_guid(clsid
), lcid
);
131 /* Load registered type library */
132 hr
= LoadRegTypeLib(&LIBID_WindowsInstaller
, 1, 0, lcid
, &pLib
);
134 hr
= LoadTypeLib(szMsiServer
, &pLib
);
136 ERR("Could not load msiserver.tlb\n");
141 /* Get type information for object */
142 hr
= ITypeLib_GetTypeInfoOfGuid(pLib
, clsid
, &pInfo
);
143 ITypeLib_Release(pLib
);
145 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid
));
152 /* Create the automation object, placing the result in the pointer ppObj. The automation object is created
153 * with the appropriate clsid and invocation function. */
154 static HRESULT
create_automation_object(MSIHANDLE msiHandle
, IUnknown
*pUnkOuter
, LPVOID
*ppObj
, REFIID clsid
,
155 HRESULT (STDMETHODCALLTYPE
*funcInvoke
)(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,
156 VARIANT
*,EXCEPINFO
*,UINT
*),
157 void (STDMETHODCALLTYPE
*funcFree
)(AutomationObject
*),
158 SIZE_T sizetPrivateData
)
160 AutomationObject
*object
;
163 TRACE("(%d,%p,%p,%s,%p,%p,%ld)\n", msiHandle
, pUnkOuter
, ppObj
, debugstr_guid(clsid
), funcInvoke
, funcFree
, sizetPrivateData
);
166 return CLASS_E_NOAGGREGATION
;
168 object
= msi_alloc_zero( sizeof(AutomationObject
) + sizetPrivateData
);
170 /* Set all the VTable references */
171 object
->lpVtbl
= &AutomationObject_Vtbl
;
172 object
->lpvtblIProvideMultipleClassInfo
= &AutomationObject_IProvideMultipleClassInfo_Vtbl
;
175 /* Store data that was passed */
176 object
->msiHandle
= msiHandle
;
177 object
->clsid
= (LPCLSID
)clsid
;
178 object
->funcInvoke
= funcInvoke
;
179 object
->funcFree
= funcFree
;
181 /* Load our TypeInfo so we don't have to process GetIDsOfNames */
182 object
->iTypeInfo
= NULL
;
183 hr
= load_type_info((IDispatch
*)object
, &object
->iTypeInfo
, clsid
, 0x0);
194 /* Create a list enumerator, placing the result in the pointer ppObj. */
195 static HRESULT
create_list_enumerator(IUnknown
*pUnkOuter
, LPVOID
*ppObj
, AutomationObject
*pObj
, ULONG ulPos
)
197 ListEnumerator
*object
;
199 TRACE("(%p,%p,%p,%uld)\n", pUnkOuter
, ppObj
, pObj
, ulPos
);
202 return CLASS_E_NOAGGREGATION
;
204 object
= msi_alloc_zero( sizeof(ListEnumerator
) );
206 /* Set all the VTable references */
207 object
->lpVtbl
= &ListEnumerator_Vtbl
;
210 /* Store data that was passed */
211 object
->ulPos
= ulPos
;
213 if (pObj
) IDispatch_AddRef((IDispatch
*)pObj
);
219 /* Macros to get pointer to AutomationObject from the other VTables. */
220 static inline AutomationObject
*obj_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
222 return (AutomationObject
*)((char*)iface
- FIELD_OFFSET(AutomationObject
, lpvtblIProvideMultipleClassInfo
));
225 /* Macro to get pointer to private object data */
226 static inline void *private_data( AutomationObject
*This
)
232 * AutomationObject methods
235 /*** IUnknown methods ***/
236 static HRESULT WINAPI
AutomationObject_QueryInterface(IDispatch
* iface
, REFIID riid
, void** ppvObject
)
238 AutomationObject
*This
= (AutomationObject
*)iface
;
240 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
242 if (ppvObject
== NULL
)
247 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IDispatch
) || IsEqualGUID(riid
, This
->clsid
))
249 else if (IsEqualGUID(riid
, &IID_IProvideClassInfo
) ||
250 IsEqualGUID(riid
, &IID_IProvideClassInfo2
) ||
251 IsEqualGUID(riid
, &IID_IProvideMultipleClassInfo
))
252 *ppvObject
= &This
->lpvtblIProvideMultipleClassInfo
;
255 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
256 return E_NOINTERFACE
;
260 * Query Interface always increases the reference count by one when it is
263 IClassFactory_AddRef(iface
);
268 static ULONG WINAPI
AutomationObject_AddRef(IDispatch
* iface
)
270 AutomationObject
*This
= (AutomationObject
*)iface
;
272 TRACE("(%p/%p)\n", iface
, This
);
274 return InterlockedIncrement(&This
->ref
);
277 static ULONG WINAPI
AutomationObject_Release(IDispatch
* iface
)
279 AutomationObject
*This
= (AutomationObject
*)iface
;
280 ULONG ref
= InterlockedDecrement(&This
->ref
);
282 TRACE("(%p/%p)\n", iface
, This
);
286 if (This
->funcFree
) This
->funcFree(This
);
287 ITypeInfo_Release(This
->iTypeInfo
);
288 MsiCloseHandle(This
->msiHandle
);
295 /*** IDispatch methods ***/
296 static HRESULT WINAPI
AutomationObject_GetTypeInfoCount(
300 AutomationObject
*This
= (AutomationObject
*)iface
;
302 TRACE("(%p/%p)->(%p)\n", iface
, This
, pctinfo
);
307 static HRESULT WINAPI
AutomationObject_GetTypeInfo(
313 AutomationObject
*This
= (AutomationObject
*)iface
;
314 TRACE("(%p/%p)->(%d,%d,%p)\n", iface
, This
, iTInfo
, lcid
, ppTInfo
);
316 ITypeInfo_AddRef(This
->iTypeInfo
);
317 *ppTInfo
= This
->iTypeInfo
;
321 static HRESULT WINAPI
AutomationObject_GetIDsOfNames(
329 AutomationObject
*This
= (AutomationObject
*)iface
;
331 TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface
, This
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
333 if (!IsEqualGUID(riid
, &IID_NULL
)) return E_INVALIDARG
;
334 hr
= ITypeInfo_GetIDsOfNames(This
->iTypeInfo
, rgszNames
, cNames
, rgDispId
);
335 if (hr
== DISP_E_UNKNOWNNAME
)
338 for (idx
=0; idx
<cNames
; idx
++)
340 if (rgDispId
[idx
] == DISPID_UNKNOWN
)
341 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames
[idx
]), debugstr_guid(This
->clsid
));
347 /* Maximum number of allowed function parameters+1 */
348 #define MAX_FUNC_PARAMS 20
350 /* Some error checking is done here to simplify individual object function invocation */
351 static HRESULT WINAPI
AutomationObject_Invoke(
357 DISPPARAMS
* pDispParams
,
359 EXCEPINFO
* pExcepInfo
,
362 AutomationObject
*This
= (AutomationObject
*)iface
;
364 unsigned int uArgErr
;
365 VARIANT varResultDummy
;
366 BSTR bstrName
= NULL
;
368 TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface
, This
, dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
370 if (!IsEqualIID(riid
, &IID_NULL
))
372 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
373 return DISP_E_UNKNOWNNAME
;
376 if (wFlags
& DISPATCH_PROPERTYGET
&& !pVarResult
)
378 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
379 return DISP_E_PARAMNOTOPTIONAL
;
382 /* This simplifies our individual object invocation functions */
383 if (puArgErr
== NULL
) puArgErr
= &uArgErr
;
384 if (pVarResult
== NULL
) pVarResult
= &varResultDummy
;
386 /* Assume return type is void unless determined otherwise */
387 VariantInit(pVarResult
);
389 /* If we are tracing, we want to see the name of the member we are invoking */
392 ITypeInfo_GetDocumentation(This
->iTypeInfo
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
393 TRACE("Method %d, %s\n", dispIdMember
, debugstr_w(bstrName
));
396 hr
= This
->funcInvoke(This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
398 if (hr
== DISP_E_MEMBERNOTFOUND
) {
399 if (bstrName
== NULL
) ITypeInfo_GetDocumentation(This
->iTypeInfo
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
400 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember
, debugstr_w(bstrName
), wFlags
, debugstr_guid(This
->clsid
));
402 else if (pExcepInfo
&&
403 (hr
== DISP_E_PARAMNOTFOUND
||
404 hr
== DISP_E_EXCEPTION
)) {
405 static const WCHAR szComma
[] = { ',',0 };
406 static const WCHAR szExceptionSource
[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
407 WCHAR szExceptionDescription
[MAX_PATH
];
408 BSTR bstrParamNames
[MAX_FUNC_PARAMS
];
412 if (FAILED(ITypeInfo_GetNames(This
->iTypeInfo
, dispIdMember
, bstrParamNames
,
413 MAX_FUNC_PARAMS
, &namesNo
)))
415 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember
);
419 memset(szExceptionDescription
, 0, sizeof(szExceptionDescription
));
420 for (i
=0; i
<namesNo
; i
++)
422 if (bFirst
) bFirst
= FALSE
;
424 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], szComma
);
426 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], bstrParamNames
[i
]);
427 SysFreeString(bstrParamNames
[i
]);
430 memset(pExcepInfo
, 0, sizeof(EXCEPINFO
));
431 pExcepInfo
->wCode
= 1000;
432 pExcepInfo
->bstrSource
= SysAllocString(szExceptionSource
);
433 pExcepInfo
->bstrDescription
= SysAllocString(szExceptionDescription
);
434 hr
= DISP_E_EXCEPTION
;
438 /* Make sure we free the return variant if it is our dummy variant */
439 if (pVarResult
== &varResultDummy
) VariantClear(pVarResult
);
441 /* Free function name if we retrieved it */
442 SysFreeString(bstrName
);
444 TRACE("Returning 0x%08x, %s\n", hr
, SUCCEEDED(hr
) ? "ok" : "not ok");
449 static const struct IDispatchVtbl AutomationObject_Vtbl
=
451 AutomationObject_QueryInterface
,
452 AutomationObject_AddRef
,
453 AutomationObject_Release
,
454 AutomationObject_GetTypeInfoCount
,
455 AutomationObject_GetTypeInfo
,
456 AutomationObject_GetIDsOfNames
,
457 AutomationObject_Invoke
461 * IProvideMultipleClassInfo methods
464 static HRESULT WINAPI
AutomationObject_IProvideMultipleClassInfo_QueryInterface(
465 IProvideMultipleClassInfo
* iface
,
469 AutomationObject
*This
= obj_from_IProvideMultipleClassInfo(iface
);
470 return AutomationObject_QueryInterface((IDispatch
*)This
, riid
, ppvoid
);
473 static ULONG WINAPI
AutomationObject_IProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo
* iface
)
475 AutomationObject
*This
= obj_from_IProvideMultipleClassInfo(iface
);
476 return AutomationObject_AddRef((IDispatch
*)This
);
479 static ULONG WINAPI
AutomationObject_IProvideMultipleClassInfo_Release(IProvideMultipleClassInfo
* iface
)
481 AutomationObject
*This
= obj_from_IProvideMultipleClassInfo(iface
);
482 return AutomationObject_Release((IDispatch
*)This
);
485 static HRESULT WINAPI
AutomationObject_IProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo
* iface
, ITypeInfo
** ppTI
)
487 AutomationObject
*This
= obj_from_IProvideMultipleClassInfo(iface
);
488 TRACE("(%p/%p)->(%p)\n", iface
, This
, ppTI
);
489 return load_type_info((IDispatch
*)This
, ppTI
, This
->clsid
, 0);
492 static HRESULT WINAPI
AutomationObject_IProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
* iface
, DWORD dwGuidKind
, GUID
* pGUID
)
494 AutomationObject
*This
= obj_from_IProvideMultipleClassInfo(iface
);
495 TRACE("(%p/%p)->(%d,%s)\n", iface
, This
, dwGuidKind
, debugstr_guid(pGUID
));
497 if (dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
500 *pGUID
= *This
->clsid
;
505 static HRESULT WINAPI
AutomationObject_GetMultiTypeInfoCount(IProvideMultipleClassInfo
* iface
, ULONG
* pcti
)
507 AutomationObject
*This
= obj_from_IProvideMultipleClassInfo(iface
);
509 TRACE("(%p/%p)->(%p)\n", iface
, This
, pcti
);
514 static HRESULT WINAPI
AutomationObject_GetInfoOfIndex(IProvideMultipleClassInfo
* iface
,
517 ITypeInfo
** pptiCoClass
,
519 ULONG
* pcdispidReserved
,
523 AutomationObject
*This
= obj_from_IProvideMultipleClassInfo(iface
);
525 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface
, This
, iti
, dwFlags
, pptiCoClass
, pdwTIFlags
, pcdispidReserved
, piidPrimary
, piidSource
);
530 if (dwFlags
& MULTICLASSINFO_GETTYPEINFO
)
531 load_type_info((IDispatch
*)This
, pptiCoClass
, This
->clsid
, 0);
533 if (dwFlags
& MULTICLASSINFO_GETNUMRESERVEDDISPIDS
)
536 *pcdispidReserved
= 0;
539 if (dwFlags
& MULTICLASSINFO_GETIIDPRIMARY
){
540 *piidPrimary
= *This
->clsid
;
543 if (dwFlags
& MULTICLASSINFO_GETIIDSOURCE
){
544 *piidSource
= *This
->clsid
;
550 static const IProvideMultipleClassInfoVtbl AutomationObject_IProvideMultipleClassInfo_Vtbl
=
552 AutomationObject_IProvideMultipleClassInfo_QueryInterface
,
553 AutomationObject_IProvideMultipleClassInfo_AddRef
,
554 AutomationObject_IProvideMultipleClassInfo_Release
,
555 AutomationObject_IProvideMultipleClassInfo_GetClassInfo
,
556 AutomationObject_IProvideMultipleClassInfo_GetGUID
,
557 AutomationObject_GetMultiTypeInfoCount
,
558 AutomationObject_GetInfoOfIndex
562 * ListEnumerator methods
565 /*** IUnknown methods ***/
566 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
, void** ppvObject
)
568 ListEnumerator
*This
= (ListEnumerator
*)iface
;
570 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
572 if (ppvObject
== NULL
)
577 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IEnumVARIANT
))
581 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
582 return E_NOINTERFACE
;
585 IClassFactory_AddRef(iface
);
589 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
591 ListEnumerator
*This
= (ListEnumerator
*)iface
;
593 TRACE("(%p/%p)\n", iface
, This
);
595 return InterlockedIncrement(&This
->ref
);
598 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
600 ListEnumerator
*This
= (ListEnumerator
*)iface
;
601 ULONG ref
= InterlockedDecrement(&This
->ref
);
603 TRACE("(%p/%p)\n", iface
, This
);
607 if (This
->pObj
) IDispatch_Release((IDispatch
*)This
->pObj
);
614 /* IEnumVARIANT methods */
616 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
618 ListEnumerator
*This
= (ListEnumerator
*)iface
;
619 ListData
*data
= private_data(This
->pObj
);
622 TRACE("(%p,%uld,%p,%p)\n", iface
, celt
, rgVar
, pCeltFetched
);
624 if (pCeltFetched
!= NULL
)
630 for (local
= 0; local
< celt
; local
++)
631 VariantInit(&rgVar
[local
]);
633 for (idx
= This
->ulPos
, local
= 0; idx
< data
->ulCount
&& local
< celt
; idx
++, local
++)
634 VariantCopy(&rgVar
[local
], &data
->pVars
[idx
]);
636 if (pCeltFetched
!= NULL
)
637 *pCeltFetched
= local
;
640 return (local
< celt
) ? S_FALSE
: S_OK
;
643 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
645 ListEnumerator
*This
= (ListEnumerator
*)iface
;
646 ListData
*data
= private_data(This
->pObj
);
648 TRACE("(%p,%uld)\n", iface
, celt
);
651 if (This
->ulPos
>= data
->ulCount
)
653 This
->ulPos
= data
->ulCount
;
659 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
661 ListEnumerator
*This
= (ListEnumerator
*)iface
;
663 TRACE("(%p)\n", iface
);
669 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
671 ListEnumerator
*This
= (ListEnumerator
*)iface
;
674 TRACE("(%p,%p)\n", iface
, ppEnum
);
680 hr
= create_list_enumerator(NULL
, (LPVOID
*)ppEnum
, This
->pObj
, 0);
684 IUnknown_Release(*ppEnum
);
691 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
693 ListEnumerator_QueryInterface
,
694 ListEnumerator_AddRef
,
695 ListEnumerator_Release
,
698 ListEnumerator_Reset
,
703 * Individual Object Invocation Functions
706 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
707 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
708 using DispGetParam/VariantChangeType. */
709 static HRESULT
DispGetParam_CopyOnly(
710 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
711 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
712 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
714 /* position is counted backwards */
717 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
718 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
719 if (*position
< pdispparams
->cArgs
) {
720 /* positional arg? */
721 pos
= pdispparams
->cArgs
- *position
- 1;
723 /* FIXME: is this how to handle named args? */
724 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
725 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
727 if (pos
==pdispparams
->cNamedArgs
)
728 return DISP_E_PARAMNOTFOUND
;
731 return VariantCopyInd(pvarResult
,
732 &pdispparams
->rgvarg
[pos
]);
735 static HRESULT WINAPI
SummaryInfoImpl_Invoke(
736 AutomationObject
* This
,
741 DISPPARAMS
* pDispParams
,
743 EXCEPINFO
* pExcepInfo
,
747 VARIANTARG varg0
, varg1
;
748 FILETIME ft
, ftlocal
;
755 switch (dispIdMember
)
757 case DISPID_SUMMARYINFO_PROPERTY
:
758 if (wFlags
& DISPATCH_PROPERTYGET
)
766 static WCHAR szEmpty
[] = {0};
768 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
769 if (FAILED(hr
)) return hr
;
770 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
771 &ft
, szEmpty
, &size
);
772 if (ret
!= ERROR_SUCCESS
&&
773 ret
!= ERROR_MORE_DATA
)
775 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
776 return DISP_E_EXCEPTION
;
786 V_VT(pVarResult
) = VT_I4
;
787 V_I4(pVarResult
) = value
;
791 if (!(str
= msi_alloc(++size
* sizeof(WCHAR
))))
792 ERR("Out of memory\n");
793 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
794 NULL
, str
, &size
)) != ERROR_SUCCESS
)
795 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
798 V_VT(pVarResult
) = VT_BSTR
;
799 V_BSTR(pVarResult
) = SysAllocString(str
);
805 FileTimeToLocalFileTime(&ft
, &ftlocal
);
806 FileTimeToSystemTime(&ftlocal
, &st
);
807 SystemTimeToVariantTime(&st
, &date
);
809 V_VT(pVarResult
) = VT_DATE
;
810 V_DATE(pVarResult
) = date
;
814 ERR("Unhandled variant type %d\n", type
);
817 else if (wFlags
& DISPATCH_PROPERTYPUT
)
819 UINT posValue
= DISPID_PROPERTYPUT
;
821 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
822 if (FAILED(hr
)) return hr
;
823 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
826 *puArgErr
= posValue
;
830 switch (V_VT(&varg1
))
834 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
838 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
839 SystemTimeToFileTime(&st
, &ftlocal
);
840 LocalFileTimeToFileTime(&ftlocal
, &ft
);
841 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
845 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
849 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
850 VariantClear(&varg1
);
851 return DISP_E_EXCEPTION
;
854 if (ret
!= ERROR_SUCCESS
)
856 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
857 return DISP_E_EXCEPTION
;
860 else return DISP_E_MEMBERNOTFOUND
;
863 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
864 if (wFlags
& DISPATCH_PROPERTYGET
) {
866 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
867 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
870 V_VT(pVarResult
) = VT_I4
;
871 V_I4(pVarResult
) = count
;
874 else return DISP_E_MEMBERNOTFOUND
;
878 return DISP_E_MEMBERNOTFOUND
;
881 VariantClear(&varg1
);
882 VariantClear(&varg0
);
887 static HRESULT WINAPI
RecordImpl_Invoke(
888 AutomationObject
* This
,
893 DISPPARAMS
* pDispParams
,
895 EXCEPINFO
* pExcepInfo
,
901 VARIANTARG varg0
, varg1
;
907 switch (dispIdMember
)
909 case DISPID_RECORD_FIELDCOUNT
:
910 if (wFlags
& DISPATCH_PROPERTYGET
) {
911 V_VT(pVarResult
) = VT_I4
;
912 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
914 else return DISP_E_MEMBERNOTFOUND
;
917 case DISPID_RECORD_STRINGDATA
:
918 if (wFlags
& DISPATCH_PROPERTYGET
) {
919 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
920 if (FAILED(hr
)) return hr
;
921 V_VT(pVarResult
) = VT_BSTR
;
922 V_BSTR(pVarResult
) = NULL
;
923 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
925 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
926 ERR("Out of memory\n");
927 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
928 V_BSTR(pVarResult
) = SysAllocString(szString
);
931 if (ret
!= ERROR_SUCCESS
)
932 ERR("MsiRecordGetString returned %d\n", ret
);
933 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
934 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
935 if (FAILED(hr
)) return hr
;
936 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_BSTR
, &varg1
, puArgErr
);
937 if (FAILED(hr
)) return hr
;
938 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
940 VariantClear(&varg1
);
941 ERR("MsiRecordSetString returned %d\n", ret
);
942 return DISP_E_EXCEPTION
;
945 else return DISP_E_MEMBERNOTFOUND
;
948 case DISPID_RECORD_INTEGERDATA
:
949 if (wFlags
& DISPATCH_PROPERTYGET
) {
950 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
951 if (FAILED(hr
)) return hr
;
952 V_VT(pVarResult
) = VT_I4
;
953 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
954 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
955 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
956 if (FAILED(hr
)) return hr
;
957 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_I4
, &varg1
, puArgErr
);
958 if (FAILED(hr
)) return hr
;
959 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
961 ERR("MsiRecordSetInteger returned %d\n", ret
);
962 return DISP_E_EXCEPTION
;
965 else return DISP_E_MEMBERNOTFOUND
;
969 return DISP_E_MEMBERNOTFOUND
;
972 VariantClear(&varg1
);
973 VariantClear(&varg0
);
978 static HRESULT WINAPI
ListImpl_Invoke(
979 AutomationObject
* This
,
984 DISPPARAMS
* pDispParams
,
986 EXCEPINFO
* pExcepInfo
,
989 ListData
*data
= private_data(This
);
992 IUnknown
*pUnk
= NULL
;
996 switch (dispIdMember
)
998 case DISPID_LIST__NEWENUM
:
999 if (wFlags
& DISPATCH_METHOD
) {
1000 V_VT(pVarResult
) = VT_UNKNOWN
;
1001 if (SUCCEEDED(hr
= create_list_enumerator(NULL
, (LPVOID
*)&pUnk
, This
, 0)))
1002 V_UNKNOWN(pVarResult
) = pUnk
;
1004 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr
);
1006 else return DISP_E_MEMBERNOTFOUND
;
1009 case DISPID_LIST_ITEM
:
1010 if (wFlags
& DISPATCH_PROPERTYGET
) {
1011 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1012 if (FAILED(hr
)) return hr
;
1013 if (V_I4(&varg0
) < 0 || V_I4(&varg0
) >= data
->ulCount
)
1014 return DISP_E_BADINDEX
;
1015 VariantCopy(pVarResult
, &data
->pVars
[V_I4(&varg0
)]);
1017 else return DISP_E_MEMBERNOTFOUND
;
1020 case DISPID_LIST_COUNT
:
1021 if (wFlags
& DISPATCH_PROPERTYGET
) {
1022 V_VT(pVarResult
) = VT_I4
;
1023 V_I4(pVarResult
) = data
->ulCount
;
1025 else return DISP_E_MEMBERNOTFOUND
;
1029 return DISP_E_MEMBERNOTFOUND
;
1032 VariantClear(&varg0
);
1037 static void WINAPI
ListImpl_Free(AutomationObject
*This
)
1039 ListData
*data
= private_data(This
);
1042 for (idx
=0; idx
<data
->ulCount
; idx
++)
1043 VariantClear(&data
->pVars
[idx
]);
1044 msi_free(data
->pVars
);
1047 static HRESULT WINAPI
ViewImpl_Invoke(
1048 AutomationObject
* This
,
1049 DISPID dispIdMember
,
1053 DISPPARAMS
* pDispParams
,
1054 VARIANT
* pVarResult
,
1055 EXCEPINFO
* pExcepInfo
,
1058 MSIHANDLE msiHandle
;
1059 IDispatch
*pDispatch
= NULL
;
1061 VARIANTARG varg0
, varg1
;
1064 VariantInit(&varg0
);
1065 VariantInit(&varg1
);
1067 switch (dispIdMember
)
1069 case DISPID_VIEW_EXECUTE
:
1070 if (wFlags
& DISPATCH_METHOD
)
1072 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1073 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1074 MsiViewExecute(This
->msiHandle
, ((AutomationObject
*)V_DISPATCH(&varg0
))->msiHandle
);
1076 MsiViewExecute(This
->msiHandle
, 0);
1078 else return DISP_E_MEMBERNOTFOUND
;
1081 case DISPID_VIEW_FETCH
:
1082 if (wFlags
& DISPATCH_METHOD
)
1084 V_VT(pVarResult
) = VT_DISPATCH
;
1085 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1087 if (SUCCEEDED(hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
*)&pDispatch
, &DIID_Record
, RecordImpl_Invoke
, NULL
, 0)))
1088 V_DISPATCH(pVarResult
) = pDispatch
;
1090 ERR("Failed to create Record object, hresult 0x%08x\n", hr
);
1092 else if (ret
== ERROR_NO_MORE_ITEMS
)
1093 V_DISPATCH(pVarResult
) = NULL
;
1096 ERR("MsiViewFetch returned %d\n", ret
);
1097 return DISP_E_EXCEPTION
;
1100 else return DISP_E_MEMBERNOTFOUND
;
1103 case DISPID_VIEW_MODIFY
:
1104 if (wFlags
& DISPATCH_METHOD
)
1106 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1107 if (FAILED(hr
)) return hr
;
1108 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1109 if (FAILED(hr
)) return hr
;
1110 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1111 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1113 VariantClear(&varg1
);
1114 ERR("MsiViewModify returned %d\n", ret
);
1115 return DISP_E_EXCEPTION
;
1118 else return DISP_E_MEMBERNOTFOUND
;
1121 case DISPID_VIEW_CLOSE
:
1122 if (wFlags
& DISPATCH_METHOD
)
1124 MsiViewClose(This
->msiHandle
);
1126 else return DISP_E_MEMBERNOTFOUND
;
1130 return DISP_E_MEMBERNOTFOUND
;
1133 VariantClear(&varg1
);
1134 VariantClear(&varg0
);
1139 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1140 DISPPARAMS
* pDispParams
,
1141 VARIANT
* pVarResult
,
1142 EXCEPINFO
* pExcepInfo
,
1145 if (!(wFlags
& DISPATCH_METHOD
))
1146 return DISP_E_MEMBERNOTFOUND
;
1150 VariantInit(pVarResult
);
1154 static HRESULT WINAPI
DatabaseImpl_Invoke(
1155 AutomationObject
* This
,
1156 DISPID dispIdMember
,
1160 DISPPARAMS
* pDispParams
,
1161 VARIANT
* pVarResult
,
1162 EXCEPINFO
* pExcepInfo
,
1165 MSIHANDLE msiHandle
;
1166 IDispatch
*pDispatch
= NULL
;
1168 VARIANTARG varg0
, varg1
;
1171 VariantInit(&varg0
);
1172 VariantInit(&varg1
);
1174 switch (dispIdMember
)
1176 case DISPID_DATABASE_SUMMARYINFORMATION
:
1177 if (wFlags
& DISPATCH_PROPERTYGET
)
1179 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1183 V_VT(pVarResult
) = VT_DISPATCH
;
1184 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1186 hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
*)&pDispatch
, &DIID_SummaryInfo
, SummaryInfoImpl_Invoke
, NULL
, 0);
1188 V_DISPATCH(pVarResult
) = pDispatch
;
1190 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr
);
1194 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1195 return DISP_E_EXCEPTION
;
1198 else return DISP_E_MEMBERNOTFOUND
;
1201 case DISPID_DATABASE_OPENVIEW
:
1202 if (wFlags
& DISPATCH_METHOD
)
1204 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1205 if (FAILED(hr
)) return hr
;
1206 V_VT(pVarResult
) = VT_DISPATCH
;
1207 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1209 if (SUCCEEDED(hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
*)&pDispatch
, &DIID_View
, ViewImpl_Invoke
, NULL
, 0)))
1210 V_DISPATCH(pVarResult
) = pDispatch
;
1212 ERR("Failed to create View object, hresult 0x%08x\n", hr
);
1216 VariantClear(&varg0
);
1217 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1218 return DISP_E_EXCEPTION
;
1221 else return DISP_E_MEMBERNOTFOUND
;
1224 case DISPID_INSTALLER_LASTERRORRECORD
:
1225 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1226 pVarResult
, pExcepInfo
,
1230 return DISP_E_MEMBERNOTFOUND
;
1233 VariantClear(&varg1
);
1234 VariantClear(&varg0
);
1239 static HRESULT WINAPI
SessionImpl_Invoke(
1240 AutomationObject
* This
,
1241 DISPID dispIdMember
,
1245 DISPPARAMS
* pDispParams
,
1246 VARIANT
* pVarResult
,
1247 EXCEPINFO
* pExcepInfo
,
1250 SessionData
*data
= private_data(This
);
1253 IDispatch
*pDispatch
= NULL
;
1254 MSIHANDLE msiHandle
;
1257 INSTALLSTATE iInstalled
, iAction
;
1258 VARIANTARG varg0
, varg1
;
1261 VariantInit(&varg0
);
1262 VariantInit(&varg1
);
1264 switch (dispIdMember
)
1266 case DISPID_SESSION_INSTALLER
:
1267 if (wFlags
& DISPATCH_PROPERTYGET
) {
1268 V_VT(pVarResult
) = VT_DISPATCH
;
1269 IDispatch_AddRef(data
->pInstaller
);
1270 V_DISPATCH(pVarResult
) = data
->pInstaller
;
1272 else return DISP_E_MEMBERNOTFOUND
;
1275 case DISPID_SESSION_PROPERTY
:
1276 if (wFlags
& DISPATCH_PROPERTYGET
) {
1277 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1278 if (FAILED(hr
)) return hr
;
1279 V_VT(pVarResult
) = VT_BSTR
;
1280 V_BSTR(pVarResult
) = NULL
;
1281 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1283 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1284 ERR("Out of memory\n");
1285 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1286 V_BSTR(pVarResult
) = SysAllocString(szString
);
1289 if (ret
!= ERROR_SUCCESS
)
1290 ERR("MsiGetProperty returned %d\n", ret
);
1291 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1292 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1293 if (FAILED(hr
)) return hr
;
1294 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_BSTR
, &varg1
, puArgErr
);
1296 VariantClear(&varg0
);
1299 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1301 VariantClear(&varg0
);
1302 VariantClear(&varg1
);
1303 ERR("MsiSetProperty returned %d\n", ret
);
1304 return DISP_E_EXCEPTION
;
1307 else return DISP_E_MEMBERNOTFOUND
;
1310 case DISPID_SESSION_LANGUAGE
:
1311 if (wFlags
& DISPATCH_PROPERTYGET
) {
1312 langId
= MsiGetLanguage(This
->msiHandle
);
1313 V_VT(pVarResult
) = VT_I4
;
1314 V_I4(pVarResult
) = langId
;
1316 else return DISP_E_MEMBERNOTFOUND
;
1319 case DISPID_SESSION_MODE
:
1320 if (wFlags
& DISPATCH_PROPERTYGET
) {
1321 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1322 if (FAILED(hr
)) return hr
;
1323 V_VT(pVarResult
) = VT_BOOL
;
1324 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
));
1325 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1326 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1327 if (FAILED(hr
)) return hr
;
1328 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_BOOL
, &varg1
, puArgErr
);
1329 if (FAILED(hr
)) return hr
;
1330 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1332 ERR("MsiSetMode returned %d\n", ret
);
1333 return DISP_E_EXCEPTION
;
1336 else return DISP_E_MEMBERNOTFOUND
;
1339 case DISPID_SESSION_DATABASE
:
1340 if (wFlags
& DISPATCH_PROPERTYGET
) {
1341 V_VT(pVarResult
) = VT_DISPATCH
;
1342 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1344 if (SUCCEEDED(hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
*)&pDispatch
, &DIID_Database
, DatabaseImpl_Invoke
, NULL
, 0)))
1345 V_DISPATCH(pVarResult
) = pDispatch
;
1347 ERR("Failed to create Database object, hresult 0x%08x\n", hr
);
1351 ERR("MsiGetActiveDatabase failed\n");
1352 return DISP_E_EXCEPTION
;
1355 else return DISP_E_MEMBERNOTFOUND
;
1358 case DISPID_SESSION_DOACTION
:
1359 if (wFlags
& DISPATCH_METHOD
) {
1360 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1361 if (FAILED(hr
)) return hr
;
1362 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1363 V_VT(pVarResult
) = VT_I4
;
1366 case ERROR_FUNCTION_NOT_CALLED
:
1367 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1370 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1372 case ERROR_INSTALL_USEREXIT
:
1373 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1375 case ERROR_INSTALL_FAILURE
:
1376 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1378 case ERROR_INSTALL_SUSPEND
:
1379 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1381 case ERROR_MORE_DATA
:
1382 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1384 case ERROR_INVALID_HANDLE_STATE
:
1385 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1387 case ERROR_INVALID_DATA
:
1388 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1391 VariantClear(&varg0
);
1392 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1393 return DISP_E_EXCEPTION
;
1396 else return DISP_E_MEMBERNOTFOUND
;
1399 case DISPID_SESSION_EVALUATECONDITION
:
1400 if (wFlags
& DISPATCH_METHOD
) {
1401 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1402 if (FAILED(hr
)) return hr
;
1403 V_VT(pVarResult
) = VT_I4
;
1404 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1406 else return DISP_E_MEMBERNOTFOUND
;
1409 case DISPID_SESSION_MESSAGE
:
1410 if(!(wFlags
& DISPATCH_METHOD
))
1411 return DISP_E_MEMBERNOTFOUND
;
1413 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1414 if (FAILED(hr
)) return hr
;
1415 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1416 if (FAILED(hr
)) return hr
;
1418 V_VT(pVarResult
) = VT_I4
;
1420 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1423 case DISPID_SESSION_SETINSTALLLEVEL
:
1424 if (wFlags
& DISPATCH_METHOD
) {
1425 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1426 if (FAILED(hr
)) return hr
;
1427 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1429 ERR("MsiSetInstallLevel returned %d\n", ret
);
1430 return DISP_E_EXCEPTION
;
1433 else return DISP_E_MEMBERNOTFOUND
;
1436 case DISPID_SESSION_FEATURECURRENTSTATE
:
1437 if (wFlags
& DISPATCH_PROPERTYGET
) {
1438 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1439 if (FAILED(hr
)) return hr
;
1440 V_VT(pVarResult
) = VT_I4
;
1441 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1442 V_I4(pVarResult
) = iInstalled
;
1445 ERR("MsiGetFeatureState returned %d\n", ret
);
1446 V_I4(pVarResult
) = msiInstallStateUnknown
;
1449 else return DISP_E_MEMBERNOTFOUND
;
1452 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1453 if (wFlags
& DISPATCH_PROPERTYGET
) {
1454 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1455 if (FAILED(hr
)) return hr
;
1456 V_VT(pVarResult
) = VT_I4
;
1457 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1458 V_I4(pVarResult
) = iAction
;
1461 ERR("MsiGetFeatureState returned %d\n", ret
);
1462 V_I4(pVarResult
) = msiInstallStateUnknown
;
1464 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1465 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1466 if (FAILED(hr
)) return hr
;
1467 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_I4
, &varg1
, puArgErr
);
1469 VariantClear(&varg0
);
1472 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1474 VariantClear(&varg0
);
1475 ERR("MsiSetFeatureState returned %d\n", ret
);
1476 return DISP_E_EXCEPTION
;
1479 else return DISP_E_MEMBERNOTFOUND
;
1483 return DISP_E_MEMBERNOTFOUND
;
1486 VariantClear(&varg1
);
1487 VariantClear(&varg0
);
1492 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1493 * registry value type. Used by Installer::RegistryValue. */
1494 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1496 static const WCHAR szREG_BINARY
[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1497 static const WCHAR szREG_
[] = { '(','R','E','G','_',']',0 };
1498 WCHAR
*szString
= (WCHAR
*)lpData
;
1499 LPWSTR szNewString
= NULL
;
1500 DWORD dwNewSize
= 0;
1505 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1506 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1507 idx
= (dwSize
/sizeof(WCHAR
))-1;
1508 while (idx
>= 0 && !szString
[idx
]) idx
--;
1509 for (; idx
>= 0; idx
--)
1510 if (!szString
[idx
]) szString
[idx
] = '\n';
1512 V_VT(pVarResult
) = VT_BSTR
;
1513 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1517 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1518 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1519 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1520 ERR("Out of memory\n");
1521 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1522 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1525 V_VT(pVarResult
) = VT_BSTR
;
1526 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1528 msi_free(szNewString
);
1532 V_VT(pVarResult
) = VT_I4
;
1533 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1537 V_VT(pVarResult
) = VT_BSTR
;
1538 V_BSTR(pVarResult
) = SysAllocString(szREG_
); /* Weird string, don't know why native returns it */
1542 V_VT(pVarResult
) = VT_BSTR
;
1543 V_BSTR(pVarResult
) = SysAllocString(szREG_BINARY
);
1547 V_VT(pVarResult
) = VT_EMPTY
;
1551 FIXME("Unhandled registry value type %d\n", dwType
);
1555 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1556 DISPPARAMS
* pDispParams
,
1557 VARIANT
* pVarResult
,
1558 EXCEPINFO
* pExcepInfo
,
1564 IDispatch
* dispatch
;
1566 if (!(wFlags
& DISPATCH_METHOD
))
1567 return DISP_E_MEMBERNOTFOUND
;
1569 VariantInit(&varg0
);
1570 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1574 V_VT(pVarResult
) = VT_DISPATCH
;
1576 hrec
= MsiCreateRecord(V_I4(&varg0
));
1578 return DISP_E_EXCEPTION
;
1580 hr
= create_automation_object(hrec
, NULL
, (LPVOID
*)&dispatch
,
1581 &DIID_Record
, RecordImpl_Invoke
, NULL
, 0);
1583 V_DISPATCH(pVarResult
) = dispatch
;
1588 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1590 DISPPARAMS
* pDispParams
,
1591 VARIANT
* pVarResult
,
1592 EXCEPINFO
* pExcepInfo
,
1598 IDispatch
* dispatch
;
1599 VARIANTARG varg0
, varg1
;
1601 if (!(wFlags
& DISPATCH_METHOD
))
1602 return DISP_E_MEMBERNOTFOUND
;
1604 if (pDispParams
->cArgs
== 0)
1605 return DISP_E_TYPEMISMATCH
;
1607 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1608 return DISP_E_TYPEMISMATCH
;
1610 VariantInit(&varg0
);
1611 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1615 VariantInit(&varg1
);
1616 if (pDispParams
->cArgs
== 2)
1618 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1624 V_VT(&varg1
) = VT_I4
;
1628 V_VT(pVarResult
) = VT_DISPATCH
;
1630 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1631 if (ret
!= ERROR_SUCCESS
)
1633 hr
= DISP_E_EXCEPTION
;
1637 hr
= create_session(hpkg
, (IDispatch
*)This
, &dispatch
);
1639 V_DISPATCH(pVarResult
) = dispatch
;
1642 VariantClear(&varg0
);
1643 VariantClear(&varg1
);
1647 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1648 DISPPARAMS
* pDispParams
,
1649 VARIANT
* pVarResult
,
1650 EXCEPINFO
* pExcepInfo
,
1656 if (!(wFlags
& DISPATCH_METHOD
))
1657 return DISP_E_MEMBERNOTFOUND
;
1659 VariantInit(&varg0
);
1660 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1664 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1666 VariantInit(pVarResult
);
1668 VariantClear(&varg0
);
1672 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1673 DISPPARAMS
* pDispParams
,
1674 VARIANT
* pVarResult
,
1675 EXCEPINFO
* pExcepInfo
,
1681 IDispatch
* dispatch
;
1682 VARIANTARG varg0
, varg1
;
1684 if (!(wFlags
& DISPATCH_METHOD
))
1685 return DISP_E_MEMBERNOTFOUND
;
1687 VariantInit(&varg0
);
1688 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1692 VariantInit(&varg1
);
1693 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1697 V_VT(pVarResult
) = VT_DISPATCH
;
1699 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1700 if (ret
!= ERROR_SUCCESS
)
1702 hr
= DISP_E_EXCEPTION
;
1706 hr
= create_automation_object(hdb
, NULL
, (LPVOID
*)&dispatch
,
1707 &DIID_Database
, DatabaseImpl_Invoke
, NULL
, 0);
1709 V_DISPATCH(pVarResult
) = dispatch
;
1712 VariantClear(&varg0
);
1713 VariantClear(&varg1
);
1717 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1718 DISPPARAMS
* pDispParams
,
1719 VARIANT
* pVarResult
,
1720 EXCEPINFO
* pExcepInfo
,
1723 if (!(wFlags
& DISPATCH_METHOD
))
1724 return DISP_E_MEMBERNOTFOUND
;
1728 VariantInit(pVarResult
);
1732 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1733 DISPPARAMS
* pDispParams
,
1734 VARIANT
* pVarResult
,
1735 EXCEPINFO
* pExcepInfo
,
1742 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1743 return DISP_E_MEMBERNOTFOUND
;
1745 if (wFlags
& DISPATCH_PROPERTYPUT
)
1747 VariantInit(&varg0
);
1748 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1752 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1753 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1754 return DISP_E_EXCEPTION
;
1756 else if (wFlags
& DISPATCH_PROPERTYGET
)
1758 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1759 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1760 return DISP_E_EXCEPTION
;
1762 V_VT(pVarResult
) = VT_I4
;
1763 V_I4(pVarResult
) = ui
;
1769 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1770 DISPPARAMS
* pDispParams
,
1771 VARIANT
* pVarResult
,
1772 EXCEPINFO
* pExcepInfo
,
1775 if (!(wFlags
& DISPATCH_METHOD
))
1776 return DISP_E_MEMBERNOTFOUND
;
1780 VariantInit(pVarResult
);
1784 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1785 DISPPARAMS
* pDispParams
,
1786 VARIANT
* pVarResult
,
1787 EXCEPINFO
* pExcepInfo
,
1792 VARIANTARG varg0
, varg1
;
1794 if (!(wFlags
& DISPATCH_METHOD
))
1795 return DISP_E_MEMBERNOTFOUND
;
1797 VariantInit(&varg0
);
1798 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1802 VariantInit(&varg1
);
1803 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1807 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1808 if (ret
!= ERROR_SUCCESS
)
1810 hr
= DISP_E_EXCEPTION
;
1815 VariantClear(&varg0
);
1816 VariantClear(&varg1
);
1820 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1821 VARIANT
* pVarResult
,
1822 EXCEPINFO
* pExcepInfo
,
1826 DLLVERSIONINFO verinfo
;
1827 WCHAR version
[MAX_PATH
];
1829 static const WCHAR format
[] = {
1830 '%','d','.','%','d','.','%','d','.','%','d',0};
1832 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1833 return DISP_E_MEMBERNOTFOUND
;
1835 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1836 hr
= DllGetVersion(&verinfo
);
1840 sprintfW(version
, format
, verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1841 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1843 V_VT(pVarResult
) = VT_BSTR
;
1844 V_BSTR(pVarResult
) = SysAllocString(version
);
1848 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1849 DISPPARAMS
* pDispParams
,
1850 VARIANT
* pVarResult
,
1851 EXCEPINFO
* pExcepInfo
,
1854 if (!(wFlags
& DISPATCH_METHOD
))
1855 return DISP_E_MEMBERNOTFOUND
;
1859 VariantInit(pVarResult
);
1863 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
1864 DISPPARAMS
* pDispParams
,
1865 VARIANT
* pVarResult
,
1866 EXCEPINFO
* pExcepInfo
,
1874 LPWSTR szString
= NULL
;
1875 VARIANTARG varg0
, varg1
, varg2
;
1877 if (!(wFlags
& DISPATCH_METHOD
))
1878 return DISP_E_MEMBERNOTFOUND
;
1880 VariantInit(&varg0
);
1881 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1885 VariantInit(&varg1
);
1886 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1890 /* Save valuePos so we can save puArgErr if we are unable to do our type
1894 VariantInit(&varg2
);
1895 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
1899 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
1900 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
1902 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
1905 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
1907 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
1908 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
1910 hr
= DISP_E_BADINDEX
;
1914 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
1915 switch (V_VT(&varg2
))
1917 /* Return VT_BOOL clarifying whether registry key exists or not. */
1919 V_VT(pVarResult
) = VT_BOOL
;
1920 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
);
1923 /* Return the value of specified key if it exists. */
1925 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
1926 NULL
, NULL
, NULL
, &size
);
1927 if (ret
!= ERROR_SUCCESS
)
1929 hr
= DISP_E_BADINDEX
;
1933 szString
= msi_alloc(size
);
1940 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
1941 &type
, (LPBYTE
)szString
, &size
);
1942 if (ret
!= ERROR_SUCCESS
)
1945 hr
= DISP_E_BADINDEX
;
1949 variant_from_registry_value(pVarResult
, type
,
1950 (LPBYTE
)szString
, size
);
1954 /* Try to make it into VT_I4, can use VariantChangeType for this. */
1956 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
1959 if (hr
== DISP_E_TYPEMISMATCH
)
1960 *puArgErr
= posValue
;
1965 /* Retrieve class name or maximum value name or subkey name size. */
1967 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
1968 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1969 else if (V_I4(&varg2
) > 0)
1970 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
1971 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
1972 else /* V_I4(&varg2) < 0 */
1973 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
1974 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1976 if (ret
!= ERROR_SUCCESS
)
1979 szString
= msi_alloc(++size
* sizeof(WCHAR
));
1987 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
1988 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1989 else if (V_I4(&varg2
) > 0)
1990 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
1991 &size
, 0, 0, NULL
, NULL
);
1992 else /* V_I4(&varg2) < 0 */
1993 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
1995 if (ret
== ERROR_SUCCESS
)
1997 V_VT(pVarResult
) = VT_BSTR
;
1998 V_BSTR(pVarResult
) = SysAllocString(szString
);
2005 VariantClear(&varg0
);
2006 VariantClear(&varg1
);
2007 VariantClear(&varg2
);
2012 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2013 DISPPARAMS
* pDispParams
,
2014 VARIANT
* pVarResult
,
2015 EXCEPINFO
* pExcepInfo
,
2018 if (!(wFlags
& DISPATCH_METHOD
))
2019 return DISP_E_MEMBERNOTFOUND
;
2023 VariantInit(pVarResult
);
2027 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2028 DISPPARAMS
* pDispParams
,
2029 VARIANT
* pVarResult
,
2030 EXCEPINFO
* pExcepInfo
,
2033 if (!(wFlags
& DISPATCH_METHOD
))
2034 return DISP_E_MEMBERNOTFOUND
;
2038 VariantInit(pVarResult
);
2042 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2043 DISPPARAMS
* pDispParams
,
2044 VARIANT
* pVarResult
,
2045 EXCEPINFO
* pExcepInfo
,
2048 if (!(wFlags
& DISPATCH_METHOD
))
2049 return DISP_E_MEMBERNOTFOUND
;
2053 VariantInit(pVarResult
);
2057 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2058 DISPPARAMS
* pDispParams
,
2059 VARIANT
* pVarResult
,
2060 EXCEPINFO
* pExcepInfo
,
2063 if (!(wFlags
& DISPATCH_METHOD
))
2064 return DISP_E_MEMBERNOTFOUND
;
2068 VariantInit(pVarResult
);
2072 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2073 DISPPARAMS
* pDispParams
,
2074 VARIANT
* pVarResult
,
2075 EXCEPINFO
* pExcepInfo
,
2081 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2082 return DISP_E_MEMBERNOTFOUND
;
2084 VariantInit(&varg0
);
2085 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2089 V_VT(pVarResult
) = VT_I4
;
2090 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2092 VariantClear(&varg0
);
2096 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2097 DISPPARAMS
* pDispParams
,
2098 VARIANT
* pVarResult
,
2099 EXCEPINFO
* pExcepInfo
,
2106 VARIANTARG varg0
, varg1
;
2108 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2109 return DISP_E_MEMBERNOTFOUND
;
2111 VariantInit(&varg0
);
2112 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2116 VariantInit(&varg1
);
2117 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2121 V_VT(pVarResult
) = VT_BSTR
;
2122 V_BSTR(pVarResult
) = NULL
;
2124 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2125 if (ret
!= ERROR_SUCCESS
)
2127 hr
= DISP_E_EXCEPTION
;
2131 str
= msi_alloc(++size
* sizeof(WCHAR
));
2138 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2139 if (ret
!= ERROR_SUCCESS
)
2141 hr
= DISP_E_EXCEPTION
;
2145 V_BSTR(pVarResult
) = SysAllocString(str
);
2150 VariantClear(&varg0
);
2151 VariantClear(&varg1
);
2155 static void cleanup_products(IDispatch
* dispatch
, ULONG count
)
2158 ListData
* ldata
= private_data((AutomationObject
*)dispatch
);
2160 for (i
= 0; i
< count
- 1; i
++)
2161 VariantClear(&ldata
->pVars
[i
]);
2164 msi_free(ldata
->pVars
);
2166 IDispatch_Release(dispatch
);
2169 static HRESULT
InstallerImpl_Products(WORD wFlags
,
2170 DISPPARAMS
* pDispParams
,
2171 VARIANT
* pVarResult
,
2172 EXCEPINFO
* pExcepInfo
,
2179 IDispatch
*dispatch
;
2180 WCHAR product
[GUID_SIZE
];
2182 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2183 return DISP_E_MEMBERNOTFOUND
;
2185 /* Find number of products. */
2186 while ((ret
= MsiEnumProductsW(idx
, product
)) == ERROR_SUCCESS
)
2189 if (ret
!= ERROR_NO_MORE_ITEMS
)
2190 return DISP_E_EXCEPTION
;
2192 V_VT(pVarResult
) = VT_DISPATCH
;
2193 hr
= create_automation_object(0, NULL
, (LPVOID
*)&dispatch
,
2194 &DIID_StringList
, ListImpl_Invoke
,
2195 ListImpl_Free
, sizeof(ListData
));
2199 V_DISPATCH(pVarResult
) = dispatch
;
2201 /* Save product strings. */
2202 ldata
= private_data((AutomationObject
*)dispatch
);
2204 ldata
->pVars
= msi_alloc_zero(sizeof(VARIANT
) * idx
);
2207 IDispatch_Release(dispatch
);
2208 return E_OUTOFMEMORY
;
2211 ldata
->ulCount
= idx
;
2212 for (idx
= 0; idx
< ldata
->ulCount
; idx
++)
2214 ret
= MsiEnumProductsW(idx
, product
);
2215 if (ret
!= ERROR_SUCCESS
)
2217 cleanup_products(dispatch
, idx
- 1);
2218 return DISP_E_EXCEPTION
;
2221 VariantInit(&ldata
->pVars
[idx
]);
2222 V_VT(&ldata
->pVars
[idx
]) = VT_BSTR
;
2223 V_BSTR(&ldata
->pVars
[idx
]) = SysAllocString(product
);
2229 static HRESULT
InstallerImpl_RelatedProducts(WORD wFlags
,
2230 DISPPARAMS
* pDispParams
,
2231 VARIANT
* pVarResult
,
2232 EXCEPINFO
* pExcepInfo
,
2240 IDispatch
* dispatch
;
2241 WCHAR product
[GUID_SIZE
];
2243 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2244 return DISP_E_MEMBERNOTFOUND
;
2246 VariantInit(&varg0
);
2247 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2251 /* Find number of related products. */
2255 ret
= MsiEnumRelatedProductsW(V_BSTR(&varg0
), 0, idx
, product
);
2256 if (ret
== ERROR_SUCCESS
)
2258 } while (ret
== ERROR_SUCCESS
);
2260 if (ret
!= ERROR_NO_MORE_ITEMS
)
2262 hr
= DISP_E_EXCEPTION
;
2266 V_VT(pVarResult
) = VT_DISPATCH
;
2268 hr
= create_automation_object(0, NULL
, (LPVOID
*)&dispatch
,
2269 &DIID_StringList
, ListImpl_Invoke
,
2270 ListImpl_Free
, sizeof(ListData
));
2274 V_DISPATCH(pVarResult
) = dispatch
;
2276 /* Save product strings. */
2277 ldata
= private_data((AutomationObject
*)dispatch
);
2278 ldata
->pVars
= msi_alloc(sizeof(VARIANT
) * idx
);
2281 IDispatch_Release(dispatch
);
2286 ldata
->ulCount
= idx
;
2287 for (idx
= 0; idx
< ldata
->ulCount
; idx
++)
2289 ret
= MsiEnumRelatedProductsW(V_BSTR(&varg0
), 0, idx
, product
);
2290 if (ret
!= ERROR_SUCCESS
)
2292 cleanup_products(dispatch
, idx
- 1);
2293 hr
= DISP_E_EXCEPTION
;
2297 VariantInit(&ldata
->pVars
[idx
]);
2298 V_VT(&ldata
->pVars
[idx
]) = VT_BSTR
;
2299 V_BSTR(&ldata
->pVars
[idx
]) = SysAllocString(product
);
2305 VariantClear(&varg0
);
2309 static HRESULT WINAPI
InstallerImpl_Invoke(
2310 AutomationObject
* This
,
2311 DISPID dispIdMember
,
2315 DISPPARAMS
* pDispParams
,
2316 VARIANT
* pVarResult
,
2317 EXCEPINFO
* pExcepInfo
,
2320 switch (dispIdMember
)
2322 case DISPID_INSTALLER_CREATERECORD
:
2323 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2324 pVarResult
, pExcepInfo
, puArgErr
);
2326 case DISPID_INSTALLER_OPENPACKAGE
:
2327 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2328 pVarResult
, pExcepInfo
, puArgErr
);
2330 case DISPID_INSTALLER_OPENPRODUCT
:
2331 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2332 pVarResult
, pExcepInfo
, puArgErr
);
2334 case DISPID_INSTALLER_OPENDATABASE
:
2335 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2336 pVarResult
, pExcepInfo
, puArgErr
);
2338 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2339 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2340 pVarResult
, pExcepInfo
,
2343 case DISPID_INSTALLER_UILEVEL
:
2344 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2345 pVarResult
, pExcepInfo
, puArgErr
);
2347 case DISPID_INSTALLER_ENABLELOG
:
2348 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2349 pVarResult
, pExcepInfo
, puArgErr
);
2351 case DISPID_INSTALLER_INSTALLPRODUCT
:
2352 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2353 pVarResult
, pExcepInfo
,
2356 case DISPID_INSTALLER_VERSION
:
2357 return InstallerImpl_Version(wFlags
, pVarResult
,
2358 pExcepInfo
, puArgErr
);
2360 case DISPID_INSTALLER_LASTERRORRECORD
:
2361 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2362 pVarResult
, pExcepInfo
,
2365 case DISPID_INSTALLER_REGISTRYVALUE
:
2366 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2367 pVarResult
, pExcepInfo
,
2370 case DISPID_INSTALLER_ENVIRONMENT
:
2371 return InstallerImpl_Environment(wFlags
, pDispParams
,
2372 pVarResult
, pExcepInfo
, puArgErr
);
2374 case DISPID_INSTALLER_FILEATTRIBUTES
:
2375 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2376 pVarResult
, pExcepInfo
,
2379 case DISPID_INSTALLER_FILESIZE
:
2380 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2381 pVarResult
, pExcepInfo
, puArgErr
);
2383 case DISPID_INSTALLER_FILEVERSION
:
2384 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2385 pVarResult
, pExcepInfo
, puArgErr
);
2387 case DISPID_INSTALLER_PRODUCTSTATE
:
2388 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2389 pVarResult
, pExcepInfo
, puArgErr
);
2391 case DISPID_INSTALLER_PRODUCTINFO
:
2392 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2393 pVarResult
, pExcepInfo
, puArgErr
);
2395 case DISPID_INSTALLER_PRODUCTS
:
2396 return InstallerImpl_Products(wFlags
, pDispParams
,
2397 pVarResult
, pExcepInfo
, puArgErr
);
2399 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2400 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2401 pVarResult
, pExcepInfo
,
2405 return DISP_E_MEMBERNOTFOUND
;
2409 /* Wrapper around create_automation_object to create an installer object. */
2410 HRESULT
create_msiserver(IUnknown
*pOuter
, LPVOID
*ppObj
)
2412 return create_automation_object(0, pOuter
, ppObj
, &DIID_Installer
, InstallerImpl_Invoke
, NULL
, 0);
2415 /* Wrapper around create_automation_object to create a session object. */
2416 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*pInstaller
, IDispatch
**pDispatch
)
2418 HRESULT hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
)pDispatch
, &DIID_Session
, SessionImpl_Invoke
, NULL
, sizeof(SessionData
));
2419 if (SUCCEEDED(hr
) && pDispatch
&& *pDispatch
)
2420 ((SessionData
*)private_data((AutomationObject
*)*pDispatch
))->pInstaller
= pInstaller
;