Rob Shearman : oleaut32: Implement automatic value getting in ITypeInfo:: Invoke.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Feb 8 06:20:41 CST 2007


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

Author: Rob Shearman <rob at codeweavers.com>
Date:   Wed Feb  7 19:28:43 2007 +0000

oleaut32: Implement automatic value getting in ITypeInfo::Invoke.

If an IDispatch object is returned from in the retval for a propget 
function and an extra parameter was passed in to ITypeInfo::Invoke then 
it should call IDispatch::Invoke on the returned object with the extra 
parameter to retrieve the value of the object, which is then returned in 
pVarResult.

---

 dlls/oleaut32/tests/tmarshal.c |   12 +++---------
 dlls/oleaut32/typelib.c        |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c
index 0654622..996c2da 100644
--- a/dlls/oleaut32/tests/tmarshal.c
+++ b/dlls/oleaut32/tests/tmarshal.c
@@ -898,11 +898,8 @@ static void test_typelibmarshal(void)
         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
         excepinfo.wCode, excepinfo.scode);
 
-    todo_wine
-    {
-        ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
-        ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
-    }
+    ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
+    ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
     VariantClear(&varresult);
 
     /* call Value with a VT_VARIANT|VT_BYREF type */
@@ -1033,10 +1030,7 @@ static void test_typelibmarshal(void)
     dispparams.rgdispidNamedArgs = NULL;
     dispparams.rgvarg = vararg;
     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
-    todo_wine
-    {
-        ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
-    }
+    ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
 
     IDispatch_Release(pDispatch);
     IWidget_Release(pWidget);
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 63ec327..50ddd2f 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -5519,6 +5519,19 @@ static HRESULT WINAPI ITypeInfo_fnInvoke
 
                 if (wParamFlags & PARAMFLAG_FRETVAL)
                 {
+                    /* under most conditions the caller is not allowed to
+                     * pass in a dispparam arg in the index of what would be
+                     * the retval parameter. however, there is an exception
+                     * where the extra parameter is used in an extra
+                     * IDispatch::Invoke below */
+                    if ((i < pDispParams->cArgs) &&
+                        ((func_desc->cParams != 1) || !pVarResult ||
+                         !(func_desc->invkind & INVOKE_PROPERTYGET)))
+                    {
+                        hres = DISP_E_BADPARAMCOUNT;
+                        break;
+                    }
+
                     /* note: this check is placed so that if the caller passes
                      * in a VARIANTARG for the retval we just ignore it, like
                      * native does */
@@ -5733,6 +5746,29 @@ static HRESULT WINAPI ITypeInfo_fnInvoke
                     VariantClear(&varresult);
             }
 
+            if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
+                (wFlags == INVOKE_PROPERTYGET) &&
+                (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
+                (pDispParams->cArgs != 0))
+            {
+                if (V_VT(pVarResult) == VT_DISPATCH)
+                {
+                    IDispatch *pDispatch = V_DISPATCH(pVarResult);
+                    /* Note: not VariantClear; we still need the dispatch
+                     * pointer to be valid */
+                    VariantInit(pVarResult);
+                    hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
+                        GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
+                        pDispParams, pVarResult, pExcepInfo, pArgErr);
+                    IDispatch_Release(pDispatch);
+                }
+                else
+                {
+                    VariantClear(pVarResult);
+                    hres = DISP_E_NOTACOLLECTION;
+                }
+            }
+
 func_fail:
             HeapFree(GetProcessHeap(), 0, buffer);
             break;




More information about the wine-cvs mailing list