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