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"
36 #include "msiserver.h"
37 #include "msiserver_dispids.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
41 #define REG_INDEX_CLASSES_ROOT 0
42 #define REG_INDEX_DYN_DATA 6
44 typedef struct AutomationObject AutomationObject
;
46 /* function that is called from AutomationObject::Invoke, specific to this type of object */
47 typedef HRESULT (*auto_invoke_func
)(AutomationObject
* This
,
48 DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD flags
, DISPPARAMS
* pDispParams
,
49 VARIANT
* result
, EXCEPINFO
* ei
, UINT
* arg_err
);
50 /* function that is called from AutomationObject::Release when the object is being freed
51 to free any private data structures (or NULL) */
52 typedef void (*auto_free_func
)(AutomationObject
* This
);
56 auto_invoke_func fn_invoke
;
57 auto_free_func fn_free
;
61 static HRESULT
database_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
62 static HRESULT
installer_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
63 static HRESULT
record_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
64 static HRESULT
session_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
65 static HRESULT
list_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
66 static void list_free(AutomationObject
*);
67 static HRESULT
summaryinfo_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
68 static HRESULT
view_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
70 static tid_id_t tid_ids
[] = {
71 { &DIID_Database
, database_invoke
},
72 { &DIID_Installer
, installer_invoke
},
73 { &DIID_Record
, record_invoke
},
74 { &DIID_Session
, session_invoke
},
75 { &DIID_StringList
, list_invoke
, list_free
},
76 { &DIID_SummaryInfo
, summaryinfo_invoke
},
77 { &DIID_View
, view_invoke
}
80 static ITypeLib
*typelib
;
81 static ITypeInfo
*typeinfos
[LAST_tid
];
83 static const IID
*get_riid_from_tid(tid_t tid
)
85 return tid_ids
[tid
].riid
;
88 HRESULT
get_typeinfo(tid_t tid
, ITypeInfo
**typeinfo
)
96 hr
= LoadRegTypeLib(&LIBID_WindowsInstaller
, 1, 0, LOCALE_NEUTRAL
, &lib
);
98 hr
= LoadTypeLib(L
"msiserver.tlb", &lib
);
100 ERR("Could not load msiserver.tlb\n");
105 if (InterlockedCompareExchangePointer((void**)&typelib
, lib
, NULL
))
106 ITypeLib_Release(lib
);
113 hr
= ITypeLib_GetTypeInfoOfGuid(typelib
, get_riid_from_tid(tid
), &ti
);
115 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid
)));
119 if(InterlockedCompareExchangePointer((void**)(typeinfos
+tid
), ti
, NULL
))
120 ITypeInfo_Release(ti
);
123 *typeinfo
= typeinfos
[tid
];
127 void release_typelib(void)
131 for (i
= 0; i
< ARRAY_SIZE(typeinfos
); i
++)
133 ITypeInfo_Release(typeinfos
[i
]);
136 ITypeLib_Release(typelib
);
140 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
141 * called from AutomationObject::Invoke.
143 struct AutomationObject
{
144 IDispatch IDispatch_iface
;
145 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface
;
148 /* type id for this class */
151 /* The MSI handle of the current object */
156 AutomationObject autoobj
;
161 static HRESULT
create_database(MSIHANDLE
, IDispatch
**);
162 static HRESULT
create_list_enumerator(ListObject
*, void**);
163 static HRESULT
create_summaryinfo(MSIHANDLE
, IDispatch
**);
164 static HRESULT
create_view(MSIHANDLE
, IDispatch
**);
166 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
168 IEnumVARIANT IEnumVARIANT_iface
;
171 /* Current position and pointer to AutomationObject that stores actual data */
177 AutomationObject autoobj
;
178 IDispatch
*installer
;
181 static inline AutomationObject
*impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
183 return CONTAINING_RECORD(iface
, AutomationObject
, IProvideMultipleClassInfo_iface
);
186 static inline AutomationObject
*impl_from_IDispatch( IDispatch
*iface
)
188 return CONTAINING_RECORD(iface
, AutomationObject
, IDispatch_iface
);
191 /* AutomationObject methods */
192 static HRESULT WINAPI
AutomationObject_QueryInterface(IDispatch
* iface
, REFIID riid
, void** ppvObject
)
194 AutomationObject
*This
= impl_from_IDispatch(iface
);
196 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
198 if (ppvObject
== NULL
)
203 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
204 IsEqualGUID(riid
, &IID_IDispatch
) ||
205 IsEqualGUID(riid
, get_riid_from_tid(This
->tid
)))
206 *ppvObject
= &This
->IDispatch_iface
;
207 else if (IsEqualGUID(riid
, &IID_IProvideClassInfo
) ||
208 IsEqualGUID(riid
, &IID_IProvideClassInfo2
) ||
209 IsEqualGUID(riid
, &IID_IProvideMultipleClassInfo
))
210 *ppvObject
= &This
->IProvideMultipleClassInfo_iface
;
213 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
214 return E_NOINTERFACE
;
217 IDispatch_AddRef(iface
);
222 static ULONG WINAPI
AutomationObject_AddRef(IDispatch
* iface
)
224 AutomationObject
*This
= impl_from_IDispatch(iface
);
226 TRACE("(%p/%p)\n", iface
, This
);
228 return InterlockedIncrement(&This
->ref
);
231 static ULONG WINAPI
AutomationObject_Release(IDispatch
* iface
)
233 AutomationObject
*This
= impl_from_IDispatch(iface
);
234 ULONG ref
= InterlockedDecrement(&This
->ref
);
236 TRACE("(%p/%p)\n", iface
, This
);
240 if (tid_ids
[This
->tid
].fn_free
) tid_ids
[This
->tid
].fn_free(This
);
241 MsiCloseHandle(This
->msiHandle
);
248 static HRESULT WINAPI
AutomationObject_GetTypeInfoCount(
252 AutomationObject
*This
= impl_from_IDispatch(iface
);
254 TRACE("(%p/%p)->(%p)\n", iface
, This
, pctinfo
);
259 static HRESULT WINAPI
AutomationObject_GetTypeInfo(
265 AutomationObject
*This
= impl_from_IDispatch(iface
);
268 TRACE("(%p/%p)->(%d,%d,%p)\n", iface
, This
, iTInfo
, lcid
, ppTInfo
);
270 hr
= get_typeinfo(This
->tid
, ppTInfo
);
274 ITypeInfo_AddRef(*ppTInfo
);
278 static HRESULT WINAPI
AutomationObject_GetIDsOfNames(
286 AutomationObject
*This
= impl_from_IDispatch(iface
);
290 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", iface
, This
,
291 debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
293 if (!IsEqualGUID(riid
, &IID_NULL
)) return E_INVALIDARG
;
295 hr
= get_typeinfo(This
->tid
, &ti
);
299 hr
= ITypeInfo_GetIDsOfNames(ti
, rgszNames
, cNames
, rgDispId
);
300 if (hr
== DISP_E_UNKNOWNNAME
)
303 for (idx
=0; idx
<cNames
; idx
++)
305 if (rgDispId
[idx
] == DISPID_UNKNOWN
)
306 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames
[idx
]), debugstr_guid(get_riid_from_tid(This
->tid
)));
312 /* Maximum number of allowed function parameters+1 */
313 #define MAX_FUNC_PARAMS 20
315 /* Some error checking is done here to simplify individual object function invocation */
316 static HRESULT WINAPI
AutomationObject_Invoke(
322 DISPPARAMS
* pDispParams
,
324 EXCEPINFO
* pExcepInfo
,
327 AutomationObject
*This
= impl_from_IDispatch(iface
);
329 unsigned int uArgErr
;
330 VARIANT varResultDummy
;
331 BSTR bstrName
= NULL
;
334 TRACE("(%p/%p)->(%d, %s, %d, %d, %p, %p, %p, %p)\n", iface
, This
,
335 dispIdMember
, debugstr_guid(riid
), lcid
, wFlags
,
336 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
338 if (!IsEqualIID(riid
, &IID_NULL
))
340 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
341 return DISP_E_UNKNOWNNAME
;
344 if (wFlags
& DISPATCH_PROPERTYGET
&& !pVarResult
)
346 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
347 return DISP_E_PARAMNOTOPTIONAL
;
350 /* This simplifies our individual object invocation functions */
351 if (puArgErr
== NULL
) puArgErr
= &uArgErr
;
352 if (pVarResult
== NULL
) pVarResult
= &varResultDummy
;
354 hr
= get_typeinfo(This
->tid
, &ti
);
358 /* Assume return type is void unless determined otherwise */
359 VariantInit(pVarResult
);
361 /* If we are tracing, we want to see the name of the member we are invoking */
364 ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
365 TRACE("Method %d, %s\n", dispIdMember
, debugstr_w(bstrName
));
368 hr
= tid_ids
[This
->tid
].fn_invoke(This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
370 if (hr
== DISP_E_MEMBERNOTFOUND
) {
371 if (bstrName
== NULL
) ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
372 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember
, debugstr_w(bstrName
), wFlags
,
373 debugstr_guid(get_riid_from_tid(This
->tid
)));
375 else if (pExcepInfo
&&
376 (hr
== DISP_E_PARAMNOTFOUND
||
377 hr
== DISP_E_EXCEPTION
)) {
378 WCHAR szExceptionDescription
[MAX_PATH
];
379 BSTR bstrParamNames
[MAX_FUNC_PARAMS
];
383 if (FAILED(ITypeInfo_GetNames(ti
, dispIdMember
, bstrParamNames
,
384 MAX_FUNC_PARAMS
, &namesNo
)))
386 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember
);
390 memset(szExceptionDescription
, 0, sizeof(szExceptionDescription
));
391 for (i
=0; i
<namesNo
; i
++)
393 if (bFirst
) bFirst
= FALSE
;
395 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], L
",");
397 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], bstrParamNames
[i
]);
398 SysFreeString(bstrParamNames
[i
]);
401 memset(pExcepInfo
, 0, sizeof(EXCEPINFO
));
402 pExcepInfo
->wCode
= 1000;
403 pExcepInfo
->bstrSource
= SysAllocString(L
"Msi API Error");
404 pExcepInfo
->bstrDescription
= SysAllocString(szExceptionDescription
);
405 hr
= DISP_E_EXCEPTION
;
409 /* Make sure we free the return variant if it is our dummy variant */
410 if (pVarResult
== &varResultDummy
) VariantClear(pVarResult
);
412 /* Free function name if we retrieved it */
413 SysFreeString(bstrName
);
415 TRACE("Returning 0x%08x, %s\n", hr
, SUCCEEDED(hr
) ? "ok" : "not ok");
420 static const struct IDispatchVtbl AutomationObjectVtbl
=
422 AutomationObject_QueryInterface
,
423 AutomationObject_AddRef
,
424 AutomationObject_Release
,
425 AutomationObject_GetTypeInfoCount
,
426 AutomationObject_GetTypeInfo
,
427 AutomationObject_GetIDsOfNames
,
428 AutomationObject_Invoke
432 * IProvideMultipleClassInfo methods
435 static HRESULT WINAPI
ProvideMultipleClassInfo_QueryInterface(
436 IProvideMultipleClassInfo
* iface
,
440 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
441 return IDispatch_QueryInterface(&This
->IDispatch_iface
, riid
, ppvoid
);
444 static ULONG WINAPI
ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo
* iface
)
446 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
447 return IDispatch_AddRef(&This
->IDispatch_iface
);
450 static ULONG WINAPI
ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo
* iface
)
452 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
453 return IDispatch_Release(&This
->IDispatch_iface
);
456 static HRESULT WINAPI
ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo
* iface
, ITypeInfo
** ppTI
)
458 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
461 TRACE("(%p/%p)->(%p)\n", iface
, This
, ppTI
);
463 hr
= get_typeinfo(This
->tid
, ppTI
);
465 ITypeInfo_AddRef(*ppTI
);
470 static HRESULT WINAPI
ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
* iface
, DWORD dwGuidKind
, GUID
* pGUID
)
472 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
473 TRACE("(%p/%p)->(%d,%s)\n", iface
, This
, dwGuidKind
, debugstr_guid(pGUID
));
475 if (dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
478 *pGUID
= *get_riid_from_tid(This
->tid
);
483 static HRESULT WINAPI
ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo
* iface
, ULONG
* pcti
)
485 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
487 TRACE("(%p/%p)->(%p)\n", iface
, This
, pcti
);
492 static HRESULT WINAPI
ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo
* iface
,
497 ULONG
* pcdispidReserved
,
501 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
503 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface
, This
, iti
, dwFlags
, ti
, pdwTIFlags
, pcdispidReserved
, piidPrimary
, piidSource
);
508 if (dwFlags
& MULTICLASSINFO_GETTYPEINFO
)
510 HRESULT hr
= get_typeinfo(This
->tid
, ti
);
514 ITypeInfo_AddRef(*ti
);
517 if (dwFlags
& MULTICLASSINFO_GETNUMRESERVEDDISPIDS
)
520 *pcdispidReserved
= 0;
523 if (dwFlags
& MULTICLASSINFO_GETIIDPRIMARY
)
524 *piidPrimary
= *get_riid_from_tid(This
->tid
);
526 if (dwFlags
& MULTICLASSINFO_GETIIDSOURCE
)
527 *piidSource
= *get_riid_from_tid(This
->tid
);
532 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl
=
534 ProvideMultipleClassInfo_QueryInterface
,
535 ProvideMultipleClassInfo_AddRef
,
536 ProvideMultipleClassInfo_Release
,
537 ProvideMultipleClassInfo_GetClassInfo
,
538 ProvideMultipleClassInfo_GetGUID
,
539 ProvideMultipleClassInfo_GetMultiTypeInfoCount
,
540 ProvideMultipleClassInfo_GetInfoOfIndex
543 static void init_automation_object(AutomationObject
*This
, MSIHANDLE msiHandle
, tid_t tid
)
545 TRACE("(%p, %d, %s)\n", This
, msiHandle
, debugstr_guid(get_riid_from_tid(tid
)));
547 This
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
548 This
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
550 This
->msiHandle
= msiHandle
;
555 * ListEnumerator methods
558 static inline ListEnumerator
*impl_from_IEnumVARIANT(IEnumVARIANT
* iface
)
560 return CONTAINING_RECORD(iface
, ListEnumerator
, IEnumVARIANT_iface
);
563 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
,
566 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
568 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
570 if (ppvObject
== NULL
)
575 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
576 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
578 *ppvObject
= &This
->IEnumVARIANT_iface
;
582 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
583 return E_NOINTERFACE
;
586 IEnumVARIANT_AddRef(iface
);
590 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
592 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
594 TRACE("(%p/%p)\n", iface
, This
);
596 return InterlockedIncrement(&This
->ref
);
599 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
601 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
602 ULONG ref
= InterlockedDecrement(&This
->ref
);
604 TRACE("(%p/%p)\n", iface
, This
);
608 if (This
->list
) IDispatch_Release(&This
->list
->autoobj
.IDispatch_iface
);
615 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
* rgVar
,
618 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
621 TRACE("(%p, %uld, %p, %p)\n", iface
, celt
, rgVar
, fetched
);
623 if (fetched
) *fetched
= 0;
628 for (local
= 0; local
< celt
; local
++)
629 VariantInit(&rgVar
[local
]);
631 for (i
= This
->pos
, local
= 0; i
< This
->list
->count
&& local
< celt
; i
++, local
++)
632 VariantCopy(&rgVar
[local
], &This
->list
->data
[i
]);
634 if (fetched
) *fetched
= local
;
637 return (local
< celt
) ? S_FALSE
: S_OK
;
640 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
642 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
644 TRACE("(%p,%uld)\n", iface
, celt
);
647 if (This
->pos
>= This
->list
->count
)
649 This
->pos
= This
->list
->count
;
656 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
658 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
660 TRACE("(%p)\n", iface
);
666 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
668 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
671 TRACE("(%p,%p)\n", iface
, ppEnum
);
677 hr
= create_list_enumerator(This
->list
, (LPVOID
*)ppEnum
);
680 if (*ppEnum
) IEnumVARIANT_Release(*ppEnum
);
687 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
689 ListEnumerator_QueryInterface
,
690 ListEnumerator_AddRef
,
691 ListEnumerator_Release
,
694 ListEnumerator_Reset
,
698 /* Create a list enumerator, placing the result in the pointer ppObj. */
699 static HRESULT
create_list_enumerator(ListObject
*list
, void **ppObj
)
701 ListEnumerator
*object
;
703 TRACE("(%p, %p)\n", list
, ppObj
);
705 object
= msi_alloc(sizeof(ListEnumerator
));
707 /* Set all the VTable references */
708 object
->IEnumVARIANT_iface
.lpVtbl
= &ListEnumerator_Vtbl
;
711 /* Store data that was passed */
714 if (list
) IDispatch_AddRef(&list
->autoobj
.IDispatch_iface
);
721 * Individual Object Invocation Functions
724 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
725 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
726 using DispGetParam/VariantChangeType. */
727 static HRESULT
DispGetParam_CopyOnly(
728 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
729 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
730 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
732 /* position is counted backwards */
735 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
736 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
737 if (*position
< pdispparams
->cArgs
) {
738 /* positional arg? */
739 pos
= pdispparams
->cArgs
- *position
- 1;
741 /* FIXME: is this how to handle named args? */
742 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
743 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
745 if (pos
==pdispparams
->cNamedArgs
)
746 return DISP_E_PARAMNOTFOUND
;
749 return VariantCopyInd(pvarResult
,
750 &pdispparams
->rgvarg
[pos
]);
753 static HRESULT
summaryinfo_invoke(
754 AutomationObject
* This
,
759 DISPPARAMS
* pDispParams
,
761 EXCEPINFO
* pExcepInfo
,
765 VARIANTARG varg0
, varg1
;
766 FILETIME ft
, ftlocal
;
773 switch (dispIdMember
)
775 case DISPID_SUMMARYINFO_PROPERTY
:
776 if (wFlags
& DISPATCH_PROPERTYGET
)
784 static WCHAR szEmpty
[] = L
"";
786 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
787 if (FAILED(hr
)) return hr
;
788 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
789 &ft
, szEmpty
, &size
);
790 if (ret
!= ERROR_SUCCESS
&&
791 ret
!= ERROR_MORE_DATA
)
793 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
794 return DISP_E_EXCEPTION
;
804 V_VT(pVarResult
) = VT_I4
;
805 V_I4(pVarResult
) = value
;
809 if (!(str
= msi_alloc(++size
* sizeof(WCHAR
))))
810 ERR("Out of memory\n");
811 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
812 NULL
, str
, &size
)) != ERROR_SUCCESS
)
813 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
816 V_VT(pVarResult
) = VT_BSTR
;
817 V_BSTR(pVarResult
) = SysAllocString(str
);
823 FileTimeToLocalFileTime(&ft
, &ftlocal
);
824 FileTimeToSystemTime(&ftlocal
, &st
);
825 SystemTimeToVariantTime(&st
, &date
);
827 V_VT(pVarResult
) = VT_DATE
;
828 V_DATE(pVarResult
) = date
;
832 ERR("Unhandled variant type %d\n", type
);
835 else if (wFlags
& DISPATCH_PROPERTYPUT
)
837 UINT posValue
= DISPID_PROPERTYPUT
;
839 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
840 if (FAILED(hr
)) return hr
;
841 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
844 *puArgErr
= posValue
;
848 switch (V_VT(&varg1
))
852 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
856 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
857 SystemTimeToFileTime(&st
, &ftlocal
);
858 LocalFileTimeToFileTime(&ftlocal
, &ft
);
859 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
863 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
867 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
868 VariantClear(&varg1
);
869 return DISP_E_EXCEPTION
;
872 if (ret
!= ERROR_SUCCESS
)
874 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
875 return DISP_E_EXCEPTION
;
878 else return DISP_E_MEMBERNOTFOUND
;
881 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
882 if (wFlags
& DISPATCH_PROPERTYGET
) {
884 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
885 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
888 V_VT(pVarResult
) = VT_I4
;
889 V_I4(pVarResult
) = count
;
892 else return DISP_E_MEMBERNOTFOUND
;
896 return DISP_E_MEMBERNOTFOUND
;
899 VariantClear(&varg1
);
900 VariantClear(&varg0
);
905 static HRESULT
record_invoke(
906 AutomationObject
* This
,
911 DISPPARAMS
* pDispParams
,
913 EXCEPINFO
* pExcepInfo
,
919 VARIANTARG varg0
, varg1
;
925 switch (dispIdMember
)
927 case DISPID_RECORD_FIELDCOUNT
:
928 if (wFlags
& DISPATCH_PROPERTYGET
) {
929 V_VT(pVarResult
) = VT_I4
;
930 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
932 else return DISP_E_MEMBERNOTFOUND
;
935 case DISPID_RECORD_STRINGDATA
:
936 if (wFlags
& DISPATCH_PROPERTYGET
) {
937 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
938 if (FAILED(hr
)) return hr
;
939 V_VT(pVarResult
) = VT_BSTR
;
940 V_BSTR(pVarResult
) = NULL
;
941 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
943 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
944 ERR("Out of memory\n");
945 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
946 V_BSTR(pVarResult
) = SysAllocString(szString
);
949 if (ret
!= ERROR_SUCCESS
)
950 ERR("MsiRecordGetString returned %d\n", ret
);
951 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
952 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
953 if (FAILED(hr
)) return hr
;
954 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
955 if (FAILED(hr
)) return hr
;
956 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
958 VariantClear(&varg1
);
959 ERR("MsiRecordSetString returned %d\n", ret
);
960 return DISP_E_EXCEPTION
;
963 else return DISP_E_MEMBERNOTFOUND
;
966 case DISPID_RECORD_INTEGERDATA
:
967 if (wFlags
& DISPATCH_PROPERTYGET
) {
968 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
969 if (FAILED(hr
)) return hr
;
970 V_VT(pVarResult
) = VT_I4
;
971 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
972 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
973 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
974 if (FAILED(hr
)) return hr
;
975 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
976 if (FAILED(hr
)) return hr
;
977 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
979 ERR("MsiRecordSetInteger returned %d\n", ret
);
980 return DISP_E_EXCEPTION
;
983 else return DISP_E_MEMBERNOTFOUND
;
987 return DISP_E_MEMBERNOTFOUND
;
990 VariantClear(&varg1
);
991 VariantClear(&varg0
);
996 static HRESULT
create_record(MSIHANDLE msiHandle
, IDispatch
**disp
)
998 AutomationObject
*record
;
1000 record
= msi_alloc(sizeof(*record
));
1001 if (!record
) return E_OUTOFMEMORY
;
1003 init_automation_object(record
, msiHandle
, Record_tid
);
1005 *disp
= &record
->IDispatch_iface
;
1010 static HRESULT
list_invoke(
1011 AutomationObject
* This
,
1012 DISPID dispIdMember
,
1016 DISPPARAMS
* pDispParams
,
1017 VARIANT
* pVarResult
,
1018 EXCEPINFO
* pExcepInfo
,
1021 ListObject
*list
= CONTAINING_RECORD(This
, ListObject
, autoobj
);
1022 IUnknown
*pUnk
= NULL
;
1025 switch (dispIdMember
)
1027 case DISPID_LIST__NEWENUM
:
1028 if (wFlags
& DISPATCH_METHOD
) {
1029 V_VT(pVarResult
) = VT_UNKNOWN
;
1030 if (SUCCEEDED(hr
= create_list_enumerator(list
, (LPVOID
*)&pUnk
)))
1031 V_UNKNOWN(pVarResult
) = pUnk
;
1033 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr
);
1035 else return DISP_E_MEMBERNOTFOUND
;
1038 case DISPID_LIST_ITEM
:
1039 if (wFlags
& DISPATCH_PROPERTYGET
) {
1042 VariantInit(&index
);
1043 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &index
, puArgErr
);
1044 if (FAILED(hr
)) return hr
;
1045 if (V_I4(&index
) < 0 || V_I4(&index
) >= list
->count
)
1046 return DISP_E_BADINDEX
;
1047 VariantCopy(pVarResult
, &list
->data
[V_I4(&index
)]);
1049 else return DISP_E_MEMBERNOTFOUND
;
1052 case DISPID_LIST_COUNT
:
1053 if (wFlags
& DISPATCH_PROPERTYGET
) {
1054 V_VT(pVarResult
) = VT_I4
;
1055 V_I4(pVarResult
) = list
->count
;
1057 else return DISP_E_MEMBERNOTFOUND
;
1061 return DISP_E_MEMBERNOTFOUND
;
1067 static void list_free(AutomationObject
*This
)
1069 ListObject
*list
= CONTAINING_RECORD(This
, ListObject
, autoobj
);
1072 for (i
= 0; i
< list
->count
; i
++)
1073 VariantClear(&list
->data
[i
]);
1074 msi_free(list
->data
);
1077 static HRESULT
get_products_count(const WCHAR
*product
, int *len
)
1083 WCHAR dataW
[GUID_SIZE
];
1086 /* all or related only */
1088 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1090 ret
= MsiEnumProductsW(i
, dataW
);
1092 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1094 if (ret
!= ERROR_SUCCESS
)
1095 return DISP_E_EXCEPTION
;
1105 static HRESULT
create_list(const WCHAR
*product
, IDispatch
**dispatch
)
1111 list
= msi_alloc_zero(sizeof(ListObject
));
1112 if (!list
) return E_OUTOFMEMORY
;
1114 init_automation_object(&list
->autoobj
, 0, StringList_tid
);
1116 *dispatch
= &list
->autoobj
.IDispatch_iface
;
1118 hr
= get_products_count(product
, &list
->count
);
1121 IDispatch_Release(*dispatch
);
1125 list
->data
= msi_alloc(list
->count
*sizeof(VARIANT
));
1128 IDispatch_Release(*dispatch
);
1129 return E_OUTOFMEMORY
;
1132 for (i
= 0; i
< list
->count
; i
++)
1134 WCHAR dataW
[GUID_SIZE
];
1137 /* all or related only */
1139 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1141 ret
= MsiEnumProductsW(i
, dataW
);
1143 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1145 V_VT(&list
->data
[i
]) = VT_BSTR
;
1146 V_BSTR(&list
->data
[i
]) = SysAllocString(dataW
);
1152 static HRESULT
view_invoke(
1153 AutomationObject
* This
,
1154 DISPID dispIdMember
,
1158 DISPPARAMS
* pDispParams
,
1159 VARIANT
* pVarResult
,
1160 EXCEPINFO
* pExcepInfo
,
1163 MSIHANDLE msiHandle
;
1165 VARIANTARG varg0
, varg1
;
1168 VariantInit(&varg0
);
1169 VariantInit(&varg1
);
1171 switch (dispIdMember
)
1173 case DISPID_VIEW_EXECUTE
:
1174 if (wFlags
& DISPATCH_METHOD
)
1176 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1177 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1178 MsiViewExecute(This
->msiHandle
, ((AutomationObject
*)V_DISPATCH(&varg0
))->msiHandle
);
1180 MsiViewExecute(This
->msiHandle
, 0);
1182 else return DISP_E_MEMBERNOTFOUND
;
1185 case DISPID_VIEW_FETCH
:
1186 if (wFlags
& DISPATCH_METHOD
)
1188 V_VT(pVarResult
) = VT_DISPATCH
;
1189 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1191 if (FAILED(hr
= create_record(msiHandle
, &V_DISPATCH(pVarResult
))))
1192 ERR("Failed to create Record object, hresult 0x%08x\n", hr
);
1194 else if (ret
== ERROR_NO_MORE_ITEMS
)
1195 V_DISPATCH(pVarResult
) = NULL
;
1198 ERR("MsiViewFetch returned %d\n", ret
);
1199 return DISP_E_EXCEPTION
;
1202 else return DISP_E_MEMBERNOTFOUND
;
1205 case DISPID_VIEW_MODIFY
:
1206 if (wFlags
& DISPATCH_METHOD
)
1208 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1209 if (FAILED(hr
)) return hr
;
1210 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1211 if (FAILED(hr
)) return hr
;
1212 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1213 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1215 VariantClear(&varg1
);
1216 ERR("MsiViewModify returned %d\n", ret
);
1217 return DISP_E_EXCEPTION
;
1220 else return DISP_E_MEMBERNOTFOUND
;
1223 case DISPID_VIEW_CLOSE
:
1224 if (wFlags
& DISPATCH_METHOD
)
1226 MsiViewClose(This
->msiHandle
);
1228 else return DISP_E_MEMBERNOTFOUND
;
1232 return DISP_E_MEMBERNOTFOUND
;
1235 VariantClear(&varg1
);
1236 VariantClear(&varg0
);
1241 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1242 DISPPARAMS
* pDispParams
,
1243 VARIANT
* pVarResult
,
1244 EXCEPINFO
* pExcepInfo
,
1247 if (!(wFlags
& DISPATCH_METHOD
))
1248 return DISP_E_MEMBERNOTFOUND
;
1252 VariantInit(pVarResult
);
1256 HRESULT
database_invoke(
1257 AutomationObject
* This
,
1258 DISPID dispIdMember
,
1262 DISPPARAMS
* pDispParams
,
1263 VARIANT
* pVarResult
,
1264 EXCEPINFO
* pExcepInfo
,
1267 IDispatch
*dispatch
= NULL
;
1268 MSIHANDLE msiHandle
;
1270 VARIANTARG varg0
, varg1
;
1273 VariantInit(&varg0
);
1274 VariantInit(&varg1
);
1276 switch (dispIdMember
)
1278 case DISPID_DATABASE_SUMMARYINFORMATION
:
1279 if (wFlags
& DISPATCH_PROPERTYGET
)
1281 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1285 V_VT(pVarResult
) = VT_DISPATCH
;
1286 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1288 hr
= create_summaryinfo(msiHandle
, &dispatch
);
1290 V_DISPATCH(pVarResult
) = dispatch
;
1292 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr
);
1296 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1297 return DISP_E_EXCEPTION
;
1300 else return DISP_E_MEMBERNOTFOUND
;
1303 case DISPID_DATABASE_OPENVIEW
:
1304 if (wFlags
& DISPATCH_METHOD
)
1306 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1307 if (FAILED(hr
)) return hr
;
1308 V_VT(pVarResult
) = VT_DISPATCH
;
1309 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1311 if (SUCCEEDED(hr
= create_view(msiHandle
, &dispatch
)))
1312 V_DISPATCH(pVarResult
) = dispatch
;
1314 ERR("Failed to create View object, hresult 0x%08x\n", hr
);
1318 VariantClear(&varg0
);
1319 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1320 return DISP_E_EXCEPTION
;
1323 else return DISP_E_MEMBERNOTFOUND
;
1326 case DISPID_INSTALLER_LASTERRORRECORD
:
1327 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1328 pVarResult
, pExcepInfo
,
1332 return DISP_E_MEMBERNOTFOUND
;
1335 VariantClear(&varg1
);
1336 VariantClear(&varg0
);
1341 static HRESULT
session_invoke(
1342 AutomationObject
* This
,
1343 DISPID dispIdMember
,
1347 DISPPARAMS
* pDispParams
,
1348 VARIANT
* pVarResult
,
1349 EXCEPINFO
* pExcepInfo
,
1352 SessionObject
*session
= CONTAINING_RECORD(This
, SessionObject
, autoobj
);
1355 MSIHANDLE msiHandle
;
1358 INSTALLSTATE iInstalled
, iAction
;
1359 VARIANTARG varg0
, varg1
;
1362 VariantInit(&varg0
);
1363 VariantInit(&varg1
);
1365 switch (dispIdMember
)
1367 case DISPID_SESSION_INSTALLER
:
1368 if (wFlags
& DISPATCH_PROPERTYGET
) {
1369 V_VT(pVarResult
) = VT_DISPATCH
;
1370 IDispatch_AddRef(session
->installer
);
1371 V_DISPATCH(pVarResult
) = session
->installer
;
1373 else return DISP_E_MEMBERNOTFOUND
;
1376 case DISPID_SESSION_PROPERTY
:
1377 if (wFlags
& DISPATCH_PROPERTYGET
) {
1378 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1379 if (FAILED(hr
)) return hr
;
1380 V_VT(pVarResult
) = VT_BSTR
;
1381 V_BSTR(pVarResult
) = NULL
;
1382 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1384 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1385 ERR("Out of memory\n");
1386 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1387 V_BSTR(pVarResult
) = SysAllocString(szString
);
1390 if (ret
!= ERROR_SUCCESS
)
1391 ERR("MsiGetProperty returned %d\n", ret
);
1392 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1393 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1394 if (FAILED(hr
)) return hr
;
1395 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1397 VariantClear(&varg0
);
1400 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1402 VariantClear(&varg0
);
1403 VariantClear(&varg1
);
1404 ERR("MsiSetProperty returned %d\n", ret
);
1405 return DISP_E_EXCEPTION
;
1408 else return DISP_E_MEMBERNOTFOUND
;
1411 case DISPID_SESSION_LANGUAGE
:
1412 if (wFlags
& DISPATCH_PROPERTYGET
) {
1413 langId
= MsiGetLanguage(This
->msiHandle
);
1414 V_VT(pVarResult
) = VT_I4
;
1415 V_I4(pVarResult
) = langId
;
1417 else return DISP_E_MEMBERNOTFOUND
;
1420 case DISPID_SESSION_MODE
:
1421 if (wFlags
& DISPATCH_PROPERTYGET
) {
1422 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1423 if (FAILED(hr
)) return hr
;
1424 V_VT(pVarResult
) = VT_BOOL
;
1425 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
)) ? VARIANT_TRUE
: VARIANT_FALSE
;
1426 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1427 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1428 if (FAILED(hr
)) return hr
;
1429 hr
= DispGetParam(pDispParams
, 1, VT_BOOL
, &varg1
, puArgErr
);
1430 if (FAILED(hr
)) return hr
;
1431 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1433 ERR("MsiSetMode returned %d\n", ret
);
1434 return DISP_E_EXCEPTION
;
1437 else return DISP_E_MEMBERNOTFOUND
;
1440 case DISPID_SESSION_DATABASE
:
1441 if (wFlags
& DISPATCH_PROPERTYGET
) {
1442 V_VT(pVarResult
) = VT_DISPATCH
;
1443 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1445 IDispatch
*dispatch
;
1447 if (SUCCEEDED(hr
= create_database(msiHandle
, &dispatch
)))
1448 V_DISPATCH(pVarResult
) = dispatch
;
1450 ERR("Failed to create Database object, hresult 0x%08x\n", hr
);
1454 ERR("MsiGetActiveDatabase failed\n");
1455 return DISP_E_EXCEPTION
;
1458 else return DISP_E_MEMBERNOTFOUND
;
1461 case DISPID_SESSION_DOACTION
:
1462 if (wFlags
& DISPATCH_METHOD
) {
1463 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1464 if (FAILED(hr
)) return hr
;
1465 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1466 V_VT(pVarResult
) = VT_I4
;
1469 case ERROR_FUNCTION_NOT_CALLED
:
1470 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1473 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1475 case ERROR_INSTALL_USEREXIT
:
1476 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1478 case ERROR_INSTALL_FAILURE
:
1479 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1481 case ERROR_INSTALL_SUSPEND
:
1482 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1484 case ERROR_MORE_DATA
:
1485 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1487 case ERROR_INVALID_HANDLE_STATE
:
1488 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1490 case ERROR_INVALID_DATA
:
1491 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1494 VariantClear(&varg0
);
1495 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1496 return DISP_E_EXCEPTION
;
1499 else return DISP_E_MEMBERNOTFOUND
;
1502 case DISPID_SESSION_EVALUATECONDITION
:
1503 if (wFlags
& DISPATCH_METHOD
) {
1504 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1505 if (FAILED(hr
)) return hr
;
1506 V_VT(pVarResult
) = VT_I4
;
1507 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1509 else return DISP_E_MEMBERNOTFOUND
;
1512 case DISPID_SESSION_MESSAGE
:
1513 if(!(wFlags
& DISPATCH_METHOD
))
1514 return DISP_E_MEMBERNOTFOUND
;
1516 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1517 if (FAILED(hr
)) return hr
;
1518 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1519 if (FAILED(hr
)) return hr
;
1521 V_VT(pVarResult
) = VT_I4
;
1523 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1526 case DISPID_SESSION_SETINSTALLLEVEL
:
1527 if (wFlags
& DISPATCH_METHOD
) {
1528 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1529 if (FAILED(hr
)) return hr
;
1530 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1532 ERR("MsiSetInstallLevel returned %d\n", ret
);
1533 return DISP_E_EXCEPTION
;
1536 else return DISP_E_MEMBERNOTFOUND
;
1539 case DISPID_SESSION_FEATURECURRENTSTATE
:
1540 if (wFlags
& DISPATCH_PROPERTYGET
) {
1541 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1542 if (FAILED(hr
)) return hr
;
1543 V_VT(pVarResult
) = VT_I4
;
1544 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1545 V_I4(pVarResult
) = iInstalled
;
1548 ERR("MsiGetFeatureState returned %d\n", ret
);
1549 V_I4(pVarResult
) = msiInstallStateUnknown
;
1552 else return DISP_E_MEMBERNOTFOUND
;
1555 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1556 if (wFlags
& DISPATCH_PROPERTYGET
) {
1557 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1558 if (FAILED(hr
)) return hr
;
1559 V_VT(pVarResult
) = VT_I4
;
1560 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1561 V_I4(pVarResult
) = iAction
;
1564 ERR("MsiGetFeatureState returned %d\n", ret
);
1565 V_I4(pVarResult
) = msiInstallStateUnknown
;
1567 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1568 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1569 if (FAILED(hr
)) return hr
;
1570 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1572 VariantClear(&varg0
);
1575 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1577 VariantClear(&varg0
);
1578 ERR("MsiSetFeatureState returned %d\n", ret
);
1579 return DISP_E_EXCEPTION
;
1582 else return DISP_E_MEMBERNOTFOUND
;
1586 return DISP_E_MEMBERNOTFOUND
;
1589 VariantClear(&varg1
);
1590 VariantClear(&varg0
);
1595 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1596 * registry value type. Used by Installer::RegistryValue. */
1597 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1599 WCHAR
*szString
= (WCHAR
*)lpData
;
1600 LPWSTR szNewString
= NULL
;
1601 DWORD dwNewSize
= 0;
1606 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1607 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1608 idx
= (dwSize
/sizeof(WCHAR
))-1;
1609 while (idx
>= 0 && !szString
[idx
]) idx
--;
1610 for (; idx
>= 0; idx
--)
1611 if (!szString
[idx
]) szString
[idx
] = '\n';
1614 V_VT(pVarResult
) = VT_BSTR
;
1615 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1619 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1620 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1621 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1622 ERR("Out of memory\n");
1623 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1624 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1627 V_VT(pVarResult
) = VT_BSTR
;
1628 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1630 msi_free(szNewString
);
1634 V_VT(pVarResult
) = VT_I4
;
1635 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1639 V_VT(pVarResult
) = VT_BSTR
;
1640 V_BSTR(pVarResult
) = SysAllocString(L
"(REG_\?\?)"); /* Weird string, don't know why native returns it */
1644 V_VT(pVarResult
) = VT_BSTR
;
1645 V_BSTR(pVarResult
) = SysAllocString(L
"(REG_BINARY)");
1649 V_VT(pVarResult
) = VT_EMPTY
;
1653 FIXME("Unhandled registry value type %d\n", dwType
);
1657 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1658 DISPPARAMS
* pDispParams
,
1659 VARIANT
* pVarResult
,
1660 EXCEPINFO
* pExcepInfo
,
1667 if (!(wFlags
& DISPATCH_METHOD
))
1668 return DISP_E_MEMBERNOTFOUND
;
1670 VariantInit(&varg0
);
1671 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1675 V_VT(pVarResult
) = VT_DISPATCH
;
1677 hrec
= MsiCreateRecord(V_I4(&varg0
));
1679 return DISP_E_EXCEPTION
;
1681 return create_record(hrec
, &V_DISPATCH(pVarResult
));
1684 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1686 DISPPARAMS
* pDispParams
,
1687 VARIANT
* pVarResult
,
1688 EXCEPINFO
* pExcepInfo
,
1694 IDispatch
* dispatch
;
1695 VARIANTARG varg0
, varg1
;
1697 if (!(wFlags
& DISPATCH_METHOD
))
1698 return DISP_E_MEMBERNOTFOUND
;
1700 if (pDispParams
->cArgs
== 0)
1701 return DISP_E_TYPEMISMATCH
;
1703 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1704 return DISP_E_TYPEMISMATCH
;
1706 VariantInit(&varg0
);
1707 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1711 VariantInit(&varg1
);
1712 if (pDispParams
->cArgs
== 2)
1714 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1720 V_VT(&varg1
) = VT_I4
;
1724 V_VT(pVarResult
) = VT_DISPATCH
;
1726 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1727 if (ret
!= ERROR_SUCCESS
)
1729 hr
= DISP_E_EXCEPTION
;
1733 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1735 V_DISPATCH(pVarResult
) = dispatch
;
1738 VariantClear(&varg0
);
1739 VariantClear(&varg1
);
1743 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1744 DISPPARAMS
* pDispParams
,
1745 VARIANT
* pVarResult
,
1746 EXCEPINFO
* pExcepInfo
,
1752 if (!(wFlags
& DISPATCH_METHOD
))
1753 return DISP_E_MEMBERNOTFOUND
;
1755 VariantInit(&varg0
);
1756 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1760 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1762 VariantInit(pVarResult
);
1764 VariantClear(&varg0
);
1768 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1769 DISPPARAMS
* pDispParams
,
1770 VARIANT
* pVarResult
,
1771 EXCEPINFO
* pExcepInfo
,
1777 IDispatch
* dispatch
;
1778 VARIANTARG varg0
, varg1
;
1780 if (!(wFlags
& DISPATCH_METHOD
))
1781 return DISP_E_MEMBERNOTFOUND
;
1783 VariantInit(&varg0
);
1784 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1788 VariantInit(&varg1
);
1789 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1793 V_VT(pVarResult
) = VT_DISPATCH
;
1795 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1796 if (ret
!= ERROR_SUCCESS
)
1798 hr
= DISP_E_EXCEPTION
;
1802 hr
= create_database(hdb
, &dispatch
);
1804 V_DISPATCH(pVarResult
) = dispatch
;
1807 VariantClear(&varg0
);
1808 VariantClear(&varg1
);
1812 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1813 DISPPARAMS
* pDispParams
,
1814 VARIANT
* pVarResult
,
1815 EXCEPINFO
* pExcepInfo
,
1821 IDispatch
*dispatch
;
1822 VARIANTARG varg0
, varg1
;
1824 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1825 return DISP_E_MEMBERNOTFOUND
;
1827 VariantInit(&varg1
);
1828 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1832 VariantInit(&varg0
);
1833 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1837 ret
= MsiGetSummaryInformationW(0, V_BSTR(&varg0
), V_I4(&varg1
), &hsuminfo
);
1838 VariantClear(&varg0
);
1839 if (ret
!= ERROR_SUCCESS
)
1840 return DISP_E_EXCEPTION
;
1842 hr
= create_summaryinfo(hsuminfo
, &dispatch
);
1846 V_VT(pVarResult
) = VT_DISPATCH
;
1847 V_DISPATCH(pVarResult
) = dispatch
;
1851 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1852 DISPPARAMS
* pDispParams
,
1853 VARIANT
* pVarResult
,
1854 EXCEPINFO
* pExcepInfo
,
1861 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1862 return DISP_E_MEMBERNOTFOUND
;
1864 if (wFlags
& DISPATCH_PROPERTYPUT
)
1866 VariantInit(&varg0
);
1867 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1871 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1872 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1873 return DISP_E_EXCEPTION
;
1875 else if (wFlags
& DISPATCH_PROPERTYGET
)
1877 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1878 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1879 return DISP_E_EXCEPTION
;
1881 V_VT(pVarResult
) = VT_I4
;
1882 V_I4(pVarResult
) = ui
;
1888 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1889 DISPPARAMS
* pDispParams
,
1890 VARIANT
* pVarResult
,
1891 EXCEPINFO
* pExcepInfo
,
1894 if (!(wFlags
& DISPATCH_METHOD
))
1895 return DISP_E_MEMBERNOTFOUND
;
1899 VariantInit(pVarResult
);
1903 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1904 DISPPARAMS
* pDispParams
,
1905 VARIANT
* pVarResult
,
1906 EXCEPINFO
* pExcepInfo
,
1911 VARIANTARG varg0
, varg1
;
1913 if (!(wFlags
& DISPATCH_METHOD
))
1914 return DISP_E_MEMBERNOTFOUND
;
1916 VariantInit(&varg0
);
1917 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1921 VariantInit(&varg1
);
1922 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1926 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1927 if (ret
!= ERROR_SUCCESS
)
1929 hr
= DISP_E_EXCEPTION
;
1934 VariantClear(&varg0
);
1935 VariantClear(&varg1
);
1939 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1940 VARIANT
* pVarResult
,
1941 EXCEPINFO
* pExcepInfo
,
1945 DLLVERSIONINFO verinfo
;
1946 WCHAR version
[MAX_PATH
];
1948 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1949 return DISP_E_MEMBERNOTFOUND
;
1951 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1952 hr
= DllGetVersion(&verinfo
);
1956 swprintf(version
, ARRAY_SIZE(version
), L
"%d.%d.%d.%d", verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1957 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1959 V_VT(pVarResult
) = VT_BSTR
;
1960 V_BSTR(pVarResult
) = SysAllocString(version
);
1964 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1965 DISPPARAMS
* pDispParams
,
1966 VARIANT
* pVarResult
,
1967 EXCEPINFO
* pExcepInfo
,
1970 if (!(wFlags
& DISPATCH_METHOD
))
1971 return DISP_E_MEMBERNOTFOUND
;
1975 VariantInit(pVarResult
);
1979 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
1980 DISPPARAMS
* pDispParams
,
1981 VARIANT
* pVarResult
,
1982 EXCEPINFO
* pExcepInfo
,
1990 LPWSTR szString
= NULL
;
1991 VARIANTARG varg0
, varg1
, varg2
;
1993 if (!(wFlags
& DISPATCH_METHOD
))
1994 return DISP_E_MEMBERNOTFOUND
;
1996 VariantInit(&varg0
);
1997 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
2001 VariantInit(&varg1
);
2002 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2006 /* Save valuePos so we can save puArgErr if we are unable to do our type
2010 VariantInit(&varg2
);
2011 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
2015 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
2016 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
2018 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
2021 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
2023 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2024 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
2026 hr
= DISP_E_BADINDEX
;
2030 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2031 switch (V_VT(&varg2
))
2033 /* Return VT_BOOL clarifying whether registry key exists or not. */
2035 V_VT(pVarResult
) = VT_BOOL
;
2036 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2039 /* Return the value of specified key if it exists. */
2041 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
2042 NULL
, NULL
, NULL
, &size
);
2043 if (ret
!= ERROR_SUCCESS
)
2045 hr
= DISP_E_BADINDEX
;
2049 szString
= msi_alloc(size
);
2056 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
2057 &type
, (LPBYTE
)szString
, &size
);
2058 if (ret
!= ERROR_SUCCESS
)
2061 hr
= DISP_E_BADINDEX
;
2065 variant_from_registry_value(pVarResult
, type
,
2066 (LPBYTE
)szString
, size
);
2070 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2072 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
2075 if (hr
== DISP_E_TYPEMISMATCH
)
2076 *puArgErr
= posValue
;
2081 /* Retrieve class name or maximum value name or subkey name size. */
2083 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
2084 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2085 else if (V_I4(&varg2
) > 0)
2086 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
2087 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
2088 else /* V_I4(&varg2) < 0 */
2089 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
2090 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2092 if (ret
!= ERROR_SUCCESS
)
2095 szString
= msi_alloc(++size
* sizeof(WCHAR
));
2103 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
2104 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2105 else if (V_I4(&varg2
) > 0)
2106 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
2107 &size
, 0, 0, NULL
, NULL
);
2108 else /* V_I4(&varg2) < 0 */
2109 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
2111 if (ret
== ERROR_SUCCESS
)
2113 V_VT(pVarResult
) = VT_BSTR
;
2114 V_BSTR(pVarResult
) = SysAllocString(szString
);
2121 VariantClear(&varg0
);
2122 VariantClear(&varg1
);
2123 VariantClear(&varg2
);
2128 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2129 DISPPARAMS
* pDispParams
,
2130 VARIANT
* pVarResult
,
2131 EXCEPINFO
* pExcepInfo
,
2134 if (!(wFlags
& DISPATCH_METHOD
))
2135 return DISP_E_MEMBERNOTFOUND
;
2139 VariantInit(pVarResult
);
2143 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2144 DISPPARAMS
* pDispParams
,
2145 VARIANT
* pVarResult
,
2146 EXCEPINFO
* pExcepInfo
,
2149 if (!(wFlags
& DISPATCH_METHOD
))
2150 return DISP_E_MEMBERNOTFOUND
;
2154 VariantInit(pVarResult
);
2158 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2159 DISPPARAMS
* pDispParams
,
2160 VARIANT
* pVarResult
,
2161 EXCEPINFO
* pExcepInfo
,
2164 if (!(wFlags
& DISPATCH_METHOD
))
2165 return DISP_E_MEMBERNOTFOUND
;
2169 VariantInit(pVarResult
);
2173 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2174 DISPPARAMS
* pDispParams
,
2175 VARIANT
* pVarResult
,
2176 EXCEPINFO
* pExcepInfo
,
2179 if (!(wFlags
& DISPATCH_METHOD
))
2180 return DISP_E_MEMBERNOTFOUND
;
2184 VariantInit(pVarResult
);
2188 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2189 DISPPARAMS
* pDispParams
,
2190 VARIANT
* pVarResult
,
2191 EXCEPINFO
* pExcepInfo
,
2197 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2198 return DISP_E_MEMBERNOTFOUND
;
2200 VariantInit(&varg0
);
2201 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2205 V_VT(pVarResult
) = VT_I4
;
2206 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2208 VariantClear(&varg0
);
2212 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2213 DISPPARAMS
* pDispParams
,
2214 VARIANT
* pVarResult
,
2215 EXCEPINFO
* pExcepInfo
,
2222 VARIANTARG varg0
, varg1
;
2224 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2225 return DISP_E_MEMBERNOTFOUND
;
2227 VariantInit(&varg0
);
2228 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2232 VariantInit(&varg1
);
2233 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2237 V_VT(pVarResult
) = VT_BSTR
;
2238 V_BSTR(pVarResult
) = NULL
;
2240 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2241 if (ret
!= ERROR_SUCCESS
)
2243 hr
= DISP_E_EXCEPTION
;
2247 str
= msi_alloc(++size
* sizeof(WCHAR
));
2254 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2255 if (ret
!= ERROR_SUCCESS
)
2257 hr
= DISP_E_EXCEPTION
;
2261 V_BSTR(pVarResult
) = SysAllocString(str
);
2266 VariantClear(&varg0
);
2267 VariantClear(&varg1
);
2271 static HRESULT
InstallerImpl_Products(WORD flags
,
2272 DISPPARAMS
* pDispParams
,
2274 EXCEPINFO
* pExcepInfo
,
2277 IDispatch
*dispatch
;
2280 if (!(flags
& DISPATCH_PROPERTYGET
))
2281 return DISP_E_MEMBERNOTFOUND
;
2283 hr
= create_list(NULL
, &dispatch
);
2287 V_VT(result
) = VT_DISPATCH
;
2288 V_DISPATCH(result
) = dispatch
;
2293 static HRESULT
InstallerImpl_RelatedProducts(WORD flags
,
2294 DISPPARAMS
* pDispParams
,
2296 EXCEPINFO
* pExcepInfo
,
2299 IDispatch
* dispatch
;
2303 if (!(flags
& DISPATCH_PROPERTYGET
))
2304 return DISP_E_MEMBERNOTFOUND
;
2306 VariantInit(&related
);
2307 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &related
, puArgErr
);
2311 hr
= create_list(V_BSTR(&related
), &dispatch
);
2312 VariantClear(&related
);
2314 V_VT(result
) = VT_DISPATCH
;
2315 V_DISPATCH(result
) = dispatch
;
2320 static HRESULT
installer_invoke(
2321 AutomationObject
* This
,
2322 DISPID dispIdMember
,
2326 DISPPARAMS
* pDispParams
,
2327 VARIANT
* pVarResult
,
2328 EXCEPINFO
* pExcepInfo
,
2331 switch (dispIdMember
)
2333 case DISPID_INSTALLER_CREATERECORD
:
2334 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2335 pVarResult
, pExcepInfo
, puArgErr
);
2337 case DISPID_INSTALLER_OPENPACKAGE
:
2338 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2339 pVarResult
, pExcepInfo
, puArgErr
);
2341 case DISPID_INSTALLER_OPENPRODUCT
:
2342 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2343 pVarResult
, pExcepInfo
, puArgErr
);
2345 case DISPID_INSTALLER_OPENDATABASE
:
2346 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2347 pVarResult
, pExcepInfo
, puArgErr
);
2349 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2350 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2351 pVarResult
, pExcepInfo
,
2354 case DISPID_INSTALLER_UILEVEL
:
2355 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2356 pVarResult
, pExcepInfo
, puArgErr
);
2358 case DISPID_INSTALLER_ENABLELOG
:
2359 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2360 pVarResult
, pExcepInfo
, puArgErr
);
2362 case DISPID_INSTALLER_INSTALLPRODUCT
:
2363 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2364 pVarResult
, pExcepInfo
,
2367 case DISPID_INSTALLER_VERSION
:
2368 return InstallerImpl_Version(wFlags
, pVarResult
,
2369 pExcepInfo
, puArgErr
);
2371 case DISPID_INSTALLER_LASTERRORRECORD
:
2372 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2373 pVarResult
, pExcepInfo
,
2376 case DISPID_INSTALLER_REGISTRYVALUE
:
2377 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2378 pVarResult
, pExcepInfo
,
2381 case DISPID_INSTALLER_ENVIRONMENT
:
2382 return InstallerImpl_Environment(wFlags
, pDispParams
,
2383 pVarResult
, pExcepInfo
, puArgErr
);
2385 case DISPID_INSTALLER_FILEATTRIBUTES
:
2386 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2387 pVarResult
, pExcepInfo
,
2390 case DISPID_INSTALLER_FILESIZE
:
2391 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2392 pVarResult
, pExcepInfo
, puArgErr
);
2394 case DISPID_INSTALLER_FILEVERSION
:
2395 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2396 pVarResult
, pExcepInfo
, puArgErr
);
2398 case DISPID_INSTALLER_PRODUCTSTATE
:
2399 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2400 pVarResult
, pExcepInfo
, puArgErr
);
2402 case DISPID_INSTALLER_PRODUCTINFO
:
2403 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2404 pVarResult
, pExcepInfo
, puArgErr
);
2406 case DISPID_INSTALLER_PRODUCTS
:
2407 return InstallerImpl_Products(wFlags
, pDispParams
,
2408 pVarResult
, pExcepInfo
, puArgErr
);
2410 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2411 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2412 pVarResult
, pExcepInfo
,
2416 return DISP_E_MEMBERNOTFOUND
;
2420 HRESULT
create_msiserver(IUnknown
*outer
, void **ppObj
)
2422 AutomationObject
*installer
;
2424 TRACE("(%p %p)\n", outer
, ppObj
);
2427 return CLASS_E_NOAGGREGATION
;
2429 installer
= msi_alloc(sizeof(AutomationObject
));
2430 if (!installer
) return E_OUTOFMEMORY
;
2432 init_automation_object(installer
, 0, Installer_tid
);
2434 *ppObj
= &installer
->IDispatch_iface
;
2439 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2441 SessionObject
*session
;
2443 session
= msi_alloc(sizeof(SessionObject
));
2444 if (!session
) return E_OUTOFMEMORY
;
2446 init_automation_object(&session
->autoobj
, msiHandle
, Session_tid
);
2448 session
->installer
= installer
;
2449 *disp
= &session
->autoobj
.IDispatch_iface
;
2454 static HRESULT
create_database(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2456 AutomationObject
*database
;
2458 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2460 database
= msi_alloc(sizeof(AutomationObject
));
2461 if (!database
) return E_OUTOFMEMORY
;
2463 init_automation_object(database
, msiHandle
, Database_tid
);
2465 *dispatch
= &database
->IDispatch_iface
;
2470 static HRESULT
create_view(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2472 AutomationObject
*view
;
2474 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2476 view
= msi_alloc(sizeof(AutomationObject
));
2477 if (!view
) return E_OUTOFMEMORY
;
2479 init_automation_object(view
, msiHandle
, View_tid
);
2481 *dispatch
= &view
->IDispatch_iface
;
2486 static HRESULT
create_summaryinfo(MSIHANDLE msiHandle
, IDispatch
**disp
)
2488 AutomationObject
*info
;
2490 info
= msi_alloc(sizeof(*info
));
2491 if (!info
) return E_OUTOFMEMORY
;
2493 init_automation_object(info
, msiHandle
, SummaryInfo_tid
);
2495 *disp
= &info
->IDispatch_iface
;