2 * Implementation of OLE Automation for Microsoft Installer (msi.dll)
4 * Copyright 2007 Misha Koshelev
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #include "msiserver.h"
38 #include "msiserver_dispids.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
42 #define REG_INDEX_CLASSES_ROOT 0
43 #define REG_INDEX_DYN_DATA 6
45 typedef struct AutomationObject AutomationObject
;
47 /* function that is called from AutomationObject::Invoke, specific to this type of object */
48 typedef HRESULT (*auto_invoke_func
)(AutomationObject
* This
,
49 DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD flags
, DISPPARAMS
* pDispParams
,
50 VARIANT
* result
, EXCEPINFO
* ei
, UINT
* arg_err
);
51 /* function that is called from AutomationObject::Release when the object is being freed
52 to free any private data structures (or NULL) */
53 typedef void (*auto_free_func
)(AutomationObject
* This
);
57 auto_invoke_func fn_invoke
;
58 auto_free_func fn_free
;
62 static HRESULT
database_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
63 static HRESULT
installer_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
64 static HRESULT
record_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
65 static HRESULT
session_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
66 static HRESULT
list_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
67 static void list_free(AutomationObject
*);
68 static HRESULT
summaryinfo_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
69 static HRESULT
view_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
71 static tid_id_t tid_ids
[] = {
72 { &DIID_Database
, database_invoke
},
73 { &DIID_Installer
, installer_invoke
},
74 { &DIID_Record
, record_invoke
},
75 { &DIID_Session
, session_invoke
},
76 { &DIID_StringList
, list_invoke
, list_free
},
77 { &DIID_SummaryInfo
, summaryinfo_invoke
},
78 { &DIID_View
, view_invoke
}
81 static ITypeLib
*typelib
;
82 static ITypeInfo
*typeinfos
[LAST_tid
];
84 static const IID
*get_riid_from_tid(tid_t tid
)
86 return tid_ids
[tid
].riid
;
89 HRESULT
get_typeinfo(tid_t tid
, ITypeInfo
**typeinfo
)
97 hr
= LoadRegTypeLib(&LIBID_WindowsInstaller
, 1, 0, LOCALE_NEUTRAL
, &lib
);
99 static const WCHAR msiserverW
[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
100 hr
= LoadTypeLib(msiserverW
, &lib
);
102 ERR("Could not load msiserver.tlb\n");
107 if (InterlockedCompareExchangePointer((void**)&typelib
, lib
, NULL
))
108 ITypeLib_Release(lib
);
115 hr
= ITypeLib_GetTypeInfoOfGuid(typelib
, get_riid_from_tid(tid
), &ti
);
117 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid
)));
121 if(InterlockedCompareExchangePointer((void**)(typeinfos
+tid
), ti
, NULL
))
122 ITypeInfo_Release(ti
);
125 *typeinfo
= typeinfos
[tid
];
129 void release_typelib(void)
133 for (i
= 0; i
< sizeof(typeinfos
)/sizeof(*typeinfos
); i
++)
135 ITypeInfo_Release(typeinfos
[i
]);
138 ITypeLib_Release(typelib
);
142 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
143 * called from AutomationObject::Invoke.
145 struct AutomationObject
{
146 IDispatch IDispatch_iface
;
147 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface
;
150 /* type id for this class */
153 /* The MSI handle of the current object */
158 AutomationObject autoobj
;
163 static HRESULT
create_database(MSIHANDLE
, IDispatch
**);
164 static HRESULT
create_list_enumerator(ListObject
*, void**);
165 static HRESULT
create_summaryinfo(MSIHANDLE
, IDispatch
**);
166 static HRESULT
create_view(MSIHANDLE
, IDispatch
**);
168 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
170 IEnumVARIANT IEnumVARIANT_iface
;
173 /* Current position and pointer to AutomationObject that stores actual data */
179 AutomationObject autoobj
;
180 IDispatch
*installer
;
183 static inline AutomationObject
*impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
185 return CONTAINING_RECORD(iface
, AutomationObject
, IProvideMultipleClassInfo_iface
);
188 static inline AutomationObject
*impl_from_IDispatch( IDispatch
*iface
)
190 return CONTAINING_RECORD(iface
, AutomationObject
, IDispatch_iface
);
193 /* AutomationObject methods */
194 static HRESULT WINAPI
AutomationObject_QueryInterface(IDispatch
* iface
, REFIID riid
, void** ppvObject
)
196 AutomationObject
*This
= impl_from_IDispatch(iface
);
198 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
200 if (ppvObject
== NULL
)
205 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
206 IsEqualGUID(riid
, &IID_IDispatch
) ||
207 IsEqualGUID(riid
, get_riid_from_tid(This
->tid
)))
208 *ppvObject
= &This
->IDispatch_iface
;
209 else if (IsEqualGUID(riid
, &IID_IProvideClassInfo
) ||
210 IsEqualGUID(riid
, &IID_IProvideClassInfo2
) ||
211 IsEqualGUID(riid
, &IID_IProvideMultipleClassInfo
))
212 *ppvObject
= &This
->IProvideMultipleClassInfo_iface
;
215 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
216 return E_NOINTERFACE
;
219 IDispatch_AddRef(iface
);
224 static ULONG WINAPI
AutomationObject_AddRef(IDispatch
* iface
)
226 AutomationObject
*This
= impl_from_IDispatch(iface
);
228 TRACE("(%p/%p)\n", iface
, This
);
230 return InterlockedIncrement(&This
->ref
);
233 static ULONG WINAPI
AutomationObject_Release(IDispatch
* iface
)
235 AutomationObject
*This
= impl_from_IDispatch(iface
);
236 ULONG ref
= InterlockedDecrement(&This
->ref
);
238 TRACE("(%p/%p)\n", iface
, This
);
242 if (tid_ids
[This
->tid
].fn_free
) tid_ids
[This
->tid
].fn_free(This
);
243 MsiCloseHandle(This
->msiHandle
);
250 static HRESULT WINAPI
AutomationObject_GetTypeInfoCount(
254 AutomationObject
*This
= impl_from_IDispatch(iface
);
256 TRACE("(%p/%p)->(%p)\n", iface
, This
, pctinfo
);
261 static HRESULT WINAPI
AutomationObject_GetTypeInfo(
267 AutomationObject
*This
= impl_from_IDispatch(iface
);
270 TRACE("(%p/%p)->(%d,%d,%p)\n", iface
, This
, iTInfo
, lcid
, ppTInfo
);
272 hr
= get_typeinfo(This
->tid
, ppTInfo
);
276 ITypeInfo_AddRef(*ppTInfo
);
280 static HRESULT WINAPI
AutomationObject_GetIDsOfNames(
288 AutomationObject
*This
= impl_from_IDispatch(iface
);
292 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", iface
, This
,
293 debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
295 if (!IsEqualGUID(riid
, &IID_NULL
)) return E_INVALIDARG
;
297 hr
= get_typeinfo(This
->tid
, &ti
);
301 hr
= ITypeInfo_GetIDsOfNames(ti
, rgszNames
, cNames
, rgDispId
);
302 if (hr
== DISP_E_UNKNOWNNAME
)
305 for (idx
=0; idx
<cNames
; idx
++)
307 if (rgDispId
[idx
] == DISPID_UNKNOWN
)
308 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames
[idx
]), debugstr_guid(get_riid_from_tid(This
->tid
)));
314 /* Maximum number of allowed function parameters+1 */
315 #define MAX_FUNC_PARAMS 20
317 /* Some error checking is done here to simplify individual object function invocation */
318 static HRESULT WINAPI
AutomationObject_Invoke(
324 DISPPARAMS
* pDispParams
,
326 EXCEPINFO
* pExcepInfo
,
329 AutomationObject
*This
= impl_from_IDispatch(iface
);
331 unsigned int uArgErr
;
332 VARIANT varResultDummy
;
333 BSTR bstrName
= NULL
;
336 TRACE("(%p/%p)->(%d, %s, %d, %d, %p, %p, %p, %p)\n", iface
, This
,
337 dispIdMember
, debugstr_guid(riid
), lcid
, wFlags
,
338 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
340 if (!IsEqualIID(riid
, &IID_NULL
))
342 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
343 return DISP_E_UNKNOWNNAME
;
346 if (wFlags
& DISPATCH_PROPERTYGET
&& !pVarResult
)
348 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
349 return DISP_E_PARAMNOTOPTIONAL
;
352 /* This simplifies our individual object invocation functions */
353 if (puArgErr
== NULL
) puArgErr
= &uArgErr
;
354 if (pVarResult
== NULL
) pVarResult
= &varResultDummy
;
356 hr
= get_typeinfo(This
->tid
, &ti
);
360 /* Assume return type is void unless determined otherwise */
361 VariantInit(pVarResult
);
363 /* If we are tracing, we want to see the name of the member we are invoking */
366 ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
367 TRACE("Method %d, %s\n", dispIdMember
, debugstr_w(bstrName
));
370 hr
= tid_ids
[This
->tid
].fn_invoke(This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
372 if (hr
== DISP_E_MEMBERNOTFOUND
) {
373 if (bstrName
== NULL
) ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
374 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember
, debugstr_w(bstrName
), wFlags
,
375 debugstr_guid(get_riid_from_tid(This
->tid
)));
377 else if (pExcepInfo
&&
378 (hr
== DISP_E_PARAMNOTFOUND
||
379 hr
== DISP_E_EXCEPTION
)) {
380 static const WCHAR szComma
[] = { ',',0 };
381 static const WCHAR szExceptionSource
[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
382 WCHAR szExceptionDescription
[MAX_PATH
];
383 BSTR bstrParamNames
[MAX_FUNC_PARAMS
];
387 if (FAILED(ITypeInfo_GetNames(ti
, dispIdMember
, bstrParamNames
,
388 MAX_FUNC_PARAMS
, &namesNo
)))
390 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember
);
394 memset(szExceptionDescription
, 0, sizeof(szExceptionDescription
));
395 for (i
=0; i
<namesNo
; i
++)
397 if (bFirst
) bFirst
= FALSE
;
399 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], szComma
);
401 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], bstrParamNames
[i
]);
402 SysFreeString(bstrParamNames
[i
]);
405 memset(pExcepInfo
, 0, sizeof(EXCEPINFO
));
406 pExcepInfo
->wCode
= 1000;
407 pExcepInfo
->bstrSource
= SysAllocString(szExceptionSource
);
408 pExcepInfo
->bstrDescription
= SysAllocString(szExceptionDescription
);
409 hr
= DISP_E_EXCEPTION
;
413 /* Make sure we free the return variant if it is our dummy variant */
414 if (pVarResult
== &varResultDummy
) VariantClear(pVarResult
);
416 /* Free function name if we retrieved it */
417 SysFreeString(bstrName
);
419 TRACE("Returning 0x%08x, %s\n", hr
, SUCCEEDED(hr
) ? "ok" : "not ok");
424 static const struct IDispatchVtbl AutomationObjectVtbl
=
426 AutomationObject_QueryInterface
,
427 AutomationObject_AddRef
,
428 AutomationObject_Release
,
429 AutomationObject_GetTypeInfoCount
,
430 AutomationObject_GetTypeInfo
,
431 AutomationObject_GetIDsOfNames
,
432 AutomationObject_Invoke
436 * IProvideMultipleClassInfo methods
439 static HRESULT WINAPI
ProvideMultipleClassInfo_QueryInterface(
440 IProvideMultipleClassInfo
* iface
,
444 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
445 return IDispatch_QueryInterface(&This
->IDispatch_iface
, riid
, ppvoid
);
448 static ULONG WINAPI
ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo
* iface
)
450 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
451 return IDispatch_AddRef(&This
->IDispatch_iface
);
454 static ULONG WINAPI
ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo
* iface
)
456 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
457 return IDispatch_Release(&This
->IDispatch_iface
);
460 static HRESULT WINAPI
ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo
* iface
, ITypeInfo
** ppTI
)
462 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
465 TRACE("(%p/%p)->(%p)\n", iface
, This
, ppTI
);
467 hr
= get_typeinfo(This
->tid
, ppTI
);
469 ITypeInfo_AddRef(*ppTI
);
474 static HRESULT WINAPI
ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
* iface
, DWORD dwGuidKind
, GUID
* pGUID
)
476 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
477 TRACE("(%p/%p)->(%d,%s)\n", iface
, This
, dwGuidKind
, debugstr_guid(pGUID
));
479 if (dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
482 *pGUID
= *get_riid_from_tid(This
->tid
);
487 static HRESULT WINAPI
ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo
* iface
, ULONG
* pcti
)
489 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
491 TRACE("(%p/%p)->(%p)\n", iface
, This
, pcti
);
496 static HRESULT WINAPI
ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo
* iface
,
501 ULONG
* pcdispidReserved
,
505 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
507 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface
, This
, iti
, dwFlags
, ti
, pdwTIFlags
, pcdispidReserved
, piidPrimary
, piidSource
);
512 if (dwFlags
& MULTICLASSINFO_GETTYPEINFO
)
514 HRESULT hr
= get_typeinfo(This
->tid
, ti
);
518 ITypeInfo_AddRef(*ti
);
521 if (dwFlags
& MULTICLASSINFO_GETNUMRESERVEDDISPIDS
)
524 *pcdispidReserved
= 0;
527 if (dwFlags
& MULTICLASSINFO_GETIIDPRIMARY
)
528 *piidPrimary
= *get_riid_from_tid(This
->tid
);
530 if (dwFlags
& MULTICLASSINFO_GETIIDSOURCE
)
531 *piidSource
= *get_riid_from_tid(This
->tid
);
536 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl
=
538 ProvideMultipleClassInfo_QueryInterface
,
539 ProvideMultipleClassInfo_AddRef
,
540 ProvideMultipleClassInfo_Release
,
541 ProvideMultipleClassInfo_GetClassInfo
,
542 ProvideMultipleClassInfo_GetGUID
,
543 ProvideMultipleClassInfo_GetMultiTypeInfoCount
,
544 ProvideMultipleClassInfo_GetInfoOfIndex
547 static HRESULT
init_automation_object(AutomationObject
*This
, MSIHANDLE msiHandle
, tid_t tid
)
549 TRACE("(%p, %d, %s)\n", This
, msiHandle
, debugstr_guid(get_riid_from_tid(tid
)));
551 This
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
552 This
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
555 This
->msiHandle
= msiHandle
;
562 * ListEnumerator methods
565 static inline ListEnumerator
*impl_from_IEnumVARIANT(IEnumVARIANT
* iface
)
567 return CONTAINING_RECORD(iface
, ListEnumerator
, IEnumVARIANT_iface
);
570 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
,
573 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
575 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
577 if (ppvObject
== NULL
)
582 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
583 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
585 *ppvObject
= &This
->IEnumVARIANT_iface
;
589 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
590 return E_NOINTERFACE
;
593 IEnumVARIANT_AddRef(iface
);
597 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
599 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
601 TRACE("(%p/%p)\n", iface
, This
);
603 return InterlockedIncrement(&This
->ref
);
606 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
608 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
609 ULONG ref
= InterlockedDecrement(&This
->ref
);
611 TRACE("(%p/%p)\n", iface
, This
);
615 if (This
->list
) IDispatch_Release(&This
->list
->autoobj
.IDispatch_iface
);
622 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
* rgVar
,
625 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
628 TRACE("(%p, %uld, %p, %p)\n", iface
, celt
, rgVar
, fetched
);
630 if (fetched
) *fetched
= 0;
635 for (local
= 0; local
< celt
; local
++)
636 VariantInit(&rgVar
[local
]);
638 for (i
= This
->pos
, local
= 0; i
< This
->list
->count
&& local
< celt
; i
++, local
++)
639 VariantCopy(&rgVar
[local
], &This
->list
->data
[i
]);
641 if (fetched
) *fetched
= local
;
644 return (local
< celt
) ? S_FALSE
: S_OK
;
647 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
649 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
651 TRACE("(%p,%uld)\n", iface
, celt
);
654 if (This
->pos
>= This
->list
->count
)
656 This
->pos
= This
->list
->count
;
663 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
665 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
667 TRACE("(%p)\n", iface
);
673 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
675 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
678 TRACE("(%p,%p)\n", iface
, ppEnum
);
684 hr
= create_list_enumerator(This
->list
, (LPVOID
*)ppEnum
);
687 if (*ppEnum
) IEnumVARIANT_Release(*ppEnum
);
694 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
696 ListEnumerator_QueryInterface
,
697 ListEnumerator_AddRef
,
698 ListEnumerator_Release
,
701 ListEnumerator_Reset
,
705 /* Create a list enumerator, placing the result in the pointer ppObj. */
706 static HRESULT
create_list_enumerator(ListObject
*list
, void **ppObj
)
708 ListEnumerator
*object
;
710 TRACE("(%p, %p)\n", list
, ppObj
);
712 object
= msi_alloc(sizeof(ListEnumerator
));
714 /* Set all the VTable references */
715 object
->IEnumVARIANT_iface
.lpVtbl
= &ListEnumerator_Vtbl
;
718 /* Store data that was passed */
721 if (list
) IDispatch_AddRef(&list
->autoobj
.IDispatch_iface
);
728 * Individual Object Invocation Functions
731 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
732 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
733 using DispGetParam/VariantChangeType. */
734 static HRESULT
DispGetParam_CopyOnly(
735 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
736 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
737 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
739 /* position is counted backwards */
742 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
743 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
744 if (*position
< pdispparams
->cArgs
) {
745 /* positional arg? */
746 pos
= pdispparams
->cArgs
- *position
- 1;
748 /* FIXME: is this how to handle named args? */
749 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
750 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
752 if (pos
==pdispparams
->cNamedArgs
)
753 return DISP_E_PARAMNOTFOUND
;
756 return VariantCopyInd(pvarResult
,
757 &pdispparams
->rgvarg
[pos
]);
760 static HRESULT
summaryinfo_invoke(
761 AutomationObject
* This
,
766 DISPPARAMS
* pDispParams
,
768 EXCEPINFO
* pExcepInfo
,
772 VARIANTARG varg0
, varg1
;
773 FILETIME ft
, ftlocal
;
780 switch (dispIdMember
)
782 case DISPID_SUMMARYINFO_PROPERTY
:
783 if (wFlags
& DISPATCH_PROPERTYGET
)
791 static WCHAR szEmpty
[] = {0};
793 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
794 if (FAILED(hr
)) return hr
;
795 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
796 &ft
, szEmpty
, &size
);
797 if (ret
!= ERROR_SUCCESS
&&
798 ret
!= ERROR_MORE_DATA
)
800 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
801 return DISP_E_EXCEPTION
;
811 V_VT(pVarResult
) = VT_I4
;
812 V_I4(pVarResult
) = value
;
816 if (!(str
= msi_alloc(++size
* sizeof(WCHAR
))))
817 ERR("Out of memory\n");
818 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
819 NULL
, str
, &size
)) != ERROR_SUCCESS
)
820 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
823 V_VT(pVarResult
) = VT_BSTR
;
824 V_BSTR(pVarResult
) = SysAllocString(str
);
830 FileTimeToLocalFileTime(&ft
, &ftlocal
);
831 FileTimeToSystemTime(&ftlocal
, &st
);
832 SystemTimeToVariantTime(&st
, &date
);
834 V_VT(pVarResult
) = VT_DATE
;
835 V_DATE(pVarResult
) = date
;
839 ERR("Unhandled variant type %d\n", type
);
842 else if (wFlags
& DISPATCH_PROPERTYPUT
)
844 UINT posValue
= DISPID_PROPERTYPUT
;
846 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
847 if (FAILED(hr
)) return hr
;
848 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
851 *puArgErr
= posValue
;
855 switch (V_VT(&varg1
))
859 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
863 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
864 SystemTimeToFileTime(&st
, &ftlocal
);
865 LocalFileTimeToFileTime(&ftlocal
, &ft
);
866 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
870 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
874 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
875 VariantClear(&varg1
);
876 return DISP_E_EXCEPTION
;
879 if (ret
!= ERROR_SUCCESS
)
881 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
882 return DISP_E_EXCEPTION
;
885 else return DISP_E_MEMBERNOTFOUND
;
888 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
889 if (wFlags
& DISPATCH_PROPERTYGET
) {
891 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
892 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
895 V_VT(pVarResult
) = VT_I4
;
896 V_I4(pVarResult
) = count
;
899 else return DISP_E_MEMBERNOTFOUND
;
903 return DISP_E_MEMBERNOTFOUND
;
906 VariantClear(&varg1
);
907 VariantClear(&varg0
);
912 static HRESULT
record_invoke(
913 AutomationObject
* This
,
918 DISPPARAMS
* pDispParams
,
920 EXCEPINFO
* pExcepInfo
,
926 VARIANTARG varg0
, varg1
;
932 switch (dispIdMember
)
934 case DISPID_RECORD_FIELDCOUNT
:
935 if (wFlags
& DISPATCH_PROPERTYGET
) {
936 V_VT(pVarResult
) = VT_I4
;
937 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
939 else return DISP_E_MEMBERNOTFOUND
;
942 case DISPID_RECORD_STRINGDATA
:
943 if (wFlags
& DISPATCH_PROPERTYGET
) {
944 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
945 if (FAILED(hr
)) return hr
;
946 V_VT(pVarResult
) = VT_BSTR
;
947 V_BSTR(pVarResult
) = NULL
;
948 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
950 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
951 ERR("Out of memory\n");
952 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
953 V_BSTR(pVarResult
) = SysAllocString(szString
);
956 if (ret
!= ERROR_SUCCESS
)
957 ERR("MsiRecordGetString returned %d\n", ret
);
958 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
959 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
960 if (FAILED(hr
)) return hr
;
961 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
962 if (FAILED(hr
)) return hr
;
963 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
965 VariantClear(&varg1
);
966 ERR("MsiRecordSetString returned %d\n", ret
);
967 return DISP_E_EXCEPTION
;
970 else return DISP_E_MEMBERNOTFOUND
;
973 case DISPID_RECORD_INTEGERDATA
:
974 if (wFlags
& DISPATCH_PROPERTYGET
) {
975 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
976 if (FAILED(hr
)) return hr
;
977 V_VT(pVarResult
) = VT_I4
;
978 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
979 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
980 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
981 if (FAILED(hr
)) return hr
;
982 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
983 if (FAILED(hr
)) return hr
;
984 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
986 ERR("MsiRecordSetInteger returned %d\n", ret
);
987 return DISP_E_EXCEPTION
;
990 else return DISP_E_MEMBERNOTFOUND
;
994 return DISP_E_MEMBERNOTFOUND
;
997 VariantClear(&varg1
);
998 VariantClear(&varg0
);
1003 static HRESULT
create_record(MSIHANDLE msiHandle
, IDispatch
**disp
)
1005 AutomationObject
*record
;
1008 record
= msi_alloc(sizeof(*record
));
1009 if (!record
) return E_OUTOFMEMORY
;
1011 hr
= init_automation_object(record
, msiHandle
, Record_tid
);
1018 *disp
= &record
->IDispatch_iface
;
1023 static HRESULT
list_invoke(
1024 AutomationObject
* This
,
1025 DISPID dispIdMember
,
1029 DISPPARAMS
* pDispParams
,
1030 VARIANT
* pVarResult
,
1031 EXCEPINFO
* pExcepInfo
,
1034 ListObject
*list
= CONTAINING_RECORD(This
, ListObject
, autoobj
);
1035 IUnknown
*pUnk
= NULL
;
1038 switch (dispIdMember
)
1040 case DISPID_LIST__NEWENUM
:
1041 if (wFlags
& DISPATCH_METHOD
) {
1042 V_VT(pVarResult
) = VT_UNKNOWN
;
1043 if (SUCCEEDED(hr
= create_list_enumerator(list
, (LPVOID
*)&pUnk
)))
1044 V_UNKNOWN(pVarResult
) = pUnk
;
1046 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr
);
1048 else return DISP_E_MEMBERNOTFOUND
;
1051 case DISPID_LIST_ITEM
:
1052 if (wFlags
& DISPATCH_PROPERTYGET
) {
1055 VariantInit(&index
);
1056 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &index
, puArgErr
);
1057 if (FAILED(hr
)) return hr
;
1058 if (V_I4(&index
) < 0 || V_I4(&index
) >= list
->count
)
1059 return DISP_E_BADINDEX
;
1060 VariantCopy(pVarResult
, &list
->data
[V_I4(&index
)]);
1062 else return DISP_E_MEMBERNOTFOUND
;
1065 case DISPID_LIST_COUNT
:
1066 if (wFlags
& DISPATCH_PROPERTYGET
) {
1067 V_VT(pVarResult
) = VT_I4
;
1068 V_I4(pVarResult
) = list
->count
;
1070 else return DISP_E_MEMBERNOTFOUND
;
1074 return DISP_E_MEMBERNOTFOUND
;
1080 static void list_free(AutomationObject
*This
)
1082 ListObject
*list
= CONTAINING_RECORD(This
, ListObject
, autoobj
);
1085 for (i
= 0; i
< list
->count
; i
++)
1086 VariantClear(&list
->data
[i
]);
1087 msi_free(list
->data
);
1090 static HRESULT
get_products_count(const WCHAR
*product
, int *len
)
1096 WCHAR dataW
[GUID_SIZE
];
1099 /* all or related only */
1101 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1103 ret
= MsiEnumProductsW(i
, dataW
);
1105 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1107 if (ret
!= ERROR_SUCCESS
)
1108 return DISP_E_EXCEPTION
;
1118 static HRESULT
create_list(const WCHAR
*product
, IDispatch
**dispatch
)
1124 list
= msi_alloc_zero(sizeof(ListObject
));
1125 if (!list
) return E_OUTOFMEMORY
;
1127 hr
= init_automation_object(&list
->autoobj
, 0, StringList_tid
);
1134 *dispatch
= &list
->autoobj
.IDispatch_iface
;
1136 hr
= get_products_count(product
, &list
->count
);
1139 IDispatch_Release(*dispatch
);
1143 list
->data
= msi_alloc(list
->count
*sizeof(VARIANT
));
1146 IDispatch_Release(*dispatch
);
1147 return E_OUTOFMEMORY
;
1150 for (i
= 0; i
< list
->count
; i
++)
1152 WCHAR dataW
[GUID_SIZE
];
1155 /* all or related only */
1157 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1159 ret
= MsiEnumProductsW(i
, dataW
);
1161 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1163 V_VT(&list
->data
[i
]) = VT_BSTR
;
1164 V_BSTR(&list
->data
[i
]) = SysAllocString(dataW
);
1170 static HRESULT
view_invoke(
1171 AutomationObject
* This
,
1172 DISPID dispIdMember
,
1176 DISPPARAMS
* pDispParams
,
1177 VARIANT
* pVarResult
,
1178 EXCEPINFO
* pExcepInfo
,
1181 MSIHANDLE msiHandle
;
1183 VARIANTARG varg0
, varg1
;
1186 VariantInit(&varg0
);
1187 VariantInit(&varg1
);
1189 switch (dispIdMember
)
1191 case DISPID_VIEW_EXECUTE
:
1192 if (wFlags
& DISPATCH_METHOD
)
1194 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1195 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1196 MsiViewExecute(This
->msiHandle
, ((AutomationObject
*)V_DISPATCH(&varg0
))->msiHandle
);
1198 MsiViewExecute(This
->msiHandle
, 0);
1200 else return DISP_E_MEMBERNOTFOUND
;
1203 case DISPID_VIEW_FETCH
:
1204 if (wFlags
& DISPATCH_METHOD
)
1206 V_VT(pVarResult
) = VT_DISPATCH
;
1207 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1209 if (FAILED(hr
= create_record(msiHandle
, &V_DISPATCH(pVarResult
))))
1210 ERR("Failed to create Record object, hresult 0x%08x\n", hr
);
1212 else if (ret
== ERROR_NO_MORE_ITEMS
)
1213 V_DISPATCH(pVarResult
) = NULL
;
1216 ERR("MsiViewFetch returned %d\n", ret
);
1217 return DISP_E_EXCEPTION
;
1220 else return DISP_E_MEMBERNOTFOUND
;
1223 case DISPID_VIEW_MODIFY
:
1224 if (wFlags
& DISPATCH_METHOD
)
1226 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1227 if (FAILED(hr
)) return hr
;
1228 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1229 if (FAILED(hr
)) return hr
;
1230 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1231 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1233 VariantClear(&varg1
);
1234 ERR("MsiViewModify returned %d\n", ret
);
1235 return DISP_E_EXCEPTION
;
1238 else return DISP_E_MEMBERNOTFOUND
;
1241 case DISPID_VIEW_CLOSE
:
1242 if (wFlags
& DISPATCH_METHOD
)
1244 MsiViewClose(This
->msiHandle
);
1246 else return DISP_E_MEMBERNOTFOUND
;
1250 return DISP_E_MEMBERNOTFOUND
;
1253 VariantClear(&varg1
);
1254 VariantClear(&varg0
);
1259 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1260 DISPPARAMS
* pDispParams
,
1261 VARIANT
* pVarResult
,
1262 EXCEPINFO
* pExcepInfo
,
1265 if (!(wFlags
& DISPATCH_METHOD
))
1266 return DISP_E_MEMBERNOTFOUND
;
1270 VariantInit(pVarResult
);
1274 HRESULT
database_invoke(
1275 AutomationObject
* This
,
1276 DISPID dispIdMember
,
1280 DISPPARAMS
* pDispParams
,
1281 VARIANT
* pVarResult
,
1282 EXCEPINFO
* pExcepInfo
,
1285 IDispatch
*dispatch
= NULL
;
1286 MSIHANDLE msiHandle
;
1288 VARIANTARG varg0
, varg1
;
1291 VariantInit(&varg0
);
1292 VariantInit(&varg1
);
1294 switch (dispIdMember
)
1296 case DISPID_DATABASE_SUMMARYINFORMATION
:
1297 if (wFlags
& DISPATCH_PROPERTYGET
)
1299 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1303 V_VT(pVarResult
) = VT_DISPATCH
;
1304 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1306 hr
= create_summaryinfo(msiHandle
, &dispatch
);
1308 V_DISPATCH(pVarResult
) = dispatch
;
1310 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr
);
1314 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1315 return DISP_E_EXCEPTION
;
1318 else return DISP_E_MEMBERNOTFOUND
;
1321 case DISPID_DATABASE_OPENVIEW
:
1322 if (wFlags
& DISPATCH_METHOD
)
1324 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1325 if (FAILED(hr
)) return hr
;
1326 V_VT(pVarResult
) = VT_DISPATCH
;
1327 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1329 if (SUCCEEDED(hr
= create_view(msiHandle
, &dispatch
)))
1330 V_DISPATCH(pVarResult
) = dispatch
;
1332 ERR("Failed to create View object, hresult 0x%08x\n", hr
);
1336 VariantClear(&varg0
);
1337 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1338 return DISP_E_EXCEPTION
;
1341 else return DISP_E_MEMBERNOTFOUND
;
1344 case DISPID_INSTALLER_LASTERRORRECORD
:
1345 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1346 pVarResult
, pExcepInfo
,
1350 return DISP_E_MEMBERNOTFOUND
;
1353 VariantClear(&varg1
);
1354 VariantClear(&varg0
);
1359 static HRESULT
session_invoke(
1360 AutomationObject
* This
,
1361 DISPID dispIdMember
,
1365 DISPPARAMS
* pDispParams
,
1366 VARIANT
* pVarResult
,
1367 EXCEPINFO
* pExcepInfo
,
1370 SessionObject
*session
= CONTAINING_RECORD(This
, SessionObject
, autoobj
);
1373 MSIHANDLE msiHandle
;
1376 INSTALLSTATE iInstalled
, iAction
;
1377 VARIANTARG varg0
, varg1
;
1380 VariantInit(&varg0
);
1381 VariantInit(&varg1
);
1383 switch (dispIdMember
)
1385 case DISPID_SESSION_INSTALLER
:
1386 if (wFlags
& DISPATCH_PROPERTYGET
) {
1387 V_VT(pVarResult
) = VT_DISPATCH
;
1388 IDispatch_AddRef(session
->installer
);
1389 V_DISPATCH(pVarResult
) = session
->installer
;
1391 else return DISP_E_MEMBERNOTFOUND
;
1394 case DISPID_SESSION_PROPERTY
:
1395 if (wFlags
& DISPATCH_PROPERTYGET
) {
1396 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1397 if (FAILED(hr
)) return hr
;
1398 V_VT(pVarResult
) = VT_BSTR
;
1399 V_BSTR(pVarResult
) = NULL
;
1400 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1402 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1403 ERR("Out of memory\n");
1404 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1405 V_BSTR(pVarResult
) = SysAllocString(szString
);
1408 if (ret
!= ERROR_SUCCESS
)
1409 ERR("MsiGetProperty returned %d\n", ret
);
1410 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1411 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1412 if (FAILED(hr
)) return hr
;
1413 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1415 VariantClear(&varg0
);
1418 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1420 VariantClear(&varg0
);
1421 VariantClear(&varg1
);
1422 ERR("MsiSetProperty returned %d\n", ret
);
1423 return DISP_E_EXCEPTION
;
1426 else return DISP_E_MEMBERNOTFOUND
;
1429 case DISPID_SESSION_LANGUAGE
:
1430 if (wFlags
& DISPATCH_PROPERTYGET
) {
1431 langId
= MsiGetLanguage(This
->msiHandle
);
1432 V_VT(pVarResult
) = VT_I4
;
1433 V_I4(pVarResult
) = langId
;
1435 else return DISP_E_MEMBERNOTFOUND
;
1438 case DISPID_SESSION_MODE
:
1439 if (wFlags
& DISPATCH_PROPERTYGET
) {
1440 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1441 if (FAILED(hr
)) return hr
;
1442 V_VT(pVarResult
) = VT_BOOL
;
1443 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
)) ? VARIANT_TRUE
: VARIANT_FALSE
;
1444 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1445 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1446 if (FAILED(hr
)) return hr
;
1447 hr
= DispGetParam(pDispParams
, 1, VT_BOOL
, &varg1
, puArgErr
);
1448 if (FAILED(hr
)) return hr
;
1449 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1451 ERR("MsiSetMode returned %d\n", ret
);
1452 return DISP_E_EXCEPTION
;
1455 else return DISP_E_MEMBERNOTFOUND
;
1458 case DISPID_SESSION_DATABASE
:
1459 if (wFlags
& DISPATCH_PROPERTYGET
) {
1460 V_VT(pVarResult
) = VT_DISPATCH
;
1461 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1463 IDispatch
*dispatch
;
1465 if (SUCCEEDED(hr
= create_database(msiHandle
, &dispatch
)))
1466 V_DISPATCH(pVarResult
) = dispatch
;
1468 ERR("Failed to create Database object, hresult 0x%08x\n", hr
);
1472 ERR("MsiGetActiveDatabase failed\n");
1473 return DISP_E_EXCEPTION
;
1476 else return DISP_E_MEMBERNOTFOUND
;
1479 case DISPID_SESSION_DOACTION
:
1480 if (wFlags
& DISPATCH_METHOD
) {
1481 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1482 if (FAILED(hr
)) return hr
;
1483 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1484 V_VT(pVarResult
) = VT_I4
;
1487 case ERROR_FUNCTION_NOT_CALLED
:
1488 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1491 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1493 case ERROR_INSTALL_USEREXIT
:
1494 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1496 case ERROR_INSTALL_FAILURE
:
1497 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1499 case ERROR_INSTALL_SUSPEND
:
1500 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1502 case ERROR_MORE_DATA
:
1503 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1505 case ERROR_INVALID_HANDLE_STATE
:
1506 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1508 case ERROR_INVALID_DATA
:
1509 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1512 VariantClear(&varg0
);
1513 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1514 return DISP_E_EXCEPTION
;
1517 else return DISP_E_MEMBERNOTFOUND
;
1520 case DISPID_SESSION_EVALUATECONDITION
:
1521 if (wFlags
& DISPATCH_METHOD
) {
1522 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1523 if (FAILED(hr
)) return hr
;
1524 V_VT(pVarResult
) = VT_I4
;
1525 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1527 else return DISP_E_MEMBERNOTFOUND
;
1530 case DISPID_SESSION_MESSAGE
:
1531 if(!(wFlags
& DISPATCH_METHOD
))
1532 return DISP_E_MEMBERNOTFOUND
;
1534 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1535 if (FAILED(hr
)) return hr
;
1536 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1537 if (FAILED(hr
)) return hr
;
1539 V_VT(pVarResult
) = VT_I4
;
1541 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1544 case DISPID_SESSION_SETINSTALLLEVEL
:
1545 if (wFlags
& DISPATCH_METHOD
) {
1546 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1547 if (FAILED(hr
)) return hr
;
1548 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1550 ERR("MsiSetInstallLevel returned %d\n", ret
);
1551 return DISP_E_EXCEPTION
;
1554 else return DISP_E_MEMBERNOTFOUND
;
1557 case DISPID_SESSION_FEATURECURRENTSTATE
:
1558 if (wFlags
& DISPATCH_PROPERTYGET
) {
1559 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1560 if (FAILED(hr
)) return hr
;
1561 V_VT(pVarResult
) = VT_I4
;
1562 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1563 V_I4(pVarResult
) = iInstalled
;
1566 ERR("MsiGetFeatureState returned %d\n", ret
);
1567 V_I4(pVarResult
) = msiInstallStateUnknown
;
1570 else return DISP_E_MEMBERNOTFOUND
;
1573 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1574 if (wFlags
& DISPATCH_PROPERTYGET
) {
1575 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1576 if (FAILED(hr
)) return hr
;
1577 V_VT(pVarResult
) = VT_I4
;
1578 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1579 V_I4(pVarResult
) = iAction
;
1582 ERR("MsiGetFeatureState returned %d\n", ret
);
1583 V_I4(pVarResult
) = msiInstallStateUnknown
;
1585 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1586 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1587 if (FAILED(hr
)) return hr
;
1588 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1590 VariantClear(&varg0
);
1593 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1595 VariantClear(&varg0
);
1596 ERR("MsiSetFeatureState returned %d\n", ret
);
1597 return DISP_E_EXCEPTION
;
1600 else return DISP_E_MEMBERNOTFOUND
;
1604 return DISP_E_MEMBERNOTFOUND
;
1607 VariantClear(&varg1
);
1608 VariantClear(&varg0
);
1613 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1614 * registry value type. Used by Installer::RegistryValue. */
1615 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1617 static const WCHAR szREG_BINARY
[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1618 static const WCHAR szREG_
[] = { '(','R','E','G','_','?','?',')',0 };
1619 WCHAR
*szString
= (WCHAR
*)lpData
;
1620 LPWSTR szNewString
= NULL
;
1621 DWORD dwNewSize
= 0;
1626 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1627 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1628 idx
= (dwSize
/sizeof(WCHAR
))-1;
1629 while (idx
>= 0 && !szString
[idx
]) idx
--;
1630 for (; idx
>= 0; idx
--)
1631 if (!szString
[idx
]) szString
[idx
] = '\n';
1634 V_VT(pVarResult
) = VT_BSTR
;
1635 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1639 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1640 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1641 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1642 ERR("Out of memory\n");
1643 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1644 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1647 V_VT(pVarResult
) = VT_BSTR
;
1648 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1650 msi_free(szNewString
);
1654 V_VT(pVarResult
) = VT_I4
;
1655 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1659 V_VT(pVarResult
) = VT_BSTR
;
1660 V_BSTR(pVarResult
) = SysAllocString(szREG_
); /* Weird string, don't know why native returns it */
1664 V_VT(pVarResult
) = VT_BSTR
;
1665 V_BSTR(pVarResult
) = SysAllocString(szREG_BINARY
);
1669 V_VT(pVarResult
) = VT_EMPTY
;
1673 FIXME("Unhandled registry value type %d\n", dwType
);
1677 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1678 DISPPARAMS
* pDispParams
,
1679 VARIANT
* pVarResult
,
1680 EXCEPINFO
* pExcepInfo
,
1687 if (!(wFlags
& DISPATCH_METHOD
))
1688 return DISP_E_MEMBERNOTFOUND
;
1690 VariantInit(&varg0
);
1691 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1695 V_VT(pVarResult
) = VT_DISPATCH
;
1697 hrec
= MsiCreateRecord(V_I4(&varg0
));
1699 return DISP_E_EXCEPTION
;
1701 return create_record(hrec
, &V_DISPATCH(pVarResult
));
1704 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1706 DISPPARAMS
* pDispParams
,
1707 VARIANT
* pVarResult
,
1708 EXCEPINFO
* pExcepInfo
,
1714 IDispatch
* dispatch
;
1715 VARIANTARG varg0
, varg1
;
1717 if (!(wFlags
& DISPATCH_METHOD
))
1718 return DISP_E_MEMBERNOTFOUND
;
1720 if (pDispParams
->cArgs
== 0)
1721 return DISP_E_TYPEMISMATCH
;
1723 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1724 return DISP_E_TYPEMISMATCH
;
1726 VariantInit(&varg0
);
1727 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1731 VariantInit(&varg1
);
1732 if (pDispParams
->cArgs
== 2)
1734 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1740 V_VT(&varg1
) = VT_I4
;
1744 V_VT(pVarResult
) = VT_DISPATCH
;
1746 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1747 if (ret
!= ERROR_SUCCESS
)
1749 hr
= DISP_E_EXCEPTION
;
1753 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1755 V_DISPATCH(pVarResult
) = dispatch
;
1758 VariantClear(&varg0
);
1759 VariantClear(&varg1
);
1763 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1764 DISPPARAMS
* pDispParams
,
1765 VARIANT
* pVarResult
,
1766 EXCEPINFO
* pExcepInfo
,
1772 if (!(wFlags
& DISPATCH_METHOD
))
1773 return DISP_E_MEMBERNOTFOUND
;
1775 VariantInit(&varg0
);
1776 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1780 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1782 VariantInit(pVarResult
);
1784 VariantClear(&varg0
);
1788 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1789 DISPPARAMS
* pDispParams
,
1790 VARIANT
* pVarResult
,
1791 EXCEPINFO
* pExcepInfo
,
1797 IDispatch
* dispatch
;
1798 VARIANTARG varg0
, varg1
;
1800 if (!(wFlags
& DISPATCH_METHOD
))
1801 return DISP_E_MEMBERNOTFOUND
;
1803 VariantInit(&varg0
);
1804 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1808 VariantInit(&varg1
);
1809 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1813 V_VT(pVarResult
) = VT_DISPATCH
;
1815 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1816 if (ret
!= ERROR_SUCCESS
)
1818 hr
= DISP_E_EXCEPTION
;
1822 hr
= create_database(hdb
, &dispatch
);
1824 V_DISPATCH(pVarResult
) = dispatch
;
1827 VariantClear(&varg0
);
1828 VariantClear(&varg1
);
1832 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1833 DISPPARAMS
* pDispParams
,
1834 VARIANT
* pVarResult
,
1835 EXCEPINFO
* pExcepInfo
,
1841 IDispatch
*dispatch
;
1842 VARIANTARG varg0
, varg1
;
1844 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1845 return DISP_E_MEMBERNOTFOUND
;
1847 VariantInit(&varg1
);
1848 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1852 VariantInit(&varg0
);
1853 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1857 ret
= MsiGetSummaryInformationW(0, V_BSTR(&varg0
), V_I4(&varg1
), &hsuminfo
);
1858 VariantClear(&varg0
);
1859 if (ret
!= ERROR_SUCCESS
)
1860 return DISP_E_EXCEPTION
;
1862 hr
= create_summaryinfo(hsuminfo
, &dispatch
);
1866 V_VT(pVarResult
) = VT_DISPATCH
;
1867 V_DISPATCH(pVarResult
) = dispatch
;
1871 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1872 DISPPARAMS
* pDispParams
,
1873 VARIANT
* pVarResult
,
1874 EXCEPINFO
* pExcepInfo
,
1881 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1882 return DISP_E_MEMBERNOTFOUND
;
1884 if (wFlags
& DISPATCH_PROPERTYPUT
)
1886 VariantInit(&varg0
);
1887 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1891 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1892 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1893 return DISP_E_EXCEPTION
;
1895 else if (wFlags
& DISPATCH_PROPERTYGET
)
1897 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1898 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1899 return DISP_E_EXCEPTION
;
1901 V_VT(pVarResult
) = VT_I4
;
1902 V_I4(pVarResult
) = ui
;
1908 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1909 DISPPARAMS
* pDispParams
,
1910 VARIANT
* pVarResult
,
1911 EXCEPINFO
* pExcepInfo
,
1914 if (!(wFlags
& DISPATCH_METHOD
))
1915 return DISP_E_MEMBERNOTFOUND
;
1919 VariantInit(pVarResult
);
1923 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1924 DISPPARAMS
* pDispParams
,
1925 VARIANT
* pVarResult
,
1926 EXCEPINFO
* pExcepInfo
,
1931 VARIANTARG varg0
, varg1
;
1933 if (!(wFlags
& DISPATCH_METHOD
))
1934 return DISP_E_MEMBERNOTFOUND
;
1936 VariantInit(&varg0
);
1937 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1941 VariantInit(&varg1
);
1942 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1946 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1947 if (ret
!= ERROR_SUCCESS
)
1949 hr
= DISP_E_EXCEPTION
;
1954 VariantClear(&varg0
);
1955 VariantClear(&varg1
);
1959 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1960 VARIANT
* pVarResult
,
1961 EXCEPINFO
* pExcepInfo
,
1965 DLLVERSIONINFO verinfo
;
1966 WCHAR version
[MAX_PATH
];
1968 static const WCHAR format
[] = {
1969 '%','d','.','%','d','.','%','d','.','%','d',0};
1971 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1972 return DISP_E_MEMBERNOTFOUND
;
1974 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1975 hr
= DllGetVersion(&verinfo
);
1979 sprintfW(version
, format
, verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1980 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1982 V_VT(pVarResult
) = VT_BSTR
;
1983 V_BSTR(pVarResult
) = SysAllocString(version
);
1987 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1988 DISPPARAMS
* pDispParams
,
1989 VARIANT
* pVarResult
,
1990 EXCEPINFO
* pExcepInfo
,
1993 if (!(wFlags
& DISPATCH_METHOD
))
1994 return DISP_E_MEMBERNOTFOUND
;
1998 VariantInit(pVarResult
);
2002 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
2003 DISPPARAMS
* pDispParams
,
2004 VARIANT
* pVarResult
,
2005 EXCEPINFO
* pExcepInfo
,
2013 LPWSTR szString
= NULL
;
2014 VARIANTARG varg0
, varg1
, varg2
;
2016 if (!(wFlags
& DISPATCH_METHOD
))
2017 return DISP_E_MEMBERNOTFOUND
;
2019 VariantInit(&varg0
);
2020 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
2024 VariantInit(&varg1
);
2025 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2029 /* Save valuePos so we can save puArgErr if we are unable to do our type
2033 VariantInit(&varg2
);
2034 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
2038 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
2039 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
2041 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
2044 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
2046 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2047 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
2049 hr
= DISP_E_BADINDEX
;
2053 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2054 switch (V_VT(&varg2
))
2056 /* Return VT_BOOL clarifying whether registry key exists or not. */
2058 V_VT(pVarResult
) = VT_BOOL
;
2059 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2062 /* Return the value of specified key if it exists. */
2064 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
2065 NULL
, NULL
, NULL
, &size
);
2066 if (ret
!= ERROR_SUCCESS
)
2068 hr
= DISP_E_BADINDEX
;
2072 szString
= msi_alloc(size
);
2079 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
2080 &type
, (LPBYTE
)szString
, &size
);
2081 if (ret
!= ERROR_SUCCESS
)
2084 hr
= DISP_E_BADINDEX
;
2088 variant_from_registry_value(pVarResult
, type
,
2089 (LPBYTE
)szString
, size
);
2093 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2095 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
2098 if (hr
== DISP_E_TYPEMISMATCH
)
2099 *puArgErr
= posValue
;
2104 /* Retrieve class name or maximum value name or subkey name size. */
2106 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
2107 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2108 else if (V_I4(&varg2
) > 0)
2109 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
2110 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
2111 else /* V_I4(&varg2) < 0 */
2112 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
2113 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2115 if (ret
!= ERROR_SUCCESS
)
2118 szString
= msi_alloc(++size
* sizeof(WCHAR
));
2126 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
2127 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2128 else if (V_I4(&varg2
) > 0)
2129 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
2130 &size
, 0, 0, NULL
, NULL
);
2131 else /* V_I4(&varg2) < 0 */
2132 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
2134 if (ret
== ERROR_SUCCESS
)
2136 V_VT(pVarResult
) = VT_BSTR
;
2137 V_BSTR(pVarResult
) = SysAllocString(szString
);
2144 VariantClear(&varg0
);
2145 VariantClear(&varg1
);
2146 VariantClear(&varg2
);
2151 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2152 DISPPARAMS
* pDispParams
,
2153 VARIANT
* pVarResult
,
2154 EXCEPINFO
* pExcepInfo
,
2157 if (!(wFlags
& DISPATCH_METHOD
))
2158 return DISP_E_MEMBERNOTFOUND
;
2162 VariantInit(pVarResult
);
2166 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2167 DISPPARAMS
* pDispParams
,
2168 VARIANT
* pVarResult
,
2169 EXCEPINFO
* pExcepInfo
,
2172 if (!(wFlags
& DISPATCH_METHOD
))
2173 return DISP_E_MEMBERNOTFOUND
;
2177 VariantInit(pVarResult
);
2181 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2182 DISPPARAMS
* pDispParams
,
2183 VARIANT
* pVarResult
,
2184 EXCEPINFO
* pExcepInfo
,
2187 if (!(wFlags
& DISPATCH_METHOD
))
2188 return DISP_E_MEMBERNOTFOUND
;
2192 VariantInit(pVarResult
);
2196 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2197 DISPPARAMS
* pDispParams
,
2198 VARIANT
* pVarResult
,
2199 EXCEPINFO
* pExcepInfo
,
2202 if (!(wFlags
& DISPATCH_METHOD
))
2203 return DISP_E_MEMBERNOTFOUND
;
2207 VariantInit(pVarResult
);
2211 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2212 DISPPARAMS
* pDispParams
,
2213 VARIANT
* pVarResult
,
2214 EXCEPINFO
* pExcepInfo
,
2220 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2221 return DISP_E_MEMBERNOTFOUND
;
2223 VariantInit(&varg0
);
2224 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2228 V_VT(pVarResult
) = VT_I4
;
2229 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2231 VariantClear(&varg0
);
2235 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2236 DISPPARAMS
* pDispParams
,
2237 VARIANT
* pVarResult
,
2238 EXCEPINFO
* pExcepInfo
,
2245 VARIANTARG varg0
, varg1
;
2247 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2248 return DISP_E_MEMBERNOTFOUND
;
2250 VariantInit(&varg0
);
2251 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2255 VariantInit(&varg1
);
2256 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2260 V_VT(pVarResult
) = VT_BSTR
;
2261 V_BSTR(pVarResult
) = NULL
;
2263 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2264 if (ret
!= ERROR_SUCCESS
)
2266 hr
= DISP_E_EXCEPTION
;
2270 str
= msi_alloc(++size
* sizeof(WCHAR
));
2277 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2278 if (ret
!= ERROR_SUCCESS
)
2280 hr
= DISP_E_EXCEPTION
;
2284 V_BSTR(pVarResult
) = SysAllocString(str
);
2289 VariantClear(&varg0
);
2290 VariantClear(&varg1
);
2294 static HRESULT
InstallerImpl_Products(WORD flags
,
2295 DISPPARAMS
* pDispParams
,
2297 EXCEPINFO
* pExcepInfo
,
2300 IDispatch
*dispatch
;
2303 if (!(flags
& DISPATCH_PROPERTYGET
))
2304 return DISP_E_MEMBERNOTFOUND
;
2306 hr
= create_list(NULL
, &dispatch
);
2310 V_VT(result
) = VT_DISPATCH
;
2311 V_DISPATCH(result
) = dispatch
;
2316 static HRESULT
InstallerImpl_RelatedProducts(WORD flags
,
2317 DISPPARAMS
* pDispParams
,
2319 EXCEPINFO
* pExcepInfo
,
2322 IDispatch
* dispatch
;
2326 if (!(flags
& DISPATCH_PROPERTYGET
))
2327 return DISP_E_MEMBERNOTFOUND
;
2329 VariantInit(&related
);
2330 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &related
, puArgErr
);
2334 hr
= create_list(V_BSTR(&related
), &dispatch
);
2335 VariantClear(&related
);
2337 V_VT(result
) = VT_DISPATCH
;
2338 V_DISPATCH(result
) = dispatch
;
2343 static HRESULT
installer_invoke(
2344 AutomationObject
* This
,
2345 DISPID dispIdMember
,
2349 DISPPARAMS
* pDispParams
,
2350 VARIANT
* pVarResult
,
2351 EXCEPINFO
* pExcepInfo
,
2354 switch (dispIdMember
)
2356 case DISPID_INSTALLER_CREATERECORD
:
2357 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2358 pVarResult
, pExcepInfo
, puArgErr
);
2360 case DISPID_INSTALLER_OPENPACKAGE
:
2361 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2362 pVarResult
, pExcepInfo
, puArgErr
);
2364 case DISPID_INSTALLER_OPENPRODUCT
:
2365 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2366 pVarResult
, pExcepInfo
, puArgErr
);
2368 case DISPID_INSTALLER_OPENDATABASE
:
2369 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2370 pVarResult
, pExcepInfo
, puArgErr
);
2372 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2373 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2374 pVarResult
, pExcepInfo
,
2377 case DISPID_INSTALLER_UILEVEL
:
2378 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2379 pVarResult
, pExcepInfo
, puArgErr
);
2381 case DISPID_INSTALLER_ENABLELOG
:
2382 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2383 pVarResult
, pExcepInfo
, puArgErr
);
2385 case DISPID_INSTALLER_INSTALLPRODUCT
:
2386 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2387 pVarResult
, pExcepInfo
,
2390 case DISPID_INSTALLER_VERSION
:
2391 return InstallerImpl_Version(wFlags
, pVarResult
,
2392 pExcepInfo
, puArgErr
);
2394 case DISPID_INSTALLER_LASTERRORRECORD
:
2395 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2396 pVarResult
, pExcepInfo
,
2399 case DISPID_INSTALLER_REGISTRYVALUE
:
2400 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2401 pVarResult
, pExcepInfo
,
2404 case DISPID_INSTALLER_ENVIRONMENT
:
2405 return InstallerImpl_Environment(wFlags
, pDispParams
,
2406 pVarResult
, pExcepInfo
, puArgErr
);
2408 case DISPID_INSTALLER_FILEATTRIBUTES
:
2409 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2410 pVarResult
, pExcepInfo
,
2413 case DISPID_INSTALLER_FILESIZE
:
2414 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2415 pVarResult
, pExcepInfo
, puArgErr
);
2417 case DISPID_INSTALLER_FILEVERSION
:
2418 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2419 pVarResult
, pExcepInfo
, puArgErr
);
2421 case DISPID_INSTALLER_PRODUCTSTATE
:
2422 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2423 pVarResult
, pExcepInfo
, puArgErr
);
2425 case DISPID_INSTALLER_PRODUCTINFO
:
2426 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2427 pVarResult
, pExcepInfo
, puArgErr
);
2429 case DISPID_INSTALLER_PRODUCTS
:
2430 return InstallerImpl_Products(wFlags
, pDispParams
,
2431 pVarResult
, pExcepInfo
, puArgErr
);
2433 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2434 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2435 pVarResult
, pExcepInfo
,
2439 return DISP_E_MEMBERNOTFOUND
;
2443 HRESULT
create_msiserver(IUnknown
*outer
, void **ppObj
)
2445 AutomationObject
*installer
;
2448 TRACE("(%p %p)\n", outer
, ppObj
);
2451 return CLASS_E_NOAGGREGATION
;
2453 installer
= msi_alloc(sizeof(AutomationObject
));
2454 if (!installer
) return E_OUTOFMEMORY
;
2456 hr
= init_automation_object(installer
, 0, Installer_tid
);
2459 msi_free(installer
);
2463 *ppObj
= &installer
->IDispatch_iface
;
2468 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2470 SessionObject
*session
;
2473 session
= msi_alloc(sizeof(SessionObject
));
2474 if (!session
) return E_OUTOFMEMORY
;
2476 hr
= init_automation_object(&session
->autoobj
, msiHandle
, Session_tid
);
2483 session
->installer
= installer
;
2484 *disp
= &session
->autoobj
.IDispatch_iface
;
2489 static HRESULT
create_database(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2491 AutomationObject
*database
;
2494 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2496 database
= msi_alloc(sizeof(AutomationObject
));
2497 if (!database
) return E_OUTOFMEMORY
;
2499 hr
= init_automation_object(database
, msiHandle
, Database_tid
);
2506 *dispatch
= &database
->IDispatch_iface
;
2511 static HRESULT
create_view(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2513 AutomationObject
*view
;
2516 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2518 view
= msi_alloc(sizeof(AutomationObject
));
2519 if (!view
) return E_OUTOFMEMORY
;
2521 hr
= init_automation_object(view
, msiHandle
, View_tid
);
2528 *dispatch
= &view
->IDispatch_iface
;
2533 static HRESULT
create_summaryinfo(MSIHANDLE msiHandle
, IDispatch
**disp
)
2535 AutomationObject
*info
;
2538 info
= msi_alloc(sizeof(*info
));
2539 if (!info
) return E_OUTOFMEMORY
;
2541 hr
= init_automation_object(info
, msiHandle
, SummaryInfo_tid
);
2548 *disp
= &info
->IDispatch_iface
;