Module: wine Branch: master Commit: 715950bc7ed6180083ec582735cf1b2f027afbf2 URL: http://source.winehq.org/git/wine.git/?a=commit;h=715950bc7ed6180083ec582735...
Author: Misha Koshelev mk144210@bcm.edu Date: Mon May 7 17:49:45 2007 -0500
msi: automation: Generalize interface-specific data storage in AutomationObject.
This makes a more general framework for interface/object-specific data storage.
---
dlls/msi/automation.c | 50 ++++++++++++++++++++++++++++++++++-------------- 1 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/dlls/msi/automation.c b/dlls/msi/automation.c index 169ad81..d14fefb 100644 --- a/dlls/msi/automation.c +++ b/dlls/msi/automation.c @@ -61,9 +61,6 @@ interface AutomationObject { /* The MSI handle of the current object */ MSIHANDLE msiHandle;
- /* The parent Installer object (only used in the Session object) */ - IDispatch *pInstaller; - /* A function that is called from AutomationObject::Invoke, specific to this type of object. */ HRESULT (STDMETHODCALLTYPE *funcInvoke)( AutomationObject* This, @@ -75,8 +72,21 @@ interface AutomationObject { VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr); + + /* A function that is called from AutomationObject::Release when the object is being freed to free any private + * data structures (or NULL) */ + void (STDMETHODCALLTYPE *funcFree)(AutomationObject* This); };
+/* + * Structures for additional data required by specific automation objects + */ + +typedef struct { + /* The parent Installer object */ + IDispatch *pInstaller; +} SessionData; + /* VTables */ static const struct IDispatchVtbl AutomationObject_Vtbl; static const struct IProvideMultipleClassInfoVtbl AutomationObject_IProvideMultipleClassInfo_Vtbl; @@ -116,17 +126,19 @@ HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID * with the appropriate clsid and invocation function. */ HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOID *ppObj, REFIID clsid, HRESULT (STDMETHODCALLTYPE *funcInvoke)(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*, - VARIANT*,EXCEPINFO*,UINT*)) + VARIANT*,EXCEPINFO*,UINT*), + void (STDMETHODCALLTYPE *funcFree)(AutomationObject*), + SIZE_T sizetPrivateData) { AutomationObject *object; HRESULT hr;
- TRACE("(%ld,%p,%p,%s,%p)\n", (unsigned long)msiHandle, pUnkOuter, ppObj, debugstr_guid(clsid), funcInvoke); + TRACE("(%ld,%p,%p,%s,%p,%p,%ld)\n", (unsigned long)msiHandle, pUnkOuter, ppObj, debugstr_guid(clsid), funcInvoke, funcFree, sizetPrivateData);
if( pUnkOuter ) return CLASS_E_NOAGGREGATION;
- object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AutomationObject)); + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AutomationObject)+sizetPrivateData);
/* Set all the VTable references */ object->lpVtbl = &AutomationObject_Vtbl; @@ -137,7 +149,7 @@ HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOI object->msiHandle = msiHandle; object->clsid = (LPCLSID)clsid; object->funcInvoke = funcInvoke; - object->pInstaller = NULL; + object->funcFree = funcFree;
/* Load our TypeInfo so we don't have to process GetIDsOfNames */ object->iTypeInfo = NULL; @@ -158,6 +170,12 @@ static inline AutomationObject *obj_from_IProvideMultipleClassInfo( IProvideMult return (AutomationObject *)((char*)iface - FIELD_OFFSET(AutomationObject, lpvtblIProvideMultipleClassInfo)); }
+/* Macro to get pointer to private object data */ +static inline void *private_data( AutomationObject *This ) +{ + return This + 1; +} + /* * AutomationObject methods */ @@ -213,6 +231,7 @@ static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
if (!ref) { + if (This->funcFree) This->funcFree(This); MsiCloseHandle(This->msiHandle); HeapFree(GetProcessHeap(), 0, This); } @@ -579,7 +598,7 @@ static HRESULT WINAPI ViewImpl_Invoke( V_VT(pVarResult) = VT_DISPATCH; if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS) { - if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Record, RecordImpl_Invoke))) + if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Record, RecordImpl_Invoke, NULL, 0))) { IDispatch_AddRef(pDispatch); V_DISPATCH(pVarResult) = pDispatch; @@ -639,7 +658,7 @@ static HRESULT WINAPI DatabaseImpl_Invoke( V_VT(pVarResult) = VT_DISPATCH; if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS) { - if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_View, ViewImpl_Invoke))) + if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_View, ViewImpl_Invoke, NULL, 0))) { IDispatch_AddRef(pDispatch); V_DISPATCH(pVarResult) = pDispatch; @@ -671,6 +690,7 @@ static HRESULT WINAPI SessionImpl_Invoke( EXCEPINFO* pExcepInfo, UINT* puArgErr) { + SessionData *data = private_data(This); WCHAR *szString; DWORD dwLen; IDispatch *pDispatch = NULL; @@ -689,8 +709,8 @@ static HRESULT WINAPI SessionImpl_Invoke( case DISPID_SESSION_INSTALLER: if (wFlags & DISPATCH_PROPERTYGET) { V_VT(pVarResult) = VT_DISPATCH; - IDispatch_AddRef(This->pInstaller); - V_DISPATCH(pVarResult) = This->pInstaller; + IDispatch_AddRef(data->pInstaller); + V_DISPATCH(pVarResult) = data->pInstaller; } break;
@@ -761,7 +781,7 @@ static HRESULT WINAPI SessionImpl_Invoke( V_VT(pVarResult) = VT_DISPATCH; if ((msiHandle = MsiGetActiveDatabase(This->msiHandle))) { - if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Database, DatabaseImpl_Invoke))) + if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Database, DatabaseImpl_Invoke, NULL, 0))) { IDispatch_AddRef(pDispatch); V_DISPATCH(pVarResult) = pDispatch; @@ -930,14 +950,14 @@ static HRESULT WINAPI InstallerImpl_Invoke( /* Wrapper around create_automation_object to create an installer object. */ HRESULT create_msiserver(IUnknown *pOuter, LPVOID *ppObj) { - return create_automation_object(0, pOuter, ppObj, &DIID_Installer, InstallerImpl_Invoke); + return create_automation_object(0, pOuter, ppObj, &DIID_Installer, InstallerImpl_Invoke, NULL, 0); }
/* Wrapper around create_automation_object to create a session object. */ HRESULT create_session(MSIHANDLE msiHandle, IDispatch *pInstaller, IDispatch **pDispatch) { - HRESULT hr = create_automation_object(msiHandle, NULL, (LPVOID)pDispatch, &DIID_Session, SessionImpl_Invoke); + HRESULT hr = create_automation_object(msiHandle, NULL, (LPVOID)pDispatch, &DIID_Session, SessionImpl_Invoke, NULL, sizeof(SessionData)); if (SUCCEEDED(hr) && pDispatch && *pDispatch) - ((AutomationObject *)*pDispatch)->pInstaller = (IDispatch *)pInstaller; + ((SessionData *)private_data((AutomationObject *)*pDispatch))->pInstaller = pInstaller; return hr; }