Misha Koshelev : msi: automation: Generalize interface-specific data storage in AutomationObject.

Alexandre Julliard julliard at wine.codeweavers.com
Tue May 8 06:59:35 CDT 2007


Module: wine
Branch: master
Commit: 715950bc7ed6180083ec582735cf1b2f027afbf2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=715950bc7ed6180083ec582735cf1b2f027afbf2

Author: Misha Koshelev <mk144210 at 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;
 }




More information about the wine-cvs mailing list