diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index f705722f09f..04f0d4de22e 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -24,13 +24,26 @@ #include #include -#include +#include "wine/test.h" #include "tmarshal.h" #include "tmarshal_dispids.h" #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", (unsigned long int)hr) +/* ULL suffix is not portable */ +#define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2) + +const MYSTRUCT MYSTRUCT_BYVAL = {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432)}; +const MYSTRUCT MYSTRUCT_BYPTR = {0x91827364, ULL_CONST(0x88776655, 0x44332211)}; +const MYSTRUCT MYSTRUCT_ARRAY[5] = { + {0x1a1b1c1d, ULL_CONST(0x1e1f1011, 0x12131415)}, + {0x2a2b2c2d, ULL_CONST(0x2e2f2021, 0x22232425)}, + {0x3a3b3c3d, ULL_CONST(0x3e3f3031, 0x32333435)}, + {0x4a4b4c4d, ULL_CONST(0x4e4f4041, 0x42434445)}, + {0x5a5b5c5d, ULL_CONST(0x5e5f5051, 0x52535455)}, +}; + /* Debugging functions from wine/libs/wine/debug.c */ /* allocate some tmp string space */ @@ -575,6 +588,18 @@ void WINAPI Widget_VarArg( ok(hr == S_OK, "SafeArrayUnaccessData failed with %x\n", hr); } +void WINAPI Widget_StructArgs( + IWidget * iface, + MYSTRUCT byval, + MYSTRUCT *byptr, + MYSTRUCT arr[5]) +{ + ok(memcmp(&byval, &MYSTRUCT_BYVAL, sizeof(MYSTRUCT))==0, "Struct parameter passed by value corrupted\n"); + ok(memcmp(byptr, &MYSTRUCT_BYPTR, sizeof(MYSTRUCT))==0, "Struct parameter passed by pointer corrupted\n"); + ok(memcmp(arr, MYSTRUCT_ARRAY, sizeof(MYSTRUCT_ARRAY))==0, "Array of structs corrupted\n"); +} + + HRESULT WINAPI Widget_Error( IWidget __RPC_FAR * iface) { @@ -616,6 +641,7 @@ static const struct IWidgetVtbl Widget_VTable = Widget_VariantArrayPtr, Widget_Variant, Widget_VarArg, + Widget_StructArgs, Widget_Error, Widget_CloneInterface }; @@ -932,6 +958,8 @@ static void test_typelibmarshal(void) DWORD tid; BSTR bstr; ITypeInfo *pTypeInfo; + MYSTRUCT mystruct; + MYSTRUCT mystructArray[5]; ok(pKEW != NULL, "Widget creation failed\n"); @@ -1071,6 +1099,11 @@ static void test_typelibmarshal(void) ok_ole_success(hr, IDispatch_Invoke); VariantClear(&varresult); + /* call StructArgs (direct) */ + mystruct = MYSTRUCT_BYPTR; + memcpy(mystructArray, MYSTRUCT_ARRAY, sizeof(mystructArray)); + IWidget_StructArgs(pWidget, MYSTRUCT_BYVAL, &mystruct, mystructArray); + /* call Clone */ dispparams.cNamedArgs = 0; dispparams.cArgs = 0; diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index 2367f2894f1..ea10797d410 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -35,6 +35,12 @@ library TestTypelib STATE_WIDGETIFIED } STATE; + typedef struct tagMYSTRUCT + { + INT field1; + ULONGLONG field2; + } MYSTRUCT; + coclass ApplicationObject2; [ @@ -111,6 +117,9 @@ library TestTypelib [vararg, id(DISPID_TM_VARARG)] void VarArg([in] int numexpect, [in] SAFEARRAY(VARIANT) values); + [id(DISPID_TM_STRUCTARGS)] + void StructArgs([in] MYSTRUCT byval, [in] MYSTRUCT *byptr, [in] MYSTRUCT arr[5]); + [id(DISPID_TM_ERROR)] HRESULT Error(); diff --git a/dlls/oleaut32/tests/tmarshal_dispids.h b/dlls/oleaut32/tests/tmarshal_dispids.h index 803b94be9e4..8fcf10909b9 100644 --- a/dlls/oleaut32/tests/tmarshal_dispids.h +++ b/dlls/oleaut32/tests/tmarshal_dispids.h @@ -33,5 +33,6 @@ #define DISPID_TM_ERROR 14 #define DISPID_TM_CLONEINTERFACE 15 #define DISPID_TM_TESTDUAL 16 +#define DISPID_TM_STRUCTARGS 17 #define DISPID_NOA_BSTRRET 1 diff --git a/dlls/oleaut32/tmarshal.c b/dlls/oleaut32/tmarshal.c index 0123e52eb38..fdfe07ce7c9 100644 --- a/dlls/oleaut32/tmarshal.c +++ b/dlls/oleaut32/tmarshal.c @@ -524,6 +524,22 @@ _argsize(TYPEDESC *tdesc, ITypeInfo *tinfo) { return (sizeof(DECIMAL)+3)/sizeof(DWORD); case VT_VARIANT: return (sizeof(VARIANT)+3)/sizeof(DWORD); + case VT_USERDEFINED: + { + ITypeInfo *tinfo2; + TYPEATTR *tattr; + HRESULT hres; + DWORD ret; + + hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2); + if (FAILED(hres)) + return 0; /* should fail critically in serialize_param */ + ITypeInfo_GetTypeAttr(tinfo2,&tattr); + ret = (tattr->cbSizeInstance+3)/sizeof(DWORD); + ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); + ITypeInfo_Release(tinfo2); + return ret; + } default: return 1; } @@ -558,6 +574,22 @@ _xsize(const TYPEDESC *td, ITypeInfo *tinfo) { case VT_UI1: case VT_I1: return 1; + case VT_USERDEFINED: + { + ITypeInfo *tinfo2; + TYPEATTR *tattr; + HRESULT hres; + DWORD ret; + + hres = ITypeInfo_GetRefTypeInfo(tinfo,td->u.hreftype,&tinfo2); + if (FAILED(hres)) + return 0; + ITypeInfo_GetTypeAttr(tinfo2,&tattr); + ret = tattr->cbSizeInstance; + ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); + ITypeInfo_Release(tinfo2); + return ret; + } default: return 4; } @@ -1149,9 +1181,6 @@ deserialize_param( case TKIND_RECORD: { int i; - if (alloc) - *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance); - if (debugout) TRACE_(olerelay)("{"); for (i=0;icVars;i++) { VARDESC *vdesc; @@ -1169,7 +1198,7 @@ deserialize_param( debugout, alloc, &vdesc->elemdescVar.tdesc, - (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst), + (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst), buf ); ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc);