winevulkan: Merge body and body_conversion.
[wine.git] / dlls / ole32 / tests / usrmarshal.c
blob96cb0b4c669dee9370402d71b35ead1329ece60b
1 /*
2 * User Marshaling Tests
4 * Copyright 2004-2006 Robert Shearman for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #define CONST_VTABLE
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "objidl.h"
30 #include "wine/test.h"
32 ULONG __RPC_USER HMETAFILE_UserSize(ULONG *, ULONG, HMETAFILE *);
33 unsigned char * __RPC_USER HMETAFILE_UserMarshal(ULONG *, unsigned char *, HMETAFILE *);
34 unsigned char * __RPC_USER HMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HMETAFILE *);
35 void __RPC_USER HMETAFILE_UserFree(ULONG *, HMETAFILE *);
37 ULONG __RPC_USER HENHMETAFILE_UserSize(ULONG *, ULONG, HENHMETAFILE *);
38 unsigned char * __RPC_USER HENHMETAFILE_UserMarshal (ULONG *, unsigned char *, HENHMETAFILE *);
39 unsigned char * __RPC_USER HENHMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HENHMETAFILE *);
40 void __RPC_USER HENHMETAFILE_UserFree(ULONG *, HENHMETAFILE *);
42 ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *, ULONG, HMETAFILEPICT *);
43 unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal (ULONG *, unsigned char *, HMETAFILEPICT *);
44 unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *, unsigned char *, HMETAFILEPICT *);
45 void __RPC_USER HMETAFILEPICT_UserFree(ULONG *, HMETAFILEPICT *);
47 ULONG __RPC_USER HBRUSH_UserSize(ULONG *, ULONG, HBRUSH *);
48 unsigned char * __RPC_USER HBRUSH_UserMarshal(ULONG *, unsigned char *, HBRUSH *);
49 unsigned char * __RPC_USER HBRUSH_UserUnmarshal(ULONG *, unsigned char *, HBRUSH *);
50 void __RPC_USER HBRUSH_UserFree(ULONG *, HBRUSH *);
52 static BOOL g_expect_user_alloc;
53 static void * WINAPI user_allocate(SIZE_T size)
55 ok(g_expect_user_alloc, "unexpected user_allocate call\n");
56 return CoTaskMemAlloc(size);
59 static BOOL g_expect_user_free;
60 static void WINAPI user_free(void *p)
62 ok(g_expect_user_free, "unexpected user_free call\n");
63 CoTaskMemFree(p);
66 static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
67 PMIDL_STUB_MESSAGE stub_msg,
68 PRPC_MESSAGE rpc_msg, unsigned char *buffer,
69 unsigned int size, MSHCTX context)
71 memset(rpc_msg, 0, sizeof(*rpc_msg));
72 rpc_msg->Buffer = buffer;
73 rpc_msg->BufferLength = size;
75 memset(stub_msg, 0, sizeof(*stub_msg));
76 stub_msg->RpcMsg = rpc_msg;
77 stub_msg->Buffer = buffer;
78 stub_msg->pfnAllocate = user_allocate;
79 stub_msg->pfnFree = user_free;
81 memset(umcb, 0, sizeof(*umcb));
82 umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION);
83 umcb->pStubMsg = stub_msg;
84 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
85 umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
88 #define RELEASEMARSHALDATA WM_USER
90 struct host_object_data
92 IStream *stream;
93 IID iid;
94 IUnknown *object;
95 MSHLFLAGS marshal_flags;
96 HANDLE marshal_event;
97 IMessageFilter *filter;
100 static DWORD CALLBACK host_object_proc(LPVOID p)
102 struct host_object_data *data = p;
103 HRESULT hr;
104 MSG msg;
106 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
108 if (data->filter)
110 IMessageFilter * prev_filter = NULL;
111 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
112 if (prev_filter) IMessageFilter_Release(prev_filter);
113 ok(hr == S_OK, "got %08lx\n", hr);
116 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
117 ok(hr == S_OK, "got %08lx\n", hr);
119 /* force the message queue to be created before signaling parent thread */
120 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
122 SetEvent(data->marshal_event);
124 while (GetMessageA(&msg, NULL, 0, 0))
126 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
128 CoReleaseMarshalData(data->stream);
129 SetEvent((HANDLE)msg.lParam);
131 else
132 DispatchMessageA(&msg);
135 HeapFree(GetProcessHeap(), 0, data);
137 CoUninitialize();
139 return hr;
142 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
144 DWORD tid = 0;
145 HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
146 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
148 data->stream = stream;
149 data->iid = *riid;
150 data->object = object;
151 data->marshal_flags = marshal_flags;
152 data->marshal_event = marshal_event;
153 data->filter = filter;
155 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
157 /* wait for marshaling to complete before returning */
158 ok( !WaitForSingleObject(marshal_event, 10000), "wait timed out\n" );
159 CloseHandle(marshal_event);
161 return tid;
164 static void end_host_object(DWORD tid, HANDLE thread)
166 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
167 ok(ret, "PostThreadMessage failed with error %ld\n", GetLastError());
168 /* be careful of races - don't return until hosting thread has terminated */
169 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
170 CloseHandle(thread);
173 static const char cf_marshaled[] =
175 0x9, 0x0, 0x0, 0x0,
176 0x0, 0x0, 0x0, 0x0,
177 0x9, 0x0, 0x0, 0x0,
178 'M', 0x0, 'y', 0x0,
179 'F', 0x0, 'o', 0x0,
180 'r', 0x0, 'm', 0x0,
181 'a', 0x0, 't', 0x0,
182 0x0, 0x0
185 static void test_marshal_CLIPFORMAT(void)
187 USER_MARSHAL_CB umcb;
188 MIDL_STUB_MESSAGE stub_msg;
189 RPC_MESSAGE rpc_msg;
190 unsigned char *buffer, *buffer_end;
191 ULONG i, size;
192 CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
193 CLIPFORMAT cf2;
195 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
196 size = CLIPFORMAT_UserSize(&umcb.Flags, 1, &cf);
197 ok(size == 12 + sizeof(cf_marshaled) ||
198 broken(size == 16 + sizeof(cf_marshaled)), /* win64 adds 4 extra (unused) bytes */
199 "CLIPFORMAT: Wrong size %ld\n", size);
201 buffer = HeapAlloc(GetProcessHeap(), 0, size);
202 memset( buffer, 0xcc, size );
203 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
204 buffer_end = CLIPFORMAT_UserMarshal(&umcb.Flags, buffer + 1, &cf);
205 ok(buffer_end == buffer + 12 + sizeof(cf_marshaled), "got %p buffer %p\n", buffer_end, buffer);
206 ok(*(LONG *)(buffer + 4) == WDT_REMOTE_CALL, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(LONG *)(buffer + 0));
207 ok(*(DWORD *)(buffer + 8) == cf, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04lx\n", cf, *(DWORD *)(buffer + 4));
208 ok(!memcmp(buffer + 12, cf_marshaled, min( sizeof(cf_marshaled), size-12 )), "Marshaled data differs\n");
209 if (size > sizeof(cf_marshaled) + 12) /* make sure the extra bytes are not used */
210 for (i = sizeof(cf_marshaled) + 12; i < size; i++)
211 ok( buffer[i] == 0xcc, "buffer offset %lu has been set to %x\n", i, buffer[i] );
213 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
214 buffer_end = CLIPFORMAT_UserUnmarshal(&umcb.Flags, buffer + 1, &cf2);
215 ok(buffer_end == buffer + 12 + sizeof(cf_marshaled), "got %p buffer %p\n", buffer_end, buffer);
216 ok(cf == cf2, "CLIPFORMAT: Didn't unmarshal properly\n");
217 HeapFree(GetProcessHeap(), 0, buffer);
219 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
220 CLIPFORMAT_UserFree(&umcb.Flags, &cf2);
223 static void test_marshal_HWND(void)
225 USER_MARSHAL_CB umcb;
226 MIDL_STUB_MESSAGE stub_msg;
227 RPC_MESSAGE rpc_msg;
228 unsigned char *buffer, *buffer_end;
229 ULONG size;
230 HWND hwnd = GetDesktopWindow();
231 HWND hwnd2;
232 wireHWND wirehwnd;
234 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
235 size = HWND_UserSize(&umcb.Flags, 1, &hwnd);
236 ok(size == 4 + sizeof(*wirehwnd), "Wrong size %ld\n", size);
238 buffer = HeapAlloc(GetProcessHeap(), 0, size);
239 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
240 buffer_end = HWND_UserMarshal(&umcb.Flags, buffer + 1, &hwnd);
241 ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
242 wirehwnd = (wireHWND)(buffer + 4);
243 ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
244 ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %lx\n", hwnd, wirehwnd->u.hRemote);
246 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
247 buffer_end = HWND_UserUnmarshal(&umcb.Flags, buffer + 1, &hwnd2);
248 ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
249 ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
250 HeapFree(GetProcessHeap(), 0, buffer);
252 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
253 HWND_UserFree(&umcb.Flags, &hwnd2);
256 static void test_marshal_HGLOBAL(void)
258 USER_MARSHAL_CB umcb;
259 MIDL_STUB_MESSAGE stub_msg;
260 RPC_MESSAGE rpc_msg;
261 unsigned char *buffer;
262 ULONG size, block_size;
263 HGLOBAL hglobal;
264 HGLOBAL hglobal2;
265 unsigned char *wirehglobal;
266 int i;
268 hglobal = NULL;
269 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
270 size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
271 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
272 * here - Wine doesn't have to emulate that */
273 ok((size == 8) || broken(size == 12) || broken(size == 16), "Size should be 8, instead of %ld\n", size);
274 buffer = HeapAlloc(GetProcessHeap(), 0, size);
275 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
276 HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
277 wirehglobal = buffer;
278 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
279 wirehglobal += sizeof(ULONG);
280 ok(*(ULONG *)wirehglobal == 0, "buffer+4 should be HGLOBAL\n");
281 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
282 hglobal2 = NULL;
283 HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
284 ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
285 HeapFree(GetProcessHeap(), 0, buffer);
286 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
287 HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
290 for(block_size = 0; block_size <= 17; block_size++)
292 ULONG actual_size, expected_size;
294 hglobal = GlobalAlloc(0, block_size);
295 buffer = GlobalLock(hglobal);
296 for (i = 0; i < block_size; i++)
297 buffer[i] = i;
298 GlobalUnlock(hglobal);
299 actual_size = GlobalSize(hglobal);
300 expected_size = actual_size + 5 * sizeof(DWORD);
301 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
302 size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
303 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
304 * here - Wine doesn't have to emulate that */
305 ok(size == expected_size ||
306 broken(size == expected_size + 4) ||
307 broken(size == expected_size + 8),
308 "%ld: got size %ld\n", block_size, size);
309 buffer = HeapAlloc(GetProcessHeap(), 0, size);
310 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
311 HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
312 wirehglobal = buffer;
313 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
314 wirehglobal += sizeof(ULONG);
315 ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0x4 should be HGLOBAL\n");
316 wirehglobal += sizeof(ULONG);
317 ok(*(ULONG *)wirehglobal == actual_size, "%ld: buffer+0x8 %08lx\n", block_size, *(ULONG *)wirehglobal);
318 wirehglobal += sizeof(ULONG);
319 ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0xc should be HGLOBAL\n");
320 wirehglobal += sizeof(ULONG);
321 ok(*(ULONG *)wirehglobal == actual_size, "%ld: buffer+0x10 %08lx\n", block_size, *(ULONG *)wirehglobal);
322 wirehglobal += sizeof(ULONG);
323 for (i = 0; i < block_size; i++)
324 ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
326 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
327 hglobal2 = NULL;
328 HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
329 ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
330 HeapFree(GetProcessHeap(), 0, buffer);
331 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
332 HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
333 GlobalFree(hglobal);
337 static HENHMETAFILE create_emf(void)
339 const RECT rect = {0, 0, 100, 100};
340 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
341 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
342 return CloseEnhMetaFile(hdc);
345 static void test_marshal_HENHMETAFILE(void)
347 USER_MARSHAL_CB umcb;
348 MIDL_STUB_MESSAGE stub_msg;
349 RPC_MESSAGE rpc_msg;
350 unsigned char *buffer, *buffer_end;
351 ULONG size;
352 HENHMETAFILE hemf;
353 HENHMETAFILE hemf2 = NULL;
354 unsigned char *wirehemf;
356 hemf = create_emf();
358 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
359 size = HENHMETAFILE_UserSize(&umcb.Flags, 1, &hemf);
360 ok(size > 24, "size should be at least 24 bytes, not %ld\n", size);
361 buffer = HeapAlloc(GetProcessHeap(), 0, size);
362 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
363 buffer_end = HENHMETAFILE_UserMarshal(&umcb.Flags, buffer + 1, &hemf);
364 ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
365 wirehemf = buffer + 4;
366 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
367 wirehemf += sizeof(DWORD);
368 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
369 wirehemf += sizeof(DWORD);
370 ok(*(DWORD *)wirehemf == (size - 0x14), "wirestgm + 0x8 should be size - 0x14 instead of 0x%08lx\n", *(DWORD *)wirehemf);
371 wirehemf += sizeof(DWORD);
372 ok(*(DWORD *)wirehemf == (size - 0x14), "wirestgm + 0xc should be size - 0x14 instead of 0x%08lx\n", *(DWORD *)wirehemf);
373 wirehemf += sizeof(DWORD);
374 ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %ld\n", *(DWORD *)wirehemf);
375 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
376 * at this point */
378 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
379 buffer_end = HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer + 1, &hemf2);
380 ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
381 ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
382 HeapFree(GetProcessHeap(), 0, buffer);
383 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
384 HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
385 DeleteEnhMetaFile(hemf);
387 /* test NULL emf */
388 hemf = NULL;
390 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
391 size = HENHMETAFILE_UserSize(&umcb.Flags, 1, &hemf);
392 ok(size == 12, "size should be 12 bytes, not %ld\n", size);
393 buffer = HeapAlloc(GetProcessHeap(), 0, size);
394 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
395 buffer_end = HENHMETAFILE_UserMarshal(&umcb.Flags, buffer + 1, &hemf);
396 ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
397 wirehemf = buffer + 4;
398 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
399 wirehemf += sizeof(DWORD);
400 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
402 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
403 buffer_end = HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer + 1, &hemf2);
404 ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
405 ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
406 HeapFree(GetProcessHeap(), 0, buffer);
407 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
408 HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
411 static HMETAFILE create_mf(void)
413 RECT rect = {0, 0, 100, 100};
414 HDC hdc = CreateMetaFileA(NULL);
415 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
416 return CloseMetaFile(hdc);
419 static void test_marshal_HMETAFILE(void)
421 USER_MARSHAL_CB umcb;
422 MIDL_STUB_MESSAGE stub_msg;
423 RPC_MESSAGE rpc_msg;
424 unsigned char *buffer;
425 ULONG size;
426 HMETAFILE hmf;
427 HMETAFILE hmf2 = NULL;
428 unsigned char *wirehmf;
430 hmf = create_mf();
432 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
433 size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
434 ok(size > 20, "size should be at least 20 bytes, not %ld\n", size);
435 buffer = HeapAlloc(GetProcessHeap(), 0, size);
436 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
437 HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
438 wirehmf = buffer;
439 ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehmf);
440 wirehmf += sizeof(DWORD);
441 ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08lx\n", *(DWORD *)wirehmf);
442 wirehmf += sizeof(DWORD);
443 ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehmf);
444 wirehmf += sizeof(DWORD);
445 ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehmf);
446 wirehmf += sizeof(DWORD);
447 ok(*(WORD *)wirehmf == 1, "wirestgm + 0x10 should be 1 instead of 0x%08lx\n", *(DWORD *)wirehmf);
448 wirehmf += sizeof(DWORD);
449 /* ... rest of data not tested - refer to tests for GetMetaFileBits
450 * at this point */
452 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
453 HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
454 ok(hmf2 != NULL, "HMETAFILE didn't unmarshal\n");
455 HeapFree(GetProcessHeap(), 0, buffer);
456 HMETAFILE_UserFree(&umcb.Flags, &hmf2);
457 DeleteMetaFile(hmf);
459 /* test NULL emf */
460 hmf = NULL;
462 size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
463 ok(size == 8, "size should be 8 bytes, not %ld\n", size);
464 buffer = HeapAlloc(GetProcessHeap(), 0, size);
465 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
466 HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
467 wirehmf = buffer;
468 ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehmf);
469 wirehmf += sizeof(DWORD);
470 ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08lx\n", *(DWORD *)wirehmf);
471 wirehmf += sizeof(DWORD);
473 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
474 HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
475 ok(hmf2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
476 HeapFree(GetProcessHeap(), 0, buffer);
477 HMETAFILE_UserFree(&umcb.Flags, &hmf2);
480 #define USER_MARSHAL_PTR_PREFIX \
481 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
482 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
484 static void test_marshal_HMETAFILEPICT(void)
486 USER_MARSHAL_CB umcb;
487 MIDL_STUB_MESSAGE stub_msg;
488 RPC_MESSAGE rpc_msg;
489 unsigned char *buffer, *buffer_end;
490 ULONG size;
491 HMETAFILEPICT hmfp;
492 HMETAFILEPICT hmfp2 = NULL;
493 METAFILEPICT *pmfp;
494 unsigned char *wirehmfp;
496 hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(*pmfp));
497 pmfp = GlobalLock(hmfp);
498 pmfp->mm = MM_ISOTROPIC;
499 pmfp->xExt = 1;
500 pmfp->yExt = 2;
501 pmfp->hMF = create_mf();
502 GlobalUnlock(hmfp);
504 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
505 size = HMETAFILEPICT_UserSize(&umcb.Flags, 1, &hmfp);
506 ok(size > 24, "size should be at least 24 bytes, not %ld\n", size);
507 buffer = HeapAlloc(GetProcessHeap(), 0, size);
508 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
509 buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer + 1, &hmfp);
510 wirehmfp = buffer + 4;
511 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehmfp);
512 wirehmfp += sizeof(DWORD);
513 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08lx\n", *(DWORD *)wirehmfp);
514 wirehmfp += sizeof(DWORD);
515 ok(*(DWORD *)wirehmfp == MM_ISOTROPIC, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08lx\n", *(DWORD *)wirehmfp);
516 wirehmfp += sizeof(DWORD);
517 ok(*(DWORD *)wirehmfp == 1, "wirestgm + 0xc should be 1 instead of 0x%08lx\n", *(DWORD *)wirehmfp);
518 wirehmfp += sizeof(DWORD);
519 ok(*(DWORD *)wirehmfp == 2, "wirestgm + 0x10 should be 2 instead of 0x%08lx\n", *(DWORD *)wirehmfp);
520 wirehmfp += sizeof(DWORD);
521 ok(*(DWORD *)wirehmfp == USER_MARSHAL_PTR_PREFIX, "wirestgm + 0x14 should be \"User\" instead of 0x%08lx\n", *(DWORD *)wirehmfp);
522 wirehmfp += sizeof(DWORD);
523 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehmfp);
524 wirehmfp += sizeof(DWORD);
525 pmfp = GlobalLock(hmfp);
526 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)pmfp->hMF, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08lx\n", *(DWORD *)wirehmfp);
527 GlobalUnlock(hmfp);
528 wirehmfp += sizeof(DWORD);
529 /* Note use (buffer_end - buffer) instead of size here, because size is an
530 * overestimate with native */
531 ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x2c), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08lx\n", *(DWORD *)wirehmfp);
532 wirehmfp += sizeof(DWORD);
533 ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x2c), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08lx\n", *(DWORD *)wirehmfp);
534 wirehmfp += sizeof(DWORD);
535 ok(*(WORD *)wirehmfp == 1, "wirehmfp + 0x28 should be 1 instead of 0x%08lx\n", *(DWORD *)wirehmfp);
536 /* ... rest of data not tested - refer to tests for GetMetaFileBits
537 * at this point */
539 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
540 HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer + 1, &hmfp2);
541 ok(hmfp2 != NULL, "HMETAFILEPICT didn't unmarshal\n");
542 HeapFree(GetProcessHeap(), 0, buffer);
543 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
544 HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
545 pmfp = GlobalLock(hmfp);
546 DeleteMetaFile(pmfp->hMF);
547 GlobalUnlock(hmfp);
548 GlobalFree(hmfp);
550 /* test NULL emf */
551 hmfp = NULL;
553 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
554 size = HMETAFILEPICT_UserSize(&umcb.Flags, 1, &hmfp);
555 ok(size == 12, "size should be 12 bytes, not %ld\n", size);
556 buffer = HeapAlloc(GetProcessHeap(), 0, size);
557 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
558 buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer + 1, &hmfp);
559 ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
560 wirehmfp = buffer + 4;
561 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehmfp);
562 wirehmfp += sizeof(DWORD);
563 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08lx\n", *(DWORD *)wirehmfp);
564 wirehmfp += sizeof(DWORD);
566 hmfp2 = NULL;
567 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
568 buffer_end = HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer + 1, &hmfp2);
569 ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
570 ok(hmfp2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
571 HeapFree(GetProcessHeap(), 0, buffer);
572 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
573 HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
576 typedef struct
578 IUnknown IUnknown_iface;
579 LONG refs;
580 } TestUnknown;
582 static inline TestUnknown *impl_from_IUnknown(IUnknown *iface)
584 return CONTAINING_RECORD(iface, TestUnknown, IUnknown_iface);
587 static HRESULT WINAPI Test_IUnknown_QueryInterface(
588 LPUNKNOWN iface,
589 REFIID riid,
590 LPVOID *ppvObj)
592 if (ppvObj == NULL) return E_POINTER;
594 if (IsEqualGUID(riid, &IID_IUnknown))
596 *ppvObj = iface;
597 IUnknown_AddRef(iface);
598 return S_OK;
601 *ppvObj = NULL;
602 return E_NOINTERFACE;
605 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
607 TestUnknown *This = impl_from_IUnknown(iface);
608 return InterlockedIncrement(&This->refs);
611 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
613 TestUnknown *This = impl_from_IUnknown(iface);
614 return InterlockedDecrement(&This->refs);
617 static const IUnknownVtbl TestUnknown_Vtbl =
619 Test_IUnknown_QueryInterface,
620 Test_IUnknown_AddRef,
621 Test_IUnknown_Release,
624 struct test_stream
626 IStream IStream_iface;
627 LONG refs;
630 static inline struct test_stream *impl_from_IStream(IStream *iface)
632 return CONTAINING_RECORD(iface, struct test_stream, IStream_iface);
635 static HRESULT WINAPI Test_IStream_QueryInterface(IStream *iface,
636 REFIID riid, LPVOID *ppvObj)
638 if (ppvObj == NULL) return E_POINTER;
640 if (IsEqualIID(riid, &IID_IUnknown) ||
641 IsEqualIID(riid, &IID_IStream))
643 *ppvObj = iface;
644 IStream_AddRef(iface);
645 return S_OK;
648 *ppvObj = NULL;
649 return E_NOINTERFACE;
652 static ULONG WINAPI Test_IStream_AddRef(IStream *iface)
654 struct test_stream *This = impl_from_IStream(iface);
655 return InterlockedIncrement(&This->refs);
658 static ULONG WINAPI Test_IStream_Release(IStream *iface)
660 struct test_stream *This = impl_from_IStream(iface);
661 return InterlockedDecrement(&This->refs);
664 static const IStreamVtbl TestStream_Vtbl =
666 Test_IStream_QueryInterface,
667 Test_IStream_AddRef,
668 Test_IStream_Release
669 /* the rest can be NULLs */
672 static TestUnknown Test_Unknown = { {&TestUnknown_Vtbl}, 1 };
673 static TestUnknown Test_Unknown2 = { {&TestUnknown_Vtbl}, 1 };
674 static struct test_stream Test_Stream = { {&TestStream_Vtbl}, 1 };
675 static struct test_stream Test_Stream2 = { {&TestStream_Vtbl}, 1 };
677 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *, REFIID);
678 unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG *, ULONG, unsigned char *, IUnknown *, REFIID);
679 unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG *, unsigned char *, IUnknown **, REFIID);
681 static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx, BOOL client, BOOL in, BOOL out)
683 USER_MARSHAL_CB umcb;
684 MIDL_STUB_MESSAGE stub_msg;
685 RPC_MESSAGE rpc_msg;
686 unsigned char *buffer, *buffer_end;
687 ULONG size;
688 IUnknown *unk;
689 IUnknown *unk2;
690 unsigned char *wireip;
691 HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
692 IStream *stm;
693 void *marshal_data;
694 LARGE_INTEGER zero;
695 ULARGE_INTEGER pos;
696 DWORD marshal_size;
698 /* shows that the WdtpInterfacePointer functions don't marshal anything for
699 * NULL pointers, so code using these functions must handle that case
700 * itself */
702 unk = NULL;
703 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx);
704 size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown);
705 ok(size == 0, "size should be 0 bytes, not %ld\n", size);
706 buffer = HeapAlloc(GetProcessHeap(), 0, size);
707 buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown);
708 ok(buffer_end == buffer, "buffer_end %p buffer %p\n", buffer_end, buffer);
709 HeapFree(GetProcessHeap(), 0, buffer);
711 /* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then
712 the result of CoMarshalInterface called with the LOWORD of the ctx */
714 unk = &Test_Unknown.IUnknown_iface;
715 Test_Unknown.refs = 1;
717 CreateStreamOnHGlobal(h, TRUE, &stm);
718 CoMarshalInterface(stm, &IID_IUnknown, unk, LOWORD(ctx), NULL, MSHLFLAGS_NORMAL);
719 zero.QuadPart = 0;
720 IStream_Seek(stm, zero, STREAM_SEEK_CUR, &pos);
721 marshal_size = pos.u.LowPart;
722 marshal_data = GlobalLock(h);
723 todo_wine
724 ok(Test_Unknown.refs == 2, "got %ld\n", Test_Unknown.refs);
726 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx);
727 size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown);
728 ok(size >= marshal_size + 2 * sizeof(DWORD), "marshal size %lx got %lx\n", marshal_size, size);
729 buffer = HeapAlloc(GetProcessHeap(), 0, size);
730 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx);
731 buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown);
732 todo_wine
733 ok(Test_Unknown.refs == 2, "got %ld\n", Test_Unknown.refs);
734 wireip = buffer;
736 ok(buffer_end == buffer + marshal_size + 2 * sizeof(DWORD), "buffer_end %p buffer %p\n", buffer_end, buffer);
738 ok(*(DWORD *)wireip == marshal_size, "wireip + 0x0 should be %lx instead of %lx\n", marshal_size, *(DWORD *)wireip);
739 wireip += sizeof(DWORD);
740 ok(*(DWORD *)wireip == marshal_size, "wireip + 0x4 should be %lx instead of %lx\n", marshal_size, *(DWORD *)wireip);
741 wireip += sizeof(DWORD);
743 ok(!memcmp(marshal_data, wireip, marshal_size), "buffer mismatch\n");
744 GlobalUnlock(h);
745 zero.QuadPart = 0;
746 IStream_Seek(stm, zero, STREAM_SEEK_SET, NULL);
747 CoReleaseMarshalData(stm);
748 IStream_Release(stm);
750 Test_Unknown2.refs = 1;
751 unk2 = &Test_Unknown2.IUnknown_iface;
752 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx);
753 umcb.pStubMsg->IsClient = client;
754 umcb.pStubMsg->fIsIn = in;
755 umcb.pStubMsg->fIsOut = out;
757 WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown);
758 ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n");
759 ok(Test_Unknown.refs == 2, "got %ld\n", Test_Unknown.refs);
760 ok(Test_Unknown2.refs == 0, "got %ld\n", Test_Unknown2.refs);
761 HeapFree(GetProcessHeap(), 0, buffer);
762 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
763 IUnknown_Release(unk2);
766 static void test_marshal_WdtpInterfacePointer(void)
769 * There are two places where we can pass the marshalling ctx: as
770 * part of the umcb and as a separate flag. The loword of that
771 * separate flag field is what matters.
774 /* All three are marshalled as inproc */
775 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_INPROC, 0,0,0);
776 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_INPROC,0,0,0);
777 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_INPROC, 0xffff),0,0,0);
779 /* All three are marshalled as remote */
780 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,0);
781 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_DIFFERENTMACHINE,0,0,0);
782 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_DIFFERENTMACHINE, 0xffff),0,0,0);
784 /* Test different combinations of client, in and out */
785 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,1);
786 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,0);
787 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,1);
788 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,0);
789 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,1);
790 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,0);
791 marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,1);
794 static void marshal_STGMEDIUM(BOOL client, BOOL in, BOOL out)
796 USER_MARSHAL_CB umcb;
797 MIDL_STUB_MESSAGE stub_msg;
798 RPC_MESSAGE rpc_msg;
799 unsigned char *buffer, *buffer_end, *expect_buffer, *expect_buffer_end;
800 ULONG size, expect_size;
801 STGMEDIUM med, med2;
802 IUnknown *unk = &Test_Unknown.IUnknown_iface;
803 IStream *stm = &Test_Stream.IStream_iface;
805 /* TYMED_NULL with pUnkForRelease */
807 Test_Unknown.refs = 1;
809 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
810 expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 2 * sizeof(DWORD), unk, &IID_IUnknown);
811 expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size);
812 *(DWORD*)expect_buffer = TYMED_NULL;
813 *((DWORD*)expect_buffer + 1) = 0xdeadbeef;
814 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
815 expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer + 2 * sizeof(DWORD), unk, &IID_IUnknown);
817 med.tymed = TYMED_NULL;
818 U(med).pstg = NULL;
819 med.pUnkForRelease = unk;
821 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
822 size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
823 ok(size == expect_size, "size %ld should be %ld bytes\n", size, expect_size);
825 buffer = HeapAlloc(GetProcessHeap(), 0, size);
826 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
827 buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
828 ok(buffer_end - buffer == expect_buffer_end - expect_buffer, "buffer size mismatch\n");
829 ok(*(DWORD*)buffer == TYMED_NULL, "got %08lx\n", *(DWORD*)buffer);
830 ok(*((DWORD*)buffer+1) != 0, "got %08lx\n", *((DWORD*)buffer+1));
831 ok(!memcmp(buffer+8, expect_buffer + 8, expect_buffer_end - expect_buffer - 8), "buffer mismatch\n");
833 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
834 umcb.pStubMsg->IsClient = client;
835 umcb.pStubMsg->fIsIn = in;
836 umcb.pStubMsg->fIsOut = out;
838 Test_Unknown2.refs = 1;
839 med2.tymed = TYMED_NULL;
840 U(med2).pstm = NULL;
841 med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
843 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
845 ok(med2.tymed == TYMED_NULL, "got tymed %lx\n", med2.tymed);
846 ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
847 ok(Test_Unknown2.refs == 0, "got %ld\n", Test_Unknown2.refs);
849 HeapFree(GetProcessHeap(), 0, buffer);
850 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
851 STGMEDIUM_UserFree(&umcb.Flags, &med2);
853 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
854 med2.tymed = TYMED_NULL;
855 U(med2).pstm = NULL;
856 med2.pUnkForRelease = NULL;
857 STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2);
858 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
859 STGMEDIUM_UserFree(&umcb.Flags, &med2);
861 ok(Test_Unknown.refs == 1, "got %ld\n", Test_Unknown.refs);
863 HeapFree(GetProcessHeap(), 0, expect_buffer);
865 /* TYMED_ISTREAM with pUnkForRelease */
867 Test_Unknown.refs = 1;
868 Test_Stream.refs = 1;
870 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
871 expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream);
872 expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, expect_size, unk, &IID_IUnknown);
874 expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size);
875 /* There may be a hole between the two interfaces so init the buffer to something */
876 memset(expect_buffer, 0xcc, expect_size);
877 *(DWORD*)expect_buffer = TYMED_ISTREAM;
878 *((DWORD*)expect_buffer + 1) = 0xdeadbeef;
879 *((DWORD*)expect_buffer + 2) = 0xcafe;
880 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
881 expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer + 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream);
882 expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer_end, unk, &IID_IUnknown);
884 med.tymed = TYMED_ISTREAM;
885 U(med).pstm = stm;
886 med.pUnkForRelease = unk;
888 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
889 size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
890 ok(size == expect_size, "size %ld should be %ld bytes\n", size, expect_size);
892 buffer = HeapAlloc(GetProcessHeap(), 0, size);
893 memset(buffer, 0xcc, size);
894 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
895 buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
896 ok(buffer_end - buffer == expect_buffer_end - expect_buffer, "buffer size mismatch\n");
897 ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08lx\n", *(DWORD*)buffer);
898 ok(*((DWORD*)buffer+1) != 0, "got %08lx\n", *((DWORD*)buffer+1));
899 ok(*((DWORD*)buffer+2) != 0, "got %08lx\n", *((DWORD*)buffer+2));
900 ok(!memcmp(buffer + 12, expect_buffer + 12, (buffer_end - buffer) - 12), "buffer mismatch\n");
902 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
903 umcb.pStubMsg->IsClient = client;
904 umcb.pStubMsg->fIsIn = in;
905 umcb.pStubMsg->fIsOut = out;
907 Test_Stream2.refs = 1;
908 Test_Unknown2.refs = 1;
909 med2.tymed = TYMED_ISTREAM;
910 U(med2).pstm = &Test_Stream2.IStream_iface;
911 med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
913 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
915 ok(med2.tymed == TYMED_ISTREAM, "got tymed %lx\n", med2.tymed);
916 ok(U(med2).pstm != NULL, "Incorrectly unmarshalled\n");
917 ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
918 ok(Test_Stream2.refs == 0, "got %ld\n", Test_Stream2.refs);
919 ok(Test_Unknown2.refs == 0, "got %ld\n", Test_Unknown2.refs);
921 HeapFree(GetProcessHeap(), 0, buffer);
922 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
923 STGMEDIUM_UserFree(&umcb.Flags, &med2);
925 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
926 med2.tymed = TYMED_NULL;
927 U(med2).pstm = NULL;
928 med2.pUnkForRelease = NULL;
929 STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2);
930 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
931 STGMEDIUM_UserFree(&umcb.Flags, &med2);
933 ok(Test_Unknown.refs == 1, "got %ld\n", Test_Unknown.refs);
934 ok(Test_Stream.refs == 1, "got %ld\n", Test_Stream.refs);
936 HeapFree(GetProcessHeap(), 0, expect_buffer);
938 /* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */
940 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
941 expect_size = 3 * sizeof(DWORD);
943 med.tymed = TYMED_ISTREAM;
944 U(med).pstm = NULL;
945 med.pUnkForRelease = NULL;
947 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
948 size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
949 ok(size == expect_size, "size %ld should be %ld bytes\n", size, expect_size);
951 buffer = HeapAlloc(GetProcessHeap(), 0, size);
952 memset(buffer, 0xcc, size);
953 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
954 buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
955 ok(buffer_end - buffer == expect_size, "buffer size mismatch\n");
956 ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08lx\n", *(DWORD*)buffer);
957 ok(*((DWORD*)buffer+1) == 0, "got %08lx\n", *((DWORD*)buffer+1));
958 ok(*((DWORD*)buffer+2) == 0, "got %08lx\n", *((DWORD*)buffer+2));
960 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
961 umcb.pStubMsg->IsClient = client;
962 umcb.pStubMsg->fIsIn = in;
963 umcb.pStubMsg->fIsOut = out;
965 Test_Stream2.refs = 1;
966 Test_Unknown2.refs = 1;
967 med2.tymed = TYMED_ISTREAM;
968 U(med2).pstm = &Test_Stream2.IStream_iface;
969 med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
971 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
973 ok(med2.tymed == TYMED_ISTREAM, "got tymed %lx\n", med2.tymed);
974 ok(U(med2).pstm == NULL, "Incorrectly unmarshalled\n");
975 ok(med2.pUnkForRelease == &Test_Unknown2.IUnknown_iface, "Incorrectly unmarshalled\n");
976 ok(Test_Stream2.refs == 0, "got %ld\n", Test_Stream2.refs);
977 ok(Test_Unknown2.refs == 1, "got %ld\n", Test_Unknown2.refs);
979 HeapFree(GetProcessHeap(), 0, buffer);
980 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
981 STGMEDIUM_UserFree(&umcb.Flags, &med2);
984 static void test_marshal_STGMEDIUM(void)
986 marshal_STGMEDIUM(0, 0, 0);
987 marshal_STGMEDIUM(0, 0, 1);
988 marshal_STGMEDIUM(0, 1, 0);
989 marshal_STGMEDIUM(0, 1, 1);
990 /* For Windows versions post 2003, client side, non-[in,out] STGMEDIUMs get zero-initialised.
991 However since inline stubs don't set fIsIn or fIsOut this behaviour would break
992 ref counting in GetDataHere_Proxy for example, as we'd end up not releasing the original
993 interface. For simplicity we don't test or implement this. */
994 marshal_STGMEDIUM(1, 1, 1);
997 static void test_marshal_SNB(void)
999 static const WCHAR str1W[] = {'s','t','r','i','n','g','1',0};
1000 static const WCHAR str2W[] = {'s','t','r','2',0};
1001 unsigned char *buffer, *src, *mbuf;
1002 MIDL_STUB_MESSAGE stub_msg;
1003 WCHAR **ptrW, *dataW;
1004 USER_MARSHAL_CB umcb;
1005 RPC_MESSAGE rpc_msg;
1006 RemSNB *wiresnb;
1007 SNB snb, snb2;
1008 ULONG size;
1010 /* 4 bytes alignment */
1011 snb = NULL;
1012 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1013 size = SNB_UserSize(&umcb.Flags, 3, &snb);
1014 ok(size == 16, "Size should be 16, instead of %ld\n", size);
1016 /* NULL block */
1017 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1018 size = SNB_UserSize(&umcb.Flags, 0, &snb);
1019 ok(size == 12, "Size should be 12, instead of %ld\n", size);
1021 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1022 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1023 mbuf = SNB_UserMarshal(&umcb.Flags, buffer, &snb);
1024 ok(mbuf == buffer + size, "got %p, %p\n", mbuf, buffer + size);
1026 wiresnb = (RemSNB*)buffer;
1027 ok(wiresnb->ulCntStr == 0, "got %lu\n", wiresnb->ulCntStr);
1028 ok(wiresnb->ulCntChar == 0, "got %lu\n", wiresnb->ulCntChar);
1029 ok(*(ULONG*)wiresnb->rgString == 0, "got %lu\n", *(ULONG*)wiresnb->rgString);
1031 snb2 = NULL;
1032 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1033 SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
1034 ok(snb2 == NULL, "got %p\n", snb2);
1036 HeapFree(GetProcessHeap(), 0, buffer);
1037 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1038 SNB_UserFree(&umcb.Flags, &snb2);
1040 /* block with actual data */
1042 /* allocate source block, n+1 pointers first, then data */
1043 src = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR*)*3 + sizeof(str1W) + sizeof(str2W));
1044 ptrW = (WCHAR**)src;
1045 dataW = *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*));
1046 ptrW++;
1047 *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*) + sizeof(str1W));
1048 ptrW++;
1049 *ptrW = NULL;
1050 lstrcpyW(dataW, str1W);
1051 dataW += lstrlenW(str1W) + 1;
1052 lstrcpyW(dataW, str2W);
1054 snb = (SNB)src;
1055 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1056 size = SNB_UserSize(&umcb.Flags, 0, &snb);
1057 ok(size == 38, "Size should be 38, instead of %ld\n", size);
1059 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1060 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1061 SNB_UserMarshal(&umcb.Flags, buffer, &snb);
1063 wiresnb = (RemSNB*)buffer;
1064 ok(wiresnb->ulCntStr == 13, "got %lu\n", wiresnb->ulCntStr);
1065 ok(wiresnb->ulCntChar == 2, "got %lu\n", wiresnb->ulCntChar);
1066 /* payload length is stored one more time, as ULONG */
1067 ok(*(ULONG*)wiresnb->rgString == wiresnb->ulCntStr, "got %lu\n", *(ULONG*)wiresnb->rgString);
1068 dataW = &wiresnb->rgString[2];
1069 ok(!lstrcmpW(dataW, str1W), "marshalled string 0: %s\n", wine_dbgstr_w(dataW));
1070 dataW += ARRAY_SIZE(str1W);
1071 ok(!lstrcmpW(dataW, str2W), "marshalled string 1: %s\n", wine_dbgstr_w(dataW));
1073 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1075 g_expect_user_alloc = TRUE;
1076 snb2 = NULL;
1077 SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
1078 g_expect_user_alloc = FALSE;
1080 ptrW = snb2;
1081 ok(!lstrcmpW(*ptrW, str1W), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW));
1082 ptrW++;
1083 ok(!lstrcmpW(*ptrW, str2W), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW));
1084 ptrW++;
1085 ok(*ptrW == NULL, "expected terminating NULL ptr, got %p, start %p\n", *ptrW, snb2);
1087 HeapFree(GetProcessHeap(), 0, buffer);
1088 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1090 g_expect_user_free = TRUE;
1091 SNB_UserFree(&umcb.Flags, &snb2);
1092 g_expect_user_free = FALSE;
1094 HeapFree(GetProcessHeap(), 0, src);
1097 static void test_marshal_HDC(void)
1099 MIDL_STUB_MESSAGE stub_msg;
1100 HDC hdc = GetDC(0), hdc2;
1101 USER_MARSHAL_CB umcb;
1102 RPC_MESSAGE rpc_msg;
1103 unsigned char *buffer, *buffer_end;
1104 wireHDC wirehdc;
1105 ULONG size;
1107 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1108 size = HDC_UserSize(&umcb.Flags, 1, &hdc);
1109 ok(size == 4 + sizeof(*wirehdc), "Wrong size %ld\n", size);
1111 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1112 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1113 buffer_end = HDC_UserMarshal(&umcb.Flags, buffer + 1, &hdc);
1114 ok(buffer_end == buffer + 4 + sizeof(*wirehdc), "got %p buffer %p\n", buffer_end, buffer);
1115 wirehdc = (wireHDC)(buffer + 4);
1116 ok(wirehdc->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehdc->fContext);
1117 ok(wirehdc->u.hInproc == (LONG_PTR)hdc, "Marshaled value should be %p instead of %lx\n", hdc, wirehdc->u.hRemote);
1119 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1120 buffer_end = HDC_UserUnmarshal(&umcb.Flags, buffer + 1, &hdc2);
1121 ok(buffer_end == buffer + 4 + sizeof(*wirehdc), "got %p buffer %p\n", buffer_end, buffer);
1122 ok(hdc == hdc2, "Didn't unmarshal properly\n");
1123 HeapFree(GetProcessHeap(), 0, buffer);
1125 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1126 HDC_UserFree(&umcb.Flags, &hdc2);
1127 ReleaseDC(0, hdc);
1130 static void test_marshal_HICON(void)
1132 static const BYTE bmp_bits[1024];
1133 MIDL_STUB_MESSAGE stub_msg;
1134 HICON hIcon, hIcon2;
1135 USER_MARSHAL_CB umcb;
1136 RPC_MESSAGE rpc_msg;
1137 unsigned char *buffer, *buffer_end;
1138 wireHICON wirehicon;
1139 ULONG size;
1141 hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
1142 ok(hIcon != 0, "CreateIcon failed\n");
1144 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1145 size = HICON_UserSize(&umcb.Flags, 1, &hIcon);
1146 ok(size == 4 + sizeof(*wirehicon), "Wrong size %ld\n", size);
1148 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1149 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1150 buffer_end = HICON_UserMarshal(&umcb.Flags, buffer + 1, &hIcon);
1151 ok(buffer_end == buffer + 4 + sizeof(*wirehicon), "got %p buffer %p\n", buffer_end, buffer);
1152 wirehicon = (wireHICON)(buffer + 4);
1153 ok(wirehicon->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehicon->fContext);
1154 ok(wirehicon->u.hInproc == (LONG_PTR)hIcon, "Marshaled value should be %p instead of %lx\n", hIcon, wirehicon->u.hRemote);
1156 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1157 buffer_end = HICON_UserUnmarshal(&umcb.Flags, buffer + 1, &hIcon2);
1158 ok(buffer_end == buffer + 4 + sizeof(*wirehicon), "got %p buffer %p\n", buffer_end, buffer);
1159 ok(hIcon == hIcon2, "Didn't unmarshal properly\n");
1160 HeapFree(GetProcessHeap(), 0, buffer);
1162 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1163 HICON_UserFree(&umcb.Flags, &hIcon2);
1164 DestroyIcon(hIcon);
1167 static void test_marshal_HBRUSH(void)
1169 MIDL_STUB_MESSAGE stub_msg;
1170 HBRUSH hBrush, hBrush2;
1171 USER_MARSHAL_CB umcb;
1172 RPC_MESSAGE rpc_msg;
1173 unsigned char *buffer, *buffer_end;
1174 LOGBRUSH logbrush;
1175 wireHBRUSH wirehbrush;
1176 ULONG size;
1178 logbrush.lbStyle = BS_SOLID;
1179 logbrush.lbColor = RGB(0, 0, 0);
1180 logbrush.lbHatch = 0;
1182 hBrush = CreateBrushIndirect(&logbrush);
1183 ok(hBrush != 0, "CreateBrushIndirect failed\n");
1185 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1186 size = HBRUSH_UserSize(&umcb.Flags, 1, &hBrush);
1187 ok(size == 4 + sizeof(*wirehbrush), "Wrong size %ld\n", size);
1189 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1190 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1191 buffer_end = HBRUSH_UserMarshal(&umcb.Flags, buffer + 1, &hBrush);
1192 ok(buffer_end == buffer + 4 + sizeof(*wirehbrush), "got %p buffer %p\n", buffer_end, buffer);
1193 wirehbrush = (wireHBRUSH)(buffer + 4);
1194 ok(wirehbrush->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehbrush->fContext);
1195 ok(wirehbrush->u.hInproc == (LONG_PTR)hBrush, "Marshaled value should be %p instead of %lx\n", hBrush, wirehbrush->u.hRemote);
1197 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1198 buffer_end = HBRUSH_UserUnmarshal(&umcb.Flags, buffer + 1, &hBrush2);
1199 ok(buffer_end == buffer + 4 + sizeof(*wirehbrush), "got %p buffer %p\n", buffer_end, buffer);
1200 ok(hBrush == hBrush2, "Didn't unmarshal properly\n");
1201 HeapFree(GetProcessHeap(), 0, buffer);
1203 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1204 HBRUSH_UserFree(&umcb.Flags, &hBrush2);
1205 DeleteObject(hBrush);
1208 static void test_marshal_HBITMAP(void)
1210 static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
1211 static BYTE bmp_bits[1024];
1212 MIDL_STUB_MESSAGE stub_msg;
1213 HBITMAP hBitmap, hBitmap2;
1214 USER_MARSHAL_CB umcb;
1215 RPC_MESSAGE rpc_msg;
1216 unsigned char *buffer, *buffer_end;
1217 unsigned char bitmap[1024];
1218 ULONG size, bitmap_size;
1220 hBitmap = CreateBitmap(16, 16, 1, 1, bmp_bits);
1221 ok(hBitmap != 0, "CreateBitmap failed\n");
1222 size = GetObjectA(hBitmap, sizeof(bitmap), bitmap);
1223 ok(size != 0, "GetObject failed\n");
1224 bitmap_size = GetBitmapBits(hBitmap, 0, NULL);
1225 ok(bitmap_size != 0, "GetBitmapBits failed\n");
1227 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
1228 size = HBITMAP_UserSize(&umcb.Flags, 1, &hBitmap);
1229 ok(size == 0xc, "Wrong size %ld\n", size);
1230 buffer = HeapAlloc(GetProcessHeap(), 0, size + 4);
1231 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
1232 buffer_end = HBITMAP_UserMarshal(&umcb.Flags, buffer + 1, &hBitmap);
1233 ok(buffer_end == buffer + 0xc, "HBITMAP_UserMarshal() returned wrong size %ld\n", (LONG)(buffer_end - buffer));
1234 ok(*(ULONG *)(buffer + 0x4) == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", *(ULONG *)(buffer + 0x4));
1235 ok(*(ULONG *)(buffer + 0x8) == (ULONG)(ULONG_PTR)hBitmap, "wirestgm + 0x4 should be bitmap handle instead of 0x%08lx\n", *(ULONG *)(buffer + 0x8));
1237 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
1238 HBITMAP_UserUnmarshal(&umcb.Flags, buffer + 1, &hBitmap2);
1239 ok(hBitmap2 != NULL, "Didn't unmarshal properly\n");
1240 HeapFree(GetProcessHeap(), 0, buffer);
1242 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
1243 HBITMAP_UserFree(&umcb.Flags, &hBitmap2);
1245 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1246 size = HBITMAP_UserSize(&umcb.Flags, 1, &hBitmap);
1247 ok(size == 0x10 + header_size + bitmap_size ||
1248 broken(size == 0x14 + header_size + bitmap_size), /* Windows adds 4 extra (unused) bytes */
1249 "Wrong size %ld\n", size);
1251 buffer = HeapAlloc(GetProcessHeap(), 0, size + 4);
1252 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1253 buffer_end = HBITMAP_UserMarshal(&umcb.Flags, buffer + 1, &hBitmap);
1254 ok(buffer_end == buffer + 0x10 + header_size + bitmap_size, "HBITMAP_UserMarshal() returned wrong size %ld\n", (LONG)(buffer_end - buffer));
1255 ok(*(ULONG *)(buffer + 0x4) == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)buffer);
1256 ok(*(ULONG *)(buffer + 0x8) == (ULONG)(ULONG_PTR)hBitmap, "wirestgm + 0x4 should be bitmap handle instead of 0x%08lx\n", *(ULONG *)(buffer + 0x4));
1257 ok(*(ULONG *)(buffer + 0xc) == (ULONG)(ULONG_PTR)bitmap_size, "wirestgm + 0x8 should be bitmap size instead of 0x%08lx\n", *(ULONG *)(buffer + 0x4));
1258 ok(!memcmp(buffer + 0x10, bitmap, header_size), "buffer mismatch\n");
1259 ok(!memcmp(buffer + 0x10 + header_size, bmp_bits, bitmap_size), "buffer mismatch\n");
1261 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1262 HBITMAP_UserUnmarshal(&umcb.Flags, buffer + 1, &hBitmap2);
1263 ok(hBitmap2 != NULL, "Didn't unmarshal properly\n");
1264 HeapFree(GetProcessHeap(), 0, buffer);
1266 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1267 HBITMAP_UserFree(&umcb.Flags, &hBitmap2);
1268 DeleteObject(hBitmap);
1271 struct obj
1273 IDataObject IDataObject_iface;
1276 static HRESULT WINAPI obj_QueryInterface(IDataObject *iface, REFIID iid, void **obj)
1278 *obj = NULL;
1280 if (IsEqualGUID(iid, &IID_IUnknown) ||
1281 IsEqualGUID(iid, &IID_IDataObject))
1282 *obj = iface;
1284 if (*obj)
1286 IDataObject_AddRef(iface);
1287 return S_OK;
1290 return E_NOINTERFACE;
1293 static ULONG WINAPI obj_AddRef(IDataObject *iface)
1295 return 2;
1298 static ULONG WINAPI obj_Release(IDataObject *iface)
1300 return 1;
1303 static HRESULT WINAPI obj_DO_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1304 STGMEDIUM *med)
1306 ok( med->pUnkForRelease == NULL, "got %p\n", med->pUnkForRelease );
1308 if (fmt->cfFormat == 2)
1310 IStream_Release(U(med)->pstm);
1311 U(med)->pstm = &Test_Stream2.IStream_iface;
1314 return S_OK;
1317 static const IDataObjectVtbl obj_data_object_vtbl =
1319 obj_QueryInterface,
1320 obj_AddRef,
1321 obj_Release,
1322 NULL, /* GetData */
1323 obj_DO_GetDataHere,
1324 NULL, /* QueryGetData */
1325 NULL, /* GetCanonicalFormatEtc */
1326 NULL, /* SetData */
1327 NULL, /* EnumFormatEtc */
1328 NULL, /* DAdvise */
1329 NULL, /* DUnadvise */
1330 NULL /* EnumDAdvise */
1333 static struct obj obj =
1335 {&obj_data_object_vtbl}
1338 static void test_GetDataHere_Proxy(void)
1340 HRESULT hr;
1341 IStream *stm;
1342 HANDLE thread;
1343 DWORD tid;
1344 static const LARGE_INTEGER zero;
1345 IDataObject *data;
1346 FORMATETC fmt;
1347 STGMEDIUM med;
1349 hr = CreateStreamOnHGlobal( NULL, TRUE, &stm );
1350 ok( hr == S_OK, "got %08lx\n", hr );
1351 tid = start_host_object2( stm, &IID_IDataObject, (IUnknown *)&obj.IDataObject_iface, MSHLFLAGS_NORMAL, NULL, &thread );
1353 IStream_Seek( stm, zero, STREAM_SEEK_SET, NULL );
1354 hr = CoUnmarshalInterface( stm, &IID_IDataObject, (void **)&data );
1355 ok( hr == S_OK, "got %08lx\n", hr );
1356 IStream_Release( stm );
1358 Test_Stream.refs = 1;
1359 Test_Stream2.refs = 1;
1360 Test_Unknown.refs = 1;
1362 fmt.cfFormat = 1;
1363 fmt.ptd = NULL;
1364 fmt.dwAspect = DVASPECT_CONTENT;
1365 fmt.lindex = -1;
1366 U(med).pstm = NULL;
1367 med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1369 fmt.tymed = med.tymed = TYMED_NULL;
1370 hr = IDataObject_GetDataHere( data, &fmt, &med );
1371 ok( hr == DV_E_TYMED, "got %08lx\n", hr );
1373 for (fmt.tymed = TYMED_HGLOBAL; fmt.tymed <= TYMED_ENHMF; fmt.tymed <<= 1)
1375 med.tymed = fmt.tymed;
1376 hr = IDataObject_GetDataHere( data, &fmt, &med );
1377 ok( hr == (fmt.tymed <= TYMED_ISTORAGE ? S_OK : DV_E_TYMED), "got %08lx for tymed %ld\n", hr, fmt.tymed );
1378 ok( Test_Unknown.refs == 1, "got %ld\n", Test_Unknown.refs );
1381 fmt.tymed = TYMED_ISTREAM;
1382 med.tymed = TYMED_ISTORAGE;
1383 hr = IDataObject_GetDataHere( data, &fmt, &med );
1384 ok( hr == DV_E_TYMED, "got %08lx\n", hr );
1386 fmt.tymed = med.tymed = TYMED_ISTREAM;
1387 U(med).pstm = &Test_Stream.IStream_iface;
1388 med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1390 hr = IDataObject_GetDataHere( data, &fmt, &med );
1391 ok( hr == S_OK, "got %08lx\n", hr );
1393 ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
1394 ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" );
1396 ok( Test_Stream.refs == 1, "got %ld\n", Test_Stream.refs );
1397 ok( Test_Unknown.refs == 1, "got %ld\n", Test_Unknown.refs );
1399 fmt.cfFormat = 2;
1400 fmt.tymed = med.tymed = TYMED_ISTREAM;
1401 U(med).pstm = &Test_Stream.IStream_iface;
1402 med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1404 hr = IDataObject_GetDataHere( data, &fmt, &med );
1405 ok( hr == S_OK, "got %08lx\n", hr );
1407 ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
1408 ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" );
1410 ok( Test_Stream.refs == 1, "got %ld\n", Test_Stream.refs );
1411 ok( Test_Unknown.refs == 1, "got %ld\n", Test_Unknown.refs );
1412 ok( Test_Stream2.refs == 0, "got %ld\n", Test_Stream2.refs );
1414 IDataObject_Release( data );
1415 end_host_object( tid, thread );
1418 START_TEST(usrmarshal)
1420 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1422 test_marshal_CLIPFORMAT();
1423 test_marshal_HWND();
1424 test_marshal_HGLOBAL();
1425 test_marshal_HENHMETAFILE();
1426 test_marshal_HMETAFILE();
1427 test_marshal_HMETAFILEPICT();
1428 test_marshal_WdtpInterfacePointer();
1429 test_marshal_STGMEDIUM();
1430 test_marshal_SNB();
1431 test_marshal_HDC();
1432 test_marshal_HICON();
1433 test_marshal_HBRUSH();
1434 test_marshal_HBITMAP();
1436 test_GetDataHere_Proxy();
1438 CoUninitialize();