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
22 #include "msiserver_dispids.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
26 #define REG_INDEX_CLASSES_ROOT 0
27 #define REG_INDEX_DYN_DATA 6
29 typedef struct AutomationObject AutomationObject
;
31 /* function that is called from AutomationObject::Invoke, specific to this type of object */
32 typedef HRESULT (*auto_invoke_func
)(AutomationObject
* This
,
33 DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD flags
, DISPPARAMS
* pDispParams
,
34 VARIANT
* result
, EXCEPINFO
* ei
, UINT
* arg_err
);
35 /* function that is called from AutomationObject::Release when the object is being freed
36 to free any private data structures (or NULL) */
37 typedef void (*auto_free_func
)(AutomationObject
* This
);
41 auto_invoke_func fn_invoke
;
42 auto_free_func fn_free
;
46 static HRESULT
database_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
47 static HRESULT
installer_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
48 static HRESULT
record_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
49 static HRESULT
session_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
50 static HRESULT
list_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
51 static void list_free(AutomationObject
*);
52 static HRESULT
summaryinfo_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
53 static HRESULT
view_invoke(AutomationObject
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
55 static tid_id_t tid_ids
[] = {
56 { &DIID_Database
, database_invoke
},
57 { &DIID_Installer
, installer_invoke
},
58 { &DIID_Record
, record_invoke
},
59 { &DIID_Session
, session_invoke
},
60 { &DIID_StringList
, list_invoke
, list_free
},
61 { &DIID_SummaryInfo
, summaryinfo_invoke
},
62 { &DIID_View
, view_invoke
}
65 static ITypeLib
*typelib
;
66 static ITypeInfo
*typeinfos
[LAST_tid
];
68 static const IID
*get_riid_from_tid(tid_t tid
)
70 return tid_ids
[tid
].riid
;
73 HRESULT
get_typeinfo(tid_t tid
, ITypeInfo
**typeinfo
)
81 hr
= LoadRegTypeLib(&LIBID_WindowsInstaller
, 1, 0, LOCALE_NEUTRAL
, &lib
);
83 static const WCHAR msiserverW
[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
84 hr
= LoadTypeLib(msiserverW
, &lib
);
86 ERR("Could not load msiserver.tlb\n");
91 if (InterlockedCompareExchangePointer((void**)&typelib
, lib
, NULL
))
92 ITypeLib_Release(lib
);
99 hr
= ITypeLib_GetTypeInfoOfGuid(typelib
, get_riid_from_tid(tid
), &ti
);
101 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid
)));
105 if(InterlockedCompareExchangePointer((void**)(typeinfos
+tid
), ti
, NULL
))
106 ITypeInfo_Release(ti
);
109 *typeinfo
= typeinfos
[tid
];
113 void release_typelib(void)
117 for (i
= 0; i
< sizeof(typeinfos
)/sizeof(*typeinfos
); i
++)
119 ITypeInfo_Release(typeinfos
[i
]);
122 ITypeLib_Release(typelib
);
126 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
127 * called from AutomationObject::Invoke.
129 struct AutomationObject
{
130 IDispatch IDispatch_iface
;
131 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface
;
134 /* type id for this class */
137 /* The MSI handle of the current object */
142 AutomationObject autoobj
;
147 static HRESULT
create_database(MSIHANDLE
, IDispatch
**);
148 static HRESULT
create_list_enumerator(ListObject
*, void**);
149 static HRESULT
create_summaryinfo(MSIHANDLE
, IDispatch
**);
150 static HRESULT
create_view(MSIHANDLE
, IDispatch
**);
152 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
154 IEnumVARIANT IEnumVARIANT_iface
;
157 /* Current position and pointer to AutomationObject that stores actual data */
163 AutomationObject autoobj
;
164 IDispatch
*installer
;
167 static inline AutomationObject
*impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
169 return CONTAINING_RECORD(iface
, AutomationObject
, IProvideMultipleClassInfo_iface
);
172 static inline AutomationObject
*impl_from_IDispatch( IDispatch
*iface
)
174 return CONTAINING_RECORD(iface
, AutomationObject
, IDispatch_iface
);
177 /* AutomationObject methods */
178 static HRESULT WINAPI
AutomationObject_QueryInterface(IDispatch
* iface
, REFIID riid
, void** ppvObject
)
180 AutomationObject
*This
= impl_from_IDispatch(iface
);
182 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
184 if (ppvObject
== NULL
)
189 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
190 IsEqualGUID(riid
, &IID_IDispatch
) ||
191 IsEqualGUID(riid
, get_riid_from_tid(This
->tid
)))
192 *ppvObject
= &This
->IDispatch_iface
;
193 else if (IsEqualGUID(riid
, &IID_IProvideClassInfo
) ||
194 IsEqualGUID(riid
, &IID_IProvideClassInfo2
) ||
195 IsEqualGUID(riid
, &IID_IProvideMultipleClassInfo
))
196 *ppvObject
= &This
->IProvideMultipleClassInfo_iface
;
199 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
200 return E_NOINTERFACE
;
203 IDispatch_AddRef(iface
);
208 static ULONG WINAPI
AutomationObject_AddRef(IDispatch
* iface
)
210 AutomationObject
*This
= impl_from_IDispatch(iface
);
212 TRACE("(%p/%p)\n", iface
, This
);
214 return InterlockedIncrement(&This
->ref
);
217 static ULONG WINAPI
AutomationObject_Release(IDispatch
* iface
)
219 AutomationObject
*This
= impl_from_IDispatch(iface
);
220 ULONG ref
= InterlockedDecrement(&This
->ref
);
222 TRACE("(%p/%p)\n", iface
, This
);
226 if (tid_ids
[This
->tid
].fn_free
) tid_ids
[This
->tid
].fn_free(This
);
227 MsiCloseHandle(This
->msiHandle
);
234 static HRESULT WINAPI
AutomationObject_GetTypeInfoCount(
238 AutomationObject
*This
= impl_from_IDispatch(iface
);
240 TRACE("(%p/%p)->(%p)\n", iface
, This
, pctinfo
);
245 static HRESULT WINAPI
AutomationObject_GetTypeInfo(
251 AutomationObject
*This
= impl_from_IDispatch(iface
);
254 TRACE("(%p/%p)->(%d,%d,%p)\n", iface
, This
, iTInfo
, lcid
, ppTInfo
);
256 hr
= get_typeinfo(This
->tid
, ppTInfo
);
260 ITypeInfo_AddRef(*ppTInfo
);
264 static HRESULT WINAPI
AutomationObject_GetIDsOfNames(
272 AutomationObject
*This
= impl_from_IDispatch(iface
);
276 TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface
, This
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
278 if (!IsEqualGUID(riid
, &IID_NULL
)) return E_INVALIDARG
;
280 hr
= get_typeinfo(This
->tid
, &ti
);
284 hr
= ITypeInfo_GetIDsOfNames(ti
, rgszNames
, cNames
, rgDispId
);
285 if (hr
== DISP_E_UNKNOWNNAME
)
288 for (idx
=0; idx
<cNames
; idx
++)
290 if (rgDispId
[idx
] == DISPID_UNKNOWN
)
291 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames
[idx
]), debugstr_guid(get_riid_from_tid(This
->tid
)));
297 /* Maximum number of allowed function parameters+1 */
298 #define MAX_FUNC_PARAMS 20
300 /* Some error checking is done here to simplify individual object function invocation */
301 static HRESULT WINAPI
AutomationObject_Invoke(
307 DISPPARAMS
* pDispParams
,
309 EXCEPINFO
* pExcepInfo
,
312 AutomationObject
*This
= impl_from_IDispatch(iface
);
314 unsigned int uArgErr
;
315 VARIANT varResultDummy
;
316 BSTR bstrName
= NULL
;
319 TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface
, This
, dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
321 if (!IsEqualIID(riid
, &IID_NULL
))
323 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
324 return DISP_E_UNKNOWNNAME
;
327 if (wFlags
& DISPATCH_PROPERTYGET
&& !pVarResult
)
329 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
330 return DISP_E_PARAMNOTOPTIONAL
;
333 /* This simplifies our individual object invocation functions */
334 if (puArgErr
== NULL
) puArgErr
= &uArgErr
;
335 if (pVarResult
== NULL
) pVarResult
= &varResultDummy
;
337 hr
= get_typeinfo(This
->tid
, &ti
);
341 /* Assume return type is void unless determined otherwise */
342 VariantInit(pVarResult
);
344 /* If we are tracing, we want to see the name of the member we are invoking */
347 ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
348 TRACE("Method %d, %s\n", dispIdMember
, debugstr_w(bstrName
));
351 hr
= tid_ids
[This
->tid
].fn_invoke(This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
353 if (hr
== DISP_E_MEMBERNOTFOUND
) {
354 if (bstrName
== NULL
) ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
355 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember
, debugstr_w(bstrName
), wFlags
,
356 debugstr_guid(get_riid_from_tid(This
->tid
)));
358 else if (pExcepInfo
&&
359 (hr
== DISP_E_PARAMNOTFOUND
||
360 hr
== DISP_E_EXCEPTION
)) {
361 static const WCHAR szComma
[] = { ',',0 };
362 static const WCHAR szExceptionSource
[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
363 WCHAR szExceptionDescription
[MAX_PATH
];
364 BSTR bstrParamNames
[MAX_FUNC_PARAMS
];
368 if (FAILED(ITypeInfo_GetNames(ti
, dispIdMember
, bstrParamNames
,
369 MAX_FUNC_PARAMS
, &namesNo
)))
371 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember
);
375 memset(szExceptionDescription
, 0, sizeof(szExceptionDescription
));
376 for (i
=0; i
<namesNo
; i
++)
378 if (bFirst
) bFirst
= FALSE
;
380 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], szComma
);
382 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], bstrParamNames
[i
]);
383 SysFreeString(bstrParamNames
[i
]);
386 memset(pExcepInfo
, 0, sizeof(EXCEPINFO
));
387 pExcepInfo
->wCode
= 1000;
388 pExcepInfo
->bstrSource
= SysAllocString(szExceptionSource
);
389 pExcepInfo
->bstrDescription
= SysAllocString(szExceptionDescription
);
390 hr
= DISP_E_EXCEPTION
;
394 /* Make sure we free the return variant if it is our dummy variant */
395 if (pVarResult
== &varResultDummy
) VariantClear(pVarResult
);
397 /* Free function name if we retrieved it */
398 SysFreeString(bstrName
);
400 TRACE("Returning 0x%08x, %s\n", hr
, SUCCEEDED(hr
) ? "ok" : "not ok");
405 static const struct IDispatchVtbl AutomationObjectVtbl
=
407 AutomationObject_QueryInterface
,
408 AutomationObject_AddRef
,
409 AutomationObject_Release
,
410 AutomationObject_GetTypeInfoCount
,
411 AutomationObject_GetTypeInfo
,
412 AutomationObject_GetIDsOfNames
,
413 AutomationObject_Invoke
417 * IProvideMultipleClassInfo methods
420 static HRESULT WINAPI
ProvideMultipleClassInfo_QueryInterface(
421 IProvideMultipleClassInfo
* iface
,
425 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
426 return IDispatch_QueryInterface(&This
->IDispatch_iface
, riid
, ppvoid
);
429 static ULONG WINAPI
ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo
* iface
)
431 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
432 return IDispatch_AddRef(&This
->IDispatch_iface
);
435 static ULONG WINAPI
ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo
* iface
)
437 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
438 return IDispatch_Release(&This
->IDispatch_iface
);
441 static HRESULT WINAPI
ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo
* iface
, ITypeInfo
** ppTI
)
443 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
446 TRACE("(%p/%p)->(%p)\n", iface
, This
, ppTI
);
448 hr
= get_typeinfo(This
->tid
, ppTI
);
450 ITypeInfo_AddRef(*ppTI
);
455 static HRESULT WINAPI
ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
* iface
, DWORD dwGuidKind
, GUID
* pGUID
)
457 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
458 TRACE("(%p/%p)->(%d,%s)\n", iface
, This
, dwGuidKind
, debugstr_guid(pGUID
));
460 if (dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
463 *pGUID
= *get_riid_from_tid(This
->tid
);
468 static HRESULT WINAPI
ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo
* iface
, ULONG
* pcti
)
470 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
472 TRACE("(%p/%p)->(%p)\n", iface
, This
, pcti
);
477 static HRESULT WINAPI
ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo
* iface
,
482 ULONG
* pcdispidReserved
,
486 AutomationObject
*This
= impl_from_IProvideMultipleClassInfo(iface
);
488 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface
, This
, iti
, dwFlags
, ti
, pdwTIFlags
, pcdispidReserved
, piidPrimary
, piidSource
);
493 if (dwFlags
& MULTICLASSINFO_GETTYPEINFO
)
495 HRESULT hr
= get_typeinfo(This
->tid
, ti
);
499 ITypeInfo_AddRef(*ti
);
502 if (dwFlags
& MULTICLASSINFO_GETNUMRESERVEDDISPIDS
)
505 *pcdispidReserved
= 0;
508 if (dwFlags
& MULTICLASSINFO_GETIIDPRIMARY
)
509 *piidPrimary
= *get_riid_from_tid(This
->tid
);
511 if (dwFlags
& MULTICLASSINFO_GETIIDSOURCE
)
512 *piidSource
= *get_riid_from_tid(This
->tid
);
517 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl
=
519 ProvideMultipleClassInfo_QueryInterface
,
520 ProvideMultipleClassInfo_AddRef
,
521 ProvideMultipleClassInfo_Release
,
522 ProvideMultipleClassInfo_GetClassInfo
,
523 ProvideMultipleClassInfo_GetGUID
,
524 ProvideMultipleClassInfo_GetMultiTypeInfoCount
,
525 ProvideMultipleClassInfo_GetInfoOfIndex
528 static HRESULT
init_automation_object(AutomationObject
*This
, MSIHANDLE msiHandle
, tid_t tid
)
530 TRACE("(%p, %d, %s)\n", This
, msiHandle
, debugstr_guid(get_riid_from_tid(tid
)));
532 This
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
533 This
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
536 This
->msiHandle
= msiHandle
;
543 * ListEnumerator methods
546 static inline ListEnumerator
*impl_from_IEnumVARIANT(IEnumVARIANT
* iface
)
548 return CONTAINING_RECORD(iface
, ListEnumerator
, IEnumVARIANT_iface
);
551 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
,
554 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
556 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
558 if (ppvObject
== NULL
)
563 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
564 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
566 *ppvObject
= &This
->IEnumVARIANT_iface
;
570 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
571 return E_NOINTERFACE
;
574 IEnumVARIANT_AddRef(iface
);
578 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
580 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
582 TRACE("(%p/%p)\n", iface
, This
);
584 return InterlockedIncrement(&This
->ref
);
587 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
589 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
590 ULONG ref
= InterlockedDecrement(&This
->ref
);
592 TRACE("(%p/%p)\n", iface
, This
);
596 if (This
->list
) IDispatch_Release(&This
->list
->autoobj
.IDispatch_iface
);
603 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
* rgVar
,
606 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
609 TRACE("(%p, %uld, %p, %p)\n", iface
, celt
, rgVar
, fetched
);
611 if (fetched
) *fetched
= 0;
616 for (local
= 0; local
< celt
; local
++)
617 VariantInit(&rgVar
[local
]);
619 for (i
= This
->pos
, local
= 0; i
< This
->list
->count
&& local
< celt
; i
++, local
++)
620 VariantCopy(&rgVar
[local
], &This
->list
->data
[i
]);
622 if (fetched
) *fetched
= local
;
625 return (local
< celt
) ? S_FALSE
: S_OK
;
628 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
630 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
632 TRACE("(%p,%uld)\n", iface
, celt
);
635 if (This
->pos
>= This
->list
->count
)
637 This
->pos
= This
->list
->count
;
644 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
646 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
648 TRACE("(%p)\n", iface
);
654 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
656 ListEnumerator
*This
= impl_from_IEnumVARIANT(iface
);
659 TRACE("(%p,%p)\n", iface
, ppEnum
);
665 hr
= create_list_enumerator(This
->list
, (LPVOID
*)ppEnum
);
668 if (*ppEnum
) IEnumVARIANT_Release(*ppEnum
);
675 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
677 ListEnumerator_QueryInterface
,
678 ListEnumerator_AddRef
,
679 ListEnumerator_Release
,
682 ListEnumerator_Reset
,
686 /* Create a list enumerator, placing the result in the pointer ppObj. */
687 static HRESULT
create_list_enumerator(ListObject
*list
, void **ppObj
)
689 ListEnumerator
*object
;
691 TRACE("(%p, %p)\n", list
, ppObj
);
693 object
= msi_alloc(sizeof(ListEnumerator
));
695 /* Set all the VTable references */
696 object
->IEnumVARIANT_iface
.lpVtbl
= &ListEnumerator_Vtbl
;
699 /* Store data that was passed */
702 if (list
) IDispatch_AddRef(&list
->autoobj
.IDispatch_iface
);
709 * Individual Object Invocation Functions
712 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
713 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
714 using DispGetParam/VariantChangeType. */
715 static HRESULT
DispGetParam_CopyOnly(
716 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
717 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
718 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
720 /* position is counted backwards */
723 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
724 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
725 if (*position
< pdispparams
->cArgs
) {
726 /* positional arg? */
727 pos
= pdispparams
->cArgs
- *position
- 1;
729 /* FIXME: is this how to handle named args? */
730 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
731 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
733 if (pos
==pdispparams
->cNamedArgs
)
734 return DISP_E_PARAMNOTFOUND
;
737 return VariantCopyInd(pvarResult
,
738 &pdispparams
->rgvarg
[pos
]);
741 static HRESULT
summaryinfo_invoke(
742 AutomationObject
* This
,
747 DISPPARAMS
* pDispParams
,
749 EXCEPINFO
* pExcepInfo
,
753 VARIANTARG varg0
, varg1
;
754 FILETIME ft
, ftlocal
;
761 switch (dispIdMember
)
763 case DISPID_SUMMARYINFO_PROPERTY
:
764 if (wFlags
& DISPATCH_PROPERTYGET
)
772 static WCHAR szEmpty
[] = {0};
774 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
775 if (FAILED(hr
)) return hr
;
776 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
777 &ft
, szEmpty
, &size
);
778 if (ret
!= ERROR_SUCCESS
&&
779 ret
!= ERROR_MORE_DATA
)
781 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
782 return DISP_E_EXCEPTION
;
792 V_VT(pVarResult
) = VT_I4
;
793 V_I4(pVarResult
) = value
;
797 if (!(str
= msi_alloc(++size
* sizeof(WCHAR
))))
798 ERR("Out of memory\n");
799 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
800 NULL
, str
, &size
)) != ERROR_SUCCESS
)
801 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
804 V_VT(pVarResult
) = VT_BSTR
;
805 V_BSTR(pVarResult
) = SysAllocString(str
);
811 FileTimeToLocalFileTime(&ft
, &ftlocal
);
812 FileTimeToSystemTime(&ftlocal
, &st
);
813 SystemTimeToVariantTime(&st
, &date
);
815 V_VT(pVarResult
) = VT_DATE
;
816 V_DATE(pVarResult
) = date
;
820 ERR("Unhandled variant type %d\n", type
);
823 else if (wFlags
& DISPATCH_PROPERTYPUT
)
825 UINT posValue
= DISPID_PROPERTYPUT
;
827 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
828 if (FAILED(hr
)) return hr
;
829 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
832 *puArgErr
= posValue
;
836 switch (V_VT(&varg1
))
840 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
844 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
845 SystemTimeToFileTime(&st
, &ftlocal
);
846 LocalFileTimeToFileTime(&ftlocal
, &ft
);
847 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
851 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
855 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
856 VariantClear(&varg1
);
857 return DISP_E_EXCEPTION
;
860 if (ret
!= ERROR_SUCCESS
)
862 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
863 return DISP_E_EXCEPTION
;
866 else return DISP_E_MEMBERNOTFOUND
;
869 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
870 if (wFlags
& DISPATCH_PROPERTYGET
) {
872 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
873 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
876 V_VT(pVarResult
) = VT_I4
;
877 V_I4(pVarResult
) = count
;
880 else return DISP_E_MEMBERNOTFOUND
;
884 return DISP_E_MEMBERNOTFOUND
;
887 VariantClear(&varg1
);
888 VariantClear(&varg0
);
893 static HRESULT
record_invoke(
894 AutomationObject
* This
,
899 DISPPARAMS
* pDispParams
,
901 EXCEPINFO
* pExcepInfo
,
907 VARIANTARG varg0
, varg1
;
913 switch (dispIdMember
)
915 case DISPID_RECORD_FIELDCOUNT
:
916 if (wFlags
& DISPATCH_PROPERTYGET
) {
917 V_VT(pVarResult
) = VT_I4
;
918 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
920 else return DISP_E_MEMBERNOTFOUND
;
923 case DISPID_RECORD_STRINGDATA
:
924 if (wFlags
& DISPATCH_PROPERTYGET
) {
925 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
926 if (FAILED(hr
)) return hr
;
927 V_VT(pVarResult
) = VT_BSTR
;
928 V_BSTR(pVarResult
) = NULL
;
929 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
931 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
932 ERR("Out of memory\n");
933 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
934 V_BSTR(pVarResult
) = SysAllocString(szString
);
937 if (ret
!= ERROR_SUCCESS
)
938 ERR("MsiRecordGetString returned %d\n", ret
);
939 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
940 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
941 if (FAILED(hr
)) return hr
;
942 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
943 if (FAILED(hr
)) return hr
;
944 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
946 VariantClear(&varg1
);
947 ERR("MsiRecordSetString returned %d\n", ret
);
948 return DISP_E_EXCEPTION
;
951 else return DISP_E_MEMBERNOTFOUND
;
954 case DISPID_RECORD_INTEGERDATA
:
955 if (wFlags
& DISPATCH_PROPERTYGET
) {
956 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
957 if (FAILED(hr
)) return hr
;
958 V_VT(pVarResult
) = VT_I4
;
959 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
960 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
961 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
962 if (FAILED(hr
)) return hr
;
963 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
964 if (FAILED(hr
)) return hr
;
965 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
967 ERR("MsiRecordSetInteger returned %d\n", ret
);
968 return DISP_E_EXCEPTION
;
971 else return DISP_E_MEMBERNOTFOUND
;
975 return DISP_E_MEMBERNOTFOUND
;
978 VariantClear(&varg1
);
979 VariantClear(&varg0
);
984 static HRESULT
create_record(MSIHANDLE msiHandle
, IDispatch
**disp
)
986 AutomationObject
*record
;
989 record
= msi_alloc(sizeof(*record
));
990 if (!record
) return E_OUTOFMEMORY
;
992 hr
= init_automation_object(record
, msiHandle
, Record_tid
);
999 *disp
= &record
->IDispatch_iface
;
1004 static HRESULT
list_invoke(
1005 AutomationObject
* This
,
1006 DISPID dispIdMember
,
1010 DISPPARAMS
* pDispParams
,
1011 VARIANT
* pVarResult
,
1012 EXCEPINFO
* pExcepInfo
,
1015 ListObject
*list
= (ListObject
*)This
;
1016 IUnknown
*pUnk
= NULL
;
1019 switch (dispIdMember
)
1021 case DISPID_LIST__NEWENUM
:
1022 if (wFlags
& DISPATCH_METHOD
) {
1023 V_VT(pVarResult
) = VT_UNKNOWN
;
1024 if (SUCCEEDED(hr
= create_list_enumerator(list
, (LPVOID
*)&pUnk
)))
1025 V_UNKNOWN(pVarResult
) = pUnk
;
1027 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr
);
1029 else return DISP_E_MEMBERNOTFOUND
;
1032 case DISPID_LIST_ITEM
:
1033 if (wFlags
& DISPATCH_PROPERTYGET
) {
1036 VariantInit(&index
);
1037 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &index
, puArgErr
);
1038 if (FAILED(hr
)) return hr
;
1039 if (V_I4(&index
) < 0 || V_I4(&index
) >= list
->count
)
1040 return DISP_E_BADINDEX
;
1041 VariantCopy(pVarResult
, &list
->data
[V_I4(&index
)]);
1043 else return DISP_E_MEMBERNOTFOUND
;
1046 case DISPID_LIST_COUNT
:
1047 if (wFlags
& DISPATCH_PROPERTYGET
) {
1048 V_VT(pVarResult
) = VT_I4
;
1049 V_I4(pVarResult
) = list
->count
;
1051 else return DISP_E_MEMBERNOTFOUND
;
1055 return DISP_E_MEMBERNOTFOUND
;
1061 static void list_free(AutomationObject
*This
)
1063 ListObject
*list
= (ListObject
*)This
;
1066 for (i
= 0; i
< list
->count
; i
++)
1067 VariantClear(&list
->data
[i
]);
1068 msi_free(list
->data
);
1071 static HRESULT
get_products_count(const WCHAR
*product
, int *len
)
1077 WCHAR dataW
[GUID_SIZE
];
1080 /* all or related only */
1082 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1084 ret
= MsiEnumProductsW(i
, dataW
);
1086 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1088 if (ret
!= ERROR_SUCCESS
)
1089 return DISP_E_EXCEPTION
;
1099 static HRESULT
create_list(const WCHAR
*product
, IDispatch
**dispatch
)
1105 list
= msi_alloc_zero(sizeof(ListObject
));
1106 if (!list
) return E_OUTOFMEMORY
;
1108 hr
= init_automation_object(&list
->autoobj
, 0, StringList_tid
);
1115 *dispatch
= &list
->autoobj
.IDispatch_iface
;
1117 hr
= get_products_count(product
, &list
->count
);
1120 IDispatch_Release(*dispatch
);
1124 list
->data
= msi_alloc(list
->count
*sizeof(VARIANT
));
1127 IDispatch_Release(*dispatch
);
1128 return E_OUTOFMEMORY
;
1131 for (i
= 0; i
< list
->count
; i
++)
1133 WCHAR dataW
[GUID_SIZE
];
1136 /* all or related only */
1138 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1140 ret
= MsiEnumProductsW(i
, dataW
);
1142 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1144 V_VT(&list
->data
[i
]) = VT_BSTR
;
1145 V_BSTR(&list
->data
[i
]) = SysAllocString(dataW
);
1151 static HRESULT
view_invoke(
1152 AutomationObject
* This
,
1153 DISPID dispIdMember
,
1157 DISPPARAMS
* pDispParams
,
1158 VARIANT
* pVarResult
,
1159 EXCEPINFO
* pExcepInfo
,
1162 MSIHANDLE msiHandle
;
1164 VARIANTARG varg0
, varg1
;
1167 VariantInit(&varg0
);
1168 VariantInit(&varg1
);
1170 switch (dispIdMember
)
1172 case DISPID_VIEW_EXECUTE
:
1173 if (wFlags
& DISPATCH_METHOD
)
1175 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1176 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1177 MsiViewExecute(This
->msiHandle
, ((AutomationObject
*)V_DISPATCH(&varg0
))->msiHandle
);
1179 MsiViewExecute(This
->msiHandle
, 0);
1181 else return DISP_E_MEMBERNOTFOUND
;
1184 case DISPID_VIEW_FETCH
:
1185 if (wFlags
& DISPATCH_METHOD
)
1187 V_VT(pVarResult
) = VT_DISPATCH
;
1188 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1190 if (FAILED(hr
= create_record(msiHandle
, &V_DISPATCH(pVarResult
))))
1191 ERR("Failed to create Record object, hresult 0x%08x\n", hr
);
1193 else if (ret
== ERROR_NO_MORE_ITEMS
)
1194 V_DISPATCH(pVarResult
) = NULL
;
1197 ERR("MsiViewFetch returned %d\n", ret
);
1198 return DISP_E_EXCEPTION
;
1201 else return DISP_E_MEMBERNOTFOUND
;
1204 case DISPID_VIEW_MODIFY
:
1205 if (wFlags
& DISPATCH_METHOD
)
1207 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1208 if (FAILED(hr
)) return hr
;
1209 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1210 if (FAILED(hr
)) return hr
;
1211 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1212 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1214 VariantClear(&varg1
);
1215 ERR("MsiViewModify returned %d\n", ret
);
1216 return DISP_E_EXCEPTION
;
1219 else return DISP_E_MEMBERNOTFOUND
;
1222 case DISPID_VIEW_CLOSE
:
1223 if (wFlags
& DISPATCH_METHOD
)
1225 MsiViewClose(This
->msiHandle
);
1227 else return DISP_E_MEMBERNOTFOUND
;
1231 return DISP_E_MEMBERNOTFOUND
;
1234 VariantClear(&varg1
);
1235 VariantClear(&varg0
);
1240 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1241 DISPPARAMS
* pDispParams
,
1242 VARIANT
* pVarResult
,
1243 EXCEPINFO
* pExcepInfo
,
1246 if (!(wFlags
& DISPATCH_METHOD
))
1247 return DISP_E_MEMBERNOTFOUND
;
1251 VariantInit(pVarResult
);
1255 HRESULT
database_invoke(
1256 AutomationObject
* This
,
1257 DISPID dispIdMember
,
1261 DISPPARAMS
* pDispParams
,
1262 VARIANT
* pVarResult
,
1263 EXCEPINFO
* pExcepInfo
,
1266 IDispatch
*dispatch
= NULL
;
1267 MSIHANDLE msiHandle
;
1269 VARIANTARG varg0
, varg1
;
1272 VariantInit(&varg0
);
1273 VariantInit(&varg1
);
1275 switch (dispIdMember
)
1277 case DISPID_DATABASE_SUMMARYINFORMATION
:
1278 if (wFlags
& DISPATCH_PROPERTYGET
)
1280 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1284 V_VT(pVarResult
) = VT_DISPATCH
;
1285 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1287 hr
= create_summaryinfo(msiHandle
, &dispatch
);
1289 V_DISPATCH(pVarResult
) = dispatch
;
1291 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr
);
1295 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1296 return DISP_E_EXCEPTION
;
1299 else return DISP_E_MEMBERNOTFOUND
;
1302 case DISPID_DATABASE_OPENVIEW
:
1303 if (wFlags
& DISPATCH_METHOD
)
1305 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1306 if (FAILED(hr
)) return hr
;
1307 V_VT(pVarResult
) = VT_DISPATCH
;
1308 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1310 if (SUCCEEDED(hr
= create_view(msiHandle
, &dispatch
)))
1311 V_DISPATCH(pVarResult
) = dispatch
;
1313 ERR("Failed to create View object, hresult 0x%08x\n", hr
);
1317 VariantClear(&varg0
);
1318 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1319 return DISP_E_EXCEPTION
;
1322 else return DISP_E_MEMBERNOTFOUND
;
1325 case DISPID_INSTALLER_LASTERRORRECORD
:
1326 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1327 pVarResult
, pExcepInfo
,
1331 return DISP_E_MEMBERNOTFOUND
;
1334 VariantClear(&varg1
);
1335 VariantClear(&varg0
);
1340 static HRESULT
session_invoke(
1341 AutomationObject
* This
,
1342 DISPID dispIdMember
,
1346 DISPPARAMS
* pDispParams
,
1347 VARIANT
* pVarResult
,
1348 EXCEPINFO
* pExcepInfo
,
1351 SessionObject
*session
= (SessionObject
*)This
;
1354 MSIHANDLE msiHandle
;
1357 INSTALLSTATE iInstalled
, iAction
;
1358 VARIANTARG varg0
, varg1
;
1361 VariantInit(&varg0
);
1362 VariantInit(&varg1
);
1364 switch (dispIdMember
)
1366 case DISPID_SESSION_INSTALLER
:
1367 if (wFlags
& DISPATCH_PROPERTYGET
) {
1368 V_VT(pVarResult
) = VT_DISPATCH
;
1369 IDispatch_AddRef(session
->installer
);
1370 V_DISPATCH(pVarResult
) = session
->installer
;
1372 else return DISP_E_MEMBERNOTFOUND
;
1375 case DISPID_SESSION_PROPERTY
:
1376 if (wFlags
& DISPATCH_PROPERTYGET
) {
1377 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1378 if (FAILED(hr
)) return hr
;
1379 V_VT(pVarResult
) = VT_BSTR
;
1380 V_BSTR(pVarResult
) = NULL
;
1381 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1383 if (!(szString
= msi_alloc((++dwLen
)*sizeof(WCHAR
))))
1384 ERR("Out of memory\n");
1385 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1386 V_BSTR(pVarResult
) = SysAllocString(szString
);
1389 if (ret
!= ERROR_SUCCESS
)
1390 ERR("MsiGetProperty returned %d\n", ret
);
1391 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1392 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1393 if (FAILED(hr
)) return hr
;
1394 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1396 VariantClear(&varg0
);
1399 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1401 VariantClear(&varg0
);
1402 VariantClear(&varg1
);
1403 ERR("MsiSetProperty returned %d\n", ret
);
1404 return DISP_E_EXCEPTION
;
1407 else return DISP_E_MEMBERNOTFOUND
;
1410 case DISPID_SESSION_LANGUAGE
:
1411 if (wFlags
& DISPATCH_PROPERTYGET
) {
1412 langId
= MsiGetLanguage(This
->msiHandle
);
1413 V_VT(pVarResult
) = VT_I4
;
1414 V_I4(pVarResult
) = langId
;
1416 else return DISP_E_MEMBERNOTFOUND
;
1419 case DISPID_SESSION_MODE
:
1420 if (wFlags
& DISPATCH_PROPERTYGET
) {
1421 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1422 if (FAILED(hr
)) return hr
;
1423 V_VT(pVarResult
) = VT_BOOL
;
1424 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
));
1425 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1426 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1427 if (FAILED(hr
)) return hr
;
1428 hr
= DispGetParam(pDispParams
, 1, VT_BOOL
, &varg1
, puArgErr
);
1429 if (FAILED(hr
)) return hr
;
1430 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1432 ERR("MsiSetMode returned %d\n", ret
);
1433 return DISP_E_EXCEPTION
;
1436 else return DISP_E_MEMBERNOTFOUND
;
1439 case DISPID_SESSION_DATABASE
:
1440 if (wFlags
& DISPATCH_PROPERTYGET
) {
1441 V_VT(pVarResult
) = VT_DISPATCH
;
1442 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1444 IDispatch
*dispatch
;
1446 if (SUCCEEDED(hr
= create_database(msiHandle
, &dispatch
)))
1447 V_DISPATCH(pVarResult
) = dispatch
;
1449 ERR("Failed to create Database object, hresult 0x%08x\n", hr
);
1453 ERR("MsiGetActiveDatabase failed\n");
1454 return DISP_E_EXCEPTION
;
1457 else return DISP_E_MEMBERNOTFOUND
;
1460 case DISPID_SESSION_DOACTION
:
1461 if (wFlags
& DISPATCH_METHOD
) {
1462 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1463 if (FAILED(hr
)) return hr
;
1464 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1465 V_VT(pVarResult
) = VT_I4
;
1468 case ERROR_FUNCTION_NOT_CALLED
:
1469 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1472 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1474 case ERROR_INSTALL_USEREXIT
:
1475 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1477 case ERROR_INSTALL_FAILURE
:
1478 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1480 case ERROR_INSTALL_SUSPEND
:
1481 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1483 case ERROR_MORE_DATA
:
1484 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1486 case ERROR_INVALID_HANDLE_STATE
:
1487 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1489 case ERROR_INVALID_DATA
:
1490 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1493 VariantClear(&varg0
);
1494 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1495 return DISP_E_EXCEPTION
;
1498 else return DISP_E_MEMBERNOTFOUND
;
1501 case DISPID_SESSION_EVALUATECONDITION
:
1502 if (wFlags
& DISPATCH_METHOD
) {
1503 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1504 if (FAILED(hr
)) return hr
;
1505 V_VT(pVarResult
) = VT_I4
;
1506 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1508 else return DISP_E_MEMBERNOTFOUND
;
1511 case DISPID_SESSION_MESSAGE
:
1512 if(!(wFlags
& DISPATCH_METHOD
))
1513 return DISP_E_MEMBERNOTFOUND
;
1515 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1516 if (FAILED(hr
)) return hr
;
1517 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1518 if (FAILED(hr
)) return hr
;
1520 V_VT(pVarResult
) = VT_I4
;
1522 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((AutomationObject
*)V_DISPATCH(&varg1
))->msiHandle
);
1525 case DISPID_SESSION_SETINSTALLLEVEL
:
1526 if (wFlags
& DISPATCH_METHOD
) {
1527 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1528 if (FAILED(hr
)) return hr
;
1529 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1531 ERR("MsiSetInstallLevel returned %d\n", ret
);
1532 return DISP_E_EXCEPTION
;
1535 else return DISP_E_MEMBERNOTFOUND
;
1538 case DISPID_SESSION_FEATURECURRENTSTATE
:
1539 if (wFlags
& DISPATCH_PROPERTYGET
) {
1540 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1541 if (FAILED(hr
)) return hr
;
1542 V_VT(pVarResult
) = VT_I4
;
1543 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1544 V_I4(pVarResult
) = iInstalled
;
1547 ERR("MsiGetFeatureState returned %d\n", ret
);
1548 V_I4(pVarResult
) = msiInstallStateUnknown
;
1551 else return DISP_E_MEMBERNOTFOUND
;
1554 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1555 if (wFlags
& DISPATCH_PROPERTYGET
) {
1556 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1557 if (FAILED(hr
)) return hr
;
1558 V_VT(pVarResult
) = VT_I4
;
1559 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1560 V_I4(pVarResult
) = iAction
;
1563 ERR("MsiGetFeatureState returned %d\n", ret
);
1564 V_I4(pVarResult
) = msiInstallStateUnknown
;
1566 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1567 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1568 if (FAILED(hr
)) return hr
;
1569 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1571 VariantClear(&varg0
);
1574 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1576 VariantClear(&varg0
);
1577 ERR("MsiSetFeatureState returned %d\n", ret
);
1578 return DISP_E_EXCEPTION
;
1581 else return DISP_E_MEMBERNOTFOUND
;
1585 return DISP_E_MEMBERNOTFOUND
;
1588 VariantClear(&varg1
);
1589 VariantClear(&varg0
);
1594 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1595 * registry value type. Used by Installer::RegistryValue. */
1596 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1598 static const WCHAR szREG_BINARY
[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1599 static const WCHAR szREG_
[] = { '(','R','E','G','_','?','?',')',0 };
1600 WCHAR
*szString
= (WCHAR
*)lpData
;
1601 LPWSTR szNewString
= NULL
;
1602 DWORD dwNewSize
= 0;
1607 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1608 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1609 idx
= (dwSize
/sizeof(WCHAR
))-1;
1610 while (idx
>= 0 && !szString
[idx
]) idx
--;
1611 for (; idx
>= 0; idx
--)
1612 if (!szString
[idx
]) szString
[idx
] = '\n';
1615 V_VT(pVarResult
) = VT_BSTR
;
1616 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1620 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1621 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1622 else if (!(szNewString
= msi_alloc(dwNewSize
* sizeof(WCHAR
))))
1623 ERR("Out of memory\n");
1624 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1625 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1628 V_VT(pVarResult
) = VT_BSTR
;
1629 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1631 msi_free(szNewString
);
1635 V_VT(pVarResult
) = VT_I4
;
1636 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1640 V_VT(pVarResult
) = VT_BSTR
;
1641 V_BSTR(pVarResult
) = SysAllocString(szREG_
); /* Weird string, don't know why native returns it */
1645 V_VT(pVarResult
) = VT_BSTR
;
1646 V_BSTR(pVarResult
) = SysAllocString(szREG_BINARY
);
1650 V_VT(pVarResult
) = VT_EMPTY
;
1654 FIXME("Unhandled registry value type %d\n", dwType
);
1658 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1659 DISPPARAMS
* pDispParams
,
1660 VARIANT
* pVarResult
,
1661 EXCEPINFO
* pExcepInfo
,
1668 if (!(wFlags
& DISPATCH_METHOD
))
1669 return DISP_E_MEMBERNOTFOUND
;
1671 VariantInit(&varg0
);
1672 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1676 V_VT(pVarResult
) = VT_DISPATCH
;
1678 hrec
= MsiCreateRecord(V_I4(&varg0
));
1680 return DISP_E_EXCEPTION
;
1682 return create_record(hrec
, &V_DISPATCH(pVarResult
));
1685 static HRESULT
InstallerImpl_OpenPackage(AutomationObject
* This
,
1687 DISPPARAMS
* pDispParams
,
1688 VARIANT
* pVarResult
,
1689 EXCEPINFO
* pExcepInfo
,
1695 IDispatch
* dispatch
;
1696 VARIANTARG varg0
, varg1
;
1698 if (!(wFlags
& DISPATCH_METHOD
))
1699 return DISP_E_MEMBERNOTFOUND
;
1701 if (pDispParams
->cArgs
== 0)
1702 return DISP_E_TYPEMISMATCH
;
1704 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1705 return DISP_E_TYPEMISMATCH
;
1707 VariantInit(&varg0
);
1708 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1712 VariantInit(&varg1
);
1713 if (pDispParams
->cArgs
== 2)
1715 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1721 V_VT(&varg1
) = VT_I4
;
1725 V_VT(pVarResult
) = VT_DISPATCH
;
1727 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1728 if (ret
!= ERROR_SUCCESS
)
1730 hr
= DISP_E_EXCEPTION
;
1734 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1736 V_DISPATCH(pVarResult
) = dispatch
;
1739 VariantClear(&varg0
);
1740 VariantClear(&varg1
);
1744 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1745 DISPPARAMS
* pDispParams
,
1746 VARIANT
* pVarResult
,
1747 EXCEPINFO
* pExcepInfo
,
1753 if (!(wFlags
& DISPATCH_METHOD
))
1754 return DISP_E_MEMBERNOTFOUND
;
1756 VariantInit(&varg0
);
1757 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1761 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1763 VariantInit(pVarResult
);
1765 VariantClear(&varg0
);
1769 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1770 DISPPARAMS
* pDispParams
,
1771 VARIANT
* pVarResult
,
1772 EXCEPINFO
* pExcepInfo
,
1778 IDispatch
* dispatch
;
1779 VARIANTARG varg0
, varg1
;
1781 if (!(wFlags
& DISPATCH_METHOD
))
1782 return DISP_E_MEMBERNOTFOUND
;
1784 VariantInit(&varg0
);
1785 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1789 VariantInit(&varg1
);
1790 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1794 V_VT(pVarResult
) = VT_DISPATCH
;
1796 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1797 if (ret
!= ERROR_SUCCESS
)
1799 hr
= DISP_E_EXCEPTION
;
1803 hr
= create_database(hdb
, &dispatch
);
1805 V_DISPATCH(pVarResult
) = dispatch
;
1808 VariantClear(&varg0
);
1809 VariantClear(&varg1
);
1813 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1814 DISPPARAMS
* pDispParams
,
1815 VARIANT
* pVarResult
,
1816 EXCEPINFO
* pExcepInfo
,
1819 if (!(wFlags
& DISPATCH_METHOD
))
1820 return DISP_E_MEMBERNOTFOUND
;
1824 VariantInit(pVarResult
);
1828 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1829 DISPPARAMS
* pDispParams
,
1830 VARIANT
* pVarResult
,
1831 EXCEPINFO
* pExcepInfo
,
1838 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1839 return DISP_E_MEMBERNOTFOUND
;
1841 if (wFlags
& DISPATCH_PROPERTYPUT
)
1843 VariantInit(&varg0
);
1844 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1848 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1849 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1850 return DISP_E_EXCEPTION
;
1852 else if (wFlags
& DISPATCH_PROPERTYGET
)
1854 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1855 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1856 return DISP_E_EXCEPTION
;
1858 V_VT(pVarResult
) = VT_I4
;
1859 V_I4(pVarResult
) = ui
;
1865 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1866 DISPPARAMS
* pDispParams
,
1867 VARIANT
* pVarResult
,
1868 EXCEPINFO
* pExcepInfo
,
1871 if (!(wFlags
& DISPATCH_METHOD
))
1872 return DISP_E_MEMBERNOTFOUND
;
1876 VariantInit(pVarResult
);
1880 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1881 DISPPARAMS
* pDispParams
,
1882 VARIANT
* pVarResult
,
1883 EXCEPINFO
* pExcepInfo
,
1888 VARIANTARG varg0
, varg1
;
1890 if (!(wFlags
& DISPATCH_METHOD
))
1891 return DISP_E_MEMBERNOTFOUND
;
1893 VariantInit(&varg0
);
1894 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1898 VariantInit(&varg1
);
1899 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1903 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1904 if (ret
!= ERROR_SUCCESS
)
1906 hr
= DISP_E_EXCEPTION
;
1911 VariantClear(&varg0
);
1912 VariantClear(&varg1
);
1916 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1917 VARIANT
* pVarResult
,
1918 EXCEPINFO
* pExcepInfo
,
1922 DLLVERSIONINFO verinfo
;
1923 WCHAR version
[MAX_PATH
];
1925 static const WCHAR format
[] = {
1926 '%','d','.','%','d','.','%','d','.','%','d',0};
1928 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1929 return DISP_E_MEMBERNOTFOUND
;
1931 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1932 hr
= DllGetVersion(&verinfo
);
1936 sprintfW(version
, format
, verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1937 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1939 V_VT(pVarResult
) = VT_BSTR
;
1940 V_BSTR(pVarResult
) = SysAllocString(version
);
1944 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1945 DISPPARAMS
* pDispParams
,
1946 VARIANT
* pVarResult
,
1947 EXCEPINFO
* pExcepInfo
,
1950 if (!(wFlags
& DISPATCH_METHOD
))
1951 return DISP_E_MEMBERNOTFOUND
;
1955 VariantInit(pVarResult
);
1959 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
1960 DISPPARAMS
* pDispParams
,
1961 VARIANT
* pVarResult
,
1962 EXCEPINFO
* pExcepInfo
,
1970 LPWSTR szString
= NULL
;
1971 VARIANTARG varg0
, varg1
, varg2
;
1973 if (!(wFlags
& DISPATCH_METHOD
))
1974 return DISP_E_MEMBERNOTFOUND
;
1976 VariantInit(&varg0
);
1977 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1981 VariantInit(&varg1
);
1982 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1986 /* Save valuePos so we can save puArgErr if we are unable to do our type
1990 VariantInit(&varg2
);
1991 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
1995 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
1996 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
1998 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
2001 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
2003 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2004 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
2006 hr
= DISP_E_BADINDEX
;
2010 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2011 switch (V_VT(&varg2
))
2013 /* Return VT_BOOL clarifying whether registry key exists or not. */
2015 V_VT(pVarResult
) = VT_BOOL
;
2016 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
);
2019 /* Return the value of specified key if it exists. */
2021 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
2022 NULL
, NULL
, NULL
, &size
);
2023 if (ret
!= ERROR_SUCCESS
)
2025 hr
= DISP_E_BADINDEX
;
2029 szString
= msi_alloc(size
);
2036 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
2037 &type
, (LPBYTE
)szString
, &size
);
2038 if (ret
!= ERROR_SUCCESS
)
2041 hr
= DISP_E_BADINDEX
;
2045 variant_from_registry_value(pVarResult
, type
,
2046 (LPBYTE
)szString
, size
);
2050 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2052 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
2055 if (hr
== DISP_E_TYPEMISMATCH
)
2056 *puArgErr
= posValue
;
2061 /* Retrieve class name or maximum value name or subkey name size. */
2063 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
2064 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2065 else if (V_I4(&varg2
) > 0)
2066 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
2067 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
2068 else /* V_I4(&varg2) < 0 */
2069 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
2070 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2072 if (ret
!= ERROR_SUCCESS
)
2075 szString
= msi_alloc(++size
* sizeof(WCHAR
));
2083 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
2084 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2085 else if (V_I4(&varg2
) > 0)
2086 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
2087 &size
, 0, 0, NULL
, NULL
);
2088 else /* V_I4(&varg2) < 0 */
2089 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
2091 if (ret
== ERROR_SUCCESS
)
2093 V_VT(pVarResult
) = VT_BSTR
;
2094 V_BSTR(pVarResult
) = SysAllocString(szString
);
2101 VariantClear(&varg0
);
2102 VariantClear(&varg1
);
2103 VariantClear(&varg2
);
2108 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2109 DISPPARAMS
* pDispParams
,
2110 VARIANT
* pVarResult
,
2111 EXCEPINFO
* pExcepInfo
,
2114 if (!(wFlags
& DISPATCH_METHOD
))
2115 return DISP_E_MEMBERNOTFOUND
;
2119 VariantInit(pVarResult
);
2123 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2124 DISPPARAMS
* pDispParams
,
2125 VARIANT
* pVarResult
,
2126 EXCEPINFO
* pExcepInfo
,
2129 if (!(wFlags
& DISPATCH_METHOD
))
2130 return DISP_E_MEMBERNOTFOUND
;
2134 VariantInit(pVarResult
);
2138 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2139 DISPPARAMS
* pDispParams
,
2140 VARIANT
* pVarResult
,
2141 EXCEPINFO
* pExcepInfo
,
2144 if (!(wFlags
& DISPATCH_METHOD
))
2145 return DISP_E_MEMBERNOTFOUND
;
2149 VariantInit(pVarResult
);
2153 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2154 DISPPARAMS
* pDispParams
,
2155 VARIANT
* pVarResult
,
2156 EXCEPINFO
* pExcepInfo
,
2159 if (!(wFlags
& DISPATCH_METHOD
))
2160 return DISP_E_MEMBERNOTFOUND
;
2164 VariantInit(pVarResult
);
2168 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2169 DISPPARAMS
* pDispParams
,
2170 VARIANT
* pVarResult
,
2171 EXCEPINFO
* pExcepInfo
,
2177 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2178 return DISP_E_MEMBERNOTFOUND
;
2180 VariantInit(&varg0
);
2181 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2185 V_VT(pVarResult
) = VT_I4
;
2186 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2188 VariantClear(&varg0
);
2192 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2193 DISPPARAMS
* pDispParams
,
2194 VARIANT
* pVarResult
,
2195 EXCEPINFO
* pExcepInfo
,
2202 VARIANTARG varg0
, varg1
;
2204 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2205 return DISP_E_MEMBERNOTFOUND
;
2207 VariantInit(&varg0
);
2208 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2212 VariantInit(&varg1
);
2213 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2217 V_VT(pVarResult
) = VT_BSTR
;
2218 V_BSTR(pVarResult
) = NULL
;
2220 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2221 if (ret
!= ERROR_SUCCESS
)
2223 hr
= DISP_E_EXCEPTION
;
2227 str
= msi_alloc(++size
* sizeof(WCHAR
));
2234 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2235 if (ret
!= ERROR_SUCCESS
)
2237 hr
= DISP_E_EXCEPTION
;
2241 V_BSTR(pVarResult
) = SysAllocString(str
);
2246 VariantClear(&varg0
);
2247 VariantClear(&varg1
);
2251 static HRESULT
InstallerImpl_Products(WORD flags
,
2252 DISPPARAMS
* pDispParams
,
2254 EXCEPINFO
* pExcepInfo
,
2257 IDispatch
*dispatch
;
2260 if (!(flags
& DISPATCH_PROPERTYGET
))
2261 return DISP_E_MEMBERNOTFOUND
;
2263 hr
= create_list(NULL
, &dispatch
);
2267 V_VT(result
) = VT_DISPATCH
;
2268 V_DISPATCH(result
) = dispatch
;
2273 static HRESULT
InstallerImpl_RelatedProducts(WORD flags
,
2274 DISPPARAMS
* pDispParams
,
2276 EXCEPINFO
* pExcepInfo
,
2279 IDispatch
* dispatch
;
2283 if (!(flags
& DISPATCH_PROPERTYGET
))
2284 return DISP_E_MEMBERNOTFOUND
;
2286 VariantInit(&related
);
2287 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &related
, puArgErr
);
2291 hr
= create_list(V_BSTR(&related
), &dispatch
);
2292 VariantClear(&related
);
2294 V_VT(result
) = VT_DISPATCH
;
2295 V_DISPATCH(result
) = dispatch
;
2300 static HRESULT
installer_invoke(
2301 AutomationObject
* This
,
2302 DISPID dispIdMember
,
2306 DISPPARAMS
* pDispParams
,
2307 VARIANT
* pVarResult
,
2308 EXCEPINFO
* pExcepInfo
,
2311 switch (dispIdMember
)
2313 case DISPID_INSTALLER_CREATERECORD
:
2314 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2315 pVarResult
, pExcepInfo
, puArgErr
);
2317 case DISPID_INSTALLER_OPENPACKAGE
:
2318 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2319 pVarResult
, pExcepInfo
, puArgErr
);
2321 case DISPID_INSTALLER_OPENPRODUCT
:
2322 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2323 pVarResult
, pExcepInfo
, puArgErr
);
2325 case DISPID_INSTALLER_OPENDATABASE
:
2326 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2327 pVarResult
, pExcepInfo
, puArgErr
);
2329 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2330 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2331 pVarResult
, pExcepInfo
,
2334 case DISPID_INSTALLER_UILEVEL
:
2335 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2336 pVarResult
, pExcepInfo
, puArgErr
);
2338 case DISPID_INSTALLER_ENABLELOG
:
2339 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2340 pVarResult
, pExcepInfo
, puArgErr
);
2342 case DISPID_INSTALLER_INSTALLPRODUCT
:
2343 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2344 pVarResult
, pExcepInfo
,
2347 case DISPID_INSTALLER_VERSION
:
2348 return InstallerImpl_Version(wFlags
, pVarResult
,
2349 pExcepInfo
, puArgErr
);
2351 case DISPID_INSTALLER_LASTERRORRECORD
:
2352 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2353 pVarResult
, pExcepInfo
,
2356 case DISPID_INSTALLER_REGISTRYVALUE
:
2357 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2358 pVarResult
, pExcepInfo
,
2361 case DISPID_INSTALLER_ENVIRONMENT
:
2362 return InstallerImpl_Environment(wFlags
, pDispParams
,
2363 pVarResult
, pExcepInfo
, puArgErr
);
2365 case DISPID_INSTALLER_FILEATTRIBUTES
:
2366 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2367 pVarResult
, pExcepInfo
,
2370 case DISPID_INSTALLER_FILESIZE
:
2371 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2372 pVarResult
, pExcepInfo
, puArgErr
);
2374 case DISPID_INSTALLER_FILEVERSION
:
2375 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2376 pVarResult
, pExcepInfo
, puArgErr
);
2378 case DISPID_INSTALLER_PRODUCTSTATE
:
2379 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2380 pVarResult
, pExcepInfo
, puArgErr
);
2382 case DISPID_INSTALLER_PRODUCTINFO
:
2383 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2384 pVarResult
, pExcepInfo
, puArgErr
);
2386 case DISPID_INSTALLER_PRODUCTS
:
2387 return InstallerImpl_Products(wFlags
, pDispParams
,
2388 pVarResult
, pExcepInfo
, puArgErr
);
2390 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2391 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2392 pVarResult
, pExcepInfo
,
2396 return DISP_E_MEMBERNOTFOUND
;
2400 HRESULT
create_msiserver(IUnknown
*outer
, void **ppObj
)
2402 AutomationObject
*installer
;
2405 TRACE("(%p %p)\n", outer
, ppObj
);
2408 return CLASS_E_NOAGGREGATION
;
2410 installer
= msi_alloc(sizeof(AutomationObject
));
2411 if (!installer
) return E_OUTOFMEMORY
;
2413 hr
= init_automation_object(installer
, 0, Installer_tid
);
2416 msi_free(installer
);
2420 *ppObj
= &installer
->IDispatch_iface
;
2425 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2427 SessionObject
*session
;
2430 session
= msi_alloc(sizeof(SessionObject
));
2431 if (!session
) return E_OUTOFMEMORY
;
2433 hr
= init_automation_object(&session
->autoobj
, msiHandle
, Session_tid
);
2440 session
->installer
= installer
;
2441 *disp
= &session
->autoobj
.IDispatch_iface
;
2446 static HRESULT
create_database(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2448 AutomationObject
*database
;
2451 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2453 database
= msi_alloc(sizeof(AutomationObject
));
2454 if (!database
) return E_OUTOFMEMORY
;
2456 hr
= init_automation_object(database
, msiHandle
, Database_tid
);
2463 *dispatch
= &database
->IDispatch_iface
;
2468 static HRESULT
create_view(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2470 AutomationObject
*view
;
2473 TRACE("(%d %p)\n", msiHandle
, dispatch
);
2475 view
= msi_alloc(sizeof(AutomationObject
));
2476 if (!view
) return E_OUTOFMEMORY
;
2478 hr
= init_automation_object(view
, msiHandle
, View_tid
);
2485 *dispatch
= &view
->IDispatch_iface
;
2490 static HRESULT
create_summaryinfo(MSIHANDLE msiHandle
, IDispatch
**disp
)
2492 AutomationObject
*info
;
2495 info
= msi_alloc(sizeof(*info
));
2496 if (!info
) return E_OUTOFMEMORY
;
2498 hr
= init_automation_object(info
, msiHandle
, SummaryInfo_tid
);
2505 *disp
= &info
->IDispatch_iface
;