1 /*
2 * Implementation of OLE Automation for Microsoft Installer (msi.dll)
3 *
4 * Copyright 2007 Misha Koshelev
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define COBJMACROS
22
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
36 #include "msiserver.h"
37 #include "msiserver_dispids.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(msi);
40
41 #define REG_INDEX_CLASSES_ROOT 0
42 #define REG_INDEX_DYN_DATA 6
43
44 struct automation_object;
45
46 struct tid_id
47 {
48 REFIID riid;
49 /* function that is called from AutomationObject::Invoke, specific to this type of object */
50 HRESULT (*fn_invoke)(struct automation_object *, DISPID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *,
51 EXCEPINFO *, UINT *);
52 /* function that is called from AutomationObject::Release when the object is being freed
53 to free any private data structures (or NULL) */
54 void (*fn_free)(struct automation_object *);
55 };
56
57 static HRESULT database_invoke(struct automation_object*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
58 static HRESULT installer_invoke(struct automation_object*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
59 static HRESULT record_invoke(struct automation_object*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
60 static HRESULT session_invoke(struct automation_object*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
61 static HRESULT list_invoke(struct automation_object*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
62 static void list_free(struct automation_object*);
63 static HRESULT summaryinfo_invoke(struct automation_object*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
64 static HRESULT view_invoke(struct automation_object*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
65
66 static struct tid_id tid_ids[] =
67 {
68 { &DIID_Database, database_invoke },
69 { &DIID_Installer, installer_invoke },
70 { &DIID_Record, record_invoke },
71 { &DIID_Session, session_invoke },
72 { &DIID_StringList, list_invoke, list_free },
73 { &DIID_SummaryInfo, summaryinfo_invoke },
74 { &DIID_View, view_invoke }
75 };
76
77 static ITypeLib *typelib;
78 static ITypeInfo *typeinfos[LAST_tid];
79
get_riid_from_tid(tid_t tid)80 static const IID *get_riid_from_tid(tid_t tid)
81 {
82 return tid_ids[tid].riid;
83 }
84
get_typeinfo(tid_t tid,ITypeInfo ** typeinfo)85 HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
86 {
87 HRESULT hr;
88
89 if (!typelib)
90 {
91 ITypeLib *lib;
92
93 hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, LOCALE_NEUTRAL, &lib);
94 if (FAILED(hr)) {
95 hr = LoadTypeLib(L"msiserver.tlb", &lib);
96 if (FAILED(hr)) {
97 ERR("Could not load msiserver.tlb\n");
98 return hr;
99 }
100 }
101
102 if (InterlockedCompareExchangePointer((void**)&typelib, lib, NULL))
103 ITypeLib_Release(lib);
104 }
105
106 if (!typeinfos[tid])
107 {
108 ITypeInfo *ti;
109
110 hr = ITypeLib_GetTypeInfoOfGuid(typelib, get_riid_from_tid(tid), &ti);
111 if (FAILED(hr)) {
112 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(get_riid_from_tid(tid)));
113 return hr;
114 }
115
116 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
117 ITypeInfo_Release(ti);
118 }
119
120 *typeinfo = typeinfos[tid];
121 return S_OK;
122 }
123
release_typelib(void)124 void release_typelib(void)
125 {
126 unsigned i;
127
128 for (i = 0; i < ARRAY_SIZE(typeinfos); i++)
129 if (typeinfos[i])
130 ITypeInfo_Release(typeinfos[i]);
131
132 if (typelib)
133 ITypeLib_Release(typelib);
134 }
135
136 /*
137 * struct automation_object - "base" class for all automation objects. For each interface, we implement Invoke
138 * function called from AutomationObject::Invoke.
139 */
140 struct automation_object
141 {
142 IDispatch IDispatch_iface;
143 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface;
144 LONG ref;
145
146 /* type id for this class */
147 tid_t tid;
148
149 /* The MSI handle of the current object */
150 MSIHANDLE msiHandle;
151 };
152
153 struct list_object
154 {
155 struct automation_object autoobj;
156 int count;
157 VARIANT *data;
158 };
159
160 static HRESULT create_database(MSIHANDLE, IDispatch**);
161 static HRESULT create_list_enumerator(struct list_object *, void **);
162 static HRESULT create_summaryinfo(MSIHANDLE, IDispatch**);
163 static HRESULT create_view(MSIHANDLE, IDispatch**);
164
165 /* struct list_enumerator - IEnumVARIANT implementation for MSI automation lists */
166 struct list_enumerator
167 {
168 IEnumVARIANT IEnumVARIANT_iface;
169 LONG ref;
170
171 /* Current position and pointer to struct automation_object that stores actual data */
172 ULONG pos;
173 struct list_object *list;
174 };
175
176 struct session_object
177 {
178 struct automation_object autoobj;
179 IDispatch *installer;
180 };
181
impl_from_IProvideMultipleClassInfo(IProvideMultipleClassInfo * iface)182 static inline struct automation_object *impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo *iface )
183 {
184 return CONTAINING_RECORD(iface, struct automation_object, IProvideMultipleClassInfo_iface);
185 }
186
impl_from_IDispatch(IDispatch * iface)187 static inline struct automation_object *impl_from_IDispatch( IDispatch *iface )
188 {
189 return CONTAINING_RECORD(iface, struct automation_object, IDispatch_iface);
190 }
191
192 /* AutomationObject methods */
AutomationObject_QueryInterface(IDispatch * iface,REFIID riid,void ** ppvObject)193 static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject)
194 {
195 struct automation_object *This = impl_from_IDispatch(iface);
196
197 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
198
199 if (ppvObject == NULL)
200 return E_INVALIDARG;
201
202 *ppvObject = 0;
203
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
213 {
214 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid));
215 return E_NOINTERFACE;
216 }
217
218 IDispatch_AddRef(iface);
219
220 return S_OK;
221 }
222
AutomationObject_AddRef(IDispatch * iface)223 static ULONG WINAPI AutomationObject_AddRef(IDispatch* iface)
224 {
225 struct automation_object *This = impl_from_IDispatch(iface);
226
227 TRACE("(%p/%p)\n", iface, This);
228
229 return InterlockedIncrement(&This->ref);
230 }
231
AutomationObject_Release(IDispatch * iface)232 static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
233 {
234 struct automation_object *This = impl_from_IDispatch(iface);
235 ULONG ref = InterlockedDecrement(&This->ref);
236
237 TRACE("(%p/%p)\n", iface, This);
238
239 if (!ref)
240 {
241 if (tid_ids[This->tid].fn_free) tid_ids[This->tid].fn_free(This);
242 MsiCloseHandle(This->msiHandle);
243 free(This);
244 }
245
246 return ref;
247 }
248
AutomationObject_GetTypeInfoCount(IDispatch * iface,UINT * pctinfo)249 static HRESULT WINAPI AutomationObject_GetTypeInfoCount(
250 IDispatch* iface,
251 UINT* pctinfo)
252 {
253 struct automation_object *This = impl_from_IDispatch(iface);
254
255 TRACE("(%p/%p)->(%p)\n", iface, This, pctinfo);
256 *pctinfo = 1;
257 return S_OK;
258 }
259
AutomationObject_GetTypeInfo(IDispatch * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)260 static HRESULT WINAPI AutomationObject_GetTypeInfo(
261 IDispatch* iface,
262 UINT iTInfo,
263 LCID lcid,
264 ITypeInfo** ppTInfo)
265 {
266 struct automation_object *This = impl_from_IDispatch(iface);
267 HRESULT hr;
268
269 TRACE( "(%p/%p)->(%u, %ld, %p)\n", iface, This, iTInfo, lcid, ppTInfo );
270
271 hr = get_typeinfo(This->tid, ppTInfo);
272 if (FAILED(hr))
273 return hr;
274
275 ITypeInfo_AddRef(*ppTInfo);
276 return hr;
277 }
278
AutomationObject_GetIDsOfNames(IDispatch * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)279 static HRESULT WINAPI AutomationObject_GetIDsOfNames(
280 IDispatch* iface,
281 REFIID riid,
282 LPOLESTR* rgszNames,
283 UINT cNames,
284 LCID lcid,
285 DISPID* rgDispId)
286 {
287 struct automation_object *This = impl_from_IDispatch(iface);
288 ITypeInfo *ti;
289 HRESULT hr;
290
291 TRACE("(%p/%p)->(%s, %p, %u, %ld, %p)\n", iface, This,
292 debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
293
294 if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG;
295
296 hr = get_typeinfo(This->tid, &ti);
297 if (FAILED(hr))
298 return hr;
299
300 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
301 if (hr == DISP_E_UNKNOWNNAME)
302 {
303 UINT idx;
304 for (idx=0; idx<cNames; idx++)
305 {
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)));
308 }
309 }
310 return hr;
311 }
312
313 /* Maximum number of allowed function parameters+1 */
314 #define MAX_FUNC_PARAMS 20
315
316 /* Some error checking is done here to simplify individual object function invocation */
AutomationObject_Invoke(IDispatch * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)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)
327 {
328 struct automation_object *This = impl_from_IDispatch(iface);
329 HRESULT hr;
330 unsigned int uArgErr;
331 VARIANT varResultDummy;
332 BSTR bstrName = NULL;
333 ITypeInfo *ti;
334
335 TRACE("(%p/%p)->(%ld, %s, %ld, %d, %p, %p, %p, %p)\n", iface, This,
336 dispIdMember, debugstr_guid(riid), lcid, wFlags,
337 pDispParams, pVarResult, pExcepInfo, puArgErr);
338
339 if (!IsEqualIID(riid, &IID_NULL))
340 {
341 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
342 return DISP_E_UNKNOWNNAME;
343 }
344
345 if (wFlags & DISPATCH_PROPERTYGET && !pVarResult)
346 {
347 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
348 return DISP_E_PARAMNOTOPTIONAL;
349 }
350
351 /* This simplifies our individual object invocation functions */
352 if (puArgErr == NULL) puArgErr = &uArgErr;
353 if (pVarResult == NULL) pVarResult = &varResultDummy;
354
355 hr = get_typeinfo(This->tid, &ti);
356 if (FAILED(hr))
357 return hr;
358
359 /* Assume return type is void unless determined otherwise */
360 VariantInit(pVarResult);
361
362 /* If we are tracing, we want to see the name of the member we are invoking */
363 if (TRACE_ON(msi))
364 {
365 ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL);
366 TRACE("method %ld, %s\n", dispIdMember, debugstr_w(bstrName));
367 }
368
369 hr = tid_ids[This->tid].fn_invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
370
371 if (hr == DISP_E_MEMBERNOTFOUND) {
372 if (bstrName == NULL) ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL);
373 FIXME("method %ld, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags,
374 debugstr_guid(get_riid_from_tid(This->tid)));
375 }
376 else if (pExcepInfo &&
377 (hr == DISP_E_PARAMNOTFOUND ||
378 hr == DISP_E_EXCEPTION)) {
379 WCHAR szExceptionDescription[MAX_PATH];
380 BSTR bstrParamNames[MAX_FUNC_PARAMS];
381 unsigned namesNo, i;
382 BOOL bFirst = TRUE;
383
384 if (FAILED(ITypeInfo_GetNames(ti, dispIdMember, bstrParamNames,
385 MAX_FUNC_PARAMS, &namesNo)))
386 {
387 TRACE("failed to retrieve names for dispIdMember %ld\n", dispIdMember);
388 }
389 else
390 {
391 memset(szExceptionDescription, 0, sizeof(szExceptionDescription));
392 for (i=0; i<namesNo; i++)
393 {
394 if (bFirst) bFirst = FALSE;
395 else {
396 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], L",");
397 }
398 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], bstrParamNames[i]);
399 SysFreeString(bstrParamNames[i]);
400 }
401
402 memset(pExcepInfo, 0, sizeof(EXCEPINFO));
403 pExcepInfo->wCode = 1000;
404 pExcepInfo->bstrSource = SysAllocString(L"Msi API Error");
405 pExcepInfo->bstrDescription = SysAllocString(szExceptionDescription);
406 hr = DISP_E_EXCEPTION;
407 }
408 }
409
410 /* Make sure we free the return variant if it is our dummy variant */
411 if (pVarResult == &varResultDummy) VariantClear(pVarResult);
412
413 /* Free function name if we retrieved it */
414 SysFreeString(bstrName);
415
416 TRACE("returning %#lx, %s\n", hr, SUCCEEDED(hr) ? "ok" : "not ok");
417
418 return hr;
419 }
420
421 static const struct IDispatchVtbl AutomationObjectVtbl =
422 {
423 AutomationObject_QueryInterface,
424 AutomationObject_AddRef,
425 AutomationObject_Release,
426 AutomationObject_GetTypeInfoCount,
427 AutomationObject_GetTypeInfo,
428 AutomationObject_GetIDsOfNames,
429 AutomationObject_Invoke
430 };
431
432 /*
433 * IProvideMultipleClassInfo methods
434 */
435
ProvideMultipleClassInfo_QueryInterface(IProvideMultipleClassInfo * iface,REFIID riid,VOID ** ppvoid)436 static HRESULT WINAPI ProvideMultipleClassInfo_QueryInterface(
437 IProvideMultipleClassInfo* iface,
438 REFIID riid,
439 VOID** ppvoid)
440 {
441 struct automation_object *This = impl_from_IProvideMultipleClassInfo(iface);
442 return IDispatch_QueryInterface(&This->IDispatch_iface, riid, ppvoid);
443 }
444
ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo * iface)445 static ULONG WINAPI ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo* iface)
446 {
447 struct automation_object *This = impl_from_IProvideMultipleClassInfo(iface);
448 return IDispatch_AddRef(&This->IDispatch_iface);
449 }
450
ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo * iface)451 static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo* iface)
452 {
453 struct automation_object *This = impl_from_IProvideMultipleClassInfo(iface);
454 return IDispatch_Release(&This->IDispatch_iface);
455 }
456
ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo * iface,ITypeInfo ** ppTI)457 static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI)
458 {
459 struct automation_object *This = impl_from_IProvideMultipleClassInfo(iface);
460 HRESULT hr;
461
462 TRACE("(%p/%p)->(%p)\n", iface, This, ppTI);
463
464 hr = get_typeinfo(This->tid, ppTI);
465 if (SUCCEEDED(hr))
466 ITypeInfo_AddRef(*ppTI);
467
468 return hr;
469 }
470
ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo * iface,DWORD dwGuidKind,GUID * pGUID)471 static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID)
472 {
473 struct automation_object *This = impl_from_IProvideMultipleClassInfo(iface);
474 TRACE("(%p/%p)->(%lu, %s)\n", iface, This, dwGuidKind, debugstr_guid(pGUID));
475
476 if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
477 return E_INVALIDARG;
478 else {
479 *pGUID = *get_riid_from_tid(This->tid);
480 return S_OK;
481 }
482 }
483
ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo * iface,ULONG * pcti)484 static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo* iface, ULONG* pcti)
485 {
486 struct automation_object *This = impl_from_IProvideMultipleClassInfo(iface);
487
488 TRACE("(%p/%p)->(%p)\n", iface, This, pcti);
489 *pcti = 1;
490 return S_OK;
491 }
492
ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo * iface,ULONG iti,DWORD dwFlags,ITypeInfo ** ti,DWORD * pdwTIFlags,ULONG * pcdispidReserved,IID * piidPrimary,IID * piidSource)493 static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface,
494 ULONG iti,
495 DWORD dwFlags,
496 ITypeInfo** ti,
497 DWORD* pdwTIFlags,
498 ULONG* pcdispidReserved,
499 IID* piidPrimary,
500 IID* piidSource)
501 {
502 struct automation_object *This = impl_from_IProvideMultipleClassInfo(iface);
503
504 TRACE("(%p/%p)->(%lu, %#lx, %p, %p, %p, %p, %p)\n", iface, This, iti, dwFlags, ti, pdwTIFlags, pcdispidReserved,
505 piidPrimary, piidSource);
506
507 if (iti != 0)
508 return E_INVALIDARG;
509
510 if (dwFlags & MULTICLASSINFO_GETTYPEINFO)
511 {
512 HRESULT hr = get_typeinfo(This->tid, ti);
513 if (FAILED(hr))
514 return hr;
515
516 ITypeInfo_AddRef(*ti);
517 }
518
519 if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
520 {
521 *pdwTIFlags = 0;
522 *pcdispidReserved = 0;
523 }
524
525 if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY)
526 *piidPrimary = *get_riid_from_tid(This->tid);
527
528 if (dwFlags & MULTICLASSINFO_GETIIDSOURCE)
529 *piidSource = *get_riid_from_tid(This->tid);
530
531 return S_OK;
532 }
533
534 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl =
535 {
536 ProvideMultipleClassInfo_QueryInterface,
537 ProvideMultipleClassInfo_AddRef,
538 ProvideMultipleClassInfo_Release,
539 ProvideMultipleClassInfo_GetClassInfo,
540 ProvideMultipleClassInfo_GetGUID,
541 ProvideMultipleClassInfo_GetMultiTypeInfoCount,
542 ProvideMultipleClassInfo_GetInfoOfIndex
543 };
544
init_automation_object(struct automation_object * This,MSIHANDLE msiHandle,tid_t tid)545 static void init_automation_object(struct automation_object *This, MSIHANDLE msiHandle, tid_t tid)
546 {
547 TRACE("%p, %lu, %s\n", This, msiHandle, debugstr_guid(get_riid_from_tid(tid)));
548
549 This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
550 This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
551 This->ref = 1;
552 This->msiHandle = msiHandle;
553 This->tid = tid;
554 }
555
556 /*
557 * ListEnumerator methods
558 */
559
impl_from_IEnumVARIANT(IEnumVARIANT * iface)560 static inline struct list_enumerator *impl_from_IEnumVARIANT(IEnumVARIANT* iface)
561 {
562 return CONTAINING_RECORD(iface, struct list_enumerator, IEnumVARIANT_iface);
563 }
564
ListEnumerator_QueryInterface(IEnumVARIANT * iface,REFIID riid,void ** ppvObject)565 static HRESULT WINAPI ListEnumerator_QueryInterface(IEnumVARIANT* iface, REFIID riid,
566 void** ppvObject)
567 {
568 struct list_enumerator *This = impl_from_IEnumVARIANT(iface);
569
570 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
571
572 if (ppvObject == NULL)
573 return E_INVALIDARG;
574
575 *ppvObject = 0;
576
577 if (IsEqualGUID(riid, &IID_IUnknown) ||
578 IsEqualGUID(riid, &IID_IEnumVARIANT))
579 {
580 *ppvObject = &This->IEnumVARIANT_iface;
581 }
582 else
583 {
584 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid));
585 return E_NOINTERFACE;
586 }
587
588 IEnumVARIANT_AddRef(iface);
589 return S_OK;
590 }
591
ListEnumerator_AddRef(IEnumVARIANT * iface)592 static ULONG WINAPI ListEnumerator_AddRef(IEnumVARIANT* iface)
593 {
594 struct list_enumerator *This = impl_from_IEnumVARIANT(iface);
595
596 TRACE("(%p/%p)\n", iface, This);
597
598 return InterlockedIncrement(&This->ref);
599 }
600
ListEnumerator_Release(IEnumVARIANT * iface)601 static ULONG WINAPI ListEnumerator_Release(IEnumVARIANT* iface)
602 {
603 struct list_enumerator *This = impl_from_IEnumVARIANT(iface);
604 ULONG ref = InterlockedDecrement(&This->ref);
605
606 TRACE("(%p/%p)\n", iface, This);
607
608 if (!ref)
609 {
610 if (This->list) IDispatch_Release(&This->list->autoobj.IDispatch_iface);
611 free(This);
612 }
613
614 return ref;
615 }
616
ListEnumerator_Next(IEnumVARIANT * iface,ULONG celt,VARIANT * rgVar,ULONG * fetched)617 static HRESULT WINAPI ListEnumerator_Next(IEnumVARIANT* iface, ULONG celt, VARIANT* rgVar,
618 ULONG* fetched)
619 {
620 struct list_enumerator *This = impl_from_IEnumVARIANT(iface);
621 ULONG i, local;
622
623 TRACE("%p, %lu, %p, %p\n", iface, celt, rgVar, fetched);
624
625 if (fetched) *fetched = 0;
626
627 if (!rgVar)
628 return S_FALSE;
629
630 for (local = 0; local < celt; local++)
631 VariantInit(&rgVar[local]);
632
633 for (i = This->pos, local = 0; i < This->list->count && local < celt; i++, local++)
634 VariantCopy(&rgVar[local], &This->list->data[i]);
635
636 if (fetched) *fetched = local;
637 This->pos = i;
638
639 return (local < celt) ? S_FALSE : S_OK;
640 }
641
ListEnumerator_Skip(IEnumVARIANT * iface,ULONG celt)642 static HRESULT WINAPI ListEnumerator_Skip(IEnumVARIANT* iface, ULONG celt)
643 {
644 struct list_enumerator *This = impl_from_IEnumVARIANT(iface);
645
646 TRACE("%p, %lu\n", iface, celt);
647
648 This->pos += celt;
649 if (This->pos >= This->list->count)
650 {
651 This->pos = This->list->count;
652 return S_FALSE;
653 }
654
655 return S_OK;
656 }
657
ListEnumerator_Reset(IEnumVARIANT * iface)658 static HRESULT WINAPI ListEnumerator_Reset(IEnumVARIANT* iface)
659 {
660 struct list_enumerator *This = impl_from_IEnumVARIANT(iface);
661
662 TRACE("(%p)\n", iface);
663
664 This->pos = 0;
665 return S_OK;
666 }
667
ListEnumerator_Clone(IEnumVARIANT * iface,IEnumVARIANT ** ppEnum)668 static HRESULT WINAPI ListEnumerator_Clone(IEnumVARIANT* iface, IEnumVARIANT **ppEnum)
669 {
670 struct list_enumerator *This = impl_from_IEnumVARIANT(iface);
671 HRESULT hr;
672
673 TRACE("(%p,%p)\n", iface, ppEnum);
674
675 if (ppEnum == NULL)
676 return S_FALSE;
677
678 *ppEnum = NULL;
679 hr = create_list_enumerator(This->list, (LPVOID *)ppEnum);
680 if (FAILED(hr))
681 {
682 if (*ppEnum) IEnumVARIANT_Release(*ppEnum);
683 return hr;
684 }
685
686 return S_OK;
687 }
688
689 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
690 {
691 ListEnumerator_QueryInterface,
692 ListEnumerator_AddRef,
693 ListEnumerator_Release,
694 ListEnumerator_Next,
695 ListEnumerator_Skip,
696 ListEnumerator_Reset,
697 ListEnumerator_Clone
698 };
699
700 /* Create a list enumerator, placing the result in the pointer ppObj. */
create_list_enumerator(struct list_object * list,void ** ppObj)701 static HRESULT create_list_enumerator(struct list_object *list, void **ppObj)
702 {
703 struct list_enumerator *object;
704
705 TRACE("(%p, %p)\n", list, ppObj);
706
707 object = malloc(sizeof(*object));
708
709 /* Set all the VTable references */
710 object->IEnumVARIANT_iface.lpVtbl = &ListEnumerator_Vtbl;
711 object->ref = 1;
712
713 /* Store data that was passed */
714 object->pos = 0;
715 object->list = list;
716 if (list) IDispatch_AddRef(&list->autoobj.IDispatch_iface);
717
718 *ppObj = object;
719 return S_OK;
720 }
721
722 /*
723 * Individual Object Invocation Functions
724 */
725
726 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
727 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
728 using DispGetParam/VariantChangeType. */
DispGetParam_CopyOnly(DISPPARAMS * pdispparams,UINT * position,VARIANT * pvarResult)729 static HRESULT DispGetParam_CopyOnly(
730 DISPPARAMS *pdispparams, /* [in] Parameter list */
731 UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
732 VARIANT *pvarResult) /* [out] Destination for resulting variant */
733 {
734 /* position is counted backwards */
735 UINT pos;
736
737 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
738 *position, pdispparams->cArgs, pdispparams->cNamedArgs);
739 if (*position < pdispparams->cArgs) {
740 /* positional arg? */
741 pos = pdispparams->cArgs - *position - 1;
742 } else {
743 /* FIXME: is this how to handle named args? */
744 for (pos=0; pos<pdispparams->cNamedArgs; pos++)
745 if (pdispparams->rgdispidNamedArgs[pos] == *position) break;
746
747 if (pos==pdispparams->cNamedArgs)
748 return DISP_E_PARAMNOTFOUND;
749 }
750 *position = pos;
751 return VariantCopyInd(pvarResult,
752 &pdispparams->rgvarg[pos]);
753 }
754
summaryinfo_invoke(struct automation_object * This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)755 static HRESULT summaryinfo_invoke(
756 struct automation_object *This,
757 DISPID dispIdMember,
758 REFIID riid,
759 LCID lcid,
760 WORD wFlags,
761 DISPPARAMS* pDispParams,
762 VARIANT* pVarResult,
763 EXCEPINFO* pExcepInfo,
764 UINT* puArgErr)
765 {
766 UINT ret;
767 VARIANTARG varg0, varg1;
768 FILETIME ft, ftlocal;
769 SYSTEMTIME st;
770 HRESULT hr;
771
772 VariantInit(&varg0);
773 VariantInit(&varg1);
774
775 switch (dispIdMember)
776 {
777 case DISPID_SUMMARYINFO_PROPERTY:
778 if (wFlags & DISPATCH_PROPERTYGET)
779 {
780 UINT type;
781 INT value;
782 DWORD size = 0;
783 DATE date;
784 LPWSTR str;
785
786 static WCHAR szEmpty[] = L"";
787
788 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
789 if (FAILED(hr)) return hr;
790 ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, &value,
791 &ft, szEmpty, &size);
792 if (ret != ERROR_SUCCESS &&
793 ret != ERROR_MORE_DATA)
794 {
795 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
796 return DISP_E_EXCEPTION;
797 }
798
799 switch (type)
800 {
801 case VT_EMPTY:
802 break;
803
804 case VT_I2:
805 case VT_I4:
806 V_VT(pVarResult) = VT_I4;
807 V_I4(pVarResult) = value;
808 break;
809
810 case VT_LPSTR:
811 if (!(str = malloc(++size * sizeof(WCHAR))))
812 ERR("Out of memory\n");
813 else if ((ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, NULL,
814 NULL, str, &size)) != ERROR_SUCCESS)
815 ERR("MsiSummaryInfoGetProperty returned %d\n", ret);
816 else
817 {
818 V_VT(pVarResult) = VT_BSTR;
819 V_BSTR(pVarResult) = SysAllocString(str);
820 }
821 free(str);
822 break;
823
824 case VT_FILETIME:
825 FileTimeToLocalFileTime(&ft, &ftlocal);
826 FileTimeToSystemTime(&ftlocal, &st);
827 SystemTimeToVariantTime(&st, &date);
828
829 V_VT(pVarResult) = VT_DATE;
830 V_DATE(pVarResult) = date;
831 break;
832
833 default:
834 ERR("Unhandled variant type %d\n", type);
835 }
836 }
837 else if (wFlags & DISPATCH_PROPERTYPUT)
838 {
839 UINT posValue = DISPID_PROPERTYPUT;
840
841 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
842 if (FAILED(hr)) return hr;
843 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg1);
844 if (FAILED(hr))
845 {
846 *puArgErr = posValue;
847 return hr;
848 }
849
850 switch (V_VT(&varg1))
851 {
852 case VT_I2:
853 case VT_I4:
854 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), V_VT(&varg1), V_I4(&varg1), NULL, NULL);
855 break;
856
857 case VT_DATE:
858 VariantTimeToSystemTime(V_DATE(&varg1), &st);
859 SystemTimeToFileTime(&st, &ftlocal);
860 LocalFileTimeToFileTime(&ftlocal, &ft);
861 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_FILETIME, 0, &ft, NULL);
862 break;
863
864 case VT_BSTR:
865 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_LPSTR, 0, NULL, V_BSTR(&varg1));
866 break;
867
868 default:
869 FIXME("Unhandled variant type %d\n", V_VT(&varg1));
870 VariantClear(&varg1);
871 return DISP_E_EXCEPTION;
872 }
873
874 if (ret != ERROR_SUCCESS)
875 {
876 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret);
877 return DISP_E_EXCEPTION;
878 }
879 }
880 else return DISP_E_MEMBERNOTFOUND;
881 break;
882
883 case DISPID_SUMMARYINFO_PROPERTYCOUNT:
884 if (wFlags & DISPATCH_PROPERTYGET) {
885 UINT count;
886 if ((ret = MsiSummaryInfoGetPropertyCount(This->msiHandle, &count)) != ERROR_SUCCESS)
887 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret);
888 else
889 {
890 V_VT(pVarResult) = VT_I4;
891 V_I4(pVarResult) = count;
892 }
893 }
894 else return DISP_E_MEMBERNOTFOUND;
895 break;
896
897 default:
898 return DISP_E_MEMBERNOTFOUND;
899 }
900
901 VariantClear(&varg1);
902 VariantClear(&varg0);
903
904 return S_OK;
905 }
906
record_invoke(struct automation_object * This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)907 static HRESULT record_invoke(
908 struct automation_object *This,
909 DISPID dispIdMember,
910 REFIID riid,
911 LCID lcid,
912 WORD wFlags,
913 DISPPARAMS* pDispParams,
914 VARIANT* pVarResult,
915 EXCEPINFO* pExcepInfo,
916 UINT* puArgErr)
917 {
918 WCHAR *szString;
919 DWORD dwLen = 0;
920 UINT ret;
921 VARIANTARG varg0, varg1;
922 HRESULT hr;
923
924 VariantInit(&varg0);
925 VariantInit(&varg1);
926
927 switch (dispIdMember)
928 {
929 case DISPID_RECORD_FIELDCOUNT:
930 if (wFlags & DISPATCH_PROPERTYGET) {
931 V_VT(pVarResult) = VT_I4;
932 V_I4(pVarResult) = MsiRecordGetFieldCount(This->msiHandle);
933 }
934 else return DISP_E_MEMBERNOTFOUND;
935 break;
936
937 case DISPID_RECORD_STRINGDATA:
938 if (wFlags & DISPATCH_PROPERTYGET) {
939 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
940 if (FAILED(hr)) return hr;
941 V_VT(pVarResult) = VT_BSTR;
942 V_BSTR(pVarResult) = NULL;
943 if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
944 {
945 if (!(szString = malloc((++dwLen) * sizeof(WCHAR))))
946 ERR("Out of memory\n");
947 else if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
948 V_BSTR(pVarResult) = SysAllocString(szString);
949 free(szString);
950 }
951 if (ret != ERROR_SUCCESS)
952 ERR("MsiRecordGetString returned %d\n", ret);
953 } else if (wFlags & DISPATCH_PROPERTYPUT) {
954 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
955 if (FAILED(hr)) return hr;
956 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
957 if (FAILED(hr)) return hr;
958 if ((ret = MsiRecordSetStringW(This->msiHandle, V_I4(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
959 {
960 VariantClear(&varg1);
961 ERR("MsiRecordSetString returned %d\n", ret);
962 return DISP_E_EXCEPTION;
963 }
964 }
965 else return DISP_E_MEMBERNOTFOUND;
966 break;
967
968 case DISPID_RECORD_INTEGERDATA:
969 if (wFlags & DISPATCH_PROPERTYGET) {
970 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
971 if (FAILED(hr)) return hr;
972 V_VT(pVarResult) = VT_I4;
973 V_I4(pVarResult) = MsiRecordGetInteger(This->msiHandle, V_I4(&varg0));
974 } else if (wFlags & DISPATCH_PROPERTYPUT) {
975 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
976 if (FAILED(hr)) return hr;
977 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
978 if (FAILED(hr)) return hr;
979 if ((ret = MsiRecordSetInteger(This->msiHandle, V_I4(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
980 {
981 ERR("MsiRecordSetInteger returned %d\n", ret);
982 return DISP_E_EXCEPTION;
983 }
984 }
985 else return DISP_E_MEMBERNOTFOUND;
986 break;
987
988 default:
989 return DISP_E_MEMBERNOTFOUND;
990 }
991
992 VariantClear(&varg1);
993 VariantClear(&varg0);
994
995 return S_OK;
996 }
997
create_record(MSIHANDLE msiHandle,IDispatch ** disp)998 static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
999 {
1000 struct automation_object *record;
1001
1002 record = malloc(sizeof(*record));
1003 if (!record) return E_OUTOFMEMORY;
1004
1005 init_automation_object(record, msiHandle, Record_tid);
1006
1007 *disp = &record->IDispatch_iface;
1008
1009 return S_OK;
1010 }
1011
list_invoke(struct automation_object * This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1012 static HRESULT list_invoke(
1013 struct automation_object *This,
1014 DISPID dispIdMember,
1015 REFIID riid,
1016 LCID lcid,
1017 WORD wFlags,
1018 DISPPARAMS* pDispParams,
1019 VARIANT* pVarResult,
1020 EXCEPINFO* pExcepInfo,
1021 UINT* puArgErr)
1022 {
1023 struct list_object *list = CONTAINING_RECORD(This, struct list_object, autoobj);
1024 IUnknown *pUnk = NULL;
1025 HRESULT hr;
1026
1027 switch (dispIdMember)
1028 {
1029 case DISPID_LIST__NEWENUM:
1030 if (wFlags & DISPATCH_METHOD) {
1031 V_VT(pVarResult) = VT_UNKNOWN;
1032 if (SUCCEEDED(hr = create_list_enumerator(list, (LPVOID *)&pUnk)))
1033 V_UNKNOWN(pVarResult) = pUnk;
1034 else
1035 ERR("failed to create IEnumVARIANT object, hresult %#lx\n", hr);
1036 }
1037 else return DISP_E_MEMBERNOTFOUND;
1038 break;
1039
1040 case DISPID_LIST_ITEM:
1041 if (wFlags & DISPATCH_PROPERTYGET) {
1042 VARIANTARG index;
1043
1044 VariantInit(&index);
1045 hr = DispGetParam(pDispParams, 0, VT_I4, &index, puArgErr);
1046 if (FAILED(hr)) return hr;
1047 if (V_I4(&index) < 0 || V_I4(&index) >= list->count)
1048 return DISP_E_BADINDEX;
1049 VariantCopy(pVarResult, &list->data[V_I4(&index)]);
1050 }
1051 else return DISP_E_MEMBERNOTFOUND;
1052 break;
1053
1054 case DISPID_LIST_COUNT:
1055 if (wFlags & DISPATCH_PROPERTYGET) {
1056 V_VT(pVarResult) = VT_I4;
1057 V_I4(pVarResult) = list->count;
1058 }
1059 else return DISP_E_MEMBERNOTFOUND;
1060 break;
1061
1062 default:
1063 return DISP_E_MEMBERNOTFOUND;
1064 }
1065
1066 return S_OK;
1067 }
1068
list_free(struct automation_object * This)1069 static void list_free(struct automation_object *This)
1070 {
1071 struct list_object *list = CONTAINING_RECORD(This, struct list_object, autoobj);
1072 int i;
1073
1074 for (i = 0; i < list->count; i++)
1075 VariantClear(&list->data[i]);
1076 free(list->data);
1077 }
1078
get_products_count(const WCHAR * product,int * len)1079 static HRESULT get_products_count(const WCHAR *product, int *len)
1080 {
1081 int i = 0;
1082
1083 while (1)
1084 {
1085 WCHAR dataW[GUID_SIZE];
1086 UINT ret;
1087
1088 /* all or related only */
1089 if (product)
1090 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1091 else
1092 ret = MsiEnumProductsW(i, dataW);
1093
1094 if (ret == ERROR_NO_MORE_ITEMS) break;
1095
1096 if (ret != ERROR_SUCCESS)
1097 return DISP_E_EXCEPTION;
1098
1099 i++;
1100 }
1101
1102 *len = i;
1103
1104 return S_OK;
1105 }
1106
create_list(const WCHAR * product,IDispatch ** dispatch)1107 static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
1108 {
1109 struct list_object *list;
1110 HRESULT hr;
1111 int i;
1112
1113 list = calloc(1, sizeof(*list));
1114 if (!list) return E_OUTOFMEMORY;
1115
1116 init_automation_object(&list->autoobj, 0, StringList_tid);
1117
1118 *dispatch = &list->autoobj.IDispatch_iface;
1119
1120 hr = get_products_count(product, &list->count);
1121 if (hr != S_OK)
1122 {
1123 IDispatch_Release(*dispatch);
1124 return hr;
1125 }
1126
1127 list->data = malloc(list->count * sizeof(VARIANT));
1128 if (!list->data)
1129 {
1130 IDispatch_Release(*dispatch);
1131 return E_OUTOFMEMORY;
1132 }
1133
1134 for (i = 0; i < list->count; i++)
1135 {
1136 WCHAR dataW[GUID_SIZE];
1137 UINT ret;
1138
1139 /* all or related only */
1140 if (product)
1141 ret = MsiEnumRelatedProductsW(product, 0, i, dataW);
1142 else
1143 ret = MsiEnumProductsW(i, dataW);
1144
1145 if (ret == ERROR_NO_MORE_ITEMS) break;
1146
1147 V_VT(&list->data[i]) = VT_BSTR;
1148 V_BSTR(&list->data[i]) = SysAllocString(dataW);
1149 }
1150
1151 return S_OK;
1152 }
1153
view_invoke(struct automation_object * This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1154 static HRESULT view_invoke(
1155 struct automation_object *This,
1156 DISPID dispIdMember,
1157 REFIID riid,
1158 LCID lcid,
1159 WORD wFlags,
1160 DISPPARAMS* pDispParams,
1161 VARIANT* pVarResult,
1162 EXCEPINFO* pExcepInfo,
1163 UINT* puArgErr)
1164 {
1165 MSIHANDLE msiHandle;
1166 UINT ret;
1167 VARIANTARG varg0, varg1;
1168 HRESULT hr;
1169
1170 VariantInit(&varg0);
1171 VariantInit(&varg1);
1172
1173 switch (dispIdMember)
1174 {
1175 case DISPID_VIEW_EXECUTE:
1176 if (wFlags & DISPATCH_METHOD)
1177 {
1178 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &varg0, puArgErr);
1179 if (SUCCEEDED(hr) && V_DISPATCH(&varg0) != NULL)
1180 MsiViewExecute(This->msiHandle, ((struct automation_object *)V_DISPATCH(&varg0))->msiHandle);
1181 else
1182 MsiViewExecute(This->msiHandle, 0);
1183 }
1184 else return DISP_E_MEMBERNOTFOUND;
1185 break;
1186
1187 case DISPID_VIEW_FETCH:
1188 if (wFlags & DISPATCH_METHOD)
1189 {
1190 V_VT(pVarResult) = VT_DISPATCH;
1191 if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS)
1192 {
1193 if (FAILED(hr = create_record(msiHandle, &V_DISPATCH(pVarResult))))
1194 ERR("failed to create Record object, hresult %#lx\n", hr);
1195 }
1196 else if (ret == ERROR_NO_MORE_ITEMS)
1197 V_DISPATCH(pVarResult) = NULL;
1198 else
1199 {
1200 ERR("MsiViewFetch returned %d\n", ret);
1201 return DISP_E_EXCEPTION;
1202 }
1203 }
1204 else return DISP_E_MEMBERNOTFOUND;
1205 break;
1206
1207 case DISPID_VIEW_MODIFY:
1208 if (wFlags & DISPATCH_METHOD)
1209 {
1210 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1211 if (FAILED(hr)) return hr;
1212 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1213 if (FAILED(hr)) return hr;
1214 if (!V_DISPATCH(&varg1)) return DISP_E_EXCEPTION;
1215 if ((ret = MsiViewModify(This->msiHandle, V_I4(&varg0),
1216 ((struct automation_object *)V_DISPATCH(&varg1))->msiHandle)) != ERROR_SUCCESS)
1217 {
1218 VariantClear(&varg1);
1219 ERR("MsiViewModify returned %d\n", ret);
1220 return DISP_E_EXCEPTION;
1221 }
1222 }
1223 else return DISP_E_MEMBERNOTFOUND;
1224 break;
1225
1226 case DISPID_VIEW_CLOSE:
1227 if (wFlags & DISPATCH_METHOD)
1228 {
1229 MsiViewClose(This->msiHandle);
1230 }
1231 else return DISP_E_MEMBERNOTFOUND;
1232 break;
1233
1234 default:
1235 return DISP_E_MEMBERNOTFOUND;
1236 }
1237
1238 VariantClear(&varg1);
1239 VariantClear(&varg0);
1240
1241 return S_OK;
1242 }
1243
DatabaseImpl_LastErrorRecord(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1244 static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
1245 DISPPARAMS* pDispParams,
1246 VARIANT* pVarResult,
1247 EXCEPINFO* pExcepInfo,
1248 UINT* puArgErr)
1249 {
1250 if (!(wFlags & DISPATCH_METHOD))
1251 return DISP_E_MEMBERNOTFOUND;
1252
1253 FIXME("\n");
1254
1255 VariantInit(pVarResult);
1256 return S_OK;
1257 }
1258
database_invoke(struct automation_object * This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1259 HRESULT database_invoke(
1260 struct automation_object *This,
1261 DISPID dispIdMember,
1262 REFIID riid,
1263 LCID lcid,
1264 WORD wFlags,
1265 DISPPARAMS* pDispParams,
1266 VARIANT* pVarResult,
1267 EXCEPINFO* pExcepInfo,
1268 UINT* puArgErr)
1269 {
1270 IDispatch *dispatch = NULL;
1271 MSIHANDLE msiHandle;
1272 UINT ret;
1273 VARIANTARG varg0, varg1;
1274 HRESULT hr;
1275
1276 VariantInit(&varg0);
1277 VariantInit(&varg1);
1278
1279 switch (dispIdMember)
1280 {
1281 case DISPID_DATABASE_SUMMARYINFORMATION:
1282 if (wFlags & DISPATCH_PROPERTYGET)
1283 {
1284 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1285 if (FAILED(hr))
1286 V_I4(&varg0) = 0;
1287
1288 V_VT(pVarResult) = VT_DISPATCH;
1289 if ((ret = MsiGetSummaryInformationW(This->msiHandle, NULL, V_I4(&varg0), &msiHandle)) == ERROR_SUCCESS)
1290 {
1291 hr = create_summaryinfo(msiHandle, &dispatch);
1292 if (SUCCEEDED(hr))
1293 V_DISPATCH(pVarResult) = dispatch;
1294 else
1295 ERR("failed to create SummaryInfo object: %#lx\n", hr);
1296 }
1297 else
1298 {
1299 ERR("MsiGetSummaryInformation returned %d\n", ret);
1300 return DISP_E_EXCEPTION;
1301 }
1302 }
1303 else return DISP_E_MEMBERNOTFOUND;
1304 break;
1305
1306 case DISPID_DATABASE_OPENVIEW:
1307 if (wFlags & DISPATCH_METHOD)
1308 {
1309 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1310 if (FAILED(hr)) return hr;
1311 V_VT(pVarResult) = VT_DISPATCH;
1312 if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS)
1313 {
1314 if (SUCCEEDED(hr = create_view(msiHandle, &dispatch)))
1315 V_DISPATCH(pVarResult) = dispatch;
1316 else
1317 ERR("failed to create View object, hresult %#lx\n", hr);
1318 }
1319 else
1320 {
1321 VariantClear(&varg0);
1322 ERR("MsiDatabaseOpenView returned %d\n", ret);
1323 return DISP_E_EXCEPTION;
1324 }
1325 }
1326 else return DISP_E_MEMBERNOTFOUND;
1327 break;
1328
1329 case DISPID_INSTALLER_LASTERRORRECORD:
1330 return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
1331 pVarResult, pExcepInfo,
1332 puArgErr);
1333
1334 default:
1335 return DISP_E_MEMBERNOTFOUND;
1336 }
1337
1338 VariantClear(&varg1);
1339 VariantClear(&varg0);
1340
1341 return S_OK;
1342 }
1343
session_invoke(struct automation_object * This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1344 static HRESULT session_invoke(
1345 struct automation_object *This,
1346 DISPID dispIdMember,
1347 REFIID riid,
1348 LCID lcid,
1349 WORD wFlags,
1350 DISPPARAMS* pDispParams,
1351 VARIANT* pVarResult,
1352 EXCEPINFO* pExcepInfo,
1353 UINT* puArgErr)
1354 {
1355 struct session_object *session = CONTAINING_RECORD(This, struct session_object, autoobj);
1356 WCHAR *szString;
1357 DWORD dwLen = 0;
1358 MSIHANDLE msiHandle;
1359 LANGID langId;
1360 UINT ret;
1361 INSTALLSTATE iInstalled, iAction;
1362 VARIANTARG varg0, varg1;
1363 HRESULT hr;
1364
1365 VariantInit(&varg0);
1366 VariantInit(&varg1);
1367
1368 switch (dispIdMember)
1369 {
1370 case DISPID_SESSION_INSTALLER:
1371 if (wFlags & DISPATCH_PROPERTYGET) {
1372 V_VT(pVarResult) = VT_DISPATCH;
1373 IDispatch_AddRef(session->installer);
1374 V_DISPATCH(pVarResult) = session->installer;
1375 }
1376 else return DISP_E_MEMBERNOTFOUND;
1377 break;
1378
1379 case DISPID_SESSION_PROPERTY:
1380 if (wFlags & DISPATCH_PROPERTYGET) {
1381 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1382 if (FAILED(hr)) return hr;
1383 V_VT(pVarResult) = VT_BSTR;
1384 V_BSTR(pVarResult) = NULL;
1385 if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), NULL, &dwLen)) == ERROR_SUCCESS)
1386 {
1387 if (!(szString = malloc((++dwLen) * sizeof(WCHAR))))
1388 ERR("Out of memory\n");
1389 else if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), szString, &dwLen)) == ERROR_SUCCESS)
1390 V_BSTR(pVarResult) = SysAllocString(szString);
1391 free(szString);
1392 }
1393 if (ret != ERROR_SUCCESS)
1394 ERR("MsiGetProperty returned %d\n", ret);
1395 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1396 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1397 if (FAILED(hr)) return hr;
1398 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1399 if (FAILED(hr)) {
1400 VariantClear(&varg0);
1401 return hr;
1402 }
1403 if ((ret = MsiSetPropertyW(This->msiHandle, V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS)
1404 {
1405 VariantClear(&varg0);
1406 VariantClear(&varg1);
1407 ERR("MsiSetProperty returned %d\n", ret);
1408 return DISP_E_EXCEPTION;
1409 }
1410 }
1411 else return DISP_E_MEMBERNOTFOUND;
1412 break;
1413
1414 case DISPID_SESSION_LANGUAGE:
1415 if (wFlags & DISPATCH_PROPERTYGET) {
1416 langId = MsiGetLanguage(This->msiHandle);
1417 V_VT(pVarResult) = VT_I4;
1418 V_I4(pVarResult) = langId;
1419 }
1420 else return DISP_E_MEMBERNOTFOUND;
1421 break;
1422
1423 case DISPID_SESSION_MODE:
1424 if (wFlags & DISPATCH_PROPERTYGET) {
1425 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1426 if (FAILED(hr)) return hr;
1427 V_VT(pVarResult) = VT_BOOL;
1428 V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0)) ? VARIANT_TRUE : VARIANT_FALSE;
1429 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1430 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1431 if (FAILED(hr)) return hr;
1432 hr = DispGetParam(pDispParams, 1, VT_BOOL, &varg1, puArgErr);
1433 if (FAILED(hr)) return hr;
1434 if ((ret = MsiSetMode(This->msiHandle, V_I4(&varg0), V_BOOL(&varg1))) != ERROR_SUCCESS)
1435 {
1436 ERR("MsiSetMode returned %d\n", ret);
1437 return DISP_E_EXCEPTION;
1438 }
1439 }
1440 else return DISP_E_MEMBERNOTFOUND;
1441 break;
1442
1443 case DISPID_SESSION_DATABASE:
1444 if (wFlags & DISPATCH_PROPERTYGET) {
1445 V_VT(pVarResult) = VT_DISPATCH;
1446 if ((msiHandle = MsiGetActiveDatabase(This->msiHandle)))
1447 {
1448 IDispatch *dispatch;
1449
1450 if (SUCCEEDED(hr = create_database(msiHandle, &dispatch)))
1451 V_DISPATCH(pVarResult) = dispatch;
1452 else
1453 ERR("failed to create Database object, hresult %#lx\n", hr);
1454 }
1455 else
1456 {
1457 ERR("MsiGetActiveDatabase failed\n");
1458 return DISP_E_EXCEPTION;
1459 }
1460 }
1461 else return DISP_E_MEMBERNOTFOUND;
1462 break;
1463
1464 case DISPID_SESSION_DOACTION:
1465 if (wFlags & DISPATCH_METHOD) {
1466 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1467 if (FAILED(hr)) return hr;
1468 ret = MsiDoActionW(This->msiHandle, V_BSTR(&varg0));
1469 V_VT(pVarResult) = VT_I4;
1470 switch (ret)
1471 {
1472 case ERROR_FUNCTION_NOT_CALLED:
1473 V_I4(pVarResult) = msiDoActionStatusNoAction;
1474 break;
1475 case ERROR_SUCCESS:
1476 V_I4(pVarResult) = msiDoActionStatusSuccess;
1477 break;
1478 case ERROR_INSTALL_USEREXIT:
1479 V_I4(pVarResult) = msiDoActionStatusUserExit;
1480 break;
1481 case ERROR_INSTALL_FAILURE:
1482 V_I4(pVarResult) = msiDoActionStatusFailure;
1483 break;
1484 case ERROR_INSTALL_SUSPEND:
1485 V_I4(pVarResult) = msiDoActionStatusSuspend;
1486 break;
1487 case ERROR_MORE_DATA:
1488 V_I4(pVarResult) = msiDoActionStatusFinished;
1489 break;
1490 case ERROR_INVALID_HANDLE_STATE:
1491 V_I4(pVarResult) = msiDoActionStatusWrongState;
1492 break;
1493 case ERROR_INVALID_DATA:
1494 V_I4(pVarResult) = msiDoActionStatusBadActionData;
1495 break;
1496 default:
1497 VariantClear(&varg0);
1498 FIXME("MsiDoAction returned unhandled value %d\n", ret);
1499 return DISP_E_EXCEPTION;
1500 }
1501 }
1502 else return DISP_E_MEMBERNOTFOUND;
1503 break;
1504
1505 case DISPID_SESSION_EVALUATECONDITION:
1506 if (wFlags & DISPATCH_METHOD) {
1507 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1508 if (FAILED(hr)) return hr;
1509 V_VT(pVarResult) = VT_I4;
1510 V_I4(pVarResult) = MsiEvaluateConditionW(This->msiHandle, V_BSTR(&varg0));
1511 }
1512 else return DISP_E_MEMBERNOTFOUND;
1513 break;
1514
1515 case DISPID_SESSION_MESSAGE:
1516 if(!(wFlags & DISPATCH_METHOD))
1517 return DISP_E_MEMBERNOTFOUND;
1518
1519 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1520 if (FAILED(hr)) return hr;
1521 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr);
1522 if (FAILED(hr)) return hr;
1523
1524 V_VT(pVarResult) = VT_I4;
1525 V_I4(pVarResult) =
1526 MsiProcessMessage(This->msiHandle, V_I4(&varg0), ((struct automation_object *)V_DISPATCH(&varg1))->msiHandle);
1527 break;
1528
1529 case DISPID_SESSION_SETINSTALLLEVEL:
1530 if (wFlags & DISPATCH_METHOD) {
1531 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1532 if (FAILED(hr)) return hr;
1533 if ((ret = MsiSetInstallLevel(This->msiHandle, V_I4(&varg0))) != ERROR_SUCCESS)
1534 {
1535 ERR("MsiSetInstallLevel returned %d\n", ret);
1536 return DISP_E_EXCEPTION;
1537 }
1538 }
1539 else return DISP_E_MEMBERNOTFOUND;
1540 break;
1541
1542 case DISPID_SESSION_FEATURECURRENTSTATE:
1543 if (wFlags & DISPATCH_PROPERTYGET) {
1544 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1545 if (FAILED(hr)) return hr;
1546 V_VT(pVarResult) = VT_I4;
1547 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1548 V_I4(pVarResult) = iInstalled;
1549 else
1550 {
1551 ERR("MsiGetFeatureState returned %d\n", ret);
1552 V_I4(pVarResult) = msiInstallStateUnknown;
1553 }
1554 }
1555 else return DISP_E_MEMBERNOTFOUND;
1556 break;
1557
1558 case DISPID_SESSION_FEATUREREQUESTSTATE:
1559 if (wFlags & DISPATCH_PROPERTYGET) {
1560 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1561 if (FAILED(hr)) return hr;
1562 V_VT(pVarResult) = VT_I4;
1563 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS)
1564 V_I4(pVarResult) = iAction;
1565 else
1566 {
1567 ERR("MsiGetFeatureState returned %d\n", ret);
1568 V_I4(pVarResult) = msiInstallStateUnknown;
1569 }
1570 } else if (wFlags & DISPATCH_PROPERTYPUT) {
1571 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1572 if (FAILED(hr)) return hr;
1573 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1574 if (FAILED(hr)) {
1575 VariantClear(&varg0);
1576 return hr;
1577 }
1578 if ((ret = MsiSetFeatureStateW(This->msiHandle, V_BSTR(&varg0), V_I4(&varg1))) != ERROR_SUCCESS)
1579 {
1580 VariantClear(&varg0);
1581 ERR("MsiSetFeatureState returned %d\n", ret);
1582 return DISP_E_EXCEPTION;
1583 }
1584 }
1585 else return DISP_E_MEMBERNOTFOUND;
1586 break;
1587
1588 default:
1589 return DISP_E_MEMBERNOTFOUND;
1590 }
1591
1592 VariantClear(&varg1);
1593 VariantClear(&varg0);
1594
1595 return S_OK;
1596 }
1597
1598 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
1599 * registry value type. Used by Installer::RegistryValue. */
variant_from_registry_value(VARIANT * pVarResult,DWORD dwType,LPBYTE lpData,DWORD dwSize)1600 static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize)
1601 {
1602 WCHAR *szString = (WCHAR *)lpData;
1603 LPWSTR szNewString = NULL;
1604 DWORD dwNewSize = 0;
1605 int idx;
1606
1607 switch (dwType)
1608 {
1609 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
1610 case REG_MULTI_SZ: /* Multi SZ change internal null characters to newlines */
1611 idx = (dwSize/sizeof(WCHAR))-1;
1612 while (idx >= 0 && !szString[idx]) idx--;
1613 for (; idx >= 0; idx--)
1614 if (!szString[idx]) szString[idx] = '\n';
1615 /* fall through */
1616 case REG_SZ:
1617 V_VT(pVarResult) = VT_BSTR;
1618 V_BSTR(pVarResult) = SysAllocStringByteLen((LPCSTR)szString, dwSize);
1619 break;
1620
1621 case REG_EXPAND_SZ:
1622 if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1623 ERR("ExpandEnvironmentStrings returned error %lu\n", GetLastError());
1624 else if (!(szNewString = malloc(dwNewSize * sizeof(WCHAR))))
1625 ERR("Out of memory\n");
1626 else if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
1627 ERR("ExpandEnvironmentStrings returned error %lu\n", GetLastError());
1628 else
1629 {
1630 V_VT(pVarResult) = VT_BSTR;
1631 V_BSTR(pVarResult) = SysAllocStringLen(szNewString, dwNewSize);
1632 }
1633 free(szNewString);
1634 break;
1635
1636 case REG_DWORD:
1637 V_VT(pVarResult) = VT_I4;
1638 V_I4(pVarResult) = *((DWORD *)lpData);
1639 break;
1640
1641 case REG_QWORD:
1642 V_VT(pVarResult) = VT_BSTR;
1643 V_BSTR(pVarResult) = SysAllocString(L"(REG_\?\?)"); /* Weird string, don't know why native returns it */
1644 break;
1645
1646 case REG_BINARY:
1647 V_VT(pVarResult) = VT_BSTR;
1648 V_BSTR(pVarResult) = SysAllocString(L"(REG_BINARY)");
1649 break;
1650
1651 case REG_NONE:
1652 V_VT(pVarResult) = VT_EMPTY;
1653 break;
1654
1655 default:
1656 FIXME("Unhandled registry value type %lu\n", dwType);
1657 }
1658 }
1659
InstallerImpl_CreateRecord(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1660 static HRESULT InstallerImpl_CreateRecord(WORD wFlags,
1661 DISPPARAMS* pDispParams,
1662 VARIANT* pVarResult,
1663 EXCEPINFO* pExcepInfo,
1664 UINT* puArgErr)
1665 {
1666 HRESULT hr;
1667 VARIANTARG varg0;
1668 MSIHANDLE hrec;
1669
1670 if (!(wFlags & DISPATCH_METHOD))
1671 return DISP_E_MEMBERNOTFOUND;
1672
1673 VariantInit(&varg0);
1674 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1675 if (FAILED(hr))
1676 return hr;
1677
1678 V_VT(pVarResult) = VT_DISPATCH;
1679
1680 hrec = MsiCreateRecord(V_I4(&varg0));
1681 if (!hrec)
1682 return DISP_E_EXCEPTION;
1683
1684 return create_record(hrec, &V_DISPATCH(pVarResult));
1685 }
1686
InstallerImpl_OpenPackage(struct automation_object * This,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1687 static HRESULT InstallerImpl_OpenPackage(struct automation_object *This,
1688 WORD wFlags,
1689 DISPPARAMS* pDispParams,
1690 VARIANT* pVarResult,
1691 EXCEPINFO* pExcepInfo,
1692 UINT* puArgErr)
1693 {
1694 UINT ret;
1695 HRESULT hr;
1696 MSIHANDLE hpkg;
1697 IDispatch* dispatch;
1698 VARIANTARG varg0, varg1;
1699
1700 if (!(wFlags & DISPATCH_METHOD))
1701 return DISP_E_MEMBERNOTFOUND;
1702
1703 if (pDispParams->cArgs == 0)
1704 return DISP_E_TYPEMISMATCH;
1705
1706 if (V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1]) != VT_BSTR)
1707 return DISP_E_TYPEMISMATCH;
1708
1709 VariantInit(&varg0);
1710 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1711 if (FAILED(hr))
1712 return hr;
1713
1714 VariantInit(&varg1);
1715 if (pDispParams->cArgs == 2)
1716 {
1717 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1718 if (FAILED(hr))
1719 goto done;
1720 }
1721 else
1722 {
1723 V_VT(&varg1) = VT_I4;
1724 V_I4(&varg1) = 0;
1725 }
1726
1727 V_VT(pVarResult) = VT_DISPATCH;
1728
1729 ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &hpkg);
1730 if (ret != ERROR_SUCCESS)
1731 {
1732 hr = DISP_E_EXCEPTION;
1733 goto done;
1734 }
1735
1736 hr = create_session(hpkg, &This->IDispatch_iface, &dispatch);
1737 if (SUCCEEDED(hr))
1738 V_DISPATCH(pVarResult) = dispatch;
1739
1740 done:
1741 VariantClear(&varg0);
1742 VariantClear(&varg1);
1743 return hr;
1744 }
1745
InstallerImpl_OpenProduct(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1746 static HRESULT InstallerImpl_OpenProduct(WORD wFlags,
1747 DISPPARAMS* pDispParams,
1748 VARIANT* pVarResult,
1749 EXCEPINFO* pExcepInfo,
1750 UINT* puArgErr)
1751 {
1752 HRESULT hr;
1753 VARIANTARG varg0;
1754
1755 if (!(wFlags & DISPATCH_METHOD))
1756 return DISP_E_MEMBERNOTFOUND;
1757
1758 VariantInit(&varg0);
1759 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1760 if (FAILED(hr))
1761 return hr;
1762
1763 FIXME("%s\n", debugstr_w(V_BSTR(&varg0)));
1764
1765 VariantInit(pVarResult);
1766
1767 VariantClear(&varg0);
1768 return S_OK;
1769 }
1770
InstallerImpl_OpenDatabase(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1771 static HRESULT InstallerImpl_OpenDatabase(WORD wFlags,
1772 DISPPARAMS* pDispParams,
1773 VARIANT* pVarResult,
1774 EXCEPINFO* pExcepInfo,
1775 UINT* puArgErr)
1776 {
1777 UINT ret;
1778 HRESULT hr;
1779 MSIHANDLE hdb;
1780 IDispatch* dispatch;
1781 VARIANTARG varg0, varg1;
1782
1783 if (!(wFlags & DISPATCH_METHOD))
1784 return DISP_E_MEMBERNOTFOUND;
1785
1786 VariantInit(&varg0);
1787 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1788 if (FAILED(hr))
1789 return hr;
1790
1791 VariantInit(&varg1);
1792 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1793 if (FAILED(hr))
1794 goto done;
1795
1796 V_VT(pVarResult) = VT_DISPATCH;
1797
1798 ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &hdb);
1799 if (ret != ERROR_SUCCESS)
1800 {
1801 hr = DISP_E_EXCEPTION;
1802 goto done;
1803 }
1804
1805 hr = create_database(hdb, &dispatch);
1806 if (SUCCEEDED(hr))
1807 V_DISPATCH(pVarResult) = dispatch;
1808
1809 done:
1810 VariantClear(&varg0);
1811 VariantClear(&varg1);
1812 return hr;
1813 }
1814
InstallerImpl_SummaryInformation(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1815 static HRESULT InstallerImpl_SummaryInformation(WORD wFlags,
1816 DISPPARAMS* pDispParams,
1817 VARIANT* pVarResult,
1818 EXCEPINFO* pExcepInfo,
1819 UINT* puArgErr)
1820 {
1821 UINT ret;
1822 HRESULT hr;
1823 MSIHANDLE hsuminfo;
1824 IDispatch *dispatch;
1825 VARIANTARG varg0, varg1;
1826
1827 if (!(wFlags & DISPATCH_PROPERTYGET))
1828 return DISP_E_MEMBERNOTFOUND;
1829
1830 VariantInit(&varg1);
1831 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr);
1832 if (FAILED(hr))
1833 return hr;
1834
1835 VariantInit(&varg0);
1836 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1837 if (FAILED(hr))
1838 return hr;
1839
1840 ret = MsiGetSummaryInformationW(0, V_BSTR(&varg0), V_I4(&varg1), &hsuminfo);
1841 VariantClear(&varg0);
1842 if (ret != ERROR_SUCCESS)
1843 return DISP_E_EXCEPTION;
1844
1845 hr = create_summaryinfo(hsuminfo, &dispatch);
1846 if (FAILED(hr))
1847 return hr;
1848
1849 V_VT(pVarResult) = VT_DISPATCH;
1850 V_DISPATCH(pVarResult) = dispatch;
1851 return S_OK;
1852 }
1853
InstallerImpl_UILevel(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1854 static HRESULT InstallerImpl_UILevel(WORD wFlags,
1855 DISPPARAMS* pDispParams,
1856 VARIANT* pVarResult,
1857 EXCEPINFO* pExcepInfo,
1858 UINT* puArgErr)
1859 {
1860 HRESULT hr;
1861 VARIANTARG varg0;
1862 INSTALLUILEVEL ui;
1863
1864 if (!(wFlags & DISPATCH_PROPERTYPUT) && !(wFlags & DISPATCH_PROPERTYGET))
1865 return DISP_E_MEMBERNOTFOUND;
1866
1867 if (wFlags & DISPATCH_PROPERTYPUT)
1868 {
1869 VariantInit(&varg0);
1870 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
1871 if (FAILED(hr))
1872 return hr;
1873
1874 ui = MsiSetInternalUI(V_I4(&varg0), NULL);
1875 if (ui == INSTALLUILEVEL_NOCHANGE)
1876 return DISP_E_EXCEPTION;
1877 }
1878 else if (wFlags & DISPATCH_PROPERTYGET)
1879 {
1880 ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL);
1881 if (ui == INSTALLUILEVEL_NOCHANGE)
1882 return DISP_E_EXCEPTION;
1883
1884 V_VT(pVarResult) = VT_I4;
1885 V_I4(pVarResult) = ui;
1886 }
1887
1888 return S_OK;
1889 }
1890
InstallerImpl_EnableLog(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1891 static HRESULT InstallerImpl_EnableLog(WORD wFlags,
1892 DISPPARAMS* pDispParams,
1893 VARIANT* pVarResult,
1894 EXCEPINFO* pExcepInfo,
1895 UINT* puArgErr)
1896 {
1897 if (!(wFlags & DISPATCH_METHOD))
1898 return DISP_E_MEMBERNOTFOUND;
1899
1900 FIXME("\n");
1901
1902 VariantInit(pVarResult);
1903 return S_OK;
1904 }
1905
InstallerImpl_InstallProduct(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1906 static HRESULT InstallerImpl_InstallProduct(WORD wFlags,
1907 DISPPARAMS* pDispParams,
1908 VARIANT* pVarResult,
1909 EXCEPINFO* pExcepInfo,
1910 UINT* puArgErr)
1911 {
1912 UINT ret;
1913 HRESULT hr;
1914 VARIANTARG varg0, varg1;
1915
1916 if (!(wFlags & DISPATCH_METHOD))
1917 return DISP_E_MEMBERNOTFOUND;
1918
1919 VariantInit(&varg0);
1920 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
1921 if (FAILED(hr))
1922 return hr;
1923
1924 VariantInit(&varg1);
1925 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
1926 if (FAILED(hr))
1927 goto done;
1928
1929 ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1));
1930 if (ret != ERROR_SUCCESS)
1931 {
1932 hr = DISP_E_EXCEPTION;
1933 goto done;
1934 }
1935
1936 done:
1937 VariantClear(&varg0);
1938 VariantClear(&varg1);
1939 return hr;
1940 }
1941
InstallerImpl_Version(WORD wFlags,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1942 static HRESULT InstallerImpl_Version(WORD wFlags,
1943 VARIANT* pVarResult,
1944 EXCEPINFO* pExcepInfo,
1945 UINT* puArgErr)
1946 {
1947 HRESULT hr;
1948 DLLVERSIONINFO verinfo;
1949 WCHAR version[MAX_PATH];
1950
1951 if (!(wFlags & DISPATCH_PROPERTYGET))
1952 return DISP_E_MEMBERNOTFOUND;
1953
1954 verinfo.cbSize = sizeof(DLLVERSIONINFO);
1955 hr = DllGetVersion(&verinfo);
1956 if (FAILED(hr))
1957 return hr;
1958
1959 swprintf(version, ARRAY_SIZE(version), L"%d.%d.%d.%d", verinfo.dwMajorVersion, verinfo.dwMinorVersion,
1960 verinfo.dwBuildNumber, verinfo.dwPlatformID);
1961
1962 V_VT(pVarResult) = VT_BSTR;
1963 V_BSTR(pVarResult) = SysAllocString(version);
1964 return S_OK;
1965 }
1966
InstallerImpl_LastErrorRecord(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1967 static HRESULT InstallerImpl_LastErrorRecord(WORD wFlags,
1968 DISPPARAMS* pDispParams,
1969 VARIANT* pVarResult,
1970 EXCEPINFO* pExcepInfo,
1971 UINT* puArgErr)
1972 {
1973 if (!(wFlags & DISPATCH_METHOD))
1974 return DISP_E_MEMBERNOTFOUND;
1975
1976 FIXME("\n");
1977
1978 VariantInit(pVarResult);
1979 return S_OK;
1980 }
1981
InstallerImpl_RegistryValue(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1982 static HRESULT InstallerImpl_RegistryValue(WORD wFlags,
1983 DISPPARAMS* pDispParams,
1984 VARIANT* pVarResult,
1985 EXCEPINFO* pExcepInfo,
1986 UINT* puArgErr)
1987 {
1988 UINT ret;
1989 HKEY hkey = NULL;
1990 HRESULT hr;
1991 UINT posValue;
1992 DWORD type, size;
1993 LPWSTR szString = NULL;
1994 VARIANTARG varg0, varg1, varg2;
1995
1996 if (!(wFlags & DISPATCH_METHOD))
1997 return DISP_E_MEMBERNOTFOUND;
1998
1999 VariantInit(&varg0);
2000 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
2001 if (FAILED(hr))
2002 return hr;
2003
2004 VariantInit(&varg1);
2005 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
2006 if (FAILED(hr))
2007 goto done;
2008
2009 /* Save valuePos so we can save puArgErr if we are unable to do our type
2010 * conversions.
2011 */
2012 posValue = 2;
2013 VariantInit(&varg2);
2014 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2);
2015 if (FAILED(hr))
2016 goto done;
2017
2018 if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT &&
2019 V_I4(&varg0) <= REG_INDEX_DYN_DATA)
2020 {
2021 V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT;
2022 }
2023
2024 ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey);
2025
2026 /* Only VT_EMPTY case can do anything if the key doesn't exist. */
2027 if (ret != ERROR_SUCCESS && V_VT(&varg2) != VT_EMPTY)
2028 {
2029 hr = DISP_E_BADINDEX;
2030 goto done;
2031 }
2032
2033 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
2034 switch (V_VT(&varg2))
2035 {
2036 /* Return VT_BOOL clarifying whether registry key exists or not. */
2037 case VT_EMPTY:
2038 V_VT(pVarResult) = VT_BOOL;
2039 V_BOOL(pVarResult) = (ret == ERROR_SUCCESS) ? VARIANT_TRUE : VARIANT_FALSE;
2040 break;
2041
2042 /* Return the value of specified key if it exists. */
2043 case VT_BSTR:
2044 ret = RegQueryValueExW(hkey, V_BSTR(&varg2),
2045 NULL, NULL, NULL, &size);
2046 if (ret != ERROR_SUCCESS)
2047 {
2048 hr = DISP_E_BADINDEX;
2049 goto done;
2050 }
2051
2052 szString = malloc(size);
2053 if (!szString)
2054 {
2055 hr = E_OUTOFMEMORY;
2056 goto done;
2057 }
2058
2059 ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL,
2060 &type, (LPBYTE)szString, &size);
2061 if (ret != ERROR_SUCCESS)
2062 {
2063 free(szString);
2064 hr = DISP_E_BADINDEX;
2065 goto done;
2066 }
2067
2068 variant_from_registry_value(pVarResult, type,
2069 (LPBYTE)szString, size);
2070 free(szString);
2071 break;
2072
2073 /* Try to make it into VT_I4, can use VariantChangeType for this. */
2074 default:
2075 hr = VariantChangeType(&varg2, &varg2, 0, VT_I4);
2076 if (FAILED(hr))
2077 {
2078 if (hr == DISP_E_TYPEMISMATCH)
2079 *puArgErr = posValue;
2080
2081 goto done;
2082 }
2083
2084 /* Retrieve class name or maximum value name or subkey name size. */
2085 if (!V_I4(&varg2))
2086 ret = RegQueryInfoKeyW(hkey, NULL, &size, NULL, NULL, NULL,
2087 NULL, NULL, NULL, NULL, NULL, NULL);
2088 else if (V_I4(&varg2) > 0)
2089 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL,
2090 NULL, NULL, &size, NULL, NULL, NULL);
2091 else /* V_I4(&varg2) < 0 */
2092 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &size,
2093 NULL, NULL, NULL, NULL, NULL, NULL);
2094
2095 if (ret != ERROR_SUCCESS)
2096 goto done;
2097
2098 szString = malloc(++size * sizeof(WCHAR));
2099 if (!szString)
2100 {
2101 hr = E_OUTOFMEMORY;
2102 goto done;
2103 }
2104
2105 if (!V_I4(&varg2))
2106 ret = RegQueryInfoKeyW(hkey, szString, &size,NULL, NULL, NULL,
2107 NULL, NULL, NULL, NULL, NULL, NULL);
2108 else if (V_I4(&varg2) > 0)
2109 ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString,
2110 &size, 0, 0, NULL, NULL);
2111 else /* V_I4(&varg2) < 0 */
2112 ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, size);
2113
2114 if (ret == ERROR_SUCCESS)
2115 {
2116 V_VT(pVarResult) = VT_BSTR;
2117 V_BSTR(pVarResult) = SysAllocString(szString);
2118 }
2119
2120 free(szString);
2121 }
2122
2123 done:
2124 VariantClear(&varg0);
2125 VariantClear(&varg1);
2126 VariantClear(&varg2);
2127 RegCloseKey(hkey);
2128 return hr;
2129 }
2130
InstallerImpl_Environment(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)2131 static HRESULT InstallerImpl_Environment(WORD wFlags,
2132 DISPPARAMS* pDispParams,
2133 VARIANT* pVarResult,
2134 EXCEPINFO* pExcepInfo,
2135 UINT* puArgErr)
2136 {
2137 if (!(wFlags & DISPATCH_METHOD))
2138 return DISP_E_MEMBERNOTFOUND;
2139
2140 FIXME("\n");
2141
2142 VariantInit(pVarResult);
2143 return S_OK;
2144 }
2145
InstallerImpl_FileAttributes(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)2146 static HRESULT InstallerImpl_FileAttributes(WORD wFlags,
2147 DISPPARAMS* pDispParams,
2148 VARIANT* pVarResult,
2149 EXCEPINFO* pExcepInfo,
2150 UINT* puArgErr)
2151 {
2152 if (!(wFlags & DISPATCH_METHOD))
2153 return DISP_E_MEMBERNOTFOUND;
2154
2155 FIXME("\n");
2156
2157 VariantInit(pVarResult);
2158 return S_OK;
2159 }
2160
InstallerImpl_FileSize(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)2161 static HRESULT InstallerImpl_FileSize(WORD wFlags,
2162 DISPPARAMS* pDispParams,
2163 VARIANT* pVarResult,
2164 EXCEPINFO* pExcepInfo,
2165 UINT* puArgErr)
2166 {
2167 if (!(wFlags & DISPATCH_METHOD))
2168 return DISP_E_MEMBERNOTFOUND;
2169
2170 FIXME("\n");
2171
2172 VariantInit(pVarResult);
2173 return S_OK;
2174 }
2175
InstallerImpl_FileVersion(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)2176 static HRESULT InstallerImpl_FileVersion(WORD wFlags,
2177 DISPPARAMS* pDispParams,
2178 VARIANT* pVarResult,
2179 EXCEPINFO* pExcepInfo,
2180 UINT* puArgErr)
2181 {
2182 if (!(wFlags & DISPATCH_METHOD))
2183 return DISP_E_MEMBERNOTFOUND;
2184
2185 FIXME("\n");
2186
2187 VariantInit(pVarResult);
2188 return S_OK;
2189 }
2190
InstallerImpl_ProductState(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)2191 static HRESULT InstallerImpl_ProductState(WORD wFlags,
2192 DISPPARAMS* pDispParams,
2193 VARIANT* pVarResult,
2194 EXCEPINFO* pExcepInfo,
2195 UINT* puArgErr)
2196 {
2197 HRESULT hr;
2198 VARIANTARG varg0;
2199
2200 if (!(wFlags & DISPATCH_PROPERTYGET))
2201 return DISP_E_MEMBERNOTFOUND;
2202
2203 VariantInit(&varg0);
2204 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2205 if (FAILED(hr))
2206 return hr;
2207
2208 V_VT(pVarResult) = VT_I4;
2209 V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0));
2210
2211 VariantClear(&varg0);
2212 return S_OK;
2213 }
2214
InstallerImpl_ProductInfo(WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)2215 static HRESULT InstallerImpl_ProductInfo(WORD wFlags,
2216 DISPPARAMS* pDispParams,
2217 VARIANT* pVarResult,
2218 EXCEPINFO* pExcepInfo,
2219 UINT* puArgErr)
2220 {
2221 UINT ret;
2222 HRESULT hr;
2223 DWORD size;
2224 LPWSTR str = NULL;
2225 VARIANTARG varg0, varg1;
2226
2227 if (!(wFlags & DISPATCH_PROPERTYGET))
2228 return DISP_E_MEMBERNOTFOUND;
2229
2230 VariantInit(&varg0);
2231 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
2232 if (FAILED(hr))
2233 return hr;
2234
2235 VariantInit(&varg1);
2236 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
2237 if (FAILED(hr))
2238 goto done;
2239
2240 V_VT(pVarResult) = VT_BSTR;
2241 V_BSTR(pVarResult) = NULL;
2242
2243 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &size);
2244 if (ret != ERROR_SUCCESS)
2245 {
2246 hr = DISP_E_EXCEPTION;
2247 goto done;
2248 }
2249
2250 str = malloc(++size * sizeof(WCHAR));
2251 if (!str)
2252 {
2253 hr = E_OUTOFMEMORY;
2254 goto done;
2255 }
2256
2257 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), str, &size);
2258 if (ret != ERROR_SUCCESS)
2259 {
2260 hr = DISP_E_EXCEPTION;
2261 goto done;
2262 }
2263
2264 V_BSTR(pVarResult) = SysAllocString(str);
2265 hr = S_OK;
2266
2267 done:
2268 free(str);
2269 VariantClear(&varg0);
2270 VariantClear(&varg1);
2271 return hr;
2272 }
2273
InstallerImpl_Products(WORD flags,DISPPARAMS * pDispParams,VARIANT * result,EXCEPINFO * pExcepInfo,UINT * puArgErr)2274 static HRESULT InstallerImpl_Products(WORD flags,
2275 DISPPARAMS* pDispParams,
2276 VARIANT* result,
2277 EXCEPINFO* pExcepInfo,
2278 UINT* puArgErr)
2279 {
2280 IDispatch *dispatch;
2281 HRESULT hr;
2282
2283 if (!(flags & DISPATCH_PROPERTYGET))
2284 return DISP_E_MEMBERNOTFOUND;
2285
2286 hr = create_list(NULL, &dispatch);
2287 if (FAILED(hr))
2288 return hr;
2289
2290 V_VT(result) = VT_DISPATCH;
2291 V_DISPATCH(result) = dispatch;
2292
2293 return hr;
2294 }
2295
InstallerImpl_RelatedProducts(WORD flags,DISPPARAMS * pDispParams,VARIANT * result,EXCEPINFO * pExcepInfo,UINT * puArgErr)2296 static HRESULT InstallerImpl_RelatedProducts(WORD flags,
2297 DISPPARAMS* pDispParams,
2298 VARIANT* result,
2299 EXCEPINFO* pExcepInfo,
2300 UINT* puArgErr)
2301 {
2302 IDispatch* dispatch;
2303 VARIANTARG related;
2304 HRESULT hr;
2305
2306 if (!(flags & DISPATCH_PROPERTYGET))
2307 return DISP_E_MEMBERNOTFOUND;
2308
2309 VariantInit(&related);
2310 hr = DispGetParam(pDispParams, 0, VT_BSTR, &related, puArgErr);
2311 if (FAILED(hr))
2312 return hr;
2313
2314 hr = create_list(V_BSTR(&related), &dispatch);
2315 VariantClear(&related);
2316
2317 V_VT(result) = VT_DISPATCH;
2318 V_DISPATCH(result) = dispatch;
2319
2320 return hr;
2321 }
2322
installer_invoke(struct automation_object * This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)2323 static HRESULT installer_invoke(
2324 struct automation_object *This,
2325 DISPID dispIdMember,
2326 REFIID riid,
2327 LCID lcid,
2328 WORD wFlags,
2329 DISPPARAMS* pDispParams,
2330 VARIANT* pVarResult,
2331 EXCEPINFO* pExcepInfo,
2332 UINT* puArgErr)
2333 {
2334 switch (dispIdMember)
2335 {
2336 case DISPID_INSTALLER_CREATERECORD:
2337 return InstallerImpl_CreateRecord(wFlags, pDispParams,
2338 pVarResult, pExcepInfo, puArgErr);
2339
2340 case DISPID_INSTALLER_OPENPACKAGE:
2341 return InstallerImpl_OpenPackage(This, wFlags, pDispParams,
2342 pVarResult, pExcepInfo, puArgErr);
2343
2344 case DISPID_INSTALLER_OPENPRODUCT:
2345 return InstallerImpl_OpenProduct(wFlags, pDispParams,
2346 pVarResult, pExcepInfo, puArgErr);
2347
2348 case DISPID_INSTALLER_OPENDATABASE:
2349 return InstallerImpl_OpenDatabase(wFlags, pDispParams,
2350 pVarResult, pExcepInfo, puArgErr);
2351
2352 case DISPID_INSTALLER_SUMMARYINFORMATION:
2353 return InstallerImpl_SummaryInformation(wFlags, pDispParams,
2354 pVarResult, pExcepInfo,
2355 puArgErr);
2356
2357 case DISPID_INSTALLER_UILEVEL:
2358 return InstallerImpl_UILevel(wFlags, pDispParams,
2359 pVarResult, pExcepInfo, puArgErr);
2360
2361 case DISPID_INSTALLER_ENABLELOG:
2362 return InstallerImpl_EnableLog(wFlags, pDispParams,
2363 pVarResult, pExcepInfo, puArgErr);
2364
2365 case DISPID_INSTALLER_INSTALLPRODUCT:
2366 return InstallerImpl_InstallProduct(wFlags, pDispParams,
2367 pVarResult, pExcepInfo,
2368 puArgErr);
2369
2370 case DISPID_INSTALLER_VERSION:
2371 return InstallerImpl_Version(wFlags, pVarResult,
2372 pExcepInfo, puArgErr);
2373
2374 case DISPID_INSTALLER_LASTERRORRECORD:
2375 return InstallerImpl_LastErrorRecord(wFlags, pDispParams,
2376 pVarResult, pExcepInfo,
2377 puArgErr);
2378
2379 case DISPID_INSTALLER_REGISTRYVALUE:
2380 return InstallerImpl_RegistryValue(wFlags, pDispParams,
2381 pVarResult, pExcepInfo,
2382 puArgErr);
2383
2384 case DISPID_INSTALLER_ENVIRONMENT:
2385 return InstallerImpl_Environment(wFlags, pDispParams,
2386 pVarResult, pExcepInfo, puArgErr);
2387
2388 case DISPID_INSTALLER_FILEATTRIBUTES:
2389 return InstallerImpl_FileAttributes(wFlags, pDispParams,
2390 pVarResult, pExcepInfo,
2391 puArgErr);
2392
2393 case DISPID_INSTALLER_FILESIZE:
2394 return InstallerImpl_FileSize(wFlags, pDispParams,
2395 pVarResult, pExcepInfo, puArgErr);
2396
2397 case DISPID_INSTALLER_FILEVERSION:
2398 return InstallerImpl_FileVersion(wFlags, pDispParams,
2399 pVarResult, pExcepInfo, puArgErr);
2400
2401 case DISPID_INSTALLER_PRODUCTSTATE:
2402 return InstallerImpl_ProductState(wFlags, pDispParams,
2403 pVarResult, pExcepInfo, puArgErr);
2404
2405 case DISPID_INSTALLER_PRODUCTINFO:
2406 return InstallerImpl_ProductInfo(wFlags, pDispParams,
2407 pVarResult, pExcepInfo, puArgErr);
2408
2409 case DISPID_INSTALLER_PRODUCTS:
2410 return InstallerImpl_Products(wFlags, pDispParams,
2411 pVarResult, pExcepInfo, puArgErr);
2412
2413 case DISPID_INSTALLER_RELATEDPRODUCTS:
2414 return InstallerImpl_RelatedProducts(wFlags, pDispParams,
2415 pVarResult, pExcepInfo,
2416 puArgErr);
2417
2418 default:
2419 return DISP_E_MEMBERNOTFOUND;
2420 }
2421 }
2422
create_msiserver(IUnknown * outer,void ** ppObj)2423 HRESULT create_msiserver(IUnknown *outer, void **ppObj)
2424 {
2425 struct automation_object *installer;
2426
2427 TRACE("(%p %p)\n", outer, ppObj);
2428
2429 if (outer)
2430 return CLASS_E_NOAGGREGATION;
2431
2432 installer = malloc(sizeof(*installer));
2433 if (!installer) return E_OUTOFMEMORY;
2434
2435 init_automation_object(installer, 0, Installer_tid);
2436
2437 *ppObj = &installer->IDispatch_iface;
2438
2439 return S_OK;
2440 }
2441
create_session(MSIHANDLE msiHandle,IDispatch * installer,IDispatch ** disp)2442 HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **disp)
2443 {
2444 struct session_object *session;
2445
2446 session = malloc(sizeof(*session));
2447 if (!session) return E_OUTOFMEMORY;
2448
2449 init_automation_object(&session->autoobj, msiHandle, Session_tid);
2450
2451 session->installer = installer;
2452 *disp = &session->autoobj.IDispatch_iface;
2453
2454 return S_OK;
2455 }
2456
create_database(MSIHANDLE msiHandle,IDispatch ** dispatch)2457 static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
2458 {
2459 struct automation_object *database;
2460
2461 TRACE("%lu %p\n", msiHandle, dispatch);
2462
2463 database = malloc(sizeof(*database));
2464 if (!database) return E_OUTOFMEMORY;
2465
2466 init_automation_object(database, msiHandle, Database_tid);
2467
2468 *dispatch = &database->IDispatch_iface;
2469
2470 return S_OK;
2471 }
2472
create_view(MSIHANDLE msiHandle,IDispatch ** dispatch)2473 static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch)
2474 {
2475 struct automation_object *view;
2476
2477 TRACE("%lu %p\n", msiHandle, dispatch);
2478
2479 view = malloc(sizeof(*view));
2480 if (!view) return E_OUTOFMEMORY;
2481
2482 init_automation_object(view, msiHandle, View_tid);
2483
2484 *dispatch = &view->IDispatch_iface;
2485
2486 return S_OK;
2487 }
2488
create_summaryinfo(MSIHANDLE msiHandle,IDispatch ** disp)2489 static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp)
2490 {
2491 struct automation_object *info;
2492
2493 info = malloc(sizeof(*info));
2494 if (!info) return E_OUTOFMEMORY;
2495
2496 init_automation_object(info, msiHandle, SummaryInfo_tid);
2497
2498 *disp = &info->IDispatch_iface;
2499
2500 return S_OK;
2501 }
2502