2007-11-29 12:54:54 +00:00
|
|
|
/*
|
|
|
|
* User Marshaling Tests
|
|
|
|
*
|
|
|
|
* Copyright 2004-2006 Robert Shearman for CodeWeavers
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
2013-03-23 10:35:40 +00:00
|
|
|
#define WIN32_NO_STATUS
|
|
|
|
#define _INC_WINDOWS
|
|
|
|
#define COM_NO_WINDOWS_H
|
|
|
|
|
2007-11-29 12:54:54 +00:00
|
|
|
#define COBJMACROS
|
|
|
|
#define CONST_VTABLE
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
2013-03-23 10:35:40 +00:00
|
|
|
#include <windef.h>
|
|
|
|
#include <winbase.h>
|
|
|
|
#include <wingdi.h>
|
|
|
|
#include <ole2.h>
|
|
|
|
//#include "objbase.h"
|
|
|
|
//#include "objidl.h"
|
2007-11-29 12:54:54 +00:00
|
|
|
|
2013-03-23 10:35:40 +00:00
|
|
|
#include <wine/test.h>
|
2007-11-29 12:54:54 +00:00
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
ULONG __RPC_USER HMETAFILE_UserSize(ULONG *, ULONG, HMETAFILE *);
|
2007-11-29 12:54:54 +00:00
|
|
|
unsigned char * __RPC_USER HMETAFILE_UserMarshal(ULONG *, unsigned char *, HMETAFILE *);
|
|
|
|
unsigned char * __RPC_USER HMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HMETAFILE *);
|
|
|
|
void __RPC_USER HMETAFILE_UserFree(ULONG *, HMETAFILE *);
|
|
|
|
|
2009-01-18 19:23:06 +00:00
|
|
|
ULONG __RPC_USER HENHMETAFILE_UserSize(ULONG *, ULONG, HENHMETAFILE *);
|
|
|
|
unsigned char * __RPC_USER HENHMETAFILE_UserMarshal (ULONG *, unsigned char *, HENHMETAFILE *);
|
|
|
|
unsigned char * __RPC_USER HENHMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HENHMETAFILE *);
|
|
|
|
void __RPC_USER HENHMETAFILE_UserFree(ULONG *, HENHMETAFILE *);
|
|
|
|
|
|
|
|
ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *, ULONG, HMETAFILEPICT *);
|
|
|
|
unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal (ULONG *, unsigned char *, HMETAFILEPICT *);
|
|
|
|
unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *, unsigned char *, HMETAFILEPICT *);
|
|
|
|
void __RPC_USER HMETAFILEPICT_UserFree(ULONG *, HMETAFILEPICT *);
|
|
|
|
|
2015-07-19 23:12:15 +00:00
|
|
|
ULONG __RPC_USER HBRUSH_UserSize(ULONG *, ULONG, HBRUSH *);
|
|
|
|
unsigned char * __RPC_USER HBRUSH_UserMarshal(ULONG *, unsigned char *, HBRUSH *);
|
|
|
|
unsigned char * __RPC_USER HBRUSH_UserUnmarshal(ULONG *, unsigned char *, HBRUSH *);
|
|
|
|
void __RPC_USER HBRUSH_UserFree(ULONG *, HBRUSH *);
|
|
|
|
|
|
|
|
static BOOL g_expect_user_alloc;
|
2009-05-17 07:05:22 +00:00
|
|
|
static void * WINAPI user_allocate(SIZE_T size)
|
|
|
|
{
|
2015-07-19 23:12:15 +00:00
|
|
|
ok(g_expect_user_alloc, "unexpected user_allocate call\n");
|
2009-05-17 07:05:22 +00:00
|
|
|
return CoTaskMemAlloc(size);
|
|
|
|
}
|
|
|
|
|
2015-07-19 23:12:15 +00:00
|
|
|
static BOOL g_expect_user_free;
|
2009-05-17 07:05:22 +00:00
|
|
|
static void WINAPI user_free(void *p)
|
|
|
|
{
|
2015-07-19 23:12:15 +00:00
|
|
|
ok(g_expect_user_free, "unexpected user_free call\n");
|
2009-05-17 07:05:22 +00:00
|
|
|
CoTaskMemFree(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
|
|
|
|
PMIDL_STUB_MESSAGE stub_msg,
|
|
|
|
PRPC_MESSAGE rpc_msg, unsigned char *buffer,
|
|
|
|
unsigned int size, MSHCTX context)
|
|
|
|
{
|
|
|
|
memset(rpc_msg, 0, sizeof(*rpc_msg));
|
|
|
|
rpc_msg->Buffer = buffer;
|
|
|
|
rpc_msg->BufferLength = size;
|
|
|
|
|
|
|
|
memset(stub_msg, 0, sizeof(*stub_msg));
|
|
|
|
stub_msg->RpcMsg = rpc_msg;
|
|
|
|
stub_msg->Buffer = buffer;
|
|
|
|
stub_msg->pfnAllocate = user_allocate;
|
|
|
|
stub_msg->pfnFree = user_free;
|
|
|
|
|
|
|
|
memset(umcb, 0, sizeof(*umcb));
|
|
|
|
umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION);
|
|
|
|
umcb->pStubMsg = stub_msg;
|
|
|
|
umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
|
|
|
|
umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
|
|
|
|
}
|
2009-01-18 19:23:06 +00:00
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
#define RELEASEMARSHALDATA WM_USER
|
|
|
|
|
|
|
|
struct host_object_data
|
|
|
|
{
|
|
|
|
IStream *stream;
|
|
|
|
IID iid;
|
|
|
|
IUnknown *object;
|
|
|
|
MSHLFLAGS marshal_flags;
|
|
|
|
HANDLE marshal_event;
|
|
|
|
IMessageFilter *filter;
|
|
|
|
};
|
|
|
|
|
|
|
|
static DWORD CALLBACK host_object_proc(LPVOID p)
|
|
|
|
{
|
|
|
|
struct host_object_data *data = p;
|
|
|
|
HRESULT hr;
|
|
|
|
MSG msg;
|
|
|
|
|
|
|
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
|
|
|
|
|
|
if (data->filter)
|
|
|
|
{
|
|
|
|
IMessageFilter * prev_filter = NULL;
|
|
|
|
hr = CoRegisterMessageFilter(data->filter, &prev_filter);
|
|
|
|
if (prev_filter) IMessageFilter_Release(prev_filter);
|
|
|
|
ok(hr == S_OK, "got %08x\n", hr);
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
|
|
|
|
ok(hr == S_OK, "got %08x\n", hr);
|
|
|
|
|
|
|
|
/* force the message queue to be created before signaling parent thread */
|
|
|
|
PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
|
|
|
|
|
|
|
SetEvent(data->marshal_event);
|
|
|
|
|
|
|
|
while (GetMessageA(&msg, NULL, 0, 0))
|
|
|
|
{
|
|
|
|
if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
|
|
|
|
{
|
|
|
|
CoReleaseMarshalData(data->stream);
|
|
|
|
SetEvent((HANDLE)msg.lParam);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
DispatchMessageA(&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, data);
|
|
|
|
|
|
|
|
CoUninitialize();
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
|
|
|
|
{
|
|
|
|
DWORD tid = 0;
|
|
|
|
HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
|
|
|
|
struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
|
|
|
|
|
|
|
|
data->stream = stream;
|
|
|
|
data->iid = *riid;
|
|
|
|
data->object = object;
|
|
|
|
data->marshal_flags = marshal_flags;
|
|
|
|
data->marshal_event = marshal_event;
|
|
|
|
data->filter = filter;
|
|
|
|
|
|
|
|
*thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
|
|
|
|
|
|
|
|
/* wait for marshaling to complete before returning */
|
|
|
|
ok( !WaitForSingleObject(marshal_event, 10000), "wait timed out\n" );
|
|
|
|
CloseHandle(marshal_event);
|
|
|
|
|
|
|
|
return tid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void end_host_object(DWORD tid, HANDLE thread)
|
|
|
|
{
|
|
|
|
BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
|
|
|
|
ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
|
|
|
|
/* be careful of races - don't return until hosting thread has terminated */
|
|
|
|
ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
|
|
|
|
CloseHandle(thread);
|
|
|
|
}
|
|
|
|
|
2007-11-29 12:54:54 +00:00
|
|
|
static const char cf_marshaled[] =
|
|
|
|
{
|
|
|
|
0x9, 0x0, 0x0, 0x0,
|
|
|
|
0x0, 0x0, 0x0, 0x0,
|
|
|
|
0x9, 0x0, 0x0, 0x0,
|
|
|
|
'M', 0x0, 'y', 0x0,
|
|
|
|
'F', 0x0, 'o', 0x0,
|
|
|
|
'r', 0x0, 'm', 0x0,
|
|
|
|
'a', 0x0, 't', 0x0,
|
|
|
|
0x0, 0x0
|
|
|
|
};
|
|
|
|
|
|
|
|
static void test_marshal_CLIPFORMAT(void)
|
|
|
|
{
|
2009-05-17 07:05:22 +00:00
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
2007-11-29 12:54:54 +00:00
|
|
|
unsigned char *buffer;
|
2009-05-17 07:05:22 +00:00
|
|
|
ULONG i, size;
|
2007-11-29 12:54:54 +00:00
|
|
|
CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
|
|
|
|
CLIPFORMAT cf2;
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = CLIPFORMAT_UserSize(&umcb.Flags, 0, &cf);
|
|
|
|
ok(size == 8 + sizeof(cf_marshaled) ||
|
|
|
|
broken(size == 12 + sizeof(cf_marshaled)) || /* win64 adds 4 extra (unused) bytes */
|
|
|
|
broken(size == 8 + sizeof(cf_marshaled) - 2), /* win9x and winnt don't include the '\0' */
|
|
|
|
"CLIPFORMAT: Wrong size %d\n", size);
|
2007-11-29 12:54:54 +00:00
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
memset( buffer, 0xcc, size );
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
CLIPFORMAT_UserMarshal(&umcb.Flags, buffer, &cf);
|
|
|
|
ok(*(LONG *)(buffer + 0) == WDT_REMOTE_CALL, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(LONG *)(buffer + 0));
|
|
|
|
ok(*(DWORD *)(buffer + 4) == cf, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04x\n", cf, *(DWORD *)(buffer + 4));
|
|
|
|
ok(!memcmp(buffer + 8, cf_marshaled, min( sizeof(cf_marshaled), size-8 )), "Marshaled data differs\n");
|
|
|
|
if (size > sizeof(cf_marshaled) + 8) /* make sure the extra bytes are not used */
|
|
|
|
for (i = sizeof(cf_marshaled) + 8; i < size; i++)
|
|
|
|
ok( buffer[i] == 0xcc, "buffer offset %u has been set to %x\n", i, buffer[i] );
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
CLIPFORMAT_UserUnmarshal(&umcb.Flags, buffer, &cf2);
|
|
|
|
ok(cf == cf2, "CLIPFORMAT: Didn't unmarshal properly\n");
|
2007-11-29 12:54:54 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
CLIPFORMAT_UserFree(&umcb.Flags, &cf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_marshal_HWND(void)
|
|
|
|
{
|
2009-05-17 07:05:22 +00:00
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
2007-11-29 12:54:54 +00:00
|
|
|
unsigned char *buffer;
|
|
|
|
ULONG size;
|
|
|
|
HWND hwnd = GetDesktopWindow();
|
|
|
|
HWND hwnd2;
|
|
|
|
wireHWND wirehwnd;
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = HWND_UserSize(&umcb.Flags, 0, &hwnd);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(size == sizeof(*wirehwnd), "Wrong size %d\n", size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HWND_UserMarshal(&umcb.Flags, buffer, &hwnd);
|
2007-11-29 12:54:54 +00:00
|
|
|
wirehwnd = (wireHWND)buffer;
|
2009-05-17 07:05:22 +00:00
|
|
|
ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehwnd->fContext);
|
2010-03-10 21:52:40 +00:00
|
|
|
ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %x\n", hwnd, wirehwnd->u.hRemote);
|
2007-11-29 12:54:54 +00:00
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HWND_UserUnmarshal(&umcb.Flags, buffer, &hwnd2);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
HWND_UserFree(&umcb.Flags, &hwnd2);
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_marshal_HGLOBAL(void)
|
|
|
|
{
|
2009-05-17 07:05:22 +00:00
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
2007-11-29 12:54:54 +00:00
|
|
|
unsigned char *buffer;
|
2010-03-10 21:52:40 +00:00
|
|
|
ULONG size, block_size;
|
2007-11-29 12:54:54 +00:00
|
|
|
HGLOBAL hglobal;
|
|
|
|
HGLOBAL hglobal2;
|
|
|
|
unsigned char *wirehglobal;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
hglobal = NULL;
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
|
|
|
|
/* native is poorly programmed and allocates 4/8 bytes more than it needs to
|
2007-11-29 12:54:54 +00:00
|
|
|
* here - Wine doesn't have to emulate that */
|
2009-05-17 07:05:22 +00:00
|
|
|
ok((size == 8) || broken(size == 12) || broken(size == 16), "Size should be 8, instead of %d\n", size);
|
2007-11-29 12:54:54 +00:00
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
|
2007-11-29 12:54:54 +00:00
|
|
|
wirehglobal = buffer;
|
|
|
|
ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
|
|
|
|
wirehglobal += sizeof(ULONG);
|
2009-05-17 07:05:22 +00:00
|
|
|
ok(*(ULONG *)wirehglobal == 0, "buffer+4 should be HGLOBAL\n");
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
2012-05-17 15:17:09 +00:00
|
|
|
hglobal2 = NULL;
|
2009-05-17 07:05:22 +00:00
|
|
|
HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
|
2007-11-29 12:54:54 +00:00
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
for(block_size = 0; block_size <= 17; block_size++)
|
|
|
|
{
|
|
|
|
ULONG actual_size, expected_size;
|
|
|
|
|
|
|
|
hglobal = GlobalAlloc(0, block_size);
|
|
|
|
buffer = GlobalLock(hglobal);
|
|
|
|
for (i = 0; i < block_size; i++)
|
|
|
|
buffer[i] = i;
|
|
|
|
GlobalUnlock(hglobal);
|
|
|
|
actual_size = GlobalSize(hglobal);
|
|
|
|
expected_size = actual_size + 5 * sizeof(DWORD);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
|
|
|
|
/* native is poorly programmed and allocates 4/8 bytes more than it needs to
|
|
|
|
* here - Wine doesn't have to emulate that */
|
|
|
|
ok(size == expected_size ||
|
|
|
|
broken(size == expected_size + 4) ||
|
|
|
|
broken(size == expected_size + 8),
|
|
|
|
"%d: got size %d\n", block_size, size);
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
|
|
|
|
wirehglobal = buffer;
|
|
|
|
ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
|
|
|
|
wirehglobal += sizeof(ULONG);
|
|
|
|
ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0x4 should be HGLOBAL\n");
|
|
|
|
wirehglobal += sizeof(ULONG);
|
|
|
|
ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x8 %08x\n", block_size, *(ULONG *)wirehglobal);
|
|
|
|
wirehglobal += sizeof(ULONG);
|
|
|
|
ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0xc should be HGLOBAL\n");
|
|
|
|
wirehglobal += sizeof(ULONG);
|
|
|
|
ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x10 %08x\n", block_size, *(ULONG *)wirehglobal);
|
|
|
|
wirehglobal += sizeof(ULONG);
|
|
|
|
for (i = 0; i < block_size; i++)
|
|
|
|
ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
2012-05-17 15:17:09 +00:00
|
|
|
hglobal2 = NULL;
|
2010-03-10 21:52:40 +00:00
|
|
|
HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
|
|
|
|
ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
|
|
|
|
GlobalFree(hglobal);
|
|
|
|
}
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HENHMETAFILE create_emf(void)
|
|
|
|
{
|
2009-01-04 17:52:22 +00:00
|
|
|
const RECT rect = {0, 0, 100, 100};
|
2014-04-24 12:14:32 +00:00
|
|
|
HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
|
|
|
|
ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
|
2007-11-29 12:54:54 +00:00
|
|
|
return CloseEnhMetaFile(hdc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_marshal_HENHMETAFILE(void)
|
|
|
|
{
|
2009-05-17 07:05:22 +00:00
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
2007-11-29 12:54:54 +00:00
|
|
|
unsigned char *buffer;
|
|
|
|
ULONG size;
|
|
|
|
HENHMETAFILE hemf;
|
|
|
|
HENHMETAFILE hemf2 = NULL;
|
|
|
|
unsigned char *wirehemf;
|
|
|
|
|
|
|
|
hemf = create_emf();
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = HENHMETAFILE_UserSize(&umcb.Flags, 0, &hemf);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HENHMETAFILE_UserMarshal(&umcb.Flags, buffer, &hemf);
|
2007-11-29 12:54:54 +00:00
|
|
|
wirehemf = buffer;
|
|
|
|
ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
|
|
|
|
wirehemf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
|
|
|
|
wirehemf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
|
|
|
|
wirehemf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
|
|
|
|
wirehemf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf);
|
|
|
|
/* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
|
|
|
|
* at this point */
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hemf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
DeleteEnhMetaFile(hemf);
|
|
|
|
|
|
|
|
/* test NULL emf */
|
|
|
|
hemf = NULL;
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = HENHMETAFILE_UserSize(&umcb.Flags, 0, &hemf);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(size == 8, "size should be 8 bytes, not %d\n", size);
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HENHMETAFILE_UserMarshal(&umcb.Flags, buffer, &hemf);
|
2007-11-29 12:54:54 +00:00
|
|
|
wirehemf = buffer;
|
|
|
|
ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
|
|
|
|
wirehemf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hemf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HMETAFILE create_mf(void)
|
|
|
|
{
|
|
|
|
RECT rect = {0, 0, 100, 100};
|
2014-04-24 12:14:32 +00:00
|
|
|
HDC hdc = CreateMetaFileA(NULL);
|
|
|
|
ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
|
2007-11-29 12:54:54 +00:00
|
|
|
return CloseMetaFile(hdc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_marshal_HMETAFILE(void)
|
|
|
|
{
|
2009-05-17 07:05:22 +00:00
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
2007-11-29 12:54:54 +00:00
|
|
|
unsigned char *buffer;
|
|
|
|
ULONG size;
|
|
|
|
HMETAFILE hmf;
|
|
|
|
HMETAFILE hmf2 = NULL;
|
|
|
|
unsigned char *wirehmf;
|
|
|
|
|
|
|
|
hmf = create_mf();
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
|
2007-11-29 12:54:54 +00:00
|
|
|
wirehmf = buffer;
|
|
|
|
ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
|
|
|
|
wirehmf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
|
|
|
|
wirehmf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
|
|
|
|
wirehmf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
|
|
|
|
wirehmf += sizeof(DWORD);
|
|
|
|
ok(*(WORD *)wirehmf == 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmf);
|
|
|
|
wirehmf += sizeof(DWORD);
|
|
|
|
/* ... rest of data not tested - refer to tests for GetMetaFileBits
|
|
|
|
* at this point */
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(hmf2 != NULL, "HMETAFILE didn't unmarshal\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
2009-05-17 07:05:22 +00:00
|
|
|
HMETAFILE_UserFree(&umcb.Flags, &hmf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
DeleteMetaFile(hmf);
|
|
|
|
|
|
|
|
/* test NULL emf */
|
|
|
|
hmf = NULL;
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(size == 8, "size should be 8 bytes, not %d\n", size);
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
|
2007-11-29 12:54:54 +00:00
|
|
|
wirehmf = buffer;
|
|
|
|
ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
|
|
|
|
wirehmf += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
|
|
|
|
wirehmf += sizeof(DWORD);
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(hmf2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
2009-05-17 07:05:22 +00:00
|
|
|
HMETAFILE_UserFree(&umcb.Flags, &hmf2);
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define USER_MARSHAL_PTR_PREFIX \
|
|
|
|
( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
|
|
|
|
( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
|
|
|
|
|
|
|
|
static void test_marshal_HMETAFILEPICT(void)
|
|
|
|
{
|
2009-05-17 07:05:22 +00:00
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
2007-11-29 12:54:54 +00:00
|
|
|
unsigned char *buffer, *buffer_end;
|
|
|
|
ULONG size;
|
|
|
|
HMETAFILEPICT hmfp;
|
|
|
|
HMETAFILEPICT hmfp2 = NULL;
|
|
|
|
METAFILEPICT *pmfp;
|
|
|
|
unsigned char *wirehmfp;
|
|
|
|
|
|
|
|
hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(*pmfp));
|
|
|
|
pmfp = GlobalLock(hmfp);
|
|
|
|
pmfp->mm = MM_ISOTROPIC;
|
|
|
|
pmfp->xExt = 1;
|
|
|
|
pmfp->yExt = 2;
|
|
|
|
pmfp->hMF = create_mf();
|
|
|
|
GlobalUnlock(hmfp);
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp);
|
2007-11-29 12:54:54 +00:00
|
|
|
wirehmfp = buffer;
|
|
|
|
ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmfp == MM_ISOTROPIC, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmfp == 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmfp == 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmfp == USER_MARSHAL_PTR_PREFIX, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
pmfp = GlobalLock(hmfp);
|
|
|
|
ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)pmfp->hMF, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
GlobalUnlock(hmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
/* Note use (buffer_end - buffer) instead of size here, because size is an
|
|
|
|
* overestimate with native */
|
|
|
|
ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(WORD *)wirehmfp == 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
/* ... rest of data not tested - refer to tests for GetMetaFileBits
|
|
|
|
* at this point */
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer, &hmfp2);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(hmfp2 != NULL, "HMETAFILEPICT didn't unmarshal\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
|
2007-11-29 12:54:54 +00:00
|
|
|
pmfp = GlobalLock(hmfp);
|
|
|
|
DeleteMetaFile(pmfp->hMF);
|
|
|
|
GlobalUnlock(hmfp);
|
|
|
|
GlobalFree(hmfp);
|
|
|
|
|
|
|
|
/* test NULL emf */
|
|
|
|
hmfp = NULL;
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(size == 8, "size should be 8 bytes, not %d\n", size);
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp);
|
2007-11-29 12:54:54 +00:00
|
|
|
wirehmfp = buffer;
|
|
|
|
ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
|
|
|
|
wirehmfp += sizeof(DWORD);
|
|
|
|
|
|
|
|
hmfp2 = NULL;
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer, &hmfp2);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(hmfp2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
2015-07-19 23:12:15 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
IUnknown IUnknown_iface;
|
|
|
|
LONG refs;
|
|
|
|
} TestUnknown;
|
|
|
|
|
|
|
|
static inline TestUnknown *impl_from_IUnknown(IUnknown *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, TestUnknown, IUnknown_iface);
|
|
|
|
}
|
|
|
|
|
2007-11-29 12:54:54 +00:00
|
|
|
static HRESULT WINAPI Test_IUnknown_QueryInterface(
|
|
|
|
LPUNKNOWN iface,
|
|
|
|
REFIID riid,
|
|
|
|
LPVOID *ppvObj)
|
|
|
|
{
|
|
|
|
if (ppvObj == NULL) return E_POINTER;
|
|
|
|
|
|
|
|
if (IsEqualGUID(riid, &IID_IUnknown))
|
|
|
|
{
|
2009-02-08 08:56:01 +00:00
|
|
|
*ppvObj = iface;
|
2007-11-29 12:54:54 +00:00
|
|
|
IUnknown_AddRef(iface);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ppvObj = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
|
|
|
|
{
|
2015-07-19 23:12:15 +00:00
|
|
|
TestUnknown *This = impl_from_IUnknown(iface);
|
|
|
|
return InterlockedIncrement(&This->refs);
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
|
|
|
|
{
|
2015-07-19 23:12:15 +00:00
|
|
|
TestUnknown *This = impl_from_IUnknown(iface);
|
|
|
|
return InterlockedDecrement(&This->refs);
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const IUnknownVtbl TestUnknown_Vtbl =
|
|
|
|
{
|
|
|
|
Test_IUnknown_QueryInterface,
|
|
|
|
Test_IUnknown_AddRef,
|
|
|
|
Test_IUnknown_Release,
|
|
|
|
};
|
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
struct test_stream
|
|
|
|
{
|
|
|
|
IStream IStream_iface;
|
|
|
|
LONG refs;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline struct test_stream *impl_from_IStream(IStream *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, struct test_stream, IStream_iface);
|
|
|
|
}
|
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
static HRESULT WINAPI Test_IStream_QueryInterface(IStream *iface,
|
|
|
|
REFIID riid, LPVOID *ppvObj)
|
|
|
|
{
|
|
|
|
if (ppvObj == NULL) return E_POINTER;
|
|
|
|
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown) ||
|
|
|
|
IsEqualIID(riid, &IID_IStream))
|
|
|
|
{
|
|
|
|
*ppvObj = iface;
|
|
|
|
IStream_AddRef(iface);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ppvObj = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI Test_IStream_AddRef(IStream *iface)
|
|
|
|
{
|
2015-11-17 10:31:59 +00:00
|
|
|
struct test_stream *This = impl_from_IStream(iface);
|
|
|
|
return InterlockedIncrement(&This->refs);
|
2010-03-10 21:52:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI Test_IStream_Release(IStream *iface)
|
|
|
|
{
|
2015-11-17 10:31:59 +00:00
|
|
|
struct test_stream *This = impl_from_IStream(iface);
|
|
|
|
return InterlockedDecrement(&This->refs);
|
2010-03-10 21:52:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const IStreamVtbl TestStream_Vtbl =
|
|
|
|
{
|
|
|
|
Test_IStream_QueryInterface,
|
|
|
|
Test_IStream_AddRef,
|
|
|
|
Test_IStream_Release
|
|
|
|
/* the rest can be NULLs */
|
|
|
|
};
|
|
|
|
|
2015-07-19 23:12:15 +00:00
|
|
|
static TestUnknown Test_Unknown = { {&TestUnknown_Vtbl}, 1 };
|
2015-11-17 10:31:59 +00:00
|
|
|
static TestUnknown Test_Unknown2 = { {&TestUnknown_Vtbl}, 1 };
|
|
|
|
static struct test_stream Test_Stream = { {&TestStream_Vtbl}, 1 };
|
|
|
|
static struct test_stream Test_Stream2 = { {&TestStream_Vtbl}, 1 };
|
2007-11-29 12:54:54 +00:00
|
|
|
|
|
|
|
ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *, REFIID);
|
|
|
|
unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG *, ULONG, unsigned char *, IUnknown *, REFIID);
|
|
|
|
unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG *, unsigned char *, IUnknown **, REFIID);
|
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx, BOOL client, BOOL in, BOOL out)
|
2007-11-29 12:54:54 +00:00
|
|
|
{
|
2009-05-17 07:05:22 +00:00
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
2007-11-29 12:54:54 +00:00
|
|
|
unsigned char *buffer, *buffer_end;
|
|
|
|
ULONG size;
|
|
|
|
IUnknown *unk;
|
|
|
|
IUnknown *unk2;
|
|
|
|
unsigned char *wireip;
|
2010-03-10 21:52:40 +00:00
|
|
|
HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
|
|
|
|
IStream *stm;
|
|
|
|
void *marshal_data;
|
|
|
|
LARGE_INTEGER zero;
|
|
|
|
ULARGE_INTEGER pos;
|
|
|
|
DWORD marshal_size;
|
2007-11-29 12:54:54 +00:00
|
|
|
|
|
|
|
/* shows that the WdtpInterfacePointer functions don't marshal anything for
|
|
|
|
* NULL pointers, so code using these functions must handle that case
|
|
|
|
* itself */
|
2010-03-10 21:52:40 +00:00
|
|
|
|
2007-11-29 12:54:54 +00:00
|
|
|
unk = NULL;
|
2010-03-10 21:52:40 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx);
|
|
|
|
size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown);
|
2007-11-29 12:54:54 +00:00
|
|
|
ok(size == 0, "size should be 0 bytes, not %d\n", size);
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2010-03-10 21:52:40 +00:00
|
|
|
buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown);
|
2015-03-09 19:58:31 +00:00
|
|
|
ok(buffer_end == buffer, "buffer_end %p buffer %p\n", buffer_end, buffer);
|
2007-11-29 12:54:54 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
/* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then
|
|
|
|
the result of CoMarshalInterface called with the LOWORD of the ctx */
|
|
|
|
|
2015-07-19 23:12:15 +00:00
|
|
|
unk = &Test_Unknown.IUnknown_iface;
|
|
|
|
Test_Unknown.refs = 1;
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
CreateStreamOnHGlobal(h, TRUE, &stm);
|
|
|
|
CoMarshalInterface(stm, &IID_IUnknown, unk, LOWORD(ctx), NULL, MSHLFLAGS_NORMAL);
|
|
|
|
zero.QuadPart = 0;
|
|
|
|
IStream_Seek(stm, zero, STREAM_SEEK_CUR, &pos);
|
|
|
|
marshal_size = pos.u.LowPart;
|
|
|
|
marshal_data = GlobalLock(h);
|
2015-07-19 23:12:15 +00:00
|
|
|
todo_wine
|
|
|
|
ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs);
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx);
|
|
|
|
size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown);
|
|
|
|
ok(size >= marshal_size + 2 * sizeof(DWORD), "marshal size %x got %x\n", marshal_size, size);
|
2007-11-29 12:54:54 +00:00
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
2010-03-10 21:52:40 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx);
|
|
|
|
buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown);
|
2015-07-19 23:12:15 +00:00
|
|
|
todo_wine
|
|
|
|
ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs);
|
2007-11-29 12:54:54 +00:00
|
|
|
wireip = buffer;
|
2010-03-10 21:52:40 +00:00
|
|
|
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
ok(buffer_end == buffer + marshal_size + 2 * sizeof(DWORD), "buffer_end %p buffer %p\n", buffer_end, buffer);
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
ok(*(DWORD *)wireip == marshal_size, "wireip + 0x0 should be %x instead of %x\n", marshal_size, *(DWORD *)wireip);
|
|
|
|
wireip += sizeof(DWORD);
|
|
|
|
ok(*(DWORD *)wireip == marshal_size, "wireip + 0x4 should be %x instead of %x\n", marshal_size, *(DWORD *)wireip);
|
|
|
|
wireip += sizeof(DWORD);
|
|
|
|
|
|
|
|
ok(!memcmp(marshal_data, wireip, marshal_size), "buffer mismatch\n");
|
|
|
|
GlobalUnlock(h);
|
|
|
|
zero.QuadPart = 0;
|
|
|
|
IStream_Seek(stm, zero, STREAM_SEEK_SET, NULL);
|
|
|
|
CoReleaseMarshalData(stm);
|
|
|
|
IStream_Release(stm);
|
2007-11-29 12:54:54 +00:00
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
Test_Unknown2.refs = 1;
|
|
|
|
unk2 = &Test_Unknown2.IUnknown_iface;
|
2010-03-10 21:52:40 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx);
|
2015-11-17 10:31:59 +00:00
|
|
|
umcb.pStubMsg->IsClient = client;
|
|
|
|
umcb.pStubMsg->fIsIn = in;
|
|
|
|
umcb.pStubMsg->fIsOut = out;
|
|
|
|
|
2007-11-29 12:54:54 +00:00
|
|
|
WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown);
|
|
|
|
ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n");
|
2015-07-19 23:12:15 +00:00
|
|
|
ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs);
|
2015-11-17 10:31:59 +00:00
|
|
|
ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
|
2007-11-29 12:54:54 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
2009-05-17 07:05:22 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
|
2012-12-12 21:02:09 +00:00
|
|
|
IUnknown_Release(unk2);
|
2007-11-29 12:54:54 +00:00
|
|
|
}
|
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
static void test_marshal_WdtpInterfacePointer(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* There are two places where we can pass the marshalling ctx: as
|
|
|
|
* part of the umcb and as a separate flag. The loword of that
|
|
|
|
* separate flag field is what matters.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* All three are marshalled as inproc */
|
2015-11-17 10:31:59 +00:00
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_INPROC, 0,0,0);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_INPROC,0,0,0);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_INPROC, 0xffff),0,0,0);
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
/* All three are marshalled as remote */
|
2015-11-17 10:31:59 +00:00
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,0);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_DIFFERENTMACHINE,0,0,0);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_DIFFERENTMACHINE, 0xffff),0,0,0);
|
|
|
|
|
|
|
|
/* Test different combinations of client, in and out */
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,1);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,0);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,1);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,0);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,1);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,0);
|
|
|
|
marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,1);
|
2010-03-10 21:52:40 +00:00
|
|
|
}
|
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
static void marshal_STGMEDIUM(BOOL client, BOOL in, BOOL out)
|
2010-03-10 21:52:40 +00:00
|
|
|
{
|
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
|
|
|
unsigned char *buffer, *buffer_end, *expect_buffer, *expect_buffer_end;
|
|
|
|
ULONG size, expect_size;
|
|
|
|
STGMEDIUM med, med2;
|
2015-07-19 23:12:15 +00:00
|
|
|
IUnknown *unk = &Test_Unknown.IUnknown_iface;
|
2015-11-17 10:31:59 +00:00
|
|
|
IStream *stm = &Test_Stream.IStream_iface;
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
/* TYMED_NULL with pUnkForRelease */
|
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
Test_Unknown.refs = 1;
|
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 2 * sizeof(DWORD), unk, &IID_IUnknown);
|
|
|
|
expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size);
|
2015-11-17 10:31:59 +00:00
|
|
|
*(DWORD*)expect_buffer = TYMED_NULL;
|
|
|
|
*((DWORD*)expect_buffer + 1) = 0xdeadbeef;
|
2010-03-10 21:52:40 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer + 2 * sizeof(DWORD), unk, &IID_IUnknown);
|
|
|
|
|
|
|
|
med.tymed = TYMED_NULL;
|
|
|
|
U(med).pstg = NULL;
|
|
|
|
med.pUnkForRelease = unk;
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
|
|
|
|
ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
|
|
|
|
ok(buffer_end - buffer == expect_buffer_end - expect_buffer, "buffer size mismatch\n");
|
|
|
|
ok(*(DWORD*)buffer == TYMED_NULL, "got %08x\n", *(DWORD*)buffer);
|
|
|
|
ok(*((DWORD*)buffer+1) != 0, "got %08x\n", *((DWORD*)buffer+1));
|
|
|
|
ok(!memcmp(buffer+8, expect_buffer + 8, expect_buffer_end - expect_buffer - 8), "buffer mismatch\n");
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
2015-11-17 10:31:59 +00:00
|
|
|
umcb.pStubMsg->IsClient = client;
|
|
|
|
umcb.pStubMsg->fIsIn = in;
|
|
|
|
umcb.pStubMsg->fIsOut = out;
|
2010-03-10 21:52:40 +00:00
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
Test_Unknown2.refs = 1;
|
2010-03-10 21:52:40 +00:00
|
|
|
med2.tymed = TYMED_NULL;
|
|
|
|
U(med2).pstm = NULL;
|
2015-11-17 10:31:59 +00:00
|
|
|
med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
|
|
|
|
|
|
|
|
ok(med2.tymed == TYMED_NULL, "got tymed %x\n", med2.tymed);
|
|
|
|
ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
|
2015-11-17 10:31:59 +00:00
|
|
|
ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
STGMEDIUM_UserFree(&umcb.Flags, &med2);
|
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
med2.tymed = TYMED_NULL;
|
|
|
|
U(med2).pstm = NULL;
|
|
|
|
med2.pUnkForRelease = NULL;
|
|
|
|
STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
STGMEDIUM_UserFree(&umcb.Flags, &med2);
|
|
|
|
|
|
|
|
ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs);
|
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, expect_buffer);
|
|
|
|
|
|
|
|
/* TYMED_ISTREAM with pUnkForRelease */
|
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
Test_Unknown.refs = 1;
|
|
|
|
Test_Stream.refs = 1;
|
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream);
|
|
|
|
expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, expect_size, unk, &IID_IUnknown);
|
|
|
|
|
|
|
|
expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size);
|
|
|
|
/* There may be a hole between the two interfaces so init the buffer to something */
|
|
|
|
memset(expect_buffer, 0xcc, expect_size);
|
2015-11-17 10:31:59 +00:00
|
|
|
*(DWORD*)expect_buffer = TYMED_ISTREAM;
|
|
|
|
*((DWORD*)expect_buffer + 1) = 0xdeadbeef;
|
|
|
|
*((DWORD*)expect_buffer + 2) = 0xcafe;
|
2010-03-10 21:52:40 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer + 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream);
|
|
|
|
expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer_end, unk, &IID_IUnknown);
|
|
|
|
|
|
|
|
med.tymed = TYMED_ISTREAM;
|
|
|
|
U(med).pstm = stm;
|
|
|
|
med.pUnkForRelease = unk;
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
|
|
|
|
ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
memset(buffer, 0xcc, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
|
|
|
|
ok(buffer_end - buffer == expect_buffer_end - expect_buffer, "buffer size mismatch\n");
|
|
|
|
ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08x\n", *(DWORD*)buffer);
|
|
|
|
ok(*((DWORD*)buffer+1) != 0, "got %08x\n", *((DWORD*)buffer+1));
|
|
|
|
ok(*((DWORD*)buffer+2) != 0, "got %08x\n", *((DWORD*)buffer+2));
|
|
|
|
ok(!memcmp(buffer + 12, expect_buffer + 12, (buffer_end - buffer) - 12), "buffer mismatch\n");
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
2015-11-17 10:31:59 +00:00
|
|
|
umcb.pStubMsg->IsClient = client;
|
|
|
|
umcb.pStubMsg->fIsIn = in;
|
|
|
|
umcb.pStubMsg->fIsOut = out;
|
2010-03-10 21:52:40 +00:00
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
Test_Stream2.refs = 1;
|
|
|
|
Test_Unknown2.refs = 1;
|
|
|
|
med2.tymed = TYMED_ISTREAM;
|
|
|
|
U(med2).pstm = &Test_Stream2.IStream_iface;
|
|
|
|
med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
|
|
|
|
|
|
|
|
ok(med2.tymed == TYMED_ISTREAM, "got tymed %x\n", med2.tymed);
|
|
|
|
ok(U(med2).pstm != NULL, "Incorrectly unmarshalled\n");
|
|
|
|
ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
|
2015-11-17 10:31:59 +00:00
|
|
|
ok(Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs);
|
|
|
|
ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
|
2010-03-10 21:52:40 +00:00
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
STGMEDIUM_UserFree(&umcb.Flags, &med2);
|
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
med2.tymed = TYMED_NULL;
|
|
|
|
U(med2).pstm = NULL;
|
|
|
|
med2.pUnkForRelease = NULL;
|
|
|
|
STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
STGMEDIUM_UserFree(&umcb.Flags, &med2);
|
|
|
|
|
|
|
|
ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs);
|
|
|
|
ok(Test_Stream.refs == 1, "got %d\n", Test_Stream.refs);
|
|
|
|
|
2010-03-10 21:52:40 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, expect_buffer);
|
2015-11-17 10:31:59 +00:00
|
|
|
|
|
|
|
/* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
expect_size = 3 * sizeof(DWORD);
|
|
|
|
|
|
|
|
med.tymed = TYMED_ISTREAM;
|
|
|
|
U(med).pstm = NULL;
|
|
|
|
med.pUnkForRelease = NULL;
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
|
|
|
|
ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
memset(buffer, 0xcc, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
|
|
|
|
ok(buffer_end - buffer == expect_size, "buffer size mismatch\n");
|
|
|
|
ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08x\n", *(DWORD*)buffer);
|
|
|
|
ok(*((DWORD*)buffer+1) == 0, "got %08x\n", *((DWORD*)buffer+1));
|
|
|
|
ok(*((DWORD*)buffer+2) == 0, "got %08x\n", *((DWORD*)buffer+2));
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
umcb.pStubMsg->IsClient = client;
|
|
|
|
umcb.pStubMsg->fIsIn = in;
|
|
|
|
umcb.pStubMsg->fIsOut = out;
|
|
|
|
|
|
|
|
Test_Stream2.refs = 1;
|
|
|
|
Test_Unknown2.refs = 1;
|
|
|
|
med2.tymed = TYMED_ISTREAM;
|
|
|
|
U(med2).pstm = &Test_Stream2.IStream_iface;
|
|
|
|
med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
|
|
|
|
|
|
|
|
STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
|
|
|
|
|
|
|
|
ok(med2.tymed == TYMED_ISTREAM, "got tymed %x\n", med2.tymed);
|
|
|
|
ok(U(med2).pstm == NULL, "Incorrectly unmarshalled\n");
|
|
|
|
ok(med2.pUnkForRelease == &Test_Unknown2.IUnknown_iface, "Incorrectly unmarshalled\n");
|
|
|
|
ok(Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs);
|
|
|
|
ok(Test_Unknown2.refs == 1, "got %d\n", Test_Unknown2.refs);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
|
|
|
STGMEDIUM_UserFree(&umcb.Flags, &med2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_marshal_STGMEDIUM(void)
|
|
|
|
{
|
|
|
|
marshal_STGMEDIUM(0, 0, 0);
|
|
|
|
marshal_STGMEDIUM(0, 0, 1);
|
|
|
|
marshal_STGMEDIUM(0, 1, 0);
|
|
|
|
marshal_STGMEDIUM(0, 1, 1);
|
|
|
|
/* For Windows versions post 2003, client side, non-[in,out] STGMEDIUMs get zero-initialised.
|
|
|
|
However since inline stubs don't set fIsIn or fIsOut this behaviour would break
|
|
|
|
ref counting in GetDataHere_Proxy for example, as we'd end up not releasing the original
|
|
|
|
interface. For simplicity we don't test or implement this. */
|
|
|
|
marshal_STGMEDIUM(1, 1, 1);
|
2010-03-10 21:52:40 +00:00
|
|
|
}
|
|
|
|
|
2015-07-19 23:12:15 +00:00
|
|
|
static void test_marshal_SNB(void)
|
|
|
|
{
|
|
|
|
static const WCHAR str1W[] = {'s','t','r','i','n','g','1',0};
|
|
|
|
static const WCHAR str2W[] = {'s','t','r','2',0};
|
|
|
|
unsigned char *buffer, *src, *mbuf;
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
WCHAR **ptrW, *dataW;
|
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
|
|
|
RemSNB *wiresnb;
|
|
|
|
SNB snb, snb2;
|
|
|
|
ULONG size;
|
|
|
|
|
|
|
|
/* 4 bytes alignment */
|
|
|
|
snb = NULL;
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = SNB_UserSize(&umcb.Flags, 3, &snb);
|
|
|
|
ok(size == 16, "Size should be 16, instead of %d\n", size);
|
|
|
|
|
|
|
|
/* NULL block */
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = SNB_UserSize(&umcb.Flags, 0, &snb);
|
|
|
|
ok(size == 12, "Size should be 12, instead of %d\n", size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
mbuf = SNB_UserMarshal(&umcb.Flags, buffer, &snb);
|
|
|
|
ok(mbuf == buffer + size, "got %p, %p\n", mbuf, buffer + size);
|
|
|
|
|
|
|
|
wiresnb = (RemSNB*)buffer;
|
|
|
|
ok(wiresnb->ulCntStr == 0, "got %u\n", wiresnb->ulCntStr);
|
|
|
|
ok(wiresnb->ulCntChar == 0, "got %u\n", wiresnb->ulCntChar);
|
|
|
|
ok(*(ULONG*)wiresnb->rgString == 0, "got %u\n", *(ULONG*)wiresnb->rgString);
|
|
|
|
|
|
|
|
snb2 = NULL;
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
|
|
|
|
ok(snb2 == NULL, "got %p\n", snb2);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
SNB_UserFree(&umcb.Flags, &snb2);
|
|
|
|
|
|
|
|
/* block with actual data */
|
|
|
|
|
|
|
|
/* allocate source block, n+1 pointers first, then data */
|
|
|
|
src = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR*)*3 + sizeof(str1W) + sizeof(str2W));
|
|
|
|
ptrW = (WCHAR**)src;
|
|
|
|
dataW = *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*));
|
|
|
|
ptrW++;
|
|
|
|
*ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*) + sizeof(str1W));
|
|
|
|
ptrW++;
|
|
|
|
*ptrW = NULL;
|
|
|
|
lstrcpyW(dataW, str1W);
|
|
|
|
dataW += lstrlenW(str1W) + 1;
|
|
|
|
lstrcpyW(dataW, str2W);
|
|
|
|
|
|
|
|
snb = (SNB)src;
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = SNB_UserSize(&umcb.Flags, 0, &snb);
|
|
|
|
ok(size == 38, "Size should be 38, instead of %d\n", size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
SNB_UserMarshal(&umcb.Flags, buffer, &snb);
|
|
|
|
|
|
|
|
wiresnb = (RemSNB*)buffer;
|
|
|
|
ok(wiresnb->ulCntStr == 13, "got %u\n", wiresnb->ulCntStr);
|
|
|
|
ok(wiresnb->ulCntChar == 2, "got %u\n", wiresnb->ulCntChar);
|
|
|
|
/* payload length is stored one more time, as ULONG */
|
|
|
|
ok(*(ULONG*)wiresnb->rgString == wiresnb->ulCntStr, "got %u\n", *(ULONG*)wiresnb->rgString);
|
|
|
|
dataW = &wiresnb->rgString[2];
|
|
|
|
ok(!lstrcmpW(dataW, str1W), "marshalled string 0: %s\n", wine_dbgstr_w(dataW));
|
|
|
|
dataW += sizeof(str1W)/sizeof(WCHAR);
|
|
|
|
ok(!lstrcmpW(dataW, str2W), "marshalled string 1: %s\n", wine_dbgstr_w(dataW));
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
|
|
|
|
g_expect_user_alloc = TRUE;
|
|
|
|
snb2 = NULL;
|
|
|
|
SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
|
|
|
|
g_expect_user_alloc = FALSE;
|
|
|
|
|
|
|
|
ptrW = snb2;
|
|
|
|
ok(!lstrcmpW(*ptrW, str1W), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW));
|
|
|
|
ptrW++;
|
|
|
|
ok(!lstrcmpW(*ptrW, str2W), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW));
|
|
|
|
ptrW++;
|
|
|
|
ok(*ptrW == NULL, "expected terminating NULL ptr, got %p, start %p\n", *ptrW, snb2);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
|
|
|
|
g_expect_user_free = TRUE;
|
|
|
|
SNB_UserFree(&umcb.Flags, &snb2);
|
|
|
|
g_expect_user_free = FALSE;
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, src);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_marshal_HDC(void)
|
|
|
|
{
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
HDC hdc = GetDC(0), hdc2;
|
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
|
|
|
unsigned char *buffer;
|
|
|
|
wireHDC wirehdc;
|
|
|
|
ULONG size;
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = HDC_UserSize(&umcb.Flags, 0, &hdc);
|
|
|
|
ok(size == sizeof(*wirehdc), "Wrong size %d\n", size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HDC_UserMarshal(&umcb.Flags, buffer, &hdc);
|
|
|
|
wirehdc = (wireHDC)buffer;
|
|
|
|
ok(wirehdc->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehdc->fContext);
|
|
|
|
ok(wirehdc->u.hInproc == (LONG_PTR)hdc, "Marshaled value should be %p instead of %x\n", hdc, wirehdc->u.hRemote);
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HDC_UserUnmarshal(&umcb.Flags, buffer, &hdc2);
|
|
|
|
ok(hdc == hdc2, "Didn't unmarshal properly\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
HDC_UserFree(&umcb.Flags, &hdc2);
|
|
|
|
ReleaseDC(0, hdc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_marshal_HICON(void)
|
|
|
|
{
|
|
|
|
static const BYTE bmp_bits[1024];
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
HICON hIcon, hIcon2;
|
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
|
|
|
unsigned char *buffer;
|
|
|
|
wireHICON wirehicon;
|
|
|
|
ULONG size;
|
|
|
|
|
|
|
|
hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
|
|
|
|
ok(hIcon != 0, "CreateIcon failed\n");
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = HICON_UserSize(&umcb.Flags, 0, &hIcon);
|
|
|
|
ok(size == sizeof(*wirehicon), "Wrong size %d\n", size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HICON_UserMarshal(&umcb.Flags, buffer, &hIcon);
|
|
|
|
wirehicon = (wireHICON)buffer;
|
|
|
|
ok(wirehicon->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehicon->fContext);
|
|
|
|
ok(wirehicon->u.hInproc == (LONG_PTR)hIcon, "Marshaled value should be %p instead of %x\n", hIcon, wirehicon->u.hRemote);
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HICON_UserUnmarshal(&umcb.Flags, buffer, &hIcon2);
|
|
|
|
ok(hIcon == hIcon2, "Didn't unmarshal properly\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
HICON_UserFree(&umcb.Flags, &hIcon2);
|
|
|
|
DestroyIcon(hIcon);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_marshal_HBRUSH(void)
|
|
|
|
{
|
|
|
|
MIDL_STUB_MESSAGE stub_msg;
|
|
|
|
HBRUSH hBrush, hBrush2;
|
|
|
|
USER_MARSHAL_CB umcb;
|
|
|
|
RPC_MESSAGE rpc_msg;
|
|
|
|
unsigned char *buffer;
|
|
|
|
LOGBRUSH logbrush;
|
|
|
|
wireHBRUSH wirehbrush;
|
|
|
|
ULONG size;
|
|
|
|
|
|
|
|
logbrush.lbStyle = BS_SOLID;
|
|
|
|
logbrush.lbColor = RGB(0, 0, 0);
|
|
|
|
logbrush.lbHatch = 0;
|
|
|
|
|
|
|
|
hBrush = CreateBrushIndirect(&logbrush);
|
|
|
|
ok(hBrush != 0, "CreateBrushIndirect failed\n");
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
size = HBRUSH_UserSize(&umcb.Flags, 0, &hBrush);
|
|
|
|
ok(size == sizeof(*wirehbrush), "Wrong size %d\n", size);
|
|
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HBRUSH_UserMarshal(&umcb.Flags, buffer, &hBrush);
|
|
|
|
wirehbrush = (wireHBRUSH)buffer;
|
|
|
|
ok(wirehbrush->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehbrush->fContext);
|
|
|
|
ok(wirehbrush->u.hInproc == (LONG_PTR)hBrush, "Marshaled value should be %p instead of %x\n", hBrush, wirehbrush->u.hRemote);
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
|
|
|
|
HBRUSH_UserUnmarshal(&umcb.Flags, buffer, &hBrush2);
|
|
|
|
ok(hBrush == hBrush2, "Didn't unmarshal properly\n");
|
|
|
|
HeapFree(GetProcessHeap(), 0, buffer);
|
|
|
|
|
|
|
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
|
|
|
|
HBRUSH_UserFree(&umcb.Flags, &hBrush2);
|
|
|
|
DeleteObject(hBrush);
|
|
|
|
}
|
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
struct obj
|
|
|
|
{
|
|
|
|
IDataObject IDataObject_iface;
|
|
|
|
};
|
|
|
|
|
|
|
|
static HRESULT WINAPI obj_QueryInterface(IDataObject *iface, REFIID iid, void **obj)
|
|
|
|
{
|
|
|
|
*obj = NULL;
|
|
|
|
|
|
|
|
if (IsEqualGUID(iid, &IID_IUnknown) ||
|
|
|
|
IsEqualGUID(iid, &IID_IDataObject))
|
|
|
|
*obj = iface;
|
|
|
|
|
|
|
|
if (*obj)
|
|
|
|
{
|
|
|
|
IDataObject_AddRef(iface);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI obj_AddRef(IDataObject *iface)
|
|
|
|
{
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI obj_Release(IDataObject *iface)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI obj_DO_GetDataHere(IDataObject *iface, FORMATETC *fmt,
|
|
|
|
STGMEDIUM *med)
|
|
|
|
{
|
|
|
|
ok( med->pUnkForRelease == NULL, "got %p\n", med->pUnkForRelease );
|
|
|
|
|
|
|
|
if (fmt->cfFormat == 2)
|
|
|
|
{
|
|
|
|
IStream_Release(U(med)->pstm);
|
|
|
|
U(med)->pstm = &Test_Stream2.IStream_iface;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const IDataObjectVtbl obj_data_object_vtbl =
|
|
|
|
{
|
|
|
|
obj_QueryInterface,
|
|
|
|
obj_AddRef,
|
|
|
|
obj_Release,
|
|
|
|
NULL, /* GetData */
|
|
|
|
obj_DO_GetDataHere,
|
|
|
|
NULL, /* QueryGetData */
|
|
|
|
NULL, /* GetCanonicalFormatEtc */
|
|
|
|
NULL, /* SetData */
|
|
|
|
NULL, /* EnumFormatEtc */
|
|
|
|
NULL, /* DAdvise */
|
|
|
|
NULL, /* DUnadvise */
|
|
|
|
NULL /* EnumDAdvise */
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct obj obj =
|
|
|
|
{
|
|
|
|
{&obj_data_object_vtbl}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void test_GetDataHere_Proxy(void)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
IStream *stm;
|
|
|
|
HANDLE thread;
|
|
|
|
DWORD tid;
|
|
|
|
static const LARGE_INTEGER zero;
|
|
|
|
IDataObject *data;
|
|
|
|
FORMATETC fmt;
|
|
|
|
STGMEDIUM med;
|
|
|
|
|
|
|
|
hr = CreateStreamOnHGlobal( NULL, TRUE, &stm );
|
|
|
|
ok( hr == S_OK, "got %08x\n", hr );
|
|
|
|
tid = start_host_object2( stm, &IID_IDataObject, (IUnknown *)&obj.IDataObject_iface, MSHLFLAGS_NORMAL, NULL, &thread );
|
|
|
|
|
|
|
|
IStream_Seek( stm, zero, STREAM_SEEK_SET, NULL );
|
|
|
|
hr = CoUnmarshalInterface( stm, &IID_IDataObject, (void **)&data );
|
|
|
|
ok( hr == S_OK, "got %08x\n", hr );
|
|
|
|
IStream_Release( stm );
|
|
|
|
|
|
|
|
Test_Stream.refs = 1;
|
|
|
|
Test_Stream2.refs = 1;
|
|
|
|
Test_Unknown.refs = 1;
|
|
|
|
|
|
|
|
fmt.cfFormat = 1;
|
|
|
|
fmt.ptd = NULL;
|
|
|
|
fmt.dwAspect = DVASPECT_CONTENT;
|
|
|
|
fmt.lindex = -1;
|
|
|
|
U(med).pstm = NULL;
|
|
|
|
med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
|
|
|
|
|
|
|
|
fmt.tymed = med.tymed = TYMED_NULL;
|
|
|
|
hr = IDataObject_GetDataHere( data, &fmt, &med );
|
|
|
|
ok( hr == DV_E_TYMED, "got %08x\n", hr );
|
|
|
|
|
|
|
|
for (fmt.tymed = TYMED_HGLOBAL; fmt.tymed <= TYMED_ENHMF; fmt.tymed <<= 1)
|
|
|
|
{
|
|
|
|
med.tymed = fmt.tymed;
|
|
|
|
hr = IDataObject_GetDataHere( data, &fmt, &med );
|
|
|
|
ok( hr == (fmt.tymed <= TYMED_ISTORAGE ? S_OK : DV_E_TYMED), "got %08x for tymed %d\n", hr, fmt.tymed );
|
|
|
|
ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.tymed = TYMED_ISTREAM;
|
|
|
|
med.tymed = TYMED_ISTORAGE;
|
|
|
|
hr = IDataObject_GetDataHere( data, &fmt, &med );
|
|
|
|
ok( hr == DV_E_TYMED, "got %08x\n", hr );
|
|
|
|
|
|
|
|
fmt.tymed = med.tymed = TYMED_ISTREAM;
|
|
|
|
U(med).pstm = &Test_Stream.IStream_iface;
|
|
|
|
med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
|
|
|
|
|
|
|
|
hr = IDataObject_GetDataHere( data, &fmt, &med );
|
|
|
|
ok( hr == S_OK, "got %08x\n", hr );
|
|
|
|
|
|
|
|
ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
|
|
|
|
ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" );
|
|
|
|
|
|
|
|
ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs );
|
|
|
|
ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
|
|
|
|
|
|
|
|
fmt.cfFormat = 2;
|
|
|
|
fmt.tymed = med.tymed = TYMED_ISTREAM;
|
|
|
|
U(med).pstm = &Test_Stream.IStream_iface;
|
|
|
|
med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
|
|
|
|
|
|
|
|
hr = IDataObject_GetDataHere( data, &fmt, &med );
|
|
|
|
ok( hr == S_OK, "got %08x\n", hr );
|
|
|
|
|
|
|
|
ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
|
|
|
|
ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" );
|
|
|
|
|
|
|
|
ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs );
|
|
|
|
ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
|
|
|
|
ok( Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs );
|
|
|
|
|
|
|
|
IDataObject_Release( data );
|
|
|
|
end_host_object( tid, thread );
|
|
|
|
}
|
|
|
|
|
2007-11-29 12:54:54 +00:00
|
|
|
START_TEST(usrmarshal)
|
|
|
|
{
|
2015-11-17 10:31:59 +00:00
|
|
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
2007-11-29 12:54:54 +00:00
|
|
|
|
|
|
|
test_marshal_CLIPFORMAT();
|
|
|
|
test_marshal_HWND();
|
|
|
|
test_marshal_HGLOBAL();
|
|
|
|
test_marshal_HENHMETAFILE();
|
|
|
|
test_marshal_HMETAFILE();
|
|
|
|
test_marshal_HMETAFILEPICT();
|
|
|
|
test_marshal_WdtpInterfacePointer();
|
2010-03-10 21:52:40 +00:00
|
|
|
test_marshal_STGMEDIUM();
|
2015-07-19 23:12:15 +00:00
|
|
|
test_marshal_SNB();
|
|
|
|
test_marshal_HDC();
|
|
|
|
test_marshal_HICON();
|
|
|
|
test_marshal_HBRUSH();
|
2007-11-29 12:54:54 +00:00
|
|
|
|
2015-11-17 10:31:59 +00:00
|
|
|
test_GetDataHere_Proxy();
|
|
|
|
|
2007-11-29 12:54:54 +00:00
|
|
|
CoUninitialize();
|
|
|
|
}
|