dmusic: Display new ref in trace for AddRef and Release for IDirectMusicInstrument.
[wine/multimedia.git] / dlls / msi / automation.c
blob918572a9d36b0bdbe980950f51614d26e9cc6df8
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)
613 IUnknown_Release(*ppEnum);
614 return hr;
617 return S_OK;
620 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
622 ListEnumerator_QueryInterface,
623 ListEnumerator_AddRef,
624 ListEnumerator_Release,
625 ListEnumerator_Next,
626 ListEnumerator_Skip,
627 ListEnumerator_Reset,
628 ListEnumerator_Clone
631 /* Create a list enumerator, placing the result in the pointer ppObj. */
632 static HRESULT create_list_enumerator(ListObject *list, void **ppObj)
634 ListEnumerator *object;
636 TRACE("(%p, %p)\n", list, ppObj);
638 object = msi_alloc(sizeof(ListEnumerator));
640 /* Set all the VTable references */
641 object->IEnumVARIANT_iface.lpVtbl = &ListEnumerator_Vtbl;
642 object->ref = 1;
644 /* Store data that was passed */
645 object->pos = 0;
646 object->list = list;
647 if (list) IDispatch_AddRef(&list->autoobj.IDispatch_iface);
649 *ppObj = object;
650 return S_OK;
654 * Individual Object Invocation Functions
657 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
658 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
659 using DispGetParam/VariantChangeType. */
660 static HRESULT DispGetParam_CopyOnly(
661 DISPPARAMS *pdispparams, /* [in] Parameter list */
662 UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
663 VARIANT *pvarResult) /* [out] Destination for resulting variant */
665 /* position is counted backwards */
666 UINT pos;
668 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
669 *position, pdispparams->cArgs, pdispparams->cNamedArgs);
670 if (*position < pdispparams->cArgs) {
671 /* positional arg? */
672 pos = pdispparams->cArgs - *position - 1;
673 } else {
674 /* FIXME: is this how to handle named args? */
675 for (pos=0; pos<pdispparams->cNamedArgs; pos++)
676 if (pdispparams->rgdispidNamedArgs[pos] == *position) break;
678 if (pos==pdispparams->cNamedArgs)
679 return DISP_E_PARAMNOTFOUND;
681 *position = pos;
682 return VariantCopyInd(pvarResult,
683 &pdispparams->rgvarg[pos]);
686 static HRESULT SummaryInfoImpl_Invoke(
687 AutomationObject* This,
688 DISPID dispIdMember,
689 REFIID riid,
690 LCID lcid,
691 WORD wFlags,
692 DISPPARAMS* pDispParams,
693 VARIANT* pVarResult,
694 EXCEPINFO* pExcepInfo,
695 UINT* puArgErr)
697 UINT ret;
698 VARIANTARG varg0, varg1;
699 FILETIME ft, ftlocal;
700 SYSTEMTIME st;
701 HRESULT hr;
703 VariantInit(&varg0);
704 VariantInit(&varg1);
706 switch (dispIdMember)
708 case DISPID_SUMMARYINFO_PROPERTY:
709 if (wFlags & DISPATCH_PROPERTYGET)
711 UINT type;
712 INT value;
713 DWORD size = 0;
714 DATE date;
715 LPWSTR str;
717 static WCHAR szEmpty[] = {0};
719 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
720 if (FAILED(hr)) return hr;
721 ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, &value,
722 &ft, szEmpty, &size);
723 if (ret != ERROR_SUCCESS &&
724 ret != ERROR_MORE_DATA)
726 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
727 return DISP_E_EXCEPTION;
730 switch (type)
732 case VT_EMPTY:
733 break;
735 case VT_I2:
736 case VT_I4:
737 V_VT(pVarResult) = VT_I4;
738 V_I4(pVarResult) = value;
739 break;
741 case VT_LPSTR:
742 if (!(str = msi_alloc(++size * sizeof(WCHAR))))
743 ERR("Out of memory\n");
744 else if ((ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, NULL,
745 NULL, str, &size)) != ERROR_SUCCESS)
746 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
747 else
749 V_VT(pVarResult) = VT_BSTR;
750 V_BSTR(pVarResult) = SysAllocString(str);
752 msi_free(str);
753 break;
755 case VT_FILETIME:
756 FileTimeToLocalFileTime(&ft, &ftlocal);
757 FileTimeToSystemTime(&ftlocal, &st);
758 SystemTimeToVariantTime(&st, &date);
760 V_VT(pVarResult) = VT_DATE;
761 V_DATE(pVarResult) = date;
762 break;
764 default:
765 ERR("Unhandled variant type %d\n", type);
768 else if (wFlags & DISPATCH_PROPERTYPUT)
770 UINT posValue = DISPID_PROPERTYPUT;
772 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
773 if (FAILED(hr)) return hr;
774 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg1);
775 if (FAILED(hr))
777 *puArgErr = posValue;
778 return hr;
781 switch (V_VT(&varg1))
783 case VT_I2:
784 case VT_I4:
785 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), V_VT(&varg1), V_I4(&varg1), NULL, NULL);
786 break;
788 case VT_DATE:
789 VariantTimeToSystemTime(V_DATE(&varg1), &st);
790 SystemTimeToFileTime(&st, &ftlocal);
791 LocalFileTimeToFileTime(&ftlocal, &ft);
792 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_FILETIME, 0, &ft, NULL);
793 break;
795 case VT_BSTR:
796 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_LPSTR, 0, NULL, V_BSTR(&varg1));
797 break;
799 default:
800 FIXME("Unhandled variant type %d\n", V_VT(&varg1));
801 VariantClear(&varg1);
802 return DISP_E_EXCEPTION;
805 if (ret != ERROR_SUCCESS)
807 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret);
808 return DISP_E_EXCEPTION;
811 else return DISP_E_MEMBERNOTFOUND;
812 break;
814 case DISPID_SUMMARYINFO_PROPERTYCOUNT:
815 if (wFlags & DISPATCH_PROPERTYGET) {
816 UINT count;
817 if ((ret = MsiSummaryInfoGetPropertyCount(This->msiHandle, &count)) != ERROR_SUCCESS)
818 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret);
819 else
821 V_VT(pVarResult) = VT_I4;
822 V_I4(pVarResult) = count;
825 else return DISP_E_MEMBERNOTFOUND;
826 break;
828 default:
829 return DISP_E_MEMBERNOTFOUND;
832 VariantClear(&varg1);
833 VariantClear(&varg0);
835 return S_OK;
838 static HRESULT RecordImpl_Invoke(
839 AutomationObject* This,
840 DISPID dispIdMember,
841 REFIID riid,
842 LCID lcid,
843 WORD wFlags,
844 DISPPARAMS* pDispParams,
845 VARIANT* pVarResult,
846 EXCEPINFO* pExcepInfo,
847 UINT* puArgErr)
849 WCHAR *szString;
850 DWORD dwLen;
851 UINT ret;
852 VARIANTARG varg0, varg1;
853 HRESULT hr;
855 VariantInit(&varg0);
856 VariantInit(&varg1);
858 switch (dispIdMember)
860 case DISPID_RECORD_FIELDCOUNT:
861 if (wFlags & DISPATCH_PROPERTYGET) {
862 V_VT(pVarResult) = VT_I4;
863 V_I4(pVarResult) = MsiRecordGetFieldCount(This->msiHandle);
865 else return DISP_E_MEMBERNOTFOUND;
866 break;
868 case DISPID_RECORD_STRINGDATA:
869 if (wFlags & DISPATCH_PROPERTYGET) {
870 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
871 if (FAILED(hr)) return hr;
872 V_VT(pVarResult) = VT_BSTR;
873 V_BSTR(pVarResult) = NULL;
874 if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
876 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
877 ERR("Out of memory\n");
878 else if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
879 V_BSTR(pVarResult) = SysAllocString(szString);
880 msi_free(szString);
882 if (ret != ERROR_SUCCESS)
883 ERR("MsiRecordGetString returned %d\n", ret);
884 } else if (wFlags & DISPATCH_PROPERTYPUT) {
885 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
886 if (FAILED(hr)) return hr;
887 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
888 if (FAILED(hr)) return hr;
889 if ((ret = MsiRecordSetStringW(This->msiHandle, V_I4(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
891 VariantClear(&varg1);
892 ERR("MsiRecordSetString returned %d\n", ret);
893 return DISP_E_EXCEPTION;
896 else return DISP_E_MEMBERNOTFOUND;
897 break;
899 case DISPID_RECORD_INTEGERDATA:
900 if (wFlags & DISPATCH_PROPERTYGET) {
901 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
902 if (FAILED(hr)) return hr;
903 V_VT(pVarResult) = VT_I4;
904 V_I4(pVarResult) = MsiRecordGetInteger(This->msiHandle, V_I4(&varg0));
905 } else if (wFlags & DISPATCH_PROPERTYPUT) {
906 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
907 if (FAILED(hr)) return hr;
908 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
909 if (FAILED(hr)) return hr;
910 if ((ret = MsiRecordSetInteger(This->msiHandle, V_I4(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
912 ERR("MsiRecordSetInteger returned %d\n", ret);
913 return DISP_E_EXCEPTION;
916 else return DISP_E_MEMBERNOTFOUND;
917 break;
919 default:
920 return DISP_E_MEMBERNOTFOUND;
923 VariantClear(&varg1);
924 VariantClear(&varg0);
926 return S_OK;
929 static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
931 AutomationObject *record;
932 HRESULT hr;
934 record = msi_alloc(sizeof(*record));
935 if (!record) return E_OUTOFMEMORY;
937 hr = init_automation_object(record, msiHandle, &DIID_Record, RecordImpl_Invoke, NULL);
938 if (hr != S_OK)
940 msi_free(record);
941 return hr;
944 *disp = &record->IDispatch_iface;
946 return hr;
949 static HRESULT ListImpl_Invoke(
950 AutomationObject* This,
951 DISPID dispIdMember,
952 REFIID riid,
953 LCID lcid,
954 WORD wFlags,
955 DISPPARAMS* pDispParams,
956 VARIANT* pVarResult,
957 EXCEPINFO* pExcepInfo,
958 UINT* puArgErr)
960 ListObject *list = (ListObject*)This;
961 IUnknown *pUnk = NULL;
962 HRESULT hr;
964 switch (dispIdMember)
966 case DISPID_LIST__NEWENUM:
967 if (wFlags & DISPATCH_METHOD) {
968 V_VT(pVarResult) = VT_UNKNOWN;
969 if (SUCCEEDED(hr = create_list_enumerator(list, (LPVOID *)&pUnk)))
970 V_UNKNOWN(pVarResult) = pUnk;
971 else
972 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr);
974 else return DISP_E_MEMBERNOTFOUND;
975 break;
977 case DISPID_LIST_ITEM:
978 if (wFlags & DISPATCH_PROPERTYGET) {
979 VARIANTARG index;
981 VariantInit(&index);
982 hr = DispGetParam(pDispParams, 0, VT_I4, &index, puArgErr);
983 if (FAILED(hr)) return hr;
984 if (V_I4(&index) < 0 || V_I4(&index) >= list->count)
985 return DISP_E_BADINDEX;
986 VariantCopy(pVarResult, &list->data[V_I4(&index)]);
988 else return DISP_E_MEMBERNOTFOUND;
989 break;
991 case DISPID_LIST_COUNT:
992 if (wFlags & DISPATCH_PROPERTYGET) {
993 V_VT(pVarResult) = VT_I4;
994 V_I4(pVarResult) = list->count;
996 else return DISP_E_MEMBERNOTFOUND;
997 break;
999 default:
1000 return DISP_E_MEMBERNOTFOUND;
1003 return S_OK;
1006 static void ListImpl_Free(AutomationObject *This)
1008 ListObject *list = (ListObject*)This;
1009 int i;
1011 for (i = 0; i < list->count; i++)
1012 VariantClear(&list->data[i]);
1013 msi_free(list->data);
1016 static HRESULT get_products_count(const WCHAR *product, int *len)
1018 int i = 0;
1020 while (1)
1022 WCHAR dataW[GUID_SIZE];
1023 UINT ret;
1025 /* all or related only */
1026 if (product)
1027 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1028 else
1029 ret = MsiEnumProductsW(i, dataW);
1031 if (ret == ERROR_NO_MORE_ITEMS) break;
1033 if (ret != ERROR_SUCCESS)
1034 return DISP_E_EXCEPTION;
1036 i++;
1039 *len = i;
1041 return S_OK;
1044 static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
1046 ListObject *list;
1047 HRESULT hr;
1048 int i;
1050 list = msi_alloc_zero(sizeof(ListObject));
1051 if (!list) return E_OUTOFMEMORY;
1053 hr = init_automation_object(&list->autoobj, 0, &DIID_StringList, ListImpl_Invoke, ListImpl_Free);
1054 if (hr != S_OK)
1056 msi_free(list);
1057 return hr;
1060 *dispatch = &list->autoobj.IDispatch_iface;
1062 hr = get_products_count(product, &list->count);
1063 if (hr != S_OK)
1065 IDispatch_Release(*dispatch);
1066 return hr;
1069 list->data = msi_alloc(list->count*sizeof(VARIANT));
1070 if (!list->data)
1072 IDispatch_Release(*dispatch);
1073 return E_OUTOFMEMORY;
1076 for (i = 0; i < list->count; i++)
1078 WCHAR dataW[GUID_SIZE];
1079 UINT ret;
1081 /* all or related only */
1082 if (product)
1083 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1084 else
1085 ret = MsiEnumProductsW(i, dataW);
1087 if (ret == ERROR_NO_MORE_ITEMS) break;
1089 V_VT(&list->data[i]) = VT_BSTR;
1090 V_BSTR(&list->data[i]) = SysAllocString(dataW);
1093 return S_OK;
1096 static HRESULT ViewImpl_Invoke(
1097 AutomationObject* This,
1098 DISPID dispIdMember,
1099 REFIID riid,
1100 LCID lcid,
1101 WORD wFlags,
1102 DISPPARAMS* pDispParams,
1103 VARIANT* pVarResult,
1104 EXCEPINFO* pExcepInfo,
1105 UINT* puArgErr)
1107 MSIHANDLE msiHandle;
1108 UINT ret;
1109 VARIANTARG varg0, varg1;
1110 HRESULT hr;
1112 VariantInit(&varg0);
1113 VariantInit(&varg1);
1115 switch (dispIdMember)
1117 case DISPID_VIEW_EXECUTE:
1118 if (wFlags & DISPATCH_METHOD)
1120 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &varg0, puArgErr);
1121 if (SUCCEEDED(hr) && V_DISPATCH(&varg0) != NULL)
1122 MsiViewExecute(This->msiHandle, ((AutomationObject *)V_DISPATCH(&varg0))->msiHandle);
1123 else
1124 MsiViewExecute(This->msiHandle, 0);
1126 else return DISP_E_MEMBERNOTFOUND;
1127 break;
1129 case DISPID_VIEW_FETCH:
1130 if (wFlags & DISPATCH_METHOD)
1132 V_VT(pVarResult) = VT_DISPATCH;
1133 if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS)
1135 IDispatch *dispatch = NULL;
1137 if (SUCCEEDED(hr = create_record(msiHandle, &dispatch)))
1138 V_DISPATCH(pVarResult) = dispatch;
1139 else
1140 ERR("Failed to create Record object, hresult 0x%08x\n", hr);
1142 else if (ret == ERROR_NO_MORE_ITEMS)
1143 V_DISPATCH(pVarResult) = NULL;
1144 else
1146 ERR("MsiViewFetch returned %d\n", ret);
1147 return DISP_E_EXCEPTION;
1150 else return DISP_E_MEMBERNOTFOUND;
1151 break;
1153 case DISPID_VIEW_MODIFY:
1154 if (wFlags & DISPATCH_METHOD)
1156 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1157 if (FAILED(hr)) return hr;
1158 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1159 if (FAILED(hr)) return hr;
1160 if (!V_DISPATCH(&varg1)) return DISP_E_EXCEPTION;
1161 if ((ret = MsiViewModify(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle)) != ERROR_SUCCESS)
1163 VariantClear(&varg1);
1164 ERR("MsiViewModify returned %d\n", ret);
1165 return DISP_E_EXCEPTION;
1168 else return DISP_E_MEMBERNOTFOUND;
1169 break;
1171 case DISPID_VIEW_CLOSE:
1172 if (wFlags & DISPATCH_METHOD)
1174 MsiViewClose(This->msiHandle);
1176 else return DISP_E_MEMBERNOTFOUND;
1177 break;
1179 default:
1180 return DISP_E_MEMBERNOTFOUND;
1183 VariantClear(&varg1);
1184 VariantClear(&varg0);
1186 return S_OK;
1189 static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
1190 DISPPARAMS* pDispParams,
1191 VARIANT* pVarResult,
1192 EXCEPINFO* pExcepInfo,
1193 UINT* puArgErr)
1195 if (!(wFlags & DISPATCH_METHOD))
1196 return DISP_E_MEMBERNOTFOUND;
1198 FIXME("\n");
1200 VariantInit(pVarResult);
1201 return S_OK;
1204 static HRESULT DatabaseImpl_Invoke(
1205 AutomationObject* This,
1206 DISPID dispIdMember,
1207 REFIID riid,
1208 LCID lcid,
1209 WORD wFlags,
1210 DISPPARAMS* pDispParams,
1211 VARIANT* pVarResult,
1212 EXCEPINFO* pExcepInfo,
1213 UINT* puArgErr)
1215 IDispatch *dispatch = NULL;
1216 MSIHANDLE msiHandle;
1217 UINT ret;
1218 VARIANTARG varg0, varg1;
1219 HRESULT hr;
1221 VariantInit(&varg0);
1222 VariantInit(&varg1);
1224 switch (dispIdMember)
1226 case DISPID_DATABASE_SUMMARYINFORMATION:
1227 if (wFlags & DISPATCH_PROPERTYGET)
1229 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1230 if (FAILED(hr))
1231 V_I4(&varg0) = 0;
1233 V_VT(pVarResult) = VT_DISPATCH;
1234 if ((ret = MsiGetSummaryInformationW(This->msiHandle, NULL, V_I4(&varg0), &msiHandle)) == ERROR_SUCCESS)
1236 hr = create_summaryinfo(msiHandle, &dispatch);
1237 if (SUCCEEDED(hr))
1238 V_DISPATCH(pVarResult) = dispatch;
1239 else
1240 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr);
1242 else
1244 ERR("MsiGetSummaryInformation returned %d\n", ret);
1245 return DISP_E_EXCEPTION;
1248 else return DISP_E_MEMBERNOTFOUND;
1249 break;
1251 case DISPID_DATABASE_OPENVIEW:
1252 if (wFlags & DISPATCH_METHOD)
1254 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1255 if (FAILED(hr)) return hr;
1256 V_VT(pVarResult) = VT_DISPATCH;
1257 if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS)
1259 if (SUCCEEDED(hr = create_view(msiHandle, &dispatch)))
1260 V_DISPATCH(pVarResult) = dispatch;
1261 else
1262 ERR("Failed to create View object, hresult 0x%08x\n", hr);
1264 else
1266 VariantClear(&varg0);
1267 ERR("MsiDatabaseOpenView returned %d\n", ret);
1268 return DISP_E_EXCEPTION;
1271 else return DISP_E_MEMBERNOTFOUND;
1272 break;
1274 case DISPID_INSTALLER_LASTERRORRECORD:
1275 return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
1276 pVarResult, pExcepInfo,
1277 puArgErr);
1279 default:
1280 return DISP_E_MEMBERNOTFOUND;
1283 VariantClear(&varg1);
1284 VariantClear(&varg0);
1286 return S_OK;
1289 static HRESULT SessionImpl_Invoke(
1290 AutomationObject* This,
1291 DISPID dispIdMember,
1292 REFIID riid,
1293 LCID lcid,
1294 WORD wFlags,
1295 DISPPARAMS* pDispParams,
1296 VARIANT* pVarResult,
1297 EXCEPINFO* pExcepInfo,
1298 UINT* puArgErr)
1300 SessionObject *session = (SessionObject*)This;
1301 WCHAR *szString;
1302 DWORD dwLen;
1303 MSIHANDLE msiHandle;
1304 LANGID langId;
1305 UINT ret;
1306 INSTALLSTATE iInstalled, iAction;
1307 VARIANTARG varg0, varg1;
1308 HRESULT hr;
1310 VariantInit(&varg0);
1311 VariantInit(&varg1);
1313 switch (dispIdMember)
1315 case DISPID_SESSION_INSTALLER:
1316 if (wFlags & DISPATCH_PROPERTYGET) {
1317 V_VT(pVarResult) = VT_DISPATCH;
1318 IDispatch_AddRef(session->installer);
1319 V_DISPATCH(pVarResult) = session->installer;
1321 else return DISP_E_MEMBERNOTFOUND;
1322 break;
1324 case DISPID_SESSION_PROPERTY:
1325 if (wFlags & DISPATCH_PROPERTYGET) {
1326 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1327 if (FAILED(hr)) return hr;
1328 V_VT(pVarResult) = VT_BSTR;
1329 V_BSTR(pVarResult) = NULL;
1330 if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
1332 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
1333 ERR("Out of memory\n");
1334 else if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
1335 V_BSTR(pVarResult) = SysAllocString(szString);
1336 msi_free(szString);
1338 if (ret != ERROR_SUCCESS)
1339 ERR("MsiGetProperty returned %d\n", ret);
1340 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1341 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1342 if (FAILED(hr)) return hr;
1343 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1344 if (FAILED(hr)) {
1345 VariantClear(&varg0);
1346 return hr;
1348 if ((ret = MsiSetPropertyW(This->msiHandle, V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
1350 VariantClear(&varg0);
1351 VariantClear(&varg1);
1352 ERR("MsiSetProperty returned %d\n", ret);
1353 return DISP_E_EXCEPTION;
1356 else return DISP_E_MEMBERNOTFOUND;
1357 break;
1359 case DISPID_SESSION_LANGUAGE:
1360 if (wFlags & DISPATCH_PROPERTYGET) {
1361 langId = MsiGetLanguage(This->msiHandle);
1362 V_VT(pVarResult) = VT_I4;
1363 V_I4(pVarResult) = langId;
1365 else return DISP_E_MEMBERNOTFOUND;
1366 break;
1368 case DISPID_SESSION_MODE:
1369 if (wFlags & DISPATCH_PROPERTYGET) {
1370 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1371 if (FAILED(hr)) return hr;
1372 V_VT(pVarResult) = VT_BOOL;
1373 V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0));
1374 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1375 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1376 if (FAILED(hr)) return hr;
1377 hr = DispGetParam(pDispParams, 1, VT_BOOL, &varg1, puArgErr);
1378 if (FAILED(hr)) return hr;
1379 if ((ret = MsiSetMode(This->msiHandle, V_I4(&varg0), V_BOOL(&varg1))) != ERROR_SUCCESS)
1381 ERR("MsiSetMode returned %d\n", ret);
1382 return DISP_E_EXCEPTION;
1385 else return DISP_E_MEMBERNOTFOUND;
1386 break;
1388 case DISPID_SESSION_DATABASE:
1389 if (wFlags & DISPATCH_PROPERTYGET) {
1390 V_VT(pVarResult) = VT_DISPATCH;
1391 if ((msiHandle = MsiGetActiveDatabase(This->msiHandle)))
1393 IDispatch *dispatch;
1395 if (SUCCEEDED(hr = create_database(msiHandle, &dispatch)))
1396 V_DISPATCH(pVarResult) = dispatch;
1397 else
1398 ERR("Failed to create Database object, hresult 0x%08x\n", hr);
1400 else
1402 ERR("MsiGetActiveDatabase failed\n");
1403 return DISP_E_EXCEPTION;
1406 else return DISP_E_MEMBERNOTFOUND;
1407 break;
1409 case DISPID_SESSION_DOACTION:
1410 if (wFlags & DISPATCH_METHOD) {
1411 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1412 if (FAILED(hr)) return hr;
1413 ret = MsiDoActionW(This->msiHandle, V_BSTR(&varg0));
1414 V_VT(pVarResult) = VT_I4;
1415 switch (ret)
1417 case ERROR_FUNCTION_NOT_CALLED:
1418 V_I4(pVarResult) = msiDoActionStatusNoAction;
1419 break;
1420 case ERROR_SUCCESS:
1421 V_I4(pVarResult) = msiDoActionStatusSuccess;
1422 break;
1423 case ERROR_INSTALL_USEREXIT:
1424 V_I4(pVarResult) = msiDoActionStatusUserExit;
1425 break;
1426 case ERROR_INSTALL_FAILURE:
1427 V_I4(pVarResult) = msiDoActionStatusFailure;
1428 break;
1429 case ERROR_INSTALL_SUSPEND:
1430 V_I4(pVarResult) = msiDoActionStatusSuspend;
1431 break;
1432 case ERROR_MORE_DATA:
1433 V_I4(pVarResult) = msiDoActionStatusFinished;
1434 break;
1435 case ERROR_INVALID_HANDLE_STATE:
1436 V_I4(pVarResult) = msiDoActionStatusWrongState;
1437 break;
1438 case ERROR_INVALID_DATA:
1439 V_I4(pVarResult) = msiDoActionStatusBadActionData;
1440 break;
1441 default:
1442 VariantClear(&varg0);
1443 FIXME("MsiDoAction returned unhandled value %d\n", ret);
1444 return DISP_E_EXCEPTION;
1447 else return DISP_E_MEMBERNOTFOUND;
1448 break;
1450 case DISPID_SESSION_EVALUATECONDITION:
1451 if (wFlags & DISPATCH_METHOD) {
1452 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1453 if (FAILED(hr)) return hr;
1454 V_VT(pVarResult) = VT_I4;
1455 V_I4(pVarResult) = MsiEvaluateConditionW(This->msiHandle, V_BSTR(&varg0));
1457 else return DISP_E_MEMBERNOTFOUND;
1458 break;
1460 case DISPID_SESSION_MESSAGE:
1461 if(!(wFlags & DISPATCH_METHOD))
1462 return DISP_E_MEMBERNOTFOUND;
1464 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1465 if (FAILED(hr)) return hr;
1466 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1467 if (FAILED(hr)) return hr;
1469 V_VT(pVarResult) = VT_I4;
1470 V_I4(pVarResult) =
1471 MsiProcessMessage(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle);
1472 break;
1474 case DISPID_SESSION_SETINSTALLLEVEL:
1475 if (wFlags & DISPATCH_METHOD) {
1476 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1477 if (FAILED(hr)) return hr;
1478 if ((ret = MsiSetInstallLevel(This->msiHandle, V_I4(&varg0))) != ERROR_SUCCESS)
1480 ERR("MsiSetInstallLevel returned %d\n", ret);
1481 return DISP_E_EXCEPTION;
1484 else return DISP_E_MEMBERNOTFOUND;
1485 break;
1487 case DISPID_SESSION_FEATURECURRENTSTATE:
1488 if (wFlags & DISPATCH_PROPERTYGET) {
1489 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1490 if (FAILED(hr)) return hr;
1491 V_VT(pVarResult) = VT_I4;
1492 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1493 V_I4(pVarResult) = iInstalled;
1494 else
1496 ERR("MsiGetFeatureState returned %d\n", ret);
1497 V_I4(pVarResult) = msiInstallStateUnknown;
1500 else return DISP_E_MEMBERNOTFOUND;
1501 break;
1503 case DISPID_SESSION_FEATUREREQUESTSTATE:
1504 if (wFlags & DISPATCH_PROPERTYGET) {
1505 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1506 if (FAILED(hr)) return hr;
1507 V_VT(pVarResult) = VT_I4;
1508 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1509 V_I4(pVarResult) = iAction;
1510 else
1512 ERR("MsiGetFeatureState returned %d\n", ret);
1513 V_I4(pVarResult) = msiInstallStateUnknown;
1515 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1516 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1517 if (FAILED(hr)) return hr;
1518 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1519 if (FAILED(hr)) {
1520 VariantClear(&varg0);
1521 return hr;
1523 if ((ret = MsiSetFeatureStateW(This->msiHandle, V_BSTR(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
1525 VariantClear(&varg0);
1526 ERR("MsiSetFeatureState returned %d\n", ret);
1527 return DISP_E_EXCEPTION;
1530 else return DISP_E_MEMBERNOTFOUND;
1531 break;
1533 default:
1534 return DISP_E_MEMBERNOTFOUND;
1537 VariantClear(&varg1);
1538 VariantClear(&varg0);
1540 return S_OK;
1543 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1544 * registry value type. Used by Installer::RegistryValue. */
1545 static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize)
1547 static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1548 static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 };
1549 WCHAR *szString = (WCHAR *)lpData;
1550 LPWSTR szNewString = NULL;
1551 DWORD dwNewSize = 0;
1552 int idx;
1554 switch (dwType)
1556 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1557 case REG_MULTI_SZ: /* Multi SZ change internal null characters to newlines */
1558 idx = (dwSize/sizeof(WCHAR))-1;
1559 while (idx >= 0 && !szString[idx]) idx--;
1560 for (; idx >= 0; idx--)
1561 if (!szString[idx]) szString[idx] = '\n';
1562 /* fall through */
1563 case REG_SZ:
1564 V_VT(pVarResult) = VT_BSTR;
1565 V_BSTR(pVarResult) = SysAllocStringByteLen((LPCSTR)szString, dwSize);
1566 break;
1568 case REG_EXPAND_SZ:
1569 if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1570 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1571 else if (!(szNewString = msi_alloc(dwNewSize * sizeof(WCHAR))))
1572 ERR("Out of memory\n");
1573 else if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1574 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1575 else
1577 V_VT(pVarResult) = VT_BSTR;
1578 V_BSTR(pVarResult) = SysAllocStringLen(szNewString, dwNewSize);
1580 msi_free(szNewString);
1581 break;
1583 case REG_DWORD:
1584 V_VT(pVarResult) = VT_I4;
1585 V_I4(pVarResult) = *((DWORD *)lpData);
1586 break;
1588 case REG_QWORD:
1589 V_VT(pVarResult) = VT_BSTR;
1590 V_BSTR(pVarResult) = SysAllocString(szREG_); /* Weird string, don't know why native returns it */
1591 break;
1593 case REG_BINARY:
1594 V_VT(pVarResult) = VT_BSTR;
1595 V_BSTR(pVarResult) = SysAllocString(szREG_BINARY);
1596 break;
1598 case REG_NONE:
1599 V_VT(pVarResult) = VT_EMPTY;
1600 break;
1602 default:
1603 FIXME("Unhandled registry value type %d\n", dwType);
1607 static HRESULT InstallerImpl_CreateRecord(WORD wFlags,
1608 DISPPARAMS* pDispParams,
1609 VARIANT* pVarResult,
1610 EXCEPINFO* pExcepInfo,
1611 UINT* puArgErr)
1613 HRESULT hr;
1614 VARIANTARG varg0;
1615 MSIHANDLE hrec;
1616 IDispatch* dispatch;
1618 if (!(wFlags & DISPATCH_METHOD))
1619 return DISP_E_MEMBERNOTFOUND;
1621 VariantInit(&varg0);
1622 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1623 if (FAILED(hr))
1624 return hr;
1626 V_VT(pVarResult) = VT_DISPATCH;
1628 hrec = MsiCreateRecord(V_I4(&varg0));
1629 if (!hrec)
1630 return DISP_E_EXCEPTION;
1632 hr = create_record(hrec, &dispatch);
1633 if (SUCCEEDED(hr))
1634 V_DISPATCH(pVarResult) = dispatch;
1636 return hr;
1639 static HRESULT InstallerImpl_OpenPackage(AutomationObject* This,
1640 WORD wFlags,
1641 DISPPARAMS* pDispParams,
1642 VARIANT* pVarResult,
1643 EXCEPINFO* pExcepInfo,
1644 UINT* puArgErr)
1646 UINT ret;
1647 HRESULT hr;
1648 MSIHANDLE hpkg;
1649 IDispatch* dispatch;
1650 VARIANTARG varg0, varg1;
1652 if (!(wFlags & DISPATCH_METHOD))
1653 return DISP_E_MEMBERNOTFOUND;
1655 if (pDispParams->cArgs == 0)
1656 return DISP_E_TYPEMISMATCH;
1658 if (V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1]) != VT_BSTR)
1659 return DISP_E_TYPEMISMATCH;
1661 VariantInit(&varg0);
1662 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1663 if (FAILED(hr))
1664 return hr;
1666 VariantInit(&varg1);
1667 if (pDispParams->cArgs == 2)
1669 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1670 if (FAILED(hr))
1671 goto done;
1673 else
1675 V_VT(&varg1) = VT_I4;
1676 V_I4(&varg1) = 0;
1679 V_VT(pVarResult) = VT_DISPATCH;
1681 ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &hpkg);
1682 if (ret != ERROR_SUCCESS)
1684 hr = DISP_E_EXCEPTION;
1685 goto done;
1688 hr = create_session(hpkg, &This->IDispatch_iface, &dispatch);
1689 if (SUCCEEDED(hr))
1690 V_DISPATCH(pVarResult) = dispatch;
1692 done:
1693 VariantClear(&varg0);
1694 VariantClear(&varg1);
1695 return hr;
1698 static HRESULT InstallerImpl_OpenProduct(WORD wFlags,
1699 DISPPARAMS* pDispParams,
1700 VARIANT* pVarResult,
1701 EXCEPINFO* pExcepInfo,
1702 UINT* puArgErr)
1704 HRESULT hr;
1705 VARIANTARG varg0;
1707 if (!(wFlags & DISPATCH_METHOD))
1708 return DISP_E_MEMBERNOTFOUND;
1710 VariantInit(&varg0);
1711 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1712 if (FAILED(hr))
1713 return hr;
1715 FIXME("%s\n", debugstr_w(V_BSTR(&varg0)));
1717 VariantInit(pVarResult);
1719 VariantClear(&varg0);
1720 return S_OK;
1723 static HRESULT InstallerImpl_OpenDatabase(WORD wFlags,
1724 DISPPARAMS* pDispParams,
1725 VARIANT* pVarResult,
1726 EXCEPINFO* pExcepInfo,
1727 UINT* puArgErr)
1729 UINT ret;
1730 HRESULT hr;
1731 MSIHANDLE hdb;
1732 IDispatch* dispatch;
1733 VARIANTARG varg0, varg1;
1735 if (!(wFlags & DISPATCH_METHOD))
1736 return DISP_E_MEMBERNOTFOUND;
1738 VariantInit(&varg0);
1739 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1740 if (FAILED(hr))
1741 return hr;
1743 VariantInit(&varg1);
1744 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1745 if (FAILED(hr))
1746 goto done;
1748 V_VT(pVarResult) = VT_DISPATCH;
1750 ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &hdb);
1751 if (ret != ERROR_SUCCESS)
1753 hr = DISP_E_EXCEPTION;
1754 goto done;
1757 hr = create_database(hdb, &dispatch);
1758 if (SUCCEEDED(hr))
1759 V_DISPATCH(pVarResult) = dispatch;
1761 done:
1762 VariantClear(&varg0);
1763 VariantClear(&varg1);
1764 return hr;
1767 static HRESULT InstallerImpl_SummaryInformation(WORD wFlags,
1768 DISPPARAMS* pDispParams,
1769 VARIANT* pVarResult,
1770 EXCEPINFO* pExcepInfo,
1771 UINT* puArgErr)
1773 if (!(wFlags & DISPATCH_METHOD))
1774 return DISP_E_MEMBERNOTFOUND;
1776 FIXME("\n");
1778 VariantInit(pVarResult);
1779 return S_OK;
1782 static HRESULT InstallerImpl_UILevel(WORD wFlags,
1783 DISPPARAMS* pDispParams,
1784 VARIANT* pVarResult,
1785 EXCEPINFO* pExcepInfo,
1786 UINT* puArgErr)
1788 HRESULT hr;
1789 VARIANTARG varg0;
1790 INSTALLUILEVEL ui;
1792 if (!(wFlags & DISPATCH_PROPERTYPUT) && !(wFlags & DISPATCH_PROPERTYGET))
1793 return DISP_E_MEMBERNOTFOUND;
1795 if (wFlags & DISPATCH_PROPERTYPUT)
1797 VariantInit(&varg0);
1798 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1799 if (FAILED(hr))
1800 return hr;
1802 ui = MsiSetInternalUI(V_I4(&varg0), NULL);
1803 if (ui == INSTALLUILEVEL_NOCHANGE)
1804 return DISP_E_EXCEPTION;
1806 else if (wFlags & DISPATCH_PROPERTYGET)
1808 ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
1809 if (ui == INSTALLUILEVEL_NOCHANGE)
1810 return DISP_E_EXCEPTION;
1812 V_VT(pVarResult) = VT_I4;
1813 V_I4(pVarResult) = ui;
1816 return S_OK;
1819 static HRESULT InstallerImpl_EnableLog(WORD wFlags,
1820 DISPPARAMS* pDispParams,
1821 VARIANT* pVarResult,
1822 EXCEPINFO* pExcepInfo,
1823 UINT* puArgErr)
1825 if (!(wFlags & DISPATCH_METHOD))
1826 return DISP_E_MEMBERNOTFOUND;
1828 FIXME("\n");
1830 VariantInit(pVarResult);
1831 return S_OK;
1834 static HRESULT InstallerImpl_InstallProduct(WORD wFlags,
1835 DISPPARAMS* pDispParams,
1836 VARIANT* pVarResult,
1837 EXCEPINFO* pExcepInfo,
1838 UINT* puArgErr)
1840 UINT ret;
1841 HRESULT hr;
1842 VARIANTARG varg0, varg1;
1844 if (!(wFlags & DISPATCH_METHOD))
1845 return DISP_E_MEMBERNOTFOUND;
1847 VariantInit(&varg0);
1848 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1849 if (FAILED(hr))
1850 return hr;
1852 VariantInit(&varg1);
1853 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1854 if (FAILED(hr))
1855 goto done;
1857 ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1));
1858 if (ret != ERROR_SUCCESS)
1860 hr = DISP_E_EXCEPTION;
1861 goto done;
1864 done:
1865 VariantClear(&varg0);
1866 VariantClear(&varg1);
1867 return hr;
1870 static HRESULT InstallerImpl_Version(WORD wFlags,
1871 VARIANT* pVarResult,
1872 EXCEPINFO* pExcepInfo,
1873 UINT* puArgErr)
1875 HRESULT hr;
1876 DLLVERSIONINFO verinfo;
1877 WCHAR version[MAX_PATH];
1879 static const WCHAR format[] = {
1880 '%','d','.','%','d','.','%','d','.','%','d',0};
1882 if (!(wFlags & DISPATCH_PROPERTYGET))
1883 return DISP_E_MEMBERNOTFOUND;
1885 verinfo.cbSize = sizeof(DLLVERSIONINFO);
1886 hr = DllGetVersion(&verinfo);
1887 if (FAILED(hr))
1888 return hr;
1890 sprintfW(version, format, verinfo.dwMajorVersion, verinfo.dwMinorVersion,
1891 verinfo.dwBuildNumber, verinfo.dwPlatformID);
1893 V_VT(pVarResult) = VT_BSTR;
1894 V_BSTR(pVarResult) = SysAllocString(version);
1895 return S_OK;
1898 static HRESULT InstallerImpl_LastErrorRecord(WORD wFlags,
1899 DISPPARAMS* pDispParams,
1900 VARIANT* pVarResult,
1901 EXCEPINFO* pExcepInfo,
1902 UINT* puArgErr)
1904 if (!(wFlags & DISPATCH_METHOD))
1905 return DISP_E_MEMBERNOTFOUND;
1907 FIXME("\n");
1909 VariantInit(pVarResult);
1910 return S_OK;
1913 static HRESULT InstallerImpl_RegistryValue(WORD wFlags,
1914 DISPPARAMS* pDispParams,
1915 VARIANT* pVarResult,
1916 EXCEPINFO* pExcepInfo,
1917 UINT* puArgErr)
1919 UINT ret;
1920 HKEY hkey = NULL;
1921 HRESULT hr;
1922 UINT posValue;
1923 DWORD type, size;
1924 LPWSTR szString = NULL;
1925 VARIANTARG varg0, varg1, varg2;
1927 if (!(wFlags & DISPATCH_METHOD))
1928 return DISP_E_MEMBERNOTFOUND;
1930 VariantInit(&varg0);
1931 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1932 if (FAILED(hr))
1933 return hr;
1935 VariantInit(&varg1);
1936 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1937 if (FAILED(hr))
1938 goto done;
1940 /* Save valuePos so we can save puArgErr if we are unable to do our type
1941 * conversions.
1943 posValue = 2;
1944 VariantInit(&varg2);
1945 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2);
1946 if (FAILED(hr))
1947 goto done;
1949 if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT &&
1950 V_I4(&varg0) <= REG_INDEX_DYN_DATA)
1952 V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT;
1955 ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey);
1957 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
1958 if (ret != ERROR_SUCCESS && V_VT(&varg2) != VT_EMPTY)
1960 hr = DISP_E_BADINDEX;
1961 goto done;
1964 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
1965 switch (V_VT(&varg2))
1967 /* Return VT_BOOL clarifying whether registry key exists or not. */
1968 case VT_EMPTY:
1969 V_VT(pVarResult) = VT_BOOL;
1970 V_BOOL(pVarResult) = (ret == ERROR_SUCCESS);
1971 break;
1973 /* Return the value of specified key if it exists. */
1974 case VT_BSTR:
1975 ret = RegQueryValueExW(hkey, V_BSTR(&varg2),
1976 NULL, NULL, NULL, &size);
1977 if (ret != ERROR_SUCCESS)
1979 hr = DISP_E_BADINDEX;
1980 goto done;
1983 szString = msi_alloc(size);
1984 if (!szString)
1986 hr = E_OUTOFMEMORY;
1987 goto done;
1990 ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL,
1991 &type, (LPBYTE)szString, &size);
1992 if (ret != ERROR_SUCCESS)
1994 msi_free(szString);
1995 hr = DISP_E_BADINDEX;
1996 goto done;
1999 variant_from_registry_value(pVarResult, type,
2000 (LPBYTE)szString, size);
2001 msi_free(szString);
2002 break;
2004 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2005 default:
2006 hr = VariantChangeType(&varg2, &varg2, 0, VT_I4);
2007 if (FAILED(hr))
2009 if (hr == DISP_E_TYPEMISMATCH)
2010 *puArgErr = posValue;
2012 goto done;
2015 /* Retrieve class name or maximum value name or subkey name size. */
2016 if (!V_I4(&varg2))
2017 ret = RegQueryInfoKeyW(hkey, NULL, &size, NULL, NULL, NULL,
2018 NULL, NULL, NULL, NULL, NULL, NULL);
2019 else if (V_I4(&varg2) > 0)
2020 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL,
2021 NULL, NULL, &size, NULL, NULL, NULL);
2022 else /* V_I4(&varg2) < 0 */
2023 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &size,
2024 NULL, NULL, NULL, NULL, NULL, NULL);
2026 if (ret != ERROR_SUCCESS)
2027 goto done;
2029 szString = msi_alloc(++size * sizeof(WCHAR));
2030 if (!szString)
2032 hr = E_OUTOFMEMORY;
2033 goto done;
2036 if (!V_I4(&varg2))
2037 ret = RegQueryInfoKeyW(hkey, szString, &size,NULL, NULL, NULL,
2038 NULL, NULL, NULL, NULL, NULL, NULL);
2039 else if (V_I4(&varg2) > 0)
2040 ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString,
2041 &size, 0, 0, NULL, NULL);
2042 else /* V_I4(&varg2) < 0 */
2043 ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, size);
2045 if (ret == ERROR_SUCCESS)
2047 V_VT(pVarResult) = VT_BSTR;
2048 V_BSTR(pVarResult) = SysAllocString(szString);
2051 msi_free(szString);
2054 done:
2055 VariantClear(&varg0);
2056 VariantClear(&varg1);
2057 VariantClear(&varg2);
2058 RegCloseKey(hkey);
2059 return hr;
2062 static HRESULT InstallerImpl_Environment(WORD wFlags,
2063 DISPPARAMS* pDispParams,
2064 VARIANT* pVarResult,
2065 EXCEPINFO* pExcepInfo,
2066 UINT* puArgErr)
2068 if (!(wFlags & DISPATCH_METHOD))
2069 return DISP_E_MEMBERNOTFOUND;
2071 FIXME("\n");
2073 VariantInit(pVarResult);
2074 return S_OK;
2077 static HRESULT InstallerImpl_FileAttributes(WORD wFlags,
2078 DISPPARAMS* pDispParams,
2079 VARIANT* pVarResult,
2080 EXCEPINFO* pExcepInfo,
2081 UINT* puArgErr)
2083 if (!(wFlags & DISPATCH_METHOD))
2084 return DISP_E_MEMBERNOTFOUND;
2086 FIXME("\n");
2088 VariantInit(pVarResult);
2089 return S_OK;
2092 static HRESULT InstallerImpl_FileSize(WORD wFlags,
2093 DISPPARAMS* pDispParams,
2094 VARIANT* pVarResult,
2095 EXCEPINFO* pExcepInfo,
2096 UINT* puArgErr)
2098 if (!(wFlags & DISPATCH_METHOD))
2099 return DISP_E_MEMBERNOTFOUND;
2101 FIXME("\n");
2103 VariantInit(pVarResult);
2104 return S_OK;
2107 static HRESULT InstallerImpl_FileVersion(WORD wFlags,
2108 DISPPARAMS* pDispParams,
2109 VARIANT* pVarResult,
2110 EXCEPINFO* pExcepInfo,
2111 UINT* puArgErr)
2113 if (!(wFlags & DISPATCH_METHOD))
2114 return DISP_E_MEMBERNOTFOUND;
2116 FIXME("\n");
2118 VariantInit(pVarResult);
2119 return S_OK;
2122 static HRESULT InstallerImpl_ProductState(WORD wFlags,
2123 DISPPARAMS* pDispParams,
2124 VARIANT* pVarResult,
2125 EXCEPINFO* pExcepInfo,
2126 UINT* puArgErr)
2128 HRESULT hr;
2129 VARIANTARG varg0;
2131 if (!(wFlags & DISPATCH_PROPERTYGET))
2132 return DISP_E_MEMBERNOTFOUND;
2134 VariantInit(&varg0);
2135 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2136 if (FAILED(hr))
2137 return hr;
2139 V_VT(pVarResult) = VT_I4;
2140 V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0));
2142 VariantClear(&varg0);
2143 return S_OK;
2146 static HRESULT InstallerImpl_ProductInfo(WORD wFlags,
2147 DISPPARAMS* pDispParams,
2148 VARIANT* pVarResult,
2149 EXCEPINFO* pExcepInfo,
2150 UINT* puArgErr)
2152 UINT ret;
2153 HRESULT hr;
2154 DWORD size;
2155 LPWSTR str = NULL;
2156 VARIANTARG varg0, varg1;
2158 if (!(wFlags & DISPATCH_PROPERTYGET))
2159 return DISP_E_MEMBERNOTFOUND;
2161 VariantInit(&varg0);
2162 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2163 if (FAILED(hr))
2164 return hr;
2166 VariantInit(&varg1);
2167 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
2168 if (FAILED(hr))
2169 goto done;
2171 V_VT(pVarResult) = VT_BSTR;
2172 V_BSTR(pVarResult) = NULL;
2174 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &size);
2175 if (ret != ERROR_SUCCESS)
2177 hr = DISP_E_EXCEPTION;
2178 goto done;
2181 str = msi_alloc(++size * sizeof(WCHAR));
2182 if (!str)
2184 hr = E_OUTOFMEMORY;
2185 goto done;
2188 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), str, &size);
2189 if (ret != ERROR_SUCCESS)
2191 hr = DISP_E_EXCEPTION;
2192 goto done;
2195 V_BSTR(pVarResult) = SysAllocString(str);
2196 hr = S_OK;
2198 done:
2199 msi_free(str);
2200 VariantClear(&varg0);
2201 VariantClear(&varg1);
2202 return hr;
2205 static HRESULT InstallerImpl_Products(WORD flags,
2206 DISPPARAMS* pDispParams,
2207 VARIANT* result,
2208 EXCEPINFO* pExcepInfo,
2209 UINT* puArgErr)
2211 IDispatch *dispatch;
2212 HRESULT hr;
2214 if (!(flags & DISPATCH_PROPERTYGET))
2215 return DISP_E_MEMBERNOTFOUND;
2217 hr = create_list(NULL, &dispatch);
2218 if (FAILED(hr))
2219 return hr;
2221 V_VT(result) = VT_DISPATCH;
2222 V_DISPATCH(result) = dispatch;
2224 return hr;
2227 static HRESULT InstallerImpl_RelatedProducts(WORD flags,
2228 DISPPARAMS* pDispParams,
2229 VARIANT* result,
2230 EXCEPINFO* pExcepInfo,
2231 UINT* puArgErr)
2233 IDispatch* dispatch;
2234 VARIANTARG related;
2235 HRESULT hr;
2237 if (!(flags & DISPATCH_PROPERTYGET))
2238 return DISP_E_MEMBERNOTFOUND;
2240 VariantInit(&related);
2241 hr = DispGetParam(pDispParams, 0, VT_BSTR, &related, puArgErr);
2242 if (FAILED(hr))
2243 return hr;
2245 hr = create_list(V_BSTR(&related), &dispatch);
2246 VariantClear(&related);
2248 V_VT(result) = VT_DISPATCH;
2249 V_DISPATCH(result) = dispatch;
2251 return hr;
2254 static HRESULT InstallerImpl_Invoke(
2255 AutomationObject* This,
2256 DISPID dispIdMember,
2257 REFIID riid,
2258 LCID lcid,
2259 WORD wFlags,
2260 DISPPARAMS* pDispParams,
2261 VARIANT* pVarResult,
2262 EXCEPINFO* pExcepInfo,
2263 UINT* puArgErr)
2265 switch (dispIdMember)
2267 case DISPID_INSTALLER_CREATERECORD:
2268 return InstallerImpl_CreateRecord(wFlags, pDispParams,
2269 pVarResult, pExcepInfo, puArgErr);
2271 case DISPID_INSTALLER_OPENPACKAGE:
2272 return InstallerImpl_OpenPackage(This, wFlags, pDispParams,
2273 pVarResult, pExcepInfo, puArgErr);
2275 case DISPID_INSTALLER_OPENPRODUCT:
2276 return InstallerImpl_OpenProduct(wFlags, pDispParams,
2277 pVarResult, pExcepInfo, puArgErr);
2279 case DISPID_INSTALLER_OPENDATABASE:
2280 return InstallerImpl_OpenDatabase(wFlags, pDispParams,
2281 pVarResult, pExcepInfo, puArgErr);
2283 case DISPID_INSTALLER_SUMMARYINFORMATION:
2284 return InstallerImpl_SummaryInformation(wFlags, pDispParams,
2285 pVarResult, pExcepInfo,
2286 puArgErr);
2288 case DISPID_INSTALLER_UILEVEL:
2289 return InstallerImpl_UILevel(wFlags, pDispParams,
2290 pVarResult, pExcepInfo, puArgErr);
2292 case DISPID_INSTALLER_ENABLELOG:
2293 return InstallerImpl_EnableLog(wFlags, pDispParams,
2294 pVarResult, pExcepInfo, puArgErr);
2296 case DISPID_INSTALLER_INSTALLPRODUCT:
2297 return InstallerImpl_InstallProduct(wFlags, pDispParams,
2298 pVarResult, pExcepInfo,
2299 puArgErr);
2301 case DISPID_INSTALLER_VERSION:
2302 return InstallerImpl_Version(wFlags, pVarResult,
2303 pExcepInfo, puArgErr);
2305 case DISPID_INSTALLER_LASTERRORRECORD:
2306 return InstallerImpl_LastErrorRecord(wFlags, pDispParams,
2307 pVarResult, pExcepInfo,
2308 puArgErr);
2310 case DISPID_INSTALLER_REGISTRYVALUE:
2311 return InstallerImpl_RegistryValue(wFlags, pDispParams,
2312 pVarResult, pExcepInfo,
2313 puArgErr);
2315 case DISPID_INSTALLER_ENVIRONMENT:
2316 return InstallerImpl_Environment(wFlags, pDispParams,
2317 pVarResult, pExcepInfo, puArgErr);
2319 case DISPID_INSTALLER_FILEATTRIBUTES:
2320 return InstallerImpl_FileAttributes(wFlags, pDispParams,
2321 pVarResult, pExcepInfo,
2322 puArgErr);
2324 case DISPID_INSTALLER_FILESIZE:
2325 return InstallerImpl_FileSize(wFlags, pDispParams,
2326 pVarResult, pExcepInfo, puArgErr);
2328 case DISPID_INSTALLER_FILEVERSION:
2329 return InstallerImpl_FileVersion(wFlags, pDispParams,
2330 pVarResult, pExcepInfo, puArgErr);
2332 case DISPID_INSTALLER_PRODUCTSTATE:
2333 return InstallerImpl_ProductState(wFlags, pDispParams,
2334 pVarResult, pExcepInfo, puArgErr);
2336 case DISPID_INSTALLER_PRODUCTINFO:
2337 return InstallerImpl_ProductInfo(wFlags, pDispParams,
2338 pVarResult, pExcepInfo, puArgErr);
2340 case DISPID_INSTALLER_PRODUCTS:
2341 return InstallerImpl_Products(wFlags, pDispParams,
2342 pVarResult, pExcepInfo, puArgErr);
2344 case DISPID_INSTALLER_RELATEDPRODUCTS:
2345 return InstallerImpl_RelatedProducts(wFlags, pDispParams,
2346 pVarResult, pExcepInfo,
2347 puArgErr);
2349 default:
2350 return DISP_E_MEMBERNOTFOUND;
2354 HRESULT create_msiserver(IUnknown *outer, void **ppObj)
2356 AutomationObject *installer;
2357 HRESULT hr;
2359 TRACE("(%p %p)\n", outer, ppObj);
2361 if (outer)
2362 return CLASS_E_NOAGGREGATION;
2364 installer = msi_alloc(sizeof(AutomationObject));
2365 if (!installer) return E_OUTOFMEMORY;
2367 hr = init_automation_object(installer, 0, &DIID_Installer, InstallerImpl_Invoke, NULL);
2368 if (hr != S_OK)
2370 msi_free(installer);
2371 return hr;
2374 *ppObj = &installer->IDispatch_iface;
2376 return hr;
2379 HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **disp)
2381 SessionObject *session;
2382 HRESULT hr;
2384 session = msi_alloc(sizeof(SessionObject));
2385 if (!session) return E_OUTOFMEMORY;
2387 hr = init_automation_object(&session->autoobj, msiHandle, &DIID_Session, SessionImpl_Invoke, NULL);
2388 if (hr != S_OK)
2390 msi_free(session);
2391 return hr;
2394 session->installer = installer;
2395 *disp = &session->autoobj.IDispatch_iface;
2397 return hr;
2400 static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
2402 AutomationObject *database;
2403 HRESULT hr;
2405 TRACE("(%d %p)\n", msiHandle, dispatch);
2407 database = msi_alloc(sizeof(AutomationObject));
2408 if (!database) return E_OUTOFMEMORY;
2410 hr = init_automation_object(database, msiHandle, &DIID_Database, DatabaseImpl_Invoke, NULL);
2411 if (hr != S_OK)
2413 msi_free(database);
2414 return hr;
2417 *dispatch = &database->IDispatch_iface;
2419 return hr;
2422 static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch)
2424 AutomationObject *view;
2425 HRESULT hr;
2427 TRACE("(%d %p)\n", msiHandle, dispatch);
2429 view = msi_alloc(sizeof(AutomationObject));
2430 if (!view) return E_OUTOFMEMORY;
2432 hr = init_automation_object(view, msiHandle, &DIID_View, ViewImpl_Invoke, NULL);
2433 if (hr != S_OK)
2435 msi_free(view);
2436 return hr;
2439 *dispatch = &view->IDispatch_iface;
2441 return hr;
2444 static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp)
2446 AutomationObject *info;
2447 HRESULT hr;
2449 info = msi_alloc(sizeof(*info));
2450 if (!info) return E_OUTOFMEMORY;
2452 hr = init_automation_object(info, msiHandle, &DIID_SummaryInfo, SummaryInfoImpl_Invoke, NULL);
2453 if (hr != S_OK)
2455 msi_free(info);
2456 return hr;
2459 *disp = &info->IDispatch_iface;
2461 return hr;