From 522a00e69a4a2481e2b066f0fcc71227a74848b3 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Thu, 25 Feb 2010 13:48:22 +0000 Subject: [PATCH] oleaut32: Correctly marshal NULL interface ptrs. --- dlls/oleaut32/tests/usrmarshal.c | 24 +++++++++++++++++++ dlls/oleaut32/usrmarshal.c | 41 +++++++++++++++++++++----------- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c index b5cdc1e3de..92758374b1 100644 --- a/dlls/oleaut32/tests/usrmarshal.c +++ b/dlls/oleaut32/tests/usrmarshal.c @@ -1427,6 +1427,30 @@ static void test_marshal_VARIANT(void) } HeapFree(GetProcessHeap(), 0, oldbuffer); + /*** NULL UNKNOWN ***/ + VariantInit(&v); + V_VT(&v) = VT_UNKNOWN; + V_UNKNOWN(&v) = NULL; + + rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); + ok(stubMsg.BufferLength >= 24, "size %d\n", stubMsg.BufferLength); + buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); + 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 == 0, "wv[5] %08x\n", *wirev); + + VariantInit(&v2); + stubMsg.Buffer = buffer; + next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); + ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); + ok(V_UNKNOWN(&v2) == NULL, "got %p expect NULL\n", V_UNKNOWN(&v2)); + VARIANT_UserFree(&umcb.Flags, &v2); + HeapFree(GetProcessHeap(), 0, oldbuffer); + /*** UNKNOWN BYREF ***/ heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown)); heap_unknown->lpVtbl = &HeapUnknown_Vtbl; diff --git a/dlls/oleaut32/usrmarshal.c b/dlls/oleaut32/usrmarshal.c index 202cf843b9..402794ce33 100644 --- a/dlls/oleaut32/usrmarshal.c +++ b/dlls/oleaut32/usrmarshal.c @@ -256,20 +256,21 @@ static unsigned int get_type_alignment(ULONG *pFlags, VARTYPE vt) static unsigned interface_variant_size(const ULONG *pFlags, REFIID riid, IUnknown *punk) { - ULONG size; - HRESULT hr; - /* find the buffer size of the marshalled dispatch interface */ - hr = CoGetMarshalSizeMax(&size, riid, punk, LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL); - if (FAILED(hr)) { - if (!punk) - WARN("NULL dispatch pointer\n"); - else - ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%x\n", hr); - return 0; - } - size += sizeof(ULONG); /* we have to store the buffersize in the stream */ - TRACE("wire-size extra of dispatch variant is %d\n", size); - return size; + ULONG size = 0; + HRESULT hr; + + if (punk) + { + hr = CoGetMarshalSizeMax(&size, riid, punk, LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL); + if (FAILED(hr)) + { + ERR("interface variant buffer size calculation failed, HRESULT=0x%x\n", hr); + return 0; + } + } + size += sizeof(ULONG); /* we have to store the buffersize in the stream */ + TRACE("wire-size extra of interface variant is %d\n", size); + return size; } static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar) @@ -322,6 +323,12 @@ static unsigned char* interface_variant_marshal(const ULONG *pFlags, unsigned ch TRACE("pFlags=%d, Buffer=%p, pUnk=%p\n", *pFlags, Buffer, punk); + if(!punk) + { + memset(Buffer, 0, sizeof(ULONG)); + return Buffer + sizeof(ULONG); + } + oldpos = Buffer; /* CoMarshalInterface needs a stream, whereas at this level we are operating in terms of buffers. @@ -378,6 +385,12 @@ static unsigned char *interface_variant_unmarshal(const ULONG *pFlags, unsigned memcpy(&size, Buffer, sizeof(ULONG)); TRACE("buffersize=%d\n", size); + if(!size) + { + *ppunk = NULL; + return Buffer + sizeof(ULONG); + } + working_mem = GlobalAlloc(0, size); if (!working_mem) return oldpos; -- 2.32.0.93.g670b81a890