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) ...@@ -1192,6 +1192,56 @@ static void test_marshal_VARIANT(void)
IUnknown_Release((IUnknown *)heap_unknown); IUnknown_Release((IUnknown *)heap_unknown);
} }
HeapFree(GetProcessHeap(), 0, buffer); 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) ...@@ -277,14 +277,14 @@ static unsigned int get_type_alignment(ULONG *pFlags, VARIANT *pvar)
return 7; 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; ULONG size;
HRESULT hr; HRESULT hr;
/* find the buffer size of the marshalled dispatch interface */ /* 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 (FAILED(hr)) {
if (!V_DISPATCH(pvar)) if (!punk)
WARN("NULL dispatch pointer\n"); WARN("NULL dispatch pointer\n");
else else
ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%x\n", hr); 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) ...@@ -313,9 +313,13 @@ static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
case VT_VARIANT | VT_BYREF: case VT_VARIANT | VT_BYREF:
return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar)); return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar));
case VT_UNKNOWN: 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: 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: case VT_RECORD:
FIXME("wire-size record\n"); FIXME("wire-size record\n");
return Start; return Start;
...@@ -329,7 +333,7 @@ static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar) ...@@ -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 */ /* 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; IStream *working;
HGLOBAL working_mem; HGLOBAL working_mem;
...@@ -338,7 +342,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu ...@@ -338,7 +342,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu
ULONG size; ULONG size;
HRESULT hr; 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; oldpos = Buffer;
...@@ -348,7 +352,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu ...@@ -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 * 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. */ * 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); working_mem = GlobalAlloc(0, size);
if (!working_mem) return oldpos; if (!working_mem) return oldpos;
...@@ -359,7 +363,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu ...@@ -359,7 +363,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu
return oldpos; 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) { if (hr != S_OK) {
IStream_Release(working); /* this also releases the hglobal */ IStream_Release(working); /* this also releases the hglobal */
return oldpos; return oldpos;
...@@ -378,7 +382,7 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu ...@@ -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 */ /* 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; IStream *working;
HGLOBAL working_mem; HGLOBAL working_mem;
...@@ -387,10 +391,10 @@ static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char * ...@@ -387,10 +391,10 @@ static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *
ULONG size; ULONG size;
HRESULT hr; 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; oldpos = Buffer;
/* get the buffersize */ /* get the buffersize */
memcpy(&size, Buffer, sizeof(ULONG)); memcpy(&size, Buffer, sizeof(ULONG));
TRACE("buffersize=%d\n", size); TRACE("buffersize=%d\n", size);
...@@ -410,7 +414,7 @@ static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char * ...@@ -410,7 +414,7 @@ static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *
memcpy(working_memlocked, Buffer + sizeof(ULONG), size); memcpy(working_memlocked, Buffer + sizeof(ULONG), size);
GlobalUnlock(working_mem); GlobalUnlock(working_mem);
hr = CoUnmarshalInterface(working, riid, (void**)&V_UNKNOWN(pvar)); hr = CoUnmarshalInterface(working, riid, (void**)ppunk);
if (hr != S_OK) { if (hr != S_OK) {
IStream_Release(working); IStream_Release(working);
return oldpos; return oldpos;
...@@ -520,16 +524,21 @@ unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, ...@@ -520,16 +524,21 @@ unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer,
case VT_VARIANT | VT_BYREF: case VT_VARIANT | VT_BYREF:
Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar)); Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
break; break;
case VT_DISPATCH | VT_BYREF:
FIXME("handle DISPATCH by ref\n");
break;
case VT_UNKNOWN: case VT_UNKNOWN:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ /* 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; break;
case VT_DISPATCH: case VT_DISPATCH:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ /* 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; break;
case VT_RECORD: case VT_RECORD:
FIXME("handle BRECORD by val\n"); FIXME("handle BRECORD by val\n");
...@@ -609,16 +618,21 @@ unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffe ...@@ -609,16 +618,21 @@ unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffe
case VT_VARIANT | VT_BYREF: case VT_VARIANT | VT_BYREF:
Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar)); Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
break; break;
case VT_DISPATCH | VT_BYREF:
FIXME("handle DISPATCH by ref\n");
break;
case VT_UNKNOWN: case VT_UNKNOWN:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ /* 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; break;
case VT_DISPATCH: case VT_DISPATCH:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ /* 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; break;
case VT_RECORD: case VT_RECORD:
FIXME("handle BRECORD by val\n"); 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