sxs: Use inline wrappers for calling COM methods.
[wine/wine-gecko.git] / dlls / msi / automation.c
blobe55717af7f122fcfc76b2a25d77d0ea49b5ed2aa
1 /*
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
21 #define COBJMACROS
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "msidefs.h"
30 #include "msipriv.h"
31 #include "activscp.h"
32 #include "oleauto.h"
33 #include "shlwapi.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #include "msiserver.h"
38 #include "msiserver_dispids.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42 #define REG_INDEX_CLASSES_ROOT 0
43 #define REG_INDEX_DYN_DATA 6
46 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
47 * called from AutomationObject::Invoke.
50 typedef struct AutomationObject AutomationObject;
52 typedef HRESULT (*autoInvokeFunc)(AutomationObject* This,
53 DISPID dispIdMember, REFIID riid, LCID lcid, WORD flags, DISPPARAMS* pDispParams,
54 VARIANT* result, EXCEPINFO* ei, UINT* arg_err);
56 typedef void (*autoFreeFunc)(AutomationObject* This);
58 struct AutomationObject {
59 IDispatch IDispatch_iface;
60 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface;
61 LONG ref;
63 /* Clsid for this class and it's appropriate ITypeInfo object */
64 LPCLSID clsid;
65 ITypeInfo *iTypeInfo;
67 /* The MSI handle of the current object */
68 MSIHANDLE msiHandle;
70 /* A function that is called from AutomationObject::Invoke, specific to this type of object. */
71 autoInvokeFunc funcInvoke;
72 /* A function that is called from AutomationObject::Release when the object is being freed to free any private
73 * data structures (or NULL) */
74 autoFreeFunc funcFree;
77 typedef struct {
78 AutomationObject autoobj;
79 int count;
80 VARIANT *data;
81 } ListObject;
83 static HRESULT create_database(MSIHANDLE, IDispatch**);
84 static HRESULT create_list_enumerator(ListObject*, void**);
85 static HRESULT create_summaryinfo(MSIHANDLE, IDispatch**);
86 static HRESULT create_view(MSIHANDLE, IDispatch**);
88 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
89 typedef struct {
90 IEnumVARIANT IEnumVARIANT_iface;
91 LONG ref;
93 /* Current position and pointer to AutomationObject that stores actual data */
94 ULONG pos;
95 ListObject *list;
96 } ListEnumerator;
98 typedef struct {
99 AutomationObject autoobj;
100 IDispatch *installer;
101 } SessionObject;
103 static inline AutomationObject *impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo *iface )
105 return CONTAINING_RECORD(iface, AutomationObject, IProvideMultipleClassInfo_iface);
108 static inline AutomationObject *impl_from_IDispatch( IDispatch *iface )
110 return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface);
113 /* Load type info so we don't have to process GetIDsOfNames */
114 HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid)
116 static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
117 ITypeInfo *ti = NULL;
118 ITypeLib *lib = NULL;
119 HRESULT hr;
121 TRACE("(%p)->(%s, %d)\n", iface, debugstr_guid(clsid), lcid);
123 /* Load registered type library */
124 hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, lcid, &lib);
125 if (FAILED(hr)) {
126 hr = LoadTypeLib(msiserverW, &lib);
127 if (FAILED(hr)) {
128 ERR("Could not load msiserver.tlb\n");
129 return hr;
133 /* Get type information for object */
134 hr = ITypeLib_GetTypeInfoOfGuid(lib, clsid, &ti);
135 ITypeLib_Release(lib);
136 if (FAILED(hr)) {
137 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid));
138 return hr;
140 *pptinfo = ti;
141 return S_OK;
144 /* AutomationObject methods */
145 static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject)
147 AutomationObject *This = impl_from_IDispatch(iface);
149 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
151 if (ppvObject == NULL)
152 return E_INVALIDARG;
154 *ppvObject = 0;
156 if (IsEqualGUID(riid, &IID_IUnknown) ||
157 IsEqualGUID(riid, &IID_IDispatch) ||
158 IsEqualGUID(riid, This->clsid))
159 *ppvObject = &This->IDispatch_iface;
160 else if (IsEqualGUID(riid, &IID_IProvideClassInfo) ||
161 IsEqualGUID(riid, &IID_IProvideClassInfo2) ||
162 IsEqualGUID(riid, &IID_IProvideMultipleClassInfo))
163 *ppvObject = &This->IProvideMultipleClassInfo_iface;
164 else
166 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid));
167 return E_NOINTERFACE;
170 IDispatch_AddRef(iface);
172 return S_OK;
175 static ULONG WINAPI AutomationObject_AddRef(IDispatch* iface)
177 AutomationObject *This = impl_from_IDispatch(iface);
179 TRACE("(%p/%p)\n", iface, This);
181 return InterlockedIncrement(&This->ref);
184 static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
186 AutomationObject *This = impl_from_IDispatch(iface);
187 ULONG ref = InterlockedDecrement(&This->ref);
189 TRACE("(%p/%p)\n", iface, This);
191 if (!ref)
193 if (This->funcFree) This->funcFree(This);
194 ITypeInfo_Release(This->iTypeInfo);
195 MsiCloseHandle(This->msiHandle);
196 msi_free(This);
199 return ref;
202 static HRESULT WINAPI AutomationObject_GetTypeInfoCount(
203 IDispatch* iface,
204 UINT* pctinfo)
206 AutomationObject *This = impl_from_IDispatch(iface);
208 TRACE("(%p/%p)->(%p)\n", iface, This, pctinfo);
209 *pctinfo = 1;
210 return S_OK;
213 static HRESULT WINAPI AutomationObject_GetTypeInfo(
214 IDispatch* iface,
215 UINT iTInfo,
216 LCID lcid,
217 ITypeInfo** ppTInfo)
219 AutomationObject *This = impl_from_IDispatch(iface);
220 TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo);
222 ITypeInfo_AddRef(This->iTypeInfo);
223 *ppTInfo = This->iTypeInfo;
224 return S_OK;
227 static HRESULT WINAPI AutomationObject_GetIDsOfNames(
228 IDispatch* iface,
229 REFIID riid,
230 LPOLESTR* rgszNames,
231 UINT cNames,
232 LCID lcid,
233 DISPID* rgDispId)
235 AutomationObject *This = impl_from_IDispatch(iface);
236 HRESULT hr;
237 TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId);
239 if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG;
240 hr = ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
241 if (hr == DISP_E_UNKNOWNNAME)
243 UINT idx;
244 for (idx=0; idx<cNames; idx++)
246 if (rgDispId[idx] == DISPID_UNKNOWN)
247 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(This->clsid));
250 return hr;
253 /* Maximum number of allowed function parameters+1 */
254 #define MAX_FUNC_PARAMS 20
256 /* Some error checking is done here to simplify individual object function invocation */
257 static HRESULT WINAPI AutomationObject_Invoke(
258 IDispatch* iface,
259 DISPID dispIdMember,
260 REFIID riid,
261 LCID lcid,
262 WORD wFlags,
263 DISPPARAMS* pDispParams,
264 VARIANT* pVarResult,
265 EXCEPINFO* pExcepInfo,
266 UINT* puArgErr)
268 AutomationObject *This = impl_from_IDispatch(iface);
269 HRESULT hr;
270 unsigned int uArgErr;
271 VARIANT varResultDummy;
272 BSTR bstrName = NULL;
274 TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface, This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
276 if (!IsEqualIID(riid, &IID_NULL))
278 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
279 return DISP_E_UNKNOWNNAME;
282 if (wFlags & DISPATCH_PROPERTYGET && !pVarResult)
284 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
285 return DISP_E_PARAMNOTOPTIONAL;
288 /* This simplifies our individual object invocation functions */
289 if (puArgErr == NULL) puArgErr = &uArgErr;
290 if (pVarResult == NULL) pVarResult = &varResultDummy;
292 /* Assume return type is void unless determined otherwise */
293 VariantInit(pVarResult);
295 /* If we are tracing, we want to see the name of the member we are invoking */
296 if (TRACE_ON(msi))
298 ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL);
299 TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName));
302 hr = This->funcInvoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
304 if (hr == DISP_E_MEMBERNOTFOUND) {
305 if (bstrName == NULL) ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL);
306 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, debugstr_guid(This->clsid));
308 else if (pExcepInfo &&
309 (hr == DISP_E_PARAMNOTFOUND ||
310 hr == DISP_E_EXCEPTION)) {
311 static const WCHAR szComma[] = { ',',0 };
312 static const WCHAR szExceptionSource[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
313 WCHAR szExceptionDescription[MAX_PATH];
314 BSTR bstrParamNames[MAX_FUNC_PARAMS];
315 unsigned namesNo, i;
316 BOOL bFirst = TRUE;
318 if (FAILED(ITypeInfo_GetNames(This->iTypeInfo, dispIdMember, bstrParamNames,
319 MAX_FUNC_PARAMS, &namesNo)))
321 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember);
323 else
325 memset(szExceptionDescription, 0, sizeof(szExceptionDescription));
326 for (i=0; i<namesNo; i++)
328 if (bFirst) bFirst = FALSE;
329 else {
330 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], szComma);
332 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], bstrParamNames[i]);
333 SysFreeString(bstrParamNames[i]);
336 memset(pExcepInfo, 0, sizeof(EXCEPINFO));
337 pExcepInfo->wCode = 1000;
338 pExcepInfo->bstrSource = SysAllocString(szExceptionSource);
339 pExcepInfo->bstrDescription = SysAllocString(szExceptionDescription);
340 hr = DISP_E_EXCEPTION;
344 /* Make sure we free the return variant if it is our dummy variant */
345 if (pVarResult == &varResultDummy) VariantClear(pVarResult);
347 /* Free function name if we retrieved it */
348 SysFreeString(bstrName);
350 TRACE("Returning 0x%08x, %s\n", hr, SUCCEEDED(hr) ? "ok" : "not ok");
352 return hr;
355 static const struct IDispatchVtbl AutomationObjectVtbl =
357 AutomationObject_QueryInterface,
358 AutomationObject_AddRef,
359 AutomationObject_Release,
360 AutomationObject_GetTypeInfoCount,
361 AutomationObject_GetTypeInfo,
362 AutomationObject_GetIDsOfNames,
363 AutomationObject_Invoke
367 * IProvideMultipleClassInfo methods
370 static HRESULT WINAPI ProvideMultipleClassInfo_QueryInterface(
371 IProvideMultipleClassInfo* iface,
372 REFIID riid,
373 VOID** ppvoid)
375 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
376 return IDispatch_QueryInterface(&This->IDispatch_iface, riid, ppvoid);
379 static ULONG WINAPI ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo* iface)
381 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
382 return IDispatch_AddRef(&This->IDispatch_iface);
385 static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo* iface)
387 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
388 return IDispatch_Release(&This->IDispatch_iface);
391 static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI)
393 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
394 TRACE("(%p/%p)->(%p)\n", iface, This, ppTI);
395 return load_type_info(&This->IDispatch_iface, ppTI, This->clsid, 0);
398 static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID)
400 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
401 TRACE("(%p/%p)->(%d,%s)\n", iface, This, dwGuidKind, debugstr_guid(pGUID));
403 if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
404 return E_INVALIDARG;
405 else {
406 *pGUID = *This->clsid;
407 return S_OK;
411 static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo* iface, ULONG* pcti)
413 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
415 TRACE("(%p/%p)->(%p)\n", iface, This, pcti);
416 *pcti = 1;
417 return S_OK;
420 static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface,
421 ULONG iti,
422 DWORD dwFlags,
423 ITypeInfo** pptiCoClass,
424 DWORD* pdwTIFlags,
425 ULONG* pcdispidReserved,
426 IID* piidPrimary,
427 IID* piidSource)
429 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
431 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, pptiCoClass, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource);
433 if (iti != 0)
434 return E_INVALIDARG;
436 if (dwFlags & MULTICLASSINFO_GETTYPEINFO)
437 load_type_info(&This->IDispatch_iface, pptiCoClass, This->clsid, 0);
439 if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
441 *pdwTIFlags = 0;
442 *pcdispidReserved = 0;
445 if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY){
446 *piidPrimary = *This->clsid;
449 if (dwFlags & MULTICLASSINFO_GETIIDSOURCE){
450 *piidSource = *This->clsid;
453 return S_OK;
456 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl =
458 ProvideMultipleClassInfo_QueryInterface,
459 ProvideMultipleClassInfo_AddRef,
460 ProvideMultipleClassInfo_Release,
461 ProvideMultipleClassInfo_GetClassInfo,
462 ProvideMultipleClassInfo_GetGUID,
463 ProvideMultipleClassInfo_GetMultiTypeInfoCount,
464 ProvideMultipleClassInfo_GetInfoOfIndex
467 static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, REFIID clsid,
468 autoInvokeFunc invokeFunc, autoFreeFunc freeFunc)
470 TRACE("(%p, %d, %s, %p, %p)\n", This, msiHandle, debugstr_guid(clsid), invokeFunc, freeFunc);
472 This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
473 This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
474 This->ref = 1;
476 This->msiHandle = msiHandle;
477 This->clsid = (LPCLSID)clsid;
478 This->funcInvoke = invokeFunc;
479 This->funcFree = freeFunc;
481 /* Load our TypeInfo so we don't have to process GetIDsOfNames */
482 This->iTypeInfo = NULL;
483 return load_type_info(&This->IDispatch_iface, &This->iTypeInfo, clsid, 0);
487 * ListEnumerator methods
490 static inline ListEnumerator *impl_from_IEnumVARIANT(IEnumVARIANT* iface)
492 return CONTAINING_RECORD(iface, ListEnumerator, IEnumVARIANT_iface);
495 static HRESULT WINAPI ListEnumerator_QueryInterface(IEnumVARIANT* iface, REFIID riid,
496 void** ppvObject)
498 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
500 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
502 if (ppvObject == NULL)
503 return E_INVALIDARG;
505 *ppvObject = 0;
507 if (IsEqualGUID(riid, &IID_IUnknown) ||
508 IsEqualGUID(riid, &IID_IEnumVARIANT))
510 *ppvObject = &This->IEnumVARIANT_iface;
512 else
514 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid));
515 return E_NOINTERFACE;
518 IEnumVARIANT_AddRef(iface);
519 return S_OK;
522 static ULONG WINAPI ListEnumerator_AddRef(IEnumVARIANT* iface)
524 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
526 TRACE("(%p/%p)\n", iface, This);
528 return InterlockedIncrement(&This->ref);
531 static ULONG WINAPI ListEnumerator_Release(IEnumVARIANT* iface)
533 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
534 ULONG ref = InterlockedDecrement(&This->ref);
536 TRACE("(%p/%p)\n", iface, This);
538 if (!ref)
540 if (This->list) IDispatch_Release(&This->list->autoobj.IDispatch_iface);
541 msi_free(This);
544 return ref;
547 static HRESULT WINAPI ListEnumerator_Next(IEnumVARIANT* iface, ULONG celt, VARIANT* rgVar,
548 ULONG* fetched)
550 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
551 ULONG i, local;
553 TRACE("(%p, %uld, %p, %p)\n", iface, celt, rgVar, fetched);
555 if (fetched) *fetched = 0;
557 if (!rgVar)
558 return S_FALSE;
560 for (local = 0; local < celt; local++)
561 VariantInit(&rgVar[local]);
563 for (i = This->pos, local = 0; i < This->list->count && local < celt; i++, local++)
564 VariantCopy(&rgVar[local], &This->list->data[i]);
566 if (fetched) *fetched = local;
567 This->pos = i;
569 return (local < celt) ? S_FALSE : S_OK;
572 static HRESULT WINAPI ListEnumerator_Skip(IEnumVARIANT* iface, ULONG celt)
574 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
576 TRACE("(%p,%uld)\n", iface, celt);
578 This->pos += celt;
579 if (This->pos >= This->list->count)
581 This->pos = This->list->count;
582 return S_FALSE;
585 return S_OK;
588 static HRESULT WINAPI ListEnumerator_Reset(IEnumVARIANT* iface)
590 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
592 TRACE("(%p)\n", iface);
594 This->pos = 0;
595 return S_OK;
598 static HRESULT WINAPI ListEnumerator_Clone(IEnumVARIANT* iface, IEnumVARIANT **ppEnum)
600 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
601 HRESULT hr;
603 TRACE("(%p,%p)\n", iface, ppEnum);
605 if (ppEnum == NULL)
606 return S_FALSE;
608 *ppEnum = NULL;
609 hr = create_list_enumerator(This->list, (LPVOID *)ppEnum);
610 if (FAILED(hr))
612 if (*ppEnum) IEnumVARIANT_Release(*ppEnum);
613 return hr;
616 return S_OK;
619 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
621 ListEnumerator_QueryInterface,
622 ListEnumerator_AddRef,
623 ListEnumerator_Release,
624 ListEnumerator_Next,
625 ListEnumerator_Skip,
626 ListEnumerator_Reset,
627 ListEnumerator_Clone
630 /* Create a list enumerator, placing the result in the pointer ppObj. */
631 static HRESULT create_list_enumerator(ListObject *list, void **ppObj)
633 ListEnumerator *object;
635 TRACE("(%p, %p)\n", list, ppObj);
637 object = msi_alloc(sizeof(ListEnumerator));
639 /* Set all the VTable references */
640 object->IEnumVARIANT_iface.lpVtbl = &ListEnumerator_Vtbl;
641 object->ref = 1;
643 /* Store data that was passed */
644 object->pos = 0;
645 object->list = list;
646 if (list) IDispatch_AddRef(&list->autoobj.IDispatch_iface);
648 *ppObj = object;
649 return S_OK;
653 * Individual Object Invocation Functions
656 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
657 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
658 using DispGetParam/VariantChangeType. */
659 static HRESULT DispGetParam_CopyOnly(
660 DISPPARAMS *pdispparams, /* [in] Parameter list */
661 UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
662 VARIANT *pvarResult) /* [out] Destination for resulting variant */
664 /* position is counted backwards */
665 UINT pos;
667 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
668 *position, pdispparams->cArgs, pdispparams->cNamedArgs);
669 if (*position < pdispparams->cArgs) {
670 /* positional arg? */
671 pos = pdispparams->cArgs - *position - 1;
672 } else {
673 /* FIXME: is this how to handle named args? */
674 for (pos=0; pos<pdispparams->cNamedArgs; pos++)
675 if (pdispparams->rgdispidNamedArgs[pos] == *position) break;
677 if (pos==pdispparams->cNamedArgs)
678 return DISP_E_PARAMNOTFOUND;
680 *position = pos;
681 return VariantCopyInd(pvarResult,
682 &pdispparams->rgvarg[pos]);
685 static HRESULT SummaryInfoImpl_Invoke(
686 AutomationObject* This,
687 DISPID dispIdMember,
688 REFIID riid,
689 LCID lcid,
690 WORD wFlags,
691 DISPPARAMS* pDispParams,
692 VARIANT* pVarResult,
693 EXCEPINFO* pExcepInfo,
694 UINT* puArgErr)
696 UINT ret;
697 VARIANTARG varg0, varg1;
698 FILETIME ft, ftlocal;
699 SYSTEMTIME st;
700 HRESULT hr;
702 VariantInit(&varg0);
703 VariantInit(&varg1);
705 switch (dispIdMember)
707 case DISPID_SUMMARYINFO_PROPERTY:
708 if (wFlags & DISPATCH_PROPERTYGET)
710 UINT type;
711 INT value;
712 DWORD size = 0;
713 DATE date;
714 LPWSTR str;
716 static WCHAR szEmpty[] = {0};
718 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
719 if (FAILED(hr)) return hr;
720 ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, &value,
721 &ft, szEmpty, &size);
722 if (ret != ERROR_SUCCESS &&
723 ret != ERROR_MORE_DATA)
725 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
726 return DISP_E_EXCEPTION;
729 switch (type)
731 case VT_EMPTY:
732 break;
734 case VT_I2:
735 case VT_I4:
736 V_VT(pVarResult) = VT_I4;
737 V_I4(pVarResult) = value;
738 break;
740 case VT_LPSTR:
741 if (!(str = msi_alloc(++size * sizeof(WCHAR))))
742 ERR("Out of memory\n");
743 else if ((ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, NULL,
744 NULL, str, &size)) != ERROR_SUCCESS)
745 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
746 else
748 V_VT(pVarResult) = VT_BSTR;
749 V_BSTR(pVarResult) = SysAllocString(str);
751 msi_free(str);
752 break;
754 case VT_FILETIME:
755 FileTimeToLocalFileTime(&ft, &ftlocal);
756 FileTimeToSystemTime(&ftlocal, &st);
757 SystemTimeToVariantTime(&st, &date);
759 V_VT(pVarResult) = VT_DATE;
760 V_DATE(pVarResult) = date;
761 break;
763 default:
764 ERR("Unhandled variant type %d\n", type);
767 else if (wFlags & DISPATCH_PROPERTYPUT)
769 UINT posValue = DISPID_PROPERTYPUT;
771 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
772 if (FAILED(hr)) return hr;
773 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg1);
774 if (FAILED(hr))
776 *puArgErr = posValue;
777 return hr;
780 switch (V_VT(&varg1))
782 case VT_I2:
783 case VT_I4:
784 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), V_VT(&varg1), V_I4(&varg1), NULL, NULL);
785 break;
787 case VT_DATE:
788 VariantTimeToSystemTime(V_DATE(&varg1), &st);
789 SystemTimeToFileTime(&st, &ftlocal);
790 LocalFileTimeToFileTime(&ftlocal, &ft);
791 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_FILETIME, 0, &ft, NULL);
792 break;
794 case VT_BSTR:
795 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_LPSTR, 0, NULL, V_BSTR(&varg1));
796 break;
798 default:
799 FIXME("Unhandled variant type %d\n", V_VT(&varg1));
800 VariantClear(&varg1);
801 return DISP_E_EXCEPTION;
804 if (ret != ERROR_SUCCESS)
806 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret);
807 return DISP_E_EXCEPTION;
810 else return DISP_E_MEMBERNOTFOUND;
811 break;
813 case DISPID_SUMMARYINFO_PROPERTYCOUNT:
814 if (wFlags & DISPATCH_PROPERTYGET) {
815 UINT count;
816 if ((ret = MsiSummaryInfoGetPropertyCount(This->msiHandle, &count)) != ERROR_SUCCESS)
817 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret);
818 else
820 V_VT(pVarResult) = VT_I4;
821 V_I4(pVarResult) = count;
824 else return DISP_E_MEMBERNOTFOUND;
825 break;
827 default:
828 return DISP_E_MEMBERNOTFOUND;
831 VariantClear(&varg1);
832 VariantClear(&varg0);
834 return S_OK;
837 static HRESULT RecordImpl_Invoke(
838 AutomationObject* This,
839 DISPID dispIdMember,
840 REFIID riid,
841 LCID lcid,
842 WORD wFlags,
843 DISPPARAMS* pDispParams,
844 VARIANT* pVarResult,
845 EXCEPINFO* pExcepInfo,
846 UINT* puArgErr)
848 WCHAR *szString;
849 DWORD dwLen;
850 UINT ret;
851 VARIANTARG varg0, varg1;
852 HRESULT hr;
854 VariantInit(&varg0);
855 VariantInit(&varg1);
857 switch (dispIdMember)
859 case DISPID_RECORD_FIELDCOUNT:
860 if (wFlags & DISPATCH_PROPERTYGET) {
861 V_VT(pVarResult) = VT_I4;
862 V_I4(pVarResult) = MsiRecordGetFieldCount(This->msiHandle);
864 else return DISP_E_MEMBERNOTFOUND;
865 break;
867 case DISPID_RECORD_STRINGDATA:
868 if (wFlags & DISPATCH_PROPERTYGET) {
869 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
870 if (FAILED(hr)) return hr;
871 V_VT(pVarResult) = VT_BSTR;
872 V_BSTR(pVarResult) = NULL;
873 if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
875 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
876 ERR("Out of memory\n");
877 else if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
878 V_BSTR(pVarResult) = SysAllocString(szString);
879 msi_free(szString);
881 if (ret != ERROR_SUCCESS)
882 ERR("MsiRecordGetString returned %d\n", ret);
883 } else if (wFlags & DISPATCH_PROPERTYPUT) {
884 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
885 if (FAILED(hr)) return hr;
886 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
887 if (FAILED(hr)) return hr;
888 if ((ret = MsiRecordSetStringW(This->msiHandle, V_I4(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
890 VariantClear(&varg1);
891 ERR("MsiRecordSetString returned %d\n", ret);
892 return DISP_E_EXCEPTION;
895 else return DISP_E_MEMBERNOTFOUND;
896 break;
898 case DISPID_RECORD_INTEGERDATA:
899 if (wFlags & DISPATCH_PROPERTYGET) {
900 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
901 if (FAILED(hr)) return hr;
902 V_VT(pVarResult) = VT_I4;
903 V_I4(pVarResult) = MsiRecordGetInteger(This->msiHandle, V_I4(&varg0));
904 } else if (wFlags & DISPATCH_PROPERTYPUT) {
905 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
906 if (FAILED(hr)) return hr;
907 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
908 if (FAILED(hr)) return hr;
909 if ((ret = MsiRecordSetInteger(This->msiHandle, V_I4(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
911 ERR("MsiRecordSetInteger returned %d\n", ret);
912 return DISP_E_EXCEPTION;
915 else return DISP_E_MEMBERNOTFOUND;
916 break;
918 default:
919 return DISP_E_MEMBERNOTFOUND;
922 VariantClear(&varg1);
923 VariantClear(&varg0);
925 return S_OK;
928 static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
930 AutomationObject *record;
931 HRESULT hr;
933 record = msi_alloc(sizeof(*record));
934 if (!record) return E_OUTOFMEMORY;
936 hr = init_automation_object(record, msiHandle, &DIID_Record, RecordImpl_Invoke, NULL);
937 if (hr != S_OK)
939 msi_free(record);
940 return hr;
943 *disp = &record->IDispatch_iface;
945 return hr;
948 static HRESULT ListImpl_Invoke(
949 AutomationObject* This,
950 DISPID dispIdMember,
951 REFIID riid,
952 LCID lcid,
953 WORD wFlags,
954 DISPPARAMS* pDispParams,
955 VARIANT* pVarResult,
956 EXCEPINFO* pExcepInfo,
957 UINT* puArgErr)
959 ListObject *list = (ListObject*)This;
960 IUnknown *pUnk = NULL;
961 HRESULT hr;
963 switch (dispIdMember)
965 case DISPID_LIST__NEWENUM:
966 if (wFlags & DISPATCH_METHOD) {
967 V_VT(pVarResult) = VT_UNKNOWN;
968 if (SUCCEEDED(hr = create_list_enumerator(list, (LPVOID *)&pUnk)))
969 V_UNKNOWN(pVarResult) = pUnk;
970 else
971 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr);
973 else return DISP_E_MEMBERNOTFOUND;
974 break;
976 case DISPID_LIST_ITEM:
977 if (wFlags & DISPATCH_PROPERTYGET) {
978 VARIANTARG index;
980 VariantInit(&index);
981 hr = DispGetParam(pDispParams, 0, VT_I4, &index, puArgErr);
982 if (FAILED(hr)) return hr;
983 if (V_I4(&index) < 0 || V_I4(&index) >= list->count)
984 return DISP_E_BADINDEX;
985 VariantCopy(pVarResult, &list->data[V_I4(&index)]);
987 else return DISP_E_MEMBERNOTFOUND;
988 break;
990 case DISPID_LIST_COUNT:
991 if (wFlags & DISPATCH_PROPERTYGET) {
992 V_VT(pVarResult) = VT_I4;
993 V_I4(pVarResult) = list->count;
995 else return DISP_E_MEMBERNOTFOUND;
996 break;
998 default:
999 return DISP_E_MEMBERNOTFOUND;
1002 return S_OK;
1005 static void ListImpl_Free(AutomationObject *This)
1007 ListObject *list = (ListObject*)This;
1008 int i;
1010 for (i = 0; i < list->count; i++)
1011 VariantClear(&list->data[i]);
1012 msi_free(list->data);
1015 static HRESULT get_products_count(const WCHAR *product, int *len)
1017 int i = 0;
1019 while (1)
1021 WCHAR dataW[GUID_SIZE];
1022 UINT ret;
1024 /* all or related only */
1025 if (product)
1026 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1027 else
1028 ret = MsiEnumProductsW(i, dataW);
1030 if (ret == ERROR_NO_MORE_ITEMS) break;
1032 if (ret != ERROR_SUCCESS)
1033 return DISP_E_EXCEPTION;
1035 i++;
1038 *len = i;
1040 return S_OK;
1043 static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
1045 ListObject *list;
1046 HRESULT hr;
1047 int i;
1049 list = msi_alloc_zero(sizeof(ListObject));
1050 if (!list) return E_OUTOFMEMORY;
1052 hr = init_automation_object(&list->autoobj, 0, &DIID_StringList, ListImpl_Invoke, ListImpl_Free);
1053 if (hr != S_OK)
1055 msi_free(list);
1056 return hr;
1059 *dispatch = &list->autoobj.IDispatch_iface;
1061 hr = get_products_count(product, &list->count);
1062 if (hr != S_OK)
1064 IDispatch_Release(*dispatch);
1065 return hr;
1068 list->data = msi_alloc(list->count*sizeof(VARIANT));
1069 if (!list->data)
1071 IDispatch_Release(*dispatch);
1072 return E_OUTOFMEMORY;
1075 for (i = 0; i < list->count; i++)
1077 WCHAR dataW[GUID_SIZE];
1078 UINT ret;
1080 /* all or related only */
1081 if (product)
1082 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1083 else
1084 ret = MsiEnumProductsW(i, dataW);
1086 if (ret == ERROR_NO_MORE_ITEMS) break;
1088 V_VT(&list->data[i]) = VT_BSTR;
1089 V_BSTR(&list->data[i]) = SysAllocString(dataW);
1092 return S_OK;
1095 static HRESULT ViewImpl_Invoke(
1096 AutomationObject* This,
1097 DISPID dispIdMember,
1098 REFIID riid,
1099 LCID lcid,
1100 WORD wFlags,
1101 DISPPARAMS* pDispParams,
1102 VARIANT* pVarResult,
1103 EXCEPINFO* pExcepInfo,
1104 UINT* puArgErr)
1106 MSIHANDLE msiHandle;
1107 UINT ret;
1108 VARIANTARG varg0, varg1;
1109 HRESULT hr;
1111 VariantInit(&varg0);
1112 VariantInit(&varg1);
1114 switch (dispIdMember)
1116 case DISPID_VIEW_EXECUTE:
1117 if (wFlags & DISPATCH_METHOD)
1119 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &varg0, puArgErr);
1120 if (SUCCEEDED(hr) && V_DISPATCH(&varg0) != NULL)
1121 MsiViewExecute(This->msiHandle, ((AutomationObject *)V_DISPATCH(&varg0))->msiHandle);
1122 else
1123 MsiViewExecute(This->msiHandle, 0);
1125 else return DISP_E_MEMBERNOTFOUND;
1126 break;
1128 case DISPID_VIEW_FETCH:
1129 if (wFlags & DISPATCH_METHOD)
1131 V_VT(pVarResult) = VT_DISPATCH;
1132 if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS)
1134 IDispatch *dispatch = NULL;
1136 if (SUCCEEDED(hr = create_record(msiHandle, &dispatch)))
1137 V_DISPATCH(pVarResult) = dispatch;
1138 else
1139 ERR("Failed to create Record object, hresult 0x%08x\n", hr);
1141 else if (ret == ERROR_NO_MORE_ITEMS)
1142 V_DISPATCH(pVarResult) = NULL;
1143 else
1145 ERR("MsiViewFetch returned %d\n", ret);
1146 return DISP_E_EXCEPTION;
1149 else return DISP_E_MEMBERNOTFOUND;
1150 break;
1152 case DISPID_VIEW_MODIFY:
1153 if (wFlags & DISPATCH_METHOD)
1155 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1156 if (FAILED(hr)) return hr;
1157 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1158 if (FAILED(hr)) return hr;
1159 if (!V_DISPATCH(&varg1)) return DISP_E_EXCEPTION;
1160 if ((ret = MsiViewModify(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle)) != ERROR_SUCCESS)
1162 VariantClear(&varg1);
1163 ERR("MsiViewModify returned %d\n", ret);
1164 return DISP_E_EXCEPTION;
1167 else return DISP_E_MEMBERNOTFOUND;
1168 break;
1170 case DISPID_VIEW_CLOSE:
1171 if (wFlags & DISPATCH_METHOD)
1173 MsiViewClose(This->msiHandle);
1175 else return DISP_E_MEMBERNOTFOUND;
1176 break;
1178 default:
1179 return DISP_E_MEMBERNOTFOUND;
1182 VariantClear(&varg1);
1183 VariantClear(&varg0);
1185 return S_OK;
1188 static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
1189 DISPPARAMS* pDispParams,
1190 VARIANT* pVarResult,
1191 EXCEPINFO* pExcepInfo,
1192 UINT* puArgErr)
1194 if (!(wFlags & DISPATCH_METHOD))
1195 return DISP_E_MEMBERNOTFOUND;
1197 FIXME("\n");
1199 VariantInit(pVarResult);
1200 return S_OK;
1203 static HRESULT DatabaseImpl_Invoke(
1204 AutomationObject* This,
1205 DISPID dispIdMember,
1206 REFIID riid,
1207 LCID lcid,
1208 WORD wFlags,
1209 DISPPARAMS* pDispParams,
1210 VARIANT* pVarResult,
1211 EXCEPINFO* pExcepInfo,
1212 UINT* puArgErr)
1214 IDispatch *dispatch = NULL;
1215 MSIHANDLE msiHandle;
1216 UINT ret;
1217 VARIANTARG varg0, varg1;
1218 HRESULT hr;
1220 VariantInit(&varg0);
1221 VariantInit(&varg1);
1223 switch (dispIdMember)
1225 case DISPID_DATABASE_SUMMARYINFORMATION:
1226 if (wFlags & DISPATCH_PROPERTYGET)
1228 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1229 if (FAILED(hr))
1230 V_I4(&varg0) = 0;
1232 V_VT(pVarResult) = VT_DISPATCH;
1233 if ((ret = MsiGetSummaryInformationW(This->msiHandle, NULL, V_I4(&varg0), &msiHandle)) == ERROR_SUCCESS)
1235 hr = create_summaryinfo(msiHandle, &dispatch);
1236 if (SUCCEEDED(hr))
1237 V_DISPATCH(pVarResult) = dispatch;
1238 else
1239 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr);
1241 else
1243 ERR("MsiGetSummaryInformation returned %d\n", ret);
1244 return DISP_E_EXCEPTION;
1247 else return DISP_E_MEMBERNOTFOUND;
1248 break;
1250 case DISPID_DATABASE_OPENVIEW:
1251 if (wFlags & DISPATCH_METHOD)
1253 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1254 if (FAILED(hr)) return hr;
1255 V_VT(pVarResult) = VT_DISPATCH;
1256 if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS)
1258 if (SUCCEEDED(hr = create_view(msiHandle, &dispatch)))
1259 V_DISPATCH(pVarResult) = dispatch;
1260 else
1261 ERR("Failed to create View object, hresult 0x%08x\n", hr);
1263 else
1265 VariantClear(&varg0);
1266 ERR("MsiDatabaseOpenView returned %d\n", ret);
1267 return DISP_E_EXCEPTION;
1270 else return DISP_E_MEMBERNOTFOUND;
1271 break;
1273 case DISPID_INSTALLER_LASTERRORRECORD:
1274 return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
1275 pVarResult, pExcepInfo,
1276 puArgErr);
1278 default:
1279 return DISP_E_MEMBERNOTFOUND;
1282 VariantClear(&varg1);
1283 VariantClear(&varg0);
1285 return S_OK;
1288 static HRESULT SessionImpl_Invoke(
1289 AutomationObject* This,
1290 DISPID dispIdMember,
1291 REFIID riid,
1292 LCID lcid,
1293 WORD wFlags,
1294 DISPPARAMS* pDispParams,
1295 VARIANT* pVarResult,
1296 EXCEPINFO* pExcepInfo,
1297 UINT* puArgErr)
1299 SessionObject *session = (SessionObject*)This;
1300 WCHAR *szString;
1301 DWORD dwLen;
1302 MSIHANDLE msiHandle;
1303 LANGID langId;
1304 UINT ret;
1305 INSTALLSTATE iInstalled, iAction;
1306 VARIANTARG varg0, varg1;
1307 HRESULT hr;
1309 VariantInit(&varg0);
1310 VariantInit(&varg1);
1312 switch (dispIdMember)
1314 case DISPID_SESSION_INSTALLER:
1315 if (wFlags & DISPATCH_PROPERTYGET) {
1316 V_VT(pVarResult) = VT_DISPATCH;
1317 IDispatch_AddRef(session->installer);
1318 V_DISPATCH(pVarResult) = session->installer;
1320 else return DISP_E_MEMBERNOTFOUND;
1321 break;
1323 case DISPID_SESSION_PROPERTY:
1324 if (wFlags & DISPATCH_PROPERTYGET) {
1325 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1326 if (FAILED(hr)) return hr;
1327 V_VT(pVarResult) = VT_BSTR;
1328 V_BSTR(pVarResult) = NULL;
1329 if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
1331 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
1332 ERR("Out of memory\n");
1333 else if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
1334 V_BSTR(pVarResult) = SysAllocString(szString);
1335 msi_free(szString);
1337 if (ret != ERROR_SUCCESS)
1338 ERR("MsiGetProperty returned %d\n", ret);
1339 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1340 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1341 if (FAILED(hr)) return hr;
1342 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1343 if (FAILED(hr)) {
1344 VariantClear(&varg0);
1345 return hr;
1347 if ((ret = MsiSetPropertyW(This->msiHandle, V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
1349 VariantClear(&varg0);
1350 VariantClear(&varg1);
1351 ERR("MsiSetProperty returned %d\n", ret);
1352 return DISP_E_EXCEPTION;
1355 else return DISP_E_MEMBERNOTFOUND;
1356 break;
1358 case DISPID_SESSION_LANGUAGE:
1359 if (wFlags & DISPATCH_PROPERTYGET) {
1360 langId = MsiGetLanguage(This->msiHandle);
1361 V_VT(pVarResult) = VT_I4;
1362 V_I4(pVarResult) = langId;
1364 else return DISP_E_MEMBERNOTFOUND;
1365 break;
1367 case DISPID_SESSION_MODE:
1368 if (wFlags & DISPATCH_PROPERTYGET) {
1369 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1370 if (FAILED(hr)) return hr;
1371 V_VT(pVarResult) = VT_BOOL;
1372 V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0));
1373 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1374 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1375 if (FAILED(hr)) return hr;
1376 hr = DispGetParam(pDispParams, 1, VT_BOOL, &varg1, puArgErr);
1377 if (FAILED(hr)) return hr;
1378 if ((ret = MsiSetMode(This->msiHandle, V_I4(&varg0), V_BOOL(&varg1))) != ERROR_SUCCESS)
1380 ERR("MsiSetMode returned %d\n", ret);
1381 return DISP_E_EXCEPTION;
1384 else return DISP_E_MEMBERNOTFOUND;
1385 break;
1387 case DISPID_SESSION_DATABASE:
1388 if (wFlags & DISPATCH_PROPERTYGET) {
1389 V_VT(pVarResult) = VT_DISPATCH;
1390 if ((msiHandle = MsiGetActiveDatabase(This->msiHandle)))
1392 IDispatch *dispatch;
1394 if (SUCCEEDED(hr = create_database(msiHandle, &dispatch)))
1395 V_DISPATCH(pVarResult) = dispatch;
1396 else
1397 ERR("Failed to create Database object, hresult 0x%08x\n", hr);
1399 else
1401 ERR("MsiGetActiveDatabase failed\n");
1402 return DISP_E_EXCEPTION;
1405 else return DISP_E_MEMBERNOTFOUND;
1406 break;
1408 case DISPID_SESSION_DOACTION:
1409 if (wFlags & DISPATCH_METHOD) {
1410 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1411 if (FAILED(hr)) return hr;
1412 ret = MsiDoActionW(This->msiHandle, V_BSTR(&varg0));
1413 V_VT(pVarResult) = VT_I4;
1414 switch (ret)
1416 case ERROR_FUNCTION_NOT_CALLED:
1417 V_I4(pVarResult) = msiDoActionStatusNoAction;
1418 break;
1419 case ERROR_SUCCESS:
1420 V_I4(pVarResult) = msiDoActionStatusSuccess;
1421 break;
1422 case ERROR_INSTALL_USEREXIT:
1423 V_I4(pVarResult) = msiDoActionStatusUserExit;
1424 break;
1425 case ERROR_INSTALL_FAILURE:
1426 V_I4(pVarResult) = msiDoActionStatusFailure;
1427 break;
1428 case ERROR_INSTALL_SUSPEND:
1429 V_I4(pVarResult) = msiDoActionStatusSuspend;
1430 break;
1431 case ERROR_MORE_DATA:
1432 V_I4(pVarResult) = msiDoActionStatusFinished;
1433 break;
1434 case ERROR_INVALID_HANDLE_STATE:
1435 V_I4(pVarResult) = msiDoActionStatusWrongState;
1436 break;
1437 case ERROR_INVALID_DATA:
1438 V_I4(pVarResult) = msiDoActionStatusBadActionData;
1439 break;
1440 default:
1441 VariantClear(&varg0);
1442 FIXME("MsiDoAction returned unhandled value %d\n", ret);
1443 return DISP_E_EXCEPTION;
1446 else return DISP_E_MEMBERNOTFOUND;
1447 break;
1449 case DISPID_SESSION_EVALUATECONDITION:
1450 if (wFlags & DISPATCH_METHOD) {
1451 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1452 if (FAILED(hr)) return hr;
1453 V_VT(pVarResult) = VT_I4;
1454 V_I4(pVarResult) = MsiEvaluateConditionW(This->msiHandle, V_BSTR(&varg0));
1456 else return DISP_E_MEMBERNOTFOUND;
1457 break;
1459 case DISPID_SESSION_MESSAGE:
1460 if(!(wFlags & DISPATCH_METHOD))
1461 return DISP_E_MEMBERNOTFOUND;
1463 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1464 if (FAILED(hr)) return hr;
1465 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1466 if (FAILED(hr)) return hr;
1468 V_VT(pVarResult) = VT_I4;
1469 V_I4(pVarResult) =
1470 MsiProcessMessage(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle);
1471 break;
1473 case DISPID_SESSION_SETINSTALLLEVEL:
1474 if (wFlags & DISPATCH_METHOD) {
1475 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1476 if (FAILED(hr)) return hr;
1477 if ((ret = MsiSetInstallLevel(This->msiHandle, V_I4(&varg0))) != ERROR_SUCCESS)
1479 ERR("MsiSetInstallLevel returned %d\n", ret);
1480 return DISP_E_EXCEPTION;
1483 else return DISP_E_MEMBERNOTFOUND;
1484 break;
1486 case DISPID_SESSION_FEATURECURRENTSTATE:
1487 if (wFlags & DISPATCH_PROPERTYGET) {
1488 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1489 if (FAILED(hr)) return hr;
1490 V_VT(pVarResult) = VT_I4;
1491 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1492 V_I4(pVarResult) = iInstalled;
1493 else
1495 ERR("MsiGetFeatureState returned %d\n", ret);
1496 V_I4(pVarResult) = msiInstallStateUnknown;
1499 else return DISP_E_MEMBERNOTFOUND;
1500 break;
1502 case DISPID_SESSION_FEATUREREQUESTSTATE:
1503 if (wFlags & DISPATCH_PROPERTYGET) {
1504 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1505 if (FAILED(hr)) return hr;
1506 V_VT(pVarResult) = VT_I4;
1507 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1508 V_I4(pVarResult) = iAction;
1509 else
1511 ERR("MsiGetFeatureState returned %d\n", ret);
1512 V_I4(pVarResult) = msiInstallStateUnknown;
1514 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1515 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1516 if (FAILED(hr)) return hr;
1517 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1518 if (FAILED(hr)) {
1519 VariantClear(&varg0);
1520 return hr;
1522 if ((ret = MsiSetFeatureStateW(This->msiHandle, V_BSTR(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
1524 VariantClear(&varg0);
1525 ERR("MsiSetFeatureState returned %d\n", ret);
1526 return DISP_E_EXCEPTION;
1529 else return DISP_E_MEMBERNOTFOUND;
1530 break;
1532 default:
1533 return DISP_E_MEMBERNOTFOUND;
1536 VariantClear(&varg1);
1537 VariantClear(&varg0);
1539 return S_OK;
1542 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1543 * registry value type. Used by Installer::RegistryValue. */
1544 static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize)
1546 static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1547 static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 };
1548 WCHAR *szString = (WCHAR *)lpData;
1549 LPWSTR szNewString = NULL;
1550 DWORD dwNewSize = 0;
1551 int idx;
1553 switch (dwType)
1555 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1556 case REG_MULTI_SZ: /* Multi SZ change internal null characters to newlines */
1557 idx = (dwSize/sizeof(WCHAR))-1;
1558 while (idx >= 0 && !szString[idx]) idx--;
1559 for (; idx >= 0; idx--)
1560 if (!szString[idx]) szString[idx] = '\n';
1561 /* fall through */
1562 case REG_SZ:
1563 V_VT(pVarResult) = VT_BSTR;
1564 V_BSTR(pVarResult) = SysAllocStringByteLen((LPCSTR)szString, dwSize);
1565 break;
1567 case REG_EXPAND_SZ:
1568 if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1569 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1570 else if (!(szNewString = msi_alloc(dwNewSize * sizeof(WCHAR))))
1571 ERR("Out of memory\n");
1572 else if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1573 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1574 else
1576 V_VT(pVarResult) = VT_BSTR;
1577 V_BSTR(pVarResult) = SysAllocStringLen(szNewString, dwNewSize);
1579 msi_free(szNewString);
1580 break;
1582 case REG_DWORD:
1583 V_VT(pVarResult) = VT_I4;
1584 V_I4(pVarResult) = *((DWORD *)lpData);
1585 break;
1587 case REG_QWORD:
1588 V_VT(pVarResult) = VT_BSTR;
1589 V_BSTR(pVarResult) = SysAllocString(szREG_); /* Weird string, don't know why native returns it */
1590 break;
1592 case REG_BINARY:
1593 V_VT(pVarResult) = VT_BSTR;
1594 V_BSTR(pVarResult) = SysAllocString(szREG_BINARY);
1595 break;
1597 case REG_NONE:
1598 V_VT(pVarResult) = VT_EMPTY;
1599 break;
1601 default:
1602 FIXME("Unhandled registry value type %d\n", dwType);
1606 static HRESULT InstallerImpl_CreateRecord(WORD wFlags,
1607 DISPPARAMS* pDispParams,
1608 VARIANT* pVarResult,
1609 EXCEPINFO* pExcepInfo,
1610 UINT* puArgErr)
1612 HRESULT hr;
1613 VARIANTARG varg0;
1614 MSIHANDLE hrec;
1615 IDispatch* dispatch;
1617 if (!(wFlags & DISPATCH_METHOD))
1618 return DISP_E_MEMBERNOTFOUND;
1620 VariantInit(&varg0);
1621 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1622 if (FAILED(hr))
1623 return hr;
1625 V_VT(pVarResult) = VT_DISPATCH;
1627 hrec = MsiCreateRecord(V_I4(&varg0));
1628 if (!hrec)
1629 return DISP_E_EXCEPTION;
1631 hr = create_record(hrec, &dispatch);
1632 if (SUCCEEDED(hr))
1633 V_DISPATCH(pVarResult) = dispatch;
1635 return hr;
1638 static HRESULT InstallerImpl_OpenPackage(AutomationObject* This,
1639 WORD wFlags,
1640 DISPPARAMS* pDispParams,
1641 VARIANT* pVarResult,
1642 EXCEPINFO* pExcepInfo,
1643 UINT* puArgErr)
1645 UINT ret;
1646 HRESULT hr;
1647 MSIHANDLE hpkg;
1648 IDispatch* dispatch;
1649 VARIANTARG varg0, varg1;
1651 if (!(wFlags & DISPATCH_METHOD))
1652 return DISP_E_MEMBERNOTFOUND;
1654 if (pDispParams->cArgs == 0)
1655 return DISP_E_TYPEMISMATCH;
1657 if (V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1]) != VT_BSTR)
1658 return DISP_E_TYPEMISMATCH;
1660 VariantInit(&varg0);
1661 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1662 if (FAILED(hr))
1663 return hr;
1665 VariantInit(&varg1);
1666 if (pDispParams->cArgs == 2)
1668 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1669 if (FAILED(hr))
1670 goto done;
1672 else
1674 V_VT(&varg1) = VT_I4;
1675 V_I4(&varg1) = 0;
1678 V_VT(pVarResult) = VT_DISPATCH;
1680 ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &hpkg);
1681 if (ret != ERROR_SUCCESS)
1683 hr = DISP_E_EXCEPTION;
1684 goto done;
1687 hr = create_session(hpkg, &This->IDispatch_iface, &dispatch);
1688 if (SUCCEEDED(hr))
1689 V_DISPATCH(pVarResult) = dispatch;
1691 done:
1692 VariantClear(&varg0);
1693 VariantClear(&varg1);
1694 return hr;
1697 static HRESULT InstallerImpl_OpenProduct(WORD wFlags,
1698 DISPPARAMS* pDispParams,
1699 VARIANT* pVarResult,
1700 EXCEPINFO* pExcepInfo,
1701 UINT* puArgErr)
1703 HRESULT hr;
1704 VARIANTARG varg0;
1706 if (!(wFlags & DISPATCH_METHOD))
1707 return DISP_E_MEMBERNOTFOUND;
1709 VariantInit(&varg0);
1710 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1711 if (FAILED(hr))
1712 return hr;
1714 FIXME("%s\n", debugstr_w(V_BSTR(&varg0)));
1716 VariantInit(pVarResult);
1718 VariantClear(&varg0);
1719 return S_OK;
1722 static HRESULT InstallerImpl_OpenDatabase(WORD wFlags,
1723 DISPPARAMS* pDispParams,
1724 VARIANT* pVarResult,
1725 EXCEPINFO* pExcepInfo,
1726 UINT* puArgErr)
1728 UINT ret;
1729 HRESULT hr;
1730 MSIHANDLE hdb;
1731 IDispatch* dispatch;
1732 VARIANTARG varg0, varg1;
1734 if (!(wFlags & DISPATCH_METHOD))
1735 return DISP_E_MEMBERNOTFOUND;
1737 VariantInit(&varg0);
1738 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1739 if (FAILED(hr))
1740 return hr;
1742 VariantInit(&varg1);
1743 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1744 if (FAILED(hr))
1745 goto done;
1747 V_VT(pVarResult) = VT_DISPATCH;
1749 ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &hdb);
1750 if (ret != ERROR_SUCCESS)
1752 hr = DISP_E_EXCEPTION;
1753 goto done;
1756 hr = create_database(hdb, &dispatch);
1757 if (SUCCEEDED(hr))
1758 V_DISPATCH(pVarResult) = dispatch;
1760 done:
1761 VariantClear(&varg0);
1762 VariantClear(&varg1);
1763 return hr;
1766 static HRESULT InstallerImpl_SummaryInformation(WORD wFlags,
1767 DISPPARAMS* pDispParams,
1768 VARIANT* pVarResult,
1769 EXCEPINFO* pExcepInfo,
1770 UINT* puArgErr)
1772 if (!(wFlags & DISPATCH_METHOD))
1773 return DISP_E_MEMBERNOTFOUND;
1775 FIXME("\n");
1777 VariantInit(pVarResult);
1778 return S_OK;
1781 static HRESULT InstallerImpl_UILevel(WORD wFlags,
1782 DISPPARAMS* pDispParams,
1783 VARIANT* pVarResult,
1784 EXCEPINFO* pExcepInfo,
1785 UINT* puArgErr)
1787 HRESULT hr;
1788 VARIANTARG varg0;
1789 INSTALLUILEVEL ui;
1791 if (!(wFlags & DISPATCH_PROPERTYPUT) && !(wFlags & DISPATCH_PROPERTYGET))
1792 return DISP_E_MEMBERNOTFOUND;
1794 if (wFlags & DISPATCH_PROPERTYPUT)
1796 VariantInit(&varg0);
1797 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1798 if (FAILED(hr))
1799 return hr;
1801 ui = MsiSetInternalUI(V_I4(&varg0), NULL);
1802 if (ui == INSTALLUILEVEL_NOCHANGE)
1803 return DISP_E_EXCEPTION;
1805 else if (wFlags & DISPATCH_PROPERTYGET)
1807 ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
1808 if (ui == INSTALLUILEVEL_NOCHANGE)
1809 return DISP_E_EXCEPTION;
1811 V_VT(pVarResult) = VT_I4;
1812 V_I4(pVarResult) = ui;
1815 return S_OK;
1818 static HRESULT InstallerImpl_EnableLog(WORD wFlags,
1819 DISPPARAMS* pDispParams,
1820 VARIANT* pVarResult,
1821 EXCEPINFO* pExcepInfo,
1822 UINT* puArgErr)
1824 if (!(wFlags & DISPATCH_METHOD))
1825 return DISP_E_MEMBERNOTFOUND;
1827 FIXME("\n");
1829 VariantInit(pVarResult);
1830 return S_OK;
1833 static HRESULT InstallerImpl_InstallProduct(WORD wFlags,
1834 DISPPARAMS* pDispParams,
1835 VARIANT* pVarResult,
1836 EXCEPINFO* pExcepInfo,
1837 UINT* puArgErr)
1839 UINT ret;
1840 HRESULT hr;
1841 VARIANTARG varg0, varg1;
1843 if (!(wFlags & DISPATCH_METHOD))
1844 return DISP_E_MEMBERNOTFOUND;
1846 VariantInit(&varg0);
1847 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1848 if (FAILED(hr))
1849 return hr;
1851 VariantInit(&varg1);
1852 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1853 if (FAILED(hr))
1854 goto done;
1856 ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1));
1857 if (ret != ERROR_SUCCESS)
1859 hr = DISP_E_EXCEPTION;
1860 goto done;
1863 done:
1864 VariantClear(&varg0);
1865 VariantClear(&varg1);
1866 return hr;
1869 static HRESULT InstallerImpl_Version(WORD wFlags,
1870 VARIANT* pVarResult,
1871 EXCEPINFO* pExcepInfo,
1872 UINT* puArgErr)
1874 HRESULT hr;
1875 DLLVERSIONINFO verinfo;
1876 WCHAR version[MAX_PATH];
1878 static const WCHAR format[] = {
1879 '%','d','.','%','d','.','%','d','.','%','d',0};
1881 if (!(wFlags & DISPATCH_PROPERTYGET))
1882 return DISP_E_MEMBERNOTFOUND;
1884 verinfo.cbSize = sizeof(DLLVERSIONINFO);
1885 hr = DllGetVersion(&verinfo);
1886 if (FAILED(hr))
1887 return hr;
1889 sprintfW(version, format, verinfo.dwMajorVersion, verinfo.dwMinorVersion,
1890 verinfo.dwBuildNumber, verinfo.dwPlatformID);
1892 V_VT(pVarResult) = VT_BSTR;
1893 V_BSTR(pVarResult) = SysAllocString(version);
1894 return S_OK;
1897 static HRESULT InstallerImpl_LastErrorRecord(WORD wFlags,
1898 DISPPARAMS* pDispParams,
1899 VARIANT* pVarResult,
1900 EXCEPINFO* pExcepInfo,
1901 UINT* puArgErr)
1903 if (!(wFlags & DISPATCH_METHOD))
1904 return DISP_E_MEMBERNOTFOUND;
1906 FIXME("\n");
1908 VariantInit(pVarResult);
1909 return S_OK;
1912 static HRESULT InstallerImpl_RegistryValue(WORD wFlags,
1913 DISPPARAMS* pDispParams,
1914 VARIANT* pVarResult,
1915 EXCEPINFO* pExcepInfo,
1916 UINT* puArgErr)
1918 UINT ret;
1919 HKEY hkey = NULL;
1920 HRESULT hr;
1921 UINT posValue;
1922 DWORD type, size;
1923 LPWSTR szString = NULL;
1924 VARIANTARG varg0, varg1, varg2;
1926 if (!(wFlags & DISPATCH_METHOD))
1927 return DISP_E_MEMBERNOTFOUND;
1929 VariantInit(&varg0);
1930 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1931 if (FAILED(hr))
1932 return hr;
1934 VariantInit(&varg1);
1935 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1936 if (FAILED(hr))
1937 goto done;
1939 /* Save valuePos so we can save puArgErr if we are unable to do our type
1940 * conversions.
1942 posValue = 2;
1943 VariantInit(&varg2);
1944 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2);
1945 if (FAILED(hr))
1946 goto done;
1948 if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT &&
1949 V_I4(&varg0) <= REG_INDEX_DYN_DATA)
1951 V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT;
1954 ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey);
1956 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
1957 if (ret != ERROR_SUCCESS && V_VT(&varg2) != VT_EMPTY)
1959 hr = DISP_E_BADINDEX;
1960 goto done;
1963 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
1964 switch (V_VT(&varg2))
1966 /* Return VT_BOOL clarifying whether registry key exists or not. */
1967 case VT_EMPTY:
1968 V_VT(pVarResult) = VT_BOOL;
1969 V_BOOL(pVarResult) = (ret == ERROR_SUCCESS);
1970 break;
1972 /* Return the value of specified key if it exists. */
1973 case VT_BSTR:
1974 ret = RegQueryValueExW(hkey, V_BSTR(&varg2),
1975 NULL, NULL, NULL, &size);
1976 if (ret != ERROR_SUCCESS)
1978 hr = DISP_E_BADINDEX;
1979 goto done;
1982 szString = msi_alloc(size);
1983 if (!szString)
1985 hr = E_OUTOFMEMORY;
1986 goto done;
1989 ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL,
1990 &type, (LPBYTE)szString, &size);
1991 if (ret != ERROR_SUCCESS)
1993 msi_free(szString);
1994 hr = DISP_E_BADINDEX;
1995 goto done;
1998 variant_from_registry_value(pVarResult, type,
1999 (LPBYTE)szString, size);
2000 msi_free(szString);
2001 break;
2003 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2004 default:
2005 hr = VariantChangeType(&varg2, &varg2, 0, VT_I4);
2006 if (FAILED(hr))
2008 if (hr == DISP_E_TYPEMISMATCH)
2009 *puArgErr = posValue;
2011 goto done;
2014 /* Retrieve class name or maximum value name or subkey name size. */
2015 if (!V_I4(&varg2))
2016 ret = RegQueryInfoKeyW(hkey, NULL, &size, NULL, NULL, NULL,
2017 NULL, NULL, NULL, NULL, NULL, NULL);
2018 else if (V_I4(&varg2) > 0)
2019 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL,
2020 NULL, NULL, &size, NULL, NULL, NULL);
2021 else /* V_I4(&varg2) < 0 */
2022 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &size,
2023 NULL, NULL, NULL, NULL, NULL, NULL);
2025 if (ret != ERROR_SUCCESS)
2026 goto done;
2028 szString = msi_alloc(++size * sizeof(WCHAR));
2029 if (!szString)
2031 hr = E_OUTOFMEMORY;
2032 goto done;
2035 if (!V_I4(&varg2))
2036 ret = RegQueryInfoKeyW(hkey, szString, &size,NULL, NULL, NULL,
2037 NULL, NULL, NULL, NULL, NULL, NULL);
2038 else if (V_I4(&varg2) > 0)
2039 ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString,
2040 &size, 0, 0, NULL, NULL);
2041 else /* V_I4(&varg2) < 0 */
2042 ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, size);
2044 if (ret == ERROR_SUCCESS)
2046 V_VT(pVarResult) = VT_BSTR;
2047 V_BSTR(pVarResult) = SysAllocString(szString);
2050 msi_free(szString);
2053 done:
2054 VariantClear(&varg0);
2055 VariantClear(&varg1);
2056 VariantClear(&varg2);
2057 RegCloseKey(hkey);
2058 return hr;
2061 static HRESULT InstallerImpl_Environment(WORD wFlags,
2062 DISPPARAMS* pDispParams,
2063 VARIANT* pVarResult,
2064 EXCEPINFO* pExcepInfo,
2065 UINT* puArgErr)
2067 if (!(wFlags & DISPATCH_METHOD))
2068 return DISP_E_MEMBERNOTFOUND;
2070 FIXME("\n");
2072 VariantInit(pVarResult);
2073 return S_OK;
2076 static HRESULT InstallerImpl_FileAttributes(WORD wFlags,
2077 DISPPARAMS* pDispParams,
2078 VARIANT* pVarResult,
2079 EXCEPINFO* pExcepInfo,
2080 UINT* puArgErr)
2082 if (!(wFlags & DISPATCH_METHOD))
2083 return DISP_E_MEMBERNOTFOUND;
2085 FIXME("\n");
2087 VariantInit(pVarResult);
2088 return S_OK;
2091 static HRESULT InstallerImpl_FileSize(WORD wFlags,
2092 DISPPARAMS* pDispParams,
2093 VARIANT* pVarResult,
2094 EXCEPINFO* pExcepInfo,
2095 UINT* puArgErr)
2097 if (!(wFlags & DISPATCH_METHOD))
2098 return DISP_E_MEMBERNOTFOUND;
2100 FIXME("\n");
2102 VariantInit(pVarResult);
2103 return S_OK;
2106 static HRESULT InstallerImpl_FileVersion(WORD wFlags,
2107 DISPPARAMS* pDispParams,
2108 VARIANT* pVarResult,
2109 EXCEPINFO* pExcepInfo,
2110 UINT* puArgErr)
2112 if (!(wFlags & DISPATCH_METHOD))
2113 return DISP_E_MEMBERNOTFOUND;
2115 FIXME("\n");
2117 VariantInit(pVarResult);
2118 return S_OK;
2121 static HRESULT InstallerImpl_ProductState(WORD wFlags,
2122 DISPPARAMS* pDispParams,
2123 VARIANT* pVarResult,
2124 EXCEPINFO* pExcepInfo,
2125 UINT* puArgErr)
2127 HRESULT hr;
2128 VARIANTARG varg0;
2130 if (!(wFlags & DISPATCH_PROPERTYGET))
2131 return DISP_E_MEMBERNOTFOUND;
2133 VariantInit(&varg0);
2134 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2135 if (FAILED(hr))
2136 return hr;
2138 V_VT(pVarResult) = VT_I4;
2139 V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0));
2141 VariantClear(&varg0);
2142 return S_OK;
2145 static HRESULT InstallerImpl_ProductInfo(WORD wFlags,
2146 DISPPARAMS* pDispParams,
2147 VARIANT* pVarResult,
2148 EXCEPINFO* pExcepInfo,
2149 UINT* puArgErr)
2151 UINT ret;
2152 HRESULT hr;
2153 DWORD size;
2154 LPWSTR str = NULL;
2155 VARIANTARG varg0, varg1;
2157 if (!(wFlags & DISPATCH_PROPERTYGET))
2158 return DISP_E_MEMBERNOTFOUND;
2160 VariantInit(&varg0);
2161 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2162 if (FAILED(hr))
2163 return hr;
2165 VariantInit(&varg1);
2166 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
2167 if (FAILED(hr))
2168 goto done;
2170 V_VT(pVarResult) = VT_BSTR;
2171 V_BSTR(pVarResult) = NULL;
2173 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &size);
2174 if (ret != ERROR_SUCCESS)
2176 hr = DISP_E_EXCEPTION;
2177 goto done;
2180 str = msi_alloc(++size * sizeof(WCHAR));
2181 if (!str)
2183 hr = E_OUTOFMEMORY;
2184 goto done;
2187 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), str, &size);
2188 if (ret != ERROR_SUCCESS)
2190 hr = DISP_E_EXCEPTION;
2191 goto done;
2194 V_BSTR(pVarResult) = SysAllocString(str);
2195 hr = S_OK;
2197 done:
2198 msi_free(str);
2199 VariantClear(&varg0);
2200 VariantClear(&varg1);
2201 return hr;
2204 static HRESULT InstallerImpl_Products(WORD flags,
2205 DISPPARAMS* pDispParams,
2206 VARIANT* result,
2207 EXCEPINFO* pExcepInfo,
2208 UINT* puArgErr)
2210 IDispatch *dispatch;
2211 HRESULT hr;
2213 if (!(flags & DISPATCH_PROPERTYGET))
2214 return DISP_E_MEMBERNOTFOUND;
2216 hr = create_list(NULL, &dispatch);
2217 if (FAILED(hr))
2218 return hr;
2220 V_VT(result) = VT_DISPATCH;
2221 V_DISPATCH(result) = dispatch;
2223 return hr;
2226 static HRESULT InstallerImpl_RelatedProducts(WORD flags,
2227 DISPPARAMS* pDispParams,
2228 VARIANT* result,
2229 EXCEPINFO* pExcepInfo,
2230 UINT* puArgErr)
2232 IDispatch* dispatch;
2233 VARIANTARG related;
2234 HRESULT hr;
2236 if (!(flags & DISPATCH_PROPERTYGET))
2237 return DISP_E_MEMBERNOTFOUND;
2239 VariantInit(&related);
2240 hr = DispGetParam(pDispParams, 0, VT_BSTR, &related, puArgErr);
2241 if (FAILED(hr))
2242 return hr;
2244 hr = create_list(V_BSTR(&related), &dispatch);
2245 VariantClear(&related);
2247 V_VT(result) = VT_DISPATCH;
2248 V_DISPATCH(result) = dispatch;
2250 return hr;
2253 static HRESULT InstallerImpl_Invoke(
2254 AutomationObject* This,
2255 DISPID dispIdMember,
2256 REFIID riid,
2257 LCID lcid,
2258 WORD wFlags,
2259 DISPPARAMS* pDispParams,
2260 VARIANT* pVarResult,
2261 EXCEPINFO* pExcepInfo,
2262 UINT* puArgErr)
2264 switch (dispIdMember)
2266 case DISPID_INSTALLER_CREATERECORD:
2267 return InstallerImpl_CreateRecord(wFlags, pDispParams,
2268 pVarResult, pExcepInfo, puArgErr);
2270 case DISPID_INSTALLER_OPENPACKAGE:
2271 return InstallerImpl_OpenPackage(This, wFlags, pDispParams,
2272 pVarResult, pExcepInfo, puArgErr);
2274 case DISPID_INSTALLER_OPENPRODUCT:
2275 return InstallerImpl_OpenProduct(wFlags, pDispParams,
2276 pVarResult, pExcepInfo, puArgErr);
2278 case DISPID_INSTALLER_OPENDATABASE:
2279 return InstallerImpl_OpenDatabase(wFlags, pDispParams,
2280 pVarResult, pExcepInfo, puArgErr);
2282 case DISPID_INSTALLER_SUMMARYINFORMATION:
2283 return InstallerImpl_SummaryInformation(wFlags, pDispParams,
2284 pVarResult, pExcepInfo,
2285 puArgErr);
2287 case DISPID_INSTALLER_UILEVEL:
2288 return InstallerImpl_UILevel(wFlags, pDispParams,
2289 pVarResult, pExcepInfo, puArgErr);
2291 case DISPID_INSTALLER_ENABLELOG:
2292 return InstallerImpl_EnableLog(wFlags, pDispParams,
2293 pVarResult, pExcepInfo, puArgErr);
2295 case DISPID_INSTALLER_INSTALLPRODUCT:
2296 return InstallerImpl_InstallProduct(wFlags, pDispParams,
2297 pVarResult, pExcepInfo,
2298 puArgErr);
2300 case DISPID_INSTALLER_VERSION:
2301 return InstallerImpl_Version(wFlags, pVarResult,
2302 pExcepInfo, puArgErr);
2304 case DISPID_INSTALLER_LASTERRORRECORD:
2305 return InstallerImpl_LastErrorRecord(wFlags, pDispParams,
2306 pVarResult, pExcepInfo,
2307 puArgErr);
2309 case DISPID_INSTALLER_REGISTRYVALUE:
2310 return InstallerImpl_RegistryValue(wFlags, pDispParams,
2311 pVarResult, pExcepInfo,
2312 puArgErr);
2314 case DISPID_INSTALLER_ENVIRONMENT:
2315 return InstallerImpl_Environment(wFlags, pDispParams,
2316 pVarResult, pExcepInfo, puArgErr);
2318 case DISPID_INSTALLER_FILEATTRIBUTES:
2319 return InstallerImpl_FileAttributes(wFlags, pDispParams,
2320 pVarResult, pExcepInfo,
2321 puArgErr);
2323 case DISPID_INSTALLER_FILESIZE:
2324 return InstallerImpl_FileSize(wFlags, pDispParams,
2325 pVarResult, pExcepInfo, puArgErr);
2327 case DISPID_INSTALLER_FILEVERSION:
2328 return InstallerImpl_FileVersion(wFlags, pDispParams,
2329 pVarResult, pExcepInfo, puArgErr);
2331 case DISPID_INSTALLER_PRODUCTSTATE:
2332 return InstallerImpl_ProductState(wFlags, pDispParams,
2333 pVarResult, pExcepInfo, puArgErr);
2335 case DISPID_INSTALLER_PRODUCTINFO:
2336 return InstallerImpl_ProductInfo(wFlags, pDispParams,
2337 pVarResult, pExcepInfo, puArgErr);
2339 case DISPID_INSTALLER_PRODUCTS:
2340 return InstallerImpl_Products(wFlags, pDispParams,
2341 pVarResult, pExcepInfo, puArgErr);
2343 case DISPID_INSTALLER_RELATEDPRODUCTS:
2344 return InstallerImpl_RelatedProducts(wFlags, pDispParams,
2345 pVarResult, pExcepInfo,
2346 puArgErr);
2348 default:
2349 return DISP_E_MEMBERNOTFOUND;
2353 HRESULT create_msiserver(IUnknown *outer, void **ppObj)
2355 AutomationObject *installer;
2356 HRESULT hr;
2358 TRACE("(%p %p)\n", outer, ppObj);
2360 if (outer)
2361 return CLASS_E_NOAGGREGATION;
2363 installer = msi_alloc(sizeof(AutomationObject));
2364 if (!installer) return E_OUTOFMEMORY;
2366 hr = init_automation_object(installer, 0, &DIID_Installer, InstallerImpl_Invoke, NULL);
2367 if (hr != S_OK)
2369 msi_free(installer);
2370 return hr;
2373 *ppObj = &installer->IDispatch_iface;
2375 return hr;
2378 HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **disp)
2380 SessionObject *session;
2381 HRESULT hr;
2383 session = msi_alloc(sizeof(SessionObject));
2384 if (!session) return E_OUTOFMEMORY;
2386 hr = init_automation_object(&session->autoobj, msiHandle, &DIID_Session, SessionImpl_Invoke, NULL);
2387 if (hr != S_OK)
2389 msi_free(session);
2390 return hr;
2393 session->installer = installer;
2394 *disp = &session->autoobj.IDispatch_iface;
2396 return hr;
2399 static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
2401 AutomationObject *database;
2402 HRESULT hr;
2404 TRACE("(%d %p)\n", msiHandle, dispatch);
2406 database = msi_alloc(sizeof(AutomationObject));
2407 if (!database) return E_OUTOFMEMORY;
2409 hr = init_automation_object(database, msiHandle, &DIID_Database, DatabaseImpl_Invoke, NULL);
2410 if (hr != S_OK)
2412 msi_free(database);
2413 return hr;
2416 *dispatch = &database->IDispatch_iface;
2418 return hr;
2421 static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch)
2423 AutomationObject *view;
2424 HRESULT hr;
2426 TRACE("(%d %p)\n", msiHandle, dispatch);
2428 view = msi_alloc(sizeof(AutomationObject));
2429 if (!view) return E_OUTOFMEMORY;
2431 hr = init_automation_object(view, msiHandle, &DIID_View, ViewImpl_Invoke, NULL);
2432 if (hr != S_OK)
2434 msi_free(view);
2435 return hr;
2438 *dispatch = &view->IDispatch_iface;
2440 return hr;
2443 static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp)
2445 AutomationObject *info;
2446 HRESULT hr;
2448 info = msi_alloc(sizeof(*info));
2449 if (!info) return E_OUTOFMEMORY;
2451 hr = init_automation_object(info, msiHandle, &DIID_SummaryInfo, SummaryInfoImpl_Invoke, NULL);
2452 if (hr != S_OK)
2454 msi_free(info);
2455 return hr;
2458 *disp = &info->IDispatch_iface;
2460 return hr;