Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenautomation.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of OLE Automation for Microsoft Installer (msi.dll) 00003 * 00004 * Copyright 2007 Misha Koshelev 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #define COBJMACROS 00022 00023 #include <stdarg.h> 00024 #include "windef.h" 00025 #include "winbase.h" 00026 #include "winerror.h" 00027 #include "winuser.h" 00028 #include "winreg.h" 00029 #include "msidefs.h" 00030 #include "msipriv.h" 00031 #include "activscp.h" 00032 #include "oleauto.h" 00033 #include "shlwapi.h" 00034 #include "wine/debug.h" 00035 #include "wine/unicode.h" 00036 00037 #include "msiserver.h" 00038 #include "msiserver_dispids.h" 00039 00040 WINE_DEFAULT_DEBUG_CHANNEL(msi); 00041 00042 #define REG_INDEX_CLASSES_ROOT 0 00043 #define REG_INDEX_DYN_DATA 6 00044 00045 /* 00046 * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function 00047 * called from AutomationObject::Invoke. 00048 */ 00049 00050 typedef struct AutomationObject AutomationObject; 00051 00052 typedef HRESULT (*autoInvokeFunc)(AutomationObject* This, 00053 DISPID dispIdMember, REFIID riid, LCID lcid, WORD flags, DISPPARAMS* pDispParams, 00054 VARIANT* result, EXCEPINFO* ei, UINT* arg_err); 00055 00056 typedef void (*autoFreeFunc)(AutomationObject* This); 00057 00058 struct AutomationObject { 00059 IDispatch IDispatch_iface; 00060 IProvideMultipleClassInfo IProvideMultipleClassInfo_iface; 00061 LONG ref; 00062 00063 /* Clsid for this class and it's appropriate ITypeInfo object */ 00064 LPCLSID clsid; 00065 ITypeInfo *iTypeInfo; 00066 00067 /* The MSI handle of the current object */ 00068 MSIHANDLE msiHandle; 00069 00070 /* A function that is called from AutomationObject::Invoke, specific to this type of object. */ 00071 autoInvokeFunc funcInvoke; 00072 /* A function that is called from AutomationObject::Release when the object is being freed to free any private 00073 * data structures (or NULL) */ 00074 autoFreeFunc funcFree; 00075 }; 00076 00077 typedef struct { 00078 AutomationObject autoobj; 00079 int count; 00080 VARIANT *data; 00081 } ListObject; 00082 00083 static HRESULT create_database(MSIHANDLE, IDispatch**); 00084 static HRESULT create_list_enumerator(ListObject*, void**); 00085 static HRESULT create_summaryinfo(MSIHANDLE, IDispatch**); 00086 static HRESULT create_view(MSIHANDLE, IDispatch**); 00087 00088 /* ListEnumerator - IEnumVARIANT implementation for MSI automation lists */ 00089 typedef struct { 00090 IEnumVARIANT IEnumVARIANT_iface; 00091 LONG ref; 00092 00093 /* Current position and pointer to AutomationObject that stores actual data */ 00094 ULONG pos; 00095 ListObject *list; 00096 } ListEnumerator; 00097 00098 typedef struct { 00099 AutomationObject autoobj; 00100 IDispatch *installer; 00101 } SessionObject; 00102 00103 static inline AutomationObject *impl_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo *iface ) 00104 { 00105 return CONTAINING_RECORD(iface, AutomationObject, IProvideMultipleClassInfo_iface); 00106 } 00107 00108 static inline AutomationObject *impl_from_IDispatch( IDispatch *iface ) 00109 { 00110 return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface); 00111 } 00112 00113 /* Load type info so we don't have to process GetIDsOfNames */ 00114 HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid) 00115 { 00116 static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0}; 00117 ITypeInfo *ti = NULL; 00118 ITypeLib *lib = NULL; 00119 HRESULT hr; 00120 00121 TRACE("(%p)->(%s, %d)\n", iface, debugstr_guid(clsid), lcid); 00122 00123 /* Load registered type library */ 00124 hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, lcid, &lib); 00125 if (FAILED(hr)) { 00126 hr = LoadTypeLib(msiserverW, &lib); 00127 if (FAILED(hr)) { 00128 ERR("Could not load msiserver.tlb\n"); 00129 return hr; 00130 } 00131 } 00132 00133 /* Get type information for object */ 00134 hr = ITypeLib_GetTypeInfoOfGuid(lib, clsid, &ti); 00135 ITypeLib_Release(lib); 00136 if (FAILED(hr)) { 00137 ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid)); 00138 return hr; 00139 } 00140 *pptinfo = ti; 00141 return S_OK; 00142 } 00143 00144 /* AutomationObject methods */ 00145 static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject) 00146 { 00147 AutomationObject *This = impl_from_IDispatch(iface); 00148 00149 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject); 00150 00151 if (ppvObject == NULL) 00152 return E_INVALIDARG; 00153 00154 *ppvObject = 0; 00155 00156 if (IsEqualGUID(riid, &IID_IUnknown) || 00157 IsEqualGUID(riid, &IID_IDispatch) || 00158 IsEqualGUID(riid, This->clsid)) 00159 *ppvObject = &This->IDispatch_iface; 00160 else if (IsEqualGUID(riid, &IID_IProvideClassInfo) || 00161 IsEqualGUID(riid, &IID_IProvideClassInfo2) || 00162 IsEqualGUID(riid, &IID_IProvideMultipleClassInfo)) 00163 *ppvObject = &This->IProvideMultipleClassInfo_iface; 00164 else 00165 { 00166 TRACE("() : asking for unsupported interface %s\n", debugstr_guid(riid)); 00167 return E_NOINTERFACE; 00168 } 00169 00170 IDispatch_AddRef(iface); 00171 00172 return S_OK; 00173 } 00174 00175 static ULONG WINAPI AutomationObject_AddRef(IDispatch* iface) 00176 { 00177 AutomationObject *This = impl_from_IDispatch(iface); 00178 00179 TRACE("(%p/%p)\n", iface, This); 00180 00181 return InterlockedIncrement(&This->ref); 00182 } 00183 00184 static ULONG WINAPI AutomationObject_Release(IDispatch* iface) 00185 { 00186 AutomationObject *This = impl_from_IDispatch(iface); 00187 ULONG ref = InterlockedDecrement(&This->ref); 00188 00189 TRACE("(%p/%p)\n", iface, This); 00190 00191 if (!ref) 00192 { 00193 if (This->funcFree) This->funcFree(This); 00194 ITypeInfo_Release(This->iTypeInfo); 00195 MsiCloseHandle(This->msiHandle); 00196 msi_free(This); 00197 } 00198 00199 return ref; 00200 } 00201 00202 static HRESULT WINAPI AutomationObject_GetTypeInfoCount( 00203 IDispatch* iface, 00204 UINT* pctinfo) 00205 { 00206 AutomationObject *This = impl_from_IDispatch(iface); 00207 00208 TRACE("(%p/%p)->(%p)\n", iface, This, pctinfo); 00209 *pctinfo = 1; 00210 return S_OK; 00211 } 00212 00213 static HRESULT WINAPI AutomationObject_GetTypeInfo( 00214 IDispatch* iface, 00215 UINT iTInfo, 00216 LCID lcid, 00217 ITypeInfo** ppTInfo) 00218 { 00219 AutomationObject *This = impl_from_IDispatch(iface); 00220 TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo); 00221 00222 ITypeInfo_AddRef(This->iTypeInfo); 00223 *ppTInfo = This->iTypeInfo; 00224 return S_OK; 00225 } 00226 00227 static HRESULT WINAPI AutomationObject_GetIDsOfNames( 00228 IDispatch* iface, 00229 REFIID riid, 00230 LPOLESTR* rgszNames, 00231 UINT cNames, 00232 LCID lcid, 00233 DISPID* rgDispId) 00234 { 00235 AutomationObject *This = impl_from_IDispatch(iface); 00236 HRESULT hr; 00237 TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId); 00238 00239 if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG; 00240 hr = ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId); 00241 if (hr == DISP_E_UNKNOWNNAME) 00242 { 00243 UINT idx; 00244 for (idx=0; idx<cNames; idx++) 00245 { 00246 if (rgDispId[idx] == DISPID_UNKNOWN) 00247 FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(This->clsid)); 00248 } 00249 } 00250 return hr; 00251 } 00252 00253 /* Maximum number of allowed function parameters+1 */ 00254 #define MAX_FUNC_PARAMS 20 00255 00256 /* Some error checking is done here to simplify individual object function invocation */ 00257 static HRESULT WINAPI AutomationObject_Invoke( 00258 IDispatch* iface, 00259 DISPID dispIdMember, 00260 REFIID riid, 00261 LCID lcid, 00262 WORD wFlags, 00263 DISPPARAMS* pDispParams, 00264 VARIANT* pVarResult, 00265 EXCEPINFO* pExcepInfo, 00266 UINT* puArgErr) 00267 { 00268 AutomationObject *This = impl_from_IDispatch(iface); 00269 HRESULT hr; 00270 unsigned int uArgErr; 00271 VARIANT varResultDummy; 00272 BSTR bstrName = NULL; 00273 00274 TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface, This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 00275 00276 if (!IsEqualIID(riid, &IID_NULL)) 00277 { 00278 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid)); 00279 return DISP_E_UNKNOWNNAME; 00280 } 00281 00282 if (wFlags & DISPATCH_PROPERTYGET && !pVarResult) 00283 { 00284 ERR("NULL pVarResult not allowed when DISPATCH_PROPERTYGET specified\n"); 00285 return DISP_E_PARAMNOTOPTIONAL; 00286 } 00287 00288 /* This simplifies our individual object invocation functions */ 00289 if (puArgErr == NULL) puArgErr = &uArgErr; 00290 if (pVarResult == NULL) pVarResult = &varResultDummy; 00291 00292 /* Assume return type is void unless determined otherwise */ 00293 VariantInit(pVarResult); 00294 00295 /* If we are tracing, we want to see the name of the member we are invoking */ 00296 if (TRACE_ON(msi)) 00297 { 00298 ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL); 00299 TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName)); 00300 } 00301 00302 hr = This->funcInvoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr); 00303 00304 if (hr == DISP_E_MEMBERNOTFOUND) { 00305 if (bstrName == NULL) ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL); 00306 FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, debugstr_guid(This->clsid)); 00307 } 00308 else if (pExcepInfo && 00309 (hr == DISP_E_PARAMNOTFOUND || 00310 hr == DISP_E_EXCEPTION)) { 00311 static const WCHAR szComma[] = { ',',0 }; 00312 static const WCHAR szExceptionSource[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0}; 00313 WCHAR szExceptionDescription[MAX_PATH]; 00314 BSTR bstrParamNames[MAX_FUNC_PARAMS]; 00315 unsigned namesNo, i; 00316 BOOL bFirst = TRUE; 00317 00318 if (FAILED(ITypeInfo_GetNames(This->iTypeInfo, dispIdMember, bstrParamNames, 00319 MAX_FUNC_PARAMS, &namesNo))) 00320 { 00321 TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember); 00322 } 00323 else 00324 { 00325 memset(szExceptionDescription, 0, sizeof(szExceptionDescription)); 00326 for (i=0; i<namesNo; i++) 00327 { 00328 if (bFirst) bFirst = FALSE; 00329 else { 00330 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], szComma); 00331 } 00332 lstrcpyW(&szExceptionDescription[lstrlenW(szExceptionDescription)], bstrParamNames[i]); 00333 SysFreeString(bstrParamNames[i]); 00334 } 00335 00336 memset(pExcepInfo, 0, sizeof(EXCEPINFO)); 00337 pExcepInfo->wCode = 1000; 00338 pExcepInfo->bstrSource = SysAllocString(szExceptionSource); 00339 pExcepInfo->bstrDescription = SysAllocString(szExceptionDescription); 00340 hr = DISP_E_EXCEPTION; 00341 } 00342 } 00343 00344 /* Make sure we free the return variant if it is our dummy variant */ 00345 if (pVarResult == &varResultDummy) VariantClear(pVarResult); 00346 00347 /* Free function name if we retrieved it */ 00348 SysFreeString(bstrName); 00349 00350 TRACE("Returning 0x%08x, %s\n", hr, SUCCEEDED(hr) ? "ok" : "not ok"); 00351 00352 return hr; 00353 } 00354 00355 static const struct IDispatchVtbl AutomationObjectVtbl = 00356 { 00357 AutomationObject_QueryInterface, 00358 AutomationObject_AddRef, 00359 AutomationObject_Release, 00360 AutomationObject_GetTypeInfoCount, 00361 AutomationObject_GetTypeInfo, 00362 AutomationObject_GetIDsOfNames, 00363 AutomationObject_Invoke 00364 }; 00365 00366 /* 00367 * IProvideMultipleClassInfo methods 00368 */ 00369 00370 static HRESULT WINAPI ProvideMultipleClassInfo_QueryInterface( 00371 IProvideMultipleClassInfo* iface, 00372 REFIID riid, 00373 VOID** ppvoid) 00374 { 00375 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); 00376 return IDispatch_QueryInterface(&This->IDispatch_iface, riid, ppvoid); 00377 } 00378 00379 static ULONG WINAPI ProvideMultipleClassInfo_AddRef(IProvideMultipleClassInfo* iface) 00380 { 00381 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); 00382 return IDispatch_AddRef(&This->IDispatch_iface); 00383 } 00384 00385 static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo* iface) 00386 { 00387 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); 00388 return IDispatch_Release(&This->IDispatch_iface); 00389 } 00390 00391 static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI) 00392 { 00393 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); 00394 TRACE("(%p/%p)->(%p)\n", iface, This, ppTI); 00395 return load_type_info(&This->IDispatch_iface, ppTI, This->clsid, 0); 00396 } 00397 00398 static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID) 00399 { 00400 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); 00401 TRACE("(%p/%p)->(%d,%s)\n", iface, This, dwGuidKind, debugstr_guid(pGUID)); 00402 00403 if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID) 00404 return E_INVALIDARG; 00405 else { 00406 *pGUID = *This->clsid; 00407 return S_OK; 00408 } 00409 } 00410 00411 static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMultipleClassInfo* iface, ULONG* pcti) 00412 { 00413 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); 00414 00415 TRACE("(%p/%p)->(%p)\n", iface, This, pcti); 00416 *pcti = 1; 00417 return S_OK; 00418 } 00419 00420 static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface, 00421 ULONG iti, 00422 DWORD dwFlags, 00423 ITypeInfo** pptiCoClass, 00424 DWORD* pdwTIFlags, 00425 ULONG* pcdispidReserved, 00426 IID* piidPrimary, 00427 IID* piidSource) 00428 { 00429 AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); 00430 00431 TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, pptiCoClass, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource); 00432 00433 if (iti != 0) 00434 return E_INVALIDARG; 00435 00436 if (dwFlags & MULTICLASSINFO_GETTYPEINFO) 00437 load_type_info(&This->IDispatch_iface, pptiCoClass, This->clsid, 0); 00438 00439 if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS) 00440 { 00441 *pdwTIFlags = 0; 00442 *pcdispidReserved = 0; 00443 } 00444 00445 if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY){ 00446 *piidPrimary = *This->clsid; 00447 } 00448 00449 if (dwFlags & MULTICLASSINFO_GETIIDSOURCE){ 00450 *piidSource = *This->clsid; 00451 } 00452 00453 return S_OK; 00454 } 00455 00456 static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl = 00457 { 00458 ProvideMultipleClassInfo_QueryInterface, 00459 ProvideMultipleClassInfo_AddRef, 00460 ProvideMultipleClassInfo_Release, 00461 ProvideMultipleClassInfo_GetClassInfo, 00462 ProvideMultipleClassInfo_GetGUID, 00463 ProvideMultipleClassInfo_GetMultiTypeInfoCount, 00464 ProvideMultipleClassInfo_GetInfoOfIndex 00465 }; 00466 00467 static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, REFIID clsid, 00468 autoInvokeFunc invokeFunc, autoFreeFunc freeFunc) 00469 { 00470 TRACE("(%p, %d, %s, %p, %p)\n", This, msiHandle, debugstr_guid(clsid), invokeFunc, freeFunc); 00471 00472 This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl; 00473 This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl; 00474 This->ref = 1; 00475 00476 This->msiHandle = msiHandle; 00477 This->clsid = (LPCLSID)clsid; 00478 This->funcInvoke = invokeFunc; 00479 This->funcFree = freeFunc; 00480 00481 /* Load our TypeInfo so we don't have to process GetIDsOfNames */ 00482 This->iTypeInfo = NULL; 00483 return load_type_info(&This->IDispatch_iface, &This->iTypeInfo, clsid, 0); 00484 } 00485 00486 /* 00487 * ListEnumerator methods 00488 */ 00489 00490 static inline ListEnumerator *impl_from_IEnumVARIANT(IEnumVARIANT* iface) 00491 { 00492 return CONTAINING_RECORD(iface, ListEnumerator, IEnumVARIANT_iface); 00493 } 00494 00495 static HRESULT WINAPI ListEnumerator_QueryInterface(IEnumVARIANT* iface, REFIID riid, 00496 void** ppvObject) 00497 { 00498 ListEnumerator *This = impl_from_IEnumVARIANT(iface); 00499 00500 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject); 00501 00502 if (ppvObject == NULL) 00503 return E_INVALIDARG; 00504 00505 *ppvObject = 0; 00506 00507 if (IsEqualGUID(riid, &IID_IUnknown) || 00508 IsEqualGUID(riid, &IID_IEnumVARIANT)) 00509 { 00510 *ppvObject = &This->IEnumVARIANT_iface; 00511 } 00512 else 00513 { 00514 TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid)); 00515 return E_NOINTERFACE; 00516 } 00517 00518 IEnumVARIANT_AddRef(iface); 00519 return S_OK; 00520 } 00521 00522 static ULONG WINAPI ListEnumerator_AddRef(IEnumVARIANT* iface) 00523 { 00524 ListEnumerator *This = impl_from_IEnumVARIANT(iface); 00525 00526 TRACE("(%p/%p)\n", iface, This); 00527 00528 return InterlockedIncrement(&This->ref); 00529 } 00530 00531 static ULONG WINAPI ListEnumerator_Release(IEnumVARIANT* iface) 00532 { 00533 ListEnumerator *This = impl_from_IEnumVARIANT(iface); 00534 ULONG ref = InterlockedDecrement(&This->ref); 00535 00536 TRACE("(%p/%p)\n", iface, This); 00537 00538 if (!ref) 00539 { 00540 if (This->list) IDispatch_Release(&This->list->autoobj.IDispatch_iface); 00541 msi_free(This); 00542 } 00543 00544 return ref; 00545 } 00546 00547 static HRESULT WINAPI ListEnumerator_Next(IEnumVARIANT* iface, ULONG celt, VARIANT* rgVar, 00548 ULONG* fetched) 00549 { 00550 ListEnumerator *This = impl_from_IEnumVARIANT(iface); 00551 ULONG i, local; 00552 00553 TRACE("(%p, %uld, %p, %p)\n", iface, celt, rgVar, fetched); 00554 00555 if (fetched) *fetched = 0; 00556 00557 if (!rgVar) 00558 return S_FALSE; 00559 00560 for (local = 0; local < celt; local++) 00561 VariantInit(&rgVar[local]); 00562 00563 for (i = This->pos, local = 0; i < This->list->count && local < celt; i++, local++) 00564 VariantCopy(&rgVar[local], &This->list->data[i]); 00565 00566 if (fetched) *fetched = local; 00567 This->pos = i; 00568 00569 return (local < celt) ? S_FALSE : S_OK; 00570 } 00571 00572 static HRESULT WINAPI ListEnumerator_Skip(IEnumVARIANT* iface, ULONG celt) 00573 { 00574 ListEnumerator *This = impl_from_IEnumVARIANT(iface); 00575 00576 TRACE("(%p,%uld)\n", iface, celt); 00577 00578 This->pos += celt; 00579 if (This->pos >= This->list->count) 00580 { 00581 This->pos = This->list->count; 00582 return S_FALSE; 00583 } 00584 00585 return S_OK; 00586 } 00587 00588 static HRESULT WINAPI ListEnumerator_Reset(IEnumVARIANT* iface) 00589 { 00590 ListEnumerator *This = impl_from_IEnumVARIANT(iface); 00591 00592 TRACE("(%p)\n", iface); 00593 00594 This->pos = 0; 00595 return S_OK; 00596 } 00597 00598 static HRESULT WINAPI ListEnumerator_Clone(IEnumVARIANT* iface, IEnumVARIANT **ppEnum) 00599 { 00600 ListEnumerator *This = impl_from_IEnumVARIANT(iface); 00601 HRESULT hr; 00602 00603 TRACE("(%p,%p)\n", iface, ppEnum); 00604 00605 if (ppEnum == NULL) 00606 return S_FALSE; 00607 00608 *ppEnum = NULL; 00609 hr = create_list_enumerator(This->list, (LPVOID *)ppEnum); 00610 if (FAILED(hr)) 00611 { 00612 if (*ppEnum) 00613 IUnknown_Release(*ppEnum); 00614 return hr; 00615 } 00616 00617 return S_OK; 00618 } 00619 00620 static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl = 00621 { 00622 ListEnumerator_QueryInterface, 00623 ListEnumerator_AddRef, 00624 ListEnumerator_Release, 00625 ListEnumerator_Next, 00626 ListEnumerator_Skip, 00627 ListEnumerator_Reset, 00628 ListEnumerator_Clone 00629 }; 00630 00631 /* Create a list enumerator, placing the result in the pointer ppObj. */ 00632 static HRESULT create_list_enumerator(ListObject *list, void **ppObj) 00633 { 00634 ListEnumerator *object; 00635 00636 TRACE("(%p, %p)\n", list, ppObj); 00637 00638 object = msi_alloc(sizeof(ListEnumerator)); 00639 00640 /* Set all the VTable references */ 00641 object->IEnumVARIANT_iface.lpVtbl = &ListEnumerator_Vtbl; 00642 object->ref = 1; 00643 00644 /* Store data that was passed */ 00645 object->pos = 0; 00646 object->list = list; 00647 if (list) IDispatch_AddRef(&list->autoobj.IDispatch_iface); 00648 00649 *ppObj = object; 00650 return S_OK; 00651 } 00652 00653 /* 00654 * Individual Object Invocation Functions 00655 */ 00656 00657 /* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam. 00658 This function is only for VARIANT type parameters that have several types that cannot be properly discriminated 00659 using DispGetParam/VariantChangeType. */ 00660 static HRESULT DispGetParam_CopyOnly( 00661 DISPPARAMS *pdispparams, /* [in] Parameter list */ 00662 UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */ 00663 VARIANT *pvarResult) /* [out] Destination for resulting variant */ 00664 { 00665 /* position is counted backwards */ 00666 UINT pos; 00667 00668 TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n", 00669 *position, pdispparams->cArgs, pdispparams->cNamedArgs); 00670 if (*position < pdispparams->cArgs) { 00671 /* positional arg? */ 00672 pos = pdispparams->cArgs - *position - 1; 00673 } else { 00674 /* FIXME: is this how to handle named args? */ 00675 for (pos=0; pos<pdispparams->cNamedArgs; pos++) 00676 if (pdispparams->rgdispidNamedArgs[pos] == *position) break; 00677 00678 if (pos==pdispparams->cNamedArgs) 00679 return DISP_E_PARAMNOTFOUND; 00680 } 00681 *position = pos; 00682 return VariantCopyInd(pvarResult, 00683 &pdispparams->rgvarg[pos]); 00684 } 00685 00686 static HRESULT SummaryInfoImpl_Invoke( 00687 AutomationObject* This, 00688 DISPID dispIdMember, 00689 REFIID riid, 00690 LCID lcid, 00691 WORD wFlags, 00692 DISPPARAMS* pDispParams, 00693 VARIANT* pVarResult, 00694 EXCEPINFO* pExcepInfo, 00695 UINT* puArgErr) 00696 { 00697 UINT ret; 00698 VARIANTARG varg0, varg1; 00699 FILETIME ft, ftlocal; 00700 SYSTEMTIME st; 00701 HRESULT hr; 00702 00703 VariantInit(&varg0); 00704 VariantInit(&varg1); 00705 00706 switch (dispIdMember) 00707 { 00708 case DISPID_SUMMARYINFO_PROPERTY: 00709 if (wFlags & DISPATCH_PROPERTYGET) 00710 { 00711 UINT type; 00712 INT value; 00713 DWORD size = 0; 00714 DATE date; 00715 LPWSTR str; 00716 00717 static WCHAR szEmpty[] = {0}; 00718 00719 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 00720 if (FAILED(hr)) return hr; 00721 ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, &value, 00722 &ft, szEmpty, &size); 00723 if (ret != ERROR_SUCCESS && 00724 ret != ERROR_MORE_DATA) 00725 { 00726 ERR("MsiSummaryInfoGetProperty returned %d\n", ret); 00727 return DISP_E_EXCEPTION; 00728 } 00729 00730 switch (type) 00731 { 00732 case VT_EMPTY: 00733 break; 00734 00735 case VT_I2: 00736 case VT_I4: 00737 V_VT(pVarResult) = VT_I4; 00738 V_I4(pVarResult) = value; 00739 break; 00740 00741 case VT_LPSTR: 00742 if (!(str = msi_alloc(++size * sizeof(WCHAR)))) 00743 ERR("Out of memory\n"); 00744 else if ((ret = MsiSummaryInfoGetPropertyW(This->msiHandle, V_I4(&varg0), &type, NULL, 00745 NULL, str, &size)) != ERROR_SUCCESS) 00746 ERR("MsiSummaryInfoGetProperty returned %d\n", ret); 00747 else 00748 { 00749 V_VT(pVarResult) = VT_BSTR; 00750 V_BSTR(pVarResult) = SysAllocString(str); 00751 } 00752 msi_free(str); 00753 break; 00754 00755 case VT_FILETIME: 00756 FileTimeToLocalFileTime(&ft, &ftlocal); 00757 FileTimeToSystemTime(&ftlocal, &st); 00758 SystemTimeToVariantTime(&st, &date); 00759 00760 V_VT(pVarResult) = VT_DATE; 00761 V_DATE(pVarResult) = date; 00762 break; 00763 00764 default: 00765 ERR("Unhandled variant type %d\n", type); 00766 } 00767 } 00768 else if (wFlags & DISPATCH_PROPERTYPUT) 00769 { 00770 UINT posValue = DISPID_PROPERTYPUT; 00771 00772 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 00773 if (FAILED(hr)) return hr; 00774 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg1); 00775 if (FAILED(hr)) 00776 { 00777 *puArgErr = posValue; 00778 return hr; 00779 } 00780 00781 switch (V_VT(&varg1)) 00782 { 00783 case VT_I2: 00784 case VT_I4: 00785 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), V_VT(&varg1), V_I4(&varg1), NULL, NULL); 00786 break; 00787 00788 case VT_DATE: 00789 VariantTimeToSystemTime(V_DATE(&varg1), &st); 00790 SystemTimeToFileTime(&st, &ftlocal); 00791 LocalFileTimeToFileTime(&ftlocal, &ft); 00792 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_FILETIME, 0, &ft, NULL); 00793 break; 00794 00795 case VT_BSTR: 00796 ret = MsiSummaryInfoSetPropertyW(This->msiHandle, V_I4(&varg0), VT_LPSTR, 0, NULL, V_BSTR(&varg1)); 00797 break; 00798 00799 default: 00800 FIXME("Unhandled variant type %d\n", V_VT(&varg1)); 00801 VariantClear(&varg1); 00802 return DISP_E_EXCEPTION; 00803 } 00804 00805 if (ret != ERROR_SUCCESS) 00806 { 00807 ERR("MsiSummaryInfoSetPropertyW returned %d\n", ret); 00808 return DISP_E_EXCEPTION; 00809 } 00810 } 00811 else return DISP_E_MEMBERNOTFOUND; 00812 break; 00813 00814 case DISPID_SUMMARYINFO_PROPERTYCOUNT: 00815 if (wFlags & DISPATCH_PROPERTYGET) { 00816 UINT count; 00817 if ((ret = MsiSummaryInfoGetPropertyCount(This->msiHandle, &count)) != ERROR_SUCCESS) 00818 ERR("MsiSummaryInfoGetPropertyCount returned %d\n", ret); 00819 else 00820 { 00821 V_VT(pVarResult) = VT_I4; 00822 V_I4(pVarResult) = count; 00823 } 00824 } 00825 else return DISP_E_MEMBERNOTFOUND; 00826 break; 00827 00828 default: 00829 return DISP_E_MEMBERNOTFOUND; 00830 } 00831 00832 VariantClear(&varg1); 00833 VariantClear(&varg0); 00834 00835 return S_OK; 00836 } 00837 00838 static HRESULT RecordImpl_Invoke( 00839 AutomationObject* This, 00840 DISPID dispIdMember, 00841 REFIID riid, 00842 LCID lcid, 00843 WORD wFlags, 00844 DISPPARAMS* pDispParams, 00845 VARIANT* pVarResult, 00846 EXCEPINFO* pExcepInfo, 00847 UINT* puArgErr) 00848 { 00849 WCHAR *szString; 00850 DWORD dwLen; 00851 UINT ret; 00852 VARIANTARG varg0, varg1; 00853 HRESULT hr; 00854 00855 VariantInit(&varg0); 00856 VariantInit(&varg1); 00857 00858 switch (dispIdMember) 00859 { 00860 case DISPID_RECORD_FIELDCOUNT: 00861 if (wFlags & DISPATCH_PROPERTYGET) { 00862 V_VT(pVarResult) = VT_I4; 00863 V_I4(pVarResult) = MsiRecordGetFieldCount(This->msiHandle); 00864 } 00865 else return DISP_E_MEMBERNOTFOUND; 00866 break; 00867 00868 case DISPID_RECORD_STRINGDATA: 00869 if (wFlags & DISPATCH_PROPERTYGET) { 00870 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 00871 if (FAILED(hr)) return hr; 00872 V_VT(pVarResult) = VT_BSTR; 00873 V_BSTR(pVarResult) = NULL; 00874 if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), NULL, &dwLen)) == ERROR_SUCCESS) 00875 { 00876 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR)))) 00877 ERR("Out of memory\n"); 00878 else if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&varg0), szString, &dwLen)) == ERROR_SUCCESS) 00879 V_BSTR(pVarResult) = SysAllocString(szString); 00880 msi_free(szString); 00881 } 00882 if (ret != ERROR_SUCCESS) 00883 ERR("MsiRecordGetString returned %d\n", ret); 00884 } else if (wFlags & DISPATCH_PROPERTYPUT) { 00885 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 00886 if (FAILED(hr)) return hr; 00887 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); 00888 if (FAILED(hr)) return hr; 00889 if ((ret = MsiRecordSetStringW(This->msiHandle, V_I4(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS) 00890 { 00891 VariantClear(&varg1); 00892 ERR("MsiRecordSetString returned %d\n", ret); 00893 return DISP_E_EXCEPTION; 00894 } 00895 } 00896 else return DISP_E_MEMBERNOTFOUND; 00897 break; 00898 00899 case DISPID_RECORD_INTEGERDATA: 00900 if (wFlags & DISPATCH_PROPERTYGET) { 00901 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 00902 if (FAILED(hr)) return hr; 00903 V_VT(pVarResult) = VT_I4; 00904 V_I4(pVarResult) = MsiRecordGetInteger(This->msiHandle, V_I4(&varg0)); 00905 } else if (wFlags & DISPATCH_PROPERTYPUT) { 00906 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 00907 if (FAILED(hr)) return hr; 00908 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr); 00909 if (FAILED(hr)) return hr; 00910 if ((ret = MsiRecordSetInteger(This->msiHandle, V_I4(&varg0), V_I4(&varg1))) != ERROR_SUCCESS) 00911 { 00912 ERR("MsiRecordSetInteger returned %d\n", ret); 00913 return DISP_E_EXCEPTION; 00914 } 00915 } 00916 else return DISP_E_MEMBERNOTFOUND; 00917 break; 00918 00919 default: 00920 return DISP_E_MEMBERNOTFOUND; 00921 } 00922 00923 VariantClear(&varg1); 00924 VariantClear(&varg0); 00925 00926 return S_OK; 00927 } 00928 00929 static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp) 00930 { 00931 AutomationObject *record; 00932 HRESULT hr; 00933 00934 record = msi_alloc(sizeof(*record)); 00935 if (!record) return E_OUTOFMEMORY; 00936 00937 hr = init_automation_object(record, msiHandle, &DIID_Record, RecordImpl_Invoke, NULL); 00938 if (hr != S_OK) 00939 { 00940 msi_free(record); 00941 return hr; 00942 } 00943 00944 *disp = &record->IDispatch_iface; 00945 00946 return hr; 00947 } 00948 00949 static HRESULT ListImpl_Invoke( 00950 AutomationObject* This, 00951 DISPID dispIdMember, 00952 REFIID riid, 00953 LCID lcid, 00954 WORD wFlags, 00955 DISPPARAMS* pDispParams, 00956 VARIANT* pVarResult, 00957 EXCEPINFO* pExcepInfo, 00958 UINT* puArgErr) 00959 { 00960 ListObject *list = (ListObject*)This; 00961 IUnknown *pUnk = NULL; 00962 HRESULT hr; 00963 00964 switch (dispIdMember) 00965 { 00966 case DISPID_LIST__NEWENUM: 00967 if (wFlags & DISPATCH_METHOD) { 00968 V_VT(pVarResult) = VT_UNKNOWN; 00969 if (SUCCEEDED(hr = create_list_enumerator(list, (LPVOID *)&pUnk))) 00970 V_UNKNOWN(pVarResult) = pUnk; 00971 else 00972 ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr); 00973 } 00974 else return DISP_E_MEMBERNOTFOUND; 00975 break; 00976 00977 case DISPID_LIST_ITEM: 00978 if (wFlags & DISPATCH_PROPERTYGET) { 00979 VARIANTARG index; 00980 00981 VariantInit(&index); 00982 hr = DispGetParam(pDispParams, 0, VT_I4, &index, puArgErr); 00983 if (FAILED(hr)) return hr; 00984 if (V_I4(&index) < 0 || V_I4(&index) >= list->count) 00985 return DISP_E_BADINDEX; 00986 VariantCopy(pVarResult, &list->data[V_I4(&index)]); 00987 } 00988 else return DISP_E_MEMBERNOTFOUND; 00989 break; 00990 00991 case DISPID_LIST_COUNT: 00992 if (wFlags & DISPATCH_PROPERTYGET) { 00993 V_VT(pVarResult) = VT_I4; 00994 V_I4(pVarResult) = list->count; 00995 } 00996 else return DISP_E_MEMBERNOTFOUND; 00997 break; 00998 00999 default: 01000 return DISP_E_MEMBERNOTFOUND; 01001 } 01002 01003 return S_OK; 01004 } 01005 01006 static void ListImpl_Free(AutomationObject *This) 01007 { 01008 ListObject *list = (ListObject*)This; 01009 int i; 01010 01011 for (i = 0; i < list->count; i++) 01012 VariantClear(&list->data[i]); 01013 msi_free(list->data); 01014 } 01015 01016 static HRESULT get_products_count(const WCHAR *product, int *len) 01017 { 01018 int i = 0; 01019 01020 while (1) 01021 { 01022 WCHAR dataW[GUID_SIZE]; 01023 UINT ret; 01024 01025 /* all or related only */ 01026 if (product) 01027 ret = MsiEnumRelatedProductsW(product, 0, i, dataW); 01028 else 01029 ret = MsiEnumProductsW(i, dataW); 01030 01031 if (ret == ERROR_NO_MORE_ITEMS) break; 01032 01033 if (ret != ERROR_SUCCESS) 01034 return DISP_E_EXCEPTION; 01035 01036 i++; 01037 } 01038 01039 *len = i; 01040 01041 return S_OK; 01042 } 01043 01044 static HRESULT create_list(const WCHAR *product, IDispatch **dispatch) 01045 { 01046 ListObject *list; 01047 HRESULT hr; 01048 int i; 01049 01050 list = msi_alloc_zero(sizeof(ListObject)); 01051 if (!list) return E_OUTOFMEMORY; 01052 01053 hr = init_automation_object(&list->autoobj, 0, &DIID_StringList, ListImpl_Invoke, ListImpl_Free); 01054 if (hr != S_OK) 01055 { 01056 msi_free(list); 01057 return hr; 01058 } 01059 01060 *dispatch = &list->autoobj.IDispatch_iface; 01061 01062 hr = get_products_count(product, &list->count); 01063 if (hr != S_OK) 01064 { 01065 IDispatch_Release(*dispatch); 01066 return hr; 01067 } 01068 01069 list->data = msi_alloc(list->count*sizeof(VARIANT)); 01070 if (!list->data) 01071 { 01072 IDispatch_Release(*dispatch); 01073 return E_OUTOFMEMORY; 01074 } 01075 01076 for (i = 0; i < list->count; i++) 01077 { 01078 WCHAR dataW[GUID_SIZE]; 01079 UINT ret; 01080 01081 /* all or related only */ 01082 if (product) 01083 ret = MsiEnumRelatedProductsW(product, 0, i, dataW); 01084 else 01085 ret = MsiEnumProductsW(i, dataW); 01086 01087 if (ret == ERROR_NO_MORE_ITEMS) break; 01088 01089 V_VT(&list->data[i]) = VT_BSTR; 01090 V_BSTR(&list->data[i]) = SysAllocString(dataW); 01091 } 01092 01093 return S_OK; 01094 } 01095 01096 static HRESULT ViewImpl_Invoke( 01097 AutomationObject* This, 01098 DISPID dispIdMember, 01099 REFIID riid, 01100 LCID lcid, 01101 WORD wFlags, 01102 DISPPARAMS* pDispParams, 01103 VARIANT* pVarResult, 01104 EXCEPINFO* pExcepInfo, 01105 UINT* puArgErr) 01106 { 01107 MSIHANDLE msiHandle; 01108 UINT ret; 01109 VARIANTARG varg0, varg1; 01110 HRESULT hr; 01111 01112 VariantInit(&varg0); 01113 VariantInit(&varg1); 01114 01115 switch (dispIdMember) 01116 { 01117 case DISPID_VIEW_EXECUTE: 01118 if (wFlags & DISPATCH_METHOD) 01119 { 01120 hr = DispGetParam(pDispParams, 0, VT_DISPATCH, &varg0, puArgErr); 01121 if (SUCCEEDED(hr) && V_DISPATCH(&varg0) != NULL) 01122 MsiViewExecute(This->msiHandle, ((AutomationObject *)V_DISPATCH(&varg0))->msiHandle); 01123 else 01124 MsiViewExecute(This->msiHandle, 0); 01125 } 01126 else return DISP_E_MEMBERNOTFOUND; 01127 break; 01128 01129 case DISPID_VIEW_FETCH: 01130 if (wFlags & DISPATCH_METHOD) 01131 { 01132 V_VT(pVarResult) = VT_DISPATCH; 01133 if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS) 01134 { 01135 IDispatch *dispatch = NULL; 01136 01137 if (SUCCEEDED(hr = create_record(msiHandle, &dispatch))) 01138 V_DISPATCH(pVarResult) = dispatch; 01139 else 01140 ERR("Failed to create Record object, hresult 0x%08x\n", hr); 01141 } 01142 else if (ret == ERROR_NO_MORE_ITEMS) 01143 V_DISPATCH(pVarResult) = NULL; 01144 else 01145 { 01146 ERR("MsiViewFetch returned %d\n", ret); 01147 return DISP_E_EXCEPTION; 01148 } 01149 } 01150 else return DISP_E_MEMBERNOTFOUND; 01151 break; 01152 01153 case DISPID_VIEW_MODIFY: 01154 if (wFlags & DISPATCH_METHOD) 01155 { 01156 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01157 if (FAILED(hr)) return hr; 01158 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr); 01159 if (FAILED(hr)) return hr; 01160 if (!V_DISPATCH(&varg1)) return DISP_E_EXCEPTION; 01161 if ((ret = MsiViewModify(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle)) != ERROR_SUCCESS) 01162 { 01163 VariantClear(&varg1); 01164 ERR("MsiViewModify returned %d\n", ret); 01165 return DISP_E_EXCEPTION; 01166 } 01167 } 01168 else return DISP_E_MEMBERNOTFOUND; 01169 break; 01170 01171 case DISPID_VIEW_CLOSE: 01172 if (wFlags & DISPATCH_METHOD) 01173 { 01174 MsiViewClose(This->msiHandle); 01175 } 01176 else return DISP_E_MEMBERNOTFOUND; 01177 break; 01178 01179 default: 01180 return DISP_E_MEMBERNOTFOUND; 01181 } 01182 01183 VariantClear(&varg1); 01184 VariantClear(&varg0); 01185 01186 return S_OK; 01187 } 01188 01189 static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags, 01190 DISPPARAMS* pDispParams, 01191 VARIANT* pVarResult, 01192 EXCEPINFO* pExcepInfo, 01193 UINT* puArgErr) 01194 { 01195 if (!(wFlags & DISPATCH_METHOD)) 01196 return DISP_E_MEMBERNOTFOUND; 01197 01198 FIXME("\n"); 01199 01200 VariantInit(pVarResult); 01201 return S_OK; 01202 } 01203 01204 static HRESULT DatabaseImpl_Invoke( 01205 AutomationObject* This, 01206 DISPID dispIdMember, 01207 REFIID riid, 01208 LCID lcid, 01209 WORD wFlags, 01210 DISPPARAMS* pDispParams, 01211 VARIANT* pVarResult, 01212 EXCEPINFO* pExcepInfo, 01213 UINT* puArgErr) 01214 { 01215 IDispatch *dispatch = NULL; 01216 MSIHANDLE msiHandle; 01217 UINT ret; 01218 VARIANTARG varg0, varg1; 01219 HRESULT hr; 01220 01221 VariantInit(&varg0); 01222 VariantInit(&varg1); 01223 01224 switch (dispIdMember) 01225 { 01226 case DISPID_DATABASE_SUMMARYINFORMATION: 01227 if (wFlags & DISPATCH_PROPERTYGET) 01228 { 01229 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01230 if (FAILED(hr)) 01231 V_I4(&varg0) = 0; 01232 01233 V_VT(pVarResult) = VT_DISPATCH; 01234 if ((ret = MsiGetSummaryInformationW(This->msiHandle, NULL, V_I4(&varg0), &msiHandle)) == ERROR_SUCCESS) 01235 { 01236 hr = create_summaryinfo(msiHandle, &dispatch); 01237 if (SUCCEEDED(hr)) 01238 V_DISPATCH(pVarResult) = dispatch; 01239 else 01240 ERR("Failed to create SummaryInfo object: 0x%08x\n", hr); 01241 } 01242 else 01243 { 01244 ERR("MsiGetSummaryInformation returned %d\n", ret); 01245 return DISP_E_EXCEPTION; 01246 } 01247 } 01248 else return DISP_E_MEMBERNOTFOUND; 01249 break; 01250 01251 case DISPID_DATABASE_OPENVIEW: 01252 if (wFlags & DISPATCH_METHOD) 01253 { 01254 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01255 if (FAILED(hr)) return hr; 01256 V_VT(pVarResult) = VT_DISPATCH; 01257 if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS) 01258 { 01259 if (SUCCEEDED(hr = create_view(msiHandle, &dispatch))) 01260 V_DISPATCH(pVarResult) = dispatch; 01261 else 01262 ERR("Failed to create View object, hresult 0x%08x\n", hr); 01263 } 01264 else 01265 { 01266 VariantClear(&varg0); 01267 ERR("MsiDatabaseOpenView returned %d\n", ret); 01268 return DISP_E_EXCEPTION; 01269 } 01270 } 01271 else return DISP_E_MEMBERNOTFOUND; 01272 break; 01273 01274 case DISPID_INSTALLER_LASTERRORRECORD: 01275 return DatabaseImpl_LastErrorRecord(wFlags, pDispParams, 01276 pVarResult, pExcepInfo, 01277 puArgErr); 01278 01279 default: 01280 return DISP_E_MEMBERNOTFOUND; 01281 } 01282 01283 VariantClear(&varg1); 01284 VariantClear(&varg0); 01285 01286 return S_OK; 01287 } 01288 01289 static HRESULT SessionImpl_Invoke( 01290 AutomationObject* This, 01291 DISPID dispIdMember, 01292 REFIID riid, 01293 LCID lcid, 01294 WORD wFlags, 01295 DISPPARAMS* pDispParams, 01296 VARIANT* pVarResult, 01297 EXCEPINFO* pExcepInfo, 01298 UINT* puArgErr) 01299 { 01300 SessionObject *session = (SessionObject*)This; 01301 WCHAR *szString; 01302 DWORD dwLen; 01303 MSIHANDLE msiHandle; 01304 LANGID langId; 01305 UINT ret; 01306 INSTALLSTATE iInstalled, iAction; 01307 VARIANTARG varg0, varg1; 01308 HRESULT hr; 01309 01310 VariantInit(&varg0); 01311 VariantInit(&varg1); 01312 01313 switch (dispIdMember) 01314 { 01315 case DISPID_SESSION_INSTALLER: 01316 if (wFlags & DISPATCH_PROPERTYGET) { 01317 V_VT(pVarResult) = VT_DISPATCH; 01318 IDispatch_AddRef(session->installer); 01319 V_DISPATCH(pVarResult) = session->installer; 01320 } 01321 else return DISP_E_MEMBERNOTFOUND; 01322 break; 01323 01324 case DISPID_SESSION_PROPERTY: 01325 if (wFlags & DISPATCH_PROPERTYGET) { 01326 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01327 if (FAILED(hr)) return hr; 01328 V_VT(pVarResult) = VT_BSTR; 01329 V_BSTR(pVarResult) = NULL; 01330 if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), NULL, &dwLen)) == ERROR_SUCCESS) 01331 { 01332 if (!(szString = msi_alloc((++dwLen)*sizeof(WCHAR)))) 01333 ERR("Out of memory\n"); 01334 else if ((ret = MsiGetPropertyW(This->msiHandle, V_BSTR(&varg0), szString, &dwLen)) == ERROR_SUCCESS) 01335 V_BSTR(pVarResult) = SysAllocString(szString); 01336 msi_free(szString); 01337 } 01338 if (ret != ERROR_SUCCESS) 01339 ERR("MsiGetProperty returned %d\n", ret); 01340 } else if (wFlags & DISPATCH_PROPERTYPUT) { 01341 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01342 if (FAILED(hr)) return hr; 01343 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); 01344 if (FAILED(hr)) { 01345 VariantClear(&varg0); 01346 return hr; 01347 } 01348 if ((ret = MsiSetPropertyW(This->msiHandle, V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS) 01349 { 01350 VariantClear(&varg0); 01351 VariantClear(&varg1); 01352 ERR("MsiSetProperty returned %d\n", ret); 01353 return DISP_E_EXCEPTION; 01354 } 01355 } 01356 else return DISP_E_MEMBERNOTFOUND; 01357 break; 01358 01359 case DISPID_SESSION_LANGUAGE: 01360 if (wFlags & DISPATCH_PROPERTYGET) { 01361 langId = MsiGetLanguage(This->msiHandle); 01362 V_VT(pVarResult) = VT_I4; 01363 V_I4(pVarResult) = langId; 01364 } 01365 else return DISP_E_MEMBERNOTFOUND; 01366 break; 01367 01368 case DISPID_SESSION_MODE: 01369 if (wFlags & DISPATCH_PROPERTYGET) { 01370 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01371 if (FAILED(hr)) return hr; 01372 V_VT(pVarResult) = VT_BOOL; 01373 V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&varg0)); 01374 } else if (wFlags & DISPATCH_PROPERTYPUT) { 01375 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01376 if (FAILED(hr)) return hr; 01377 hr = DispGetParam(pDispParams, 1, VT_BOOL, &varg1, puArgErr); 01378 if (FAILED(hr)) return hr; 01379 if ((ret = MsiSetMode(This->msiHandle, V_I4(&varg0), V_BOOL(&varg1))) != ERROR_SUCCESS) 01380 { 01381 ERR("MsiSetMode returned %d\n", ret); 01382 return DISP_E_EXCEPTION; 01383 } 01384 } 01385 else return DISP_E_MEMBERNOTFOUND; 01386 break; 01387 01388 case DISPID_SESSION_DATABASE: 01389 if (wFlags & DISPATCH_PROPERTYGET) { 01390 V_VT(pVarResult) = VT_DISPATCH; 01391 if ((msiHandle = MsiGetActiveDatabase(This->msiHandle))) 01392 { 01393 IDispatch *dispatch; 01394 01395 if (SUCCEEDED(hr = create_database(msiHandle, &dispatch))) 01396 V_DISPATCH(pVarResult) = dispatch; 01397 else 01398 ERR("Failed to create Database object, hresult 0x%08x\n", hr); 01399 } 01400 else 01401 { 01402 ERR("MsiGetActiveDatabase failed\n"); 01403 return DISP_E_EXCEPTION; 01404 } 01405 } 01406 else return DISP_E_MEMBERNOTFOUND; 01407 break; 01408 01409 case DISPID_SESSION_DOACTION: 01410 if (wFlags & DISPATCH_METHOD) { 01411 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01412 if (FAILED(hr)) return hr; 01413 ret = MsiDoActionW(This->msiHandle, V_BSTR(&varg0)); 01414 V_VT(pVarResult) = VT_I4; 01415 switch (ret) 01416 { 01417 case ERROR_FUNCTION_NOT_CALLED: 01418 V_I4(pVarResult) = msiDoActionStatusNoAction; 01419 break; 01420 case ERROR_SUCCESS: 01421 V_I4(pVarResult) = msiDoActionStatusSuccess; 01422 break; 01423 case ERROR_INSTALL_USEREXIT: 01424 V_I4(pVarResult) = msiDoActionStatusUserExit; 01425 break; 01426 case ERROR_INSTALL_FAILURE: 01427 V_I4(pVarResult) = msiDoActionStatusFailure; 01428 break; 01429 case ERROR_INSTALL_SUSPEND: 01430 V_I4(pVarResult) = msiDoActionStatusSuspend; 01431 break; 01432 case ERROR_MORE_DATA: 01433 V_I4(pVarResult) = msiDoActionStatusFinished; 01434 break; 01435 case ERROR_INVALID_HANDLE_STATE: 01436 V_I4(pVarResult) = msiDoActionStatusWrongState; 01437 break; 01438 case ERROR_INVALID_DATA: 01439 V_I4(pVarResult) = msiDoActionStatusBadActionData; 01440 break; 01441 default: 01442 VariantClear(&varg0); 01443 FIXME("MsiDoAction returned unhandled value %d\n", ret); 01444 return DISP_E_EXCEPTION; 01445 } 01446 } 01447 else return DISP_E_MEMBERNOTFOUND; 01448 break; 01449 01450 case DISPID_SESSION_EVALUATECONDITION: 01451 if (wFlags & DISPATCH_METHOD) { 01452 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01453 if (FAILED(hr)) return hr; 01454 V_VT(pVarResult) = VT_I4; 01455 V_I4(pVarResult) = MsiEvaluateConditionW(This->msiHandle, V_BSTR(&varg0)); 01456 } 01457 else return DISP_E_MEMBERNOTFOUND; 01458 break; 01459 01460 case DISPID_SESSION_MESSAGE: 01461 if(!(wFlags & DISPATCH_METHOD)) 01462 return DISP_E_MEMBERNOTFOUND; 01463 01464 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01465 if (FAILED(hr)) return hr; 01466 hr = DispGetParam(pDispParams, 1, VT_DISPATCH, &varg1, puArgErr); 01467 if (FAILED(hr)) return hr; 01468 01469 V_VT(pVarResult) = VT_I4; 01470 V_I4(pVarResult) = 01471 MsiProcessMessage(This->msiHandle, V_I4(&varg0), ((AutomationObject *)V_DISPATCH(&varg1))->msiHandle); 01472 break; 01473 01474 case DISPID_SESSION_SETINSTALLLEVEL: 01475 if (wFlags & DISPATCH_METHOD) { 01476 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01477 if (FAILED(hr)) return hr; 01478 if ((ret = MsiSetInstallLevel(This->msiHandle, V_I4(&varg0))) != ERROR_SUCCESS) 01479 { 01480 ERR("MsiSetInstallLevel returned %d\n", ret); 01481 return DISP_E_EXCEPTION; 01482 } 01483 } 01484 else return DISP_E_MEMBERNOTFOUND; 01485 break; 01486 01487 case DISPID_SESSION_FEATURECURRENTSTATE: 01488 if (wFlags & DISPATCH_PROPERTYGET) { 01489 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01490 if (FAILED(hr)) return hr; 01491 V_VT(pVarResult) = VT_I4; 01492 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS) 01493 V_I4(pVarResult) = iInstalled; 01494 else 01495 { 01496 ERR("MsiGetFeatureState returned %d\n", ret); 01497 V_I4(pVarResult) = msiInstallStateUnknown; 01498 } 01499 } 01500 else return DISP_E_MEMBERNOTFOUND; 01501 break; 01502 01503 case DISPID_SESSION_FEATUREREQUESTSTATE: 01504 if (wFlags & DISPATCH_PROPERTYGET) { 01505 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01506 if (FAILED(hr)) return hr; 01507 V_VT(pVarResult) = VT_I4; 01508 if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&varg0), &iInstalled, &iAction)) == ERROR_SUCCESS) 01509 V_I4(pVarResult) = iAction; 01510 else 01511 { 01512 ERR("MsiGetFeatureState returned %d\n", ret); 01513 V_I4(pVarResult) = msiInstallStateUnknown; 01514 } 01515 } else if (wFlags & DISPATCH_PROPERTYPUT) { 01516 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01517 if (FAILED(hr)) return hr; 01518 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr); 01519 if (FAILED(hr)) { 01520 VariantClear(&varg0); 01521 return hr; 01522 } 01523 if ((ret = MsiSetFeatureStateW(This->msiHandle, V_BSTR(&varg0), V_I4(&varg1))) != ERROR_SUCCESS) 01524 { 01525 VariantClear(&varg0); 01526 ERR("MsiSetFeatureState returned %d\n", ret); 01527 return DISP_E_EXCEPTION; 01528 } 01529 } 01530 else return DISP_E_MEMBERNOTFOUND; 01531 break; 01532 01533 default: 01534 return DISP_E_MEMBERNOTFOUND; 01535 } 01536 01537 VariantClear(&varg1); 01538 VariantClear(&varg0); 01539 01540 return S_OK; 01541 } 01542 01543 /* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the 01544 * registry value type. Used by Installer::RegistryValue. */ 01545 static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize) 01546 { 01547 static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 }; 01548 static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 }; 01549 WCHAR *szString = (WCHAR *)lpData; 01550 LPWSTR szNewString = NULL; 01551 DWORD dwNewSize = 0; 01552 int idx; 01553 01554 switch (dwType) 01555 { 01556 /* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */ 01557 case REG_MULTI_SZ: /* Multi SZ change internal null characters to newlines */ 01558 idx = (dwSize/sizeof(WCHAR))-1; 01559 while (idx >= 0 && !szString[idx]) idx--; 01560 for (; idx >= 0; idx--) 01561 if (!szString[idx]) szString[idx] = '\n'; 01562 /* fall through */ 01563 case REG_SZ: 01564 V_VT(pVarResult) = VT_BSTR; 01565 V_BSTR(pVarResult) = SysAllocStringByteLen((LPCSTR)szString, dwSize); 01566 break; 01567 01568 case REG_EXPAND_SZ: 01569 if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize))) 01570 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError()); 01571 else if (!(szNewString = msi_alloc(dwNewSize * sizeof(WCHAR)))) 01572 ERR("Out of memory\n"); 01573 else if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize))) 01574 ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError()); 01575 else 01576 { 01577 V_VT(pVarResult) = VT_BSTR; 01578 V_BSTR(pVarResult) = SysAllocStringLen(szNewString, dwNewSize); 01579 } 01580 msi_free(szNewString); 01581 break; 01582 01583 case REG_DWORD: 01584 V_VT(pVarResult) = VT_I4; 01585 V_I4(pVarResult) = *((DWORD *)lpData); 01586 break; 01587 01588 case REG_QWORD: 01589 V_VT(pVarResult) = VT_BSTR; 01590 V_BSTR(pVarResult) = SysAllocString(szREG_); /* Weird string, don't know why native returns it */ 01591 break; 01592 01593 case REG_BINARY: 01594 V_VT(pVarResult) = VT_BSTR; 01595 V_BSTR(pVarResult) = SysAllocString(szREG_BINARY); 01596 break; 01597 01598 case REG_NONE: 01599 V_VT(pVarResult) = VT_EMPTY; 01600 break; 01601 01602 default: 01603 FIXME("Unhandled registry value type %d\n", dwType); 01604 } 01605 } 01606 01607 static HRESULT InstallerImpl_CreateRecord(WORD wFlags, 01608 DISPPARAMS* pDispParams, 01609 VARIANT* pVarResult, 01610 EXCEPINFO* pExcepInfo, 01611 UINT* puArgErr) 01612 { 01613 HRESULT hr; 01614 VARIANTARG varg0; 01615 MSIHANDLE hrec; 01616 IDispatch* dispatch; 01617 01618 if (!(wFlags & DISPATCH_METHOD)) 01619 return DISP_E_MEMBERNOTFOUND; 01620 01621 VariantInit(&varg0); 01622 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01623 if (FAILED(hr)) 01624 return hr; 01625 01626 V_VT(pVarResult) = VT_DISPATCH; 01627 01628 hrec = MsiCreateRecord(V_I4(&varg0)); 01629 if (!hrec) 01630 return DISP_E_EXCEPTION; 01631 01632 hr = create_record(hrec, &dispatch); 01633 if (SUCCEEDED(hr)) 01634 V_DISPATCH(pVarResult) = dispatch; 01635 01636 return hr; 01637 } 01638 01639 static HRESULT InstallerImpl_OpenPackage(AutomationObject* This, 01640 WORD wFlags, 01641 DISPPARAMS* pDispParams, 01642 VARIANT* pVarResult, 01643 EXCEPINFO* pExcepInfo, 01644 UINT* puArgErr) 01645 { 01646 UINT ret; 01647 HRESULT hr; 01648 MSIHANDLE hpkg; 01649 IDispatch* dispatch; 01650 VARIANTARG varg0, varg1; 01651 01652 if (!(wFlags & DISPATCH_METHOD)) 01653 return DISP_E_MEMBERNOTFOUND; 01654 01655 if (pDispParams->cArgs == 0) 01656 return DISP_E_TYPEMISMATCH; 01657 01658 if (V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1]) != VT_BSTR) 01659 return DISP_E_TYPEMISMATCH; 01660 01661 VariantInit(&varg0); 01662 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01663 if (FAILED(hr)) 01664 return hr; 01665 01666 VariantInit(&varg1); 01667 if (pDispParams->cArgs == 2) 01668 { 01669 hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr); 01670 if (FAILED(hr)) 01671 goto done; 01672 } 01673 else 01674 { 01675 V_VT(&varg1) = VT_I4; 01676 V_I4(&varg1) = 0; 01677 } 01678 01679 V_VT(pVarResult) = VT_DISPATCH; 01680 01681 ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &hpkg); 01682 if (ret != ERROR_SUCCESS) 01683 { 01684 hr = DISP_E_EXCEPTION; 01685 goto done; 01686 } 01687 01688 hr = create_session(hpkg, &This->IDispatch_iface, &dispatch); 01689 if (SUCCEEDED(hr)) 01690 V_DISPATCH(pVarResult) = dispatch; 01691 01692 done: 01693 VariantClear(&varg0); 01694 VariantClear(&varg1); 01695 return hr; 01696 } 01697 01698 static HRESULT InstallerImpl_OpenProduct(WORD wFlags, 01699 DISPPARAMS* pDispParams, 01700 VARIANT* pVarResult, 01701 EXCEPINFO* pExcepInfo, 01702 UINT* puArgErr) 01703 { 01704 HRESULT hr; 01705 VARIANTARG varg0; 01706 01707 if (!(wFlags & DISPATCH_METHOD)) 01708 return DISP_E_MEMBERNOTFOUND; 01709 01710 VariantInit(&varg0); 01711 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01712 if (FAILED(hr)) 01713 return hr; 01714 01715 FIXME("%s\n", debugstr_w(V_BSTR(&varg0))); 01716 01717 VariantInit(pVarResult); 01718 01719 VariantClear(&varg0); 01720 return S_OK; 01721 } 01722 01723 static HRESULT InstallerImpl_OpenDatabase(WORD wFlags, 01724 DISPPARAMS* pDispParams, 01725 VARIANT* pVarResult, 01726 EXCEPINFO* pExcepInfo, 01727 UINT* puArgErr) 01728 { 01729 UINT ret; 01730 HRESULT hr; 01731 MSIHANDLE hdb; 01732 IDispatch* dispatch; 01733 VARIANTARG varg0, varg1; 01734 01735 if (!(wFlags & DISPATCH_METHOD)) 01736 return DISP_E_MEMBERNOTFOUND; 01737 01738 VariantInit(&varg0); 01739 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01740 if (FAILED(hr)) 01741 return hr; 01742 01743 VariantInit(&varg1); 01744 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); 01745 if (FAILED(hr)) 01746 goto done; 01747 01748 V_VT(pVarResult) = VT_DISPATCH; 01749 01750 ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &hdb); 01751 if (ret != ERROR_SUCCESS) 01752 { 01753 hr = DISP_E_EXCEPTION; 01754 goto done; 01755 } 01756 01757 hr = create_database(hdb, &dispatch); 01758 if (SUCCEEDED(hr)) 01759 V_DISPATCH(pVarResult) = dispatch; 01760 01761 done: 01762 VariantClear(&varg0); 01763 VariantClear(&varg1); 01764 return hr; 01765 } 01766 01767 static HRESULT InstallerImpl_SummaryInformation(WORD wFlags, 01768 DISPPARAMS* pDispParams, 01769 VARIANT* pVarResult, 01770 EXCEPINFO* pExcepInfo, 01771 UINT* puArgErr) 01772 { 01773 if (!(wFlags & DISPATCH_METHOD)) 01774 return DISP_E_MEMBERNOTFOUND; 01775 01776 FIXME("\n"); 01777 01778 VariantInit(pVarResult); 01779 return S_OK; 01780 } 01781 01782 static HRESULT InstallerImpl_UILevel(WORD wFlags, 01783 DISPPARAMS* pDispParams, 01784 VARIANT* pVarResult, 01785 EXCEPINFO* pExcepInfo, 01786 UINT* puArgErr) 01787 { 01788 HRESULT hr; 01789 VARIANTARG varg0; 01790 INSTALLUILEVEL ui; 01791 01792 if (!(wFlags & DISPATCH_PROPERTYPUT) && !(wFlags & DISPATCH_PROPERTYGET)) 01793 return DISP_E_MEMBERNOTFOUND; 01794 01795 if (wFlags & DISPATCH_PROPERTYPUT) 01796 { 01797 VariantInit(&varg0); 01798 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01799 if (FAILED(hr)) 01800 return hr; 01801 01802 ui = MsiSetInternalUI(V_I4(&varg0), NULL); 01803 if (ui == INSTALLUILEVEL_NOCHANGE) 01804 return DISP_E_EXCEPTION; 01805 } 01806 else if (wFlags & DISPATCH_PROPERTYGET) 01807 { 01808 ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL); 01809 if (ui == INSTALLUILEVEL_NOCHANGE) 01810 return DISP_E_EXCEPTION; 01811 01812 V_VT(pVarResult) = VT_I4; 01813 V_I4(pVarResult) = ui; 01814 } 01815 01816 return S_OK; 01817 } 01818 01819 static HRESULT InstallerImpl_EnableLog(WORD wFlags, 01820 DISPPARAMS* pDispParams, 01821 VARIANT* pVarResult, 01822 EXCEPINFO* pExcepInfo, 01823 UINT* puArgErr) 01824 { 01825 if (!(wFlags & DISPATCH_METHOD)) 01826 return DISP_E_MEMBERNOTFOUND; 01827 01828 FIXME("\n"); 01829 01830 VariantInit(pVarResult); 01831 return S_OK; 01832 } 01833 01834 static HRESULT InstallerImpl_InstallProduct(WORD wFlags, 01835 DISPPARAMS* pDispParams, 01836 VARIANT* pVarResult, 01837 EXCEPINFO* pExcepInfo, 01838 UINT* puArgErr) 01839 { 01840 UINT ret; 01841 HRESULT hr; 01842 VARIANTARG varg0, varg1; 01843 01844 if (!(wFlags & DISPATCH_METHOD)) 01845 return DISP_E_MEMBERNOTFOUND; 01846 01847 VariantInit(&varg0); 01848 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 01849 if (FAILED(hr)) 01850 return hr; 01851 01852 VariantInit(&varg1); 01853 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); 01854 if (FAILED(hr)) 01855 goto done; 01856 01857 ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1)); 01858 if (ret != ERROR_SUCCESS) 01859 { 01860 hr = DISP_E_EXCEPTION; 01861 goto done; 01862 } 01863 01864 done: 01865 VariantClear(&varg0); 01866 VariantClear(&varg1); 01867 return hr; 01868 } 01869 01870 static HRESULT InstallerImpl_Version(WORD wFlags, 01871 VARIANT* pVarResult, 01872 EXCEPINFO* pExcepInfo, 01873 UINT* puArgErr) 01874 { 01875 HRESULT hr; 01876 DLLVERSIONINFO verinfo; 01877 WCHAR version[MAX_PATH]; 01878 01879 static const WCHAR format[] = { 01880 '%','d','.','%','d','.','%','d','.','%','d',0}; 01881 01882 if (!(wFlags & DISPATCH_PROPERTYGET)) 01883 return DISP_E_MEMBERNOTFOUND; 01884 01885 verinfo.cbSize = sizeof(DLLVERSIONINFO); 01886 hr = DllGetVersion(&verinfo); 01887 if (FAILED(hr)) 01888 return hr; 01889 01890 sprintfW(version, format, verinfo.dwMajorVersion, verinfo.dwMinorVersion, 01891 verinfo.dwBuildNumber, verinfo.dwPlatformID); 01892 01893 V_VT(pVarResult) = VT_BSTR; 01894 V_BSTR(pVarResult) = SysAllocString(version); 01895 return S_OK; 01896 } 01897 01898 static HRESULT InstallerImpl_LastErrorRecord(WORD wFlags, 01899 DISPPARAMS* pDispParams, 01900 VARIANT* pVarResult, 01901 EXCEPINFO* pExcepInfo, 01902 UINT* puArgErr) 01903 { 01904 if (!(wFlags & DISPATCH_METHOD)) 01905 return DISP_E_MEMBERNOTFOUND; 01906 01907 FIXME("\n"); 01908 01909 VariantInit(pVarResult); 01910 return S_OK; 01911 } 01912 01913 static HRESULT InstallerImpl_RegistryValue(WORD wFlags, 01914 DISPPARAMS* pDispParams, 01915 VARIANT* pVarResult, 01916 EXCEPINFO* pExcepInfo, 01917 UINT* puArgErr) 01918 { 01919 UINT ret; 01920 HKEY hkey = NULL; 01921 HRESULT hr; 01922 UINT posValue; 01923 DWORD type, size; 01924 LPWSTR szString = NULL; 01925 VARIANTARG varg0, varg1, varg2; 01926 01927 if (!(wFlags & DISPATCH_METHOD)) 01928 return DISP_E_MEMBERNOTFOUND; 01929 01930 VariantInit(&varg0); 01931 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); 01932 if (FAILED(hr)) 01933 return hr; 01934 01935 VariantInit(&varg1); 01936 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); 01937 if (FAILED(hr)) 01938 goto done; 01939 01940 /* Save valuePos so we can save puArgErr if we are unable to do our type 01941 * conversions. 01942 */ 01943 posValue = 2; 01944 VariantInit(&varg2); 01945 hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2); 01946 if (FAILED(hr)) 01947 goto done; 01948 01949 if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT && 01950 V_I4(&varg0) <= REG_INDEX_DYN_DATA) 01951 { 01952 V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT; 01953 } 01954 01955 ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey); 01956 01957 /* Only VT_EMPTY case can do anything if the key doesn't exist. */ 01958 if (ret != ERROR_SUCCESS && V_VT(&varg2) != VT_EMPTY) 01959 { 01960 hr = DISP_E_BADINDEX; 01961 goto done; 01962 } 01963 01964 /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */ 01965 switch (V_VT(&varg2)) 01966 { 01967 /* Return VT_BOOL clarifying whether registry key exists or not. */ 01968 case VT_EMPTY: 01969 V_VT(pVarResult) = VT_BOOL; 01970 V_BOOL(pVarResult) = (ret == ERROR_SUCCESS); 01971 break; 01972 01973 /* Return the value of specified key if it exists. */ 01974 case VT_BSTR: 01975 ret = RegQueryValueExW(hkey, V_BSTR(&varg2), 01976 NULL, NULL, NULL, &size); 01977 if (ret != ERROR_SUCCESS) 01978 { 01979 hr = DISP_E_BADINDEX; 01980 goto done; 01981 } 01982 01983 szString = msi_alloc(size); 01984 if (!szString) 01985 { 01986 hr = E_OUTOFMEMORY; 01987 goto done; 01988 } 01989 01990 ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL, 01991 &type, (LPBYTE)szString, &size); 01992 if (ret != ERROR_SUCCESS) 01993 { 01994 msi_free(szString); 01995 hr = DISP_E_BADINDEX; 01996 goto done; 01997 } 01998 01999 variant_from_registry_value(pVarResult, type, 02000 (LPBYTE)szString, size); 02001 msi_free(szString); 02002 break; 02003 02004 /* Try to make it into VT_I4, can use VariantChangeType for this. */ 02005 default: 02006 hr = VariantChangeType(&varg2, &varg2, 0, VT_I4); 02007 if (FAILED(hr)) 02008 { 02009 if (hr == DISP_E_TYPEMISMATCH) 02010 *puArgErr = posValue; 02011 02012 goto done; 02013 } 02014 02015 /* Retrieve class name or maximum value name or subkey name size. */ 02016 if (!V_I4(&varg2)) 02017 ret = RegQueryInfoKeyW(hkey, NULL, &size, NULL, NULL, NULL, 02018 NULL, NULL, NULL, NULL, NULL, NULL); 02019 else if (V_I4(&varg2) > 0) 02020 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, 02021 NULL, NULL, &size, NULL, NULL, NULL); 02022 else /* V_I4(&varg2) < 0 */ 02023 ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &size, 02024 NULL, NULL, NULL, NULL, NULL, NULL); 02025 02026 if (ret != ERROR_SUCCESS) 02027 goto done; 02028 02029 szString = msi_alloc(++size * sizeof(WCHAR)); 02030 if (!szString) 02031 { 02032 hr = E_OUTOFMEMORY; 02033 goto done; 02034 } 02035 02036 if (!V_I4(&varg2)) 02037 ret = RegQueryInfoKeyW(hkey, szString, &size,NULL, NULL, NULL, 02038 NULL, NULL, NULL, NULL, NULL, NULL); 02039 else if (V_I4(&varg2) > 0) 02040 ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString, 02041 &size, 0, 0, NULL, NULL); 02042 else /* V_I4(&varg2) < 0 */ 02043 ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, size); 02044 02045 if (ret == ERROR_SUCCESS) 02046 { 02047 V_VT(pVarResult) = VT_BSTR; 02048 V_BSTR(pVarResult) = SysAllocString(szString); 02049 } 02050 02051 msi_free(szString); 02052 } 02053 02054 done: 02055 VariantClear(&varg0); 02056 VariantClear(&varg1); 02057 VariantClear(&varg2); 02058 RegCloseKey(hkey); 02059 return hr; 02060 } 02061 02062 static HRESULT InstallerImpl_Environment(WORD wFlags, 02063 DISPPARAMS* pDispParams, 02064 VARIANT* pVarResult, 02065 EXCEPINFO* pExcepInfo, 02066 UINT* puArgErr) 02067 { 02068 if (!(wFlags & DISPATCH_METHOD)) 02069 return DISP_E_MEMBERNOTFOUND; 02070 02071 FIXME("\n"); 02072 02073 VariantInit(pVarResult); 02074 return S_OK; 02075 } 02076 02077 static HRESULT InstallerImpl_FileAttributes(WORD wFlags, 02078 DISPPARAMS* pDispParams, 02079 VARIANT* pVarResult, 02080 EXCEPINFO* pExcepInfo, 02081 UINT* puArgErr) 02082 { 02083 if (!(wFlags & DISPATCH_METHOD)) 02084 return DISP_E_MEMBERNOTFOUND; 02085 02086 FIXME("\n"); 02087 02088 VariantInit(pVarResult); 02089 return S_OK; 02090 } 02091 02092 static HRESULT InstallerImpl_FileSize(WORD wFlags, 02093 DISPPARAMS* pDispParams, 02094 VARIANT* pVarResult, 02095 EXCEPINFO* pExcepInfo, 02096 UINT* puArgErr) 02097 { 02098 if (!(wFlags & DISPATCH_METHOD)) 02099 return DISP_E_MEMBERNOTFOUND; 02100 02101 FIXME("\n"); 02102 02103 VariantInit(pVarResult); 02104 return S_OK; 02105 } 02106 02107 static HRESULT InstallerImpl_FileVersion(WORD wFlags, 02108 DISPPARAMS* pDispParams, 02109 VARIANT* pVarResult, 02110 EXCEPINFO* pExcepInfo, 02111 UINT* puArgErr) 02112 { 02113 if (!(wFlags & DISPATCH_METHOD)) 02114 return DISP_E_MEMBERNOTFOUND; 02115 02116 FIXME("\n"); 02117 02118 VariantInit(pVarResult); 02119 return S_OK; 02120 } 02121 02122 static HRESULT InstallerImpl_ProductState(WORD wFlags, 02123 DISPPARAMS* pDispParams, 02124 VARIANT* pVarResult, 02125 EXCEPINFO* pExcepInfo, 02126 UINT* puArgErr) 02127 { 02128 HRESULT hr; 02129 VARIANTARG varg0; 02130 02131 if (!(wFlags & DISPATCH_PROPERTYGET)) 02132 return DISP_E_MEMBERNOTFOUND; 02133 02134 VariantInit(&varg0); 02135 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 02136 if (FAILED(hr)) 02137 return hr; 02138 02139 V_VT(pVarResult) = VT_I4; 02140 V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0)); 02141 02142 VariantClear(&varg0); 02143 return S_OK; 02144 } 02145 02146 static HRESULT InstallerImpl_ProductInfo(WORD wFlags, 02147 DISPPARAMS* pDispParams, 02148 VARIANT* pVarResult, 02149 EXCEPINFO* pExcepInfo, 02150 UINT* puArgErr) 02151 { 02152 UINT ret; 02153 HRESULT hr; 02154 DWORD size; 02155 LPWSTR str = NULL; 02156 VARIANTARG varg0, varg1; 02157 02158 if (!(wFlags & DISPATCH_PROPERTYGET)) 02159 return DISP_E_MEMBERNOTFOUND; 02160 02161 VariantInit(&varg0); 02162 hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); 02163 if (FAILED(hr)) 02164 return hr; 02165 02166 VariantInit(&varg1); 02167 hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); 02168 if (FAILED(hr)) 02169 goto done; 02170 02171 V_VT(pVarResult) = VT_BSTR; 02172 V_BSTR(pVarResult) = NULL; 02173 02174 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &size); 02175 if (ret != ERROR_SUCCESS) 02176 { 02177 hr = DISP_E_EXCEPTION; 02178 goto done; 02179 } 02180 02181 str = msi_alloc(++size * sizeof(WCHAR)); 02182 if (!str) 02183 { 02184 hr = E_OUTOFMEMORY; 02185 goto done; 02186 } 02187 02188 ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), str, &size); 02189 if (ret != ERROR_SUCCESS) 02190 { 02191 hr = DISP_E_EXCEPTION; 02192 goto done; 02193 } 02194 02195 V_BSTR(pVarResult) = SysAllocString(str); 02196 hr = S_OK; 02197 02198 done: 02199 msi_free(str); 02200 VariantClear(&varg0); 02201 VariantClear(&varg1); 02202 return hr; 02203 } 02204 02205 static HRESULT InstallerImpl_Products(WORD flags, 02206 DISPPARAMS* pDispParams, 02207 VARIANT* result, 02208 EXCEPINFO* pExcepInfo, 02209 UINT* puArgErr) 02210 { 02211 IDispatch *dispatch; 02212 HRESULT hr; 02213 02214 if (!(flags & DISPATCH_PROPERTYGET)) 02215 return DISP_E_MEMBERNOTFOUND; 02216 02217 hr = create_list(NULL, &dispatch); 02218 if (FAILED(hr)) 02219 return hr; 02220 02221 V_VT(result) = VT_DISPATCH; 02222 V_DISPATCH(result) = dispatch; 02223 02224 return hr; 02225 } 02226 02227 static HRESULT InstallerImpl_RelatedProducts(WORD flags, 02228 DISPPARAMS* pDispParams, 02229 VARIANT* result, 02230 EXCEPINFO* pExcepInfo, 02231 UINT* puArgErr) 02232 { 02233 IDispatch* dispatch; 02234 VARIANTARG related; 02235 HRESULT hr; 02236 02237 if (!(flags & DISPATCH_PROPERTYGET)) 02238 return DISP_E_MEMBERNOTFOUND; 02239 02240 VariantInit(&related); 02241 hr = DispGetParam(pDispParams, 0, VT_BSTR, &related, puArgErr); 02242 if (FAILED(hr)) 02243 return hr; 02244 02245 hr = create_list(V_BSTR(&related), &dispatch); 02246 VariantClear(&related); 02247 02248 V_VT(result) = VT_DISPATCH; 02249 V_DISPATCH(result) = dispatch; 02250 02251 return hr; 02252 } 02253 02254 static HRESULT InstallerImpl_Invoke( 02255 AutomationObject* This, 02256 DISPID dispIdMember, 02257 REFIID riid, 02258 LCID lcid, 02259 WORD wFlags, 02260 DISPPARAMS* pDispParams, 02261 VARIANT* pVarResult, 02262 EXCEPINFO* pExcepInfo, 02263 UINT* puArgErr) 02264 { 02265 switch (dispIdMember) 02266 { 02267 case DISPID_INSTALLER_CREATERECORD: 02268 return InstallerImpl_CreateRecord(wFlags, pDispParams, 02269 pVarResult, pExcepInfo, puArgErr); 02270 02271 case DISPID_INSTALLER_OPENPACKAGE: 02272 return InstallerImpl_OpenPackage(This, wFlags, pDispParams, 02273 pVarResult, pExcepInfo, puArgErr); 02274 02275 case DISPID_INSTALLER_OPENPRODUCT: 02276 return InstallerImpl_OpenProduct(wFlags, pDispParams, 02277 pVarResult, pExcepInfo, puArgErr); 02278 02279 case DISPID_INSTALLER_OPENDATABASE: 02280 return InstallerImpl_OpenDatabase(wFlags, pDispParams, 02281 pVarResult, pExcepInfo, puArgErr); 02282 02283 case DISPID_INSTALLER_SUMMARYINFORMATION: 02284 return InstallerImpl_SummaryInformation(wFlags, pDispParams, 02285 pVarResult, pExcepInfo, 02286 puArgErr); 02287 02288 case DISPID_INSTALLER_UILEVEL: 02289 return InstallerImpl_UILevel(wFlags, pDispParams, 02290 pVarResult, pExcepInfo, puArgErr); 02291 02292 case DISPID_INSTALLER_ENABLELOG: 02293 return InstallerImpl_EnableLog(wFlags, pDispParams, 02294 pVarResult, pExcepInfo, puArgErr); 02295 02296 case DISPID_INSTALLER_INSTALLPRODUCT: 02297 return InstallerImpl_InstallProduct(wFlags, pDispParams, 02298 pVarResult, pExcepInfo, 02299 puArgErr); 02300 02301 case DISPID_INSTALLER_VERSION: 02302 return InstallerImpl_Version(wFlags, pVarResult, 02303 pExcepInfo, puArgErr); 02304 02305 case DISPID_INSTALLER_LASTERRORRECORD: 02306 return InstallerImpl_LastErrorRecord(wFlags, pDispParams, 02307 pVarResult, pExcepInfo, 02308 puArgErr); 02309 02310 case DISPID_INSTALLER_REGISTRYVALUE: 02311 return InstallerImpl_RegistryValue(wFlags, pDispParams, 02312 pVarResult, pExcepInfo, 02313 puArgErr); 02314 02315 case DISPID_INSTALLER_ENVIRONMENT: 02316 return InstallerImpl_Environment(wFlags, pDispParams, 02317 pVarResult, pExcepInfo, puArgErr); 02318 02319 case DISPID_INSTALLER_FILEATTRIBUTES: 02320 return InstallerImpl_FileAttributes(wFlags, pDispParams, 02321 pVarResult, pExcepInfo, 02322 puArgErr); 02323 02324 case DISPID_INSTALLER_FILESIZE: 02325 return InstallerImpl_FileSize(wFlags, pDispParams, 02326 pVarResult, pExcepInfo, puArgErr); 02327 02328 case DISPID_INSTALLER_FILEVERSION: 02329 return InstallerImpl_FileVersion(wFlags, pDispParams, 02330 pVarResult, pExcepInfo, puArgErr); 02331 02332 case DISPID_INSTALLER_PRODUCTSTATE: 02333 return InstallerImpl_ProductState(wFlags, pDispParams, 02334 pVarResult, pExcepInfo, puArgErr); 02335 02336 case DISPID_INSTALLER_PRODUCTINFO: 02337 return InstallerImpl_ProductInfo(wFlags, pDispParams, 02338 pVarResult, pExcepInfo, puArgErr); 02339 02340 case DISPID_INSTALLER_PRODUCTS: 02341 return InstallerImpl_Products(wFlags, pDispParams, 02342 pVarResult, pExcepInfo, puArgErr); 02343 02344 case DISPID_INSTALLER_RELATEDPRODUCTS: 02345 return InstallerImpl_RelatedProducts(wFlags, pDispParams, 02346 pVarResult, pExcepInfo, 02347 puArgErr); 02348 02349 default: 02350 return DISP_E_MEMBERNOTFOUND; 02351 } 02352 } 02353 02354 HRESULT create_msiserver(IUnknown *outer, void **ppObj) 02355 { 02356 AutomationObject *installer; 02357 HRESULT hr; 02358 02359 TRACE("(%p %p)\n", outer, ppObj); 02360 02361 if (outer) 02362 return CLASS_E_NOAGGREGATION; 02363 02364 installer = msi_alloc(sizeof(AutomationObject)); 02365 if (!installer) return E_OUTOFMEMORY; 02366 02367 hr = init_automation_object(installer, 0, &DIID_Installer, InstallerImpl_Invoke, NULL); 02368 if (hr != S_OK) 02369 { 02370 msi_free(installer); 02371 return hr; 02372 } 02373 02374 *ppObj = &installer->IDispatch_iface; 02375 02376 return hr; 02377 } 02378 02379 HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **disp) 02380 { 02381 SessionObject *session; 02382 HRESULT hr; 02383 02384 session = msi_alloc(sizeof(SessionObject)); 02385 if (!session) return E_OUTOFMEMORY; 02386 02387 hr = init_automation_object(&session->autoobj, msiHandle, &DIID_Session, SessionImpl_Invoke, NULL); 02388 if (hr != S_OK) 02389 { 02390 msi_free(session); 02391 return hr; 02392 } 02393 02394 session->installer = installer; 02395 *disp = &session->autoobj.IDispatch_iface; 02396 02397 return hr; 02398 } 02399 02400 static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch) 02401 { 02402 AutomationObject *database; 02403 HRESULT hr; 02404 02405 TRACE("(%d %p)\n", msiHandle, dispatch); 02406 02407 database = msi_alloc(sizeof(AutomationObject)); 02408 if (!database) return E_OUTOFMEMORY; 02409 02410 hr = init_automation_object(database, msiHandle, &DIID_Database, DatabaseImpl_Invoke, NULL); 02411 if (hr != S_OK) 02412 { 02413 msi_free(database); 02414 return hr; 02415 } 02416 02417 *dispatch = &database->IDispatch_iface; 02418 02419 return hr; 02420 } 02421 02422 static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch) 02423 { 02424 AutomationObject *view; 02425 HRESULT hr; 02426 02427 TRACE("(%d %p)\n", msiHandle, dispatch); 02428 02429 view = msi_alloc(sizeof(AutomationObject)); 02430 if (!view) return E_OUTOFMEMORY; 02431 02432 hr = init_automation_object(view, msiHandle, &DIID_View, ViewImpl_Invoke, NULL); 02433 if (hr != S_OK) 02434 { 02435 msi_free(view); 02436 return hr; 02437 } 02438 02439 *dispatch = &view->IDispatch_iface; 02440 02441 return hr; 02442 } 02443 02444 static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp) 02445 { 02446 AutomationObject *info; 02447 HRESULT hr; 02448 02449 info = msi_alloc(sizeof(*info)); 02450 if (!info) return E_OUTOFMEMORY; 02451 02452 hr = init_automation_object(info, msiHandle, &DIID_SummaryInfo, SummaryInfoImpl_Invoke, NULL); 02453 if (hr != S_OK) 02454 { 02455 msi_free(info); 02456 return hr; 02457 } 02458 02459 *disp = &info->IDispatch_iface; 02460 02461 return hr; 02462 } Generated on Sun May 27 2012 04:25:12 for ReactOS by
1.7.6.1
|