dispex: Check whether the server function changes the type of the arguments.
authorHuw Davies <huw@codeweavers.com>
Mon, 22 Mar 2010 14:44:52 +0000 (14:44 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 23 Mar 2010 12:24:27 +0000 (13:24 +0100)
dlls/dispex/tests/marshal.c
dlls/dispex/usrmarshal.c

index b2777195493853eeb6726ceab739a31c483bf662..43806219591eecf9d064a41ba7c302a5f3a247e8 100644 (file)
@@ -405,7 +405,6 @@ static void test_dispex(void)
     /* change one of the argument vts */
     i = 0xbeef;
     hr = IDispatchEx_InvokeEx(dispex, 3, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-todo_wine
     ok(hr == DISP_E_BADCALLEE, "got %08x\n", hr);
 
     hr = IDispatchEx_InvokeEx(dispex, 4, LOCALE_SYSTEM_DEFAULT, 0xffff, &params, NULL, NULL, NULL);
index 915e5bc3320974e06ff6c6275298ce65e1c8913d..cc7246917535859633bf0dd9a79badbaee191d1f 100644 (file)
@@ -118,6 +118,7 @@ HRESULT __RPC_STUB IDispatchEx_InvokeEx_Stub(IDispatchEx* This, DISPID id, LCID
 {
     HRESULT hr;
     UINT arg;
+    VARTYPE *vt_list = NULL;
 
     TRACE("(%p)->(%08x, %04x, %08x, %p, %p, %p, %p, %d, %p, %p)\n", This, id, lcid, dwFlags,
           pdp, result, pei, pspCaller, byref_args, ref_idx, ref_arg);
@@ -131,8 +132,30 @@ HRESULT __RPC_STUB IDispatchEx_InvokeEx_Stub(IDispatchEx* This, DISPID id, LCID
     if(dwFlags & NULL_RESULT) result = NULL;
     if(dwFlags & NULL_EXCEPINFO) pei = NULL;
 
+    /* Create an array of the original VTs to check that the function doesn't change
+       any on return. */
+    if(byref_args)
+    {
+        vt_list = HeapAlloc(GetProcessHeap(), 0, pdp->cArgs * sizeof(vt_list[0]));
+        if(!vt_list) return E_OUTOFMEMORY;
+        for(arg = 0; arg < pdp->cArgs; arg++)
+            vt_list[arg] = V_VT(pdp->rgvarg + arg);
+    }
+
     hr = IDispatchEx_InvokeEx(This, id, lcid, dwFlags & 0xffff, pdp, result, pei, pspCaller);
 
+    if(SUCCEEDED(hr) && byref_args)
+    {
+        for(arg = 0; arg < pdp->cArgs; arg++)
+        {
+            if(vt_list[arg] != V_VT(pdp->rgvarg + arg))
+            {
+                hr = DISP_E_BADCALLEE;
+                break;
+            }
+        }
+    }
+
     if(hr == DISP_E_EXCEPTION)
     {
         if(pei && pei->pfnDeferredFillIn)
@@ -145,5 +168,6 @@ HRESULT __RPC_STUB IDispatchEx_InvokeEx_Stub(IDispatchEx* This, DISPID id, LCID
     for(arg = 0; arg < byref_args; arg++)
         VariantInit(pdp->rgvarg + ref_idx[arg]);
 
+    HeapFree(GetProcessHeap(), 0, vt_list);
     return hr;
 }