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 static const WCHAR msiserverW
[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
99 hr
= LoadTypeLib(msiserverW
, &lib
);
101 ERR("Could not load msiserver.tlb\n");
106 if (InterlockedCompareExchangePointer((void**)&typelib
, lib
, NULL
))
107 ITypeLib_Release(lib
);
114 hr
= ITypeLib_GetTypeInfoOfGuid(typelib
, get_riid_from_tid(tid
), &ti
);
116 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid
)));
120 if(InterlockedCompareExchangePointer((void**)(typeinfos
+tid
), ti
, NULL
))
121 ITypeInfo_Release(ti
);
124 *typeinfo
= typeinfos
[tid
];
128 void release_typelib(void)
132 for (i
= 0; i
< ARRAY_SIZE(typeinfos
); i
++)
134 ITypeInfo_Release(typeinfos
[i
]);
137 ITypeLib_Release(typelib
);
141 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
142 * called from AutomationObject::Invoke.
144 struct AutomationObject
{
145 IDispatch IDispatch_iface
;
146 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface
;
149 /* type id for this class */
152 /* The MSI handle of the current object */
157 AutomationObject autoobj
;
162 static HRESULT
create_database(MSIHANDLE
, IDispatch
**);
163 static HRESULT
create_list_enumerator(ListObject
*, void**);
164 static HRESULT
create_summaryinfo(MSIHANDLE
, IDispatch
**);
165 static HRESULT
create_view(MSIHANDLE
, IDispatch
**);
167 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
169 IEnumVARIANT IEnumVARIANT_iface
;
172 /* Current position and pointer to AutomationObject that stores actual data */
178 AutomationObject autoobj
;
179 IDispatch
*installer
;
182 static inline AutomationObject
*impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
184 return CONTAINING_RECORD(iface
, AutomationObject
, IProvideMultipleClassInfo_iface
);
187 static inline AutomationObject
*impl_from_IDispatch( IDispatch
*iface
)
189 return CONTAINING_RECORD(iface
, AutomationObject
, IDispatch_iface
);
192 /* AutomationObject methods */
193 static HRESULT WINAPI
AutomationObject_QueryInterface(IDispatch
* iface
, REFIID riid
, void** ppvObject
)
195 AutomationObject
*This
= impl_from_IDispatch(iface
);
197 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
199 if (ppvObject
== NULL
)
204 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
205 IsEqualGUID(riid
, &IID_IDispatch
) ||
206 IsEqualGUID(riid
, get_riid_from_tid(This
->tid
)))
207 *ppvObject
= &This
->IDispatch_iface
;
208 else if (IsEqualGUID(riid
, &IID_IProvideClassInfo
) ||
209 IsEqualGUID(riid
, &IID_IProvideClassInfo2
) ||
210 IsEqualGUID(riid
, &IID_IProvideMultipleClassInfo
))
211 *ppvObject
= &This
->IProvideMultipleClassInfo_iface
;
214 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
215 return E_NOINTERFACE
;
218 IDispatch_AddRef(iface
);
223 static ULONG WINAPI
AutomationObject_AddRef(IDispatch
* iface
)
225 AutomationObject
*This
= impl_from_IDispatch(iface
);
227 TRACE("(%p/%p)\n", iface
, This
);
229 return InterlockedIncrement(&This
->ref
);
232 static ULONG WINAPI
AutomationObject_Release(IDispatch
* iface
)
234 AutomationObject
*This
= impl_from_IDispatch(iface
);
235 ULONG ref
= InterlockedDecrement(&This
->ref
);
237 TRACE("(%p/%p)\n", iface
, This
);
241 if (tid_ids
[This
->tid
].fn_free
) tid_ids
[This
->tid
].fn_free(This
);
242 MsiCloseHandle(This
->msiHandle
);
249 static HRESULT WINAPI
AutomationObject_GetTypeInfoCount(
253 AutomationObject
*This
= impl_from_IDispatch(iface
);
255 TRACE("(%p/%p)->(%p)\n", iface
, This
, pctinfo
);
260 static HRESULT WINAPI
AutomationObject_GetTypeInfo(
266 AutomationObject
*This
= impl_from_IDispatch(iface
);
269 TRACE("(%p/%p)->(%d,%d,%p)\n", iface
, This
, iTInfo
, lcid
, ppTInfo
);
271 hr
= get_typeinfo(This
->tid
, ppTInfo
);
275 ITypeInfo_AddRef(*ppTInfo
);
279 static HRESULT WINAPI
AutomationObject_GetIDsOfNames(
287 AutomationObject
*This
= impl_from_IDispatch(iface
);
291 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", iface
, This
,
292 debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
294 if (!IsEqualGUID(riid
, &IID_NULL
)) return E_INVALIDARG
;
296 hr
= get_typeinfo(This
->tid
, &ti
);
300 hr
= ITypeInfo_GetIDsOfNames(ti
, rgszNames
, cNames
, rgDispId
);
301 if (hr
== DISP_E_UNKNOWNNAME
)
304 for (idx
=0; idx
<cNames
; idx
++)
306 if (rgDispId
[idx
] == DISPID_UNKNOWN
)
307 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames
[idx
]), debugstr_guid(get_riid_from_tid(This
->tid
)));
313 /* Maximum number of allowed function parameters+1 */
314 #define MAX_FUNC_PARAMS 20
316 /* Some error checking is done here to simplify individual object function invocation */
317 static HRESULT WINAPI
AutomationObject_Invoke(
323 DISPPARAMS
* pDispParams
,
325 EXCEPINFO
* pExcepInfo
,
328 AutomationObject
*This
= impl_from_IDispatch(iface
);
330 unsigned int uArgErr
;
331 VARIANT varResultDummy
;
332 BSTR bstrName
= NULL
;
335 TRACE("(%p/%p)->(%d, %s, %d, %d, %p, %p, %p, %p)\n", iface
, This
,
336 dispIdMember
, debugstr_guid(riid
), lcid
, wFlags
,
337 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
339 if (!IsEqualIID(riid
, &IID_NULL
))
341 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
342 return DISP_E_UNKNOWNNAME
;
345 if (wFlags
& DISPATCH_PROPERTYGET
&& !pVarResult
)
347 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
348 return DISP_E_PARAMNOTOPTIONAL
;
351 /* This simplifies our individual object invocation functions */
352 if (puArgErr
== NULL
) puArgErr
= &uArgErr
;
353 if (pVarResult
== NULL
) pVarResult
= &varResultDummy
;
355 hr
= get_typeinfo(This
->tid
, &ti
);
359 /* Assume return type is void unless determined otherwise */
360 VariantInit(pVarResult
);
362 /* If we are tracing, we want to see the name of the member we are invoking */
365 ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
366 TRACE("Method %d, %s\n", dispIdMember
, debugstr_w(bstrName
));
369 hr
= tid_ids
[This
->tid
].fn_invoke(This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
371 if (hr
== DISP_E_MEMBERNOTFOUND
) {
372 if (bstrName
== NULL
) ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
373 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember
, debugstr_w(bstrName
), wFlags
,
374 debugstr_guid(get_riid_from_tid(This
->tid
)));
376 else if (pExcepInfo
&&
377 (hr
== DISP_E_PARAMNOTFOUND
||
378 hr
== DISP_E_EXCEPTION
)) {
379 static const WCHAR szComma
[] = { ',',0 };
380 static const WCHAR szExceptionSource
[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
381 WCHAR szExceptionDescription
[MAX_PATH
];
382 BSTR bstrParamNames
[MAX_FUNC_PARAMS
];
386 if (FAILED(ITypeInfo_GetNames(ti
, dispIdMember
, bstrParamNames
,
387 MAX_FUNC_PARAMS
, &namesNo
)))
389 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember
);
393 memset(szExceptionDescription
, 0, sizeof(szExceptionDescription
));
394 for (i
=0; i
<namesNo
; i
++)
396 if (bFirst
) bFirst
= FALSE
;
398 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], szComma
);
400 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], bstrParamNames
[i
]);
401 SysFreeString(bstrParamNames
[i
]);
404 memset(pExcepInfo
, 0, sizeof(EXCEPINFO
));
405 pExcepInfo
->wCode
= 1000;
406 pExcepInfo
->bstrSource
= SysAllocString(szExceptionSource
);
407 pExcepInfo
->bstrDescription
= SysAllocString(szExceptionDescription
);
408 hr
= DISP_E_EXCEPTION
;
412 /* Make sure we free the return variant if it is our dummy variant */
413 if (pVarResult
== &varResultDummy
) VariantClear(pVarResult
);
415 /* Free function name if we retrieved it */
416 SysFreeString(bstrName
);
418 TRACE("Returning 0x%08x, %s\n", hr
, SUCCEEDED(hr
) ? "ok" : "not ok");
423 static const struct IDispatchVtbl AutomationObjectVtbl
=
425 AutomationObject_QueryInterface
,
426 AutomationObject_AddRef
,
427 AutomationObject_Release
,
428 AutomationObject_GetTypeInfoCount
,
429 AutomationObject_GetTypeInfo
,
430 AutomationObject_GetIDsOfNames
,
431 AutomationObject_Invoke
435 * IProvideMultipleClassInfo methods
438 static HRESULT WINAPI
ProvideMultipleClassInfo_QueryInterface(
439 IProvideMultipleClassInfo
* iface
,
443 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
444 return IDispatch_QueryInterface(&This
->IDispatch_iface
, riid
, ppvoid
);
447 static ULONG WINAPI
ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo
* iface
)
449 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
450 return IDispatch_AddRef(&This
->IDispatch_iface
);
453 static ULONG WINAPI
ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo
* iface
)
455 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
456 return IDispatch_Release(&This
->IDispatch_iface
);
459 static HRESULT WINAPI
ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo
* iface
, ITypeInfo
** ppTI
)
461 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
464 TRACE("(%p/%p)->(%p)\n", iface
, This
, ppTI
);
466 hr
= get_typeinfo(This
->tid
, ppTI
);
468 ITypeInfo_AddRef(*ppTI
);
473 static HRESULT WINAPI
ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
* iface
, DWORD dwGuidKind
, GUID
* pGUID
)
475 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
476 TRACE("(%p/%p)->(%d,%s)\n", iface
, This
, dwGuidKind
, debugstr_guid(pGUID
));
478 if (dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
481 *pGUID
= *get_riid_from_tid(This
->tid
);
486 static HRESULT WINAPI
ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo
* iface
, ULONG
* pcti
)
488 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
490 TRACE("(%p/%p)->(%p)\n", iface
, This
, pcti
);
495 static HRESULT WINAPI
ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo
* iface
,
500 ULONG
* pcdispidReserved
,
504 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
506 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface
, This
, iti
, dwFlags
, ti
, pdwTIFlags
, pcdispidReserved
, piidPrimary
, piidSource
);
511 if (dwFlags
& MULTICLASSINFO_GETTYPEINFO
)
513 HRESULT hr
= get_typeinfo(This
->tid
, ti
);
517 ITypeInfo_AddRef(*ti
);
520 if (dwFlags
& MULTICLASSINFO_GETNUMRESERVEDDISPIDS
)
523 *pcdispidReserved
= 0;
526 if (dwFlags
& MULTICLASSINFO_GETIIDPRIMARY
)
527 *piidPrimary
= *get_riid_from_tid(This
->tid
);
529 if (dwFlags
& MULTICLASSINFO_GETIIDSOURCE
)
530 *piidSource
= *get_riid_from_tid(This
->tid
);
535 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl
=
537 ProvideMultipleClassInfo_QueryInterface
,
538 ProvideMultipleClassInfo_AddRef
,
539 ProvideMultipleClassInfo_Release
,
540 ProvideMultipleClassInfo_GetClassInfo
,
541 ProvideMultipleClassInfo_GetGUID
,
542 ProvideMultipleClassInfo_GetMultiTypeInfoCount
,
543 ProvideMultipleClassInfo_GetInfoOfIndex
546 static HRESULT
init_automation_object(AutomationObject
*This
, MSIHANDLE msiHandle
, tid_t tid
)
548 TRACE("(%p, %d, %s)\n", This
, msiHandle
, debugstr_guid(get_riid_from_tid(tid
)));
550 This
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
551 This
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
554 This
->msiHandle
= msiHandle
;
561 * ListEnumerator methods
564 static inline ListEnumerator
*impl_from_IEnumVARIANT(IEnumVARIANT
* iface
)
566 return CONTAINING_RECORD(iface
, ListEnumerator
, IEnumVARIANT_iface
);
569 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
,
572 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
574 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
576 if (ppvObject
== NULL
)
581 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
582 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
584 *ppvObject
= &This
->IEnumVARIANT_iface
;
588 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
589 return E_NOINTERFACE
;
592 IEnumVARIANT_AddRef(iface
);
596 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
598 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
600 TRACE("(%p/%p)\n", iface
, This
);
602 return InterlockedIncrement(&This
->ref
);
605 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
607 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
608 ULONG ref
= InterlockedDecrement(&This
->ref
);
610 TRACE("(%p/%p)\n", iface
, This
);
614 if (This
->list
) IDispatch_Release(&This
->list
->autoobj
.IDispatch_iface
);
621 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
* rgVar
,
624 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
627 TRACE("(%p, %uld, %p, %p)\n", iface
, celt
, rgVar
, fetched
);
629 if (fetched
) *fetched
= 0;
634 for (local
= 0; local
< celt
; local
++)
635 VariantInit(&rgVar
[local
]);
637 for (i
= This
->pos
, local
= 0; i
< This
->list
->count
&& local
< celt
; i
++, local
++)
638 VariantCopy(&rgVar
[local
], &This
->list
->data
[i
]);
640 if (fetched
) *fetched
= local
;
643 return (local
< celt
) ? S_FALSE
: S_OK
;
646 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
648 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
650 TRACE("(%p,%uld)\n", iface
, celt
);
653 if (This
->pos
>= This
->list
->count
)
655 This
->pos
= This
->list
->count
;
662 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
664 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
666 TRACE("(%p)\n", iface
);
672 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
674 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
677 TRACE("(%p,%p)\n", iface
, ppEnum
);
683 hr
= create_list_enumerator(This
->list
, (LPVOID
*)ppEnum
);
686 if (*ppEnum
) IEnumVARIANT_Release(*ppEnum
);
693 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
695 ListEnumerator_QueryInterface
,
696 ListEnumerator_AddRef
,
697 ListEnumerator_Release
,
700 ListEnumerator_Reset
,
704 /* Create a list enumerator, placing the result in the pointer ppObj. */
705 static HRESULT
create_list_enumerator(ListObject
*list
, void **ppObj
)
707 ListEnumerator
*object
;
709 TRACE("(%p, %p)\n", list
, ppObj
);
711 object
= msi_alloc(sizeof(ListEnumerator
));
713 /* Set all the VTable references */
714 object
->IEnumVARIANT_iface
.lpVtbl
= &ListEnumerator_Vtbl
;
717 /* Store data that was passed */
720 if (list
) IDispatch_AddRef(&list
->autoobj
.IDispatch_iface
);
727 * Individual Object Invocation Functions
730 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
731 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
732 using DispGetParam/VariantChangeType. */
733 static HRESULT
DispGetParam_CopyOnly(
734 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
735 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
736 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
738 /* position is counted backwards */
741 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
742 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
743 if (*position
< pdispparams
->cArgs
) {
744 /* positional arg? */
745 pos
= pdispparams
->cArgs
- *position
- 1;
747 /* FIXME: is this how to handle named args? */
748 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
749 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
751 if (pos
==pdispparams
->cNamedArgs
)
752 return DISP_E_PARAMNOTFOUND
;
755 return VariantCopyInd(pvarResult
,
756 &pdispparams
->rgvarg
[pos
]);
759 static HRESULT
summaryinfo_invoke(
760 AutomationObject
* This
,
765 DISPPARAMS
* pDispParams
,
767 EXCEPINFO
* pExcepInfo
,
771 VARIANTARG varg0
, varg1
;
772 FILETIME ft
, ftlocal
;
779 switch (dispIdMember
)
781 case DISPID_SUMMARYINFO_PROPERTY
:
782 if (wFlags
& DISPATCH_PROPERTYGET
)
790 static WCHAR szEmpty
[] = {0};
792 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
793 if (FAILED(hr
)) return hr
;
794 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
795 &ft
, szEmpty
, &size
);
796 if (ret
!= ERROR_SUCCESS
&&
797 ret
!= ERROR_MORE_DATA
)
799 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
800 return DISP_E_EXCEPTION
;
810 V_VT(pVarResult
) = VT_I4
;
811 V_I4(pVarResult
) = value
;
815 if (!(str
= msi_alloc(++size
* sizeof(WCHAR
))))
816 ERR("Out of memory\n");
817 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
818 NULL
, str
, &size
)) != ERROR_SUCCESS
)
819 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
822 V_VT(pVarResult
) = VT_BSTR
;
823 V_BSTR(pVarResult
) = SysAllocString(str
);
829 FileTimeToLocalFileTime(&ft
, &ftlocal
);
830 FileTimeToSystemTime(&ftlocal
, &st
);
831 SystemTimeToVariantTime(&st
, &date
);
833 V_VT(pVarResult
) = VT_DATE
;
834 V_DATE(pVarResult
) = date
;
838 ERR("Unhandled variant type %d\n", type
);
841 else if (wFlags
& DISPATCH_PROPERTYPUT
)
843 UINT posValue
= DISPID_PROPERTYPUT
;
845 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
846 if (FAILED(hr
)) return hr
;
847 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
850 *puArgErr
= posValue
;
854 switch (V_VT(&varg1
))
858 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
862 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
863 SystemTimeToFileTime(&st
, &ftlocal
);
864 LocalFileTimeToFileTime(&ftlocal
, &ft
);
865 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
869 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
873 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
874 VariantClear(&varg1
);
875 return DISP_E_EXCEPTION
;
878 if (ret
!= ERROR_SUCCESS
)
880 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
881 return DISP_E_EXCEPTION
;
884 else return DISP_E_MEMBERNOTFOUND
;
887 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
888 if (wFlags
& DISPATCH_PROPERTYGET
) {
890 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
891 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
894 V_VT(pVarResult
) = VT_I4
;
895 V_I4(pVarResult
) = count
;
898 else return DISP_E_MEMBERNOTFOUND
;
902 return DISP_E_MEMBERNOTFOUND
;
905 VariantClear(&varg1
);
906 VariantClear(&varg0
);
911 static HRESULT
record_invoke(
912 AutomationObject
* This
,
917 DISPPARAMS
* pDispParams
,
919 EXCEPINFO
* pExcepInfo
,
925 VARIANTARG varg0
, varg1
;
931 switch (dispIdMember
)
933 case DISPID_RECORD_FIELDCOUNT
:
934 if (wFlags
& DISPATCH_PROPERTYGET
) {
935 V_VT(pVarResult
) = VT_I4
;
936 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
938 else return DISP_E_MEMBERNOTFOUND
;
941 case DISPID_RECORD_STRINGDATA
:
942 if (wFlags
& DISPATCH_PROPERTYGET
) {
943 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
944 if (FAILED(hr
)) return hr
;
945 V_VT(pVarResult
) = VT_BSTR
;
946 V_BSTR(pVarResult
) = NULL
;
947 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
949 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
950 ERR("Out of memory\n");
951 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
952 V_BSTR(pVarResult
) = SysAllocString(szString
);
955 if (ret
!= ERROR_SUCCESS
)
956 ERR("MsiRecordGetString returned %d\n", ret
);
957 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
958 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
959 if (FAILED(hr
)) return hr
;
960 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
961 if (FAILED(hr
)) return hr
;
962 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
964 VariantClear(&varg1
);
965 ERR("MsiRecordSetString returned %d\n", ret
);
966 return DISP_E_EXCEPTION
;
969 else return DISP_E_MEMBERNOTFOUND
;
972 case DISPID_RECORD_INTEGERDATA
:
973 if (wFlags
& DISPATCH_PROPERTYGET
) {
974 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
975 if (FAILED(hr
)) return hr
;
976 V_VT(pVarResult
) = VT_I4
;
977 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
978 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
979 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
980 if (FAILED(hr
)) return hr
;
981 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
982 if (FAILED(hr
)) return hr
;
983 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
985 ERR("MsiRecordSetInteger returned %d\n", ret
);
986 return DISP_E_EXCEPTION
;
989 else return DISP_E_MEMBERNOTFOUND
;
993 return DISP_E_MEMBERNOTFOUND
;
996 VariantClear(&varg1
);
997 VariantClear(&varg0
);
1002 static HRESULT
create_record(MSIHANDLE msiHandle
, IDispatch
**disp
)
1004 AutomationObject
*record
;
1007 record
= msi_alloc(sizeof(*record
));
1008 if (!record
) return E_OUTOFMEMORY
;
1010 hr
= init_automation_object(record
, msiHandle
, Record_tid
);
1017 *disp
= &record
->IDispatch_iface
;
1022 static HRESULT
list_invoke(
1023 AutomationObject
* This
,
1024 DISPID dispIdMember
,
1028 DISPPARAMS
* pDispParams
,
1029 VARIANT
* pVarResult
,
1030 EXCEPINFO
* pExcepInfo
,
1033 ListObject
*list
= CONTAINING_RECORD(This
, ListObject
, autoobj
);
1034 IUnknown
*pUnk
= NULL
;
1037 switch (dispIdMember
)
1039 case DISPID_LIST__NEWENUM
:
1040 if (wFlags
& DISPATCH_METHOD
) {
1041 V_VT(pVarResult
) = VT_UNKNOWN
;
1042 if (SUCCEEDED(hr
= create_list_enumerator(list
, (LPVOID
*)&pUnk
)))
1043 V_UNKNOWN(pVarResult
) = pUnk
;
1045 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr
);
1047 else return DISP_E_MEMBERNOTFOUND
;
1050 case DISPID_LIST_ITEM
:
1051 if (wFlags
& DISPATCH_PROPERTYGET
) {
1054 VariantInit(&index
);
1055 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &index
, puArgErr
);
1056 if (FAILED(hr
)) return hr
;
1057 if (V_I4(&index
) < 0 || V_I4(&index
) >= list
->count
)
1058 return DISP_E_BADINDEX
;
1059 VariantCopy(pVarResult
, &list
->data
[V_I4(&index
)]);
1061 else return DISP_E_MEMBERNOTFOUND
;
1064 case DISPID_LIST_COUNT
:
1065 if (wFlags
& DISPATCH_PROPERTYGET
) {
1066 V_VT(pVarResult
) = VT_I4
;
1067 V_I4(pVarResult
) = list
->count
;
1069 else return DISP_E_MEMBERNOTFOUND
;
1073 return DISP_E_MEMBERNOTFOUND
;
1079 static void list_free(AutomationObject
*This
)
1081 ListObject
*list
= CONTAINING_RECORD(This
, ListObject
, autoobj
);
1084 for (i
= 0; i
< list
->count
; i
++)
1085 VariantClear(&list
->data
[i
]);
1086 msi_free(list
->data
);
1089 static HRESULT
get_products_count(const WCHAR
*product
, int *len
)
1095 WCHAR dataW
[GUID_SIZE
];
1098 /* all or related only */
1100 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1102 ret
= MsiEnumProductsW(i
, dataW
);
1104 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1106 if (ret
!= ERROR_SUCCESS
)
1107 return DISP_E_EXCEPTION
;
1117 static HRESULT
create_list(const WCHAR
*product
, IDispatch
**dispatch
)
1123 list
= msi_alloc_zero(sizeof(ListObject
));
1124 if (!list
) return E_OUTOFMEMORY
;
1126 hr
= init_automation_object(&list
->autoobj
, 0, StringList_tid
);
1133 *dispatch
= &list
->autoobj
.IDispatch_iface
;
1135 hr
= get_products_count(product
, &list
->count
);
1138 IDispatch_Release(*dispatch
);
1142 list
->data
= msi_alloc(list
->count
*sizeof(VARIANT
));
1145 IDispatch_Release(*dispatch
);
1146 return E_OUTOFMEMORY
;
1149 for (i
= 0; i
< list
->count
; i
++)
1151 WCHAR dataW
[GUID_SIZE
];
1154 /* all or related only */
1156 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1158 ret
= MsiEnumProductsW(i
, dataW
);
1160 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1162 V_VT(&list
->data
[i
]) = VT_BSTR
;
1163 V_BSTR(&list
->data
[i
]) = SysAllocString(dataW
);
1169 static HRESULT
view_invoke(
1170 AutomationObject
* This
,
1171 DISPID dispIdMember
,
1175 DISPPARAMS
* pDispParams
,
1176 VARIANT
* pVarResult
,
1177 EXCEPINFO
* pExcepInfo
,
1180 MSIHANDLE msiHandle
;
1182 VARIANTARG varg0
, varg1
;
1185 VariantInit(&varg0
);
1186 VariantInit(&varg1
);
1188 switch (dispIdMember
)
1190 case DISPID_VIEW_EXECUTE
:
1191 if (wFlags
& DISPATCH_METHOD
)
1193 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1194 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1195 MsiViewExecute(This
->msiHandle
, ((AutomationObject
*)V_DISPATCH(&varg0
))->msiHandle
);
1197 MsiViewExecute(This
->msiHandle
, 0);
1199 else return DISP_E_MEMBERNOTFOUND
;
1202 case DISPID_VIEW_FETCH
:
1203 if (wFlags
& DISPATCH_METHOD
)
1205 V_VT(pVarResult
) = VT_DISPATCH
;
1206 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1208 if (FAILED(hr
= create_record(msiHandle
, &V_DISPATCH(pVarResult
))))
1209 ERR("Failed to create Record object, hresult 0x%08x\n", hr
);
1211 else if (ret
== ERROR_NO_MORE_ITEMS
)
1212 V_DISPATCH(pVarResult
) = NULL
;
1215 ERR("MsiViewFetch returned %d\n", ret
);
1216 return DISP_E_EXCEPTION
;
1219 else return DISP_E_MEMBERNOTFOUND
;
1222 case DISPID_VIEW_MODIFY
:
1223 if (wFlags
& DISPATCH_METHOD
)
1225 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1226 if (FAILED(hr
)) return hr
;
1227 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1228 if (FAILED(hr
)) return hr
;
1229 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1230 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1232 VariantClear(&varg1
);
1233 ERR("MsiViewModify returned %d\n", ret
);
1234 return DISP_E_EXCEPTION
;
1237 else return DISP_E_MEMBERNOTFOUND
;
1240 case DISPID_VIEW_CLOSE
:
1241 if (wFlags
& DISPATCH_METHOD
)
1243 MsiViewClose(This
->msiHandle
);
1245 else return DISP_E_MEMBERNOTFOUND
;
1249 return DISP_E_MEMBERNOTFOUND
;
1252 VariantClear(&varg1
);
1253 VariantClear(&varg0
);
1258 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1259 DISPPARAMS
* pDispParams
,
1260 VARIANT
* pVarResult
,
1261 EXCEPINFO
* pExcepInfo
,
1264 if (!(wFlags
& DISPATCH_METHOD
))
1265 return DISP_E_MEMBERNOTFOUND
;
1269 VariantInit(pVarResult
);
1273 HRESULT
database_invoke(
1274 AutomationObject
* This
,
1275 DISPID dispIdMember
,
1279 DISPPARAMS
* pDispParams
,
1280 VARIANT
* pVarResult
,
1281 EXCEPINFO
* pExcepInfo
,
1284 IDispatch
*dispatch
= NULL
;
1285 MSIHANDLE msiHandle
;
1287 VARIANTARG varg0
, varg1
;
1290 VariantInit(&varg0
);
1291 VariantInit(&varg1
);
1293 switch (dispIdMember
)
1295 case DISPID_DATABASE_SUMMARYINFORMATION
:
1296 if (wFlags
& DISPATCH_PROPERTYGET
)
1298 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1302 V_VT(pVarResult
) = VT_DISPATCH
;
1303 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1305 hr
= create_summaryinfo(msiHandle
, &dispatch
);
1307 V_DISPATCH(pVarResult
) = dispatch
;
1309 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr
);
1313 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1314 return DISP_E_EXCEPTION
;
1317 else return DISP_E_MEMBERNOTFOUND
;
1320 case DISPID_DATABASE_OPENVIEW
:
1321 if (wFlags
& DISPATCH_METHOD
)
1323 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1324 if (FAILED(hr
)) return hr
;
1325 V_VT(pVarResult
) = VT_DISPATCH
;
1326 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1328 if (SUCCEEDED(hr
= create_view(msiHandle
, &dispatch
)))
1329 V_DISPATCH(pVarResult
) = dispatch
;
1331 ERR("Failed to create View object, hresult 0x%08x\n", hr
);
1335 VariantClear(&varg0
);
1336 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1337 return DISP_E_EXCEPTION
;
1340 else return DISP_E_MEMBERNOTFOUND
;
1343 case DISPID_INSTALLER_LASTERRORRECORD
:
1344 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1345 pVarResult
, pExcepInfo
,
1349 return DISP_E_MEMBERNOTFOUND
;
1352 VariantClear(&varg1
);
1353 VariantClear(&varg0
);
1358 static HRESULT
session_invoke(
1359 AutomationObject
* This
,
1360 DISPID dispIdMember
,
1364 DISPPARAMS
* pDispParams
,
1365 VARIANT
* pVarResult
,
1366 EXCEPINFO
* pExcepInfo
,
1369 SessionObject
*session
= CONTAINING_RECORD(This
, SessionObject
, autoobj
);
1372 MSIHANDLE msiHandle
;
1375 INSTALLSTATE iInstalled
, iAction
;
1376 VARIANTARG varg0
, varg1
;
1379 VariantInit(&varg0
);
1380 VariantInit(&varg1
);
1382 switch (dispIdMember
)
1384 case DISPID_SESSION_INSTALLER
:
1385 if (wFlags
& DISPATCH_PROPERTYGET
) {
1386 V_VT(pVarResult
) = VT_DISPATCH
;
1387 IDispatch_AddRef(session
->installer
);
1388 V_DISPATCH(pVarResult
) = session
->installer
;
1390 else return DISP_E_MEMBERNOTFOUND
;
1393 case DISPID_SESSION_PROPERTY
:
1394 if (wFlags
& DISPATCH_PROPERTYGET
) {
1395 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1396 if (FAILED(hr
)) return hr
;
1397 V_VT(pVarResult
) = VT_BSTR
;
1398 V_BSTR(pVarResult
) = NULL
;
1399 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1401 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1402 ERR("Out of memory\n");
1403 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1404 V_BSTR(pVarResult
) = SysAllocString(szString
);
1407 if (ret
!= ERROR_SUCCESS
)
1408 ERR("MsiGetProperty returned %d\n", ret
);
1409 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1410 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1411 if (FAILED(hr
)) return hr
;
1412 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1414 VariantClear(&varg0
);
1417 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1419 VariantClear(&varg0
);
1420 VariantClear(&varg1
);
1421 ERR("MsiSetProperty returned %d\n", ret
);
1422 return DISP_E_EXCEPTION
;
1425 else return DISP_E_MEMBERNOTFOUND
;
1428 case DISPID_SESSION_LANGUAGE
:
1429 if (wFlags
& DISPATCH_PROPERTYGET
) {
1430 langId
= MsiGetLanguage(This
->msiHandle
);
1431 V_VT(pVarResult
) = VT_I4
;
1432 V_I4(pVarResult
) = langId
;
1434 else return DISP_E_MEMBERNOTFOUND
;
1437 case DISPID_SESSION_MODE
:
1438 if (wFlags
& DISPATCH_PROPERTYGET
) {
1439 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1440 if (FAILED(hr
)) return hr
;
1441 V_VT(pVarResult
) = VT_BOOL
;
1442 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
)) ? VARIANT_TRUE
: VARIANT_FALSE
;
1443 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1444 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1445 if (FAILED(hr
)) return hr
;
1446 hr
= DispGetParam(pDispParams
, 1, VT_BOOL
, &varg1
, puArgErr
);
1447 if (FAILED(hr
)) return hr
;
1448 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1450 ERR("MsiSetMode returned %d\n", ret
);
1451 return DISP_E_EXCEPTION
;
1454 else return DISP_E_MEMBERNOTFOUND
;
1457 case DISPID_SESSION_DATABASE
:
1458 if (wFlags
& DISPATCH_PROPERTYGET
) {
1459 V_VT(pVarResult
) = VT_DISPATCH
;
1460 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1462 IDispatch
*dispatch
;
1464 if (SUCCEEDED(hr
= create_database(msiHandle
, &dispatch
)))
1465 V_DISPATCH(pVarResult
) = dispatch
;
1467 ERR("Failed to create Database object, hresult 0x%08x\n", hr
);
1471 ERR("MsiGetActiveDatabase failed\n");
1472 return DISP_E_EXCEPTION
;
1475 else return DISP_E_MEMBERNOTFOUND
;
1478 case DISPID_SESSION_DOACTION
:
1479 if (wFlags
& DISPATCH_METHOD
) {
1480 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1481 if (FAILED(hr
)) return hr
;
1482 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1483 V_VT(pVarResult
) = VT_I4
;
1486 case ERROR_FUNCTION_NOT_CALLED
:
1487 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1490 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1492 case ERROR_INSTALL_USEREXIT
:
1493 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1495 case ERROR_INSTALL_FAILURE
:
1496 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1498 case ERROR_INSTALL_SUSPEND
:
1499 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1501 case ERROR_MORE_DATA
:
1502 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1504 case ERROR_INVALID_HANDLE_STATE
:
1505 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1507 case ERROR_INVALID_DATA
:
1508 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1511 VariantClear(&varg0
);
1512 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1513 return DISP_E_EXCEPTION
;
1516 else return DISP_E_MEMBERNOTFOUND
;
1519 case DISPID_SESSION_EVALUATECONDITION
:
1520 if (wFlags
& DISPATCH_METHOD
) {
1521 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1522 if (FAILED(hr
)) return hr
;
1523 V_VT(pVarResult
) = VT_I4
;
1524 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1526 else return DISP_E_MEMBERNOTFOUND
;
1529 case DISPID_SESSION_MESSAGE
:
1530 if(!(wFlags
& DISPATCH_METHOD
))
1531 return DISP_E_MEMBERNOTFOUND
;
1533 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1534 if (FAILED(hr
)) return hr
;
1535 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1536 if (FAILED(hr
)) return hr
;
1538 V_VT(pVarResult
) = VT_I4
;
1540 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1543 case DISPID_SESSION_SETINSTALLLEVEL
:
1544 if (wFlags
& DISPATCH_METHOD
) {
1545 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1546 if (FAILED(hr
)) return hr
;
1547 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1549 ERR("MsiSetInstallLevel returned %d\n", ret
);
1550 return DISP_E_EXCEPTION
;
1553 else return DISP_E_MEMBERNOTFOUND
;
1556 case DISPID_SESSION_FEATURECURRENTSTATE
:
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
) = iInstalled
;
1565 ERR("MsiGetFeatureState returned %d\n", ret
);
1566 V_I4(pVarResult
) = msiInstallStateUnknown
;
1569 else return DISP_E_MEMBERNOTFOUND
;
1572 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1573 if (wFlags
& DISPATCH_PROPERTYGET
) {
1574 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1575 if (FAILED(hr
)) return hr
;
1576 V_VT(pVarResult
) = VT_I4
;
1577 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1578 V_I4(pVarResult
) = iAction
;
1581 ERR("MsiGetFeatureState returned %d\n", ret
);
1582 V_I4(pVarResult
) = msiInstallStateUnknown
;
1584 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1585 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1586 if (FAILED(hr
)) return hr
;
1587 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1589 VariantClear(&varg0
);
1592 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1594 VariantClear(&varg0
);
1595 ERR("MsiSetFeatureState returned %d\n", ret
);
1596 return DISP_E_EXCEPTION
;
1599 else return DISP_E_MEMBERNOTFOUND
;
1603 return DISP_E_MEMBERNOTFOUND
;
1606 VariantClear(&varg1
);
1607 VariantClear(&varg0
);
1612 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1613 * registry value type. Used by Installer::RegistryValue. */
1614 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1616 static const WCHAR szREG_BINARY
[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1617 static const WCHAR szREG_
[] = { '(','R','E','G','_','?','?',')',0 };
1618 WCHAR
*szString
= (WCHAR
*)lpData
;
1619 LPWSTR szNewString
= NULL
;
1620 DWORD dwNewSize
= 0;
1625 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1626 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1627 idx
= (dwSize
/sizeof(WCHAR
))-1;
1628 while (idx
>= 0 && !szString
[idx
]) idx
--;
1629 for (; idx
>= 0; idx
--)
1630 if (!szString
[idx
]) szString
[idx
] = '\n';
1633 V_VT(pVarResult
) = VT_BSTR
;
1634 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1638 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1639 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1640 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1641 ERR("Out of memory\n");
1642 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1643 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1646 V_VT(pVarResult
) = VT_BSTR
;
1647 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1649 msi_free(szNewString
);
1653 V_VT(pVarResult
) = VT_I4
;
1654 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1658 V_VT(pVarResult
) = VT_BSTR
;
1659 V_BSTR(pVarResult
) = SysAllocString(szREG_
); /* Weird string, don't know why native returns it */
1663 V_VT(pVarResult
) = VT_BSTR
;
1664 V_BSTR(pVarResult
) = SysAllocString(szREG_BINARY
);
1668 V_VT(pVarResult
) = VT_EMPTY
;
1672 FIXME("Unhandled registry value type %d\n", dwType
);
1676 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1677 DISPPARAMS
* pDispParams
,
1678 VARIANT
* pVarResult
,
1679 EXCEPINFO
* pExcepInfo
,
1686 if (!(wFlags
& DISPATCH_METHOD
))
1687 return DISP_E_MEMBERNOTFOUND
;
1689 VariantInit(&varg0
);
1690 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1694 V_VT(pVarResult
) = VT_DISPATCH
;
1696 hrec
= MsiCreateRecord(V_I4(&varg0
));
1698 return DISP_E_EXCEPTION
;
1700 return create_record(hrec
, &V_DISPATCH(pVarResult
));
1703 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1705 DISPPARAMS
* pDispParams
,
1706 VARIANT
* pVarResult
,
1707 EXCEPINFO
* pExcepInfo
,
1713 IDispatch
* dispatch
;
1714 VARIANTARG varg0
, varg1
;
1716 if (!(wFlags
& DISPATCH_METHOD
))
1717 return DISP_E_MEMBERNOTFOUND
;
1719 if (pDispParams
->cArgs
== 0)
1720 return DISP_E_TYPEMISMATCH
;
1722 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1723 return DISP_E_TYPEMISMATCH
;
1725 VariantInit(&varg0
);
1726 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1730 VariantInit(&varg1
);
1731 if (pDispParams
->cArgs
== 2)
1733 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1739 V_VT(&varg1
) = VT_I4
;
1743 V_VT(pVarResult
) = VT_DISPATCH
;
1745 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1746 if (ret
!= ERROR_SUCCESS
)
1748 hr
= DISP_E_EXCEPTION
;
1752 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1754 V_DISPATCH(pVarResult
) = dispatch
;
1757 VariantClear(&varg0
);
1758 VariantClear(&varg1
);
1762 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1763 DISPPARAMS
* pDispParams
,
1764 VARIANT
* pVarResult
,
1765 EXCEPINFO
* pExcepInfo
,
1771 if (!(wFlags
& DISPATCH_METHOD
))
1772 return DISP_E_MEMBERNOTFOUND
;
1774 VariantInit(&varg0
);
1775 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1779 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1781 VariantInit(pVarResult
);
1783 VariantClear(&varg0
);
1787 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1788 DISPPARAMS
* pDispParams
,
1789 VARIANT
* pVarResult
,
1790 EXCEPINFO
* pExcepInfo
,
1796 IDispatch
* dispatch
;
1797 VARIANTARG varg0
, varg1
;
1799 if (!(wFlags
& DISPATCH_METHOD
))
1800 return DISP_E_MEMBERNOTFOUND
;
1802 VariantInit(&varg0
);
1803 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1807 VariantInit(&varg1
);
1808 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1812 V_VT(pVarResult
) = VT_DISPATCH
;
1814 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1815 if (ret
!= ERROR_SUCCESS
)
1817 hr
= DISP_E_EXCEPTION
;
1821 hr
= create_database(hdb
, &dispatch
);
1823 V_DISPATCH(pVarResult
) = dispatch
;
1826 VariantClear(&varg0
);
1827 VariantClear(&varg1
);
1831 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1832 DISPPARAMS
* pDispParams
,
1833 VARIANT
* pVarResult
,
1834 EXCEPINFO
* pExcepInfo
,
1840 IDispatch
*dispatch
;
1841 VARIANTARG varg0
, varg1
;
1843 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1844 return DISP_E_MEMBERNOTFOUND
;
1846 VariantInit(&varg1
);
1847 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1851 VariantInit(&varg0
);
1852 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1856 ret
= MsiGetSummaryInformationW(0, V_BSTR(&varg0
), V_I4(&varg1
), &hsuminfo
);
1857 VariantClear(&varg0
);
1858 if (ret
!= ERROR_SUCCESS
)
1859 return DISP_E_EXCEPTION
;
1861 hr
= create_summaryinfo(hsuminfo
, &dispatch
);
1865 V_VT(pVarResult
) = VT_DISPATCH
;
1866 V_DISPATCH(pVarResult
) = dispatch
;
1870 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1871 DISPPARAMS
* pDispParams
,
1872 VARIANT
* pVarResult
,
1873 EXCEPINFO
* pExcepInfo
,
1880 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1881 return DISP_E_MEMBERNOTFOUND
;
1883 if (wFlags
& DISPATCH_PROPERTYPUT
)
1885 VariantInit(&varg0
);
1886 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1890 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1891 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1892 return DISP_E_EXCEPTION
;
1894 else if (wFlags
& DISPATCH_PROPERTYGET
)
1896 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1897 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1898 return DISP_E_EXCEPTION
;
1900 V_VT(pVarResult
) = VT_I4
;
1901 V_I4(pVarResult
) = ui
;
1907 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1908 DISPPARAMS
* pDispParams
,
1909 VARIANT
* pVarResult
,
1910 EXCEPINFO
* pExcepInfo
,
1913 if (!(wFlags
& DISPATCH_METHOD
))
1914 return DISP_E_MEMBERNOTFOUND
;
1918 VariantInit(pVarResult
);
1922 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1923 DISPPARAMS
* pDispParams
,
1924 VARIANT
* pVarResult
,
1925 EXCEPINFO
* pExcepInfo
,
1930 VARIANTARG varg0
, varg1
;
1932 if (!(wFlags
& DISPATCH_METHOD
))
1933 return DISP_E_MEMBERNOTFOUND
;
1935 VariantInit(&varg0
);
1936 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1940 VariantInit(&varg1
);
1941 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1945 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1946 if (ret
!= ERROR_SUCCESS
)
1948 hr
= DISP_E_EXCEPTION
;
1953 VariantClear(&varg0
);
1954 VariantClear(&varg1
);
1958 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1959 VARIANT
* pVarResult
,
1960 EXCEPINFO
* pExcepInfo
,
1964 DLLVERSIONINFO verinfo
;
1965 WCHAR version
[MAX_PATH
];
1967 static const WCHAR format
[] = {
1968 '%','d','.','%','d','.','%','d','.','%','d',0};
1970 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1971 return DISP_E_MEMBERNOTFOUND
;
1973 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1974 hr
= DllGetVersion(&verinfo
);
1978 swprintf(version
, ARRAY_SIZE(version
), format
, verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1979 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1981 V_VT(pVarResult
) = VT_BSTR
;
1982 V_BSTR(pVarResult
) = SysAllocString(version
);
1986 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1987 DISPPARAMS
* pDispParams
,
1988 VARIANT
* pVarResult
,
1989 EXCEPINFO
* pExcepInfo
,
1992 if (!(wFlags
& DISPATCH_METHOD
))
1993 return DISP_E_MEMBERNOTFOUND
;
1997 VariantInit(pVarResult
);
2001 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
2002 DISPPARAMS
* pDispParams
,
2003 VARIANT
* pVarResult
,
2004 EXCEPINFO
* pExcepInfo
,
2012 LPWSTR szString
= NULL
;
2013 VARIANTARG varg0
, varg1
, varg2
;
2015 if (!(wFlags
& DISPATCH_METHOD
))
2016 return DISP_E_MEMBERNOTFOUND
;
2018 VariantInit(&varg0
);
2019 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
2023 VariantInit(&varg1
);
2024 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2028 /* Save valuePos so we can save puArgErr if we are unable to do our type
2032 VariantInit(&varg2
);
2033 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
2037 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
2038 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
2040 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
2043 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
2045 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2046 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
2048 hr
= DISP_E_BADINDEX
;
2052 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2053 switch (V_VT(&varg2
))
2055 /* Return VT_BOOL clarifying whether registry key exists or not. */
2057 V_VT(pVarResult
) = VT_BOOL
;
2058 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2061 /* Return the value of specified key if it exists. */
2063 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
2064 NULL
, NULL
, NULL
, &size
);
2065 if (ret
!= ERROR_SUCCESS
)
2067 hr
= DISP_E_BADINDEX
;
2071 szString
= msi_alloc(size
);
2078 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
2079 &type
, (LPBYTE
)szString
, &size
);
2080 if (ret
!= ERROR_SUCCESS
)
2083 hr
= DISP_E_BADINDEX
;
2087 variant_from_registry_value(pVarResult
, type
,
2088 (LPBYTE
)szString
, size
);
2092 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2094 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
2097 if (hr
== DISP_E_TYPEMISMATCH
)
2098 *puArgErr
= posValue
;
2103 /* Retrieve class name or maximum value name or subkey name size. */
2105 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
2106 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2107 else if (V_I4(&varg2
) > 0)
2108 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
2109 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
2110 else /* V_I4(&varg2) < 0 */
2111 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
2112 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2114 if (ret
!= ERROR_SUCCESS
)
2117 szString
= msi_alloc(++size
* sizeof(WCHAR
));
2125 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
2126 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2127 else if (V_I4(&varg2
) > 0)
2128 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
2129 &size
, 0, 0, NULL
, NULL
);
2130 else /* V_I4(&varg2) < 0 */
2131 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
2133 if (ret
== ERROR_SUCCESS
)
2135 V_VT(pVarResult
) = VT_BSTR
;
2136 V_BSTR(pVarResult
) = SysAllocString(szString
);
2143 VariantClear(&varg0
);
2144 VariantClear(&varg1
);
2145 VariantClear(&varg2
);
2150 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2151 DISPPARAMS
* pDispParams
,
2152 VARIANT
* pVarResult
,
2153 EXCEPINFO
* pExcepInfo
,
2156 if (!(wFlags
& DISPATCH_METHOD
))
2157 return DISP_E_MEMBERNOTFOUND
;
2161 VariantInit(pVarResult
);
2165 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2166 DISPPARAMS
* pDispParams
,
2167 VARIANT
* pVarResult
,
2168 EXCEPINFO
* pExcepInfo
,
2171 if (!(wFlags
& DISPATCH_METHOD
))
2172 return DISP_E_MEMBERNOTFOUND
;
2176 VariantInit(pVarResult
);
2180 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2181 DISPPARAMS
* pDispParams
,
2182 VARIANT
* pVarResult
,
2183 EXCEPINFO
* pExcepInfo
,
2186 if (!(wFlags
& DISPATCH_METHOD
))
2187 return DISP_E_MEMBERNOTFOUND
;
2191 VariantInit(pVarResult
);
2195 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2196 DISPPARAMS
* pDispParams
,
2197 VARIANT
* pVarResult
,
2198 EXCEPINFO
* pExcepInfo
,
2201 if (!(wFlags
& DISPATCH_METHOD
))
2202 return DISP_E_MEMBERNOTFOUND
;
2206 VariantInit(pVarResult
);
2210 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2211 DISPPARAMS
* pDispParams
,
2212 VARIANT
* pVarResult
,
2213 EXCEPINFO
* pExcepInfo
,
2219 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2220 return DISP_E_MEMBERNOTFOUND
;
2222 VariantInit(&varg0
);
2223 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2227 V_VT(pVarResult
) = VT_I4
;
2228 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2230 VariantClear(&varg0
);
2234 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2235 DISPPARAMS
* pDispParams
,
2236 VARIANT
* pVarResult
,
2237 EXCEPINFO
* pExcepInfo
,
2244 VARIANTARG varg0
, varg1
;
2246 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2247 return DISP_E_MEMBERNOTFOUND
;
2249 VariantInit(&varg0
);
2250 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2254 VariantInit(&varg1
);
2255 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2259 V_VT(pVarResult
) = VT_BSTR
;
2260 V_BSTR(pVarResult
) = NULL
;
2262 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2263 if (ret
!= ERROR_SUCCESS
)
2265 hr
= DISP_E_EXCEPTION
;
2269 str
= msi_alloc(++size
* sizeof(WCHAR
));
2276 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2277 if (ret
!= ERROR_SUCCESS
)
2279 hr
= DISP_E_EXCEPTION
;
2283 V_BSTR(pVarResult
) = SysAllocString(str
);
2288 VariantClear(&varg0
);
2289 VariantClear(&varg1
);
2293 static HRESULT
InstallerImpl_Products(WORD flags
,
2294 DISPPARAMS
* pDispParams
,
2296 EXCEPINFO
* pExcepInfo
,
2299 IDispatch
*dispatch
;
2302 if (!(flags
& DISPATCH_PROPERTYGET
))
2303 return DISP_E_MEMBERNOTFOUND
;
2305 hr
= create_list(NULL
, &dispatch
);
2309 V_VT(result
) = VT_DISPATCH
;
2310 V_DISPATCH(result
) = dispatch
;
2315 static HRESULT
InstallerImpl_RelatedProducts(WORD flags
,
2316 DISPPARAMS
* pDispParams
,
2318 EXCEPINFO
* pExcepInfo
,
2321 IDispatch
* dispatch
;
2325 if (!(flags
& DISPATCH_PROPERTYGET
))
2326 return DISP_E_MEMBERNOTFOUND
;
2328 VariantInit(&related
);
2329 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &related
, puArgErr
);
2333 hr
= create_list(V_BSTR(&related
), &dispatch
);
2334 VariantClear(&related
);
2336 V_VT(result
) = VT_DISPATCH
;
2337 V_DISPATCH(result
) = dispatch
;
2342 static HRESULT
installer_invoke(
2343 AutomationObject
* This
,
2344 DISPID dispIdMember
,
2348 DISPPARAMS
* pDispParams
,
2349 VARIANT
* pVarResult
,
2350 EXCEPINFO
* pExcepInfo
,
2353 switch (dispIdMember
)
2355 case DISPID_INSTALLER_CREATERECORD
:
2356 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2357 pVarResult
, pExcepInfo
, puArgErr
);
2359 case DISPID_INSTALLER_OPENPACKAGE
:
2360 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2361 pVarResult
, pExcepInfo
, puArgErr
);
2363 case DISPID_INSTALLER_OPENPRODUCT
:
2364 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2365 pVarResult
, pExcepInfo
, puArgErr
);
2367 case DISPID_INSTALLER_OPENDATABASE
:
2368 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2369 pVarResult
, pExcepInfo
, puArgErr
);
2371 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2372 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2373 pVarResult
, pExcepInfo
,
2376 case DISPID_INSTALLER_UILEVEL
:
2377 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2378 pVarResult
, pExcepInfo
, puArgErr
);
2380 case DISPID_INSTALLER_ENABLELOG
:
2381 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2382 pVarResult
, pExcepInfo
, puArgErr
);
2384 case DISPID_INSTALLER_INSTALLPRODUCT
:
2385 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2386 pVarResult
, pExcepInfo
,
2389 case DISPID_INSTALLER_VERSION
:
2390 return InstallerImpl_Version(wFlags
, pVarResult
,
2391 pExcepInfo
, puArgErr
);
2393 case DISPID_INSTALLER_LASTERRORRECORD
:
2394 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2395 pVarResult
, pExcepInfo
,
2398 case DISPID_INSTALLER_REGISTRYVALUE
:
2399 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2400 pVarResult
, pExcepInfo
,
2403 case DISPID_INSTALLER_ENVIRONMENT
:
2404 return InstallerImpl_Environment(wFlags
, pDispParams
,
2405 pVarResult
, pExcepInfo
, puArgErr
);
2407 case DISPID_INSTALLER_FILEATTRIBUTES
:
2408 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2409 pVarResult
, pExcepInfo
,
2412 case DISPID_INSTALLER_FILESIZE
:
2413 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2414 pVarResult
, pExcepInfo
, puArgErr
);
2416 case DISPID_INSTALLER_FILEVERSION
:
2417 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2418 pVarResult
, pExcepInfo
, puArgErr
);
2420 case DISPID_INSTALLER_PRODUCTSTATE
:
2421 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2422 pVarResult
, pExcepInfo
, puArgErr
);
2424 case DISPID_INSTALLER_PRODUCTINFO
:
2425 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2426 pVarResult
, pExcepInfo
, puArgErr
);
2428 case DISPID_INSTALLER_PRODUCTS
:
2429 return InstallerImpl_Products(wFlags
, pDispParams
,
2430 pVarResult
, pExcepInfo
, puArgErr
);
2432 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2433 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2434 pVarResult
, pExcepInfo
,
2438 return DISP_E_MEMBERNOTFOUND
;
2442 HRESULT
create_msiserver(IUnknown
*outer
, void **ppObj
)
2444 AutomationObject
*installer
;
2447 TRACE("(%p %p)\n", outer
, ppObj
);
2450 return CLASS_E_NOAGGREGATION
;
2452 installer
= msi_alloc(sizeof(AutomationObject
));
2453 if (!installer
) return E_OUTOFMEMORY
;
2455 hr
= init_automation_object(installer
, 0, Installer_tid
);
2458 msi_free(installer
);
2462 *ppObj
= &installer
->IDispatch_iface
;
2467 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2469 SessionObject
*session
;
2472 session
= msi_alloc(sizeof(SessionObject
));
2473 if (!session
) return E_OUTOFMEMORY
;
2475 hr
= init_automation_object(&session
->autoobj
, msiHandle
, Session_tid
);
2482 session
->installer
= installer
;
2483 *disp
= &session
->autoobj
.IDispatch_iface
;
2488 static HRESULT
create_database(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2490 AutomationObject
*database
;
2493 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2495 database
= msi_alloc(sizeof(AutomationObject
));
2496 if (!database
) return E_OUTOFMEMORY
;
2498 hr
= init_automation_object(database
, msiHandle
, Database_tid
);
2505 *dispatch
= &database
->IDispatch_iface
;
2510 static HRESULT
create_view(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2512 AutomationObject
*view
;
2515 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2517 view
= msi_alloc(sizeof(AutomationObject
));
2518 if (!view
) return E_OUTOFMEMORY
;
2520 hr
= init_automation_object(view
, msiHandle
, View_tid
);
2527 *dispatch
= &view
->IDispatch_iface
;
2532 static HRESULT
create_summaryinfo(MSIHANDLE msiHandle
, IDispatch
**disp
)
2534 AutomationObject
*info
;
2537 info
= msi_alloc(sizeof(*info
));
2538 if (!info
) return E_OUTOFMEMORY
;
2540 hr
= init_automation_object(info
, msiHandle
, SummaryInfo_tid
);
2547 *disp
= &info
->IDispatch_iface
;