2 * Implementation of OLE Automation for Microsoft Installer (msi.dll)
4 * Copyright 2007 Misha Koshelev
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
36 #include "msiserver.h"
37 #include "msiserver_dispids.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
41 #define REG_INDEX_CLASSES_ROOT 0
42 #define REG_INDEX_DYN_DATA 6
44 struct automation_object
;
49 /* function that is called from AutomationObject::Invoke, specific to this type of object */
50 HRESULT (*fn_invoke
)(struct automation_object
*, DISPID
, REFIID
, LCID
, WORD
, DISPPARAMS
*, VARIANT
*,
52 /* function that is called from AutomationObject::Release when the object is being freed
53 to free any private data structures (or NULL) */
54 void (*fn_free
)(struct automation_object
*);
57 static HRESULT
database_invoke(struct automation_object
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
58 static HRESULT
installer_invoke(struct automation_object
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
59 static HRESULT
record_invoke(struct automation_object
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
60 static HRESULT
session_invoke(struct automation_object
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
61 static HRESULT
list_invoke(struct automation_object
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
62 static void list_free(struct automation_object
*);
63 static HRESULT
summaryinfo_invoke(struct automation_object
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
64 static HRESULT
view_invoke(struct automation_object
*,DISPID
,REFIID
,LCID
,WORD
,DISPPARAMS
*,VARIANT
*,EXCEPINFO
*,UINT
*);
66 static struct tid_id tid_ids
[] =
68 { &DIID_Database
, database_invoke
},
69 { &DIID_Installer
, installer_invoke
},
70 { &DIID_Record
, record_invoke
},
71 { &DIID_Session
, session_invoke
},
72 { &DIID_StringList
, list_invoke
, list_free
},
73 { &DIID_SummaryInfo
, summaryinfo_invoke
},
74 { &DIID_View
, view_invoke
}
77 static ITypeLib
*typelib
;
78 static ITypeInfo
*typeinfos
[LAST_tid
];
80 static const IID
*get_riid_from_tid(tid_t tid
)
82 return tid_ids
[tid
].riid
;
85 HRESULT
get_typeinfo(tid_t tid
, ITypeInfo
**typeinfo
)
93 hr
= LoadRegTypeLib(&LIBID_WindowsInstaller
, 1, 0, LOCALE_NEUTRAL
, &lib
);
95 hr
= LoadTypeLib(L
"msiserver.tlb", &lib
);
97 ERR("Could not load msiserver.tlb\n");
102 if (InterlockedCompareExchangePointer((void**)&typelib
, lib
, NULL
))
103 ITypeLib_Release(lib
);
110 hr
= ITypeLib_GetTypeInfoOfGuid(typelib
, get_riid_from_tid(tid
), &ti
);
112 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid
)));
116 if(InterlockedCompareExchangePointer((void**)(typeinfos
+tid
), ti
, NULL
))
117 ITypeInfo_Release(ti
);
120 *typeinfo
= typeinfos
[tid
];
124 void release_typelib(void)
128 for (i
= 0; i
< ARRAY_SIZE(typeinfos
); i
++)
130 ITypeInfo_Release(typeinfos
[i
]);
133 ITypeLib_Release(typelib
);
137 * struct automation_object - "base" class for all automation objects. For each interface, we implement Invoke
138 * function called from AutomationObject::Invoke.
140 struct automation_object
142 IDispatch IDispatch_iface
;
143 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface
;
146 /* type id for this class */
149 /* The MSI handle of the current object */
155 struct automation_object autoobj
;
160 static HRESULT
create_database(MSIHANDLE
, IDispatch
**);
161 static HRESULT
create_list_enumerator(struct list_object
*, void **);
162 static HRESULT
create_summaryinfo(MSIHANDLE
, IDispatch
**);
163 static HRESULT
create_view(MSIHANDLE
, IDispatch
**);
165 /* struct list_enumerator - IEnumVARIANT implementation for MSI automation lists */
166 struct list_enumerator
168 IEnumVARIANT IEnumVARIANT_iface
;
171 /* Current position and pointer to struct automation_object that stores actual data */
173 struct list_object
*list
;
176 struct session_object
178 struct automation_object autoobj
;
179 IDispatch
*installer
;
182 static inline struct automation_object
*impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo
*iface
)
184 return CONTAINING_RECORD(iface
, struct automation_object
, IProvideMultipleClassInfo_iface
);
187 static inline struct automation_object
*impl_from_IDispatch( IDispatch
*iface
)
189 return CONTAINING_RECORD(iface
, struct automation_object
, IDispatch_iface
);
192 /* AutomationObject methods */
193 static HRESULT WINAPI
AutomationObject_QueryInterface(IDispatch
* iface
, REFIID riid
, void** ppvObject
)
195 struct automation_object
*This
= impl_from_IDispatch(iface
);
197 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
199 if (ppvObject
== NULL
)
204 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
205 IsEqualGUID(riid
, &IID_IDispatch
) ||
206 IsEqualGUID(riid
, get_riid_from_tid(This
->tid
)))
207 *ppvObject
= &This
->IDispatch_iface
;
208 else if (IsEqualGUID(riid
, &IID_IProvideClassInfo
) ||
209 IsEqualGUID(riid
, &IID_IProvideClassInfo2
) ||
210 IsEqualGUID(riid
, &IID_IProvideMultipleClassInfo
))
211 *ppvObject
= &This
->IProvideMultipleClassInfo_iface
;
214 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
215 return E_NOINTERFACE
;
218 IDispatch_AddRef(iface
);
223 static ULONG WINAPI
AutomationObject_AddRef(IDispatch
* iface
)
225 struct automation_object
*This
= impl_from_IDispatch(iface
);
227 TRACE("(%p/%p)\n", iface
, This
);
229 return InterlockedIncrement(&This
->ref
);
232 static ULONG WINAPI
AutomationObject_Release(IDispatch
* iface
)
234 struct automation_object
*This
= impl_from_IDispatch(iface
);
235 ULONG ref
= InterlockedDecrement(&This
->ref
);
237 TRACE("(%p/%p)\n", iface
, This
);
241 if (tid_ids
[This
->tid
].fn_free
) tid_ids
[This
->tid
].fn_free(This
);
242 MsiCloseHandle(This
->msiHandle
);
249 static HRESULT WINAPI
AutomationObject_GetTypeInfoCount(
253 struct automation_object
*This
= impl_from_IDispatch(iface
);
255 TRACE("(%p/%p)->(%p)\n", iface
, This
, pctinfo
);
260 static HRESULT WINAPI
AutomationObject_GetTypeInfo(
266 struct automation_object
*This
= impl_from_IDispatch(iface
);
269 TRACE( "(%p/%p)->(%u, %ld, %p)\n", iface
, This
, iTInfo
, lcid
, ppTInfo
);
271 hr
= get_typeinfo(This
->tid
, ppTInfo
);
275 ITypeInfo_AddRef(*ppTInfo
);
279 static HRESULT WINAPI
AutomationObject_GetIDsOfNames(
287 struct automation_object
*This
= impl_from_IDispatch(iface
);
291 TRACE("(%p/%p)->(%s, %p, %u, %ld, %p)\n", iface
, This
,
292 debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
294 if (!IsEqualGUID(riid
, &IID_NULL
)) return E_INVALIDARG
;
296 hr
= get_typeinfo(This
->tid
, &ti
);
300 hr
= ITypeInfo_GetIDsOfNames(ti
, rgszNames
, cNames
, rgDispId
);
301 if (hr
== DISP_E_UNKNOWNNAME
)
304 for (idx
=0; idx
<cNames
; idx
++)
306 if (rgDispId
[idx
] == DISPID_UNKNOWN
)
307 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames
[idx
]), debugstr_guid(get_riid_from_tid(This
->tid
)));
313 /* Maximum number of allowed function parameters+1 */
314 #define MAX_FUNC_PARAMS 20
316 /* Some error checking is done here to simplify individual object function invocation */
317 static HRESULT WINAPI
AutomationObject_Invoke(
323 DISPPARAMS
* pDispParams
,
325 EXCEPINFO
* pExcepInfo
,
328 struct automation_object
*This
= impl_from_IDispatch(iface
);
330 unsigned int uArgErr
;
331 VARIANT varResultDummy
;
332 BSTR bstrName
= NULL
;
335 TRACE("(%p/%p)->(%ld, %s, %ld, %d, %p, %p, %p, %p)\n", iface
, This
,
336 dispIdMember
, debugstr_guid(riid
), lcid
, wFlags
,
337 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
339 if (!IsEqualIID(riid
, &IID_NULL
))
341 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
342 return DISP_E_UNKNOWNNAME
;
345 if (wFlags
& DISPATCH_PROPERTYGET
&& !pVarResult
)
347 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
348 return DISP_E_PARAMNOTOPTIONAL
;
351 /* This simplifies our individual object invocation functions */
352 if (puArgErr
== NULL
) puArgErr
= &uArgErr
;
353 if (pVarResult
== NULL
) pVarResult
= &varResultDummy
;
355 hr
= get_typeinfo(This
->tid
, &ti
);
359 /* Assume return type is void unless determined otherwise */
360 VariantInit(pVarResult
);
362 /* If we are tracing, we want to see the name of the member we are invoking */
365 ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
366 TRACE("method %ld, %s\n", dispIdMember
, debugstr_w(bstrName
));
369 hr
= tid_ids
[This
->tid
].fn_invoke(This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
371 if (hr
== DISP_E_MEMBERNOTFOUND
) {
372 if (bstrName
== NULL
) ITypeInfo_GetDocumentation(ti
, dispIdMember
, &bstrName
, NULL
, NULL
, NULL
);
373 FIXME("method %ld, %s wflags %d not implemented, clsid %s\n", dispIdMember
, debugstr_w(bstrName
), wFlags
,
374 debugstr_guid(get_riid_from_tid(This
->tid
)));
376 else if (pExcepInfo
&&
377 (hr
== DISP_E_PARAMNOTFOUND
||
378 hr
== DISP_E_EXCEPTION
)) {
379 WCHAR szExceptionDescription
[MAX_PATH
];
380 BSTR bstrParamNames
[MAX_FUNC_PARAMS
];
384 if (FAILED(ITypeInfo_GetNames(ti
, dispIdMember
, bstrParamNames
,
385 MAX_FUNC_PARAMS
, &namesNo
)))
387 TRACE("failed to retrieve names for dispIdMember %ld\n", dispIdMember
);
391 memset(szExceptionDescription
, 0, sizeof(szExceptionDescription
));
392 for (i
=0; i
<namesNo
; i
++)
394 if (bFirst
) bFirst
= FALSE
;
396 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], L
",");
398 lstrcpyW(&szExceptionDescription
[lstrlenW(szExceptionDescription
)], bstrParamNames
[i
]);
399 SysFreeString(bstrParamNames
[i
]);
402 memset(pExcepInfo
, 0, sizeof(EXCEPINFO
));
403 pExcepInfo
->wCode
= 1000;
404 pExcepInfo
->bstrSource
= SysAllocString(L
"Msi API Error");
405 pExcepInfo
->bstrDescription
= SysAllocString(szExceptionDescription
);
406 hr
= DISP_E_EXCEPTION
;
410 /* Make sure we free the return variant if it is our dummy variant */
411 if (pVarResult
== &varResultDummy
) VariantClear(pVarResult
);
413 /* Free function name if we retrieved it */
414 SysFreeString(bstrName
);
416 TRACE("returning %#lx, %s\n", hr
, SUCCEEDED(hr
) ? "ok" : "not ok");
421 static const struct IDispatchVtbl AutomationObjectVtbl
=
423 AutomationObject_QueryInterface
,
424 AutomationObject_AddRef
,
425 AutomationObject_Release
,
426 AutomationObject_GetTypeInfoCount
,
427 AutomationObject_GetTypeInfo
,
428 AutomationObject_GetIDsOfNames
,
429 AutomationObject_Invoke
433 * IProvideMultipleClassInfo methods
436 static HRESULT WINAPI
ProvideMultipleClassInfo_QueryInterface(
437 IProvideMultipleClassInfo
* iface
,
441 struct automation_object
*This
= impl_from_IProvideMultipleClassInfo(iface
);
442 return IDispatch_QueryInterface(&This
->IDispatch_iface
, riid
, ppvoid
);
445 static ULONG WINAPI
ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo
* iface
)
447 struct automation_object
*This
= impl_from_IProvideMultipleClassInfo(iface
);
448 return IDispatch_AddRef(&This
->IDispatch_iface
);
451 static ULONG WINAPI
ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo
* iface
)
453 struct automation_object
*This
= impl_from_IProvideMultipleClassInfo(iface
);
454 return IDispatch_Release(&This
->IDispatch_iface
);
457 static HRESULT WINAPI
ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo
* iface
, ITypeInfo
** ppTI
)
459 struct automation_object
*This
= impl_from_IProvideMultipleClassInfo(iface
);
462 TRACE("(%p/%p)->(%p)\n", iface
, This
, ppTI
);
464 hr
= get_typeinfo(This
->tid
, ppTI
);
466 ITypeInfo_AddRef(*ppTI
);
471 static HRESULT WINAPI
ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
* iface
, DWORD dwGuidKind
, GUID
* pGUID
)
473 struct automation_object
*This
= impl_from_IProvideMultipleClassInfo(iface
);
474 TRACE("(%p/%p)->(%lu, %s)\n", iface
, This
, dwGuidKind
, debugstr_guid(pGUID
));
476 if (dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
479 *pGUID
= *get_riid_from_tid(This
->tid
);
484 static HRESULT WINAPI
ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo
* iface
, ULONG
* pcti
)
486 struct automation_object
*This
= impl_from_IProvideMultipleClassInfo(iface
);
488 TRACE("(%p/%p)->(%p)\n", iface
, This
, pcti
);
493 static HRESULT WINAPI
ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo
* iface
,
498 ULONG
* pcdispidReserved
,
502 struct automation_object
*This
= impl_from_IProvideMultipleClassInfo(iface
);
504 TRACE("(%p/%p)->(%lu, %#lx, %p, %p, %p, %p, %p)\n", iface
, This
, iti
, dwFlags
, ti
, pdwTIFlags
, pcdispidReserved
,
505 piidPrimary
, piidSource
);
510 if (dwFlags
& MULTICLASSINFO_GETTYPEINFO
)
512 HRESULT hr
= get_typeinfo(This
->tid
, ti
);
516 ITypeInfo_AddRef(*ti
);
519 if (dwFlags
& MULTICLASSINFO_GETNUMRESERVEDDISPIDS
)
522 *pcdispidReserved
= 0;
525 if (dwFlags
& MULTICLASSINFO_GETIIDPRIMARY
)
526 *piidPrimary
= *get_riid_from_tid(This
->tid
);
528 if (dwFlags
& MULTICLASSINFO_GETIIDSOURCE
)
529 *piidSource
= *get_riid_from_tid(This
->tid
);
534 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl
=
536 ProvideMultipleClassInfo_QueryInterface
,
537 ProvideMultipleClassInfo_AddRef
,
538 ProvideMultipleClassInfo_Release
,
539 ProvideMultipleClassInfo_GetClassInfo
,
540 ProvideMultipleClassInfo_GetGUID
,
541 ProvideMultipleClassInfo_GetMultiTypeInfoCount
,
542 ProvideMultipleClassInfo_GetInfoOfIndex
545 static void init_automation_object(struct automation_object
*This
, MSIHANDLE msiHandle
, tid_t tid
)
547 TRACE("%p, %lu, %s\n", This
, msiHandle
, debugstr_guid(get_riid_from_tid(tid
)));
549 This
->IDispatch_iface
.lpVtbl
= &AutomationObjectVtbl
;
550 This
->IProvideMultipleClassInfo_iface
.lpVtbl
= &ProvideMultipleClassInfoVtbl
;
552 This
->msiHandle
= msiHandle
;
557 * ListEnumerator methods
560 static inline struct list_enumerator
*impl_from_IEnumVARIANT(IEnumVARIANT
* iface
)
562 return CONTAINING_RECORD(iface
, struct list_enumerator
, IEnumVARIANT_iface
);
565 static HRESULT WINAPI
ListEnumerator_QueryInterface(IEnumVARIANT
* iface
, REFIID riid
,
568 struct list_enumerator
*This
= impl_from_IEnumVARIANT(iface
);
570 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ppvObject
);
572 if (ppvObject
== NULL
)
577 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
578 IsEqualGUID(riid
, &IID_IEnumVARIANT
))
580 *ppvObject
= &This
->IEnumVARIANT_iface
;
584 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
585 return E_NOINTERFACE
;
588 IEnumVARIANT_AddRef(iface
);
592 static ULONG WINAPI
ListEnumerator_AddRef(IEnumVARIANT
* iface
)
594 struct list_enumerator
*This
= impl_from_IEnumVARIANT(iface
);
596 TRACE("(%p/%p)\n", iface
, This
);
598 return InterlockedIncrement(&This
->ref
);
601 static ULONG WINAPI
ListEnumerator_Release(IEnumVARIANT
* iface
)
603 struct list_enumerator
*This
= impl_from_IEnumVARIANT(iface
);
604 ULONG ref
= InterlockedDecrement(&This
->ref
);
606 TRACE("(%p/%p)\n", iface
, This
);
610 if (This
->list
) IDispatch_Release(&This
->list
->autoobj
.IDispatch_iface
);
617 static HRESULT WINAPI
ListEnumerator_Next(IEnumVARIANT
* iface
, ULONG celt
, VARIANT
* rgVar
,
620 struct list_enumerator
*This
= impl_from_IEnumVARIANT(iface
);
623 TRACE("%p, %lu, %p, %p\n", iface
, celt
, rgVar
, fetched
);
625 if (fetched
) *fetched
= 0;
630 for (local
= 0; local
< celt
; local
++)
631 VariantInit(&rgVar
[local
]);
633 for (i
= This
->pos
, local
= 0; i
< This
->list
->count
&& local
< celt
; i
++, local
++)
634 VariantCopy(&rgVar
[local
], &This
->list
->data
[i
]);
636 if (fetched
) *fetched
= local
;
639 return (local
< celt
) ? S_FALSE
: S_OK
;
642 static HRESULT WINAPI
ListEnumerator_Skip(IEnumVARIANT
* iface
, ULONG celt
)
644 struct list_enumerator
*This
= impl_from_IEnumVARIANT(iface
);
646 TRACE("%p, %lu\n", iface
, celt
);
649 if (This
->pos
>= This
->list
->count
)
651 This
->pos
= This
->list
->count
;
658 static HRESULT WINAPI
ListEnumerator_Reset(IEnumVARIANT
* iface
)
660 struct list_enumerator
*This
= impl_from_IEnumVARIANT(iface
);
662 TRACE("(%p)\n", iface
);
668 static HRESULT WINAPI
ListEnumerator_Clone(IEnumVARIANT
* iface
, IEnumVARIANT
**ppEnum
)
670 struct list_enumerator
*This
= impl_from_IEnumVARIANT(iface
);
673 TRACE("(%p,%p)\n", iface
, ppEnum
);
679 hr
= create_list_enumerator(This
->list
, (LPVOID
*)ppEnum
);
682 if (*ppEnum
) IEnumVARIANT_Release(*ppEnum
);
689 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl
=
691 ListEnumerator_QueryInterface
,
692 ListEnumerator_AddRef
,
693 ListEnumerator_Release
,
696 ListEnumerator_Reset
,
700 /* Create a list enumerator, placing the result in the pointer ppObj. */
701 static HRESULT
create_list_enumerator(struct list_object
*list
, void **ppObj
)
703 struct list_enumerator
*object
;
705 TRACE("(%p, %p)\n", list
, ppObj
);
707 object
= malloc(sizeof(*object
));
709 /* Set all the VTable references */
710 object
->IEnumVARIANT_iface
.lpVtbl
= &ListEnumerator_Vtbl
;
713 /* Store data that was passed */
716 if (list
) IDispatch_AddRef(&list
->autoobj
.IDispatch_iface
);
723 * Individual Object Invocation Functions
726 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
727 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
728 using DispGetParam/VariantChangeType. */
729 static HRESULT
DispGetParam_CopyOnly(
730 DISPPARAMS
*pdispparams
, /* [in] Parameter list */
731 UINT
*position
, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
732 VARIANT
*pvarResult
) /* [out] Destination for resulting variant */
734 /* position is counted backwards */
737 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
738 *position
, pdispparams
->cArgs
, pdispparams
->cNamedArgs
);
739 if (*position
< pdispparams
->cArgs
) {
740 /* positional arg? */
741 pos
= pdispparams
->cArgs
- *position
- 1;
743 /* FIXME: is this how to handle named args? */
744 for (pos
=0; pos
<pdispparams
->cNamedArgs
; pos
++)
745 if (pdispparams
->rgdispidNamedArgs
[pos
] == *position
) break;
747 if (pos
==pdispparams
->cNamedArgs
)
748 return DISP_E_PARAMNOTFOUND
;
751 return VariantCopyInd(pvarResult
,
752 &pdispparams
->rgvarg
[pos
]);
755 static HRESULT
summaryinfo_invoke(
756 struct automation_object
*This
,
761 DISPPARAMS
* pDispParams
,
763 EXCEPINFO
* pExcepInfo
,
767 VARIANTARG varg0
, varg1
;
768 FILETIME ft
, ftlocal
;
775 switch (dispIdMember
)
777 case DISPID_SUMMARYINFO_PROPERTY
:
778 if (wFlags
& DISPATCH_PROPERTYGET
)
786 static WCHAR szEmpty
[] = L
"";
788 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
789 if (FAILED(hr
)) return hr
;
790 ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, &value
,
791 &ft
, szEmpty
, &size
);
792 if (ret
!= ERROR_SUCCESS
&&
793 ret
!= ERROR_MORE_DATA
)
795 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
796 return DISP_E_EXCEPTION
;
806 V_VT(pVarResult
) = VT_I4
;
807 V_I4(pVarResult
) = value
;
811 if (!(str
= malloc(++size
* sizeof(WCHAR
))))
812 ERR("Out of memory\n");
813 else if ((ret
= MsiSummaryInfoGetPropertyW(This
->msiHandle
, V_I4(&varg0
), &type
, NULL
,
814 NULL
, str
, &size
)) != ERROR_SUCCESS
)
815 ERR("MsiSummaryInfoGetProperty returned %d\n", ret
);
818 V_VT(pVarResult
) = VT_BSTR
;
819 V_BSTR(pVarResult
) = SysAllocString(str
);
825 FileTimeToLocalFileTime(&ft
, &ftlocal
);
826 FileTimeToSystemTime(&ftlocal
, &st
);
827 SystemTimeToVariantTime(&st
, &date
);
829 V_VT(pVarResult
) = VT_DATE
;
830 V_DATE(pVarResult
) = date
;
834 ERR("Unhandled variant type %d\n", type
);
837 else if (wFlags
& DISPATCH_PROPERTYPUT
)
839 UINT posValue
= DISPID_PROPERTYPUT
;
841 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
842 if (FAILED(hr
)) return hr
;
843 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg1
);
846 *puArgErr
= posValue
;
850 switch (V_VT(&varg1
))
854 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), V_VT(&varg1
), V_I4(&varg1
), NULL
, NULL
);
858 VariantTimeToSystemTime(V_DATE(&varg1
), &st
);
859 SystemTimeToFileTime(&st
, &ftlocal
);
860 LocalFileTimeToFileTime(&ftlocal
, &ft
);
861 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_FILETIME
, 0, &ft
, NULL
);
865 ret
= MsiSummaryInfoSetPropertyW(This
->msiHandle
, V_I4(&varg0
), VT_LPSTR
, 0, NULL
, V_BSTR(&varg1
));
869 FIXME("Unhandled variant type %d\n", V_VT(&varg1
));
870 VariantClear(&varg1
);
871 return DISP_E_EXCEPTION
;
874 if (ret
!= ERROR_SUCCESS
)
876 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret
);
877 return DISP_E_EXCEPTION
;
880 else return DISP_E_MEMBERNOTFOUND
;
883 case DISPID_SUMMARYINFO_PROPERTYCOUNT
:
884 if (wFlags
& DISPATCH_PROPERTYGET
) {
886 if ((ret
= MsiSummaryInfoGetPropertyCount(This
->msiHandle
, &count
)) != ERROR_SUCCESS
)
887 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret
);
890 V_VT(pVarResult
) = VT_I4
;
891 V_I4(pVarResult
) = count
;
894 else return DISP_E_MEMBERNOTFOUND
;
898 return DISP_E_MEMBERNOTFOUND
;
901 VariantClear(&varg1
);
902 VariantClear(&varg0
);
907 static HRESULT
record_invoke(
908 struct automation_object
*This
,
913 DISPPARAMS
* pDispParams
,
915 EXCEPINFO
* pExcepInfo
,
921 VARIANTARG varg0
, varg1
;
927 switch (dispIdMember
)
929 case DISPID_RECORD_FIELDCOUNT
:
930 if (wFlags
& DISPATCH_PROPERTYGET
) {
931 V_VT(pVarResult
) = VT_I4
;
932 V_I4(pVarResult
) = MsiRecordGetFieldCount(This
->msiHandle
);
934 else return DISP_E_MEMBERNOTFOUND
;
937 case DISPID_RECORD_STRINGDATA
:
938 if (wFlags
& DISPATCH_PROPERTYGET
) {
939 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
940 if (FAILED(hr
)) return hr
;
941 V_VT(pVarResult
) = VT_BSTR
;
942 V_BSTR(pVarResult
) = NULL
;
943 if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
945 if (!(szString
= malloc((++dwLen
) * sizeof(WCHAR
))))
946 ERR("Out of memory\n");
947 else if ((ret
= MsiRecordGetStringW(This
->msiHandle
, V_I4(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
948 V_BSTR(pVarResult
) = SysAllocString(szString
);
951 if (ret
!= ERROR_SUCCESS
)
952 ERR("MsiRecordGetString returned %d\n", ret
);
953 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
954 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
955 if (FAILED(hr
)) return hr
;
956 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
957 if (FAILED(hr
)) return hr
;
958 if ((ret
= MsiRecordSetStringW(This
->msiHandle
, V_I4(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
960 VariantClear(&varg1
);
961 ERR("MsiRecordSetString returned %d\n", ret
);
962 return DISP_E_EXCEPTION
;
965 else return DISP_E_MEMBERNOTFOUND
;
968 case DISPID_RECORD_INTEGERDATA
:
969 if (wFlags
& DISPATCH_PROPERTYGET
) {
970 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
971 if (FAILED(hr
)) return hr
;
972 V_VT(pVarResult
) = VT_I4
;
973 V_I4(pVarResult
) = MsiRecordGetInteger(This
->msiHandle
, V_I4(&varg0
));
974 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
975 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
976 if (FAILED(hr
)) return hr
;
977 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
978 if (FAILED(hr
)) return hr
;
979 if ((ret
= MsiRecordSetInteger(This
->msiHandle
, V_I4(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
981 ERR("MsiRecordSetInteger returned %d\n", ret
);
982 return DISP_E_EXCEPTION
;
985 else return DISP_E_MEMBERNOTFOUND
;
989 return DISP_E_MEMBERNOTFOUND
;
992 VariantClear(&varg1
);
993 VariantClear(&varg0
);
998 static HRESULT
create_record(MSIHANDLE msiHandle
, IDispatch
**disp
)
1000 struct automation_object
*record
;
1002 record
= malloc(sizeof(*record
));
1003 if (!record
) return E_OUTOFMEMORY
;
1005 init_automation_object(record
, msiHandle
, Record_tid
);
1007 *disp
= &record
->IDispatch_iface
;
1012 static HRESULT
list_invoke(
1013 struct automation_object
*This
,
1014 DISPID dispIdMember
,
1018 DISPPARAMS
* pDispParams
,
1019 VARIANT
* pVarResult
,
1020 EXCEPINFO
* pExcepInfo
,
1023 struct list_object
*list
= CONTAINING_RECORD(This
, struct list_object
, autoobj
);
1024 IUnknown
*pUnk
= NULL
;
1027 switch (dispIdMember
)
1029 case DISPID_LIST__NEWENUM
:
1030 if (wFlags
& DISPATCH_METHOD
) {
1031 V_VT(pVarResult
) = VT_UNKNOWN
;
1032 if (SUCCEEDED(hr
= create_list_enumerator(list
, (LPVOID
*)&pUnk
)))
1033 V_UNKNOWN(pVarResult
) = pUnk
;
1035 ERR("failed to create IEnumVARIANT object, hresult %#lx\n", hr
);
1037 else return DISP_E_MEMBERNOTFOUND
;
1040 case DISPID_LIST_ITEM
:
1041 if (wFlags
& DISPATCH_PROPERTYGET
) {
1044 VariantInit(&index
);
1045 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &index
, puArgErr
);
1046 if (FAILED(hr
)) return hr
;
1047 if (V_I4(&index
) < 0 || V_I4(&index
) >= list
->count
)
1048 return DISP_E_BADINDEX
;
1049 VariantCopy(pVarResult
, &list
->data
[V_I4(&index
)]);
1051 else return DISP_E_MEMBERNOTFOUND
;
1054 case DISPID_LIST_COUNT
:
1055 if (wFlags
& DISPATCH_PROPERTYGET
) {
1056 V_VT(pVarResult
) = VT_I4
;
1057 V_I4(pVarResult
) = list
->count
;
1059 else return DISP_E_MEMBERNOTFOUND
;
1063 return DISP_E_MEMBERNOTFOUND
;
1069 static void list_free(struct automation_object
*This
)
1071 struct list_object
*list
= CONTAINING_RECORD(This
, struct list_object
, autoobj
);
1074 for (i
= 0; i
< list
->count
; i
++)
1075 VariantClear(&list
->data
[i
]);
1079 static HRESULT
get_products_count(const WCHAR
*product
, int *len
)
1085 WCHAR dataW
[GUID_SIZE
];
1088 /* all or related only */
1090 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1092 ret
= MsiEnumProductsW(i
, dataW
);
1094 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1096 if (ret
!= ERROR_SUCCESS
)
1097 return DISP_E_EXCEPTION
;
1107 static HRESULT
create_list(const WCHAR
*product
, IDispatch
**dispatch
)
1109 struct list_object
*list
;
1113 list
= calloc(1, sizeof(*list
));
1114 if (!list
) return E_OUTOFMEMORY
;
1116 init_automation_object(&list
->autoobj
, 0, StringList_tid
);
1118 *dispatch
= &list
->autoobj
.IDispatch_iface
;
1120 hr
= get_products_count(product
, &list
->count
);
1123 IDispatch_Release(*dispatch
);
1127 list
->data
= malloc(list
->count
* sizeof(VARIANT
));
1130 IDispatch_Release(*dispatch
);
1131 return E_OUTOFMEMORY
;
1134 for (i
= 0; i
< list
->count
; i
++)
1136 WCHAR dataW
[GUID_SIZE
];
1139 /* all or related only */
1141 ret
= MsiEnumRelatedProductsW(product
, 0, i
, dataW
);
1143 ret
= MsiEnumProductsW(i
, dataW
);
1145 if (ret
== ERROR_NO_MORE_ITEMS
) break;
1147 V_VT(&list
->data
[i
]) = VT_BSTR
;
1148 V_BSTR(&list
->data
[i
]) = SysAllocString(dataW
);
1154 static HRESULT
view_invoke(
1155 struct automation_object
*This
,
1156 DISPID dispIdMember
,
1160 DISPPARAMS
* pDispParams
,
1161 VARIANT
* pVarResult
,
1162 EXCEPINFO
* pExcepInfo
,
1165 MSIHANDLE msiHandle
;
1167 VARIANTARG varg0
, varg1
;
1170 VariantInit(&varg0
);
1171 VariantInit(&varg1
);
1173 switch (dispIdMember
)
1175 case DISPID_VIEW_EXECUTE
:
1176 if (wFlags
& DISPATCH_METHOD
)
1178 hr
= DispGetParam(pDispParams
, 0, VT_DISPATCH
, &varg0
, puArgErr
);
1179 if (SUCCEEDED(hr
) && V_DISPATCH(&varg0
) != NULL
)
1180 MsiViewExecute(This
->msiHandle
, ((struct automation_object
*)V_DISPATCH(&varg0
))->msiHandle
);
1182 MsiViewExecute(This
->msiHandle
, 0);
1184 else return DISP_E_MEMBERNOTFOUND
;
1187 case DISPID_VIEW_FETCH
:
1188 if (wFlags
& DISPATCH_METHOD
)
1190 V_VT(pVarResult
) = VT_DISPATCH
;
1191 if ((ret
= MsiViewFetch(This
->msiHandle
, &msiHandle
)) == ERROR_SUCCESS
)
1193 if (FAILED(hr
= create_record(msiHandle
, &V_DISPATCH(pVarResult
))))
1194 ERR("failed to create Record object, hresult %#lx\n", hr
);
1196 else if (ret
== ERROR_NO_MORE_ITEMS
)
1197 V_DISPATCH(pVarResult
) = NULL
;
1200 ERR("MsiViewFetch returned %d\n", ret
);
1201 return DISP_E_EXCEPTION
;
1204 else return DISP_E_MEMBERNOTFOUND
;
1207 case DISPID_VIEW_MODIFY
:
1208 if (wFlags
& DISPATCH_METHOD
)
1210 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1211 if (FAILED(hr
)) return hr
;
1212 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1213 if (FAILED(hr
)) return hr
;
1214 if (!V_DISPATCH(&varg1
)) return DISP_E_EXCEPTION
;
1215 if ((ret
= MsiViewModify(This
->msiHandle
, V_I4(&varg0
),
1216 ((struct automation_object
*)V_DISPATCH(&varg1
))->msiHandle
)) != ERROR_SUCCESS
)
1218 VariantClear(&varg1
);
1219 ERR("MsiViewModify returned %d\n", ret
);
1220 return DISP_E_EXCEPTION
;
1223 else return DISP_E_MEMBERNOTFOUND
;
1226 case DISPID_VIEW_CLOSE
:
1227 if (wFlags
& DISPATCH_METHOD
)
1229 MsiViewClose(This
->msiHandle
);
1231 else return DISP_E_MEMBERNOTFOUND
;
1235 return DISP_E_MEMBERNOTFOUND
;
1238 VariantClear(&varg1
);
1239 VariantClear(&varg0
);
1244 static HRESULT
DatabaseImpl_LastErrorRecord(WORD wFlags
,
1245 DISPPARAMS
* pDispParams
,
1246 VARIANT
* pVarResult
,
1247 EXCEPINFO
* pExcepInfo
,
1250 if (!(wFlags
& DISPATCH_METHOD
))
1251 return DISP_E_MEMBERNOTFOUND
;
1255 VariantInit(pVarResult
);
1259 HRESULT
database_invoke(
1260 struct automation_object
*This
,
1261 DISPID dispIdMember
,
1265 DISPPARAMS
* pDispParams
,
1266 VARIANT
* pVarResult
,
1267 EXCEPINFO
* pExcepInfo
,
1270 IDispatch
*dispatch
= NULL
;
1271 MSIHANDLE msiHandle
;
1273 VARIANTARG varg0
, varg1
;
1276 VariantInit(&varg0
);
1277 VariantInit(&varg1
);
1279 switch (dispIdMember
)
1281 case DISPID_DATABASE_SUMMARYINFORMATION
:
1282 if (wFlags
& DISPATCH_PROPERTYGET
)
1284 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1288 V_VT(pVarResult
) = VT_DISPATCH
;
1289 if ((ret
= MsiGetSummaryInformationW(This
->msiHandle
, NULL
, V_I4(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1291 hr
= create_summaryinfo(msiHandle
, &dispatch
);
1293 V_DISPATCH(pVarResult
) = dispatch
;
1295 ERR("failed to create SummaryInfo object: %#lx\n", hr
);
1299 ERR("MsiGetSummaryInformation returned %d\n", ret
);
1300 return DISP_E_EXCEPTION
;
1303 else return DISP_E_MEMBERNOTFOUND
;
1306 case DISPID_DATABASE_OPENVIEW
:
1307 if (wFlags
& DISPATCH_METHOD
)
1309 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1310 if (FAILED(hr
)) return hr
;
1311 V_VT(pVarResult
) = VT_DISPATCH
;
1312 if ((ret
= MsiDatabaseOpenViewW(This
->msiHandle
, V_BSTR(&varg0
), &msiHandle
)) == ERROR_SUCCESS
)
1314 if (SUCCEEDED(hr
= create_view(msiHandle
, &dispatch
)))
1315 V_DISPATCH(pVarResult
) = dispatch
;
1317 ERR("failed to create View object, hresult %#lx\n", hr
);
1321 VariantClear(&varg0
);
1322 ERR("MsiDatabaseOpenView returned %d\n", ret
);
1323 return DISP_E_EXCEPTION
;
1326 else return DISP_E_MEMBERNOTFOUND
;
1329 case DISPID_INSTALLER_LASTERRORRECORD
:
1330 return DatabaseImpl_LastErrorRecord(wFlags
, pDispParams
,
1331 pVarResult
, pExcepInfo
,
1335 return DISP_E_MEMBERNOTFOUND
;
1338 VariantClear(&varg1
);
1339 VariantClear(&varg0
);
1344 static HRESULT
session_invoke(
1345 struct automation_object
*This
,
1346 DISPID dispIdMember
,
1350 DISPPARAMS
* pDispParams
,
1351 VARIANT
* pVarResult
,
1352 EXCEPINFO
* pExcepInfo
,
1355 struct session_object
*session
= CONTAINING_RECORD(This
, struct session_object
, autoobj
);
1358 MSIHANDLE msiHandle
;
1361 INSTALLSTATE iInstalled
, iAction
;
1362 VARIANTARG varg0
, varg1
;
1365 VariantInit(&varg0
);
1366 VariantInit(&varg1
);
1368 switch (dispIdMember
)
1370 case DISPID_SESSION_INSTALLER
:
1371 if (wFlags
& DISPATCH_PROPERTYGET
) {
1372 V_VT(pVarResult
) = VT_DISPATCH
;
1373 IDispatch_AddRef(session
->installer
);
1374 V_DISPATCH(pVarResult
) = session
->installer
;
1376 else return DISP_E_MEMBERNOTFOUND
;
1379 case DISPID_SESSION_PROPERTY
:
1380 if (wFlags
& DISPATCH_PROPERTYGET
) {
1381 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1382 if (FAILED(hr
)) return hr
;
1383 V_VT(pVarResult
) = VT_BSTR
;
1384 V_BSTR(pVarResult
) = NULL
;
1385 if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), NULL
, &dwLen
)) == ERROR_SUCCESS
)
1387 if (!(szString
= malloc((++dwLen
) * sizeof(WCHAR
))))
1388 ERR("Out of memory\n");
1389 else if ((ret
= MsiGetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), szString
, &dwLen
)) == ERROR_SUCCESS
)
1390 V_BSTR(pVarResult
) = SysAllocString(szString
);
1393 if (ret
!= ERROR_SUCCESS
)
1394 ERR("MsiGetProperty returned %d\n", ret
);
1395 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1396 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1397 if (FAILED(hr
)) return hr
;
1398 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1400 VariantClear(&varg0
);
1403 if ((ret
= MsiSetPropertyW(This
->msiHandle
, V_BSTR(&varg0
), V_BSTR(&varg1
))) != ERROR_SUCCESS
)
1405 VariantClear(&varg0
);
1406 VariantClear(&varg1
);
1407 ERR("MsiSetProperty returned %d\n", ret
);
1408 return DISP_E_EXCEPTION
;
1411 else return DISP_E_MEMBERNOTFOUND
;
1414 case DISPID_SESSION_LANGUAGE
:
1415 if (wFlags
& DISPATCH_PROPERTYGET
) {
1416 langId
= MsiGetLanguage(This
->msiHandle
);
1417 V_VT(pVarResult
) = VT_I4
;
1418 V_I4(pVarResult
) = langId
;
1420 else return DISP_E_MEMBERNOTFOUND
;
1423 case DISPID_SESSION_MODE
:
1424 if (wFlags
& DISPATCH_PROPERTYGET
) {
1425 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1426 if (FAILED(hr
)) return hr
;
1427 V_VT(pVarResult
) = VT_BOOL
;
1428 V_BOOL(pVarResult
) = MsiGetMode(This
->msiHandle
, V_I4(&varg0
)) ? VARIANT_TRUE
: VARIANT_FALSE
;
1429 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1430 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1431 if (FAILED(hr
)) return hr
;
1432 hr
= DispGetParam(pDispParams
, 1, VT_BOOL
, &varg1
, puArgErr
);
1433 if (FAILED(hr
)) return hr
;
1434 if ((ret
= MsiSetMode(This
->msiHandle
, V_I4(&varg0
), V_BOOL(&varg1
))) != ERROR_SUCCESS
)
1436 ERR("MsiSetMode returned %d\n", ret
);
1437 return DISP_E_EXCEPTION
;
1440 else return DISP_E_MEMBERNOTFOUND
;
1443 case DISPID_SESSION_DATABASE
:
1444 if (wFlags
& DISPATCH_PROPERTYGET
) {
1445 V_VT(pVarResult
) = VT_DISPATCH
;
1446 if ((msiHandle
= MsiGetActiveDatabase(This
->msiHandle
)))
1448 IDispatch
*dispatch
;
1450 if (SUCCEEDED(hr
= create_database(msiHandle
, &dispatch
)))
1451 V_DISPATCH(pVarResult
) = dispatch
;
1453 ERR("failed to create Database object, hresult %#lx\n", hr
);
1457 ERR("MsiGetActiveDatabase failed\n");
1458 return DISP_E_EXCEPTION
;
1461 else return DISP_E_MEMBERNOTFOUND
;
1464 case DISPID_SESSION_DOACTION
:
1465 if (wFlags
& DISPATCH_METHOD
) {
1466 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1467 if (FAILED(hr
)) return hr
;
1468 ret
= MsiDoActionW(This
->msiHandle
, V_BSTR(&varg0
));
1469 V_VT(pVarResult
) = VT_I4
;
1472 case ERROR_FUNCTION_NOT_CALLED
:
1473 V_I4(pVarResult
) = msiDoActionStatusNoAction
;
1476 V_I4(pVarResult
) = msiDoActionStatusSuccess
;
1478 case ERROR_INSTALL_USEREXIT
:
1479 V_I4(pVarResult
) = msiDoActionStatusUserExit
;
1481 case ERROR_INSTALL_FAILURE
:
1482 V_I4(pVarResult
) = msiDoActionStatusFailure
;
1484 case ERROR_INSTALL_SUSPEND
:
1485 V_I4(pVarResult
) = msiDoActionStatusSuspend
;
1487 case ERROR_MORE_DATA
:
1488 V_I4(pVarResult
) = msiDoActionStatusFinished
;
1490 case ERROR_INVALID_HANDLE_STATE
:
1491 V_I4(pVarResult
) = msiDoActionStatusWrongState
;
1493 case ERROR_INVALID_DATA
:
1494 V_I4(pVarResult
) = msiDoActionStatusBadActionData
;
1497 VariantClear(&varg0
);
1498 FIXME("MsiDoAction returned unhandled value %d\n", ret
);
1499 return DISP_E_EXCEPTION
;
1502 else return DISP_E_MEMBERNOTFOUND
;
1505 case DISPID_SESSION_EVALUATECONDITION
:
1506 if (wFlags
& DISPATCH_METHOD
) {
1507 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1508 if (FAILED(hr
)) return hr
;
1509 V_VT(pVarResult
) = VT_I4
;
1510 V_I4(pVarResult
) = MsiEvaluateConditionW(This
->msiHandle
, V_BSTR(&varg0
));
1512 else return DISP_E_MEMBERNOTFOUND
;
1515 case DISPID_SESSION_MESSAGE
:
1516 if(!(wFlags
& DISPATCH_METHOD
))
1517 return DISP_E_MEMBERNOTFOUND
;
1519 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1520 if (FAILED(hr
)) return hr
;
1521 hr
= DispGetParam(pDispParams
, 1, VT_DISPATCH
, &varg1
, puArgErr
);
1522 if (FAILED(hr
)) return hr
;
1524 V_VT(pVarResult
) = VT_I4
;
1526 MsiProcessMessage(This
->msiHandle
, V_I4(&varg0
), ((struct automation_object
*)V_DISPATCH(&varg1
))->msiHandle
);
1529 case DISPID_SESSION_SETINSTALLLEVEL
:
1530 if (wFlags
& DISPATCH_METHOD
) {
1531 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1532 if (FAILED(hr
)) return hr
;
1533 if ((ret
= MsiSetInstallLevel(This
->msiHandle
, V_I4(&varg0
))) != ERROR_SUCCESS
)
1535 ERR("MsiSetInstallLevel returned %d\n", ret
);
1536 return DISP_E_EXCEPTION
;
1539 else return DISP_E_MEMBERNOTFOUND
;
1542 case DISPID_SESSION_FEATURECURRENTSTATE
:
1543 if (wFlags
& DISPATCH_PROPERTYGET
) {
1544 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1545 if (FAILED(hr
)) return hr
;
1546 V_VT(pVarResult
) = VT_I4
;
1547 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1548 V_I4(pVarResult
) = iInstalled
;
1551 ERR("MsiGetFeatureState returned %d\n", ret
);
1552 V_I4(pVarResult
) = msiInstallStateUnknown
;
1555 else return DISP_E_MEMBERNOTFOUND
;
1558 case DISPID_SESSION_FEATUREREQUESTSTATE
:
1559 if (wFlags
& DISPATCH_PROPERTYGET
) {
1560 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1561 if (FAILED(hr
)) return hr
;
1562 V_VT(pVarResult
) = VT_I4
;
1563 if ((ret
= MsiGetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), &iInstalled
, &iAction
)) == ERROR_SUCCESS
)
1564 V_I4(pVarResult
) = iAction
;
1567 ERR("MsiGetFeatureState returned %d\n", ret
);
1568 V_I4(pVarResult
) = msiInstallStateUnknown
;
1570 } else if (wFlags
& DISPATCH_PROPERTYPUT
) {
1571 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1572 if (FAILED(hr
)) return hr
;
1573 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1575 VariantClear(&varg0
);
1578 if ((ret
= MsiSetFeatureStateW(This
->msiHandle
, V_BSTR(&varg0
), V_I4(&varg1
))) != ERROR_SUCCESS
)
1580 VariantClear(&varg0
);
1581 ERR("MsiSetFeatureState returned %d\n", ret
);
1582 return DISP_E_EXCEPTION
;
1585 else return DISP_E_MEMBERNOTFOUND
;
1589 return DISP_E_MEMBERNOTFOUND
;
1592 VariantClear(&varg1
);
1593 VariantClear(&varg0
);
1598 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1599 * registry value type. Used by Installer::RegistryValue. */
1600 static void variant_from_registry_value(VARIANT
*pVarResult
, DWORD dwType
, LPBYTE lpData
, DWORD dwSize
)
1602 WCHAR
*szString
= (WCHAR
*)lpData
;
1603 LPWSTR szNewString
= NULL
;
1604 DWORD dwNewSize
= 0;
1609 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1610 case REG_MULTI_SZ
: /* Multi SZ change internal null characters to newlines */
1611 idx
= (dwSize
/sizeof(WCHAR
))-1;
1612 while (idx
>= 0 && !szString
[idx
]) idx
--;
1613 for (; idx
>= 0; idx
--)
1614 if (!szString
[idx
]) szString
[idx
] = '\n';
1617 V_VT(pVarResult
) = VT_BSTR
;
1618 V_BSTR(pVarResult
) = SysAllocStringByteLen((LPCSTR
)szString
, dwSize
);
1622 if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1623 ERR("ExpandEnvironmentStrings returned error %lu\n", GetLastError());
1624 else if (!(szNewString
= malloc(dwNewSize
* sizeof(WCHAR
))))
1625 ERR("Out of memory\n");
1626 else if (!(dwNewSize
= ExpandEnvironmentStringsW(szString
, szNewString
, dwNewSize
)))
1627 ERR("ExpandEnvironmentStrings returned error %lu\n", GetLastError());
1630 V_VT(pVarResult
) = VT_BSTR
;
1631 V_BSTR(pVarResult
) = SysAllocStringLen(szNewString
, dwNewSize
);
1637 V_VT(pVarResult
) = VT_I4
;
1638 V_I4(pVarResult
) = *((DWORD
*)lpData
);
1642 V_VT(pVarResult
) = VT_BSTR
;
1643 V_BSTR(pVarResult
) = SysAllocString(L
"(REG_\?\?)"); /* Weird string, don't know why native returns it */
1647 V_VT(pVarResult
) = VT_BSTR
;
1648 V_BSTR(pVarResult
) = SysAllocString(L
"(REG_BINARY)");
1652 V_VT(pVarResult
) = VT_EMPTY
;
1656 FIXME("Unhandled registry value type %lu\n", dwType
);
1660 static HRESULT
InstallerImpl_CreateRecord(WORD wFlags
,
1661 DISPPARAMS
* pDispParams
,
1662 VARIANT
* pVarResult
,
1663 EXCEPINFO
* pExcepInfo
,
1670 if (!(wFlags
& DISPATCH_METHOD
))
1671 return DISP_E_MEMBERNOTFOUND
;
1673 VariantInit(&varg0
);
1674 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1678 V_VT(pVarResult
) = VT_DISPATCH
;
1680 hrec
= MsiCreateRecord(V_I4(&varg0
));
1682 return DISP_E_EXCEPTION
;
1684 return create_record(hrec
, &V_DISPATCH(pVarResult
));
1687 static HRESULT
InstallerImpl_OpenPackage(struct automation_object
*This
,
1689 DISPPARAMS
* pDispParams
,
1690 VARIANT
* pVarResult
,
1691 EXCEPINFO
* pExcepInfo
,
1697 IDispatch
* dispatch
;
1698 VARIANTARG varg0
, varg1
;
1700 if (!(wFlags
& DISPATCH_METHOD
))
1701 return DISP_E_MEMBERNOTFOUND
;
1703 if (pDispParams
->cArgs
== 0)
1704 return DISP_E_TYPEMISMATCH
;
1706 if (V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1]) != VT_BSTR
)
1707 return DISP_E_TYPEMISMATCH
;
1709 VariantInit(&varg0
);
1710 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1714 VariantInit(&varg1
);
1715 if (pDispParams
->cArgs
== 2)
1717 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1723 V_VT(&varg1
) = VT_I4
;
1727 V_VT(pVarResult
) = VT_DISPATCH
;
1729 ret
= MsiOpenPackageExW(V_BSTR(&varg0
), V_I4(&varg1
), &hpkg
);
1730 if (ret
!= ERROR_SUCCESS
)
1732 hr
= DISP_E_EXCEPTION
;
1736 hr
= create_session(hpkg
, &This
->IDispatch_iface
, &dispatch
);
1738 V_DISPATCH(pVarResult
) = dispatch
;
1741 VariantClear(&varg0
);
1742 VariantClear(&varg1
);
1746 static HRESULT
InstallerImpl_OpenProduct(WORD wFlags
,
1747 DISPPARAMS
* pDispParams
,
1748 VARIANT
* pVarResult
,
1749 EXCEPINFO
* pExcepInfo
,
1755 if (!(wFlags
& DISPATCH_METHOD
))
1756 return DISP_E_MEMBERNOTFOUND
;
1758 VariantInit(&varg0
);
1759 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1763 FIXME("%s\n", debugstr_w(V_BSTR(&varg0
)));
1765 VariantInit(pVarResult
);
1767 VariantClear(&varg0
);
1771 static HRESULT
InstallerImpl_OpenDatabase(WORD wFlags
,
1772 DISPPARAMS
* pDispParams
,
1773 VARIANT
* pVarResult
,
1774 EXCEPINFO
* pExcepInfo
,
1780 IDispatch
* dispatch
;
1781 VARIANTARG varg0
, varg1
;
1783 if (!(wFlags
& DISPATCH_METHOD
))
1784 return DISP_E_MEMBERNOTFOUND
;
1786 VariantInit(&varg0
);
1787 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1791 VariantInit(&varg1
);
1792 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1796 V_VT(pVarResult
) = VT_DISPATCH
;
1798 ret
= MsiOpenDatabaseW(V_BSTR(&varg0
), V_BSTR(&varg1
), &hdb
);
1799 if (ret
!= ERROR_SUCCESS
)
1801 hr
= DISP_E_EXCEPTION
;
1805 hr
= create_database(hdb
, &dispatch
);
1807 V_DISPATCH(pVarResult
) = dispatch
;
1810 VariantClear(&varg0
);
1811 VariantClear(&varg1
);
1815 static HRESULT
InstallerImpl_SummaryInformation(WORD wFlags
,
1816 DISPPARAMS
* pDispParams
,
1817 VARIANT
* pVarResult
,
1818 EXCEPINFO
* pExcepInfo
,
1824 IDispatch
*dispatch
;
1825 VARIANTARG varg0
, varg1
;
1827 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1828 return DISP_E_MEMBERNOTFOUND
;
1830 VariantInit(&varg1
);
1831 hr
= DispGetParam(pDispParams
, 1, VT_I4
, &varg1
, puArgErr
);
1835 VariantInit(&varg0
);
1836 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1840 ret
= MsiGetSummaryInformationW(0, V_BSTR(&varg0
), V_I4(&varg1
), &hsuminfo
);
1841 VariantClear(&varg0
);
1842 if (ret
!= ERROR_SUCCESS
)
1843 return DISP_E_EXCEPTION
;
1845 hr
= create_summaryinfo(hsuminfo
, &dispatch
);
1849 V_VT(pVarResult
) = VT_DISPATCH
;
1850 V_DISPATCH(pVarResult
) = dispatch
;
1854 static HRESULT
InstallerImpl_UILevel(WORD wFlags
,
1855 DISPPARAMS
* pDispParams
,
1856 VARIANT
* pVarResult
,
1857 EXCEPINFO
* pExcepInfo
,
1864 if (!(wFlags
& DISPATCH_PROPERTYPUT
) && !(wFlags
& DISPATCH_PROPERTYGET
))
1865 return DISP_E_MEMBERNOTFOUND
;
1867 if (wFlags
& DISPATCH_PROPERTYPUT
)
1869 VariantInit(&varg0
);
1870 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
1874 ui
= MsiSetInternalUI(V_I4(&varg0
), NULL
);
1875 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1876 return DISP_E_EXCEPTION
;
1878 else if (wFlags
& DISPATCH_PROPERTYGET
)
1880 ui
= MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE
, NULL
);
1881 if (ui
== INSTALLUILEVEL_NOCHANGE
)
1882 return DISP_E_EXCEPTION
;
1884 V_VT(pVarResult
) = VT_I4
;
1885 V_I4(pVarResult
) = ui
;
1891 static HRESULT
InstallerImpl_EnableLog(WORD wFlags
,
1892 DISPPARAMS
* pDispParams
,
1893 VARIANT
* pVarResult
,
1894 EXCEPINFO
* pExcepInfo
,
1897 if (!(wFlags
& DISPATCH_METHOD
))
1898 return DISP_E_MEMBERNOTFOUND
;
1902 VariantInit(pVarResult
);
1906 static HRESULT
InstallerImpl_InstallProduct(WORD wFlags
,
1907 DISPPARAMS
* pDispParams
,
1908 VARIANT
* pVarResult
,
1909 EXCEPINFO
* pExcepInfo
,
1914 VARIANTARG varg0
, varg1
;
1916 if (!(wFlags
& DISPATCH_METHOD
))
1917 return DISP_E_MEMBERNOTFOUND
;
1919 VariantInit(&varg0
);
1920 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
1924 VariantInit(&varg1
);
1925 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
1929 ret
= MsiInstallProductW(V_BSTR(&varg0
), V_BSTR(&varg1
));
1930 if (ret
!= ERROR_SUCCESS
)
1932 hr
= DISP_E_EXCEPTION
;
1937 VariantClear(&varg0
);
1938 VariantClear(&varg1
);
1942 static HRESULT
InstallerImpl_Version(WORD wFlags
,
1943 VARIANT
* pVarResult
,
1944 EXCEPINFO
* pExcepInfo
,
1948 DLLVERSIONINFO verinfo
;
1949 WCHAR version
[MAX_PATH
];
1951 if (!(wFlags
& DISPATCH_PROPERTYGET
))
1952 return DISP_E_MEMBERNOTFOUND
;
1954 verinfo
.cbSize
= sizeof(DLLVERSIONINFO
);
1955 hr
= DllGetVersion(&verinfo
);
1959 swprintf(version
, ARRAY_SIZE(version
), L
"%d.%d.%d.%d", verinfo
.dwMajorVersion
, verinfo
.dwMinorVersion
,
1960 verinfo
.dwBuildNumber
, verinfo
.dwPlatformID
);
1962 V_VT(pVarResult
) = VT_BSTR
;
1963 V_BSTR(pVarResult
) = SysAllocString(version
);
1967 static HRESULT
InstallerImpl_LastErrorRecord(WORD wFlags
,
1968 DISPPARAMS
* pDispParams
,
1969 VARIANT
* pVarResult
,
1970 EXCEPINFO
* pExcepInfo
,
1973 if (!(wFlags
& DISPATCH_METHOD
))
1974 return DISP_E_MEMBERNOTFOUND
;
1978 VariantInit(pVarResult
);
1982 static HRESULT
InstallerImpl_RegistryValue(WORD wFlags
,
1983 DISPPARAMS
* pDispParams
,
1984 VARIANT
* pVarResult
,
1985 EXCEPINFO
* pExcepInfo
,
1993 LPWSTR szString
= NULL
;
1994 VARIANTARG varg0
, varg1
, varg2
;
1996 if (!(wFlags
& DISPATCH_METHOD
))
1997 return DISP_E_MEMBERNOTFOUND
;
1999 VariantInit(&varg0
);
2000 hr
= DispGetParam(pDispParams
, 0, VT_I4
, &varg0
, puArgErr
);
2004 VariantInit(&varg1
);
2005 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2009 /* Save valuePos so we can save puArgErr if we are unable to do our type
2013 VariantInit(&varg2
);
2014 hr
= DispGetParam_CopyOnly(pDispParams
, &posValue
, &varg2
);
2018 if (V_I4(&varg0
) >= REG_INDEX_CLASSES_ROOT
&&
2019 V_I4(&varg0
) <= REG_INDEX_DYN_DATA
)
2021 V_I4(&varg0
) |= (UINT_PTR
)HKEY_CLASSES_ROOT
;
2024 ret
= RegOpenKeyW((HKEY
)(UINT_PTR
)V_I4(&varg0
), V_BSTR(&varg1
), &hkey
);
2026 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2027 if (ret
!= ERROR_SUCCESS
&& V_VT(&varg2
) != VT_EMPTY
)
2029 hr
= DISP_E_BADINDEX
;
2033 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2034 switch (V_VT(&varg2
))
2036 /* Return VT_BOOL clarifying whether registry key exists or not. */
2038 V_VT(pVarResult
) = VT_BOOL
;
2039 V_BOOL(pVarResult
) = (ret
== ERROR_SUCCESS
) ? VARIANT_TRUE
: VARIANT_FALSE
;
2042 /* Return the value of specified key if it exists. */
2044 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
),
2045 NULL
, NULL
, NULL
, &size
);
2046 if (ret
!= ERROR_SUCCESS
)
2048 hr
= DISP_E_BADINDEX
;
2052 szString
= malloc(size
);
2059 ret
= RegQueryValueExW(hkey
, V_BSTR(&varg2
), NULL
,
2060 &type
, (LPBYTE
)szString
, &size
);
2061 if (ret
!= ERROR_SUCCESS
)
2064 hr
= DISP_E_BADINDEX
;
2068 variant_from_registry_value(pVarResult
, type
,
2069 (LPBYTE
)szString
, size
);
2073 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2075 hr
= VariantChangeType(&varg2
, &varg2
, 0, VT_I4
);
2078 if (hr
== DISP_E_TYPEMISMATCH
)
2079 *puArgErr
= posValue
;
2084 /* Retrieve class name or maximum value name or subkey name size. */
2086 ret
= RegQueryInfoKeyW(hkey
, NULL
, &size
, NULL
, NULL
, NULL
,
2087 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2088 else if (V_I4(&varg2
) > 0)
2089 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
,
2090 NULL
, NULL
, &size
, NULL
, NULL
, NULL
);
2091 else /* V_I4(&varg2) < 0 */
2092 ret
= RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, &size
,
2093 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2095 if (ret
!= ERROR_SUCCESS
)
2098 szString
= malloc(++size
* sizeof(WCHAR
));
2106 ret
= RegQueryInfoKeyW(hkey
, szString
, &size
,NULL
, NULL
, NULL
,
2107 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2108 else if (V_I4(&varg2
) > 0)
2109 ret
= RegEnumValueW(hkey
, V_I4(&varg2
)-1, szString
,
2110 &size
, 0, 0, NULL
, NULL
);
2111 else /* V_I4(&varg2) < 0 */
2112 ret
= RegEnumKeyW(hkey
, -1 - V_I4(&varg2
), szString
, size
);
2114 if (ret
== ERROR_SUCCESS
)
2116 V_VT(pVarResult
) = VT_BSTR
;
2117 V_BSTR(pVarResult
) = SysAllocString(szString
);
2124 VariantClear(&varg0
);
2125 VariantClear(&varg1
);
2126 VariantClear(&varg2
);
2131 static HRESULT
InstallerImpl_Environment(WORD wFlags
,
2132 DISPPARAMS
* pDispParams
,
2133 VARIANT
* pVarResult
,
2134 EXCEPINFO
* pExcepInfo
,
2137 if (!(wFlags
& DISPATCH_METHOD
))
2138 return DISP_E_MEMBERNOTFOUND
;
2142 VariantInit(pVarResult
);
2146 static HRESULT
InstallerImpl_FileAttributes(WORD wFlags
,
2147 DISPPARAMS
* pDispParams
,
2148 VARIANT
* pVarResult
,
2149 EXCEPINFO
* pExcepInfo
,
2152 if (!(wFlags
& DISPATCH_METHOD
))
2153 return DISP_E_MEMBERNOTFOUND
;
2157 VariantInit(pVarResult
);
2161 static HRESULT
InstallerImpl_FileSize(WORD wFlags
,
2162 DISPPARAMS
* pDispParams
,
2163 VARIANT
* pVarResult
,
2164 EXCEPINFO
* pExcepInfo
,
2167 if (!(wFlags
& DISPATCH_METHOD
))
2168 return DISP_E_MEMBERNOTFOUND
;
2172 VariantInit(pVarResult
);
2176 static HRESULT
InstallerImpl_FileVersion(WORD wFlags
,
2177 DISPPARAMS
* pDispParams
,
2178 VARIANT
* pVarResult
,
2179 EXCEPINFO
* pExcepInfo
,
2182 if (!(wFlags
& DISPATCH_METHOD
))
2183 return DISP_E_MEMBERNOTFOUND
;
2187 VariantInit(pVarResult
);
2191 static HRESULT
InstallerImpl_ProductState(WORD wFlags
,
2192 DISPPARAMS
* pDispParams
,
2193 VARIANT
* pVarResult
,
2194 EXCEPINFO
* pExcepInfo
,
2200 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2201 return DISP_E_MEMBERNOTFOUND
;
2203 VariantInit(&varg0
);
2204 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2208 V_VT(pVarResult
) = VT_I4
;
2209 V_I4(pVarResult
) = MsiQueryProductStateW(V_BSTR(&varg0
));
2211 VariantClear(&varg0
);
2215 static HRESULT
InstallerImpl_ProductInfo(WORD wFlags
,
2216 DISPPARAMS
* pDispParams
,
2217 VARIANT
* pVarResult
,
2218 EXCEPINFO
* pExcepInfo
,
2225 VARIANTARG varg0
, varg1
;
2227 if (!(wFlags
& DISPATCH_PROPERTYGET
))
2228 return DISP_E_MEMBERNOTFOUND
;
2230 VariantInit(&varg0
);
2231 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &varg0
, puArgErr
);
2235 VariantInit(&varg1
);
2236 hr
= DispGetParam(pDispParams
, 1, VT_BSTR
, &varg1
, puArgErr
);
2240 V_VT(pVarResult
) = VT_BSTR
;
2241 V_BSTR(pVarResult
) = NULL
;
2243 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), NULL
, &size
);
2244 if (ret
!= ERROR_SUCCESS
)
2246 hr
= DISP_E_EXCEPTION
;
2250 str
= malloc(++size
* sizeof(WCHAR
));
2257 ret
= MsiGetProductInfoW(V_BSTR(&varg0
), V_BSTR(&varg1
), str
, &size
);
2258 if (ret
!= ERROR_SUCCESS
)
2260 hr
= DISP_E_EXCEPTION
;
2264 V_BSTR(pVarResult
) = SysAllocString(str
);
2269 VariantClear(&varg0
);
2270 VariantClear(&varg1
);
2274 static HRESULT
InstallerImpl_Products(WORD flags
,
2275 DISPPARAMS
* pDispParams
,
2277 EXCEPINFO
* pExcepInfo
,
2280 IDispatch
*dispatch
;
2283 if (!(flags
& DISPATCH_PROPERTYGET
))
2284 return DISP_E_MEMBERNOTFOUND
;
2286 hr
= create_list(NULL
, &dispatch
);
2290 V_VT(result
) = VT_DISPATCH
;
2291 V_DISPATCH(result
) = dispatch
;
2296 static HRESULT
InstallerImpl_RelatedProducts(WORD flags
,
2297 DISPPARAMS
* pDispParams
,
2299 EXCEPINFO
* pExcepInfo
,
2302 IDispatch
* dispatch
;
2306 if (!(flags
& DISPATCH_PROPERTYGET
))
2307 return DISP_E_MEMBERNOTFOUND
;
2309 VariantInit(&related
);
2310 hr
= DispGetParam(pDispParams
, 0, VT_BSTR
, &related
, puArgErr
);
2314 hr
= create_list(V_BSTR(&related
), &dispatch
);
2315 VariantClear(&related
);
2317 V_VT(result
) = VT_DISPATCH
;
2318 V_DISPATCH(result
) = dispatch
;
2323 static HRESULT
installer_invoke(
2324 struct automation_object
*This
,
2325 DISPID dispIdMember
,
2329 DISPPARAMS
* pDispParams
,
2330 VARIANT
* pVarResult
,
2331 EXCEPINFO
* pExcepInfo
,
2334 switch (dispIdMember
)
2336 case DISPID_INSTALLER_CREATERECORD
:
2337 return InstallerImpl_CreateRecord(wFlags
, pDispParams
,
2338 pVarResult
, pExcepInfo
, puArgErr
);
2340 case DISPID_INSTALLER_OPENPACKAGE
:
2341 return InstallerImpl_OpenPackage(This
, wFlags
, pDispParams
,
2342 pVarResult
, pExcepInfo
, puArgErr
);
2344 case DISPID_INSTALLER_OPENPRODUCT
:
2345 return InstallerImpl_OpenProduct(wFlags
, pDispParams
,
2346 pVarResult
, pExcepInfo
, puArgErr
);
2348 case DISPID_INSTALLER_OPENDATABASE
:
2349 return InstallerImpl_OpenDatabase(wFlags
, pDispParams
,
2350 pVarResult
, pExcepInfo
, puArgErr
);
2352 case DISPID_INSTALLER_SUMMARYINFORMATION
:
2353 return InstallerImpl_SummaryInformation(wFlags
, pDispParams
,
2354 pVarResult
, pExcepInfo
,
2357 case DISPID_INSTALLER_UILEVEL
:
2358 return InstallerImpl_UILevel(wFlags
, pDispParams
,
2359 pVarResult
, pExcepInfo
, puArgErr
);
2361 case DISPID_INSTALLER_ENABLELOG
:
2362 return InstallerImpl_EnableLog(wFlags
, pDispParams
,
2363 pVarResult
, pExcepInfo
, puArgErr
);
2365 case DISPID_INSTALLER_INSTALLPRODUCT
:
2366 return InstallerImpl_InstallProduct(wFlags
, pDispParams
,
2367 pVarResult
, pExcepInfo
,
2370 case DISPID_INSTALLER_VERSION
:
2371 return InstallerImpl_Version(wFlags
, pVarResult
,
2372 pExcepInfo
, puArgErr
);
2374 case DISPID_INSTALLER_LASTERRORRECORD
:
2375 return InstallerImpl_LastErrorRecord(wFlags
, pDispParams
,
2376 pVarResult
, pExcepInfo
,
2379 case DISPID_INSTALLER_REGISTRYVALUE
:
2380 return InstallerImpl_RegistryValue(wFlags
, pDispParams
,
2381 pVarResult
, pExcepInfo
,
2384 case DISPID_INSTALLER_ENVIRONMENT
:
2385 return InstallerImpl_Environment(wFlags
, pDispParams
,
2386 pVarResult
, pExcepInfo
, puArgErr
);
2388 case DISPID_INSTALLER_FILEATTRIBUTES
:
2389 return InstallerImpl_FileAttributes(wFlags
, pDispParams
,
2390 pVarResult
, pExcepInfo
,
2393 case DISPID_INSTALLER_FILESIZE
:
2394 return InstallerImpl_FileSize(wFlags
, pDispParams
,
2395 pVarResult
, pExcepInfo
, puArgErr
);
2397 case DISPID_INSTALLER_FILEVERSION
:
2398 return InstallerImpl_FileVersion(wFlags
, pDispParams
,
2399 pVarResult
, pExcepInfo
, puArgErr
);
2401 case DISPID_INSTALLER_PRODUCTSTATE
:
2402 return InstallerImpl_ProductState(wFlags
, pDispParams
,
2403 pVarResult
, pExcepInfo
, puArgErr
);
2405 case DISPID_INSTALLER_PRODUCTINFO
:
2406 return InstallerImpl_ProductInfo(wFlags
, pDispParams
,
2407 pVarResult
, pExcepInfo
, puArgErr
);
2409 case DISPID_INSTALLER_PRODUCTS
:
2410 return InstallerImpl_Products(wFlags
, pDispParams
,
2411 pVarResult
, pExcepInfo
, puArgErr
);
2413 case DISPID_INSTALLER_RELATEDPRODUCTS
:
2414 return InstallerImpl_RelatedProducts(wFlags
, pDispParams
,
2415 pVarResult
, pExcepInfo
,
2419 return DISP_E_MEMBERNOTFOUND
;
2423 HRESULT
create_msiserver(IUnknown
*outer
, void **ppObj
)
2425 struct automation_object
*installer
;
2427 TRACE("(%p %p)\n", outer
, ppObj
);
2430 return CLASS_E_NOAGGREGATION
;
2432 installer
= malloc(sizeof(*installer
));
2433 if (!installer
) return E_OUTOFMEMORY
;
2435 init_automation_object(installer
, 0, Installer_tid
);
2437 *ppObj
= &installer
->IDispatch_iface
;
2442 HRESULT
create_session(MSIHANDLE msiHandle
, IDispatch
*installer
, IDispatch
**disp
)
2444 struct session_object
*session
;
2446 session
= malloc(sizeof(*session
));
2447 if (!session
) return E_OUTOFMEMORY
;
2449 init_automation_object(&session
->autoobj
, msiHandle
, Session_tid
);
2451 session
->installer
= installer
;
2452 *disp
= &session
->autoobj
.IDispatch_iface
;
2457 static HRESULT
create_database(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2459 struct automation_object
*database
;
2461 TRACE("%lu %p\n", msiHandle
, dispatch
);
2463 database
= malloc(sizeof(*database
));
2464 if (!database
) return E_OUTOFMEMORY
;
2466 init_automation_object(database
, msiHandle
, Database_tid
);
2468 *dispatch
= &database
->IDispatch_iface
;
2473 static HRESULT
create_view(MSIHANDLE msiHandle
, IDispatch
**dispatch
)
2475 struct automation_object
*view
;
2477 TRACE("%lu %p\n", msiHandle
, dispatch
);
2479 view
= malloc(sizeof(*view
));
2480 if (!view
) return E_OUTOFMEMORY
;
2482 init_automation_object(view
, msiHandle
, View_tid
);
2484 *dispatch
= &view
->IDispatch_iface
;
2489 static HRESULT
create_summaryinfo(MSIHANDLE msiHandle
, IDispatch
**disp
)
2491 struct automation_object
*info
;
2493 info
= malloc(sizeof(*info
));
2494 if (!info
) return E_OUTOFMEMORY
;
2496 init_automation_object(info
, msiHandle
, SummaryInfo_tid
);
2498 *disp
= &info
->IDispatch_iface
;