From 5b6312f24cab6dbf2dd0cd67c21f5423ddc5cd32 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Thu, 14 May 2009 12:23:37 +0100 Subject: [PATCH] ole32: Implement the WdtpInterfacePointer marshal functions. --- dlls/ole32/tests/usrmarshal.c | 53 +++++++++---------- dlls/ole32/usrmarshal.c | 98 +++++++++++++++++++++++++++++++---- 2 files changed, 113 insertions(+), 38 deletions(-) diff --git a/dlls/ole32/tests/usrmarshal.c b/dlls/ole32/tests/usrmarshal.c index e597b21e14..f1c0e34e89 100644 --- a/dlls/ole32/tests/usrmarshal.c +++ b/dlls/ole32/tests/usrmarshal.c @@ -512,7 +512,11 @@ static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx) IUnknown *unk; IUnknown *unk2; unsigned char *wireip; - DWORD expected_size; + HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0); + IStream *stm; + void *ptr; + LARGE_INTEGER pos; + DWORD h_size, marshal_size, expected_size; /* The marshalled data depends on the LOWORD of the ctx */ @@ -541,42 +545,35 @@ static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx) init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx); buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown); wireip = buffer; - if(size) - { - HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0); - IStream *stm; - void *ptr; - LARGE_INTEGER pos; - DWORD h_size, marshal_size; - ok(buffer_end == buffer + expected_size, "buffer_end %p buffer %p (diff %x)\n", buffer_end, buffer, buffer_end - buffer); + /* Wine's standard marshalling appears to be a DWORD short */ + todo_wine + ok(buffer_end == buffer + expected_size, "buffer_end %p buffer %p (diff %x)\n", buffer_end, buffer, buffer_end - buffer); - marshal_size = buffer_end - buffer - 2 * sizeof(DWORD); - ok(*(DWORD *)wireip == marshal_size, "wireip + 0x0 should be 0x44 instead of 0x%08x\n", *(DWORD *)wireip); - wireip += sizeof(DWORD); - ok(*(DWORD *)wireip == marshal_size, "wireip + 0x4 should be 0x44 instead of 0x%08x\n", *(DWORD *)wireip); - wireip += sizeof(DWORD); + marshal_size = buffer_end - buffer - 2 * sizeof(DWORD); + ok(*(DWORD *)wireip == marshal_size, "wireip + 0x0 should be 0x44 instead of 0x%08x\n", *(DWORD *)wireip); + wireip += sizeof(DWORD); + ok(*(DWORD *)wireip == marshal_size, "wireip + 0x4 should be 0x44 instead of 0x%08x\n", *(DWORD *)wireip); + wireip += sizeof(DWORD); - /* The remaining 0x44/0xac bytes are the result of CoMarshalInterface */ + /* The remaining 0x44/0xac bytes are the result of CoMarshalInterface */ - CreateStreamOnHGlobal(h, TRUE, &stm); - CoMarshalInterface(stm, &IID_IUnknown, unk, LOWORD(ctx), NULL, MSHLFLAGS_NORMAL); - h_size = GlobalSize(h); - ok(h_size == marshal_size, "size %x\n", h_size); + CreateStreamOnHGlobal(h, TRUE, &stm); + CoMarshalInterface(stm, &IID_IUnknown, unk, LOWORD(ctx), NULL, MSHLFLAGS_NORMAL); + h_size = GlobalSize(h); + ok(h_size == marshal_size, "size %x\n", h_size); - ptr = GlobalLock(h); - ok(!memcmp(ptr, wireip, h_size), "buffer mismatch\n"); - GlobalUnlock(h); - pos.QuadPart = 0; - IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL); - CoReleaseMarshalData(stm); - IStream_Release(stm); - } + ptr = GlobalLock(h); + ok(!memcmp(ptr, wireip, h_size), "buffer mismatch\n"); + GlobalUnlock(h); + pos.QuadPart = 0; + IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL); + CoReleaseMarshalData(stm); + IStream_Release(stm); unk2 = NULL; init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx); WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown); - todo_wine ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n"); HeapFree(GetProcessHeap(), 0, buffer); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC); diff --git a/dlls/ole32/usrmarshal.c b/dlls/ole32/usrmarshal.c index 57a048e82d..07a4aed1c4 100644 --- a/dlls/ole32/usrmarshal.c +++ b/dlls/ole32/usrmarshal.c @@ -1570,10 +1570,19 @@ void __RPC_USER HMETAFILEPICT_UserFree(ULONG *pFlags, HMETAFILEPICT *phMfp) * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which * the first parameter is a ULONG. */ -ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, IUnknown *punk, ULONG StartingSize, REFIID riid) +ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, ULONG StartingSize, IUnknown *punk, REFIID riid) { - FIXME("(%s, 0%x, %p, %d, %s): stub\n", debugstr_user_flags(pFlags), RealFlags, punk, StartingSize, debugstr_guid(riid)); - return 0; + DWORD marshal_size = 0; + HRESULT hr; + + TRACE("(%s, 0%x, %d, %p, %s)\n", debugstr_user_flags(pFlags), RealFlags, StartingSize, punk, debugstr_guid(riid)); + + hr = CoGetMarshalSizeMax(&marshal_size, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL); + if(FAILED(hr)) return StartingSize; + + ALIGN_LENGTH(StartingSize, 3); + StartingSize += 2 * sizeof(DWORD); + return StartingSize + marshal_size; } /****************************************************************************** @@ -1598,8 +1607,40 @@ ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, I */ unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer, IUnknown *punk, REFIID riid) { - FIXME("(%s, 0x%x, %p, &%p, %s): stub\n", debugstr_user_flags(pFlags), RealFlags, pBuffer, punk, debugstr_guid(riid)); - return NULL; + HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0); + IStream *stm; + DWORD size; + void *ptr; + + TRACE("(%s, 0x%x, %p, &%p, %s)\n", debugstr_user_flags(pFlags), RealFlags, pBuffer, punk, debugstr_guid(riid)); + + if(!h) return NULL; + if(CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK) + { + GlobalFree(h); + return NULL; + } + + if(CoMarshalInterface(stm, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL) != S_OK) + { + IStream_Release(stm); + return NULL; + } + + ALIGN_POINTER(pBuffer, 3); + size = GlobalSize(h); + + *(DWORD *)pBuffer = size; + pBuffer += sizeof(DWORD); + *(DWORD *)pBuffer = size; + pBuffer += sizeof(DWORD); + + ptr = GlobalLock(h); + memcpy(pBuffer, ptr, size); + GlobalUnlock(h); + + IStream_Release(stm); + return pBuffer + size; } /****************************************************************************** @@ -1623,24 +1664,61 @@ unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG Rea */ unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid) { - FIXME("(%s, %p, %p, %s): stub\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid)); - return NULL; + HRESULT hr; + HGLOBAL h; + IStream *stm; + DWORD size; + void *ptr; + + TRACE("(%s, %p, %p, %s)\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid)); + + ALIGN_POINTER(pBuffer, 3); + + size = *(DWORD *)pBuffer; + pBuffer += sizeof(DWORD); + if(size != *(DWORD *)pBuffer) + RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL); + + pBuffer += sizeof(DWORD); + + /* FIXME: sanity check on size */ + + h = GlobalAlloc(GMEM_MOVEABLE, size); + if(!h) RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL); + + if(CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK) + { + GlobalFree(h); + RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL); + } + + ptr = GlobalLock(h); + memcpy(ptr, pBuffer, size); + GlobalUnlock(h); + + hr = CoUnmarshalInterface(stm, riid, (void**)ppunk); + IStream_Release(stm); + + if(hr != S_OK) RaiseException(hr, 0, 0, NULL); + + return pBuffer + size; } /****************************************************************************** * WdtpInterfacePointer_UserFree [OLE32.@] * - * Frees an unmarshaled interface pointer. + * Releases an unmarshaled interface pointer. * * PARAMS - * punk [I] Interface pointer to free. + * punk [I] Interface pointer to release. * * RETURNS * Nothing. */ void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk) { - FIXME("(%p): stub\n", punk); + TRACE("(%p)\n", punk); + if(punk) IUnknown_Release(punk); } /******************************************************************************