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)->(%u, %ld, %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, %u, %ld, %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)->(%ld, %s, %ld, %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 %ld, %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 %ld, %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 %ld\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 %#lx, %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)->(%lu, %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)->(%lu, %#lx, %p, %p, %p, %p, %p)\n", iface
, This
, iti
, dwFlags
, ti
, pdwTIFlags
, pcdispidReserved
,
504 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 void init_automation_object(AutomationObject
*This
, MSIHANDLE msiHandle
, tid_t tid
)
546 TRACE("%p, %lu, %s\n", This
, msiHandle
, debugstr_guid(get_riid_from_tid(tid
)));
548 This
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
549 This
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
551 This
->msiHandle
= msiHandle
;
556 * ListEnumerator methods
559 static inline ListEnumerator
*impl_from_IEnumVARIANT(IEnumVARIANT
* iface
)
561 return CONTAINING_RECORD(iface
, ListEnumerator
, IEnumVARIANT_iface
);
564 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
,
567 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
569 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
571 if (ppvObject
== NULL
)
576 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
577 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
579 *ppvObject
= &This
->IEnumVARIANT_iface
;
583 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
584 return E_NOINTERFACE
;
587 IEnumVARIANT_AddRef(iface
);
591 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
593 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
595 TRACE("(%p/%p)\n", iface
, This
);
597 return InterlockedIncrement(&This
->ref
);
600 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
602 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
603 ULONG ref
= InterlockedDecrement(&This
->ref
);
605 TRACE("(%p/%p)\n", iface
, This
);
609 if (This
->list
) IDispatch_Release(&This
->list
->autoobj
.IDispatch_iface
);
616 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
* rgVar
,
619 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
622 TRACE("%p, %lu, %p, %p\n", iface
, celt
, rgVar
, fetched
);
624 if (fetched
) *fetched
= 0;
629 for (local
= 0; local
< celt
; local
++)
630 VariantInit(&rgVar
[local
]);
632 for (i
= This
->pos
, local
= 0; i
< This
->list
->count
&& local
< celt
; i
++, local
++)
633 VariantCopy(&rgVar
[local
], &This
->list
->data
[i
]);
635 if (fetched
) *fetched
= local
;
638 return (local
< celt
) ? S_FALSE
: S_OK
;
641 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
643 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
645 TRACE("%p, %lu\n", iface
, celt
);
648 if (This
->pos
>= This
->list
->count
)
650 This
->pos
= This
->list
->count
;
657 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
659 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
661 TRACE("(%p)\n", iface
);
667 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
669 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
672 TRACE("(%p,%p)\n", iface
, ppEnum
);
678 hr
= create_list_enumerator(This
->list
, (LPVOID
*)ppEnum
);
681 if (*ppEnum
) IEnumVARIANT_Release(*ppEnum
);
688 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
690 ListEnumerator_QueryInterface
,
691 ListEnumerator_AddRef
,
692 ListEnumerator_Release
,
695 ListEnumerator_Reset
,
699 /* Create a list enumerator, placing the result in the pointer ppObj. */
700 static HRESULT
create_list_enumerator(ListObject
*list
, void **ppObj
)
702 ListEnumerator
*object
;
704 TRACE("(%p, %p)\n", list
, ppObj
);
706 object
= msi_alloc(sizeof(ListEnumerator
));
708 /* Set all the VTable references */
709 object
->IEnumVARIANT_iface
.lpVtbl
= &ListEnumerator_Vtbl
;
712 /* Store data that was passed */
715 if (list
) IDispatch_AddRef(&list
->autoobj
.IDispatch_iface
);
722 * Individual Object Invocation Functions
725 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
726 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
727 using DispGetParam/VariantChangeType. */
728 static HRESULT
DispGetParam_CopyOnly(
729 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
730 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
731 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
733 /* position is counted backwards */
736 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
737 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
738 if (*position
< pdispparams
->cArgs
) {
739 /* positional arg? */
740 pos
= pdispparams
->cArgs
- *position
- 1;
742 /* FIXME: is this how to handle named args? */
743 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
744 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
746 if (pos
==pdispparams
->cNamedArgs
)
747 return DISP_E_PARAMNOTFOUND
;
750 return VariantCopyInd(pvarResult
,
751 &pdispparams
->rgvarg
[pos
]);
754 static HRESULT
summaryinfo_invoke(
755 AutomationObject
* This
,
760 DISPPARAMS
* pDispParams
,
762 EXCEPINFO
* pExcepInfo
,
766 VARIANTARG varg0
, varg1
;
767 FILETIME ft
, ftlocal
;
774 switch (dispIdMember
)
776 case DISPID_SUMMARYINFO_PROPERTY
:
777 if (wFlags
& DISPATCH_PROPERTYGET
)
785 static WCHAR szEmpty
[] = L
"";
787 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
788 if (FAILED(hr
)) return hr
;
789 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
790 &ft
, szEmpty
, &size
);
791 if (ret
!= ERROR_SUCCESS
&&
792 ret
!= ERROR_MORE_DATA
)
794 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
795 return DISP_E_EXCEPTION
;
805 V_VT(pVarResult
) = VT_I4
;
806 V_I4(pVarResult
) = value
;
810 if (!(str
= msi_alloc(++size
* sizeof(WCHAR
))))
811 ERR("Out of memory\n");
812 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
813 NULL
, str
, &size
)) != ERROR_SUCCESS
)
814 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
817 V_VT(pVarResult
) = VT_BSTR
;
818 V_BSTR(pVarResult
) = SysAllocString(str
);
824 FileTimeToLocalFileTime(&ft
, &ftlocal
);
825 FileTimeToSystemTime(&ftlocal
, &st
);
826 SystemTimeToVariantTime(&st
, &date
);
828 V_VT(pVarResult
) = VT_DATE
;
829 V_DATE(pVarResult
) = date
;
833 ERR("Unhandled variant type %d\n", type
);
836 else if (wFlags
& DISPATCH_PROPERTYPUT
)
838 UINT posValue
= DISPID_PROPERTYPUT
;
840 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
841 if (FAILED(hr
)) return hr
;
842 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
845 *puArgErr
= posValue
;
849 switch (V_VT(&varg1
))
853 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
857 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
858 SystemTimeToFileTime(&st
, &ftlocal
);
859 LocalFileTimeToFileTime(&ftlocal
, &ft
);
860 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
864 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
868 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
869 VariantClear(&varg1
);
870 return DISP_E_EXCEPTION
;
873 if (ret
!= ERROR_SUCCESS
)
875 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
876 return DISP_E_EXCEPTION
;
879 else return DISP_E_MEMBERNOTFOUND
;
882 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
883 if (wFlags
& DISPATCH_PROPERTYGET
) {
885 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
886 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
889 V_VT(pVarResult
) = VT_I4
;
890 V_I4(pVarResult
) = count
;
893 else return DISP_E_MEMBERNOTFOUND
;
897 return DISP_E_MEMBERNOTFOUND
;
900 VariantClear(&varg1
);
901 VariantClear(&varg0
);
906 static HRESULT
record_invoke(
907 AutomationObject
* This
,
912 DISPPARAMS
* pDispParams
,
914 EXCEPINFO
* pExcepInfo
,
920 VARIANTARG varg0
, varg1
;
926 switch (dispIdMember
)
928 case DISPID_RECORD_FIELDCOUNT
:
929 if (wFlags
& DISPATCH_PROPERTYGET
) {
930 V_VT(pVarResult
) = VT_I4
;
931 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
933 else return DISP_E_MEMBERNOTFOUND
;
936 case DISPID_RECORD_STRINGDATA
:
937 if (wFlags
& DISPATCH_PROPERTYGET
) {
938 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
939 if (FAILED(hr
)) return hr
;
940 V_VT(pVarResult
) = VT_BSTR
;
941 V_BSTR(pVarResult
) = NULL
;
942 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
944 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
945 ERR("Out of memory\n");
946 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
947 V_BSTR(pVarResult
) = SysAllocString(szString
);
950 if (ret
!= ERROR_SUCCESS
)
951 ERR("MsiRecordGetString returned %d\n", ret
);
952 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
953 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
954 if (FAILED(hr
)) return hr
;
955 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
956 if (FAILED(hr
)) return hr
;
957 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
959 VariantClear(&varg1
);
960 ERR("MsiRecordSetString returned %d\n", ret
);
961 return DISP_E_EXCEPTION
;
964 else return DISP_E_MEMBERNOTFOUND
;
967 case DISPID_RECORD_INTEGERDATA
:
968 if (wFlags
& DISPATCH_PROPERTYGET
) {
969 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
970 if (FAILED(hr
)) return hr
;
971 V_VT(pVarResult
) = VT_I4
;
972 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
973 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
974 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
975 if (FAILED(hr
)) return hr
;
976 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
977 if (FAILED(hr
)) return hr
;
978 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
980 ERR("MsiRecordSetInteger returned %d\n", ret
);
981 return DISP_E_EXCEPTION
;
984 else return DISP_E_MEMBERNOTFOUND
;
988 return DISP_E_MEMBERNOTFOUND
;
991 VariantClear(&varg1
);
992 VariantClear(&varg0
);
997 static HRESULT
create_record(MSIHANDLE msiHandle
, IDispatch
**disp
)
999 AutomationObject
*record
;
1001 record
= msi_alloc(sizeof(*record
));
1002 if (!record
) return E_OUTOFMEMORY
;
1004 init_automation_object(record
, msiHandle
, Record_tid
);
1006 *disp
= &record
->IDispatch_iface
;
1011 static HRESULT
list_invoke(
1012 AutomationObject
* This
,
1013 DISPID dispIdMember
,
1017 DISPPARAMS
* pDispParams
,
1018 VARIANT
* pVarResult
,
1019 EXCEPINFO
* pExcepInfo
,
1022 ListObject
*list
= CONTAINING_RECORD(This
, ListObject
, autoobj
);
1023 IUnknown
*pUnk
= NULL
;
1026 switch (dispIdMember
)
1028 case DISPID_LIST__NEWENUM
:
1029 if (wFlags
& DISPATCH_METHOD
) {
1030 V_VT(pVarResult
) = VT_UNKNOWN
;
1031 if (SUCCEEDED(hr
= create_list_enumerator(list
, (LPVOID
*)&pUnk
)))
1032 V_UNKNOWN(pVarResult
) = pUnk
;
1034 ERR("failed to create IEnumVARIANT object, hresult %#lx\n", hr
);
1036 else return DISP_E_MEMBERNOTFOUND
;
1039 case DISPID_LIST_ITEM
:
1040 if (wFlags
& DISPATCH_PROPERTYGET
) {
1043 VariantInit(&index
);
1044 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &index
, puArgErr
);
1045 if (FAILED(hr
)) return hr
;
1046 if (V_I4(&index
) < 0 || V_I4(&index
) >= list
->count
)
1047 return DISP_E_BADINDEX
;
1048 VariantCopy(pVarResult
, &list
->data
[V_I4(&index
)]);
1050 else return DISP_E_MEMBERNOTFOUND
;
1053 case DISPID_LIST_COUNT
:
1054 if (wFlags
& DISPATCH_PROPERTYGET
) {
1055 V_VT(pVarResult
) = VT_I4
;
1056 V_I4(pVarResult
) = list
->count
;
1058 else return DISP_E_MEMBERNOTFOUND
;
1062 return DISP_E_MEMBERNOTFOUND
;
1068 static void list_free(AutomationObject
*This
)
1070 ListObject
*list
= CONTAINING_RECORD(This
, ListObject
, autoobj
);
1073 for (i
= 0; i
< list
->count
; i
++)
1074 VariantClear(&list
->data
[i
]);
1075 msi_free(list
->data
);
1078 static HRESULT
get_products_count(const WCHAR
*product
, int *len
)
1084 WCHAR dataW
[GUID_SIZE
];
1087 /* all or related only */
1089 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1091 ret
= MsiEnumProductsW(i
, dataW
);
1093 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1095 if (ret
!= ERROR_SUCCESS
)
1096 return DISP_E_EXCEPTION
;
1106 static HRESULT
create_list(const WCHAR
*product
, IDispatch
**dispatch
)
1112 list
= msi_alloc_zero(sizeof(ListObject
));
1113 if (!list
) return E_OUTOFMEMORY
;
1115 init_automation_object(&list
->autoobj
, 0, StringList_tid
);
1117 *dispatch
= &list
->autoobj
.IDispatch_iface
;
1119 hr
= get_products_count(product
, &list
->count
);
1122 IDispatch_Release(*dispatch
);
1126 list
->data
= msi_alloc(list
->count
*sizeof(VARIANT
));
1129 IDispatch_Release(*dispatch
);
1130 return E_OUTOFMEMORY
;
1133 for (i
= 0; i
< list
->count
; i
++)
1135 WCHAR dataW
[GUID_SIZE
];
1138 /* all or related only */
1140 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1142 ret
= MsiEnumProductsW(i
, dataW
);
1144 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1146 V_VT(&list
->data
[i
]) = VT_BSTR
;
1147 V_BSTR(&list
->data
[i
]) = SysAllocString(dataW
);
1153 static HRESULT
view_invoke(
1154 AutomationObject
* This
,
1155 DISPID dispIdMember
,
1159 DISPPARAMS
* pDispParams
,
1160 VARIANT
* pVarResult
,
1161 EXCEPINFO
* pExcepInfo
,
1164 MSIHANDLE msiHandle
;
1166 VARIANTARG varg0
, varg1
;
1169 VariantInit(&varg0
);
1170 VariantInit(&varg1
);
1172 switch (dispIdMember
)
1174 case DISPID_VIEW_EXECUTE
:
1175 if (wFlags
& DISPATCH_METHOD
)
1177 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1178 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1179 MsiViewExecute(This
->msiHandle
, ((AutomationObject
*)V_DISPATCH(&varg0
))->msiHandle
);
1181 MsiViewExecute(This
->msiHandle
, 0);
1183 else return DISP_E_MEMBERNOTFOUND
;
1186 case DISPID_VIEW_FETCH
:
1187 if (wFlags
& DISPATCH_METHOD
)
1189 V_VT(pVarResult
) = VT_DISPATCH
;
1190 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1192 if (FAILED(hr
= create_record(msiHandle
, &V_DISPATCH(pVarResult
))))
1193 ERR("failed to create Record object, hresult %#lx\n", hr
);
1195 else if (ret
== ERROR_NO_MORE_ITEMS
)
1196 V_DISPATCH(pVarResult
) = NULL
;
1199 ERR("MsiViewFetch returned %d\n", ret
);
1200 return DISP_E_EXCEPTION
;
1203 else return DISP_E_MEMBERNOTFOUND
;
1206 case DISPID_VIEW_MODIFY
:
1207 if (wFlags
& DISPATCH_METHOD
)
1209 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1210 if (FAILED(hr
)) return hr
;
1211 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1212 if (FAILED(hr
)) return hr
;
1213 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1214 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1216 VariantClear(&varg1
);
1217 ERR("MsiViewModify returned %d\n", ret
);
1218 return DISP_E_EXCEPTION
;
1221 else return DISP_E_MEMBERNOTFOUND
;
1224 case DISPID_VIEW_CLOSE
:
1225 if (wFlags
& DISPATCH_METHOD
)
1227 MsiViewClose(This
->msiHandle
);
1229 else return DISP_E_MEMBERNOTFOUND
;
1233 return DISP_E_MEMBERNOTFOUND
;
1236 VariantClear(&varg1
);
1237 VariantClear(&varg0
);
1242 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1243 DISPPARAMS
* pDispParams
,
1244 VARIANT
* pVarResult
,
1245 EXCEPINFO
* pExcepInfo
,
1248 if (!(wFlags
& DISPATCH_METHOD
))
1249 return DISP_E_MEMBERNOTFOUND
;
1253 VariantInit(pVarResult
);
1257 HRESULT
database_invoke(
1258 AutomationObject
* This
,
1259 DISPID dispIdMember
,
1263 DISPPARAMS
* pDispParams
,
1264 VARIANT
* pVarResult
,
1265 EXCEPINFO
* pExcepInfo
,
1268 IDispatch
*dispatch
= NULL
;
1269 MSIHANDLE msiHandle
;
1271 VARIANTARG varg0
, varg1
;
1274 VariantInit(&varg0
);
1275 VariantInit(&varg1
);
1277 switch (dispIdMember
)
1279 case DISPID_DATABASE_SUMMARYINFORMATION
:
1280 if (wFlags
& DISPATCH_PROPERTYGET
)
1282 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1286 V_VT(pVarResult
) = VT_DISPATCH
;
1287 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1289 hr
= create_summaryinfo(msiHandle
, &dispatch
);
1291 V_DISPATCH(pVarResult
) = dispatch
;
1293 ERR("failed to create SummaryInfo object: %#lx\n", hr
);
1297 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1298 return DISP_E_EXCEPTION
;
1301 else return DISP_E_MEMBERNOTFOUND
;
1304 case DISPID_DATABASE_OPENVIEW
:
1305 if (wFlags
& DISPATCH_METHOD
)
1307 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1308 if (FAILED(hr
)) return hr
;
1309 V_VT(pVarResult
) = VT_DISPATCH
;
1310 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1312 if (SUCCEEDED(hr
= create_view(msiHandle
, &dispatch
)))
1313 V_DISPATCH(pVarResult
) = dispatch
;
1315 ERR("failed to create View object, hresult %#lx\n", hr
);
1319 VariantClear(&varg0
);
1320 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1321 return DISP_E_EXCEPTION
;
1324 else return DISP_E_MEMBERNOTFOUND
;
1327 case DISPID_INSTALLER_LASTERRORRECORD
:
1328 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1329 pVarResult
, pExcepInfo
,
1333 return DISP_E_MEMBERNOTFOUND
;
1336 VariantClear(&varg1
);
1337 VariantClear(&varg0
);
1342 static HRESULT
session_invoke(
1343 AutomationObject
* This
,
1344 DISPID dispIdMember
,
1348 DISPPARAMS
* pDispParams
,
1349 VARIANT
* pVarResult
,
1350 EXCEPINFO
* pExcepInfo
,
1353 SessionObject
*session
= CONTAINING_RECORD(This
, SessionObject
, autoobj
);
1356 MSIHANDLE msiHandle
;
1359 INSTALLSTATE iInstalled
, iAction
;
1360 VARIANTARG varg0
, varg1
;
1363 VariantInit(&varg0
);
1364 VariantInit(&varg1
);
1366 switch (dispIdMember
)
1368 case DISPID_SESSION_INSTALLER
:
1369 if (wFlags
& DISPATCH_PROPERTYGET
) {
1370 V_VT(pVarResult
) = VT_DISPATCH
;
1371 IDispatch_AddRef(session
->installer
);
1372 V_DISPATCH(pVarResult
) = session
->installer
;
1374 else return DISP_E_MEMBERNOTFOUND
;
1377 case DISPID_SESSION_PROPERTY
:
1378 if (wFlags
& DISPATCH_PROPERTYGET
) {
1379 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1380 if (FAILED(hr
)) return hr
;
1381 V_VT(pVarResult
) = VT_BSTR
;
1382 V_BSTR(pVarResult
) = NULL
;
1383 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1385 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1386 ERR("Out of memory\n");
1387 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1388 V_BSTR(pVarResult
) = SysAllocString(szString
);
1391 if (ret
!= ERROR_SUCCESS
)
1392 ERR("MsiGetProperty returned %d\n", ret
);
1393 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1394 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1395 if (FAILED(hr
)) return hr
;
1396 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1398 VariantClear(&varg0
);
1401 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1403 VariantClear(&varg0
);
1404 VariantClear(&varg1
);
1405 ERR("MsiSetProperty returned %d\n", ret
);
1406 return DISP_E_EXCEPTION
;
1409 else return DISP_E_MEMBERNOTFOUND
;
1412 case DISPID_SESSION_LANGUAGE
:
1413 if (wFlags
& DISPATCH_PROPERTYGET
) {
1414 langId
= MsiGetLanguage(This
->msiHandle
);
1415 V_VT(pVarResult
) = VT_I4
;
1416 V_I4(pVarResult
) = langId
;
1418 else return DISP_E_MEMBERNOTFOUND
;
1421 case DISPID_SESSION_MODE
:
1422 if (wFlags
& DISPATCH_PROPERTYGET
) {
1423 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1424 if (FAILED(hr
)) return hr
;
1425 V_VT(pVarResult
) = VT_BOOL
;
1426 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
)) ? VARIANT_TRUE
: VARIANT_FALSE
;
1427 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1428 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1429 if (FAILED(hr
)) return hr
;
1430 hr
= DispGetParam(pDispParams
, 1, VT_BOOL
, &varg1
, puArgErr
);
1431 if (FAILED(hr
)) return hr
;
1432 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1434 ERR("MsiSetMode returned %d\n", ret
);
1435 return DISP_E_EXCEPTION
;
1438 else return DISP_E_MEMBERNOTFOUND
;
1441 case DISPID_SESSION_DATABASE
:
1442 if (wFlags
& DISPATCH_PROPERTYGET
) {
1443 V_VT(pVarResult
) = VT_DISPATCH
;
1444 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1446 IDispatch
*dispatch
;
1448 if (SUCCEEDED(hr
= create_database(msiHandle
, &dispatch
)))
1449 V_DISPATCH(pVarResult
) = dispatch
;
1451 ERR("failed to create Database object, hresult %#lx\n", hr
);
1455 ERR("MsiGetActiveDatabase failed\n");
1456 return DISP_E_EXCEPTION
;
1459 else return DISP_E_MEMBERNOTFOUND
;
1462 case DISPID_SESSION_DOACTION
:
1463 if (wFlags
& DISPATCH_METHOD
) {
1464 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1465 if (FAILED(hr
)) return hr
;
1466 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1467 V_VT(pVarResult
) = VT_I4
;
1470 case ERROR_FUNCTION_NOT_CALLED
:
1471 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1474 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1476 case ERROR_INSTALL_USEREXIT
:
1477 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1479 case ERROR_INSTALL_FAILURE
:
1480 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1482 case ERROR_INSTALL_SUSPEND
:
1483 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1485 case ERROR_MORE_DATA
:
1486 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1488 case ERROR_INVALID_HANDLE_STATE
:
1489 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1491 case ERROR_INVALID_DATA
:
1492 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1495 VariantClear(&varg0
);
1496 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1497 return DISP_E_EXCEPTION
;
1500 else return DISP_E_MEMBERNOTFOUND
;
1503 case DISPID_SESSION_EVALUATECONDITION
:
1504 if (wFlags
& DISPATCH_METHOD
) {
1505 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1506 if (FAILED(hr
)) return hr
;
1507 V_VT(pVarResult
) = VT_I4
;
1508 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1510 else return DISP_E_MEMBERNOTFOUND
;
1513 case DISPID_SESSION_MESSAGE
:
1514 if(!(wFlags
& DISPATCH_METHOD
))
1515 return DISP_E_MEMBERNOTFOUND
;
1517 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1518 if (FAILED(hr
)) return hr
;
1519 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1520 if (FAILED(hr
)) return hr
;
1522 V_VT(pVarResult
) = VT_I4
;
1524 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1527 case DISPID_SESSION_SETINSTALLLEVEL
:
1528 if (wFlags
& DISPATCH_METHOD
) {
1529 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1530 if (FAILED(hr
)) return hr
;
1531 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1533 ERR("MsiSetInstallLevel returned %d\n", ret
);
1534 return DISP_E_EXCEPTION
;
1537 else return DISP_E_MEMBERNOTFOUND
;
1540 case DISPID_SESSION_FEATURECURRENTSTATE
:
1541 if (wFlags
& DISPATCH_PROPERTYGET
) {
1542 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1543 if (FAILED(hr
)) return hr
;
1544 V_VT(pVarResult
) = VT_I4
;
1545 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1546 V_I4(pVarResult
) = iInstalled
;
1549 ERR("MsiGetFeatureState returned %d\n", ret
);
1550 V_I4(pVarResult
) = msiInstallStateUnknown
;
1553 else return DISP_E_MEMBERNOTFOUND
;
1556 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1557 if (wFlags
& DISPATCH_PROPERTYGET
) {
1558 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1559 if (FAILED(hr
)) return hr
;
1560 V_VT(pVarResult
) = VT_I4
;
1561 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1562 V_I4(pVarResult
) = iAction
;
1565 ERR("MsiGetFeatureState returned %d\n", ret
);
1566 V_I4(pVarResult
) = msiInstallStateUnknown
;
1568 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1569 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1570 if (FAILED(hr
)) return hr
;
1571 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1573 VariantClear(&varg0
);
1576 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1578 VariantClear(&varg0
);
1579 ERR("MsiSetFeatureState returned %d\n", ret
);
1580 return DISP_E_EXCEPTION
;
1583 else return DISP_E_MEMBERNOTFOUND
;
1587 return DISP_E_MEMBERNOTFOUND
;
1590 VariantClear(&varg1
);
1591 VariantClear(&varg0
);
1596 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1597 * registry value type. Used by Installer::RegistryValue. */
1598 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1600 WCHAR
*szString
= (WCHAR
*)lpData
;
1601 LPWSTR szNewString
= NULL
;
1602 DWORD dwNewSize
= 0;
1607 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1608 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1609 idx
= (dwSize
/sizeof(WCHAR
))-1;
1610 while (idx
>= 0 && !szString
[idx
]) idx
--;
1611 for (; idx
>= 0; idx
--)
1612 if (!szString
[idx
]) szString
[idx
] = '\n';
1615 V_VT(pVarResult
) = VT_BSTR
;
1616 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1620 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1621 ERR("ExpandEnvironmentStrings returned error %lu\n", GetLastError());
1622 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1623 ERR("Out of memory\n");
1624 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1625 ERR("ExpandEnvironmentStrings returned error %lu\n", GetLastError());
1628 V_VT(pVarResult
) = VT_BSTR
;
1629 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1631 msi_free(szNewString
);
1635 V_VT(pVarResult
) = VT_I4
;
1636 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1640 V_VT(pVarResult
) = VT_BSTR
;
1641 V_BSTR(pVarResult
) = SysAllocString(L
"(REG_\?\?)"); /* Weird string, don't know why native returns it */
1645 V_VT(pVarResult
) = VT_BSTR
;
1646 V_BSTR(pVarResult
) = SysAllocString(L
"(REG_BINARY)");
1650 V_VT(pVarResult
) = VT_EMPTY
;
1654 FIXME("Unhandled registry value type %lu\n", dwType
);
1658 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1659 DISPPARAMS
* pDispParams
,
1660 VARIANT
* pVarResult
,
1661 EXCEPINFO
* pExcepInfo
,
1668 if (!(wFlags
& DISPATCH_METHOD
))
1669 return DISP_E_MEMBERNOTFOUND
;
1671 VariantInit(&varg0
);
1672 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1676 V_VT(pVarResult
) = VT_DISPATCH
;
1678 hrec
= MsiCreateRecord(V_I4(&varg0
));
1680 return DISP_E_EXCEPTION
;
1682 return create_record(hrec
, &V_DISPATCH(pVarResult
));
1685 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1687 DISPPARAMS
* pDispParams
,
1688 VARIANT
* pVarResult
,
1689 EXCEPINFO
* pExcepInfo
,
1695 IDispatch
* dispatch
;
1696 VARIANTARG varg0
, varg1
;
1698 if (!(wFlags
& DISPATCH_METHOD
))
1699 return DISP_E_MEMBERNOTFOUND
;
1701 if (pDispParams
->cArgs
== 0)
1702 return DISP_E_TYPEMISMATCH
;
1704 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1705 return DISP_E_TYPEMISMATCH
;
1707 VariantInit(&varg0
);
1708 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1712 VariantInit(&varg1
);
1713 if (pDispParams
->cArgs
== 2)
1715 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1721 V_VT(&varg1
) = VT_I4
;
1725 V_VT(pVarResult
) = VT_DISPATCH
;
1727 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1728 if (ret
!= ERROR_SUCCESS
)
1730 hr
= DISP_E_EXCEPTION
;
1734 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1736 V_DISPATCH(pVarResult
) = dispatch
;
1739 VariantClear(&varg0
);
1740 VariantClear(&varg1
);
1744 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1745 DISPPARAMS
* pDispParams
,
1746 VARIANT
* pVarResult
,
1747 EXCEPINFO
* pExcepInfo
,
1753 if (!(wFlags
& DISPATCH_METHOD
))
1754 return DISP_E_MEMBERNOTFOUND
;
1756 VariantInit(&varg0
);
1757 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1761 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1763 VariantInit(pVarResult
);
1765 VariantClear(&varg0
);
1769 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1770 DISPPARAMS
* pDispParams
,
1771 VARIANT
* pVarResult
,
1772 EXCEPINFO
* pExcepInfo
,
1778 IDispatch
* dispatch
;
1779 VARIANTARG varg0
, varg1
;
1781 if (!(wFlags
& DISPATCH_METHOD
))
1782 return DISP_E_MEMBERNOTFOUND
;
1784 VariantInit(&varg0
);
1785 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1789 VariantInit(&varg1
);
1790 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1794 V_VT(pVarResult
) = VT_DISPATCH
;
1796 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1797 if (ret
!= ERROR_SUCCESS
)
1799 hr
= DISP_E_EXCEPTION
;
1803 hr
= create_database(hdb
, &dispatch
);
1805 V_DISPATCH(pVarResult
) = dispatch
;
1808 VariantClear(&varg0
);
1809 VariantClear(&varg1
);
1813 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1814 DISPPARAMS
* pDispParams
,
1815 VARIANT
* pVarResult
,
1816 EXCEPINFO
* pExcepInfo
,
1822 IDispatch
*dispatch
;
1823 VARIANTARG varg0
, varg1
;
1825 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1826 return DISP_E_MEMBERNOTFOUND
;
1828 VariantInit(&varg1
);
1829 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1833 VariantInit(&varg0
);
1834 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1838 ret
= MsiGetSummaryInformationW(0, V_BSTR(&varg0
), V_I4(&varg1
), &hsuminfo
);
1839 VariantClear(&varg0
);
1840 if (ret
!= ERROR_SUCCESS
)
1841 return DISP_E_EXCEPTION
;
1843 hr
= create_summaryinfo(hsuminfo
, &dispatch
);
1847 V_VT(pVarResult
) = VT_DISPATCH
;
1848 V_DISPATCH(pVarResult
) = dispatch
;
1852 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1853 DISPPARAMS
* pDispParams
,
1854 VARIANT
* pVarResult
,
1855 EXCEPINFO
* pExcepInfo
,
1862 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1863 return DISP_E_MEMBERNOTFOUND
;
1865 if (wFlags
& DISPATCH_PROPERTYPUT
)
1867 VariantInit(&varg0
);
1868 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1872 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1873 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1874 return DISP_E_EXCEPTION
;
1876 else if (wFlags
& DISPATCH_PROPERTYGET
)
1878 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1879 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1880 return DISP_E_EXCEPTION
;
1882 V_VT(pVarResult
) = VT_I4
;
1883 V_I4(pVarResult
) = ui
;
1889 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1890 DISPPARAMS
* pDispParams
,
1891 VARIANT
* pVarResult
,
1892 EXCEPINFO
* pExcepInfo
,
1895 if (!(wFlags
& DISPATCH_METHOD
))
1896 return DISP_E_MEMBERNOTFOUND
;
1900 VariantInit(pVarResult
);
1904 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1905 DISPPARAMS
* pDispParams
,
1906 VARIANT
* pVarResult
,
1907 EXCEPINFO
* pExcepInfo
,
1912 VARIANTARG varg0
, varg1
;
1914 if (!(wFlags
& DISPATCH_METHOD
))
1915 return DISP_E_MEMBERNOTFOUND
;
1917 VariantInit(&varg0
);
1918 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1922 VariantInit(&varg1
);
1923 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1927 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1928 if (ret
!= ERROR_SUCCESS
)
1930 hr
= DISP_E_EXCEPTION
;
1935 VariantClear(&varg0
);
1936 VariantClear(&varg1
);
1940 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1941 VARIANT
* pVarResult
,
1942 EXCEPINFO
* pExcepInfo
,
1946 DLLVERSIONINFO verinfo
;
1947 WCHAR version
[MAX_PATH
];
1949 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1950 return DISP_E_MEMBERNOTFOUND
;
1952 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1953 hr
= DllGetVersion(&verinfo
);
1957 swprintf(version
, ARRAY_SIZE(version
), L
"%d.%d.%d.%d", verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1958 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1960 V_VT(pVarResult
) = VT_BSTR
;
1961 V_BSTR(pVarResult
) = SysAllocString(version
);
1965 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1966 DISPPARAMS
* pDispParams
,
1967 VARIANT
* pVarResult
,
1968 EXCEPINFO
* pExcepInfo
,
1971 if (!(wFlags
& DISPATCH_METHOD
))
1972 return DISP_E_MEMBERNOTFOUND
;
1976 VariantInit(pVarResult
);
1980 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
1981 DISPPARAMS
* pDispParams
,
1982 VARIANT
* pVarResult
,
1983 EXCEPINFO
* pExcepInfo
,
1991 LPWSTR szString
= NULL
;
1992 VARIANTARG varg0
, varg1
, varg2
;
1994 if (!(wFlags
& DISPATCH_METHOD
))
1995 return DISP_E_MEMBERNOTFOUND
;
1997 VariantInit(&varg0
);
1998 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
2002 VariantInit(&varg1
);
2003 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2007 /* Save valuePos so we can save puArgErr if we are unable to do our type
2011 VariantInit(&varg2
);
2012 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
2016 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
2017 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
2019 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
2022 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
2024 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2025 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
2027 hr
= DISP_E_BADINDEX
;
2031 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2032 switch (V_VT(&varg2
))
2034 /* Return VT_BOOL clarifying whether registry key exists or not. */
2036 V_VT(pVarResult
) = VT_BOOL
;
2037 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2040 /* Return the value of specified key if it exists. */
2042 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
2043 NULL
, NULL
, NULL
, &size
);
2044 if (ret
!= ERROR_SUCCESS
)
2046 hr
= DISP_E_BADINDEX
;
2050 szString
= msi_alloc(size
);
2057 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
2058 &type
, (LPBYTE
)szString
, &size
);
2059 if (ret
!= ERROR_SUCCESS
)
2062 hr
= DISP_E_BADINDEX
;
2066 variant_from_registry_value(pVarResult
, type
,
2067 (LPBYTE
)szString
, size
);
2071 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2073 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
2076 if (hr
== DISP_E_TYPEMISMATCH
)
2077 *puArgErr
= posValue
;
2082 /* Retrieve class name or maximum value name or subkey name size. */
2084 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
2085 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2086 else if (V_I4(&varg2
) > 0)
2087 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
2088 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
2089 else /* V_I4(&varg2) < 0 */
2090 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
2091 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2093 if (ret
!= ERROR_SUCCESS
)
2096 szString
= msi_alloc(++size
* sizeof(WCHAR
));
2104 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
2105 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2106 else if (V_I4(&varg2
) > 0)
2107 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
2108 &size
, 0, 0, NULL
, NULL
);
2109 else /* V_I4(&varg2) < 0 */
2110 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
2112 if (ret
== ERROR_SUCCESS
)
2114 V_VT(pVarResult
) = VT_BSTR
;
2115 V_BSTR(pVarResult
) = SysAllocString(szString
);
2122 VariantClear(&varg0
);
2123 VariantClear(&varg1
);
2124 VariantClear(&varg2
);
2129 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2130 DISPPARAMS
* pDispParams
,
2131 VARIANT
* pVarResult
,
2132 EXCEPINFO
* pExcepInfo
,
2135 if (!(wFlags
& DISPATCH_METHOD
))
2136 return DISP_E_MEMBERNOTFOUND
;
2140 VariantInit(pVarResult
);
2144 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2145 DISPPARAMS
* pDispParams
,
2146 VARIANT
* pVarResult
,
2147 EXCEPINFO
* pExcepInfo
,
2150 if (!(wFlags
& DISPATCH_METHOD
))
2151 return DISP_E_MEMBERNOTFOUND
;
2155 VariantInit(pVarResult
);
2159 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2160 DISPPARAMS
* pDispParams
,
2161 VARIANT
* pVarResult
,
2162 EXCEPINFO
* pExcepInfo
,
2165 if (!(wFlags
& DISPATCH_METHOD
))
2166 return DISP_E_MEMBERNOTFOUND
;
2170 VariantInit(pVarResult
);
2174 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2175 DISPPARAMS
* pDispParams
,
2176 VARIANT
* pVarResult
,
2177 EXCEPINFO
* pExcepInfo
,
2180 if (!(wFlags
& DISPATCH_METHOD
))
2181 return DISP_E_MEMBERNOTFOUND
;
2185 VariantInit(pVarResult
);
2189 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2190 DISPPARAMS
* pDispParams
,
2191 VARIANT
* pVarResult
,
2192 EXCEPINFO
* pExcepInfo
,
2198 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2199 return DISP_E_MEMBERNOTFOUND
;
2201 VariantInit(&varg0
);
2202 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2206 V_VT(pVarResult
) = VT_I4
;
2207 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2209 VariantClear(&varg0
);
2213 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2214 DISPPARAMS
* pDispParams
,
2215 VARIANT
* pVarResult
,
2216 EXCEPINFO
* pExcepInfo
,
2223 VARIANTARG varg0
, varg1
;
2225 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2226 return DISP_E_MEMBERNOTFOUND
;
2228 VariantInit(&varg0
);
2229 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2233 VariantInit(&varg1
);
2234 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2238 V_VT(pVarResult
) = VT_BSTR
;
2239 V_BSTR(pVarResult
) = NULL
;
2241 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2242 if (ret
!= ERROR_SUCCESS
)
2244 hr
= DISP_E_EXCEPTION
;
2248 str
= msi_alloc(++size
* sizeof(WCHAR
));
2255 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2256 if (ret
!= ERROR_SUCCESS
)
2258 hr
= DISP_E_EXCEPTION
;
2262 V_BSTR(pVarResult
) = SysAllocString(str
);
2267 VariantClear(&varg0
);
2268 VariantClear(&varg1
);
2272 static HRESULT
InstallerImpl_Products(WORD flags
,
2273 DISPPARAMS
* pDispParams
,
2275 EXCEPINFO
* pExcepInfo
,
2278 IDispatch
*dispatch
;
2281 if (!(flags
& DISPATCH_PROPERTYGET
))
2282 return DISP_E_MEMBERNOTFOUND
;
2284 hr
= create_list(NULL
, &dispatch
);
2288 V_VT(result
) = VT_DISPATCH
;
2289 V_DISPATCH(result
) = dispatch
;
2294 static HRESULT
InstallerImpl_RelatedProducts(WORD flags
,
2295 DISPPARAMS
* pDispParams
,
2297 EXCEPINFO
* pExcepInfo
,
2300 IDispatch
* dispatch
;
2304 if (!(flags
& DISPATCH_PROPERTYGET
))
2305 return DISP_E_MEMBERNOTFOUND
;
2307 VariantInit(&related
);
2308 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &related
, puArgErr
);
2312 hr
= create_list(V_BSTR(&related
), &dispatch
);
2313 VariantClear(&related
);
2315 V_VT(result
) = VT_DISPATCH
;
2316 V_DISPATCH(result
) = dispatch
;
2321 static HRESULT
installer_invoke(
2322 AutomationObject
* This
,
2323 DISPID dispIdMember
,
2327 DISPPARAMS
* pDispParams
,
2328 VARIANT
* pVarResult
,
2329 EXCEPINFO
* pExcepInfo
,
2332 switch (dispIdMember
)
2334 case DISPID_INSTALLER_CREATERECORD
:
2335 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2336 pVarResult
, pExcepInfo
, puArgErr
);
2338 case DISPID_INSTALLER_OPENPACKAGE
:
2339 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2340 pVarResult
, pExcepInfo
, puArgErr
);
2342 case DISPID_INSTALLER_OPENPRODUCT
:
2343 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2344 pVarResult
, pExcepInfo
, puArgErr
);
2346 case DISPID_INSTALLER_OPENDATABASE
:
2347 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2348 pVarResult
, pExcepInfo
, puArgErr
);
2350 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2351 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2352 pVarResult
, pExcepInfo
,
2355 case DISPID_INSTALLER_UILEVEL
:
2356 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2357 pVarResult
, pExcepInfo
, puArgErr
);
2359 case DISPID_INSTALLER_ENABLELOG
:
2360 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2361 pVarResult
, pExcepInfo
, puArgErr
);
2363 case DISPID_INSTALLER_INSTALLPRODUCT
:
2364 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2365 pVarResult
, pExcepInfo
,
2368 case DISPID_INSTALLER_VERSION
:
2369 return InstallerImpl_Version(wFlags
, pVarResult
,
2370 pExcepInfo
, puArgErr
);
2372 case DISPID_INSTALLER_LASTERRORRECORD
:
2373 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2374 pVarResult
, pExcepInfo
,
2377 case DISPID_INSTALLER_REGISTRYVALUE
:
2378 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2379 pVarResult
, pExcepInfo
,
2382 case DISPID_INSTALLER_ENVIRONMENT
:
2383 return InstallerImpl_Environment(wFlags
, pDispParams
,
2384 pVarResult
, pExcepInfo
, puArgErr
);
2386 case DISPID_INSTALLER_FILEATTRIBUTES
:
2387 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2388 pVarResult
, pExcepInfo
,
2391 case DISPID_INSTALLER_FILESIZE
:
2392 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2393 pVarResult
, pExcepInfo
, puArgErr
);
2395 case DISPID_INSTALLER_FILEVERSION
:
2396 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2397 pVarResult
, pExcepInfo
, puArgErr
);
2399 case DISPID_INSTALLER_PRODUCTSTATE
:
2400 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2401 pVarResult
, pExcepInfo
, puArgErr
);
2403 case DISPID_INSTALLER_PRODUCTINFO
:
2404 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2405 pVarResult
, pExcepInfo
, puArgErr
);
2407 case DISPID_INSTALLER_PRODUCTS
:
2408 return InstallerImpl_Products(wFlags
, pDispParams
,
2409 pVarResult
, pExcepInfo
, puArgErr
);
2411 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2412 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2413 pVarResult
, pExcepInfo
,
2417 return DISP_E_MEMBERNOTFOUND
;
2421 HRESULT
create_msiserver(IUnknown
*outer
, void **ppObj
)
2423 AutomationObject
*installer
;
2425 TRACE("(%p %p)\n", outer
, ppObj
);
2428 return CLASS_E_NOAGGREGATION
;
2430 installer
= msi_alloc(sizeof(AutomationObject
));
2431 if (!installer
) return E_OUTOFMEMORY
;
2433 init_automation_object(installer
, 0, Installer_tid
);
2435 *ppObj
= &installer
->IDispatch_iface
;
2440 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2442 SessionObject
*session
;
2444 session
= msi_alloc(sizeof(SessionObject
));
2445 if (!session
) return E_OUTOFMEMORY
;
2447 init_automation_object(&session
->autoobj
, msiHandle
, Session_tid
);
2449 session
->installer
= installer
;
2450 *disp
= &session
->autoobj
.IDispatch_iface
;
2455 static HRESULT
create_database(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2457 AutomationObject
*database
;
2459 TRACE("%lu %p\n", msiHandle
, dispatch
);
2461 database
= msi_alloc(sizeof(AutomationObject
));
2462 if (!database
) return E_OUTOFMEMORY
;
2464 init_automation_object(database
, msiHandle
, Database_tid
);
2466 *dispatch
= &database
->IDispatch_iface
;
2471 static HRESULT
create_view(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2473 AutomationObject
*view
;
2475 TRACE("%lu %p\n", msiHandle
, dispatch
);
2477 view
= msi_alloc(sizeof(AutomationObject
));
2478 if (!view
) return E_OUTOFMEMORY
;
2480 init_automation_object(view
, msiHandle
, View_tid
);
2482 *dispatch
= &view
->IDispatch_iface
;
2487 static HRESULT
create_summaryinfo(MSIHANDLE msiHandle
, IDispatch
**disp
)
2489 AutomationObject
*info
;
2491 info
= msi_alloc(sizeof(*info
));
2492 if (!info
) return E_OUTOFMEMORY
;
2494 init_automation_object(info
, msiHandle
, SummaryInfo_tid
);
2496 *disp
= &info
->IDispatch_iface
;