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
45 typedef struct AutomationObject AutomationObject
;
47 /* function that is called from AutomationObject::Invoke, specific to this type of object */
48 typedef HRESULT (*auto_invoke_func
)(AutomationObject
* This
,
49 DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD flags
, DISPPARAMS
* pDispParams
,
50 VARIANT
* result
, EXCEPINFO
* ei
, UINT
* arg_err
);
51 /* function that is called from AutomationObject::Release when the object is being freed
52 to free any private data structures (or NULL) */
53 typedef void (*auto_free_func
)(AutomationObject
* This
);
57 auto_invoke_func fn_invoke
;
58 auto_free_func fn_free
;
62 static HRESULT
database_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
63 static HRESULT
installer_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
64 static HRESULT
record_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
65 static HRESULT
session_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
66 static HRESULT
list_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
67 static void list_free(AutomationObject
*);
68 static HRESULT
summaryinfo_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
69 static HRESULT
view_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
71 static tid_id_t tid_ids
[] = {
72 { &DIID_Database
, database_invoke
},
73 { &DIID_Installer
, installer_invoke
},
74 { &DIID_Record
, record_invoke
},
75 { &DIID_Session
, session_invoke
},
76 { &DIID_StringList
, list_invoke
, list_free
},
77 { &DIID_SummaryInfo
, summaryinfo_invoke
},
78 { &DIID_View
, view_invoke
}
81 static ITypeLib
*typelib
;
82 static ITypeInfo
*typeinfos
[LAST_tid
];
84 static const IID
*get_riid_from_tid(tid_t tid
)
86 return tid_ids
[tid
].riid
;
89 HRESULT
get_typeinfo(tid_t tid
, ITypeInfo
**typeinfo
)
97 hr
= LoadRegTypeLib(&LIBID_WindowsInstaller
, 1, 0, LOCALE_NEUTRAL
, &lib
);
99 static const WCHAR msiserverW
[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
100 hr
= LoadTypeLib(msiserverW
, &lib
);
102 ERR("Could not load msiserver.tlb\n");
107 if (InterlockedCompareExchangePointer((void**)&typelib
, lib
, NULL
))
108 ITypeLib_Release(lib
);
115 hr
= ITypeLib_GetTypeInfoOfGuid(typelib
, get_riid_from_tid(tid
), &ti
);
117 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid
)));
121 if(InterlockedCompareExchangePointer((void**)(typeinfos
+tid
), ti
, NULL
))
122 ITypeInfo_Release(ti
);
125 *typeinfo
= typeinfos
[tid
];
129 void release_typelib(void)
133 for (i
= 0; i
< sizeof(typeinfos
)/sizeof(*typeinfos
); i
++)
135 ITypeInfo_Release(typeinfos
[i
]);
138 ITypeLib_Release(typelib
);
142 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
143 * called from AutomationObject::Invoke.
145 struct AutomationObject
{
146 IDispatch IDispatch_iface
;
147 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface
;
150 /* type id for this class */
153 /* The MSI handle of the current object */
158 AutomationObject autoobj
;
163 static HRESULT
create_database(MSIHANDLE
, IDispatch
**);
164 static HRESULT
create_list_enumerator(ListObject
*, void**);
165 static HRESULT
create_summaryinfo(MSIHANDLE
, IDispatch
**);
166 static HRESULT
create_view(MSIHANDLE
, IDispatch
**);
168 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
170 IEnumVARIANT IEnumVARIANT_iface
;
173 /* Current position and pointer to AutomationObject that stores actual data */
179 AutomationObject autoobj
;
180 IDispatch
*installer
;
183 static inline AutomationObject
*impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
185 return CONTAINING_RECORD(iface
, AutomationObject
, IProvideMultipleClassInfo_iface
);
188 static inline AutomationObject
*impl_from_IDispatch( IDispatch
*iface
)
190 return CONTAINING_RECORD(iface
, AutomationObject
, IDispatch_iface
);
193 /* AutomationObject methods */
194 static HRESULT WINAPI
AutomationObject_QueryInterface(IDispatch
* iface
, REFIID riid
, void** ppvObject
)
196 AutomationObject
*This
= impl_from_IDispatch(iface
);
198 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
200 if (ppvObject
== NULL
)
205 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
206 IsEqualGUID(riid
, &IID_IDispatch
) ||
207 IsEqualGUID(riid
, get_riid_from_tid(This
->tid
)))
208 *ppvObject
= &This
->IDispatch_iface
;
209 else if (IsEqualGUID(riid
, &IID_IProvideClassInfo
) ||
210 IsEqualGUID(riid
, &IID_IProvideClassInfo2
) ||
211 IsEqualGUID(riid
, &IID_IProvideMultipleClassInfo
))
212 *ppvObject
= &This
->IProvideMultipleClassInfo_iface
;
215 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
216 return E_NOINTERFACE
;
219 IDispatch_AddRef(iface
);
224 static ULONG WINAPI
AutomationObject_AddRef(IDispatch
* iface
)
226 AutomationObject
*This
= impl_from_IDispatch(iface
);
228 TRACE("(%p/%p)\n", iface
, This
);
230 return InterlockedIncrement(&This
->ref
);
233 static ULONG WINAPI
AutomationObject_Release(IDispatch
* iface
)
235 AutomationObject
*This
= impl_from_IDispatch(iface
);
236 ULONG ref
= InterlockedDecrement(&This
->ref
);
238 TRACE("(%p/%p)\n", iface
, This
);
242 if (tid_ids
[This
->tid
].fn_free
) tid_ids
[This
->tid
].fn_free(This
);
243 MsiCloseHandle(This
->msiHandle
);
250 static HRESULT WINAPI
AutomationObject_GetTypeInfoCount(
254 AutomationObject
*This
= impl_from_IDispatch(iface
);
256 TRACE("(%p/%p)->(%p)\n", iface
, This
, pctinfo
);
261 static HRESULT WINAPI
AutomationObject_GetTypeInfo(
267 AutomationObject
*This
= impl_from_IDispatch(iface
);
270 TRACE("(%p/%p)->(%d,%d,%p)\n", iface
, This
, iTInfo
, lcid
, ppTInfo
);
272 hr
= get_typeinfo(This
->tid
, ppTInfo
);
276 ITypeInfo_AddRef(*ppTInfo
);
280 static HRESULT WINAPI
AutomationObject_GetIDsOfNames(
288 AutomationObject
*This
= impl_from_IDispatch(iface
);
292 TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface
, This
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
294 if (!IsEqualGUID(riid
, &IID_NULL
)) return E_INVALIDARG
;
296 hr
= get_typeinfo(This
->tid
, &ti
);
300 hr
= ITypeInfo_GetIDsOfNames(ti
, rgszNames
, cNames
, rgDispId
);
301 if (hr
== DISP_E_UNKNOWNNAME
)
304 for (idx
=0; idx
<cNames
; idx
++)
306 if (rgDispId
[idx
] == DISPID_UNKNOWN
)
307 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames
[idx
]), debugstr_guid(get_riid_from_tid(This
->tid
)));
313 /* Maximum number of allowed function parameters+1 */
314 #define MAX_FUNC_PARAMS 20
316 /* Some error checking is done here to simplify individual object function invocation */
317 static HRESULT WINAPI
AutomationObject_Invoke(
323 DISPPARAMS
* pDispParams
,
325 EXCEPINFO
* pExcepInfo
,
328 AutomationObject
*This
= impl_from_IDispatch(iface
);
330 unsigned int uArgErr
;
331 VARIANT varResultDummy
;
332 BSTR bstrName
= NULL
;
335 TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface
, This
, dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
337 if (!IsEqualIID(riid
, &IID_NULL
))
339 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
340 return DISP_E_UNKNOWNNAME
;
343 if (wFlags
& DISPATCH_PROPERTYGET
&& !pVarResult
)
345 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
346 return DISP_E_PARAMNOTOPTIONAL
;
349 /* This simplifies our individual object invocation functions */
350 if (puArgErr
== NULL
) puArgErr
= &uArgErr
;
351 if (pVarResult
== NULL
) pVarResult
= &varResultDummy
;
353 hr
= get_typeinfo(This
->tid
, &ti
);
357 /* Assume return type is void unless determined otherwise */
358 VariantInit(pVarResult
);
360 /* If we are tracing, we want to see the name of the member we are invoking */
363 ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
364 TRACE("Method %d, %s\n", dispIdMember
, debugstr_w(bstrName
));
367 hr
= tid_ids
[This
->tid
].fn_invoke(This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
369 if (hr
== DISP_E_MEMBERNOTFOUND
) {
370 if (bstrName
== NULL
) ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
371 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember
, debugstr_w(bstrName
), wFlags
,
372 debugstr_guid(get_riid_from_tid(This
->tid
)));
374 else if (pExcepInfo
&&
375 (hr
== DISP_E_PARAMNOTFOUND
||
376 hr
== DISP_E_EXCEPTION
)) {
377 static const WCHAR szComma
[] = { ',',0 };
378 static const WCHAR szExceptionSource
[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
379 WCHAR szExceptionDescription
[MAX_PATH
];
380 BSTR bstrParamNames
[MAX_FUNC_PARAMS
];
384 if (FAILED(ITypeInfo_GetNames(ti
, dispIdMember
, bstrParamNames
,
385 MAX_FUNC_PARAMS
, &namesNo
)))
387 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember
);
391 memset(szExceptionDescription
, 0, sizeof(szExceptionDescription
));
392 for (i
=0; i
<namesNo
; i
++)
394 if (bFirst
) bFirst
= FALSE
;
396 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], szComma
);
398 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], bstrParamNames
[i
]);
399 SysFreeString(bstrParamNames
[i
]);
402 memset(pExcepInfo
, 0, sizeof(EXCEPINFO
));
403 pExcepInfo
->wCode
= 1000;
404 pExcepInfo
->bstrSource
= SysAllocString(szExceptionSource
);
405 pExcepInfo
->bstrDescription
= SysAllocString(szExceptionDescription
);
406 hr
= DISP_E_EXCEPTION
;
410 /* Make sure we free the return variant if it is our dummy variant */
411 if (pVarResult
== &varResultDummy
) VariantClear(pVarResult
);
413 /* Free function name if we retrieved it */
414 SysFreeString(bstrName
);
416 TRACE("Returning 0x%08x, %s\n", hr
, SUCCEEDED(hr
) ? "ok" : "not ok");
421 static const struct IDispatchVtbl AutomationObjectVtbl
=
423 AutomationObject_QueryInterface
,
424 AutomationObject_AddRef
,
425 AutomationObject_Release
,
426 AutomationObject_GetTypeInfoCount
,
427 AutomationObject_GetTypeInfo
,
428 AutomationObject_GetIDsOfNames
,
429 AutomationObject_Invoke
433 * IProvideMultipleClassInfo methods
436 static HRESULT WINAPI
ProvideMultipleClassInfo_QueryInterface(
437 IProvideMultipleClassInfo
* iface
,
441 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
442 return IDispatch_QueryInterface(&This
->IDispatch_iface
, riid
, ppvoid
);
445 static ULONG WINAPI
ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo
* iface
)
447 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
448 return IDispatch_AddRef(&This
->IDispatch_iface
);
451 static ULONG WINAPI
ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo
* iface
)
453 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
454 return IDispatch_Release(&This
->IDispatch_iface
);
457 static HRESULT WINAPI
ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo
* iface
, ITypeInfo
** ppTI
)
459 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
462 TRACE("(%p/%p)->(%p)\n", iface
, This
, ppTI
);
464 hr
= get_typeinfo(This
->tid
, ppTI
);
466 ITypeInfo_AddRef(*ppTI
);
471 static HRESULT WINAPI
ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
* iface
, DWORD dwGuidKind
, GUID
* pGUID
)
473 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
474 TRACE("(%p/%p)->(%d,%s)\n", iface
, This
, dwGuidKind
, debugstr_guid(pGUID
));
476 if (dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
479 *pGUID
= *get_riid_from_tid(This
->tid
);
484 static HRESULT WINAPI
ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo
* iface
, ULONG
* pcti
)
486 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
488 TRACE("(%p/%p)->(%p)\n", iface
, This
, pcti
);
493 static HRESULT WINAPI
ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo
* iface
,
498 ULONG
* pcdispidReserved
,
502 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
504 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface
, This
, iti
, dwFlags
, ti
, pdwTIFlags
, pcdispidReserved
, piidPrimary
, piidSource
);
509 if (dwFlags
& MULTICLASSINFO_GETTYPEINFO
)
511 HRESULT hr
= get_typeinfo(This
->tid
, ti
);
515 ITypeInfo_AddRef(*ti
);
518 if (dwFlags
& MULTICLASSINFO_GETNUMRESERVEDDISPIDS
)
521 *pcdispidReserved
= 0;
524 if (dwFlags
& MULTICLASSINFO_GETIIDPRIMARY
)
525 *piidPrimary
= *get_riid_from_tid(This
->tid
);
527 if (dwFlags
& MULTICLASSINFO_GETIIDSOURCE
)
528 *piidSource
= *get_riid_from_tid(This
->tid
);
533 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl
=
535 ProvideMultipleClassInfo_QueryInterface
,
536 ProvideMultipleClassInfo_AddRef
,
537 ProvideMultipleClassInfo_Release
,
538 ProvideMultipleClassInfo_GetClassInfo
,
539 ProvideMultipleClassInfo_GetGUID
,
540 ProvideMultipleClassInfo_GetMultiTypeInfoCount
,
541 ProvideMultipleClassInfo_GetInfoOfIndex
544 static HRESULT
init_automation_object(AutomationObject
*This
, MSIHANDLE msiHandle
, tid_t tid
)
546 TRACE("(%p, %d, %s)\n", This
, msiHandle
, debugstr_guid(get_riid_from_tid(tid
)));
548 This
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
549 This
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
552 This
->msiHandle
= msiHandle
;
559 * ListEnumerator methods
562 static inline ListEnumerator
*impl_from_IEnumVARIANT(IEnumVARIANT
* iface
)
564 return CONTAINING_RECORD(iface
, ListEnumerator
, IEnumVARIANT_iface
);
567 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
,
570 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
572 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
574 if (ppvObject
== NULL
)
579 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
580 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
582 *ppvObject
= &This
->IEnumVARIANT_iface
;
586 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
587 return E_NOINTERFACE
;
590 IEnumVARIANT_AddRef(iface
);
594 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
596 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
598 TRACE("(%p/%p)\n", iface
, This
);
600 return InterlockedIncrement(&This
->ref
);
603 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
605 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
606 ULONG ref
= InterlockedDecrement(&This
->ref
);
608 TRACE("(%p/%p)\n", iface
, This
);
612 if (This
->list
) IDispatch_Release(&This
->list
->autoobj
.IDispatch_iface
);
619 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
* rgVar
,
622 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
625 TRACE("(%p, %uld, %p, %p)\n", iface
, celt
, rgVar
, fetched
);
627 if (fetched
) *fetched
= 0;
632 for (local
= 0; local
< celt
; local
++)
633 VariantInit(&rgVar
[local
]);
635 for (i
= This
->pos
, local
= 0; i
< This
->list
->count
&& local
< celt
; i
++, local
++)
636 VariantCopy(&rgVar
[local
], &This
->list
->data
[i
]);
638 if (fetched
) *fetched
= local
;
641 return (local
< celt
) ? S_FALSE
: S_OK
;
644 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
646 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
648 TRACE("(%p,%uld)\n", iface
, celt
);
651 if (This
->pos
>= This
->list
->count
)
653 This
->pos
= This
->list
->count
;
660 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
662 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
664 TRACE("(%p)\n", iface
);
670 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
672 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
675 TRACE("(%p,%p)\n", iface
, ppEnum
);
681 hr
= create_list_enumerator(This
->list
, (LPVOID
*)ppEnum
);
684 if (*ppEnum
) IEnumVARIANT_Release(*ppEnum
);
691 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
693 ListEnumerator_QueryInterface
,
694 ListEnumerator_AddRef
,
695 ListEnumerator_Release
,
698 ListEnumerator_Reset
,
702 /* Create a list enumerator, placing the result in the pointer ppObj. */
703 static HRESULT
create_list_enumerator(ListObject
*list
, void **ppObj
)
705 ListEnumerator
*object
;
707 TRACE("(%p, %p)\n", list
, ppObj
);
709 object
= msi_alloc(sizeof(ListEnumerator
));
711 /* Set all the VTable references */
712 object
->IEnumVARIANT_iface
.lpVtbl
= &ListEnumerator_Vtbl
;
715 /* Store data that was passed */
718 if (list
) IDispatch_AddRef(&list
->autoobj
.IDispatch_iface
);
725 * Individual Object Invocation Functions
728 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
729 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
730 using DispGetParam/VariantChangeType. */
731 static HRESULT
DispGetParam_CopyOnly(
732 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
733 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
734 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
736 /* position is counted backwards */
739 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
740 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
741 if (*position
< pdispparams
->cArgs
) {
742 /* positional arg? */
743 pos
= pdispparams
->cArgs
- *position
- 1;
745 /* FIXME: is this how to handle named args? */
746 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
747 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
749 if (pos
==pdispparams
->cNamedArgs
)
750 return DISP_E_PARAMNOTFOUND
;
753 return VariantCopyInd(pvarResult
,
754 &pdispparams
->rgvarg
[pos
]);
757 static HRESULT
summaryinfo_invoke(
758 AutomationObject
* This
,
763 DISPPARAMS
* pDispParams
,
765 EXCEPINFO
* pExcepInfo
,
769 VARIANTARG varg0
, varg1
;
770 FILETIME ft
, ftlocal
;
777 switch (dispIdMember
)
779 case DISPID_SUMMARYINFO_PROPERTY
:
780 if (wFlags
& DISPATCH_PROPERTYGET
)
788 static WCHAR szEmpty
[] = {0};
790 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
791 if (FAILED(hr
)) return hr
;
792 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
793 &ft
, szEmpty
, &size
);
794 if (ret
!= ERROR_SUCCESS
&&
795 ret
!= ERROR_MORE_DATA
)
797 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
798 return DISP_E_EXCEPTION
;
808 V_VT(pVarResult
) = VT_I4
;
809 V_I4(pVarResult
) = value
;
813 if (!(str
= msi_alloc(++size
* sizeof(WCHAR
))))
814 ERR("Out of memory\n");
815 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
816 NULL
, str
, &size
)) != ERROR_SUCCESS
)
817 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
820 V_VT(pVarResult
) = VT_BSTR
;
821 V_BSTR(pVarResult
) = SysAllocString(str
);
827 FileTimeToLocalFileTime(&ft
, &ftlocal
);
828 FileTimeToSystemTime(&ftlocal
, &st
);
829 SystemTimeToVariantTime(&st
, &date
);
831 V_VT(pVarResult
) = VT_DATE
;
832 V_DATE(pVarResult
) = date
;
836 ERR("Unhandled variant type %d\n", type
);
839 else if (wFlags
& DISPATCH_PROPERTYPUT
)
841 UINT posValue
= DISPID_PROPERTYPUT
;
843 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
844 if (FAILED(hr
)) return hr
;
845 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
848 *puArgErr
= posValue
;
852 switch (V_VT(&varg1
))
856 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
860 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
861 SystemTimeToFileTime(&st
, &ftlocal
);
862 LocalFileTimeToFileTime(&ftlocal
, &ft
);
863 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
867 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
871 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
872 VariantClear(&varg1
);
873 return DISP_E_EXCEPTION
;
876 if (ret
!= ERROR_SUCCESS
)
878 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
879 return DISP_E_EXCEPTION
;
882 else return DISP_E_MEMBERNOTFOUND
;
885 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
886 if (wFlags
& DISPATCH_PROPERTYGET
) {
888 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
889 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
892 V_VT(pVarResult
) = VT_I4
;
893 V_I4(pVarResult
) = count
;
896 else return DISP_E_MEMBERNOTFOUND
;
900 return DISP_E_MEMBERNOTFOUND
;
903 VariantClear(&varg1
);
904 VariantClear(&varg0
);
909 static HRESULT
record_invoke(
910 AutomationObject
* This
,
915 DISPPARAMS
* pDispParams
,
917 EXCEPINFO
* pExcepInfo
,
923 VARIANTARG varg0
, varg1
;
929 switch (dispIdMember
)
931 case DISPID_RECORD_FIELDCOUNT
:
932 if (wFlags
& DISPATCH_PROPERTYGET
) {
933 V_VT(pVarResult
) = VT_I4
;
934 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
936 else return DISP_E_MEMBERNOTFOUND
;
939 case DISPID_RECORD_STRINGDATA
:
940 if (wFlags
& DISPATCH_PROPERTYGET
) {
941 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
942 if (FAILED(hr
)) return hr
;
943 V_VT(pVarResult
) = VT_BSTR
;
944 V_BSTR(pVarResult
) = NULL
;
945 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
947 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
948 ERR("Out of memory\n");
949 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
950 V_BSTR(pVarResult
) = SysAllocString(szString
);
953 if (ret
!= ERROR_SUCCESS
)
954 ERR("MsiRecordGetString returned %d\n", ret
);
955 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
956 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
957 if (FAILED(hr
)) return hr
;
958 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
959 if (FAILED(hr
)) return hr
;
960 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
962 VariantClear(&varg1
);
963 ERR("MsiRecordSetString returned %d\n", ret
);
964 return DISP_E_EXCEPTION
;
967 else return DISP_E_MEMBERNOTFOUND
;
970 case DISPID_RECORD_INTEGERDATA
:
971 if (wFlags
& DISPATCH_PROPERTYGET
) {
972 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
973 if (FAILED(hr
)) return hr
;
974 V_VT(pVarResult
) = VT_I4
;
975 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
976 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
977 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
978 if (FAILED(hr
)) return hr
;
979 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
980 if (FAILED(hr
)) return hr
;
981 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
983 ERR("MsiRecordSetInteger returned %d\n", ret
);
984 return DISP_E_EXCEPTION
;
987 else return DISP_E_MEMBERNOTFOUND
;
991 return DISP_E_MEMBERNOTFOUND
;
994 VariantClear(&varg1
);
995 VariantClear(&varg0
);
1000 static HRESULT
create_record(MSIHANDLE msiHandle
, IDispatch
**disp
)
1002 AutomationObject
*record
;
1005 record
= msi_alloc(sizeof(*record
));
1006 if (!record
) return E_OUTOFMEMORY
;
1008 hr
= init_automation_object(record
, msiHandle
, Record_tid
);
1015 *disp
= &record
->IDispatch_iface
;
1020 static HRESULT
list_invoke(
1021 AutomationObject
* This
,
1022 DISPID dispIdMember
,
1026 DISPPARAMS
* pDispParams
,
1027 VARIANT
* pVarResult
,
1028 EXCEPINFO
* pExcepInfo
,
1031 ListObject
*list
= (ListObject
*)This
;
1032 IUnknown
*pUnk
= NULL
;
1035 switch (dispIdMember
)
1037 case DISPID_LIST__NEWENUM
:
1038 if (wFlags
& DISPATCH_METHOD
) {
1039 V_VT(pVarResult
) = VT_UNKNOWN
;
1040 if (SUCCEEDED(hr
= create_list_enumerator(list
, (LPVOID
*)&pUnk
)))
1041 V_UNKNOWN(pVarResult
) = pUnk
;
1043 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr
);
1045 else return DISP_E_MEMBERNOTFOUND
;
1048 case DISPID_LIST_ITEM
:
1049 if (wFlags
& DISPATCH_PROPERTYGET
) {
1052 VariantInit(&index
);
1053 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &index
, puArgErr
);
1054 if (FAILED(hr
)) return hr
;
1055 if (V_I4(&index
) < 0 || V_I4(&index
) >= list
->count
)
1056 return DISP_E_BADINDEX
;
1057 VariantCopy(pVarResult
, &list
->data
[V_I4(&index
)]);
1059 else return DISP_E_MEMBERNOTFOUND
;
1062 case DISPID_LIST_COUNT
:
1063 if (wFlags
& DISPATCH_PROPERTYGET
) {
1064 V_VT(pVarResult
) = VT_I4
;
1065 V_I4(pVarResult
) = list
->count
;
1067 else return DISP_E_MEMBERNOTFOUND
;
1071 return DISP_E_MEMBERNOTFOUND
;
1077 static void list_free(AutomationObject
*This
)
1079 ListObject
*list
= (ListObject
*)This
;
1082 for (i
= 0; i
< list
->count
; i
++)
1083 VariantClear(&list
->data
[i
]);
1084 msi_free(list
->data
);
1087 static HRESULT
get_products_count(const WCHAR
*product
, int *len
)
1093 WCHAR dataW
[GUID_SIZE
];
1096 /* all or related only */
1098 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1100 ret
= MsiEnumProductsW(i
, dataW
);
1102 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1104 if (ret
!= ERROR_SUCCESS
)
1105 return DISP_E_EXCEPTION
;
1115 static HRESULT
create_list(const WCHAR
*product
, IDispatch
**dispatch
)
1121 list
= msi_alloc_zero(sizeof(ListObject
));
1122 if (!list
) return E_OUTOFMEMORY
;
1124 hr
= init_automation_object(&list
->autoobj
, 0, StringList_tid
);
1131 *dispatch
= &list
->autoobj
.IDispatch_iface
;
1133 hr
= get_products_count(product
, &list
->count
);
1136 IDispatch_Release(*dispatch
);
1140 list
->data
= msi_alloc(list
->count
*sizeof(VARIANT
));
1143 IDispatch_Release(*dispatch
);
1144 return E_OUTOFMEMORY
;
1147 for (i
= 0; i
< list
->count
; i
++)
1149 WCHAR dataW
[GUID_SIZE
];
1152 /* all or related only */
1154 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1156 ret
= MsiEnumProductsW(i
, dataW
);
1158 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1160 V_VT(&list
->data
[i
]) = VT_BSTR
;
1161 V_BSTR(&list
->data
[i
]) = SysAllocString(dataW
);
1167 static HRESULT
view_invoke(
1168 AutomationObject
* This
,
1169 DISPID dispIdMember
,
1173 DISPPARAMS
* pDispParams
,
1174 VARIANT
* pVarResult
,
1175 EXCEPINFO
* pExcepInfo
,
1178 MSIHANDLE msiHandle
;
1180 VARIANTARG varg0
, varg1
;
1183 VariantInit(&varg0
);
1184 VariantInit(&varg1
);
1186 switch (dispIdMember
)
1188 case DISPID_VIEW_EXECUTE
:
1189 if (wFlags
& DISPATCH_METHOD
)
1191 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1192 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1193 MsiViewExecute(This
->msiHandle
, ((AutomationObject
*)V_DISPATCH(&varg0
))->msiHandle
);
1195 MsiViewExecute(This
->msiHandle
, 0);
1197 else return DISP_E_MEMBERNOTFOUND
;
1200 case DISPID_VIEW_FETCH
:
1201 if (wFlags
& DISPATCH_METHOD
)
1203 V_VT(pVarResult
) = VT_DISPATCH
;
1204 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1206 if (FAILED(hr
= create_record(msiHandle
, &V_DISPATCH(pVarResult
))))
1207 ERR("Failed to create Record object, hresult 0x%08x\n", hr
);
1209 else if (ret
== ERROR_NO_MORE_ITEMS
)
1210 V_DISPATCH(pVarResult
) = NULL
;
1213 ERR("MsiViewFetch returned %d\n", ret
);
1214 return DISP_E_EXCEPTION
;
1217 else return DISP_E_MEMBERNOTFOUND
;
1220 case DISPID_VIEW_MODIFY
:
1221 if (wFlags
& DISPATCH_METHOD
)
1223 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1224 if (FAILED(hr
)) return hr
;
1225 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1226 if (FAILED(hr
)) return hr
;
1227 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1228 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1230 VariantClear(&varg1
);
1231 ERR("MsiViewModify returned %d\n", ret
);
1232 return DISP_E_EXCEPTION
;
1235 else return DISP_E_MEMBERNOTFOUND
;
1238 case DISPID_VIEW_CLOSE
:
1239 if (wFlags
& DISPATCH_METHOD
)
1241 MsiViewClose(This
->msiHandle
);
1243 else return DISP_E_MEMBERNOTFOUND
;
1247 return DISP_E_MEMBERNOTFOUND
;
1250 VariantClear(&varg1
);
1251 VariantClear(&varg0
);
1256 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1257 DISPPARAMS
* pDispParams
,
1258 VARIANT
* pVarResult
,
1259 EXCEPINFO
* pExcepInfo
,
1262 if (!(wFlags
& DISPATCH_METHOD
))
1263 return DISP_E_MEMBERNOTFOUND
;
1267 VariantInit(pVarResult
);
1271 HRESULT
database_invoke(
1272 AutomationObject
* This
,
1273 DISPID dispIdMember
,
1277 DISPPARAMS
* pDispParams
,
1278 VARIANT
* pVarResult
,
1279 EXCEPINFO
* pExcepInfo
,
1282 IDispatch
*dispatch
= NULL
;
1283 MSIHANDLE msiHandle
;
1285 VARIANTARG varg0
, varg1
;
1288 VariantInit(&varg0
);
1289 VariantInit(&varg1
);
1291 switch (dispIdMember
)
1293 case DISPID_DATABASE_SUMMARYINFORMATION
:
1294 if (wFlags
& DISPATCH_PROPERTYGET
)
1296 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1300 V_VT(pVarResult
) = VT_DISPATCH
;
1301 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1303 hr
= create_summaryinfo(msiHandle
, &dispatch
);
1305 V_DISPATCH(pVarResult
) = dispatch
;
1307 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr
);
1311 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1312 return DISP_E_EXCEPTION
;
1315 else return DISP_E_MEMBERNOTFOUND
;
1318 case DISPID_DATABASE_OPENVIEW
:
1319 if (wFlags
& DISPATCH_METHOD
)
1321 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1322 if (FAILED(hr
)) return hr
;
1323 V_VT(pVarResult
) = VT_DISPATCH
;
1324 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1326 if (SUCCEEDED(hr
= create_view(msiHandle
, &dispatch
)))
1327 V_DISPATCH(pVarResult
) = dispatch
;
1329 ERR("Failed to create View object, hresult 0x%08x\n", hr
);
1333 VariantClear(&varg0
);
1334 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1335 return DISP_E_EXCEPTION
;
1338 else return DISP_E_MEMBERNOTFOUND
;
1341 case DISPID_INSTALLER_LASTERRORRECORD
:
1342 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1343 pVarResult
, pExcepInfo
,
1347 return DISP_E_MEMBERNOTFOUND
;
1350 VariantClear(&varg1
);
1351 VariantClear(&varg0
);
1356 static HRESULT
session_invoke(
1357 AutomationObject
* This
,
1358 DISPID dispIdMember
,
1362 DISPPARAMS
* pDispParams
,
1363 VARIANT
* pVarResult
,
1364 EXCEPINFO
* pExcepInfo
,
1367 SessionObject
*session
= (SessionObject
*)This
;
1370 MSIHANDLE msiHandle
;
1373 INSTALLSTATE iInstalled
, iAction
;
1374 VARIANTARG varg0
, varg1
;
1377 VariantInit(&varg0
);
1378 VariantInit(&varg1
);
1380 switch (dispIdMember
)
1382 case DISPID_SESSION_INSTALLER
:
1383 if (wFlags
& DISPATCH_PROPERTYGET
) {
1384 V_VT(pVarResult
) = VT_DISPATCH
;
1385 IDispatch_AddRef(session
->installer
);
1386 V_DISPATCH(pVarResult
) = session
->installer
;
1388 else return DISP_E_MEMBERNOTFOUND
;
1391 case DISPID_SESSION_PROPERTY
:
1392 if (wFlags
& DISPATCH_PROPERTYGET
) {
1393 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1394 if (FAILED(hr
)) return hr
;
1395 V_VT(pVarResult
) = VT_BSTR
;
1396 V_BSTR(pVarResult
) = NULL
;
1397 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1399 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1400 ERR("Out of memory\n");
1401 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1402 V_BSTR(pVarResult
) = SysAllocString(szString
);
1405 if (ret
!= ERROR_SUCCESS
)
1406 ERR("MsiGetProperty returned %d\n", ret
);
1407 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1408 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1409 if (FAILED(hr
)) return hr
;
1410 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1412 VariantClear(&varg0
);
1415 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1417 VariantClear(&varg0
);
1418 VariantClear(&varg1
);
1419 ERR("MsiSetProperty returned %d\n", ret
);
1420 return DISP_E_EXCEPTION
;
1423 else return DISP_E_MEMBERNOTFOUND
;
1426 case DISPID_SESSION_LANGUAGE
:
1427 if (wFlags
& DISPATCH_PROPERTYGET
) {
1428 langId
= MsiGetLanguage(This
->msiHandle
);
1429 V_VT(pVarResult
) = VT_I4
;
1430 V_I4(pVarResult
) = langId
;
1432 else return DISP_E_MEMBERNOTFOUND
;
1435 case DISPID_SESSION_MODE
:
1436 if (wFlags
& DISPATCH_PROPERTYGET
) {
1437 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1438 if (FAILED(hr
)) return hr
;
1439 V_VT(pVarResult
) = VT_BOOL
;
1440 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
));
1441 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1442 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1443 if (FAILED(hr
)) return hr
;
1444 hr
= DispGetParam(pDispParams
, 1, VT_BOOL
, &varg1
, puArgErr
);
1445 if (FAILED(hr
)) return hr
;
1446 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1448 ERR("MsiSetMode returned %d\n", ret
);
1449 return DISP_E_EXCEPTION
;
1452 else return DISP_E_MEMBERNOTFOUND
;
1455 case DISPID_SESSION_DATABASE
:
1456 if (wFlags
& DISPATCH_PROPERTYGET
) {
1457 V_VT(pVarResult
) = VT_DISPATCH
;
1458 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1460 IDispatch
*dispatch
;
1462 if (SUCCEEDED(hr
= create_database(msiHandle
, &dispatch
)))
1463 V_DISPATCH(pVarResult
) = dispatch
;
1465 ERR("Failed to create Database object, hresult 0x%08x\n", hr
);
1469 ERR("MsiGetActiveDatabase failed\n");
1470 return DISP_E_EXCEPTION
;
1473 else return DISP_E_MEMBERNOTFOUND
;
1476 case DISPID_SESSION_DOACTION
:
1477 if (wFlags
& DISPATCH_METHOD
) {
1478 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1479 if (FAILED(hr
)) return hr
;
1480 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1481 V_VT(pVarResult
) = VT_I4
;
1484 case ERROR_FUNCTION_NOT_CALLED
:
1485 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1488 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1490 case ERROR_INSTALL_USEREXIT
:
1491 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1493 case ERROR_INSTALL_FAILURE
:
1494 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1496 case ERROR_INSTALL_SUSPEND
:
1497 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1499 case ERROR_MORE_DATA
:
1500 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1502 case ERROR_INVALID_HANDLE_STATE
:
1503 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1505 case ERROR_INVALID_DATA
:
1506 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1509 VariantClear(&varg0
);
1510 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1511 return DISP_E_EXCEPTION
;
1514 else return DISP_E_MEMBERNOTFOUND
;
1517 case DISPID_SESSION_EVALUATECONDITION
:
1518 if (wFlags
& DISPATCH_METHOD
) {
1519 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1520 if (FAILED(hr
)) return hr
;
1521 V_VT(pVarResult
) = VT_I4
;
1522 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1524 else return DISP_E_MEMBERNOTFOUND
;
1527 case DISPID_SESSION_MESSAGE
:
1528 if(!(wFlags
& DISPATCH_METHOD
))
1529 return DISP_E_MEMBERNOTFOUND
;
1531 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1532 if (FAILED(hr
)) return hr
;
1533 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1534 if (FAILED(hr
)) return hr
;
1536 V_VT(pVarResult
) = VT_I4
;
1538 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1541 case DISPID_SESSION_SETINSTALLLEVEL
:
1542 if (wFlags
& DISPATCH_METHOD
) {
1543 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1544 if (FAILED(hr
)) return hr
;
1545 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1547 ERR("MsiSetInstallLevel returned %d\n", ret
);
1548 return DISP_E_EXCEPTION
;
1551 else return DISP_E_MEMBERNOTFOUND
;
1554 case DISPID_SESSION_FEATURECURRENTSTATE
:
1555 if (wFlags
& DISPATCH_PROPERTYGET
) {
1556 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1557 if (FAILED(hr
)) return hr
;
1558 V_VT(pVarResult
) = VT_I4
;
1559 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1560 V_I4(pVarResult
) = iInstalled
;
1563 ERR("MsiGetFeatureState returned %d\n", ret
);
1564 V_I4(pVarResult
) = msiInstallStateUnknown
;
1567 else return DISP_E_MEMBERNOTFOUND
;
1570 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1571 if (wFlags
& DISPATCH_PROPERTYGET
) {
1572 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1573 if (FAILED(hr
)) return hr
;
1574 V_VT(pVarResult
) = VT_I4
;
1575 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1576 V_I4(pVarResult
) = iAction
;
1579 ERR("MsiGetFeatureState returned %d\n", ret
);
1580 V_I4(pVarResult
) = msiInstallStateUnknown
;
1582 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1583 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1584 if (FAILED(hr
)) return hr
;
1585 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1587 VariantClear(&varg0
);
1590 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1592 VariantClear(&varg0
);
1593 ERR("MsiSetFeatureState returned %d\n", ret
);
1594 return DISP_E_EXCEPTION
;
1597 else return DISP_E_MEMBERNOTFOUND
;
1601 return DISP_E_MEMBERNOTFOUND
;
1604 VariantClear(&varg1
);
1605 VariantClear(&varg0
);
1610 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1611 * registry value type. Used by Installer::RegistryValue. */
1612 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1614 static const WCHAR szREG_BINARY
[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1615 static const WCHAR szREG_
[] = { '(','R','E','G','_','?','?',')',0 };
1616 WCHAR
*szString
= (WCHAR
*)lpData
;
1617 LPWSTR szNewString
= NULL
;
1618 DWORD dwNewSize
= 0;
1623 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1624 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1625 idx
= (dwSize
/sizeof(WCHAR
))-1;
1626 while (idx
>= 0 && !szString
[idx
]) idx
--;
1627 for (; idx
>= 0; idx
--)
1628 if (!szString
[idx
]) szString
[idx
] = '\n';
1631 V_VT(pVarResult
) = VT_BSTR
;
1632 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1636 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1637 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1638 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1639 ERR("Out of memory\n");
1640 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1641 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1644 V_VT(pVarResult
) = VT_BSTR
;
1645 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1647 msi_free(szNewString
);
1651 V_VT(pVarResult
) = VT_I4
;
1652 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1656 V_VT(pVarResult
) = VT_BSTR
;
1657 V_BSTR(pVarResult
) = SysAllocString(szREG_
); /* Weird string, don't know why native returns it */
1661 V_VT(pVarResult
) = VT_BSTR
;
1662 V_BSTR(pVarResult
) = SysAllocString(szREG_BINARY
);
1666 V_VT(pVarResult
) = VT_EMPTY
;
1670 FIXME("Unhandled registry value type %d\n", dwType
);
1674 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1675 DISPPARAMS
* pDispParams
,
1676 VARIANT
* pVarResult
,
1677 EXCEPINFO
* pExcepInfo
,
1684 if (!(wFlags
& DISPATCH_METHOD
))
1685 return DISP_E_MEMBERNOTFOUND
;
1687 VariantInit(&varg0
);
1688 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1692 V_VT(pVarResult
) = VT_DISPATCH
;
1694 hrec
= MsiCreateRecord(V_I4(&varg0
));
1696 return DISP_E_EXCEPTION
;
1698 return create_record(hrec
, &V_DISPATCH(pVarResult
));
1701 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1703 DISPPARAMS
* pDispParams
,
1704 VARIANT
* pVarResult
,
1705 EXCEPINFO
* pExcepInfo
,
1711 IDispatch
* dispatch
;
1712 VARIANTARG varg0
, varg1
;
1714 if (!(wFlags
& DISPATCH_METHOD
))
1715 return DISP_E_MEMBERNOTFOUND
;
1717 if (pDispParams
->cArgs
== 0)
1718 return DISP_E_TYPEMISMATCH
;
1720 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1721 return DISP_E_TYPEMISMATCH
;
1723 VariantInit(&varg0
);
1724 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1728 VariantInit(&varg1
);
1729 if (pDispParams
->cArgs
== 2)
1731 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1737 V_VT(&varg1
) = VT_I4
;
1741 V_VT(pVarResult
) = VT_DISPATCH
;
1743 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1744 if (ret
!= ERROR_SUCCESS
)
1746 hr
= DISP_E_EXCEPTION
;
1750 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1752 V_DISPATCH(pVarResult
) = dispatch
;
1755 VariantClear(&varg0
);
1756 VariantClear(&varg1
);
1760 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1761 DISPPARAMS
* pDispParams
,
1762 VARIANT
* pVarResult
,
1763 EXCEPINFO
* pExcepInfo
,
1769 if (!(wFlags
& DISPATCH_METHOD
))
1770 return DISP_E_MEMBERNOTFOUND
;
1772 VariantInit(&varg0
);
1773 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1777 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1779 VariantInit(pVarResult
);
1781 VariantClear(&varg0
);
1785 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1786 DISPPARAMS
* pDispParams
,
1787 VARIANT
* pVarResult
,
1788 EXCEPINFO
* pExcepInfo
,
1794 IDispatch
* dispatch
;
1795 VARIANTARG varg0
, varg1
;
1797 if (!(wFlags
& DISPATCH_METHOD
))
1798 return DISP_E_MEMBERNOTFOUND
;
1800 VariantInit(&varg0
);
1801 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1805 VariantInit(&varg1
);
1806 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1810 V_VT(pVarResult
) = VT_DISPATCH
;
1812 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1813 if (ret
!= ERROR_SUCCESS
)
1815 hr
= DISP_E_EXCEPTION
;
1819 hr
= create_database(hdb
, &dispatch
);
1821 V_DISPATCH(pVarResult
) = dispatch
;
1824 VariantClear(&varg0
);
1825 VariantClear(&varg1
);
1829 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1830 DISPPARAMS
* pDispParams
,
1831 VARIANT
* pVarResult
,
1832 EXCEPINFO
* pExcepInfo
,
1835 if (!(wFlags
& DISPATCH_METHOD
))
1836 return DISP_E_MEMBERNOTFOUND
;
1840 VariantInit(pVarResult
);
1844 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1845 DISPPARAMS
* pDispParams
,
1846 VARIANT
* pVarResult
,
1847 EXCEPINFO
* pExcepInfo
,
1854 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1855 return DISP_E_MEMBERNOTFOUND
;
1857 if (wFlags
& DISPATCH_PROPERTYPUT
)
1859 VariantInit(&varg0
);
1860 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1864 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1865 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1866 return DISP_E_EXCEPTION
;
1868 else if (wFlags
& DISPATCH_PROPERTYGET
)
1870 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1871 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1872 return DISP_E_EXCEPTION
;
1874 V_VT(pVarResult
) = VT_I4
;
1875 V_I4(pVarResult
) = ui
;
1881 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1882 DISPPARAMS
* pDispParams
,
1883 VARIANT
* pVarResult
,
1884 EXCEPINFO
* pExcepInfo
,
1887 if (!(wFlags
& DISPATCH_METHOD
))
1888 return DISP_E_MEMBERNOTFOUND
;
1892 VariantInit(pVarResult
);
1896 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1897 DISPPARAMS
* pDispParams
,
1898 VARIANT
* pVarResult
,
1899 EXCEPINFO
* pExcepInfo
,
1904 VARIANTARG varg0
, varg1
;
1906 if (!(wFlags
& DISPATCH_METHOD
))
1907 return DISP_E_MEMBERNOTFOUND
;
1909 VariantInit(&varg0
);
1910 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1914 VariantInit(&varg1
);
1915 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1919 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1920 if (ret
!= ERROR_SUCCESS
)
1922 hr
= DISP_E_EXCEPTION
;
1927 VariantClear(&varg0
);
1928 VariantClear(&varg1
);
1932 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1933 VARIANT
* pVarResult
,
1934 EXCEPINFO
* pExcepInfo
,
1938 DLLVERSIONINFO verinfo
;
1939 WCHAR version
[MAX_PATH
];
1941 static const WCHAR format
[] = {
1942 '%','d','.','%','d','.','%','d','.','%','d',0};
1944 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1945 return DISP_E_MEMBERNOTFOUND
;
1947 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1948 hr
= DllGetVersion(&verinfo
);
1952 sprintfW(version
, format
, verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1953 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1955 V_VT(pVarResult
) = VT_BSTR
;
1956 V_BSTR(pVarResult
) = SysAllocString(version
);
1960 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1961 DISPPARAMS
* pDispParams
,
1962 VARIANT
* pVarResult
,
1963 EXCEPINFO
* pExcepInfo
,
1966 if (!(wFlags
& DISPATCH_METHOD
))
1967 return DISP_E_MEMBERNOTFOUND
;
1971 VariantInit(pVarResult
);
1975 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
1976 DISPPARAMS
* pDispParams
,
1977 VARIANT
* pVarResult
,
1978 EXCEPINFO
* pExcepInfo
,
1986 LPWSTR szString
= NULL
;
1987 VARIANTARG varg0
, varg1
, varg2
;
1989 if (!(wFlags
& DISPATCH_METHOD
))
1990 return DISP_E_MEMBERNOTFOUND
;
1992 VariantInit(&varg0
);
1993 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1997 VariantInit(&varg1
);
1998 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2002 /* Save valuePos so we can save puArgErr if we are unable to do our type
2006 VariantInit(&varg2
);
2007 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
2011 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
2012 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
2014 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
2017 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
2019 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2020 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
2022 hr
= DISP_E_BADINDEX
;
2026 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2027 switch (V_VT(&varg2
))
2029 /* Return VT_BOOL clarifying whether registry key exists or not. */
2031 V_VT(pVarResult
) = VT_BOOL
;
2032 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
);
2035 /* Return the value of specified key if it exists. */
2037 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
2038 NULL
, NULL
, NULL
, &size
);
2039 if (ret
!= ERROR_SUCCESS
)
2041 hr
= DISP_E_BADINDEX
;
2045 szString
= msi_alloc(size
);
2052 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
2053 &type
, (LPBYTE
)szString
, &size
);
2054 if (ret
!= ERROR_SUCCESS
)
2057 hr
= DISP_E_BADINDEX
;
2061 variant_from_registry_value(pVarResult
, type
,
2062 (LPBYTE
)szString
, size
);
2066 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2068 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
2071 if (hr
== DISP_E_TYPEMISMATCH
)
2072 *puArgErr
= posValue
;
2077 /* Retrieve class name or maximum value name or subkey name size. */
2079 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
2080 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2081 else if (V_I4(&varg2
) > 0)
2082 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
2083 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
2084 else /* V_I4(&varg2) < 0 */
2085 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
2086 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2088 if (ret
!= ERROR_SUCCESS
)
2091 szString
= msi_alloc(++size
* sizeof(WCHAR
));
2099 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
2100 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2101 else if (V_I4(&varg2
) > 0)
2102 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
2103 &size
, 0, 0, NULL
, NULL
);
2104 else /* V_I4(&varg2) < 0 */
2105 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
2107 if (ret
== ERROR_SUCCESS
)
2109 V_VT(pVarResult
) = VT_BSTR
;
2110 V_BSTR(pVarResult
) = SysAllocString(szString
);
2117 VariantClear(&varg0
);
2118 VariantClear(&varg1
);
2119 VariantClear(&varg2
);
2124 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2125 DISPPARAMS
* pDispParams
,
2126 VARIANT
* pVarResult
,
2127 EXCEPINFO
* pExcepInfo
,
2130 if (!(wFlags
& DISPATCH_METHOD
))
2131 return DISP_E_MEMBERNOTFOUND
;
2135 VariantInit(pVarResult
);
2139 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2140 DISPPARAMS
* pDispParams
,
2141 VARIANT
* pVarResult
,
2142 EXCEPINFO
* pExcepInfo
,
2145 if (!(wFlags
& DISPATCH_METHOD
))
2146 return DISP_E_MEMBERNOTFOUND
;
2150 VariantInit(pVarResult
);
2154 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2155 DISPPARAMS
* pDispParams
,
2156 VARIANT
* pVarResult
,
2157 EXCEPINFO
* pExcepInfo
,
2160 if (!(wFlags
& DISPATCH_METHOD
))
2161 return DISP_E_MEMBERNOTFOUND
;
2165 VariantInit(pVarResult
);
2169 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2170 DISPPARAMS
* pDispParams
,
2171 VARIANT
* pVarResult
,
2172 EXCEPINFO
* pExcepInfo
,
2175 if (!(wFlags
& DISPATCH_METHOD
))
2176 return DISP_E_MEMBERNOTFOUND
;
2180 VariantInit(pVarResult
);
2184 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2185 DISPPARAMS
* pDispParams
,
2186 VARIANT
* pVarResult
,
2187 EXCEPINFO
* pExcepInfo
,
2193 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2194 return DISP_E_MEMBERNOTFOUND
;
2196 VariantInit(&varg0
);
2197 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2201 V_VT(pVarResult
) = VT_I4
;
2202 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2204 VariantClear(&varg0
);
2208 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2209 DISPPARAMS
* pDispParams
,
2210 VARIANT
* pVarResult
,
2211 EXCEPINFO
* pExcepInfo
,
2218 VARIANTARG varg0
, varg1
;
2220 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2221 return DISP_E_MEMBERNOTFOUND
;
2223 VariantInit(&varg0
);
2224 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2228 VariantInit(&varg1
);
2229 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2233 V_VT(pVarResult
) = VT_BSTR
;
2234 V_BSTR(pVarResult
) = NULL
;
2236 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2237 if (ret
!= ERROR_SUCCESS
)
2239 hr
= DISP_E_EXCEPTION
;
2243 str
= msi_alloc(++size
* sizeof(WCHAR
));
2250 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2251 if (ret
!= ERROR_SUCCESS
)
2253 hr
= DISP_E_EXCEPTION
;
2257 V_BSTR(pVarResult
) = SysAllocString(str
);
2262 VariantClear(&varg0
);
2263 VariantClear(&varg1
);
2267 static HRESULT
InstallerImpl_Products(WORD flags
,
2268 DISPPARAMS
* pDispParams
,
2270 EXCEPINFO
* pExcepInfo
,
2273 IDispatch
*dispatch
;
2276 if (!(flags
& DISPATCH_PROPERTYGET
))
2277 return DISP_E_MEMBERNOTFOUND
;
2279 hr
= create_list(NULL
, &dispatch
);
2283 V_VT(result
) = VT_DISPATCH
;
2284 V_DISPATCH(result
) = dispatch
;
2289 static HRESULT
InstallerImpl_RelatedProducts(WORD flags
,
2290 DISPPARAMS
* pDispParams
,
2292 EXCEPINFO
* pExcepInfo
,
2295 IDispatch
* dispatch
;
2299 if (!(flags
& DISPATCH_PROPERTYGET
))
2300 return DISP_E_MEMBERNOTFOUND
;
2302 VariantInit(&related
);
2303 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &related
, puArgErr
);
2307 hr
= create_list(V_BSTR(&related
), &dispatch
);
2308 VariantClear(&related
);
2310 V_VT(result
) = VT_DISPATCH
;
2311 V_DISPATCH(result
) = dispatch
;
2316 static HRESULT
installer_invoke(
2317 AutomationObject
* This
,
2318 DISPID dispIdMember
,
2322 DISPPARAMS
* pDispParams
,
2323 VARIANT
* pVarResult
,
2324 EXCEPINFO
* pExcepInfo
,
2327 switch (dispIdMember
)
2329 case DISPID_INSTALLER_CREATERECORD
:
2330 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2331 pVarResult
, pExcepInfo
, puArgErr
);
2333 case DISPID_INSTALLER_OPENPACKAGE
:
2334 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2335 pVarResult
, pExcepInfo
, puArgErr
);
2337 case DISPID_INSTALLER_OPENPRODUCT
:
2338 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2339 pVarResult
, pExcepInfo
, puArgErr
);
2341 case DISPID_INSTALLER_OPENDATABASE
:
2342 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2343 pVarResult
, pExcepInfo
, puArgErr
);
2345 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2346 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2347 pVarResult
, pExcepInfo
,
2350 case DISPID_INSTALLER_UILEVEL
:
2351 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2352 pVarResult
, pExcepInfo
, puArgErr
);
2354 case DISPID_INSTALLER_ENABLELOG
:
2355 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2356 pVarResult
, pExcepInfo
, puArgErr
);
2358 case DISPID_INSTALLER_INSTALLPRODUCT
:
2359 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2360 pVarResult
, pExcepInfo
,
2363 case DISPID_INSTALLER_VERSION
:
2364 return InstallerImpl_Version(wFlags
, pVarResult
,
2365 pExcepInfo
, puArgErr
);
2367 case DISPID_INSTALLER_LASTERRORRECORD
:
2368 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2369 pVarResult
, pExcepInfo
,
2372 case DISPID_INSTALLER_REGISTRYVALUE
:
2373 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2374 pVarResult
, pExcepInfo
,
2377 case DISPID_INSTALLER_ENVIRONMENT
:
2378 return InstallerImpl_Environment(wFlags
, pDispParams
,
2379 pVarResult
, pExcepInfo
, puArgErr
);
2381 case DISPID_INSTALLER_FILEATTRIBUTES
:
2382 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2383 pVarResult
, pExcepInfo
,
2386 case DISPID_INSTALLER_FILESIZE
:
2387 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2388 pVarResult
, pExcepInfo
, puArgErr
);
2390 case DISPID_INSTALLER_FILEVERSION
:
2391 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2392 pVarResult
, pExcepInfo
, puArgErr
);
2394 case DISPID_INSTALLER_PRODUCTSTATE
:
2395 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2396 pVarResult
, pExcepInfo
, puArgErr
);
2398 case DISPID_INSTALLER_PRODUCTINFO
:
2399 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2400 pVarResult
, pExcepInfo
, puArgErr
);
2402 case DISPID_INSTALLER_PRODUCTS
:
2403 return InstallerImpl_Products(wFlags
, pDispParams
,
2404 pVarResult
, pExcepInfo
, puArgErr
);
2406 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2407 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2408 pVarResult
, pExcepInfo
,
2412 return DISP_E_MEMBERNOTFOUND
;
2416 HRESULT
create_msiserver(IUnknown
*outer
, void **ppObj
)
2418 AutomationObject
*installer
;
2421 TRACE("(%p %p)\n", outer
, ppObj
);
2424 return CLASS_E_NOAGGREGATION
;
2426 installer
= msi_alloc(sizeof(AutomationObject
));
2427 if (!installer
) return E_OUTOFMEMORY
;
2429 hr
= init_automation_object(installer
, 0, Installer_tid
);
2432 msi_free(installer
);
2436 *ppObj
= &installer
->IDispatch_iface
;
2441 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2443 SessionObject
*session
;
2446 session
= msi_alloc(sizeof(SessionObject
));
2447 if (!session
) return E_OUTOFMEMORY
;
2449 hr
= init_automation_object(&session
->autoobj
, msiHandle
, Session_tid
);
2456 session
->installer
= installer
;
2457 *disp
= &session
->autoobj
.IDispatch_iface
;
2462 static HRESULT
create_database(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2464 AutomationObject
*database
;
2467 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2469 database
= msi_alloc(sizeof(AutomationObject
));
2470 if (!database
) return E_OUTOFMEMORY
;
2472 hr
= init_automation_object(database
, msiHandle
, Database_tid
);
2479 *dispatch
= &database
->IDispatch_iface
;
2484 static HRESULT
create_view(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2486 AutomationObject
*view
;
2489 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2491 view
= msi_alloc(sizeof(AutomationObject
));
2492 if (!view
) return E_OUTOFMEMORY
;
2494 hr
= init_automation_object(view
, msiHandle
, View_tid
);
2501 *dispatch
= &view
->IDispatch_iface
;
2506 static HRESULT
create_summaryinfo(MSIHANDLE msiHandle
, IDispatch
**disp
)
2508 AutomationObject
*info
;
2511 info
= msi_alloc(sizeof(*info
));
2512 if (!info
) return E_OUTOFMEMORY
;
2514 hr
= init_automation_object(info
, msiHandle
, SummaryInfo_tid
);
2521 *disp
= &info
->IDispatch_iface
;