d3d8: Stop setting the device state in d3d8_device_SetPixelShaderConstant().
[wine.git] / dlls / msi / automation.c
blobba3a068a74bf24f3e7fb094659507a5f98b71146
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"
36 #include "msiserver.h"
37 #include "msiserver_dispids.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msi);
41 #define REG_INDEX_CLASSES_ROOT 0
42 #define REG_INDEX_DYN_DATA 6
44 typedef struct AutomationObject AutomationObject;
46 /* function that is called from AutomationObject::Invoke, specific to this type of object */
47 typedef HRESULT (*auto_invoke_func)(AutomationObject* This,
48 DISPID dispIdMember, REFIID riid, LCID lcid, WORD flags, DISPPARAMS* pDispParams,
49 VARIANT* result, EXCEPINFO* ei, UINT* arg_err);
50 /* function that is called from AutomationObject::Release when the object is being freed
51 to free any private data structures (or NULL) */
52 typedef void (*auto_free_func)(AutomationObject* This);
54 typedef struct {
55 REFIID riid;
56 auto_invoke_func fn_invoke;
57 auto_free_func fn_free;
58 } tid_id_t;
61 static HRESULT database_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
62 static HRESULT installer_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
63 static HRESULT record_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
64 static HRESULT session_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
65 static HRESULT list_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
66 static void list_free(AutomationObject*);
67 static HRESULT summaryinfo_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
68 static HRESULT view_invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
70 static tid_id_t tid_ids[] = {
71 { &DIID_Database, database_invoke },
72 { &DIID_Installer, installer_invoke },
73 { &DIID_Record, record_invoke },
74 { &DIID_Session, session_invoke },
75 { &DIID_StringList, list_invoke, list_free },
76 { &DIID_SummaryInfo, summaryinfo_invoke },
77 { &DIID_View, view_invoke }
80 static ITypeLib *typelib;
81 static ITypeInfo *typeinfos[LAST_tid];
83 static const IID *get_riid_from_tid(tid_t tid)
85 return tid_ids[tid].riid;
88 HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
90 HRESULT hr;
92 if (!typelib)
94 ITypeLib *lib;
96 hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, LOCALE_NEUTRAL, &lib);
97 if (FAILED(hr)) {
98 static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
99 hr = LoadTypeLib(msiserverW, &lib);
100 if (FAILED(hr)) {
101 ERR("Could not load msiserver.tlb\n");
102 return hr;
106 if (InterlockedCompareExchangePointer((void**)&typelib, lib, NULL))
107 ITypeLib_Release(lib);
110 if (!typeinfos[tid])
112 ITypeInfo *ti;
114 hr = ITypeLib_GetTypeInfoOfGuid(typelib, get_riid_from_tid(tid), &ti);
115 if (FAILED(hr)) {
116 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid)));
117 return hr;
120 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
121 ITypeInfo_Release(ti);
124 *typeinfo = typeinfos[tid];
125 return S_OK;
128 void release_typelib(void)
130 unsigned i;
132 for (i = 0; i < ARRAY_SIZE(typeinfos); i++)
133 if (typeinfos[i])
134 ITypeInfo_Release(typeinfos[i]);
136 if (typelib)
137 ITypeLib_Release(typelib);
141 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
142 * called from AutomationObject::Invoke.
144 struct AutomationObject {
145 IDispatch IDispatch_iface;
146 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface;
147 LONG ref;
149 /* type id for this class */
150 tid_t tid;
152 /* The MSI handle of the current object */
153 MSIHANDLE msiHandle;
156 typedef struct {
157 AutomationObject autoobj;
158 int count;
159 VARIANT *data;
160 } ListObject;
162 static HRESULT create_database(MSIHANDLE, IDispatch**);
163 static HRESULT create_list_enumerator(ListObject*, void**);
164 static HRESULT create_summaryinfo(MSIHANDLE, IDispatch**);
165 static HRESULT create_view(MSIHANDLE, IDispatch**);
167 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */
168 typedef struct {
169 IEnumVARIANT IEnumVARIANT_iface;
170 LONG ref;
172 /* Current position and pointer to AutomationObject that stores actual data */
173 ULONG pos;
174 ListObject *list;
175 } ListEnumerator;
177 typedef struct {
178 AutomationObject autoobj;
179 IDispatch *installer;
180 } SessionObject;
182 static inline AutomationObject *impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo *iface )
184 return CONTAINING_RECORD(iface, AutomationObject, IProvideMultipleClassInfo_iface);
187 static inline AutomationObject *impl_from_IDispatch( IDispatch *iface )
189 return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface);
192 /* AutomationObject methods */
193 static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject)
195 AutomationObject *This = impl_from_IDispatch(iface);
197 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
199 if (ppvObject == NULL)
200 return E_INVALIDARG;
202 *ppvObject = 0;
204 if (IsEqualGUID(riid, &IID_IUnknown) ||
205 IsEqualGUID(riid, &IID_IDispatch) ||
206 IsEqualGUID(riid, get_riid_from_tid(This->tid)))
207 *ppvObject = &This->IDispatch_iface;
208 else if (IsEqualGUID(riid, &IID_IProvideClassInfo) ||
209 IsEqualGUID(riid, &IID_IProvideClassInfo2) ||
210 IsEqualGUID(riid, &IID_IProvideMultipleClassInfo))
211 *ppvObject = &This->IProvideMultipleClassInfo_iface;
212 else
214 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid));
215 return E_NOINTERFACE;
218 IDispatch_AddRef(iface);
220 return S_OK;
223 static ULONG WINAPI AutomationObject_AddRef(IDispatch* iface)
225 AutomationObject *This = impl_from_IDispatch(iface);
227 TRACE("(%p/%p)\n", iface, This);
229 return InterlockedIncrement(&This->ref);
232 static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
234 AutomationObject *This = impl_from_IDispatch(iface);
235 ULONG ref = InterlockedDecrement(&This->ref);
237 TRACE("(%p/%p)\n", iface, This);
239 if (!ref)
241 if (tid_ids[This->tid].fn_free) tid_ids[This->tid].fn_free(This);
242 MsiCloseHandle(This->msiHandle);
243 msi_free(This);
246 return ref;
249 static HRESULT WINAPI AutomationObject_GetTypeInfoCount(
250 IDispatch* iface,
251 UINT* pctinfo)
253 AutomationObject *This = impl_from_IDispatch(iface);
255 TRACE("(%p/%p)->(%p)\n", iface, This, pctinfo);
256 *pctinfo = 1;
257 return S_OK;
260 static HRESULT WINAPI AutomationObject_GetTypeInfo(
261 IDispatch* iface,
262 UINT iTInfo,
263 LCID lcid,
264 ITypeInfo** ppTInfo)
266 AutomationObject *This = impl_from_IDispatch(iface);
267 HRESULT hr;
269 TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo);
271 hr = get_typeinfo(This->tid, ppTInfo);
272 if (FAILED(hr))
273 return hr;
275 ITypeInfo_AddRef(*ppTInfo);
276 return hr;
279 static HRESULT WINAPI AutomationObject_GetIDsOfNames(
280 IDispatch* iface,
281 REFIID riid,
282 LPOLESTR* rgszNames,
283 UINT cNames,
284 LCID lcid,
285 DISPID* rgDispId)
287 AutomationObject *This = impl_from_IDispatch(iface);
288 ITypeInfo *ti;
289 HRESULT hr;
291 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", iface, This,
292 debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
294 if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG;
296 hr = get_typeinfo(This->tid, &ti);
297 if (FAILED(hr))
298 return hr;
300 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
301 if (hr == DISP_E_UNKNOWNNAME)
303 UINT idx;
304 for (idx=0; idx<cNames; idx++)
306 if (rgDispId[idx] == DISPID_UNKNOWN)
307 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(get_riid_from_tid(This->tid)));
310 return hr;
313 /* Maximum number of allowed function parameters+1 */
314 #define MAX_FUNC_PARAMS 20
316 /* Some error checking is done here to simplify individual object function invocation */
317 static HRESULT WINAPI AutomationObject_Invoke(
318 IDispatch* iface,
319 DISPID dispIdMember,
320 REFIID riid,
321 LCID lcid,
322 WORD wFlags,
323 DISPPARAMS* pDispParams,
324 VARIANT* pVarResult,
325 EXCEPINFO* pExcepInfo,
326 UINT* puArgErr)
328 AutomationObject *This = impl_from_IDispatch(iface);
329 HRESULT hr;
330 unsigned int uArgErr;
331 VARIANT varResultDummy;
332 BSTR bstrName = NULL;
333 ITypeInfo *ti;
335 TRACE("(%p/%p)->(%d, %s, %d, %d, %p, %p, %p, %p)\n", iface, This,
336 dispIdMember, debugstr_guid(riid), lcid, wFlags,
337 pDispParams, pVarResult, pExcepInfo, puArgErr);
339 if (!IsEqualIID(riid, &IID_NULL))
341 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
342 return DISP_E_UNKNOWNNAME;
345 if (wFlags & DISPATCH_PROPERTYGET && !pVarResult)
347 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
348 return DISP_E_PARAMNOTOPTIONAL;
351 /* This simplifies our individual object invocation functions */
352 if (puArgErr == NULL) puArgErr = &uArgErr;
353 if (pVarResult == NULL) pVarResult = &varResultDummy;
355 hr = get_typeinfo(This->tid, &ti);
356 if (FAILED(hr))
357 return hr;
359 /* Assume return type is void unless determined otherwise */
360 VariantInit(pVarResult);
362 /* If we are tracing, we want to see the name of the member we are invoking */
363 if (TRACE_ON(msi))
365 ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL);
366 TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName));
369 hr = tid_ids[This->tid].fn_invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
371 if (hr == DISP_E_MEMBERNOTFOUND) {
372 if (bstrName == NULL) ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL);
373 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags,
374 debugstr_guid(get_riid_from_tid(This->tid)));
376 else if (pExcepInfo &&
377 (hr == DISP_E_PARAMNOTFOUND ||
378 hr == DISP_E_EXCEPTION)) {
379 static const WCHAR szComma[] = { ',',0 };
380 static const WCHAR szExceptionSource[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
381 WCHAR szExceptionDescription[MAX_PATH];
382 BSTR bstrParamNames[MAX_FUNC_PARAMS];
383 unsigned namesNo, i;
384 BOOL bFirst = TRUE;
386 if (FAILED(ITypeInfo_GetNames(ti, dispIdMember, bstrParamNames,
387 MAX_FUNC_PARAMS, &namesNo)))
389 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember);
391 else
393 memset(szExceptionDescription, 0, sizeof(szExceptionDescription));
394 for (i=0; i<namesNo; i++)
396 if (bFirst) bFirst = FALSE;
397 else {
398 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], szComma);
400 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], bstrParamNames[i]);
401 SysFreeString(bstrParamNames[i]);
404 memset(pExcepInfo, 0, sizeof(EXCEPINFO));
405 pExcepInfo->wCode = 1000;
406 pExcepInfo->bstrSource = SysAllocString(szExceptionSource);
407 pExcepInfo->bstrDescription = SysAllocString(szExceptionDescription);
408 hr = DISP_E_EXCEPTION;
412 /* Make sure we free the return variant if it is our dummy variant */
413 if (pVarResult == &varResultDummy) VariantClear(pVarResult);
415 /* Free function name if we retrieved it */
416 SysFreeString(bstrName);
418 TRACE("Returning 0x%08x, %s\n", hr, SUCCEEDED(hr) ? "ok" : "not ok");
420 return hr;
423 static const struct IDispatchVtbl AutomationObjectVtbl =
425 AutomationObject_QueryInterface,
426 AutomationObject_AddRef,
427 AutomationObject_Release,
428 AutomationObject_GetTypeInfoCount,
429 AutomationObject_GetTypeInfo,
430 AutomationObject_GetIDsOfNames,
431 AutomationObject_Invoke
435 * IProvideMultipleClassInfo methods
438 static HRESULT WINAPI ProvideMultipleClassInfo_QueryInterface(
439 IProvideMultipleClassInfo* iface,
440 REFIID riid,
441 VOID** ppvoid)
443 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
444 return IDispatch_QueryInterface(&This->IDispatch_iface, riid, ppvoid);
447 static ULONG WINAPI ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo* iface)
449 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
450 return IDispatch_AddRef(&This->IDispatch_iface);
453 static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo* iface)
455 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
456 return IDispatch_Release(&This->IDispatch_iface);
459 static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI)
461 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
462 HRESULT hr;
464 TRACE("(%p/%p)->(%p)\n", iface, This, ppTI);
466 hr = get_typeinfo(This->tid, ppTI);
467 if (SUCCEEDED(hr))
468 ITypeInfo_AddRef(*ppTI);
470 return hr;
473 static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID)
475 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
476 TRACE("(%p/%p)->(%d,%s)\n", iface, This, dwGuidKind, debugstr_guid(pGUID));
478 if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
479 return E_INVALIDARG;
480 else {
481 *pGUID = *get_riid_from_tid(This->tid);
482 return S_OK;
486 static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo* iface, ULONG* pcti)
488 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
490 TRACE("(%p/%p)->(%p)\n", iface, This, pcti);
491 *pcti = 1;
492 return S_OK;
495 static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface,
496 ULONG iti,
497 DWORD dwFlags,
498 ITypeInfo** ti,
499 DWORD* pdwTIFlags,
500 ULONG* pcdispidReserved,
501 IID* piidPrimary,
502 IID* piidSource)
504 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
506 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, ti, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource);
508 if (iti != 0)
509 return E_INVALIDARG;
511 if (dwFlags & MULTICLASSINFO_GETTYPEINFO)
513 HRESULT hr = get_typeinfo(This->tid, ti);
514 if (FAILED(hr))
515 return hr;
517 ITypeInfo_AddRef(*ti);
520 if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
522 *pdwTIFlags = 0;
523 *pcdispidReserved = 0;
526 if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY)
527 *piidPrimary = *get_riid_from_tid(This->tid);
529 if (dwFlags & MULTICLASSINFO_GETIIDSOURCE)
530 *piidSource = *get_riid_from_tid(This->tid);
532 return S_OK;
535 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl =
537 ProvideMultipleClassInfo_QueryInterface,
538 ProvideMultipleClassInfo_AddRef,
539 ProvideMultipleClassInfo_Release,
540 ProvideMultipleClassInfo_GetClassInfo,
541 ProvideMultipleClassInfo_GetGUID,
542 ProvideMultipleClassInfo_GetMultiTypeInfoCount,
543 ProvideMultipleClassInfo_GetInfoOfIndex
546 static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, tid_t tid)
548 TRACE("(%p, %d, %s)\n", This, msiHandle, debugstr_guid(get_riid_from_tid(tid)));
550 This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
551 This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
552 This->ref = 1;
554 This->msiHandle = msiHandle;
555 This->tid = tid;
557 return S_OK;
561 * ListEnumerator methods
564 static inline ListEnumerator *impl_from_IEnumVARIANT(IEnumVARIANT* iface)
566 return CONTAINING_RECORD(iface, ListEnumerator, IEnumVARIANT_iface);
569 static HRESULT WINAPI ListEnumerator_QueryInterface(IEnumVARIANT* iface, REFIID riid,
570 void** ppvObject)
572 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
574 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
576 if (ppvObject == NULL)
577 return E_INVALIDARG;
579 *ppvObject = 0;
581 if (IsEqualGUID(riid, &IID_IUnknown) ||
582 IsEqualGUID(riid, &IID_IEnumVARIANT))
584 *ppvObject = &This->IEnumVARIANT_iface;
586 else
588 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid));
589 return E_NOINTERFACE;
592 IEnumVARIANT_AddRef(iface);
593 return S_OK;
596 static ULONG WINAPI ListEnumerator_AddRef(IEnumVARIANT* iface)
598 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
600 TRACE("(%p/%p)\n", iface, This);
602 return InterlockedIncrement(&This->ref);
605 static ULONG WINAPI ListEnumerator_Release(IEnumVARIANT* iface)
607 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
608 ULONG ref = InterlockedDecrement(&This->ref);
610 TRACE("(%p/%p)\n", iface, This);
612 if (!ref)
614 if (This->list) IDispatch_Release(&This->list->autoobj.IDispatch_iface);
615 msi_free(This);
618 return ref;
621 static HRESULT WINAPI ListEnumerator_Next(IEnumVARIANT* iface, ULONG celt, VARIANT* rgVar,
622 ULONG* fetched)
624 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
625 ULONG i, local;
627 TRACE("(%p, %uld, %p, %p)\n", iface, celt, rgVar, fetched);
629 if (fetched) *fetched = 0;
631 if (!rgVar)
632 return S_FALSE;
634 for (local = 0; local < celt; local++)
635 VariantInit(&rgVar[local]);
637 for (i = This->pos, local = 0; i < This->list->count && local < celt; i++, local++)
638 VariantCopy(&rgVar[local], &This->list->data[i]);
640 if (fetched) *fetched = local;
641 This->pos = i;
643 return (local < celt) ? S_FALSE : S_OK;
646 static HRESULT WINAPI ListEnumerator_Skip(IEnumVARIANT* iface, ULONG celt)
648 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
650 TRACE("(%p,%uld)\n", iface, celt);
652 This->pos += celt;
653 if (This->pos >= This->list->count)
655 This->pos = This->list->count;
656 return S_FALSE;
659 return S_OK;
662 static HRESULT WINAPI ListEnumerator_Reset(IEnumVARIANT* iface)
664 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
666 TRACE("(%p)\n", iface);
668 This->pos = 0;
669 return S_OK;
672 static HRESULT WINAPI ListEnumerator_Clone(IEnumVARIANT* iface, IEnumVARIANT **ppEnum)
674 ListEnumerator *This = impl_from_IEnumVARIANT(iface);
675 HRESULT hr;
677 TRACE("(%p,%p)\n", iface, ppEnum);
679 if (ppEnum == NULL)
680 return S_FALSE;
682 *ppEnum = NULL;
683 hr = create_list_enumerator(This->list, (LPVOID *)ppEnum);
684 if (FAILED(hr))
686 if (*ppEnum) IEnumVARIANT_Release(*ppEnum);
687 return hr;
690 return S_OK;
693 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
695 ListEnumerator_QueryInterface,
696 ListEnumerator_AddRef,
697 ListEnumerator_Release,
698 ListEnumerator_Next,
699 ListEnumerator_Skip,
700 ListEnumerator_Reset,
701 ListEnumerator_Clone
704 /* Create a list enumerator, placing the result in the pointer ppObj. */
705 static HRESULT create_list_enumerator(ListObject *list, void **ppObj)
707 ListEnumerator *object;
709 TRACE("(%p, %p)\n", list, ppObj);
711 object = msi_alloc(sizeof(ListEnumerator));
713 /* Set all the VTable references */
714 object->IEnumVARIANT_iface.lpVtbl = &ListEnumerator_Vtbl;
715 object->ref = 1;
717 /* Store data that was passed */
718 object->pos = 0;
719 object->list = list;
720 if (list) IDispatch_AddRef(&list->autoobj.IDispatch_iface);
722 *ppObj = object;
723 return S_OK;
727 * Individual Object Invocation Functions
730 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
731 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
732 using DispGetParam/VariantChangeType. */
733 static HRESULT DispGetParam_CopyOnly(
734 DISPPARAMS *pdispparams, /* [in] Parameter list */
735 UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
736 VARIANT *pvarResult) /* [out] Destination for resulting variant */
738 /* position is counted backwards */
739 UINT pos;
741 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
742 *position, pdispparams->cArgs, pdispparams->cNamedArgs);
743 if (*position < pdispparams->cArgs) {
744 /* positional arg? */
745 pos = pdispparams->cArgs - *position - 1;
746 } else {
747 /* FIXME: is this how to handle named args? */
748 for (pos=0; pos<pdispparams->cNamedArgs; pos++)
749 if (pdispparams->rgdispidNamedArgs[pos] == *position) break;
751 if (pos==pdispparams->cNamedArgs)
752 return DISP_E_PARAMNOTFOUND;
754 *position = pos;
755 return VariantCopyInd(pvarResult,
756 &pdispparams->rgvarg[pos]);
759 static HRESULT summaryinfo_invoke(
760 AutomationObject* This,
761 DISPID dispIdMember,
762 REFIID riid,
763 LCID lcid,
764 WORD wFlags,
765 DISPPARAMS* pDispParams,
766 VARIANT* pVarResult,
767 EXCEPINFO* pExcepInfo,
768 UINT* puArgErr)
770 UINT ret;
771 VARIANTARG varg0, varg1;
772 FILETIME ft, ftlocal;
773 SYSTEMTIME st;
774 HRESULT hr;
776 VariantInit(&varg0);
777 VariantInit(&varg1);
779 switch (dispIdMember)
781 case DISPID_SUMMARYINFO_PROPERTY:
782 if (wFlags & DISPATCH_PROPERTYGET)
784 UINT type;
785 INT value;
786 DWORD size = 0;
787 DATE date;
788 LPWSTR str;
790 static WCHAR szEmpty[] = {0};
792 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
793 if (FAILED(hr)) return hr;
794 ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, &value,
795 &ft, szEmpty, &size);
796 if (ret != ERROR_SUCCESS &&
797 ret != ERROR_MORE_DATA)
799 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
800 return DISP_E_EXCEPTION;
803 switch (type)
805 case VT_EMPTY:
806 break;
808 case VT_I2:
809 case VT_I4:
810 V_VT(pVarResult) = VT_I4;
811 V_I4(pVarResult) = value;
812 break;
814 case VT_LPSTR:
815 if (!(str = msi_alloc(++size * sizeof(WCHAR))))
816 ERR("Out of memory\n");
817 else if ((ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, NULL,
818 NULL, str, &size)) != ERROR_SUCCESS)
819 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
820 else
822 V_VT(pVarResult) = VT_BSTR;
823 V_BSTR(pVarResult) = SysAllocString(str);
825 msi_free(str);
826 break;
828 case VT_FILETIME:
829 FileTimeToLocalFileTime(&ft, &ftlocal);
830 FileTimeToSystemTime(&ftlocal, &st);
831 SystemTimeToVariantTime(&st, &date);
833 V_VT(pVarResult) = VT_DATE;
834 V_DATE(pVarResult) = date;
835 break;
837 default:
838 ERR("Unhandled variant type %d\n", type);
841 else if (wFlags & DISPATCH_PROPERTYPUT)
843 UINT posValue = DISPID_PROPERTYPUT;
845 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
846 if (FAILED(hr)) return hr;
847 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg1);
848 if (FAILED(hr))
850 *puArgErr = posValue;
851 return hr;
854 switch (V_VT(&varg1))
856 case VT_I2:
857 case VT_I4:
858 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), V_VT(&varg1), V_I4(&varg1), NULL, NULL);
859 break;
861 case VT_DATE:
862 VariantTimeToSystemTime(V_DATE(&varg1), &st);
863 SystemTimeToFileTime(&st, &ftlocal);
864 LocalFileTimeToFileTime(&ftlocal, &ft);
865 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_FILETIME, 0, &ft, NULL);
866 break;
868 case VT_BSTR:
869 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_LPSTR, 0, NULL, V_BSTR(&varg1));
870 break;
872 default:
873 FIXME("Unhandled variant type %d\n", V_VT(&varg1));
874 VariantClear(&varg1);
875 return DISP_E_EXCEPTION;
878 if (ret != ERROR_SUCCESS)
880 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret);
881 return DISP_E_EXCEPTION;
884 else return DISP_E_MEMBERNOTFOUND;
885 break;
887 case DISPID_SUMMARYINFO_PROPERTYCOUNT:
888 if (wFlags & DISPATCH_PROPERTYGET) {
889 UINT count;
890 if ((ret = MsiSummaryInfoGetPropertyCount(This->msiHandle, &count)) != ERROR_SUCCESS)
891 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret);
892 else
894 V_VT(pVarResult) = VT_I4;
895 V_I4(pVarResult) = count;
898 else return DISP_E_MEMBERNOTFOUND;
899 break;
901 default:
902 return DISP_E_MEMBERNOTFOUND;
905 VariantClear(&varg1);
906 VariantClear(&varg0);
908 return S_OK;
911 static HRESULT record_invoke(
912 AutomationObject* This,
913 DISPID dispIdMember,
914 REFIID riid,
915 LCID lcid,
916 WORD wFlags,
917 DISPPARAMS* pDispParams,
918 VARIANT* pVarResult,
919 EXCEPINFO* pExcepInfo,
920 UINT* puArgErr)
922 WCHAR *szString;
923 DWORD dwLen = 0;
924 UINT ret;
925 VARIANTARG varg0, varg1;
926 HRESULT hr;
928 VariantInit(&varg0);
929 VariantInit(&varg1);
931 switch (dispIdMember)
933 case DISPID_RECORD_FIELDCOUNT:
934 if (wFlags & DISPATCH_PROPERTYGET) {
935 V_VT(pVarResult) = VT_I4;
936 V_I4(pVarResult) = MsiRecordGetFieldCount(This->msiHandle);
938 else return DISP_E_MEMBERNOTFOUND;
939 break;
941 case DISPID_RECORD_STRINGDATA:
942 if (wFlags & DISPATCH_PROPERTYGET) {
943 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
944 if (FAILED(hr)) return hr;
945 V_VT(pVarResult) = VT_BSTR;
946 V_BSTR(pVarResult) = NULL;
947 if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
949 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
950 ERR("Out of memory\n");
951 else if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
952 V_BSTR(pVarResult) = SysAllocString(szString);
953 msi_free(szString);
955 if (ret != ERROR_SUCCESS)
956 ERR("MsiRecordGetString returned %d\n", ret);
957 } else if (wFlags & DISPATCH_PROPERTYPUT) {
958 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
959 if (FAILED(hr)) return hr;
960 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
961 if (FAILED(hr)) return hr;
962 if ((ret = MsiRecordSetStringW(This->msiHandle, V_I4(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
964 VariantClear(&varg1);
965 ERR("MsiRecordSetString returned %d\n", ret);
966 return DISP_E_EXCEPTION;
969 else return DISP_E_MEMBERNOTFOUND;
970 break;
972 case DISPID_RECORD_INTEGERDATA:
973 if (wFlags & DISPATCH_PROPERTYGET) {
974 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
975 if (FAILED(hr)) return hr;
976 V_VT(pVarResult) = VT_I4;
977 V_I4(pVarResult) = MsiRecordGetInteger(This->msiHandle, V_I4(&varg0));
978 } else if (wFlags & DISPATCH_PROPERTYPUT) {
979 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
980 if (FAILED(hr)) return hr;
981 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
982 if (FAILED(hr)) return hr;
983 if ((ret = MsiRecordSetInteger(This->msiHandle, V_I4(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
985 ERR("MsiRecordSetInteger returned %d\n", ret);
986 return DISP_E_EXCEPTION;
989 else return DISP_E_MEMBERNOTFOUND;
990 break;
992 default:
993 return DISP_E_MEMBERNOTFOUND;
996 VariantClear(&varg1);
997 VariantClear(&varg0);
999 return S_OK;
1002 static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
1004 AutomationObject *record;
1005 HRESULT hr;
1007 record = msi_alloc(sizeof(*record));
1008 if (!record) return E_OUTOFMEMORY;
1010 hr = init_automation_object(record, msiHandle, Record_tid);
1011 if (hr != S_OK)
1013 msi_free(record);
1014 return hr;
1017 *disp = &record->IDispatch_iface;
1019 return hr;
1022 static HRESULT list_invoke(
1023 AutomationObject* This,
1024 DISPID dispIdMember,
1025 REFIID riid,
1026 LCID lcid,
1027 WORD wFlags,
1028 DISPPARAMS* pDispParams,
1029 VARIANT* pVarResult,
1030 EXCEPINFO* pExcepInfo,
1031 UINT* puArgErr)
1033 ListObject *list = CONTAINING_RECORD(This, ListObject, autoobj);
1034 IUnknown *pUnk = NULL;
1035 HRESULT hr;
1037 switch (dispIdMember)
1039 case DISPID_LIST__NEWENUM:
1040 if (wFlags & DISPATCH_METHOD) {
1041 V_VT(pVarResult) = VT_UNKNOWN;
1042 if (SUCCEEDED(hr = create_list_enumerator(list, (LPVOID *)&pUnk)))
1043 V_UNKNOWN(pVarResult) = pUnk;
1044 else
1045 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr);
1047 else return DISP_E_MEMBERNOTFOUND;
1048 break;
1050 case DISPID_LIST_ITEM:
1051 if (wFlags & DISPATCH_PROPERTYGET) {
1052 VARIANTARG index;
1054 VariantInit(&index);
1055 hr = DispGetParam(pDispParams, 0, VT_I4, &index, puArgErr);
1056 if (FAILED(hr)) return hr;
1057 if (V_I4(&index) < 0 || V_I4(&index) >= list->count)
1058 return DISP_E_BADINDEX;
1059 VariantCopy(pVarResult, &list->data[V_I4(&index)]);
1061 else return DISP_E_MEMBERNOTFOUND;
1062 break;
1064 case DISPID_LIST_COUNT:
1065 if (wFlags & DISPATCH_PROPERTYGET) {
1066 V_VT(pVarResult) = VT_I4;
1067 V_I4(pVarResult) = list->count;
1069 else return DISP_E_MEMBERNOTFOUND;
1070 break;
1072 default:
1073 return DISP_E_MEMBERNOTFOUND;
1076 return S_OK;
1079 static void list_free(AutomationObject *This)
1081 ListObject *list = CONTAINING_RECORD(This, ListObject, autoobj);
1082 int i;
1084 for (i = 0; i < list->count; i++)
1085 VariantClear(&list->data[i]);
1086 msi_free(list->data);
1089 static HRESULT get_products_count(const WCHAR *product, int *len)
1091 int i = 0;
1093 while (1)
1095 WCHAR dataW[GUID_SIZE];
1096 UINT ret;
1098 /* all or related only */
1099 if (product)
1100 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1101 else
1102 ret = MsiEnumProductsW(i, dataW);
1104 if (ret == ERROR_NO_MORE_ITEMS) break;
1106 if (ret != ERROR_SUCCESS)
1107 return DISP_E_EXCEPTION;
1109 i++;
1112 *len = i;
1114 return S_OK;
1117 static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
1119 ListObject *list;
1120 HRESULT hr;
1121 int i;
1123 list = msi_alloc_zero(sizeof(ListObject));
1124 if (!list) return E_OUTOFMEMORY;
1126 hr = init_automation_object(&list->autoobj, 0, StringList_tid);
1127 if (hr != S_OK)
1129 msi_free(list);
1130 return hr;
1133 *dispatch = &list->autoobj.IDispatch_iface;
1135 hr = get_products_count(product, &list->count);
1136 if (hr != S_OK)
1138 IDispatch_Release(*dispatch);
1139 return hr;
1142 list->data = msi_alloc(list->count*sizeof(VARIANT));
1143 if (!list->data)
1145 IDispatch_Release(*dispatch);
1146 return E_OUTOFMEMORY;
1149 for (i = 0; i < list->count; i++)
1151 WCHAR dataW[GUID_SIZE];
1152 UINT ret;
1154 /* all or related only */
1155 if (product)
1156 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1157 else
1158 ret = MsiEnumProductsW(i, dataW);
1160 if (ret == ERROR_NO_MORE_ITEMS) break;
1162 V_VT(&list->data[i]) = VT_BSTR;
1163 V_BSTR(&list->data[i]) = SysAllocString(dataW);
1166 return S_OK;
1169 static HRESULT view_invoke(
1170 AutomationObject* This,
1171 DISPID dispIdMember,
1172 REFIID riid,
1173 LCID lcid,
1174 WORD wFlags,
1175 DISPPARAMS* pDispParams,
1176 VARIANT* pVarResult,
1177 EXCEPINFO* pExcepInfo,
1178 UINT* puArgErr)
1180 MSIHANDLE msiHandle;
1181 UINT ret;
1182 VARIANTARG varg0, varg1;
1183 HRESULT hr;
1185 VariantInit(&varg0);
1186 VariantInit(&varg1);
1188 switch (dispIdMember)
1190 case DISPID_VIEW_EXECUTE:
1191 if (wFlags & DISPATCH_METHOD)
1193 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &varg0, puArgErr);
1194 if (SUCCEEDED(hr) && V_DISPATCH(&varg0) != NULL)
1195 MsiViewExecute(This->msiHandle, ((AutomationObject *)V_DISPATCH(&varg0))->msiHandle);
1196 else
1197 MsiViewExecute(This->msiHandle, 0);
1199 else return DISP_E_MEMBERNOTFOUND;
1200 break;
1202 case DISPID_VIEW_FETCH:
1203 if (wFlags & DISPATCH_METHOD)
1205 V_VT(pVarResult) = VT_DISPATCH;
1206 if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS)
1208 if (FAILED(hr = create_record(msiHandle, &V_DISPATCH(pVarResult))))
1209 ERR("Failed to create Record object, hresult 0x%08x\n", hr);
1211 else if (ret == ERROR_NO_MORE_ITEMS)
1212 V_DISPATCH(pVarResult) = NULL;
1213 else
1215 ERR("MsiViewFetch returned %d\n", ret);
1216 return DISP_E_EXCEPTION;
1219 else return DISP_E_MEMBERNOTFOUND;
1220 break;
1222 case DISPID_VIEW_MODIFY:
1223 if (wFlags & DISPATCH_METHOD)
1225 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1226 if (FAILED(hr)) return hr;
1227 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1228 if (FAILED(hr)) return hr;
1229 if (!V_DISPATCH(&varg1)) return DISP_E_EXCEPTION;
1230 if ((ret = MsiViewModify(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle)) != ERROR_SUCCESS)
1232 VariantClear(&varg1);
1233 ERR("MsiViewModify returned %d\n", ret);
1234 return DISP_E_EXCEPTION;
1237 else return DISP_E_MEMBERNOTFOUND;
1238 break;
1240 case DISPID_VIEW_CLOSE:
1241 if (wFlags & DISPATCH_METHOD)
1243 MsiViewClose(This->msiHandle);
1245 else return DISP_E_MEMBERNOTFOUND;
1246 break;
1248 default:
1249 return DISP_E_MEMBERNOTFOUND;
1252 VariantClear(&varg1);
1253 VariantClear(&varg0);
1255 return S_OK;
1258 static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
1259 DISPPARAMS* pDispParams,
1260 VARIANT* pVarResult,
1261 EXCEPINFO* pExcepInfo,
1262 UINT* puArgErr)
1264 if (!(wFlags & DISPATCH_METHOD))
1265 return DISP_E_MEMBERNOTFOUND;
1267 FIXME("\n");
1269 VariantInit(pVarResult);
1270 return S_OK;
1273 HRESULT database_invoke(
1274 AutomationObject* This,
1275 DISPID dispIdMember,
1276 REFIID riid,
1277 LCID lcid,
1278 WORD wFlags,
1279 DISPPARAMS* pDispParams,
1280 VARIANT* pVarResult,
1281 EXCEPINFO* pExcepInfo,
1282 UINT* puArgErr)
1284 IDispatch *dispatch = NULL;
1285 MSIHANDLE msiHandle;
1286 UINT ret;
1287 VARIANTARG varg0, varg1;
1288 HRESULT hr;
1290 VariantInit(&varg0);
1291 VariantInit(&varg1);
1293 switch (dispIdMember)
1295 case DISPID_DATABASE_SUMMARYINFORMATION:
1296 if (wFlags & DISPATCH_PROPERTYGET)
1298 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1299 if (FAILED(hr))
1300 V_I4(&varg0) = 0;
1302 V_VT(pVarResult) = VT_DISPATCH;
1303 if ((ret = MsiGetSummaryInformationW(This->msiHandle, NULL, V_I4(&varg0), &msiHandle)) == ERROR_SUCCESS)
1305 hr = create_summaryinfo(msiHandle, &dispatch);
1306 if (SUCCEEDED(hr))
1307 V_DISPATCH(pVarResult) = dispatch;
1308 else
1309 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr);
1311 else
1313 ERR("MsiGetSummaryInformation returned %d\n", ret);
1314 return DISP_E_EXCEPTION;
1317 else return DISP_E_MEMBERNOTFOUND;
1318 break;
1320 case DISPID_DATABASE_OPENVIEW:
1321 if (wFlags & DISPATCH_METHOD)
1323 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1324 if (FAILED(hr)) return hr;
1325 V_VT(pVarResult) = VT_DISPATCH;
1326 if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS)
1328 if (SUCCEEDED(hr = create_view(msiHandle, &dispatch)))
1329 V_DISPATCH(pVarResult) = dispatch;
1330 else
1331 ERR("Failed to create View object, hresult 0x%08x\n", hr);
1333 else
1335 VariantClear(&varg0);
1336 ERR("MsiDatabaseOpenView returned %d\n", ret);
1337 return DISP_E_EXCEPTION;
1340 else return DISP_E_MEMBERNOTFOUND;
1341 break;
1343 case DISPID_INSTALLER_LASTERRORRECORD:
1344 return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
1345 pVarResult, pExcepInfo,
1346 puArgErr);
1348 default:
1349 return DISP_E_MEMBERNOTFOUND;
1352 VariantClear(&varg1);
1353 VariantClear(&varg0);
1355 return S_OK;
1358 static HRESULT session_invoke(
1359 AutomationObject* This,
1360 DISPID dispIdMember,
1361 REFIID riid,
1362 LCID lcid,
1363 WORD wFlags,
1364 DISPPARAMS* pDispParams,
1365 VARIANT* pVarResult,
1366 EXCEPINFO* pExcepInfo,
1367 UINT* puArgErr)
1369 SessionObject *session = CONTAINING_RECORD(This, SessionObject, autoobj);
1370 WCHAR *szString;
1371 DWORD dwLen = 0;
1372 MSIHANDLE msiHandle;
1373 LANGID langId;
1374 UINT ret;
1375 INSTALLSTATE iInstalled, iAction;
1376 VARIANTARG varg0, varg1;
1377 HRESULT hr;
1379 VariantInit(&varg0);
1380 VariantInit(&varg1);
1382 switch (dispIdMember)
1384 case DISPID_SESSION_INSTALLER:
1385 if (wFlags & DISPATCH_PROPERTYGET) {
1386 V_VT(pVarResult) = VT_DISPATCH;
1387 IDispatch_AddRef(session->installer);
1388 V_DISPATCH(pVarResult) = session->installer;
1390 else return DISP_E_MEMBERNOTFOUND;
1391 break;
1393 case DISPID_SESSION_PROPERTY:
1394 if (wFlags & DISPATCH_PROPERTYGET) {
1395 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1396 if (FAILED(hr)) return hr;
1397 V_VT(pVarResult) = VT_BSTR;
1398 V_BSTR(pVarResult) = NULL;
1399 if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
1401 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR))))
1402 ERR("Out of memory\n");
1403 else if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
1404 V_BSTR(pVarResult) = SysAllocString(szString);
1405 msi_free(szString);
1407 if (ret != ERROR_SUCCESS)
1408 ERR("MsiGetProperty returned %d\n", ret);
1409 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1410 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1411 if (FAILED(hr)) return hr;
1412 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1413 if (FAILED(hr)) {
1414 VariantClear(&varg0);
1415 return hr;
1417 if ((ret = MsiSetPropertyW(This->msiHandle, V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
1419 VariantClear(&varg0);
1420 VariantClear(&varg1);
1421 ERR("MsiSetProperty returned %d\n", ret);
1422 return DISP_E_EXCEPTION;
1425 else return DISP_E_MEMBERNOTFOUND;
1426 break;
1428 case DISPID_SESSION_LANGUAGE:
1429 if (wFlags & DISPATCH_PROPERTYGET) {
1430 langId = MsiGetLanguage(This->msiHandle);
1431 V_VT(pVarResult) = VT_I4;
1432 V_I4(pVarResult) = langId;
1434 else return DISP_E_MEMBERNOTFOUND;
1435 break;
1437 case DISPID_SESSION_MODE:
1438 if (wFlags & DISPATCH_PROPERTYGET) {
1439 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1440 if (FAILED(hr)) return hr;
1441 V_VT(pVarResult) = VT_BOOL;
1442 V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0)) ? VARIANT_TRUE : VARIANT_FALSE;
1443 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1444 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1445 if (FAILED(hr)) return hr;
1446 hr = DispGetParam(pDispParams, 1, VT_BOOL, &varg1, puArgErr);
1447 if (FAILED(hr)) return hr;
1448 if ((ret = MsiSetMode(This->msiHandle, V_I4(&varg0), V_BOOL(&varg1))) != ERROR_SUCCESS)
1450 ERR("MsiSetMode returned %d\n", ret);
1451 return DISP_E_EXCEPTION;
1454 else return DISP_E_MEMBERNOTFOUND;
1455 break;
1457 case DISPID_SESSION_DATABASE:
1458 if (wFlags & DISPATCH_PROPERTYGET) {
1459 V_VT(pVarResult) = VT_DISPATCH;
1460 if ((msiHandle = MsiGetActiveDatabase(This->msiHandle)))
1462 IDispatch *dispatch;
1464 if (SUCCEEDED(hr = create_database(msiHandle, &dispatch)))
1465 V_DISPATCH(pVarResult) = dispatch;
1466 else
1467 ERR("Failed to create Database object, hresult 0x%08x\n", hr);
1469 else
1471 ERR("MsiGetActiveDatabase failed\n");
1472 return DISP_E_EXCEPTION;
1475 else return DISP_E_MEMBERNOTFOUND;
1476 break;
1478 case DISPID_SESSION_DOACTION:
1479 if (wFlags & DISPATCH_METHOD) {
1480 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1481 if (FAILED(hr)) return hr;
1482 ret = MsiDoActionW(This->msiHandle, V_BSTR(&varg0));
1483 V_VT(pVarResult) = VT_I4;
1484 switch (ret)
1486 case ERROR_FUNCTION_NOT_CALLED:
1487 V_I4(pVarResult) = msiDoActionStatusNoAction;
1488 break;
1489 case ERROR_SUCCESS:
1490 V_I4(pVarResult) = msiDoActionStatusSuccess;
1491 break;
1492 case ERROR_INSTALL_USEREXIT:
1493 V_I4(pVarResult) = msiDoActionStatusUserExit;
1494 break;
1495 case ERROR_INSTALL_FAILURE:
1496 V_I4(pVarResult) = msiDoActionStatusFailure;
1497 break;
1498 case ERROR_INSTALL_SUSPEND:
1499 V_I4(pVarResult) = msiDoActionStatusSuspend;
1500 break;
1501 case ERROR_MORE_DATA:
1502 V_I4(pVarResult) = msiDoActionStatusFinished;
1503 break;
1504 case ERROR_INVALID_HANDLE_STATE:
1505 V_I4(pVarResult) = msiDoActionStatusWrongState;
1506 break;
1507 case ERROR_INVALID_DATA:
1508 V_I4(pVarResult) = msiDoActionStatusBadActionData;
1509 break;
1510 default:
1511 VariantClear(&varg0);
1512 FIXME("MsiDoAction returned unhandled value %d\n", ret);
1513 return DISP_E_EXCEPTION;
1516 else return DISP_E_MEMBERNOTFOUND;
1517 break;
1519 case DISPID_SESSION_EVALUATECONDITION:
1520 if (wFlags & DISPATCH_METHOD) {
1521 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1522 if (FAILED(hr)) return hr;
1523 V_VT(pVarResult) = VT_I4;
1524 V_I4(pVarResult) = MsiEvaluateConditionW(This->msiHandle, V_BSTR(&varg0));
1526 else return DISP_E_MEMBERNOTFOUND;
1527 break;
1529 case DISPID_SESSION_MESSAGE:
1530 if(!(wFlags & DISPATCH_METHOD))
1531 return DISP_E_MEMBERNOTFOUND;
1533 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1534 if (FAILED(hr)) return hr;
1535 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1536 if (FAILED(hr)) return hr;
1538 V_VT(pVarResult) = VT_I4;
1539 V_I4(pVarResult) =
1540 MsiProcessMessage(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle);
1541 break;
1543 case DISPID_SESSION_SETINSTALLLEVEL:
1544 if (wFlags & DISPATCH_METHOD) {
1545 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1546 if (FAILED(hr)) return hr;
1547 if ((ret = MsiSetInstallLevel(This->msiHandle, V_I4(&varg0))) != ERROR_SUCCESS)
1549 ERR("MsiSetInstallLevel returned %d\n", ret);
1550 return DISP_E_EXCEPTION;
1553 else return DISP_E_MEMBERNOTFOUND;
1554 break;
1556 case DISPID_SESSION_FEATURECURRENTSTATE:
1557 if (wFlags & DISPATCH_PROPERTYGET) {
1558 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1559 if (FAILED(hr)) return hr;
1560 V_VT(pVarResult) = VT_I4;
1561 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1562 V_I4(pVarResult) = iInstalled;
1563 else
1565 ERR("MsiGetFeatureState returned %d\n", ret);
1566 V_I4(pVarResult) = msiInstallStateUnknown;
1569 else return DISP_E_MEMBERNOTFOUND;
1570 break;
1572 case DISPID_SESSION_FEATUREREQUESTSTATE:
1573 if (wFlags & DISPATCH_PROPERTYGET) {
1574 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1575 if (FAILED(hr)) return hr;
1576 V_VT(pVarResult) = VT_I4;
1577 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1578 V_I4(pVarResult) = iAction;
1579 else
1581 ERR("MsiGetFeatureState returned %d\n", ret);
1582 V_I4(pVarResult) = msiInstallStateUnknown;
1584 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1585 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1586 if (FAILED(hr)) return hr;
1587 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1588 if (FAILED(hr)) {
1589 VariantClear(&varg0);
1590 return hr;
1592 if ((ret = MsiSetFeatureStateW(This->msiHandle, V_BSTR(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
1594 VariantClear(&varg0);
1595 ERR("MsiSetFeatureState returned %d\n", ret);
1596 return DISP_E_EXCEPTION;
1599 else return DISP_E_MEMBERNOTFOUND;
1600 break;
1602 default:
1603 return DISP_E_MEMBERNOTFOUND;
1606 VariantClear(&varg1);
1607 VariantClear(&varg0);
1609 return S_OK;
1612 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1613 * registry value type. Used by Installer::RegistryValue. */
1614 static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize)
1616 static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
1617 static const WCHAR szREG_[] = { '(','R','E','G','_','?','?',')',0 };
1618 WCHAR *szString = (WCHAR *)lpData;
1619 LPWSTR szNewString = NULL;
1620 DWORD dwNewSize = 0;
1621 int idx;
1623 switch (dwType)
1625 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1626 case REG_MULTI_SZ: /* Multi SZ change internal null characters to newlines */
1627 idx = (dwSize/sizeof(WCHAR))-1;
1628 while (idx >= 0 && !szString[idx]) idx--;
1629 for (; idx >= 0; idx--)
1630 if (!szString[idx]) szString[idx] = '\n';
1631 /* fall through */
1632 case REG_SZ:
1633 V_VT(pVarResult) = VT_BSTR;
1634 V_BSTR(pVarResult) = SysAllocStringByteLen((LPCSTR)szString, dwSize);
1635 break;
1637 case REG_EXPAND_SZ:
1638 if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1639 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1640 else if (!(szNewString = msi_alloc(dwNewSize * sizeof(WCHAR))))
1641 ERR("Out of memory\n");
1642 else if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1643 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
1644 else
1646 V_VT(pVarResult) = VT_BSTR;
1647 V_BSTR(pVarResult) = SysAllocStringLen(szNewString, dwNewSize);
1649 msi_free(szNewString);
1650 break;
1652 case REG_DWORD:
1653 V_VT(pVarResult) = VT_I4;
1654 V_I4(pVarResult) = *((DWORD *)lpData);
1655 break;
1657 case REG_QWORD:
1658 V_VT(pVarResult) = VT_BSTR;
1659 V_BSTR(pVarResult) = SysAllocString(szREG_); /* Weird string, don't know why native returns it */
1660 break;
1662 case REG_BINARY:
1663 V_VT(pVarResult) = VT_BSTR;
1664 V_BSTR(pVarResult) = SysAllocString(szREG_BINARY);
1665 break;
1667 case REG_NONE:
1668 V_VT(pVarResult) = VT_EMPTY;
1669 break;
1671 default:
1672 FIXME("Unhandled registry value type %d\n", dwType);
1676 static HRESULT InstallerImpl_CreateRecord(WORD wFlags,
1677 DISPPARAMS* pDispParams,
1678 VARIANT* pVarResult,
1679 EXCEPINFO* pExcepInfo,
1680 UINT* puArgErr)
1682 HRESULT hr;
1683 VARIANTARG varg0;
1684 MSIHANDLE hrec;
1686 if (!(wFlags & DISPATCH_METHOD))
1687 return DISP_E_MEMBERNOTFOUND;
1689 VariantInit(&varg0);
1690 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1691 if (FAILED(hr))
1692 return hr;
1694 V_VT(pVarResult) = VT_DISPATCH;
1696 hrec = MsiCreateRecord(V_I4(&varg0));
1697 if (!hrec)
1698 return DISP_E_EXCEPTION;
1700 return create_record(hrec, &V_DISPATCH(pVarResult));
1703 static HRESULT InstallerImpl_OpenPackage(AutomationObject* This,
1704 WORD wFlags,
1705 DISPPARAMS* pDispParams,
1706 VARIANT* pVarResult,
1707 EXCEPINFO* pExcepInfo,
1708 UINT* puArgErr)
1710 UINT ret;
1711 HRESULT hr;
1712 MSIHANDLE hpkg;
1713 IDispatch* dispatch;
1714 VARIANTARG varg0, varg1;
1716 if (!(wFlags & DISPATCH_METHOD))
1717 return DISP_E_MEMBERNOTFOUND;
1719 if (pDispParams->cArgs == 0)
1720 return DISP_E_TYPEMISMATCH;
1722 if (V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1]) != VT_BSTR)
1723 return DISP_E_TYPEMISMATCH;
1725 VariantInit(&varg0);
1726 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1727 if (FAILED(hr))
1728 return hr;
1730 VariantInit(&varg1);
1731 if (pDispParams->cArgs == 2)
1733 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1734 if (FAILED(hr))
1735 goto done;
1737 else
1739 V_VT(&varg1) = VT_I4;
1740 V_I4(&varg1) = 0;
1743 V_VT(pVarResult) = VT_DISPATCH;
1745 ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &hpkg);
1746 if (ret != ERROR_SUCCESS)
1748 hr = DISP_E_EXCEPTION;
1749 goto done;
1752 hr = create_session(hpkg, &This->IDispatch_iface, &dispatch);
1753 if (SUCCEEDED(hr))
1754 V_DISPATCH(pVarResult) = dispatch;
1756 done:
1757 VariantClear(&varg0);
1758 VariantClear(&varg1);
1759 return hr;
1762 static HRESULT InstallerImpl_OpenProduct(WORD wFlags,
1763 DISPPARAMS* pDispParams,
1764 VARIANT* pVarResult,
1765 EXCEPINFO* pExcepInfo,
1766 UINT* puArgErr)
1768 HRESULT hr;
1769 VARIANTARG varg0;
1771 if (!(wFlags & DISPATCH_METHOD))
1772 return DISP_E_MEMBERNOTFOUND;
1774 VariantInit(&varg0);
1775 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1776 if (FAILED(hr))
1777 return hr;
1779 FIXME("%s\n", debugstr_w(V_BSTR(&varg0)));
1781 VariantInit(pVarResult);
1783 VariantClear(&varg0);
1784 return S_OK;
1787 static HRESULT InstallerImpl_OpenDatabase(WORD wFlags,
1788 DISPPARAMS* pDispParams,
1789 VARIANT* pVarResult,
1790 EXCEPINFO* pExcepInfo,
1791 UINT* puArgErr)
1793 UINT ret;
1794 HRESULT hr;
1795 MSIHANDLE hdb;
1796 IDispatch* dispatch;
1797 VARIANTARG varg0, varg1;
1799 if (!(wFlags & DISPATCH_METHOD))
1800 return DISP_E_MEMBERNOTFOUND;
1802 VariantInit(&varg0);
1803 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1804 if (FAILED(hr))
1805 return hr;
1807 VariantInit(&varg1);
1808 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1809 if (FAILED(hr))
1810 goto done;
1812 V_VT(pVarResult) = VT_DISPATCH;
1814 ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &hdb);
1815 if (ret != ERROR_SUCCESS)
1817 hr = DISP_E_EXCEPTION;
1818 goto done;
1821 hr = create_database(hdb, &dispatch);
1822 if (SUCCEEDED(hr))
1823 V_DISPATCH(pVarResult) = dispatch;
1825 done:
1826 VariantClear(&varg0);
1827 VariantClear(&varg1);
1828 return hr;
1831 static HRESULT InstallerImpl_SummaryInformation(WORD wFlags,
1832 DISPPARAMS* pDispParams,
1833 VARIANT* pVarResult,
1834 EXCEPINFO* pExcepInfo,
1835 UINT* puArgErr)
1837 UINT ret;
1838 HRESULT hr;
1839 MSIHANDLE hsuminfo;
1840 IDispatch *dispatch;
1841 VARIANTARG varg0, varg1;
1843 if (!(wFlags & DISPATCH_PROPERTYGET))
1844 return DISP_E_MEMBERNOTFOUND;
1846 VariantInit(&varg1);
1847 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1848 if (FAILED(hr))
1849 return hr;
1851 VariantInit(&varg0);
1852 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1853 if (FAILED(hr))
1854 return hr;
1856 ret = MsiGetSummaryInformationW(0, V_BSTR(&varg0), V_I4(&varg1), &hsuminfo);
1857 VariantClear(&varg0);
1858 if (ret != ERROR_SUCCESS)
1859 return DISP_E_EXCEPTION;
1861 hr = create_summaryinfo(hsuminfo, &dispatch);
1862 if (FAILED(hr))
1863 return hr;
1865 V_VT(pVarResult) = VT_DISPATCH;
1866 V_DISPATCH(pVarResult) = dispatch;
1867 return S_OK;
1870 static HRESULT InstallerImpl_UILevel(WORD wFlags,
1871 DISPPARAMS* pDispParams,
1872 VARIANT* pVarResult,
1873 EXCEPINFO* pExcepInfo,
1874 UINT* puArgErr)
1876 HRESULT hr;
1877 VARIANTARG varg0;
1878 INSTALLUILEVEL ui;
1880 if (!(wFlags & DISPATCH_PROPERTYPUT) && !(wFlags & DISPATCH_PROPERTYGET))
1881 return DISP_E_MEMBERNOTFOUND;
1883 if (wFlags & DISPATCH_PROPERTYPUT)
1885 VariantInit(&varg0);
1886 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1887 if (FAILED(hr))
1888 return hr;
1890 ui = MsiSetInternalUI(V_I4(&varg0), NULL);
1891 if (ui == INSTALLUILEVEL_NOCHANGE)
1892 return DISP_E_EXCEPTION;
1894 else if (wFlags & DISPATCH_PROPERTYGET)
1896 ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
1897 if (ui == INSTALLUILEVEL_NOCHANGE)
1898 return DISP_E_EXCEPTION;
1900 V_VT(pVarResult) = VT_I4;
1901 V_I4(pVarResult) = ui;
1904 return S_OK;
1907 static HRESULT InstallerImpl_EnableLog(WORD wFlags,
1908 DISPPARAMS* pDispParams,
1909 VARIANT* pVarResult,
1910 EXCEPINFO* pExcepInfo,
1911 UINT* puArgErr)
1913 if (!(wFlags & DISPATCH_METHOD))
1914 return DISP_E_MEMBERNOTFOUND;
1916 FIXME("\n");
1918 VariantInit(pVarResult);
1919 return S_OK;
1922 static HRESULT InstallerImpl_InstallProduct(WORD wFlags,
1923 DISPPARAMS* pDispParams,
1924 VARIANT* pVarResult,
1925 EXCEPINFO* pExcepInfo,
1926 UINT* puArgErr)
1928 UINT ret;
1929 HRESULT hr;
1930 VARIANTARG varg0, varg1;
1932 if (!(wFlags & DISPATCH_METHOD))
1933 return DISP_E_MEMBERNOTFOUND;
1935 VariantInit(&varg0);
1936 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1937 if (FAILED(hr))
1938 return hr;
1940 VariantInit(&varg1);
1941 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1942 if (FAILED(hr))
1943 goto done;
1945 ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1));
1946 if (ret != ERROR_SUCCESS)
1948 hr = DISP_E_EXCEPTION;
1949 goto done;
1952 done:
1953 VariantClear(&varg0);
1954 VariantClear(&varg1);
1955 return hr;
1958 static HRESULT InstallerImpl_Version(WORD wFlags,
1959 VARIANT* pVarResult,
1960 EXCEPINFO* pExcepInfo,
1961 UINT* puArgErr)
1963 HRESULT hr;
1964 DLLVERSIONINFO verinfo;
1965 WCHAR version[MAX_PATH];
1967 static const WCHAR format[] = {
1968 '%','d','.','%','d','.','%','d','.','%','d',0};
1970 if (!(wFlags & DISPATCH_PROPERTYGET))
1971 return DISP_E_MEMBERNOTFOUND;
1973 verinfo.cbSize = sizeof(DLLVERSIONINFO);
1974 hr = DllGetVersion(&verinfo);
1975 if (FAILED(hr))
1976 return hr;
1978 swprintf(version, ARRAY_SIZE(version), format, verinfo.dwMajorVersion, verinfo.dwMinorVersion,
1979 verinfo.dwBuildNumber, verinfo.dwPlatformID);
1981 V_VT(pVarResult) = VT_BSTR;
1982 V_BSTR(pVarResult) = SysAllocString(version);
1983 return S_OK;
1986 static HRESULT InstallerImpl_LastErrorRecord(WORD wFlags,
1987 DISPPARAMS* pDispParams,
1988 VARIANT* pVarResult,
1989 EXCEPINFO* pExcepInfo,
1990 UINT* puArgErr)
1992 if (!(wFlags & DISPATCH_METHOD))
1993 return DISP_E_MEMBERNOTFOUND;
1995 FIXME("\n");
1997 VariantInit(pVarResult);
1998 return S_OK;
2001 static HRESULT InstallerImpl_RegistryValue(WORD wFlags,
2002 DISPPARAMS* pDispParams,
2003 VARIANT* pVarResult,
2004 EXCEPINFO* pExcepInfo,
2005 UINT* puArgErr)
2007 UINT ret;
2008 HKEY hkey = NULL;
2009 HRESULT hr;
2010 UINT posValue;
2011 DWORD type, size;
2012 LPWSTR szString = NULL;
2013 VARIANTARG varg0, varg1, varg2;
2015 if (!(wFlags & DISPATCH_METHOD))
2016 return DISP_E_MEMBERNOTFOUND;
2018 VariantInit(&varg0);
2019 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
2020 if (FAILED(hr))
2021 return hr;
2023 VariantInit(&varg1);
2024 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
2025 if (FAILED(hr))
2026 goto done;
2028 /* Save valuePos so we can save puArgErr if we are unable to do our type
2029 * conversions.
2031 posValue = 2;
2032 VariantInit(&varg2);
2033 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2);
2034 if (FAILED(hr))
2035 goto done;
2037 if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT &&
2038 V_I4(&varg0) <= REG_INDEX_DYN_DATA)
2040 V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT;
2043 ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey);
2045 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2046 if (ret != ERROR_SUCCESS && V_VT(&varg2) != VT_EMPTY)
2048 hr = DISP_E_BADINDEX;
2049 goto done;
2052 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2053 switch (V_VT(&varg2))
2055 /* Return VT_BOOL clarifying whether registry key exists or not. */
2056 case VT_EMPTY:
2057 V_VT(pVarResult) = VT_BOOL;
2058 V_BOOL(pVarResult) = (ret == ERROR_SUCCESS) ? VARIANT_TRUE : VARIANT_FALSE;
2059 break;
2061 /* Return the value of specified key if it exists. */
2062 case VT_BSTR:
2063 ret = RegQueryValueExW(hkey, V_BSTR(&varg2),
2064 NULL, NULL, NULL, &size);
2065 if (ret != ERROR_SUCCESS)
2067 hr = DISP_E_BADINDEX;
2068 goto done;
2071 szString = msi_alloc(size);
2072 if (!szString)
2074 hr = E_OUTOFMEMORY;
2075 goto done;
2078 ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL,
2079 &type, (LPBYTE)szString, &size);
2080 if (ret != ERROR_SUCCESS)
2082 msi_free(szString);
2083 hr = DISP_E_BADINDEX;
2084 goto done;
2087 variant_from_registry_value(pVarResult, type,
2088 (LPBYTE)szString, size);
2089 msi_free(szString);
2090 break;
2092 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2093 default:
2094 hr = VariantChangeType(&varg2, &varg2, 0, VT_I4);
2095 if (FAILED(hr))
2097 if (hr == DISP_E_TYPEMISMATCH)
2098 *puArgErr = posValue;
2100 goto done;
2103 /* Retrieve class name or maximum value name or subkey name size. */
2104 if (!V_I4(&varg2))
2105 ret = RegQueryInfoKeyW(hkey, NULL, &size, NULL, NULL, NULL,
2106 NULL, NULL, NULL, NULL, NULL, NULL);
2107 else if (V_I4(&varg2) > 0)
2108 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL,
2109 NULL, NULL, &size, NULL, NULL, NULL);
2110 else /* V_I4(&varg2) < 0 */
2111 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &size,
2112 NULL, NULL, NULL, NULL, NULL, NULL);
2114 if (ret != ERROR_SUCCESS)
2115 goto done;
2117 szString = msi_alloc(++size * sizeof(WCHAR));
2118 if (!szString)
2120 hr = E_OUTOFMEMORY;
2121 goto done;
2124 if (!V_I4(&varg2))
2125 ret = RegQueryInfoKeyW(hkey, szString, &size,NULL, NULL, NULL,
2126 NULL, NULL, NULL, NULL, NULL, NULL);
2127 else if (V_I4(&varg2) > 0)
2128 ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString,
2129 &size, 0, 0, NULL, NULL);
2130 else /* V_I4(&varg2) < 0 */
2131 ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, size);
2133 if (ret == ERROR_SUCCESS)
2135 V_VT(pVarResult) = VT_BSTR;
2136 V_BSTR(pVarResult) = SysAllocString(szString);
2139 msi_free(szString);
2142 done:
2143 VariantClear(&varg0);
2144 VariantClear(&varg1);
2145 VariantClear(&varg2);
2146 RegCloseKey(hkey);
2147 return hr;
2150 static HRESULT InstallerImpl_Environment(WORD wFlags,
2151 DISPPARAMS* pDispParams,
2152 VARIANT* pVarResult,
2153 EXCEPINFO* pExcepInfo,
2154 UINT* puArgErr)
2156 if (!(wFlags & DISPATCH_METHOD))
2157 return DISP_E_MEMBERNOTFOUND;
2159 FIXME("\n");
2161 VariantInit(pVarResult);
2162 return S_OK;
2165 static HRESULT InstallerImpl_FileAttributes(WORD wFlags,
2166 DISPPARAMS* pDispParams,
2167 VARIANT* pVarResult,
2168 EXCEPINFO* pExcepInfo,
2169 UINT* puArgErr)
2171 if (!(wFlags & DISPATCH_METHOD))
2172 return DISP_E_MEMBERNOTFOUND;
2174 FIXME("\n");
2176 VariantInit(pVarResult);
2177 return S_OK;
2180 static HRESULT InstallerImpl_FileSize(WORD wFlags,
2181 DISPPARAMS* pDispParams,
2182 VARIANT* pVarResult,
2183 EXCEPINFO* pExcepInfo,
2184 UINT* puArgErr)
2186 if (!(wFlags & DISPATCH_METHOD))
2187 return DISP_E_MEMBERNOTFOUND;
2189 FIXME("\n");
2191 VariantInit(pVarResult);
2192 return S_OK;
2195 static HRESULT InstallerImpl_FileVersion(WORD wFlags,
2196 DISPPARAMS* pDispParams,
2197 VARIANT* pVarResult,
2198 EXCEPINFO* pExcepInfo,
2199 UINT* puArgErr)
2201 if (!(wFlags & DISPATCH_METHOD))
2202 return DISP_E_MEMBERNOTFOUND;
2204 FIXME("\n");
2206 VariantInit(pVarResult);
2207 return S_OK;
2210 static HRESULT InstallerImpl_ProductState(WORD wFlags,
2211 DISPPARAMS* pDispParams,
2212 VARIANT* pVarResult,
2213 EXCEPINFO* pExcepInfo,
2214 UINT* puArgErr)
2216 HRESULT hr;
2217 VARIANTARG varg0;
2219 if (!(wFlags & DISPATCH_PROPERTYGET))
2220 return DISP_E_MEMBERNOTFOUND;
2222 VariantInit(&varg0);
2223 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2224 if (FAILED(hr))
2225 return hr;
2227 V_VT(pVarResult) = VT_I4;
2228 V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0));
2230 VariantClear(&varg0);
2231 return S_OK;
2234 static HRESULT InstallerImpl_ProductInfo(WORD wFlags,
2235 DISPPARAMS* pDispParams,
2236 VARIANT* pVarResult,
2237 EXCEPINFO* pExcepInfo,
2238 UINT* puArgErr)
2240 UINT ret;
2241 HRESULT hr;
2242 DWORD size;
2243 LPWSTR str = NULL;
2244 VARIANTARG varg0, varg1;
2246 if (!(wFlags & DISPATCH_PROPERTYGET))
2247 return DISP_E_MEMBERNOTFOUND;
2249 VariantInit(&varg0);
2250 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2251 if (FAILED(hr))
2252 return hr;
2254 VariantInit(&varg1);
2255 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
2256 if (FAILED(hr))
2257 goto done;
2259 V_VT(pVarResult) = VT_BSTR;
2260 V_BSTR(pVarResult) = NULL;
2262 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &size);
2263 if (ret != ERROR_SUCCESS)
2265 hr = DISP_E_EXCEPTION;
2266 goto done;
2269 str = msi_alloc(++size * sizeof(WCHAR));
2270 if (!str)
2272 hr = E_OUTOFMEMORY;
2273 goto done;
2276 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), str, &size);
2277 if (ret != ERROR_SUCCESS)
2279 hr = DISP_E_EXCEPTION;
2280 goto done;
2283 V_BSTR(pVarResult) = SysAllocString(str);
2284 hr = S_OK;
2286 done:
2287 msi_free(str);
2288 VariantClear(&varg0);
2289 VariantClear(&varg1);
2290 return hr;
2293 static HRESULT InstallerImpl_Products(WORD flags,
2294 DISPPARAMS* pDispParams,
2295 VARIANT* result,
2296 EXCEPINFO* pExcepInfo,
2297 UINT* puArgErr)
2299 IDispatch *dispatch;
2300 HRESULT hr;
2302 if (!(flags & DISPATCH_PROPERTYGET))
2303 return DISP_E_MEMBERNOTFOUND;
2305 hr = create_list(NULL, &dispatch);
2306 if (FAILED(hr))
2307 return hr;
2309 V_VT(result) = VT_DISPATCH;
2310 V_DISPATCH(result) = dispatch;
2312 return hr;
2315 static HRESULT InstallerImpl_RelatedProducts(WORD flags,
2316 DISPPARAMS* pDispParams,
2317 VARIANT* result,
2318 EXCEPINFO* pExcepInfo,
2319 UINT* puArgErr)
2321 IDispatch* dispatch;
2322 VARIANTARG related;
2323 HRESULT hr;
2325 if (!(flags & DISPATCH_PROPERTYGET))
2326 return DISP_E_MEMBERNOTFOUND;
2328 VariantInit(&related);
2329 hr = DispGetParam(pDispParams, 0, VT_BSTR, &related, puArgErr);
2330 if (FAILED(hr))
2331 return hr;
2333 hr = create_list(V_BSTR(&related), &dispatch);
2334 VariantClear(&related);
2336 V_VT(result) = VT_DISPATCH;
2337 V_DISPATCH(result) = dispatch;
2339 return hr;
2342 static HRESULT installer_invoke(
2343 AutomationObject* This,
2344 DISPID dispIdMember,
2345 REFIID riid,
2346 LCID lcid,
2347 WORD wFlags,
2348 DISPPARAMS* pDispParams,
2349 VARIANT* pVarResult,
2350 EXCEPINFO* pExcepInfo,
2351 UINT* puArgErr)
2353 switch (dispIdMember)
2355 case DISPID_INSTALLER_CREATERECORD:
2356 return InstallerImpl_CreateRecord(wFlags, pDispParams,
2357 pVarResult, pExcepInfo, puArgErr);
2359 case DISPID_INSTALLER_OPENPACKAGE:
2360 return InstallerImpl_OpenPackage(This, wFlags, pDispParams,
2361 pVarResult, pExcepInfo, puArgErr);
2363 case DISPID_INSTALLER_OPENPRODUCT:
2364 return InstallerImpl_OpenProduct(wFlags, pDispParams,
2365 pVarResult, pExcepInfo, puArgErr);
2367 case DISPID_INSTALLER_OPENDATABASE:
2368 return InstallerImpl_OpenDatabase(wFlags, pDispParams,
2369 pVarResult, pExcepInfo, puArgErr);
2371 case DISPID_INSTALLER_SUMMARYINFORMATION:
2372 return InstallerImpl_SummaryInformation(wFlags, pDispParams,
2373 pVarResult, pExcepInfo,
2374 puArgErr);
2376 case DISPID_INSTALLER_UILEVEL:
2377 return InstallerImpl_UILevel(wFlags, pDispParams,
2378 pVarResult, pExcepInfo, puArgErr);
2380 case DISPID_INSTALLER_ENABLELOG:
2381 return InstallerImpl_EnableLog(wFlags, pDispParams,
2382 pVarResult, pExcepInfo, puArgErr);
2384 case DISPID_INSTALLER_INSTALLPRODUCT:
2385 return InstallerImpl_InstallProduct(wFlags, pDispParams,
2386 pVarResult, pExcepInfo,
2387 puArgErr);
2389 case DISPID_INSTALLER_VERSION:
2390 return InstallerImpl_Version(wFlags, pVarResult,
2391 pExcepInfo, puArgErr);
2393 case DISPID_INSTALLER_LASTERRORRECORD:
2394 return InstallerImpl_LastErrorRecord(wFlags, pDispParams,
2395 pVarResult, pExcepInfo,
2396 puArgErr);
2398 case DISPID_INSTALLER_REGISTRYVALUE:
2399 return InstallerImpl_RegistryValue(wFlags, pDispParams,
2400 pVarResult, pExcepInfo,
2401 puArgErr);
2403 case DISPID_INSTALLER_ENVIRONMENT:
2404 return InstallerImpl_Environment(wFlags, pDispParams,
2405 pVarResult, pExcepInfo, puArgErr);
2407 case DISPID_INSTALLER_FILEATTRIBUTES:
2408 return InstallerImpl_FileAttributes(wFlags, pDispParams,
2409 pVarResult, pExcepInfo,
2410 puArgErr);
2412 case DISPID_INSTALLER_FILESIZE:
2413 return InstallerImpl_FileSize(wFlags, pDispParams,
2414 pVarResult, pExcepInfo, puArgErr);
2416 case DISPID_INSTALLER_FILEVERSION:
2417 return InstallerImpl_FileVersion(wFlags, pDispParams,
2418 pVarResult, pExcepInfo, puArgErr);
2420 case DISPID_INSTALLER_PRODUCTSTATE:
2421 return InstallerImpl_ProductState(wFlags, pDispParams,
2422 pVarResult, pExcepInfo, puArgErr);
2424 case DISPID_INSTALLER_PRODUCTINFO:
2425 return InstallerImpl_ProductInfo(wFlags, pDispParams,
2426 pVarResult, pExcepInfo, puArgErr);
2428 case DISPID_INSTALLER_PRODUCTS:
2429 return InstallerImpl_Products(wFlags, pDispParams,
2430 pVarResult, pExcepInfo, puArgErr);
2432 case DISPID_INSTALLER_RELATEDPRODUCTS:
2433 return InstallerImpl_RelatedProducts(wFlags, pDispParams,
2434 pVarResult, pExcepInfo,
2435 puArgErr);
2437 default:
2438 return DISP_E_MEMBERNOTFOUND;
2442 HRESULT create_msiserver(IUnknown *outer, void **ppObj)
2444 AutomationObject *installer;
2445 HRESULT hr;
2447 TRACE("(%p %p)\n", outer, ppObj);
2449 if (outer)
2450 return CLASS_E_NOAGGREGATION;
2452 installer = msi_alloc(sizeof(AutomationObject));
2453 if (!installer) return E_OUTOFMEMORY;
2455 hr = init_automation_object(installer, 0, Installer_tid);
2456 if (hr != S_OK)
2458 msi_free(installer);
2459 return hr;
2462 *ppObj = &installer->IDispatch_iface;
2464 return hr;
2467 HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **disp)
2469 SessionObject *session;
2470 HRESULT hr;
2472 session = msi_alloc(sizeof(SessionObject));
2473 if (!session) return E_OUTOFMEMORY;
2475 hr = init_automation_object(&session->autoobj, msiHandle, Session_tid);
2476 if (hr != S_OK)
2478 msi_free(session);
2479 return hr;
2482 session->installer = installer;
2483 *disp = &session->autoobj.IDispatch_iface;
2485 return hr;
2488 static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
2490 AutomationObject *database;
2491 HRESULT hr;
2493 TRACE("(%d %p)\n", msiHandle, dispatch);
2495 database = msi_alloc(sizeof(AutomationObject));
2496 if (!database) return E_OUTOFMEMORY;
2498 hr = init_automation_object(database, msiHandle, Database_tid);
2499 if (hr != S_OK)
2501 msi_free(database);
2502 return hr;
2505 *dispatch = &database->IDispatch_iface;
2507 return hr;
2510 static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch)
2512 AutomationObject *view;
2513 HRESULT hr;
2515 TRACE("(%d %p)\n", msiHandle, dispatch);
2517 view = msi_alloc(sizeof(AutomationObject));
2518 if (!view) return E_OUTOFMEMORY;
2520 hr = init_automation_object(view, msiHandle, View_tid);
2521 if (hr != S_OK)
2523 msi_free(view);
2524 return hr;
2527 *dispatch = &view->IDispatch_iface;
2529 return hr;
2532 static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp)
2534 AutomationObject *info;
2535 HRESULT hr;
2537 info = msi_alloc(sizeof(*info));
2538 if (!info) return E_OUTOFMEMORY;
2540 hr = init_automation_object(info, msiHandle, SummaryInfo_tid);
2541 if (hr != S_OK)
2543 msi_free(info);
2544 return hr;
2547 *disp = &info->IDispatch_iface;
2549 return hr;