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 static inline AutomationObject
*impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
108 return CONTAINING_RECORD(iface
, AutomationObject
, IProvideMultipleClassInfo_iface
);
111 static inline AutomationObject
*impl_from_IDispatch( IDispatch
*iface
)
113 return CONTAINING_RECORD(iface
, AutomationObject
, IDispatch_iface
);
116 /* Load type info so we don't have to process GetIDsOfNames */
117 HRESULT
load_type_info(IDispatch
*iface
, ITypeInfo
**pptinfo
, REFIID clsid
, LCID lcid
)
119 static const WCHAR msiserverW
[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
120 ITypeInfo
*ti
= NULL
;
121 ITypeLib
*lib
= NULL
;
124 TRACE("(%p)->(%s, %d)\n", iface
, debugstr_guid(clsid
), lcid
);
126 /* Load registered type library */
127 hr
= LoadRegTypeLib(&LIBID_WindowsInstaller
, 1, 0, lcid
, &lib
);
129 hr
= LoadTypeLib(msiserverW
, &lib
);
131 ERR("Could not load msiserver.tlb\n");
136 /* Get type information for object */
137 hr
= ITypeLib_GetTypeInfoOfGuid(lib
, clsid
, &ti
);
138 ITypeLib_Release(lib
);
140 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid
));
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
create_database(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
1244 AutomationObject
*database
;
1247 TRACE("(%d %p)\n", msiHandle
, dispatch
);
1249 database
= msi_alloc(sizeof(AutomationObject
));
1250 if (!database
) return E_OUTOFMEMORY
;
1252 hr
= init_automation_object(database
, msiHandle
, &DIID_Database
, DatabaseImpl_Invoke
, NULL
);
1259 *dispatch
= &database
->IDispatch_iface
;
1264 static HRESULT
SessionImpl_Invoke(
1265 AutomationObject
* This
,
1266 DISPID dispIdMember
,
1270 DISPPARAMS
* pDispParams
,
1271 VARIANT
* pVarResult
,
1272 EXCEPINFO
* pExcepInfo
,
1275 SessionObject
*session
= (SessionObject
*)This
;
1278 MSIHANDLE msiHandle
;
1281 INSTALLSTATE iInstalled
, iAction
;
1282 VARIANTARG varg0
, varg1
;
1285 VariantInit(&varg0
);
1286 VariantInit(&varg1
);
1288 switch (dispIdMember
)
1290 case DISPID_SESSION_INSTALLER
:
1291 if (wFlags
& DISPATCH_PROPERTYGET
) {
1292 V_VT(pVarResult
) = VT_DISPATCH
;
1293 IDispatch_AddRef(session
->installer
);
1294 V_DISPATCH(pVarResult
) = session
->installer
;
1296 else return DISP_E_MEMBERNOTFOUND
;
1299 case DISPID_SESSION_PROPERTY
:
1300 if (wFlags
& DISPATCH_PROPERTYGET
) {
1301 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1302 if (FAILED(hr
)) return hr
;
1303 V_VT(pVarResult
) = VT_BSTR
;
1304 V_BSTR(pVarResult
) = NULL
;
1305 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1307 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1308 ERR("Out of memory\n");
1309 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1310 V_BSTR(pVarResult
) = SysAllocString(szString
);
1313 if (ret
!= ERROR_SUCCESS
)
1314 ERR("MsiGetProperty returned %d\n", ret
);
1315 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1316 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1317 if (FAILED(hr
)) return hr
;
1318 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_BSTR
, &varg1
, puArgErr
);
1320 VariantClear(&varg0
);
1323 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1325 VariantClear(&varg0
);
1326 VariantClear(&varg1
);
1327 ERR("MsiSetProperty returned %d\n", ret
);
1328 return DISP_E_EXCEPTION
;
1331 else return DISP_E_MEMBERNOTFOUND
;
1334 case DISPID_SESSION_LANGUAGE
:
1335 if (wFlags
& DISPATCH_PROPERTYGET
) {
1336 langId
= MsiGetLanguage(This
->msiHandle
);
1337 V_VT(pVarResult
) = VT_I4
;
1338 V_I4(pVarResult
) = langId
;
1340 else return DISP_E_MEMBERNOTFOUND
;
1343 case DISPID_SESSION_MODE
:
1344 if (wFlags
& DISPATCH_PROPERTYGET
) {
1345 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1346 if (FAILED(hr
)) return hr
;
1347 V_VT(pVarResult
) = VT_BOOL
;
1348 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
));
1349 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1350 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1351 if (FAILED(hr
)) return hr
;
1352 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_BOOL
, &varg1
, puArgErr
);
1353 if (FAILED(hr
)) return hr
;
1354 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1356 ERR("MsiSetMode returned %d\n", ret
);
1357 return DISP_E_EXCEPTION
;
1360 else return DISP_E_MEMBERNOTFOUND
;
1363 case DISPID_SESSION_DATABASE
:
1364 if (wFlags
& DISPATCH_PROPERTYGET
) {
1365 V_VT(pVarResult
) = VT_DISPATCH
;
1366 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1368 IDispatch
*dispatch
;
1370 if (SUCCEEDED(hr
= create_database(msiHandle
, &dispatch
)))
1371 V_DISPATCH(pVarResult
) = dispatch
;
1373 ERR("Failed to create Database object, hresult 0x%08x\n", hr
);
1377 ERR("MsiGetActiveDatabase failed\n");
1378 return DISP_E_EXCEPTION
;
1381 else return DISP_E_MEMBERNOTFOUND
;
1384 case DISPID_SESSION_DOACTION
:
1385 if (wFlags
& DISPATCH_METHOD
) {
1386 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1387 if (FAILED(hr
)) return hr
;
1388 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1389 V_VT(pVarResult
) = VT_I4
;
1392 case ERROR_FUNCTION_NOT_CALLED
:
1393 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1396 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1398 case ERROR_INSTALL_USEREXIT
:
1399 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1401 case ERROR_INSTALL_FAILURE
:
1402 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1404 case ERROR_INSTALL_SUSPEND
:
1405 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1407 case ERROR_MORE_DATA
:
1408 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1410 case ERROR_INVALID_HANDLE_STATE
:
1411 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1413 case ERROR_INVALID_DATA
:
1414 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1417 VariantClear(&varg0
);
1418 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1419 return DISP_E_EXCEPTION
;
1422 else return DISP_E_MEMBERNOTFOUND
;
1425 case DISPID_SESSION_EVALUATECONDITION
:
1426 if (wFlags
& DISPATCH_METHOD
) {
1427 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1428 if (FAILED(hr
)) return hr
;
1429 V_VT(pVarResult
) = VT_I4
;
1430 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1432 else return DISP_E_MEMBERNOTFOUND
;
1435 case DISPID_SESSION_MESSAGE
:
1436 if(!(wFlags
& DISPATCH_METHOD
))
1437 return DISP_E_MEMBERNOTFOUND
;
1439 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1440 if (FAILED(hr
)) return hr
;
1441 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1442 if (FAILED(hr
)) return hr
;
1444 V_VT(pVarResult
) = VT_I4
;
1446 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1449 case DISPID_SESSION_SETINSTALLLEVEL
:
1450 if (wFlags
& DISPATCH_METHOD
) {
1451 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1452 if (FAILED(hr
)) return hr
;
1453 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1455 ERR("MsiSetInstallLevel returned %d\n", ret
);
1456 return DISP_E_EXCEPTION
;
1459 else return DISP_E_MEMBERNOTFOUND
;
1462 case DISPID_SESSION_FEATURECURRENTSTATE
:
1463 if (wFlags
& DISPATCH_PROPERTYGET
) {
1464 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1465 if (FAILED(hr
)) return hr
;
1466 V_VT(pVarResult
) = VT_I4
;
1467 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1468 V_I4(pVarResult
) = iInstalled
;
1471 ERR("MsiGetFeatureState returned %d\n", ret
);
1472 V_I4(pVarResult
) = msiInstallStateUnknown
;
1475 else return DISP_E_MEMBERNOTFOUND
;
1478 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1479 if (wFlags
& DISPATCH_PROPERTYGET
) {
1480 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1481 if (FAILED(hr
)) return hr
;
1482 V_VT(pVarResult
) = VT_I4
;
1483 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1484 V_I4(pVarResult
) = iAction
;
1487 ERR("MsiGetFeatureState returned %d\n", ret
);
1488 V_I4(pVarResult
) = msiInstallStateUnknown
;
1490 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1491 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1492 if (FAILED(hr
)) return hr
;
1493 hr
= DispGetParam(pDispParams
, DISPID_PROPERTYPUT
, VT_I4
, &varg1
, puArgErr
);
1495 VariantClear(&varg0
);
1498 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1500 VariantClear(&varg0
);
1501 ERR("MsiSetFeatureState returned %d\n", ret
);
1502 return DISP_E_EXCEPTION
;
1505 else return DISP_E_MEMBERNOTFOUND
;
1509 return DISP_E_MEMBERNOTFOUND
;
1512 VariantClear(&varg1
);
1513 VariantClear(&varg0
);
1518 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1519 * registry value type. Used by Installer::RegistryValue. */
1520 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1522 static const WCHAR szREG_BINARY
[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1523 static const WCHAR szREG_
[] = { '(','R','E','G','_',']',0 };
1524 WCHAR
*szString
= (WCHAR
*)lpData
;
1525 LPWSTR szNewString
= NULL
;
1526 DWORD dwNewSize
= 0;
1531 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1532 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1533 idx
= (dwSize
/sizeof(WCHAR
))-1;
1534 while (idx
>= 0 && !szString
[idx
]) idx
--;
1535 for (; idx
>= 0; idx
--)
1536 if (!szString
[idx
]) szString
[idx
] = '\n';
1539 V_VT(pVarResult
) = VT_BSTR
;
1540 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1544 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1545 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1546 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1547 ERR("Out of memory\n");
1548 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1549 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1552 V_VT(pVarResult
) = VT_BSTR
;
1553 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1555 msi_free(szNewString
);
1559 V_VT(pVarResult
) = VT_I4
;
1560 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1564 V_VT(pVarResult
) = VT_BSTR
;
1565 V_BSTR(pVarResult
) = SysAllocString(szREG_
); /* Weird string, don't know why native returns it */
1569 V_VT(pVarResult
) = VT_BSTR
;
1570 V_BSTR(pVarResult
) = SysAllocString(szREG_BINARY
);
1574 V_VT(pVarResult
) = VT_EMPTY
;
1578 FIXME("Unhandled registry value type %d\n", dwType
);
1582 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1583 DISPPARAMS
* pDispParams
,
1584 VARIANT
* pVarResult
,
1585 EXCEPINFO
* pExcepInfo
,
1591 IDispatch
* dispatch
;
1593 if (!(wFlags
& DISPATCH_METHOD
))
1594 return DISP_E_MEMBERNOTFOUND
;
1596 VariantInit(&varg0
);
1597 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1601 V_VT(pVarResult
) = VT_DISPATCH
;
1603 hrec
= MsiCreateRecord(V_I4(&varg0
));
1605 return DISP_E_EXCEPTION
;
1607 hr
= create_automation_object(hrec
, NULL
, (LPVOID
*)&dispatch
,
1608 &DIID_Record
, RecordImpl_Invoke
, NULL
, 0);
1610 V_DISPATCH(pVarResult
) = dispatch
;
1615 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1617 DISPPARAMS
* pDispParams
,
1618 VARIANT
* pVarResult
,
1619 EXCEPINFO
* pExcepInfo
,
1625 IDispatch
* dispatch
;
1626 VARIANTARG varg0
, varg1
;
1628 if (!(wFlags
& DISPATCH_METHOD
))
1629 return DISP_E_MEMBERNOTFOUND
;
1631 if (pDispParams
->cArgs
== 0)
1632 return DISP_E_TYPEMISMATCH
;
1634 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1635 return DISP_E_TYPEMISMATCH
;
1637 VariantInit(&varg0
);
1638 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1642 VariantInit(&varg1
);
1643 if (pDispParams
->cArgs
== 2)
1645 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1651 V_VT(&varg1
) = VT_I4
;
1655 V_VT(pVarResult
) = VT_DISPATCH
;
1657 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1658 if (ret
!= ERROR_SUCCESS
)
1660 hr
= DISP_E_EXCEPTION
;
1664 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1666 V_DISPATCH(pVarResult
) = dispatch
;
1669 VariantClear(&varg0
);
1670 VariantClear(&varg1
);
1674 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1675 DISPPARAMS
* pDispParams
,
1676 VARIANT
* pVarResult
,
1677 EXCEPINFO
* pExcepInfo
,
1683 if (!(wFlags
& DISPATCH_METHOD
))
1684 return DISP_E_MEMBERNOTFOUND
;
1686 VariantInit(&varg0
);
1687 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1691 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1693 VariantInit(pVarResult
);
1695 VariantClear(&varg0
);
1699 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1700 DISPPARAMS
* pDispParams
,
1701 VARIANT
* pVarResult
,
1702 EXCEPINFO
* pExcepInfo
,
1708 IDispatch
* dispatch
;
1709 VARIANTARG varg0
, varg1
;
1711 if (!(wFlags
& DISPATCH_METHOD
))
1712 return DISP_E_MEMBERNOTFOUND
;
1714 VariantInit(&varg0
);
1715 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1719 VariantInit(&varg1
);
1720 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1724 V_VT(pVarResult
) = VT_DISPATCH
;
1726 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1727 if (ret
!= ERROR_SUCCESS
)
1729 hr
= DISP_E_EXCEPTION
;
1733 hr
= create_database(hdb
, &dispatch
);
1735 V_DISPATCH(pVarResult
) = dispatch
;
1738 VariantClear(&varg0
);
1739 VariantClear(&varg1
);
1743 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1744 DISPPARAMS
* pDispParams
,
1745 VARIANT
* pVarResult
,
1746 EXCEPINFO
* pExcepInfo
,
1749 if (!(wFlags
& DISPATCH_METHOD
))
1750 return DISP_E_MEMBERNOTFOUND
;
1754 VariantInit(pVarResult
);
1758 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1759 DISPPARAMS
* pDispParams
,
1760 VARIANT
* pVarResult
,
1761 EXCEPINFO
* pExcepInfo
,
1768 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1769 return DISP_E_MEMBERNOTFOUND
;
1771 if (wFlags
& DISPATCH_PROPERTYPUT
)
1773 VariantInit(&varg0
);
1774 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1778 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1779 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1780 return DISP_E_EXCEPTION
;
1782 else if (wFlags
& DISPATCH_PROPERTYGET
)
1784 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1785 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1786 return DISP_E_EXCEPTION
;
1788 V_VT(pVarResult
) = VT_I4
;
1789 V_I4(pVarResult
) = ui
;
1795 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1796 DISPPARAMS
* pDispParams
,
1797 VARIANT
* pVarResult
,
1798 EXCEPINFO
* pExcepInfo
,
1801 if (!(wFlags
& DISPATCH_METHOD
))
1802 return DISP_E_MEMBERNOTFOUND
;
1806 VariantInit(pVarResult
);
1810 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1811 DISPPARAMS
* pDispParams
,
1812 VARIANT
* pVarResult
,
1813 EXCEPINFO
* pExcepInfo
,
1818 VARIANTARG varg0
, varg1
;
1820 if (!(wFlags
& DISPATCH_METHOD
))
1821 return DISP_E_MEMBERNOTFOUND
;
1823 VariantInit(&varg0
);
1824 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1828 VariantInit(&varg1
);
1829 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1833 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1834 if (ret
!= ERROR_SUCCESS
)
1836 hr
= DISP_E_EXCEPTION
;
1841 VariantClear(&varg0
);
1842 VariantClear(&varg1
);
1846 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1847 VARIANT
* pVarResult
,
1848 EXCEPINFO
* pExcepInfo
,
1852 DLLVERSIONINFO verinfo
;
1853 WCHAR version
[MAX_PATH
];
1855 static const WCHAR format
[] = {
1856 '%','d','.','%','d','.','%','d','.','%','d',0};
1858 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1859 return DISP_E_MEMBERNOTFOUND
;
1861 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1862 hr
= DllGetVersion(&verinfo
);
1866 sprintfW(version
, format
, verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1867 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1869 V_VT(pVarResult
) = VT_BSTR
;
1870 V_BSTR(pVarResult
) = SysAllocString(version
);
1874 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1875 DISPPARAMS
* pDispParams
,
1876 VARIANT
* pVarResult
,
1877 EXCEPINFO
* pExcepInfo
,
1880 if (!(wFlags
& DISPATCH_METHOD
))
1881 return DISP_E_MEMBERNOTFOUND
;
1885 VariantInit(pVarResult
);
1889 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
1890 DISPPARAMS
* pDispParams
,
1891 VARIANT
* pVarResult
,
1892 EXCEPINFO
* pExcepInfo
,
1900 LPWSTR szString
= NULL
;
1901 VARIANTARG varg0
, varg1
, varg2
;
1903 if (!(wFlags
& DISPATCH_METHOD
))
1904 return DISP_E_MEMBERNOTFOUND
;
1906 VariantInit(&varg0
);
1907 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1911 VariantInit(&varg1
);
1912 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1916 /* Save valuePos so we can save puArgErr if we are unable to do our type
1920 VariantInit(&varg2
);
1921 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
1925 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
1926 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
1928 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
1931 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
1933 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
1934 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
1936 hr
= DISP_E_BADINDEX
;
1940 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
1941 switch (V_VT(&varg2
))
1943 /* Return VT_BOOL clarifying whether registry key exists or not. */
1945 V_VT(pVarResult
) = VT_BOOL
;
1946 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
);
1949 /* Return the value of specified key if it exists. */
1951 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
1952 NULL
, NULL
, NULL
, &size
);
1953 if (ret
!= ERROR_SUCCESS
)
1955 hr
= DISP_E_BADINDEX
;
1959 szString
= msi_alloc(size
);
1966 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
1967 &type
, (LPBYTE
)szString
, &size
);
1968 if (ret
!= ERROR_SUCCESS
)
1971 hr
= DISP_E_BADINDEX
;
1975 variant_from_registry_value(pVarResult
, type
,
1976 (LPBYTE
)szString
, size
);
1980 /* Try to make it into VT_I4, can use VariantChangeType for this. */
1982 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
1985 if (hr
== DISP_E_TYPEMISMATCH
)
1986 *puArgErr
= posValue
;
1991 /* Retrieve class name or maximum value name or subkey name size. */
1993 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
1994 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1995 else if (V_I4(&varg2
) > 0)
1996 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
1997 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
1998 else /* V_I4(&varg2) < 0 */
1999 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
2000 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2002 if (ret
!= ERROR_SUCCESS
)
2005 szString
= msi_alloc(++size
* sizeof(WCHAR
));
2013 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
2014 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2015 else if (V_I4(&varg2
) > 0)
2016 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
2017 &size
, 0, 0, NULL
, NULL
);
2018 else /* V_I4(&varg2) < 0 */
2019 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
2021 if (ret
== ERROR_SUCCESS
)
2023 V_VT(pVarResult
) = VT_BSTR
;
2024 V_BSTR(pVarResult
) = SysAllocString(szString
);
2031 VariantClear(&varg0
);
2032 VariantClear(&varg1
);
2033 VariantClear(&varg2
);
2038 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2039 DISPPARAMS
* pDispParams
,
2040 VARIANT
* pVarResult
,
2041 EXCEPINFO
* pExcepInfo
,
2044 if (!(wFlags
& DISPATCH_METHOD
))
2045 return DISP_E_MEMBERNOTFOUND
;
2049 VariantInit(pVarResult
);
2053 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2054 DISPPARAMS
* pDispParams
,
2055 VARIANT
* pVarResult
,
2056 EXCEPINFO
* pExcepInfo
,
2059 if (!(wFlags
& DISPATCH_METHOD
))
2060 return DISP_E_MEMBERNOTFOUND
;
2064 VariantInit(pVarResult
);
2068 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2069 DISPPARAMS
* pDispParams
,
2070 VARIANT
* pVarResult
,
2071 EXCEPINFO
* pExcepInfo
,
2074 if (!(wFlags
& DISPATCH_METHOD
))
2075 return DISP_E_MEMBERNOTFOUND
;
2079 VariantInit(pVarResult
);
2083 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2084 DISPPARAMS
* pDispParams
,
2085 VARIANT
* pVarResult
,
2086 EXCEPINFO
* pExcepInfo
,
2089 if (!(wFlags
& DISPATCH_METHOD
))
2090 return DISP_E_MEMBERNOTFOUND
;
2094 VariantInit(pVarResult
);
2098 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2099 DISPPARAMS
* pDispParams
,
2100 VARIANT
* pVarResult
,
2101 EXCEPINFO
* pExcepInfo
,
2107 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2108 return DISP_E_MEMBERNOTFOUND
;
2110 VariantInit(&varg0
);
2111 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2115 V_VT(pVarResult
) = VT_I4
;
2116 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2118 VariantClear(&varg0
);
2122 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2123 DISPPARAMS
* pDispParams
,
2124 VARIANT
* pVarResult
,
2125 EXCEPINFO
* pExcepInfo
,
2132 VARIANTARG varg0
, varg1
;
2134 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2135 return DISP_E_MEMBERNOTFOUND
;
2137 VariantInit(&varg0
);
2138 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2142 VariantInit(&varg1
);
2143 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2147 V_VT(pVarResult
) = VT_BSTR
;
2148 V_BSTR(pVarResult
) = NULL
;
2150 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2151 if (ret
!= ERROR_SUCCESS
)
2153 hr
= DISP_E_EXCEPTION
;
2157 str
= msi_alloc(++size
* sizeof(WCHAR
));
2164 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2165 if (ret
!= ERROR_SUCCESS
)
2167 hr
= DISP_E_EXCEPTION
;
2171 V_BSTR(pVarResult
) = SysAllocString(str
);
2176 VariantClear(&varg0
);
2177 VariantClear(&varg1
);
2181 static void cleanup_products(IDispatch
* dispatch
, ULONG count
)
2184 ListData
* ldata
= private_data((AutomationObject
*)dispatch
);
2186 for (i
= 0; i
< count
- 1; i
++)
2187 VariantClear(&ldata
->pVars
[i
]);
2190 msi_free(ldata
->pVars
);
2192 IDispatch_Release(dispatch
);
2195 static HRESULT
InstallerImpl_Products(WORD wFlags
,
2196 DISPPARAMS
* pDispParams
,
2197 VARIANT
* pVarResult
,
2198 EXCEPINFO
* pExcepInfo
,
2205 IDispatch
*dispatch
;
2206 WCHAR product
[GUID_SIZE
];
2208 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2209 return DISP_E_MEMBERNOTFOUND
;
2211 /* Find number of products. */
2212 while ((ret
= MsiEnumProductsW(idx
, product
)) == ERROR_SUCCESS
)
2215 if (ret
!= ERROR_NO_MORE_ITEMS
)
2216 return DISP_E_EXCEPTION
;
2218 V_VT(pVarResult
) = VT_DISPATCH
;
2219 hr
= create_automation_object(0, NULL
, (LPVOID
*)&dispatch
,
2220 &DIID_StringList
, ListImpl_Invoke
,
2221 ListImpl_Free
, sizeof(ListData
));
2225 V_DISPATCH(pVarResult
) = dispatch
;
2227 /* Save product strings. */
2228 ldata
= private_data((AutomationObject
*)dispatch
);
2230 ldata
->pVars
= msi_alloc_zero(sizeof(VARIANT
) * idx
);
2233 IDispatch_Release(dispatch
);
2234 return E_OUTOFMEMORY
;
2237 ldata
->ulCount
= idx
;
2238 for (idx
= 0; idx
< ldata
->ulCount
; idx
++)
2240 ret
= MsiEnumProductsW(idx
, product
);
2241 if (ret
!= ERROR_SUCCESS
)
2243 cleanup_products(dispatch
, idx
- 1);
2244 return DISP_E_EXCEPTION
;
2247 VariantInit(&ldata
->pVars
[idx
]);
2248 V_VT(&ldata
->pVars
[idx
]) = VT_BSTR
;
2249 V_BSTR(&ldata
->pVars
[idx
]) = SysAllocString(product
);
2255 static HRESULT
InstallerImpl_RelatedProducts(WORD wFlags
,
2256 DISPPARAMS
* pDispParams
,
2257 VARIANT
* pVarResult
,
2258 EXCEPINFO
* pExcepInfo
,
2266 IDispatch
* dispatch
;
2267 WCHAR product
[GUID_SIZE
];
2269 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2270 return DISP_E_MEMBERNOTFOUND
;
2272 VariantInit(&varg0
);
2273 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2277 /* Find number of related products. */
2281 ret
= MsiEnumRelatedProductsW(V_BSTR(&varg0
), 0, idx
, product
);
2282 if (ret
== ERROR_SUCCESS
)
2284 } while (ret
== ERROR_SUCCESS
);
2286 if (ret
!= ERROR_NO_MORE_ITEMS
)
2288 hr
= DISP_E_EXCEPTION
;
2292 V_VT(pVarResult
) = VT_DISPATCH
;
2294 hr
= create_automation_object(0, NULL
, (LPVOID
*)&dispatch
,
2295 &DIID_StringList
, ListImpl_Invoke
,
2296 ListImpl_Free
, sizeof(ListData
));
2300 V_DISPATCH(pVarResult
) = dispatch
;
2302 /* Save product strings. */
2303 ldata
= private_data((AutomationObject
*)dispatch
);
2304 ldata
->pVars
= msi_alloc(sizeof(VARIANT
) * idx
);
2307 IDispatch_Release(dispatch
);
2312 ldata
->ulCount
= idx
;
2313 for (idx
= 0; idx
< ldata
->ulCount
; idx
++)
2315 ret
= MsiEnumRelatedProductsW(V_BSTR(&varg0
), 0, idx
, product
);
2316 if (ret
!= ERROR_SUCCESS
)
2318 cleanup_products(dispatch
, idx
- 1);
2319 hr
= DISP_E_EXCEPTION
;
2323 VariantInit(&ldata
->pVars
[idx
]);
2324 V_VT(&ldata
->pVars
[idx
]) = VT_BSTR
;
2325 V_BSTR(&ldata
->pVars
[idx
]) = SysAllocString(product
);
2331 VariantClear(&varg0
);
2335 static HRESULT
InstallerImpl_Invoke(
2336 AutomationObject
* This
,
2337 DISPID dispIdMember
,
2341 DISPPARAMS
* pDispParams
,
2342 VARIANT
* pVarResult
,
2343 EXCEPINFO
* pExcepInfo
,
2346 switch (dispIdMember
)
2348 case DISPID_INSTALLER_CREATERECORD
:
2349 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2350 pVarResult
, pExcepInfo
, puArgErr
);
2352 case DISPID_INSTALLER_OPENPACKAGE
:
2353 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2354 pVarResult
, pExcepInfo
, puArgErr
);
2356 case DISPID_INSTALLER_OPENPRODUCT
:
2357 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2358 pVarResult
, pExcepInfo
, puArgErr
);
2360 case DISPID_INSTALLER_OPENDATABASE
:
2361 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2362 pVarResult
, pExcepInfo
, puArgErr
);
2364 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2365 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2366 pVarResult
, pExcepInfo
,
2369 case DISPID_INSTALLER_UILEVEL
:
2370 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2371 pVarResult
, pExcepInfo
, puArgErr
);
2373 case DISPID_INSTALLER_ENABLELOG
:
2374 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2375 pVarResult
, pExcepInfo
, puArgErr
);
2377 case DISPID_INSTALLER_INSTALLPRODUCT
:
2378 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2379 pVarResult
, pExcepInfo
,
2382 case DISPID_INSTALLER_VERSION
:
2383 return InstallerImpl_Version(wFlags
, pVarResult
,
2384 pExcepInfo
, puArgErr
);
2386 case DISPID_INSTALLER_LASTERRORRECORD
:
2387 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2388 pVarResult
, pExcepInfo
,
2391 case DISPID_INSTALLER_REGISTRYVALUE
:
2392 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2393 pVarResult
, pExcepInfo
,
2396 case DISPID_INSTALLER_ENVIRONMENT
:
2397 return InstallerImpl_Environment(wFlags
, pDispParams
,
2398 pVarResult
, pExcepInfo
, puArgErr
);
2400 case DISPID_INSTALLER_FILEATTRIBUTES
:
2401 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2402 pVarResult
, pExcepInfo
,
2405 case DISPID_INSTALLER_FILESIZE
:
2406 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2407 pVarResult
, pExcepInfo
, puArgErr
);
2409 case DISPID_INSTALLER_FILEVERSION
:
2410 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2411 pVarResult
, pExcepInfo
, puArgErr
);
2413 case DISPID_INSTALLER_PRODUCTSTATE
:
2414 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2415 pVarResult
, pExcepInfo
, puArgErr
);
2417 case DISPID_INSTALLER_PRODUCTINFO
:
2418 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2419 pVarResult
, pExcepInfo
, puArgErr
);
2421 case DISPID_INSTALLER_PRODUCTS
:
2422 return InstallerImpl_Products(wFlags
, pDispParams
,
2423 pVarResult
, pExcepInfo
, puArgErr
);
2425 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2426 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2427 pVarResult
, pExcepInfo
,
2431 return DISP_E_MEMBERNOTFOUND
;
2435 HRESULT
create_msiserver(IUnknown
*outer
, void **ppObj
)
2437 AutomationObject
*installer
;
2440 TRACE("(%p %p)\n", outer
, ppObj
);
2443 return CLASS_E_NOAGGREGATION
;
2445 installer
= msi_alloc(sizeof(AutomationObject
));
2446 if (!installer
) return E_OUTOFMEMORY
;
2448 hr
= init_automation_object(installer
, 0, &DIID_Installer
, InstallerImpl_Invoke
, NULL
);
2451 msi_free(installer
);
2455 *ppObj
= &installer
->IDispatch_iface
;
2460 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2462 SessionObject
*session
;
2465 session
= msi_alloc(sizeof(SessionObject
));
2466 if (!session
) return E_OUTOFMEMORY
;
2468 hr
= init_automation_object(&session
->autoobj
, msiHandle
, &DIID_Session
, SessionImpl_Invoke
, NULL
);
2475 session
->installer
= installer
;
2476 *disp
= &session
->autoobj
.IDispatch_iface
;