Commit 3c8534f0 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

oleaut32: Implement marshaling of VT_BYREF interfaces.

parent 17fca45d
......@@ -1192,6 +1192,56 @@ static void test_marshal_VARIANT(void)
IUnknown_Release((IUnknown *)heap_unknown);
}
HeapFree(GetProcessHeap(), 0, buffer);
/*** UNKNOWN BYREF ***/
heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
heap_unknown->refs = 1;
VariantInit(&v);
VariantInit(&v2);
V_VT(&v) = VT_UNKNOWN | VT_BYREF;
V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
ok(stubMsg.BufferLength > 36, "size %d\n", stubMsg.BufferLength);
buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
memset(buffer, 0xcc, stubMsg.BufferLength);
next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
wirev = (DWORD*)buffer;
check_variant_header(wirev, &v, next - buffer);
wirev += 5;
ok(*wirev == 4, "wv[5] %08x\n", *wirev);
wirev++;
todo_wine
ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ ||
*wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev);
wirev++;
todo_wine
ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev);
wirev++;
todo_wine
ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev);
wirev++;
todo_wine
ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev);
if (VARIANT_UNMARSHAL_WORKS)
{
VARIANT v3;
VariantInit(&v3);
V_VT(&v3) = VT_UNKNOWN;
V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
IUnknown_AddRef(V_UNKNOWN(&v3));
stubMsg.Buffer = buffer;
next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
VARIANT_UserFree(&umcb.Flags, &v3);
ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
IUnknown_Release((IUnknown *)heap_unknown);
}
HeapFree(GetProcessHeap(), 0, buffer);
}
......
......@@ -277,14 +277,14 @@ static unsigned int get_type_alignment(ULONG *pFlags, VARIANT *pvar)
return 7;
}
static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, VARIANT *pvar)
static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, IUnknown *punk)
{
ULONG size;
HRESULT hr;
/* find the buffer size of the marshalled dispatch interface */
hr = CoGetMarshalSizeMax(&size, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
hr = CoGetMarshalSizeMax(&size, riid, punk, LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
if (FAILED(hr)) {
if (!V_DISPATCH(pvar))
if (!punk)
WARN("NULL dispatch pointer\n");
else
ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%x\n", hr);
......@@ -313,9 +313,13 @@ static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
case VT_VARIANT | VT_BYREF:
return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar));
case VT_UNKNOWN:
return Start + interface_variant_size(pFlags, &IID_IUnknown, pvar);
return Start + interface_variant_size(pFlags, &IID_IUnknown, V_UNKNOWN(pvar));
case VT_UNKNOWN | VT_BYREF:
return Start + interface_variant_size(pFlags, &IID_IUnknown, *V_UNKNOWNREF(pvar));
case VT_DISPATCH:
return Start + interface_variant_size(pFlags, &IID_IDispatch, pvar);
return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
case VT_DISPATCH | VT_BYREF:
return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
case VT_RECORD:
FIXME("wire-size record\n");
return Start;
......@@ -329,7 +333,7 @@ static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
}
/* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer. returns Buffer on failure, new position otherwise */
static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar)
static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, IUnknown *punk)
{
IStream *working;
HGLOBAL working_mem;
......@@ -338,7 +342,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu
ULONG size;
HRESULT hr;
TRACE("pFlags=%d, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
TRACE("pFlags=%d, Buffer=%p, pUnk=%p\n", *pFlags, Buffer, punk);
oldpos = Buffer;
......@@ -348,7 +352,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu
* but that would be overkill here, hence this implementation. We save the size because the unmarshal
* code has no way to know how long the marshalled buffer is. */
size = wire_extra_user_size(pFlags, 0, pvar);
size = interface_variant_size(pFlags, riid, punk);
working_mem = GlobalAlloc(0, size);
if (!working_mem) return oldpos;
......@@ -359,7 +363,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu
return oldpos;
}
hr = CoMarshalInterface(working, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
hr = CoMarshalInterface(working, riid, punk, LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
if (hr != S_OK) {
IStream_Release(working); /* this also releases the hglobal */
return oldpos;
......@@ -378,7 +382,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu
}
/* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer. returns Buffer on failure, new position otherwise */
static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar)
static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, IUnknown **ppunk)
{
IStream *working;
HGLOBAL working_mem;
......@@ -387,10 +391,10 @@ static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *
ULONG size;
HRESULT hr;
TRACE("pFlags=%d, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
TRACE("pFlags=%d, Buffer=%p, ppUnk=%p\n", *pFlags, Buffer, ppunk);
oldpos = Buffer;
/* get the buffersize */
memcpy(&size, Buffer, sizeof(ULONG));
TRACE("buffersize=%d\n", size);
......@@ -410,7 +414,7 @@ static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *
memcpy(working_memlocked, Buffer + sizeof(ULONG), size);
GlobalUnlock(working_mem);
hr = CoUnmarshalInterface(working, riid, (void**)&V_UNKNOWN(pvar));
hr = CoUnmarshalInterface(working, riid, (void**)ppunk);
if (hr != S_OK) {
IStream_Release(working);
return oldpos;
......@@ -520,16 +524,21 @@ unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer,
case VT_VARIANT | VT_BYREF:
Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
break;
case VT_DISPATCH | VT_BYREF:
FIXME("handle DISPATCH by ref\n");
break;
case VT_UNKNOWN:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar);
Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar));
break;
case VT_UNKNOWN | VT_BYREF:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar));
break;
case VT_DISPATCH:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar);
Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
break;
case VT_DISPATCH | VT_BYREF:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
break;
case VT_RECORD:
FIXME("handle BRECORD by val\n");
......@@ -609,16 +618,21 @@ unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffe
case VT_VARIANT | VT_BYREF:
Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
break;
case VT_DISPATCH | VT_BYREF:
FIXME("handle DISPATCH by ref\n");
break;
case VT_UNKNOWN:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, pvar);
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar));
break;
case VT_UNKNOWN | VT_BYREF:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar));
break;
case VT_DISPATCH:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, pvar);
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar));
break;
case VT_DISPATCH | VT_BYREF:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar));
break;
case VT_RECORD:
FIXME("handle BRECORD by val\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment