msi: Add proper parameter handling to OLE automation interfaces.

Misha Koshelev mk144210 at bcm.tmc.edu
Tue Feb 27 16:27:24 CST 2007


This patch is to my other patches that add the OLE automation interface
partial implementation. This adds a proper error checking framework that
makes parameter conversion and use fairly simple in order to write in
all the MSI automation interfaces and implements this error checking for
the existing interfaces/methods that are already present.

Changelog:

	* msi: Add proper parameter handling to OLE automation interfaces.
-------------- next part --------------
From 03f03b30402c178b224a2b31da104bcca21be04a Mon Sep 17 00:00:00 2001
From: Misha Koshelev <mk144210 at bcm.tmc.edu>
Date: Tue, 27 Feb 2007 16:24:34 -0600
Subject: msi: Add proper parameter handling to OLE automation interfaces.
---
 dlls/msi/automation.c |  169 +++++++++++++++++++++++++++++++------------------
 1 files changed, 108 insertions(+), 61 deletions(-)

diff --git a/dlls/msi/automation.c b/dlls/msi/automation.c
index c7ca30b..ffa603a 100644
--- a/dlls/msi/automation.c
+++ b/dlls/msi/automation.c
@@ -572,6 +572,41 @@ static const IProvideMultipleClassInfoVt
  *      the functions below remain just down to what they need to do.
  */
 
+/* Macros for variant conversions */
+#define V_DECLARE \
+    VARIANTARG vararg[pDispParams->cArgs]; \
+    int iVarCount; \
+    HRESULT hr = S_OK; \
+    memset(vararg, 0, sizeof(vararg));
+#define V_PREPARE(n, type) \
+    VariantInit(&vararg[n]); \
+    hr = VariantChangeTypeEx(&vararg[n], &pDispParams->rgvarg[n], lcid, 0, VT_##type); \
+    if (FAILED(hr)) \
+    { \
+        *puArgErr = n; \
+        goto v_finish; \
+    }
+#define V_PREPAREOPT(n, type) \
+    VariantInit(&vararg[n]); \
+    if (FAILED(VariantChangeTypeEx(&vararg[n], &pDispParams->rgvarg[n], lcid, 0, VT_##type))) \
+        VariantClear(&vararg[n]); 
+#define V_PREPARED(n) (V_VT(&vararg[n]) != VT_EMPTY)
+#define V(n, type) V_##type(&vararg[n])
+#define V_RETURN(value, type) \
+    V_VT(pVarResult) = VT_##type; \
+    V_##type(pVarResult) = value;  
+#define V_FAIL hr = E_FAIL; 
+#define V_DEFAULT \
+    default: \
+        hr = DISP_E_MEMBERNOTFOUND;
+#define V_FINISH \
+    goto v_finish; /* suppress warnings about unused label v_free */ \
+v_finish: \
+    for (iVarCount = 0; iVarCount < pDispParams->cArgs; iVarCount++) \
+        if (V_PREPARED(iVarCount))                                   \
+            VariantClear(&vararg[iVarCount]); \
+    return hr;
+
 HRESULT WINAPI RecordImpl_Invoke(
         AutomationObject* This,
         DISPID dispIdMember,
@@ -586,29 +621,34 @@ HRESULT WINAPI RecordImpl_Invoke(
     WCHAR szString[MAX_MSI_STRING];
     DWORD dwLen = MAX_MSI_STRING;
     UINT ret;
+    V_DECLARE
 
     switch (dispIdMember) 
     {
 	case DISPID_RECORD_STRINGDATA:
 	    if (wFlags & DISPATCH_PROPERTYGET) {
- 	        V_VT(pVarResult) = VT_BSTR;
-		if ((ret = MsiRecordGetStringW(This->msiHandle, V_I4(&pDispParams->rgvarg[0]),
-				               szString, &dwLen)) == ERROR_SUCCESS)
-		    V_BSTR(pVarResult) = SysAllocString(szString);
+                V_PREPARE(0, I4);
+		if ((ret = MsiRecordGetStringW(This->msiHandle, V(0, I4), szString, &dwLen)) == ERROR_SUCCESS)
+                {
+		    V_RETURN(SysAllocString(szString), BSTR);
+                }
 		else
 		{
 		    TRACE("MsiRecordGetString returned %d\n", ret);
-		    V_BSTR(pVarResult) = NULL;
+		    V_RETURN(NULL, BSTR);
 		}
-		return S_OK;
 	    } else if (wFlags & DISPATCH_PROPERTYPUT) {
-		return (MsiRecordSetStringW(This->msiHandle, V_I4(&pDispParams->rgvarg[1]),
-   				        V_BSTR(&pDispParams->rgvarg[0])) == ERROR_SUCCESS ? S_OK : E_FAIL);
+                V_PREPARE(1, I4);
+                V_PREPARE(0, BSTR);
+		if (MsiRecordSetStringW(This->msiHandle, V(1, I4), V(0, BSTR)) != ERROR_SUCCESS) 
+                    V_FAIL;
 	    }
 	    break;
+            
+       V_DEFAULT
     }
 
-    return DISP_E_MEMBERNOTFOUND;
+    V_FINISH
 }
 
 HRESULT WINAPI ViewImpl_Invoke(
@@ -623,30 +663,30 @@ HRESULT WINAPI ViewImpl_Invoke(
         UINT* puArgErr)
 {
     MSIHANDLE msiHandle;
-    AutomationObject *obj = NULL;
     IDispatch *iDispatch = NULL;
     UINT ret;
+    V_DECLARE
 
     switch (dispIdMember) 
     {
 	case DISPID_VIEW_EXECUTE:
 	    if (wFlags & DISPATCH_METHOD)
-	    { 
-	        obj = (AutomationObject *)V_DISPATCH(&pDispParams->rgvarg[0]);
-		MsiViewExecute(This->msiHandle, obj == NULL ? 0 : obj->msiHandle);
-		return S_OK;
+	    {
+                V_PREPAREOPT(0, DISPATCH);
+                if (V_PREPARED(0))
+                    MsiViewExecute(This->msiHandle, ((AutomationObject *)V(0, DISPATCH))->msiHandle);
+                else
+                    MsiViewExecute(This->msiHandle, 0);
 	    }
 	    break;
 
 	case DISPID_VIEW_FETCH:
 	    if (wFlags & DISPATCH_METHOD)
 	    { 
-		V_VT(pVarResult) = VT_DISPATCH;
 		if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS) 
 		    create_automation_object(msiHandle, NULL, (LPVOID)&iDispatch, &DIID_Record, RecordImpl_Invoke);
 		else TRACE("MsiViewFetch returned %d\n", ret);
-		V_DISPATCH(pVarResult) = iDispatch;
-		return S_OK;
+		V_RETURN(iDispatch, DISPATCH);
 	    }
 	    break;
 
@@ -654,12 +694,13 @@ HRESULT WINAPI ViewImpl_Invoke(
 	    if (wFlags & DISPATCH_METHOD)
 	    { 
 		MsiViewClose(This->msiHandle);
-		return S_OK;
 	    }
 	    break;
+
+        V_DEFAULT
     }
 
-    return DISP_E_MEMBERNOTFOUND;
+    V_FINISH
 }
 
 HRESULT WINAPI DatabaseImpl_Invoke(
@@ -676,23 +717,25 @@ HRESULT WINAPI DatabaseImpl_Invoke(
     MSIHANDLE msiHandle;
     IDispatch *iDispatch = NULL;
     UINT ret;
+    V_DECLARE
 
     switch (dispIdMember) 
     {
 	case DISPID_DATABASE_OPENVIEW:
 	    if (wFlags & DISPATCH_METHOD)
 	    { 
-		V_VT(pVarResult) = VT_DISPATCH;
-		if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&pDispParams->rgvarg[0]), &msiHandle)) == ERROR_SUCCESS) 
+                V_PREPARE(0, BSTR);
+		if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V(0, BSTR), &msiHandle)) == ERROR_SUCCESS) 
 		    create_automation_object(msiHandle, NULL, (LPVOID)&iDispatch, &DIID_View, ViewImpl_Invoke);
 		else TRACE("MsiDatabaseOpenViewW returned %d\n", ret);
-	        V_DISPATCH(pVarResult) = iDispatch;
-		return S_OK;
+	        V_RETURN(iDispatch, DISPATCH);
 	    }
 	    break;
+            
+        V_DEFAULT
     }
 
-    return DISP_E_MEMBERNOTFOUND;
+    V_FINISH
 }
 
 HRESULT WINAPI SessionImpl_Invoke(
@@ -713,20 +756,24 @@ HRESULT WINAPI SessionImpl_Invoke(
     LANGID langId;
     UINT ret;
     INSTALLSTATE iInstalled, iAction;
+    V_DECLARE
 
     switch (dispIdMember)
     {
 	case DISPID_SESSION_PROPERTY:
 	    if (wFlags & DISPATCH_PROPERTYGET) {
-		V_VT(pVarResult) = VT_BSTR;
-		V_BSTR(pVarResult) = NULL;
-		if (MsiGetPropertyW(This->msiHandle, V_BSTR(&pDispParams->rgvarg[0]),
-				    szString, &dwLen) == ERROR_SUCCESS)
-		    V_BSTR(pVarResult) = SysAllocString(szString);
-		return S_OK;
+                V_PREPARE(0, BSTR);
+		if (MsiGetPropertyW(This->msiHandle, V(0, BSTR), szString, &dwLen) == ERROR_SUCCESS)
+                {
+		    V_RETURN(SysAllocString(szString), BSTR);
+                } else {
+                    V_RETURN(NULL, BSTR);
+                }
 	    } else if (wFlags & DISPATCH_PROPERTYPUT) {
-		return (MsiSetPropertyW(This->msiHandle, V_BSTR(&pDispParams->rgvarg[1]),
-   				        V_BSTR(&pDispParams->rgvarg[0])) == ERROR_SUCCESS ? S_OK : E_FAIL);
+                V_PREPARE(1, BSTR);
+                V_PREPARE(0, BSTR);
+		if (MsiSetPropertyW(This->msiHandle, V(1, BSTR), V(0, BSTR)) != ERROR_SUCCESS) 
+                    V_FAIL;
 	    }
 	    break;
 
@@ -735,71 +782,71 @@ HRESULT WINAPI SessionImpl_Invoke(
 		langId = MsiGetLanguage(This->msiHandle);
 		if (langId != ERROR_INVALID_HANDLE)
 		{
-		    V_VT(pVarResult) = VT_I4;
-		    V_I4(pVarResult) = langId;	
-		    return S_OK;
-		} else return E_FAIL;
+                    V_RETURN(langId, I4);
+		} else V_FAIL;
 	    } 
 	    break;
 
 	case DISPID_SESSION_MODE:
 	    if (wFlags & DISPATCH_PROPERTYGET) {
-		V_VT(pVarResult) = VT_BOOL;
-		V_BOOL(pVarResult) = MsiGetMode(This->msiHandle, V_I4(&pDispParams->rgvarg[0]));
-		return S_OK;
+                V_PREPARE(0, I4);
+		V_RETURN(MsiGetMode(This->msiHandle, V(0, I4)), BOOL);
 	    } else if (wFlags & DISPATCH_PROPERTYPUT) {
-		return (MsiSetMode(This->msiHandle, V_I4(&pDispParams->rgvarg[1]),
-   				   V_BOOL(&pDispParams->rgvarg[0])) == ERROR_SUCCESS ? S_OK : E_FAIL);
+                V_PREPARE(1, I4);
+                V_PREPARE(0, BOOL);
+		if (MsiSetMode(This->msiHandle, V(1, I4), V(0, BOOL)) != ERROR_SUCCESS)
+                    V_FAIL;
 	    }
 	    break;
 
 	case DISPID_SESSION_DATABASE:
 	    if (wFlags & DISPATCH_PROPERTYGET) {
-  	        V_VT(pVarResult) = VT_DISPATCH;
-		msiHandle = MsiGetActiveDatabase(This->msiHandle);
-		if (msiHandle) 
+		if ((msiHandle = MsiGetActiveDatabase(This->msiHandle))) 
 		    create_automation_object(msiHandle, NULL, (LPVOID)&iDispatch, &DIID_Database, DatabaseImpl_Invoke);
 		else TRACE("MsiGetActiveDatabase failed\n");
-		V_DISPATCH(pVarResult) = iDispatch;
-		return S_OK;
+                V_RETURN(iDispatch, DISPATCH);
 	    }
 	    break;
 
 	case DISPID_SESSION_FEATURECURRENTSTATE:
 	    if (wFlags & DISPATCH_PROPERTYGET) {
-		V_VT(pVarResult) = VT_I4;
-		if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&pDispParams->rgvarg[0]),
-					      &iInstalled, &iAction)) == ERROR_SUCCESS)
-		    V_I4(pVarResult) = iInstalled;
+                V_PREPARE(0, BSTR);
+		if ((ret = MsiGetFeatureStateW(This->msiHandle, V(0, BSTR), &iInstalled, &iAction)) == ERROR_SUCCESS) 
+                {
+		    V_RETURN(iInstalled, I4);
+                }
 		else 
 		{
 		    TRACE("MsiGetFeatureState returned %d\n", ret);
-		    V_I4(pVarResult) = msiInstallStateUnknown;
+                    V_RETURN(msiInstallStateUnknown, I4);
 		}
-		return S_OK;
 	    } 
 	    break;
 
 	case DISPID_SESSION_FEATUREREQUESTSTATE:
 	    if (wFlags & DISPATCH_PROPERTYGET) {
-		V_VT(pVarResult) = VT_I4;
-		if ((ret = MsiGetFeatureStateW(This->msiHandle, V_BSTR(&pDispParams->rgvarg[0]),
-					      &iInstalled, &iAction)) == ERROR_SUCCESS)
-		    V_I4(pVarResult) = iAction;
+                V_PREPARE(0, BSTR);
+		if ((ret = MsiGetFeatureStateW(This->msiHandle, V(0, BSTR), &iInstalled, &iAction)) == ERROR_SUCCESS) 
+                {
+		    V_RETURN(iAction, I4);
+                }
 		else 
 		{
 		    TRACE("MsiGetFeatureState returned %d\n", ret);
-		    V_I4(pVarResult) = msiInstallStateUnknown;
+                    V_RETURN(msiInstallStateUnknown, I4);
 		}
-		return S_OK;
 	    } else if (wFlags & DISPATCH_PROPERTYPUT) {
-		return (MsiSetFeatureStateW(This->msiHandle, V_BSTR(&pDispParams->rgvarg[1]),
-   				   (INSTALLSTATE)V_I4(&pDispParams->rgvarg[0])) == ERROR_SUCCESS ? S_OK : E_FAIL);
+                V_PREPARE(1, BSTR);
+                V_PREPARE(0, I4);
+		if (MsiSetFeatureStateW(This->msiHandle, V(1, BSTR), V(0, I4)) != ERROR_SUCCESS)
+                    V_FAIL;
 	    }
 	    break;
+
+       V_DEFAULT
     }
 
-    return DISP_E_MEMBERNOTFOUND;
+    V_FINISH
 }
 
 /* Wrapper around create_automation_object to create a session object. */
-- 
1.4.1



More information about the wine-patches mailing list