2 * Implementation of OLE Automation for Microsoft Installer (msi.dll)
4 * Copyright 2007 Misha Koshelev
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #include "msiserver.h"
38 #include "msiserver_dispids.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
42 #define REG_INDEX_CLASSES_ROOT 0
43 #define REG_INDEX_DYN_DATA 6
46 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
47 * called from AutomationObject::Invoke, and pass this function to create_automation_object.
50 typedef struct AutomationObject AutomationObject
;
52 typedef HRESULT (*autoInvokeFunc
)(AutomationObject
* This
,
53 DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD flags
, DISPPARAMS
* pDispParams
,
54 VARIANT
* result
, EXCEPINFO
* ei
, UINT
* arg_err
);
56 typedef void (*autoFreeFunc
)(AutomationObject
* This
);
58 struct AutomationObject
{
59 IDispatch IDispatch_iface
;
60 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface
;
63 /* Clsid for this class and it's appropriate ITypeInfo object */
67 /* The MSI handle of the current object */
70 /* A function that is called from AutomationObject::Invoke, specific to this type of object. */
71 autoInvokeFunc funcInvoke
;
72 /* A function that is called from AutomationObject::Release when the object is being freed to free any private
73 * data structures (or NULL) */
74 autoFreeFunc funcFree
;
77 static HRESULT
create_list_enumerator(IUnknown
*, void**, AutomationObject
*, ULONG
);
80 * ListEnumerator - IEnumVARIANT implementation for MSI automation lists.
84 IEnumVARIANT IEnumVARIANT_iface
;
87 /* Current position and pointer to AutomationObject that stores actual data */
89 AutomationObject
*pObj
;
93 * Structures for additional data required by specific automation objects
102 AutomationObject autoobj
;
103 IDispatch
*installer
;
106 /* Load type info so we don't have to process GetIDsOfNames */
107 HRESULT
load_type_info(IDispatch
*iface
, ITypeInfo
**pptinfo
, REFIID clsid
, LCID lcid
)
110 LPTYPELIB pLib
= NULL
;
111 LPTYPEINFO pInfo
= NULL
;
112 static const WCHAR szMsiServer
[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b'};
114 TRACE("(%p)->(%s,%d)\n", iface
, debugstr_guid(clsid
), lcid
);
116 /* Load registered type library */
117 hr
= LoadRegTypeLib(&LIBID_WindowsInstaller
, 1, 0, lcid
, &pLib
);
119 hr
= LoadTypeLib(szMsiServer
, &pLib
);
121 ERR("Could not load msiserver.tlb\n");
126 /* Get type information for object */
127 hr
= ITypeLib_GetTypeInfoOfGuid(pLib
, clsid
, &pInfo
);
128 ITypeLib_Release(pLib
);
130 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid
));
137 static inline AutomationObject
*impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
139 return CONTAINING_RECORD(iface
, AutomationObject
, IProvideMultipleClassInfo_iface
);
142 static inline AutomationObject
*impl_from_IDispatch( IDispatch
*iface
)
144 return CONTAINING_RECORD(iface
, AutomationObject
, IDispatch_iface
);
147 /* Macro to get pointer to private object data */
148 static inline void *private_data( AutomationObject
*This
)
154 * AutomationObject methods
157 static HRESULT WINAPI
AutomationObject_QueryInterface(IDispatch
* iface
, REFIID riid
, void** ppvObject
)
159 AutomationObject
*This
= impl_from_IDispatch(iface
);
161 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
163 if (ppvObject
== NULL
)
168 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
169 IsEqualGUID(riid
, &IID_IDispatch
) ||
170 IsEqualGUID(riid
, This
->clsid
))
171 *ppvObject
= &This
->IDispatch_iface
;
172 else if (IsEqualGUID(riid
, &IID_IProvideClassInfo
) ||
173 IsEqualGUID(riid
, &IID_IProvideClassInfo2
) ||
174 IsEqualGUID(riid
, &IID_IProvideMultipleClassInfo
))
175 *ppvObject
= &This
->IProvideMultipleClassInfo_iface
;
178 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
179 return E_NOINTERFACE
;
182 IDispatch_AddRef(iface
);
187 static ULONG WINAPI
AutomationObject_AddRef(IDispatch
* iface
)
189 AutomationObject
*This
= impl_from_IDispatch(iface
);
191 TRACE("(%p/%p)\n", iface
, This
);
193 return InterlockedIncrement(&This
->ref
);
196 static ULONG WINAPI
AutomationObject_Release(IDispatch
* iface
)
198 AutomationObject
*This
= impl_from_IDispatch(iface
);
199 ULONG ref
= InterlockedDecrement(&This
->ref
);
201 TRACE("(%p/%p)\n", iface
, This
);
205 if (This
->funcFree
) This
->funcFree(This
);
206 ITypeInfo_Release(This
->iTypeInfo
);
207 MsiCloseHandle(This
->msiHandle
);
214 static HRESULT WINAPI
AutomationObject_GetTypeInfoCount(
218 AutomationObject
*This
= impl_from_IDispatch(iface
);
220 TRACE("(%p/%p)->(%p)\n", iface
, This
, pctinfo
);
225 static HRESULT WINAPI
AutomationObject_GetTypeInfo(
231 AutomationObject
*This
= impl_from_IDispatch(iface
);
232 TRACE("(%p/%p)->(%d,%d,%p)\n", iface
, This
, iTInfo
, lcid
, ppTInfo
);
234 ITypeInfo_AddRef(This
->iTypeInfo
);
235 *ppTInfo
= This
->iTypeInfo
;
239 static HRESULT WINAPI
AutomationObject_GetIDsOfNames(
247 AutomationObject
*This
= impl_from_IDispatch(iface
);
249 TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface
, This
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
251 if (!IsEqualGUID(riid
, &IID_NULL
)) return E_INVALIDARG
;
252 hr
= ITypeInfo_GetIDsOfNames(This
->iTypeInfo
, rgszNames
, cNames
, rgDispId
);
253 if (hr
== DISP_E_UNKNOWNNAME
)
256 for (idx
=0; idx
<cNames
; idx
++)
258 if (rgDispId
[idx
] == DISPID_UNKNOWN
)
259 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames
[idx
]), debugstr_guid(This
->clsid
));
265 /* Maximum number of allowed function parameters+1 */
266 #define MAX_FUNC_PARAMS 20
268 /* Some error checking is done here to simplify individual object function invocation */
269 static HRESULT WINAPI
AutomationObject_Invoke(
275 DISPPARAMS
* pDispParams
,
277 EXCEPINFO
* pExcepInfo
,
280 AutomationObject
*This
= impl_from_IDispatch(iface
);
282 unsigned int uArgErr
;
283 VARIANT varResultDummy
;
284 BSTR bstrName
= NULL
;
286 TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface
, This
, dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
288 if (!IsEqualIID(riid
, &IID_NULL
))
290 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
291 return DISP_E_UNKNOWNNAME
;
294 if (wFlags
& DISPATCH_PROPERTYGET
&& !pVarResult
)
296 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
297 return DISP_E_PARAMNOTOPTIONAL
;
300 /* This simplifies our individual object invocation functions */
301 if (puArgErr
== NULL
) puArgErr
= &uArgErr
;
302 if (pVarResult
== NULL
) pVarResult
= &varResultDummy
;
304 /* Assume return type is void unless determined otherwise */
305 VariantInit(pVarResult
);
307 /* If we are tracing, we want to see the name of the member we are invoking */
310 ITypeInfo_GetDocumentation(This
->iTypeInfo
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
311 TRACE("Method %d, %s\n", dispIdMember
, debugstr_w(bstrName
));
314 hr
= This
->funcInvoke(This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
316 if (hr
== DISP_E_MEMBERNOTFOUND
) {
317 if (bstrName
== NULL
) ITypeInfo_GetDocumentation(This
->iTypeInfo
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
318 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember
, debugstr_w(bstrName
), wFlags
, debugstr_guid(This
->clsid
));
320 else if (pExcepInfo
&&
321 (hr
== DISP_E_PARAMNOTFOUND
||
322 hr
== DISP_E_EXCEPTION
)) {
323 static const WCHAR szComma
[] = { ',',0 };
324 static const WCHAR szExceptionSource
[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
325 WCHAR szExceptionDescription
[MAX_PATH
];
326 BSTR bstrParamNames
[MAX_FUNC_PARAMS
];
330 if (FAILED(ITypeInfo_GetNames(This
->iTypeInfo
, dispIdMember
, bstrParamNames
,
331 MAX_FUNC_PARAMS
, &namesNo
)))
333 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember
);
337 memset(szExceptionDescription
, 0, sizeof(szExceptionDescription
));
338 for (i
=0; i
<namesNo
; i
++)
340 if (bFirst
) bFirst
= FALSE
;
342 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], szComma
);
344 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], bstrParamNames
[i
]);
345 SysFreeString(bstrParamNames
[i
]);
348 memset(pExcepInfo
, 0, sizeof(EXCEPINFO
));
349 pExcepInfo
->wCode
= 1000;
350 pExcepInfo
->bstrSource
= SysAllocString(szExceptionSource
);
351 pExcepInfo
->bstrDescription
= SysAllocString(szExceptionDescription
);
352 hr
= DISP_E_EXCEPTION
;
356 /* Make sure we free the return variant if it is our dummy variant */
357 if (pVarResult
== &varResultDummy
) VariantClear(pVarResult
);
359 /* Free function name if we retrieved it */
360 SysFreeString(bstrName
);
362 TRACE("Returning 0x%08x, %s\n", hr
, SUCCEEDED(hr
) ? "ok" : "not ok");
367 static const struct IDispatchVtbl AutomationObjectVtbl
=
369 AutomationObject_QueryInterface
,
370 AutomationObject_AddRef
,
371 AutomationObject_Release
,
372 AutomationObject_GetTypeInfoCount
,
373 AutomationObject_GetTypeInfo
,
374 AutomationObject_GetIDsOfNames
,
375 AutomationObject_Invoke
379 * IProvideMultipleClassInfo methods
382 static HRESULT WINAPI
ProvideMultipleClassInfo_QueryInterface(
383 IProvideMultipleClassInfo
* iface
,
387 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
388 return IDispatch_QueryInterface(&This
->IDispatch_iface
, riid
, ppvoid
);
391 static ULONG WINAPI
ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo
* iface
)
393 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
394 return IDispatch_AddRef(&This
->IDispatch_iface
);
397 static ULONG WINAPI
ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo
* iface
)
399 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
400 return IDispatch_Release(&This
->IDispatch_iface
);
403 static HRESULT WINAPI
ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo
* iface
, ITypeInfo
** ppTI
)
405 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
406 TRACE("(%p/%p)->(%p)\n", iface
, This
, ppTI
);
407 return load_type_info(&This
->IDispatch_iface
, ppTI
, This
->clsid
, 0);
410 static HRESULT WINAPI
ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
* iface
, DWORD dwGuidKind
, GUID
* pGUID
)
412 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
413 TRACE("(%p/%p)->(%d,%s)\n", iface
, This
, dwGuidKind
, debugstr_guid(pGUID
));
415 if (dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
418 *pGUID
= *This
->clsid
;
423 static HRESULT WINAPI
ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo
* iface
, ULONG
* pcti
)
425 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
427 TRACE("(%p/%p)->(%p)\n", iface
, This
, pcti
);
432 static HRESULT WINAPI
ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo
* iface
,
435 ITypeInfo
** pptiCoClass
,
437 ULONG
* pcdispidReserved
,
441 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
443 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface
, This
, iti
, dwFlags
, pptiCoClass
, pdwTIFlags
, pcdispidReserved
, piidPrimary
, piidSource
);
448 if (dwFlags
& MULTICLASSINFO_GETTYPEINFO
)
449 load_type_info(&This
->IDispatch_iface
, pptiCoClass
, This
->clsid
, 0);
451 if (dwFlags
& MULTICLASSINFO_GETNUMRESERVEDDISPIDS
)
454 *pcdispidReserved
= 0;
457 if (dwFlags
& MULTICLASSINFO_GETIIDPRIMARY
){
458 *piidPrimary
= *This
->clsid
;
461 if (dwFlags
& MULTICLASSINFO_GETIIDSOURCE
){
462 *piidSource
= *This
->clsid
;
468 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl
=
470 ProvideMultipleClassInfo_QueryInterface
,
471 ProvideMultipleClassInfo_AddRef
,
472 ProvideMultipleClassInfo_Release
,
473 ProvideMultipleClassInfo_GetClassInfo
,
474 ProvideMultipleClassInfo_GetGUID
,
475 ProvideMultipleClassInfo_GetMultiTypeInfoCount
,
476 ProvideMultipleClassInfo_GetInfoOfIndex
479 /* Create the automation object, placing the result in the pointer ppObj. The automation object is created
480 * with the appropriate clsid and invocation function. */
481 static HRESULT
create_automation_object(MSIHANDLE msiHandle
, IUnknown
*pUnkOuter
, void **ppObj
, REFIID clsid
,
482 autoInvokeFunc invokeFunc
, autoFreeFunc freeFunc
, SIZE_T sizetPrivateData
)
484 AutomationObject
*object
;
487 TRACE("(%d,%p,%p,%s,%p,%p,%ld)\n", msiHandle
, pUnkOuter
, ppObj
, debugstr_guid(clsid
), invokeFunc
, freeFunc
, sizetPrivateData
);
490 return CLASS_E_NOAGGREGATION
;
492 object
= msi_alloc_zero( sizeof(AutomationObject
) + sizetPrivateData
);
494 object
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
495 object
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
498 object
->msiHandle
= msiHandle
;
499 object
->clsid
= (LPCLSID
)clsid
;
500 object
->funcInvoke
= invokeFunc
;
501 object
->funcFree
= freeFunc
;
503 /* Load our TypeInfo so we don't have to process GetIDsOfNames */
504 object
->iTypeInfo
= NULL
;
505 hr
= load_type_info(&object
->IDispatch_iface
, &object
->iTypeInfo
, clsid
, 0x0);
516 static HRESULT
init_automation_object(AutomationObject
*This
, MSIHANDLE msiHandle
, REFIID clsid
,
517 autoInvokeFunc invokeFunc
, autoFreeFunc freeFunc
)
519 TRACE("(%p, %d, %s, %p, %p)\n", This
, msiHandle
, debugstr_guid(clsid
), invokeFunc
, freeFunc
);
521 This
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
522 This
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
525 This
->msiHandle
= msiHandle
;
526 This
->clsid
= (LPCLSID
)clsid
;
527 This
->funcInvoke
= invokeFunc
;
528 This
->funcFree
= freeFunc
;
530 /* Load our TypeInfo so we don't have to process GetIDsOfNames */
531 This
->iTypeInfo
= NULL
;
532 return load_type_info(&This
->IDispatch_iface
, &This
->iTypeInfo
, clsid
, 0);
536 * ListEnumerator methods
539 static inline ListEnumerator
*impl_from_IEnumVARIANT(IEnumVARIANT
* iface
)
541 return CONTAINING_RECORD(iface
, ListEnumerator
, IEnumVARIANT_iface
);
544 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
,
547 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
549 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
551 if (ppvObject
== NULL
)
556 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IEnumVARIANT
))
560 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
561 return E_NOINTERFACE
;
564 IClassFactory_AddRef(iface
);
568 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
570 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
572 TRACE("(%p/%p)\n", iface
, This
);
574 return InterlockedIncrement(&This
->ref
);
577 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
579 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
580 ULONG ref
= InterlockedDecrement(&This
->ref
);
582 TRACE("(%p/%p)\n", iface
, This
);
586 if (This
->pObj
) IDispatch_Release(&This
->pObj
->IDispatch_iface
);
593 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
* rgVar
,
596 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
597 ListData
*data
= private_data(This
->pObj
);
600 TRACE("(%p,%uld,%p,%p)\n", iface
, celt
, rgVar
, pCeltFetched
);
602 if (pCeltFetched
!= NULL
)
608 for (local
= 0; local
< celt
; local
++)
609 VariantInit(&rgVar
[local
]);
611 for (idx
= This
->ulPos
, local
= 0; idx
< data
->ulCount
&& local
< celt
; idx
++, local
++)
612 VariantCopy(&rgVar
[local
], &data
->pVars
[idx
]);
614 if (pCeltFetched
!= NULL
)
615 *pCeltFetched
= local
;
618 return (local
< celt
) ? S_FALSE
: S_OK
;
621 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
623 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
624 ListData
*data
= private_data(This
->pObj
);
626 TRACE("(%p,%uld)\n", iface
, celt
);
629 if (This
->ulPos
>= data
->ulCount
)
631 This
->ulPos
= data
->ulCount
;
637 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
639 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
641 TRACE("(%p)\n", iface
);
647 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
649 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
652 TRACE("(%p,%p)\n", iface
, ppEnum
);
658 hr
= create_list_enumerator(NULL
, (LPVOID
*)ppEnum
, This
->pObj
, 0);
662 IUnknown_Release(*ppEnum
);
669 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
671 ListEnumerator_QueryInterface
,
672 ListEnumerator_AddRef
,
673 ListEnumerator_Release
,
676 ListEnumerator_Reset
,
680 /* Create a list enumerator, placing the result in the pointer ppObj. */
681 static HRESULT
create_list_enumerator(IUnknown
*outer
, void **ppObj
, AutomationObject
*aut_obj
, ULONG pos
)
683 ListEnumerator
*object
;
685 TRACE("(%p, %p, %p, %uld)\n", outer
, ppObj
, aut_obj
, pos
);
688 return CLASS_E_NOAGGREGATION
;
690 object
= msi_alloc( sizeof(ListEnumerator
) );
692 /* Set all the VTable references */
693 object
->IEnumVARIANT_iface
.lpVtbl
= &ListEnumerator_Vtbl
;
696 /* Store data that was passed */
698 object
->pObj
= aut_obj
;
699 if (aut_obj
) IDispatch_AddRef(&aut_obj
->IDispatch_iface
);
706 * Individual Object Invocation Functions
709 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
710 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
711 using DispGetParam/VariantChangeType. */
712 static HRESULT
DispGetParam_CopyOnly(
713 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
714 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
715 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
717 /* position is counted backwards */
720 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
721 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
722 if (*position
< pdispparams
->cArgs
) {
723 /* positional arg? */
724 pos
= pdispparams
->cArgs
- *position
- 1;
726 /* FIXME: is this how to handle named args? */
727 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
728 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
730 if (pos
==pdispparams
->cNamedArgs
)
731 return DISP_E_PARAMNOTFOUND
;
734 return VariantCopyInd(pvarResult
,
735 &pdispparams
->rgvarg
[pos
]);
738 static HRESULT
SummaryInfoImpl_Invoke(
739 AutomationObject
* This
,
744 DISPPARAMS
* pDispParams
,
746 EXCEPINFO
* pExcepInfo
,
750 VARIANTARG varg0
, varg1
;
751 FILETIME ft
, ftlocal
;
758 switch (dispIdMember
)
760 case DISPID_SUMMARYINFO_PROPERTY
:
761 if (wFlags
& DISPATCH_PROPERTYGET
)
769 static WCHAR szEmpty
[] = {0};
771 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
772 if (FAILED(hr
)) return hr
;
773 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
774 &ft
, szEmpty
, &size
);
775 if (ret
!= ERROR_SUCCESS
&&
776 ret
!= ERROR_MORE_DATA
)
778 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
779 return DISP_E_EXCEPTION
;
789 V_VT(pVarResult
) = VT_I4
;
790 V_I4(pVarResult
) = value
;
794 if (!(str
= msi_alloc(++size
* sizeof(WCHAR
))))
795 ERR("Out of memory\n");
796 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
797 NULL
, str
, &size
)) != ERROR_SUCCESS
)
798 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
801 V_VT(pVarResult
) = VT_BSTR
;
802 V_BSTR(pVarResult
) = SysAllocString(str
);
808 FileTimeToLocalFileTime(&ft
, &ftlocal
);
809 FileTimeToSystemTime(&ftlocal
, &st
);
810 SystemTimeToVariantTime(&st
, &date
);
812 V_VT(pVarResult
) = VT_DATE
;
813 V_DATE(pVarResult
) = date
;
817 ERR("Unhandled variant type %d\n", type
);
820 else if (wFlags
& DISPATCH_PROPERTYPUT
)
822 UINT posValue
= DISPID_PROPERTYPUT
;
824 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
825 if (FAILED(hr
)) return hr
;
826 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
829 *puArgErr
= posValue
;
833 switch (V_VT(&varg1
))
837 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
841 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
842 SystemTimeToFileTime(&st
, &ftlocal
);
843 LocalFileTimeToFileTime(&ftlocal
, &ft
);
844 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
848 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
852 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
853 VariantClear(&varg1
);
854 return DISP_E_EXCEPTION
;
857 if (ret
!= ERROR_SUCCESS
)
859 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
860 return DISP_E_EXCEPTION
;
863 else return DISP_E_MEMBERNOTFOUND
;
866 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
867 if (wFlags
& DISPATCH_PROPERTYGET
) {
869 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
870 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
873 V_VT(pVarResult
) = VT_I4
;
874 V_I4(pVarResult
) = count
;
877 else return DISP_E_MEMBERNOTFOUND
;
881 return DISP_E_MEMBERNOTFOUND
;
884 VariantClear(&varg1
);
885 VariantClear(&varg0
);
890 static HRESULT
RecordImpl_Invoke(
891 AutomationObject
* This
,
896 DISPPARAMS
* pDispParams
,
898 EXCEPINFO
* pExcepInfo
,
904 VARIANTARG varg0
, varg1
;
910 switch (dispIdMember
)
912 case DISPID_RECORD_FIELDCOUNT
:
913 if (wFlags
& DISPATCH_PROPERTYGET
) {
914 V_VT(pVarResult
) = VT_I4
;
915 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
917 else return DISP_E_MEMBERNOTFOUND
;
920 case DISPID_RECORD_STRINGDATA
:
921 if (wFlags
& DISPATCH_PROPERTYGET
) {
922 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
923 if (FAILED(hr
)) return hr
;
924 V_VT(pVarResult
) = VT_BSTR
;
925 V_BSTR(pVarResult
) = NULL
;
926 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
928 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
929 ERR("Out of memory\n");
930 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
931 V_BSTR(pVarResult
) = SysAllocString(szString
);
934 if (ret
!= ERROR_SUCCESS
)
935 ERR("MsiRecordGetString returned %d\n", ret
);
936 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
937 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
938 if (FAILED(hr
)) return hr
;
939 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_BSTR
, &varg1
, puArgErr
);
940 if (FAILED(hr
)) return hr
;
941 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
943 VariantClear(&varg1
);
944 ERR("MsiRecordSetString returned %d\n", ret
);
945 return DISP_E_EXCEPTION
;
948 else return DISP_E_MEMBERNOTFOUND
;
951 case DISPID_RECORD_INTEGERDATA
:
952 if (wFlags
& DISPATCH_PROPERTYGET
) {
953 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
954 if (FAILED(hr
)) return hr
;
955 V_VT(pVarResult
) = VT_I4
;
956 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
957 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
958 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
959 if (FAILED(hr
)) return hr
;
960 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_I4
, &varg1
, puArgErr
);
961 if (FAILED(hr
)) return hr
;
962 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
964 ERR("MsiRecordSetInteger returned %d\n", ret
);
965 return DISP_E_EXCEPTION
;
968 else return DISP_E_MEMBERNOTFOUND
;
972 return DISP_E_MEMBERNOTFOUND
;
975 VariantClear(&varg1
);
976 VariantClear(&varg0
);
981 static HRESULT
ListImpl_Invoke(
982 AutomationObject
* This
,
987 DISPPARAMS
* pDispParams
,
989 EXCEPINFO
* pExcepInfo
,
992 ListData
*data
= private_data(This
);
995 IUnknown
*pUnk
= NULL
;
999 switch (dispIdMember
)
1001 case DISPID_LIST__NEWENUM
:
1002 if (wFlags
& DISPATCH_METHOD
) {
1003 V_VT(pVarResult
) = VT_UNKNOWN
;
1004 if (SUCCEEDED(hr
= create_list_enumerator(NULL
, (LPVOID
*)&pUnk
, This
, 0)))
1005 V_UNKNOWN(pVarResult
) = pUnk
;
1007 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr
);
1009 else return DISP_E_MEMBERNOTFOUND
;
1012 case DISPID_LIST_ITEM
:
1013 if (wFlags
& DISPATCH_PROPERTYGET
) {
1014 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1015 if (FAILED(hr
)) return hr
;
1016 if (V_I4(&varg0
) < 0 || V_I4(&varg0
) >= data
->ulCount
)
1017 return DISP_E_BADINDEX
;
1018 VariantCopy(pVarResult
, &data
->pVars
[V_I4(&varg0
)]);
1020 else return DISP_E_MEMBERNOTFOUND
;
1023 case DISPID_LIST_COUNT
:
1024 if (wFlags
& DISPATCH_PROPERTYGET
) {
1025 V_VT(pVarResult
) = VT_I4
;
1026 V_I4(pVarResult
) = data
->ulCount
;
1028 else return DISP_E_MEMBERNOTFOUND
;
1032 return DISP_E_MEMBERNOTFOUND
;
1035 VariantClear(&varg0
);
1040 static void ListImpl_Free(AutomationObject
*This
)
1042 ListData
*data
= private_data(This
);
1045 for (idx
=0; idx
<data
->ulCount
; idx
++)
1046 VariantClear(&data
->pVars
[idx
]);
1047 msi_free(data
->pVars
);
1050 static HRESULT
ViewImpl_Invoke(
1051 AutomationObject
* This
,
1052 DISPID dispIdMember
,
1056 DISPPARAMS
* pDispParams
,
1057 VARIANT
* pVarResult
,
1058 EXCEPINFO
* pExcepInfo
,
1061 MSIHANDLE msiHandle
;
1062 IDispatch
*pDispatch
= NULL
;
1064 VARIANTARG varg0
, varg1
;
1067 VariantInit(&varg0
);
1068 VariantInit(&varg1
);
1070 switch (dispIdMember
)
1072 case DISPID_VIEW_EXECUTE
:
1073 if (wFlags
& DISPATCH_METHOD
)
1075 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1076 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1077 MsiViewExecute(This
->msiHandle
, ((AutomationObject
*)V_DISPATCH(&varg0
))->msiHandle
);
1079 MsiViewExecute(This
->msiHandle
, 0);
1081 else return DISP_E_MEMBERNOTFOUND
;
1084 case DISPID_VIEW_FETCH
:
1085 if (wFlags
& DISPATCH_METHOD
)
1087 V_VT(pVarResult
) = VT_DISPATCH
;
1088 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1090 if (SUCCEEDED(hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
*)&pDispatch
, &DIID_Record
, RecordImpl_Invoke
, NULL
, 0)))
1091 V_DISPATCH(pVarResult
) = pDispatch
;
1093 ERR("Failed to create Record object, hresult 0x%08x\n", hr
);
1095 else if (ret
== ERROR_NO_MORE_ITEMS
)
1096 V_DISPATCH(pVarResult
) = NULL
;
1099 ERR("MsiViewFetch returned %d\n", ret
);
1100 return DISP_E_EXCEPTION
;
1103 else return DISP_E_MEMBERNOTFOUND
;
1106 case DISPID_VIEW_MODIFY
:
1107 if (wFlags
& DISPATCH_METHOD
)
1109 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1110 if (FAILED(hr
)) return hr
;
1111 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1112 if (FAILED(hr
)) return hr
;
1113 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1114 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1116 VariantClear(&varg1
);
1117 ERR("MsiViewModify returned %d\n", ret
);
1118 return DISP_E_EXCEPTION
;
1121 else return DISP_E_MEMBERNOTFOUND
;
1124 case DISPID_VIEW_CLOSE
:
1125 if (wFlags
& DISPATCH_METHOD
)
1127 MsiViewClose(This
->msiHandle
);
1129 else return DISP_E_MEMBERNOTFOUND
;
1133 return DISP_E_MEMBERNOTFOUND
;
1136 VariantClear(&varg1
);
1137 VariantClear(&varg0
);
1142 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1143 DISPPARAMS
* pDispParams
,
1144 VARIANT
* pVarResult
,
1145 EXCEPINFO
* pExcepInfo
,
1148 if (!(wFlags
& DISPATCH_METHOD
))
1149 return DISP_E_MEMBERNOTFOUND
;
1153 VariantInit(pVarResult
);
1157 static HRESULT
DatabaseImpl_Invoke(
1158 AutomationObject
* This
,
1159 DISPID dispIdMember
,
1163 DISPPARAMS
* pDispParams
,
1164 VARIANT
* pVarResult
,
1165 EXCEPINFO
* pExcepInfo
,
1168 MSIHANDLE msiHandle
;
1169 IDispatch
*pDispatch
= NULL
;
1171 VARIANTARG varg0
, varg1
;
1174 VariantInit(&varg0
);
1175 VariantInit(&varg1
);
1177 switch (dispIdMember
)
1179 case DISPID_DATABASE_SUMMARYINFORMATION
:
1180 if (wFlags
& DISPATCH_PROPERTYGET
)
1182 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1186 V_VT(pVarResult
) = VT_DISPATCH
;
1187 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1189 hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
*)&pDispatch
, &DIID_SummaryInfo
, SummaryInfoImpl_Invoke
, NULL
, 0);
1191 V_DISPATCH(pVarResult
) = pDispatch
;
1193 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr
);
1197 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1198 return DISP_E_EXCEPTION
;
1201 else return DISP_E_MEMBERNOTFOUND
;
1204 case DISPID_DATABASE_OPENVIEW
:
1205 if (wFlags
& DISPATCH_METHOD
)
1207 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1208 if (FAILED(hr
)) return hr
;
1209 V_VT(pVarResult
) = VT_DISPATCH
;
1210 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1212 if (SUCCEEDED(hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
*)&pDispatch
, &DIID_View
, ViewImpl_Invoke
, NULL
, 0)))
1213 V_DISPATCH(pVarResult
) = pDispatch
;
1215 ERR("Failed to create View object, hresult 0x%08x\n", hr
);
1219 VariantClear(&varg0
);
1220 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1221 return DISP_E_EXCEPTION
;
1224 else return DISP_E_MEMBERNOTFOUND
;
1227 case DISPID_INSTALLER_LASTERRORRECORD
:
1228 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1229 pVarResult
, pExcepInfo
,
1233 return DISP_E_MEMBERNOTFOUND
;
1236 VariantClear(&varg1
);
1237 VariantClear(&varg0
);
1242 static HRESULT
SessionImpl_Invoke(
1243 AutomationObject
* This
,
1244 DISPID dispIdMember
,
1248 DISPPARAMS
* pDispParams
,
1249 VARIANT
* pVarResult
,
1250 EXCEPINFO
* pExcepInfo
,
1253 SessionObject
*session
= (SessionObject
*)This
;
1256 IDispatch
*pDispatch
= NULL
;
1257 MSIHANDLE msiHandle
;
1260 INSTALLSTATE iInstalled
, iAction
;
1261 VARIANTARG varg0
, varg1
;
1264 VariantInit(&varg0
);
1265 VariantInit(&varg1
);
1267 switch (dispIdMember
)
1269 case DISPID_SESSION_INSTALLER
:
1270 if (wFlags
& DISPATCH_PROPERTYGET
) {
1271 V_VT(pVarResult
) = VT_DISPATCH
;
1272 IDispatch_AddRef(session
->installer
);
1273 V_DISPATCH(pVarResult
) = session
->installer
;
1275 else return DISP_E_MEMBERNOTFOUND
;
1278 case DISPID_SESSION_PROPERTY
:
1279 if (wFlags
& DISPATCH_PROPERTYGET
) {
1280 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1281 if (FAILED(hr
)) return hr
;
1282 V_VT(pVarResult
) = VT_BSTR
;
1283 V_BSTR(pVarResult
) = NULL
;
1284 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1286 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1287 ERR("Out of memory\n");
1288 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1289 V_BSTR(pVarResult
) = SysAllocString(szString
);
1292 if (ret
!= ERROR_SUCCESS
)
1293 ERR("MsiGetProperty returned %d\n", ret
);
1294 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1295 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1296 if (FAILED(hr
)) return hr
;
1297 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_BSTR
, &varg1
, puArgErr
);
1299 VariantClear(&varg0
);
1302 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1304 VariantClear(&varg0
);
1305 VariantClear(&varg1
);
1306 ERR("MsiSetProperty returned %d\n", ret
);
1307 return DISP_E_EXCEPTION
;
1310 else return DISP_E_MEMBERNOTFOUND
;
1313 case DISPID_SESSION_LANGUAGE
:
1314 if (wFlags
& DISPATCH_PROPERTYGET
) {
1315 langId
= MsiGetLanguage(This
->msiHandle
);
1316 V_VT(pVarResult
) = VT_I4
;
1317 V_I4(pVarResult
) = langId
;
1319 else return DISP_E_MEMBERNOTFOUND
;
1322 case DISPID_SESSION_MODE
:
1323 if (wFlags
& DISPATCH_PROPERTYGET
) {
1324 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1325 if (FAILED(hr
)) return hr
;
1326 V_VT(pVarResult
) = VT_BOOL
;
1327 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
));
1328 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1329 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1330 if (FAILED(hr
)) return hr
;
1331 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_BOOL
, &varg1
, puArgErr
);
1332 if (FAILED(hr
)) return hr
;
1333 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1335 ERR("MsiSetMode returned %d\n", ret
);
1336 return DISP_E_EXCEPTION
;
1339 else return DISP_E_MEMBERNOTFOUND
;
1342 case DISPID_SESSION_DATABASE
:
1343 if (wFlags
& DISPATCH_PROPERTYGET
) {
1344 V_VT(pVarResult
) = VT_DISPATCH
;
1345 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1347 if (SUCCEEDED(hr
= create_automation_object(msiHandle
, NULL
, (LPVOID
*)&pDispatch
, &DIID_Database
, DatabaseImpl_Invoke
, NULL
, 0)))
1348 V_DISPATCH(pVarResult
) = pDispatch
;
1350 ERR("Failed to create Database object, hresult 0x%08x\n", hr
);
1354 ERR("MsiGetActiveDatabase failed\n");
1355 return DISP_E_EXCEPTION
;
1358 else return DISP_E_MEMBERNOTFOUND
;
1361 case DISPID_SESSION_DOACTION
:
1362 if (wFlags
& DISPATCH_METHOD
) {
1363 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1364 if (FAILED(hr
)) return hr
;
1365 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1366 V_VT(pVarResult
) = VT_I4
;
1369 case ERROR_FUNCTION_NOT_CALLED
:
1370 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1373 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1375 case ERROR_INSTALL_USEREXIT
:
1376 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1378 case ERROR_INSTALL_FAILURE
:
1379 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1381 case ERROR_INSTALL_SUSPEND
:
1382 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1384 case ERROR_MORE_DATA
:
1385 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1387 case ERROR_INVALID_HANDLE_STATE
:
1388 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1390 case ERROR_INVALID_DATA
:
1391 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1394 VariantClear(&varg0
);
1395 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1396 return DISP_E_EXCEPTION
;
1399 else return DISP_E_MEMBERNOTFOUND
;
1402 case DISPID_SESSION_EVALUATECONDITION
:
1403 if (wFlags
& DISPATCH_METHOD
) {
1404 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1405 if (FAILED(hr
)) return hr
;
1406 V_VT(pVarResult
) = VT_I4
;
1407 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1409 else return DISP_E_MEMBERNOTFOUND
;
1412 case DISPID_SESSION_MESSAGE
:
1413 if(!(wFlags
& DISPATCH_METHOD
))
1414 return DISP_E_MEMBERNOTFOUND
;
1416 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1417 if (FAILED(hr
)) return hr
;
1418 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1419 if (FAILED(hr
)) return hr
;
1421 V_VT(pVarResult
) = VT_I4
;
1423 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1426 case DISPID_SESSION_SETINSTALLLEVEL
:
1427 if (wFlags
& DISPATCH_METHOD
) {
1428 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1429 if (FAILED(hr
)) return hr
;
1430 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1432 ERR("MsiSetInstallLevel returned %d\n", ret
);
1433 return DISP_E_EXCEPTION
;
1436 else return DISP_E_MEMBERNOTFOUND
;
1439 case DISPID_SESSION_FEATURECURRENTSTATE
:
1440 if (wFlags
& DISPATCH_PROPERTYGET
) {
1441 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1442 if (FAILED(hr
)) return hr
;
1443 V_VT(pVarResult
) = VT_I4
;
1444 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1445 V_I4(pVarResult
) = iInstalled
;
1448 ERR("MsiGetFeatureState returned %d\n", ret
);
1449 V_I4(pVarResult
) = msiInstallStateUnknown
;
1452 else return DISP_E_MEMBERNOTFOUND
;
1455 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1456 if (wFlags
& DISPATCH_PROPERTYGET
) {
1457 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1458 if (FAILED(hr
)) return hr
;
1459 V_VT(pVarResult
) = VT_I4
;
1460 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1461 V_I4(pVarResult
) = iAction
;
1464 ERR("MsiGetFeatureState returned %d\n", ret
);
1465 V_I4(pVarResult
) = msiInstallStateUnknown
;
1467 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1468 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1469 if (FAILED(hr
)) return hr
;
1470 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_I4
, &varg1
, puArgErr
);
1472 VariantClear(&varg0
);
1475 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1477 VariantClear(&varg0
);
1478 ERR("MsiSetFeatureState returned %d\n", ret
);
1479 return DISP_E_EXCEPTION
;
1482 else return DISP_E_MEMBERNOTFOUND
;
1486 return DISP_E_MEMBERNOTFOUND
;
1489 VariantClear(&varg1
);
1490 VariantClear(&varg0
);
1495 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1496 * registry value type. Used by Installer::RegistryValue. */
1497 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1499 static const WCHAR szREG_BINARY
[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1500 static const WCHAR szREG_
[] = { '(','R','E','G','_',']',0 };
1501 WCHAR
*szString
= (WCHAR
*)lpData
;
1502 LPWSTR szNewString
= NULL
;
1503 DWORD dwNewSize
= 0;
1508 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1509 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1510 idx
= (dwSize
/sizeof(WCHAR
))-1;
1511 while (idx
>= 0 && !szString
[idx
]) idx
--;
1512 for (; idx
>= 0; idx
--)
1513 if (!szString
[idx
]) szString
[idx
] = '\n';
1516 V_VT(pVarResult
) = VT_BSTR
;
1517 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1521 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1522 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1523 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1524 ERR("Out of memory\n");
1525 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1526 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1529 V_VT(pVarResult
) = VT_BSTR
;
1530 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1532 msi_free(szNewString
);
1536 V_VT(pVarResult
) = VT_I4
;
1537 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1541 V_VT(pVarResult
) = VT_BSTR
;
1542 V_BSTR(pVarResult
) = SysAllocString(szREG_
); /* Weird string, don't know why native returns it */
1546 V_VT(pVarResult
) = VT_BSTR
;
1547 V_BSTR(pVarResult
) = SysAllocString(szREG_BINARY
);
1551 V_VT(pVarResult
) = VT_EMPTY
;
1555 FIXME("Unhandled registry value type %d\n", dwType
);
1559 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1560 DISPPARAMS
* pDispParams
,
1561 VARIANT
* pVarResult
,
1562 EXCEPINFO
* pExcepInfo
,
1568 IDispatch
* dispatch
;
1570 if (!(wFlags
& DISPATCH_METHOD
))
1571 return DISP_E_MEMBERNOTFOUND
;
1573 VariantInit(&varg0
);
1574 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1578 V_VT(pVarResult
) = VT_DISPATCH
;
1580 hrec
= MsiCreateRecord(V_I4(&varg0
));
1582 return DISP_E_EXCEPTION
;
1584 hr
= create_automation_object(hrec
, NULL
, (LPVOID
*)&dispatch
,
1585 &DIID_Record
, RecordImpl_Invoke
, NULL
, 0);
1587 V_DISPATCH(pVarResult
) = dispatch
;
1592 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1594 DISPPARAMS
* pDispParams
,
1595 VARIANT
* pVarResult
,
1596 EXCEPINFO
* pExcepInfo
,
1602 IDispatch
* dispatch
;
1603 VARIANTARG varg0
, varg1
;
1605 if (!(wFlags
& DISPATCH_METHOD
))
1606 return DISP_E_MEMBERNOTFOUND
;
1608 if (pDispParams
->cArgs
== 0)
1609 return DISP_E_TYPEMISMATCH
;
1611 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1612 return DISP_E_TYPEMISMATCH
;
1614 VariantInit(&varg0
);
1615 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1619 VariantInit(&varg1
);
1620 if (pDispParams
->cArgs
== 2)
1622 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1628 V_VT(&varg1
) = VT_I4
;
1632 V_VT(pVarResult
) = VT_DISPATCH
;
1634 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1635 if (ret
!= ERROR_SUCCESS
)
1637 hr
= DISP_E_EXCEPTION
;
1641 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1643 V_DISPATCH(pVarResult
) = dispatch
;
1646 VariantClear(&varg0
);
1647 VariantClear(&varg1
);
1651 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1652 DISPPARAMS
* pDispParams
,
1653 VARIANT
* pVarResult
,
1654 EXCEPINFO
* pExcepInfo
,
1660 if (!(wFlags
& DISPATCH_METHOD
))
1661 return DISP_E_MEMBERNOTFOUND
;
1663 VariantInit(&varg0
);
1664 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1668 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1670 VariantInit(pVarResult
);
1672 VariantClear(&varg0
);
1676 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1677 DISPPARAMS
* pDispParams
,
1678 VARIANT
* pVarResult
,
1679 EXCEPINFO
* pExcepInfo
,
1685 IDispatch
* dispatch
;
1686 VARIANTARG varg0
, varg1
;
1688 if (!(wFlags
& DISPATCH_METHOD
))
1689 return DISP_E_MEMBERNOTFOUND
;
1691 VariantInit(&varg0
);
1692 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1696 VariantInit(&varg1
);
1697 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1701 V_VT(pVarResult
) = VT_DISPATCH
;
1703 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1704 if (ret
!= ERROR_SUCCESS
)
1706 hr
= DISP_E_EXCEPTION
;
1710 hr
= create_automation_object(hdb
, NULL
, (LPVOID
*)&dispatch
,
1711 &DIID_Database
, DatabaseImpl_Invoke
, NULL
, 0);
1713 V_DISPATCH(pVarResult
) = dispatch
;
1716 VariantClear(&varg0
);
1717 VariantClear(&varg1
);
1721 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1722 DISPPARAMS
* pDispParams
,
1723 VARIANT
* pVarResult
,
1724 EXCEPINFO
* pExcepInfo
,
1727 if (!(wFlags
& DISPATCH_METHOD
))
1728 return DISP_E_MEMBERNOTFOUND
;
1732 VariantInit(pVarResult
);
1736 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1737 DISPPARAMS
* pDispParams
,
1738 VARIANT
* pVarResult
,
1739 EXCEPINFO
* pExcepInfo
,
1746 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1747 return DISP_E_MEMBERNOTFOUND
;
1749 if (wFlags
& DISPATCH_PROPERTYPUT
)
1751 VariantInit(&varg0
);
1752 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1756 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1757 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1758 return DISP_E_EXCEPTION
;
1760 else if (wFlags
& DISPATCH_PROPERTYGET
)
1762 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1763 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1764 return DISP_E_EXCEPTION
;
1766 V_VT(pVarResult
) = VT_I4
;
1767 V_I4(pVarResult
) = ui
;
1773 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1774 DISPPARAMS
* pDispParams
,
1775 VARIANT
* pVarResult
,
1776 EXCEPINFO
* pExcepInfo
,
1779 if (!(wFlags
& DISPATCH_METHOD
))
1780 return DISP_E_MEMBERNOTFOUND
;
1784 VariantInit(pVarResult
);
1788 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1789 DISPPARAMS
* pDispParams
,
1790 VARIANT
* pVarResult
,
1791 EXCEPINFO
* pExcepInfo
,
1796 VARIANTARG varg0
, varg1
;
1798 if (!(wFlags
& DISPATCH_METHOD
))
1799 return DISP_E_MEMBERNOTFOUND
;
1801 VariantInit(&varg0
);
1802 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1806 VariantInit(&varg1
);
1807 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1811 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1812 if (ret
!= ERROR_SUCCESS
)
1814 hr
= DISP_E_EXCEPTION
;
1819 VariantClear(&varg0
);
1820 VariantClear(&varg1
);
1824 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1825 VARIANT
* pVarResult
,
1826 EXCEPINFO
* pExcepInfo
,
1830 DLLVERSIONINFO verinfo
;
1831 WCHAR version
[MAX_PATH
];
1833 static const WCHAR format
[] = {
1834 '%','d','.','%','d','.','%','d','.','%','d',0};
1836 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1837 return DISP_E_MEMBERNOTFOUND
;
1839 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1840 hr
= DllGetVersion(&verinfo
);
1844 sprintfW(version
, format
, verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1845 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1847 V_VT(pVarResult
) = VT_BSTR
;
1848 V_BSTR(pVarResult
) = SysAllocString(version
);
1852 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1853 DISPPARAMS
* pDispParams
,
1854 VARIANT
* pVarResult
,
1855 EXCEPINFO
* pExcepInfo
,
1858 if (!(wFlags
& DISPATCH_METHOD
))
1859 return DISP_E_MEMBERNOTFOUND
;
1863 VariantInit(pVarResult
);
1867 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
1868 DISPPARAMS
* pDispParams
,
1869 VARIANT
* pVarResult
,
1870 EXCEPINFO
* pExcepInfo
,
1878 LPWSTR szString
= NULL
;
1879 VARIANTARG varg0
, varg1
, varg2
;
1881 if (!(wFlags
& DISPATCH_METHOD
))
1882 return DISP_E_MEMBERNOTFOUND
;
1884 VariantInit(&varg0
);
1885 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1889 VariantInit(&varg1
);
1890 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1894 /* Save valuePos so we can save puArgErr if we are unable to do our type
1898 VariantInit(&varg2
);
1899 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
1903 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
1904 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
1906 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
1909 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
1911 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
1912 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
1914 hr
= DISP_E_BADINDEX
;
1918 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
1919 switch (V_VT(&varg2
))
1921 /* Return VT_BOOL clarifying whether registry key exists or not. */
1923 V_VT(pVarResult
) = VT_BOOL
;
1924 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
);
1927 /* Return the value of specified key if it exists. */
1929 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
1930 NULL
, NULL
, NULL
, &size
);
1931 if (ret
!= ERROR_SUCCESS
)
1933 hr
= DISP_E_BADINDEX
;
1937 szString
= msi_alloc(size
);
1944 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
1945 &type
, (LPBYTE
)szString
, &size
);
1946 if (ret
!= ERROR_SUCCESS
)
1949 hr
= DISP_E_BADINDEX
;
1953 variant_from_registry_value(pVarResult
, type
,
1954 (LPBYTE
)szString
, size
);
1958 /* Try to make it into VT_I4, can use VariantChangeType for this. */
1960 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
1963 if (hr
== DISP_E_TYPEMISMATCH
)
1964 *puArgErr
= posValue
;
1969 /* Retrieve class name or maximum value name or subkey name size. */
1971 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
1972 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1973 else if (V_I4(&varg2
) > 0)
1974 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
1975 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
1976 else /* V_I4(&varg2) < 0 */
1977 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
1978 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1980 if (ret
!= ERROR_SUCCESS
)
1983 szString
= msi_alloc(++size
* sizeof(WCHAR
));
1991 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
1992 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1993 else if (V_I4(&varg2
) > 0)
1994 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
1995 &size
, 0, 0, NULL
, NULL
);
1996 else /* V_I4(&varg2) < 0 */
1997 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
1999 if (ret
== ERROR_SUCCESS
)
2001 V_VT(pVarResult
) = VT_BSTR
;
2002 V_BSTR(pVarResult
) = SysAllocString(szString
);
2009 VariantClear(&varg0
);
2010 VariantClear(&varg1
);
2011 VariantClear(&varg2
);
2016 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2017 DISPPARAMS
* pDispParams
,
2018 VARIANT
* pVarResult
,
2019 EXCEPINFO
* pExcepInfo
,
2022 if (!(wFlags
& DISPATCH_METHOD
))
2023 return DISP_E_MEMBERNOTFOUND
;
2027 VariantInit(pVarResult
);
2031 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2032 DISPPARAMS
* pDispParams
,
2033 VARIANT
* pVarResult
,
2034 EXCEPINFO
* pExcepInfo
,
2037 if (!(wFlags
& DISPATCH_METHOD
))
2038 return DISP_E_MEMBERNOTFOUND
;
2042 VariantInit(pVarResult
);
2046 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2047 DISPPARAMS
* pDispParams
,
2048 VARIANT
* pVarResult
,
2049 EXCEPINFO
* pExcepInfo
,
2052 if (!(wFlags
& DISPATCH_METHOD
))
2053 return DISP_E_MEMBERNOTFOUND
;
2057 VariantInit(pVarResult
);
2061 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2062 DISPPARAMS
* pDispParams
,
2063 VARIANT
* pVarResult
,
2064 EXCEPINFO
* pExcepInfo
,
2067 if (!(wFlags
& DISPATCH_METHOD
))
2068 return DISP_E_MEMBERNOTFOUND
;
2072 VariantInit(pVarResult
);
2076 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2077 DISPPARAMS
* pDispParams
,
2078 VARIANT
* pVarResult
,
2079 EXCEPINFO
* pExcepInfo
,
2085 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2086 return DISP_E_MEMBERNOTFOUND
;
2088 VariantInit(&varg0
);
2089 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2093 V_VT(pVarResult
) = VT_I4
;
2094 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2096 VariantClear(&varg0
);
2100 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2101 DISPPARAMS
* pDispParams
,
2102 VARIANT
* pVarResult
,
2103 EXCEPINFO
* pExcepInfo
,
2110 VARIANTARG varg0
, varg1
;
2112 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2113 return DISP_E_MEMBERNOTFOUND
;
2115 VariantInit(&varg0
);
2116 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2120 VariantInit(&varg1
);
2121 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2125 V_VT(pVarResult
) = VT_BSTR
;
2126 V_BSTR(pVarResult
) = NULL
;
2128 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2129 if (ret
!= ERROR_SUCCESS
)
2131 hr
= DISP_E_EXCEPTION
;
2135 str
= msi_alloc(++size
* sizeof(WCHAR
));
2142 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2143 if (ret
!= ERROR_SUCCESS
)
2145 hr
= DISP_E_EXCEPTION
;
2149 V_BSTR(pVarResult
) = SysAllocString(str
);
2154 VariantClear(&varg0
);
2155 VariantClear(&varg1
);
2159 static void cleanup_products(IDispatch
* dispatch
, ULONG count
)
2162 ListData
* ldata
= private_data((AutomationObject
*)dispatch
);
2164 for (i
= 0; i
< count
- 1; i
++)
2165 VariantClear(&ldata
->pVars
[i
]);
2168 msi_free(ldata
->pVars
);
2170 IDispatch_Release(dispatch
);
2173 static HRESULT
InstallerImpl_Products(WORD wFlags
,
2174 DISPPARAMS
* pDispParams
,
2175 VARIANT
* pVarResult
,
2176 EXCEPINFO
* pExcepInfo
,
2183 IDispatch
*dispatch
;
2184 WCHAR product
[GUID_SIZE
];
2186 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2187 return DISP_E_MEMBERNOTFOUND
;
2189 /* Find number of products. */
2190 while ((ret
= MsiEnumProductsW(idx
, product
)) == ERROR_SUCCESS
)
2193 if (ret
!= ERROR_NO_MORE_ITEMS
)
2194 return DISP_E_EXCEPTION
;
2196 V_VT(pVarResult
) = VT_DISPATCH
;
2197 hr
= create_automation_object(0, NULL
, (LPVOID
*)&dispatch
,
2198 &DIID_StringList
, ListImpl_Invoke
,
2199 ListImpl_Free
, sizeof(ListData
));
2203 V_DISPATCH(pVarResult
) = dispatch
;
2205 /* Save product strings. */
2206 ldata
= private_data((AutomationObject
*)dispatch
);
2208 ldata
->pVars
= msi_alloc_zero(sizeof(VARIANT
) * idx
);
2211 IDispatch_Release(dispatch
);
2212 return E_OUTOFMEMORY
;
2215 ldata
->ulCount
= idx
;
2216 for (idx
= 0; idx
< ldata
->ulCount
; idx
++)
2218 ret
= MsiEnumProductsW(idx
, product
);
2219 if (ret
!= ERROR_SUCCESS
)
2221 cleanup_products(dispatch
, idx
- 1);
2222 return DISP_E_EXCEPTION
;
2225 VariantInit(&ldata
->pVars
[idx
]);
2226 V_VT(&ldata
->pVars
[idx
]) = VT_BSTR
;
2227 V_BSTR(&ldata
->pVars
[idx
]) = SysAllocString(product
);
2233 static HRESULT
InstallerImpl_RelatedProducts(WORD wFlags
,
2234 DISPPARAMS
* pDispParams
,
2235 VARIANT
* pVarResult
,
2236 EXCEPINFO
* pExcepInfo
,
2244 IDispatch
* dispatch
;
2245 WCHAR product
[GUID_SIZE
];
2247 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2248 return DISP_E_MEMBERNOTFOUND
;
2250 VariantInit(&varg0
);
2251 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2255 /* Find number of related products. */
2259 ret
= MsiEnumRelatedProductsW(V_BSTR(&varg0
), 0, idx
, product
);
2260 if (ret
== ERROR_SUCCESS
)
2262 } while (ret
== ERROR_SUCCESS
);
2264 if (ret
!= ERROR_NO_MORE_ITEMS
)
2266 hr
= DISP_E_EXCEPTION
;
2270 V_VT(pVarResult
) = VT_DISPATCH
;
2272 hr
= create_automation_object(0, NULL
, (LPVOID
*)&dispatch
,
2273 &DIID_StringList
, ListImpl_Invoke
,
2274 ListImpl_Free
, sizeof(ListData
));
2278 V_DISPATCH(pVarResult
) = dispatch
;
2280 /* Save product strings. */
2281 ldata
= private_data((AutomationObject
*)dispatch
);
2282 ldata
->pVars
= msi_alloc(sizeof(VARIANT
) * idx
);
2285 IDispatch_Release(dispatch
);
2290 ldata
->ulCount
= idx
;
2291 for (idx
= 0; idx
< ldata
->ulCount
; idx
++)
2293 ret
= MsiEnumRelatedProductsW(V_BSTR(&varg0
), 0, idx
, product
);
2294 if (ret
!= ERROR_SUCCESS
)
2296 cleanup_products(dispatch
, idx
- 1);
2297 hr
= DISP_E_EXCEPTION
;
2301 VariantInit(&ldata
->pVars
[idx
]);
2302 V_VT(&ldata
->pVars
[idx
]) = VT_BSTR
;
2303 V_BSTR(&ldata
->pVars
[idx
]) = SysAllocString(product
);
2309 VariantClear(&varg0
);
2313 static HRESULT
InstallerImpl_Invoke(
2314 AutomationObject
* This
,
2315 DISPID dispIdMember
,
2319 DISPPARAMS
* pDispParams
,
2320 VARIANT
* pVarResult
,
2321 EXCEPINFO
* pExcepInfo
,
2324 switch (dispIdMember
)
2326 case DISPID_INSTALLER_CREATERECORD
:
2327 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2328 pVarResult
, pExcepInfo
, puArgErr
);
2330 case DISPID_INSTALLER_OPENPACKAGE
:
2331 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2332 pVarResult
, pExcepInfo
, puArgErr
);
2334 case DISPID_INSTALLER_OPENPRODUCT
:
2335 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2336 pVarResult
, pExcepInfo
, puArgErr
);
2338 case DISPID_INSTALLER_OPENDATABASE
:
2339 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2340 pVarResult
, pExcepInfo
, puArgErr
);
2342 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2343 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2344 pVarResult
, pExcepInfo
,
2347 case DISPID_INSTALLER_UILEVEL
:
2348 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2349 pVarResult
, pExcepInfo
, puArgErr
);
2351 case DISPID_INSTALLER_ENABLELOG
:
2352 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2353 pVarResult
, pExcepInfo
, puArgErr
);
2355 case DISPID_INSTALLER_INSTALLPRODUCT
:
2356 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2357 pVarResult
, pExcepInfo
,
2360 case DISPID_INSTALLER_VERSION
:
2361 return InstallerImpl_Version(wFlags
, pVarResult
,
2362 pExcepInfo
, puArgErr
);
2364 case DISPID_INSTALLER_LASTERRORRECORD
:
2365 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2366 pVarResult
, pExcepInfo
,
2369 case DISPID_INSTALLER_REGISTRYVALUE
:
2370 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2371 pVarResult
, pExcepInfo
,
2374 case DISPID_INSTALLER_ENVIRONMENT
:
2375 return InstallerImpl_Environment(wFlags
, pDispParams
,
2376 pVarResult
, pExcepInfo
, puArgErr
);
2378 case DISPID_INSTALLER_FILEATTRIBUTES
:
2379 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2380 pVarResult
, pExcepInfo
,
2383 case DISPID_INSTALLER_FILESIZE
:
2384 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2385 pVarResult
, pExcepInfo
, puArgErr
);
2387 case DISPID_INSTALLER_FILEVERSION
:
2388 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2389 pVarResult
, pExcepInfo
, puArgErr
);
2391 case DISPID_INSTALLER_PRODUCTSTATE
:
2392 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2393 pVarResult
, pExcepInfo
, puArgErr
);
2395 case DISPID_INSTALLER_PRODUCTINFO
:
2396 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2397 pVarResult
, pExcepInfo
, puArgErr
);
2399 case DISPID_INSTALLER_PRODUCTS
:
2400 return InstallerImpl_Products(wFlags
, pDispParams
,
2401 pVarResult
, pExcepInfo
, puArgErr
);
2403 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2404 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2405 pVarResult
, pExcepInfo
,
2409 return DISP_E_MEMBERNOTFOUND
;
2413 /* Wrapper around create_automation_object to create an installer object. */
2414 HRESULT
create_msiserver(IUnknown
*pOuter
, LPVOID
*ppObj
)
2416 return create_automation_object(0, pOuter
, ppObj
, &DIID_Installer
, InstallerImpl_Invoke
, NULL
, 0);
2419 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2421 SessionObject
*session
;
2424 session
= msi_alloc(sizeof(SessionObject
));
2425 if (!session
) return E_OUTOFMEMORY
;
2427 hr
= init_automation_object(&session
->autoobj
, msiHandle
, &DIID_Session
, SessionImpl_Invoke
, NULL
);
2434 session
->installer
= installer
;
2435 *disp
= &session
->autoobj
.IDispatch_iface
;