ole32: Fix ref counting in GetDataHere Proxy.
[wine.git] / dlls / ole32 / tests / usrmarshal.c
blob529ad757c6a1093cef09b4d4c7a9b2e7b150dac2
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 %08x\n", hr);
116 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
117 ok(hr == S_OK, "got %08x\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 %d\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;
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, 0, &cf);
197 ok(size == 8 + sizeof(cf_marshaled) ||
198 broken(size == 12 + sizeof(cf_marshaled)) || /* win64 adds 4 extra (unused) bytes */
199 broken(size == 8 + sizeof(cf_marshaled) - 2), /* win9x and winnt don't include the '\0' */
200 "CLIPFORMAT: Wrong size %d\n", size);
202 buffer = HeapAlloc(GetProcessHeap(), 0, size);
203 memset( buffer, 0xcc, size );
204 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
205 CLIPFORMAT_UserMarshal(&umcb.Flags, buffer, &cf);
206 ok(*(LONG *)(buffer + 0) == WDT_REMOTE_CALL, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(LONG *)(buffer + 0));
207 ok(*(DWORD *)(buffer + 4) == cf, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04x\n", cf, *(DWORD *)(buffer + 4));
208 ok(!memcmp(buffer + 8, cf_marshaled, min( sizeof(cf_marshaled), size-8 )), "Marshaled data differs\n");
209 if (size > sizeof(cf_marshaled) + 8) /* make sure the extra bytes are not used */
210 for (i = sizeof(cf_marshaled) + 8; i < size; i++)
211 ok( buffer[i] == 0xcc, "buffer offset %u has been set to %x\n", i, buffer[i] );
213 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
214 CLIPFORMAT_UserUnmarshal(&umcb.Flags, buffer, &cf2);
215 ok(cf == cf2, "CLIPFORMAT: Didn't unmarshal properly\n");
216 HeapFree(GetProcessHeap(), 0, buffer);
218 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
219 CLIPFORMAT_UserFree(&umcb.Flags, &cf2);
222 static void test_marshal_HWND(void)
224 USER_MARSHAL_CB umcb;
225 MIDL_STUB_MESSAGE stub_msg;
226 RPC_MESSAGE rpc_msg;
227 unsigned char *buffer;
228 ULONG size;
229 HWND hwnd = GetDesktopWindow();
230 HWND hwnd2;
231 wireHWND wirehwnd;
233 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
234 size = HWND_UserSize(&umcb.Flags, 0, &hwnd);
235 ok(size == sizeof(*wirehwnd), "Wrong size %d\n", size);
237 buffer = HeapAlloc(GetProcessHeap(), 0, size);
238 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
239 HWND_UserMarshal(&umcb.Flags, buffer, &hwnd);
240 wirehwnd = (wireHWND)buffer;
241 ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehwnd->fContext);
242 ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %x\n", hwnd, wirehwnd->u.hRemote);
244 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
245 HWND_UserUnmarshal(&umcb.Flags, buffer, &hwnd2);
246 ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
247 HeapFree(GetProcessHeap(), 0, buffer);
249 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
250 HWND_UserFree(&umcb.Flags, &hwnd2);
253 static void test_marshal_HGLOBAL(void)
255 USER_MARSHAL_CB umcb;
256 MIDL_STUB_MESSAGE stub_msg;
257 RPC_MESSAGE rpc_msg;
258 unsigned char *buffer;
259 ULONG size, block_size;
260 HGLOBAL hglobal;
261 HGLOBAL hglobal2;
262 unsigned char *wirehglobal;
263 int i;
265 hglobal = NULL;
266 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
267 size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
268 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
269 * here - Wine doesn't have to emulate that */
270 ok((size == 8) || broken(size == 12) || broken(size == 16), "Size should be 8, instead of %d\n", size);
271 buffer = HeapAlloc(GetProcessHeap(), 0, size);
272 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
273 HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
274 wirehglobal = buffer;
275 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
276 wirehglobal += sizeof(ULONG);
277 ok(*(ULONG *)wirehglobal == 0, "buffer+4 should be HGLOBAL\n");
278 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
279 hglobal2 = NULL;
280 HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
281 ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
282 HeapFree(GetProcessHeap(), 0, buffer);
283 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
284 HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
287 for(block_size = 0; block_size <= 17; block_size++)
289 ULONG actual_size, expected_size;
291 hglobal = GlobalAlloc(0, block_size);
292 buffer = GlobalLock(hglobal);
293 for (i = 0; i < block_size; i++)
294 buffer[i] = i;
295 GlobalUnlock(hglobal);
296 actual_size = GlobalSize(hglobal);
297 expected_size = actual_size + 5 * sizeof(DWORD);
298 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
299 size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
300 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
301 * here - Wine doesn't have to emulate that */
302 ok(size == expected_size ||
303 broken(size == expected_size + 4) ||
304 broken(size == expected_size + 8),
305 "%d: got size %d\n", block_size, size);
306 buffer = HeapAlloc(GetProcessHeap(), 0, size);
307 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
308 HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
309 wirehglobal = buffer;
310 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
311 wirehglobal += sizeof(ULONG);
312 ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0x4 should be HGLOBAL\n");
313 wirehglobal += sizeof(ULONG);
314 ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x8 %08x\n", block_size, *(ULONG *)wirehglobal);
315 wirehglobal += sizeof(ULONG);
316 ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0xc should be HGLOBAL\n");
317 wirehglobal += sizeof(ULONG);
318 ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x10 %08x\n", block_size, *(ULONG *)wirehglobal);
319 wirehglobal += sizeof(ULONG);
320 for (i = 0; i < block_size; i++)
321 ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
323 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
324 hglobal2 = NULL;
325 HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
326 ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
327 HeapFree(GetProcessHeap(), 0, buffer);
328 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
329 HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
330 GlobalFree(hglobal);
334 static HENHMETAFILE create_emf(void)
336 const RECT rect = {0, 0, 100, 100};
337 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
338 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
339 return CloseEnhMetaFile(hdc);
342 static void test_marshal_HENHMETAFILE(void)
344 USER_MARSHAL_CB umcb;
345 MIDL_STUB_MESSAGE stub_msg;
346 RPC_MESSAGE rpc_msg;
347 unsigned char *buffer;
348 ULONG size;
349 HENHMETAFILE hemf;
350 HENHMETAFILE hemf2 = NULL;
351 unsigned char *wirehemf;
353 hemf = create_emf();
355 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
356 size = HENHMETAFILE_UserSize(&umcb.Flags, 0, &hemf);
357 ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
358 buffer = HeapAlloc(GetProcessHeap(), 0, size);
359 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
360 HENHMETAFILE_UserMarshal(&umcb.Flags, buffer, &hemf);
361 wirehemf = buffer;
362 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
363 wirehemf += sizeof(DWORD);
364 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
365 wirehemf += sizeof(DWORD);
366 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
367 wirehemf += sizeof(DWORD);
368 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
369 wirehemf += sizeof(DWORD);
370 ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf);
371 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
372 * at this point */
374 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
375 HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hemf2);
376 ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
377 HeapFree(GetProcessHeap(), 0, buffer);
378 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
379 HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
380 DeleteEnhMetaFile(hemf);
382 /* test NULL emf */
383 hemf = NULL;
385 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
386 size = HENHMETAFILE_UserSize(&umcb.Flags, 0, &hemf);
387 ok(size == 8, "size should be 8 bytes, not %d\n", size);
388 buffer = HeapAlloc(GetProcessHeap(), 0, size);
389 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
390 HENHMETAFILE_UserMarshal(&umcb.Flags, buffer, &hemf);
391 wirehemf = buffer;
392 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
393 wirehemf += sizeof(DWORD);
394 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
396 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
397 HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hemf2);
398 ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
399 HeapFree(GetProcessHeap(), 0, buffer);
400 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
401 HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
404 static HMETAFILE create_mf(void)
406 RECT rect = {0, 0, 100, 100};
407 HDC hdc = CreateMetaFileA(NULL);
408 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
409 return CloseMetaFile(hdc);
412 static void test_marshal_HMETAFILE(void)
414 USER_MARSHAL_CB umcb;
415 MIDL_STUB_MESSAGE stub_msg;
416 RPC_MESSAGE rpc_msg;
417 unsigned char *buffer;
418 ULONG size;
419 HMETAFILE hmf;
420 HMETAFILE hmf2 = NULL;
421 unsigned char *wirehmf;
423 hmf = create_mf();
425 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
426 size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
427 ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
428 buffer = HeapAlloc(GetProcessHeap(), 0, size);
429 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
430 HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
431 wirehmf = buffer;
432 ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
433 wirehmf += sizeof(DWORD);
434 ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
435 wirehmf += sizeof(DWORD);
436 ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
437 wirehmf += sizeof(DWORD);
438 ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
439 wirehmf += sizeof(DWORD);
440 ok(*(WORD *)wirehmf == 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmf);
441 wirehmf += sizeof(DWORD);
442 /* ... rest of data not tested - refer to tests for GetMetaFileBits
443 * at this point */
445 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
446 HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
447 ok(hmf2 != NULL, "HMETAFILE didn't unmarshal\n");
448 HeapFree(GetProcessHeap(), 0, buffer);
449 HMETAFILE_UserFree(&umcb.Flags, &hmf2);
450 DeleteMetaFile(hmf);
452 /* test NULL emf */
453 hmf = NULL;
455 size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
456 ok(size == 8, "size should be 8 bytes, not %d\n", size);
457 buffer = HeapAlloc(GetProcessHeap(), 0, size);
458 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
459 HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
460 wirehmf = buffer;
461 ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
462 wirehmf += sizeof(DWORD);
463 ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
464 wirehmf += sizeof(DWORD);
466 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
467 HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
468 ok(hmf2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
469 HeapFree(GetProcessHeap(), 0, buffer);
470 HMETAFILE_UserFree(&umcb.Flags, &hmf2);
473 #define USER_MARSHAL_PTR_PREFIX \
474 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
475 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
477 static void test_marshal_HMETAFILEPICT(void)
479 USER_MARSHAL_CB umcb;
480 MIDL_STUB_MESSAGE stub_msg;
481 RPC_MESSAGE rpc_msg;
482 unsigned char *buffer, *buffer_end;
483 ULONG size;
484 HMETAFILEPICT hmfp;
485 HMETAFILEPICT hmfp2 = NULL;
486 METAFILEPICT *pmfp;
487 unsigned char *wirehmfp;
489 hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(*pmfp));
490 pmfp = GlobalLock(hmfp);
491 pmfp->mm = MM_ISOTROPIC;
492 pmfp->xExt = 1;
493 pmfp->yExt = 2;
494 pmfp->hMF = create_mf();
495 GlobalUnlock(hmfp);
497 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
498 size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp);
499 ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
500 buffer = HeapAlloc(GetProcessHeap(), 0, size);
501 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
502 buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp);
503 wirehmfp = buffer;
504 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
505 wirehmfp += sizeof(DWORD);
506 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
507 wirehmfp += sizeof(DWORD);
508 ok(*(DWORD *)wirehmfp == MM_ISOTROPIC, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD *)wirehmfp);
509 wirehmfp += sizeof(DWORD);
510 ok(*(DWORD *)wirehmfp == 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
511 wirehmfp += sizeof(DWORD);
512 ok(*(DWORD *)wirehmfp == 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD *)wirehmfp);
513 wirehmfp += sizeof(DWORD);
514 ok(*(DWORD *)wirehmfp == USER_MARSHAL_PTR_PREFIX, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD *)wirehmfp);
515 wirehmfp += sizeof(DWORD);
516 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
517 wirehmfp += sizeof(DWORD);
518 pmfp = GlobalLock(hmfp);
519 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)pmfp->hMF, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD *)wirehmfp);
520 GlobalUnlock(hmfp);
521 wirehmfp += sizeof(DWORD);
522 /* Note use (buffer_end - buffer) instead of size here, because size is an
523 * overestimate with native */
524 ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
525 wirehmfp += sizeof(DWORD);
526 ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
527 wirehmfp += sizeof(DWORD);
528 ok(*(WORD *)wirehmfp == 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
529 /* ... rest of data not tested - refer to tests for GetMetaFileBits
530 * at this point */
532 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
533 HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer, &hmfp2);
534 ok(hmfp2 != NULL, "HMETAFILEPICT didn't unmarshal\n");
535 HeapFree(GetProcessHeap(), 0, buffer);
536 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
537 HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
538 pmfp = GlobalLock(hmfp);
539 DeleteMetaFile(pmfp->hMF);
540 GlobalUnlock(hmfp);
541 GlobalFree(hmfp);
543 /* test NULL emf */
544 hmfp = NULL;
546 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
547 size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp);
548 ok(size == 8, "size should be 8 bytes, not %d\n", size);
549 buffer = HeapAlloc(GetProcessHeap(), 0, size);
550 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
551 HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp);
552 wirehmfp = buffer;
553 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
554 wirehmfp += sizeof(DWORD);
555 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
556 wirehmfp += sizeof(DWORD);
558 hmfp2 = NULL;
559 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
560 HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer, &hmfp2);
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);
567 typedef struct
569 IUnknown IUnknown_iface;
570 LONG refs;
571 } TestUnknown;
573 static inline TestUnknown *impl_from_IUnknown(IUnknown *iface)
575 return CONTAINING_RECORD(iface, TestUnknown, IUnknown_iface);
578 static HRESULT WINAPI Test_IUnknown_QueryInterface(
579 LPUNKNOWN iface,
580 REFIID riid,
581 LPVOID *ppvObj)
583 if (ppvObj == NULL) return E_POINTER;
585 if (IsEqualGUID(riid, &IID_IUnknown))
587 *ppvObj = iface;
588 IUnknown_AddRef(iface);
589 return S_OK;
592 *ppvObj = NULL;
593 return E_NOINTERFACE;
596 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
598 TestUnknown *This = impl_from_IUnknown(iface);
599 return InterlockedIncrement(&This->refs);
602 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
604 TestUnknown *This = impl_from_IUnknown(iface);
605 return InterlockedDecrement(&This->refs);
608 static const IUnknownVtbl TestUnknown_Vtbl =
610 Test_IUnknown_QueryInterface,
611 Test_IUnknown_AddRef,
612 Test_IUnknown_Release,
615 struct test_stream
617 IStream IStream_iface;
618 LONG refs;
621 static inline struct test_stream *impl_from_IStream(IStream *iface)
623 return CONTAINING_RECORD(iface, struct test_stream, IStream_iface);
626 static HRESULT WINAPI Test_IStream_QueryInterface(IStream *iface,
627 REFIID riid, LPVOID *ppvObj)
629 if (ppvObj == NULL) return E_POINTER;
631 if (IsEqualIID(riid, &IID_IUnknown) ||
632 IsEqualIID(riid, &IID_IStream))
634 *ppvObj = iface;
635 IStream_AddRef(iface);
636 return S_OK;
639 *ppvObj = NULL;
640 return E_NOINTERFACE;
643 static ULONG WINAPI Test_IStream_AddRef(IStream *iface)
645 struct test_stream *This = impl_from_IStream(iface);
646 return InterlockedIncrement(&This->refs);
649 static ULONG WINAPI Test_IStream_Release(IStream *iface)
651 struct test_stream *This = impl_from_IStream(iface);
652 return InterlockedDecrement(&This->refs);
655 static const IStreamVtbl TestStream_Vtbl =
657 Test_IStream_QueryInterface,
658 Test_IStream_AddRef,
659 Test_IStream_Release
660 /* the rest can be NULLs */
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 };
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);
672 static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx, BOOL client, BOOL in, BOOL out)
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;
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 */
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);
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 */
705 unk = &Test_Unknown.IUnknown_iface;
706 Test_Unknown.refs = 1;
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);
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;
727 ok(buffer_end == buffer + marshal_size + 2 * sizeof(DWORD), "buffer_end %p buffer %p\n", buffer_end, buffer);
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);
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);
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;
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);
757 static void test_marshal_WdtpInterfacePointer(void)
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.
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);
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);
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);
785 static void marshal_STGMEDIUM(BOOL client, BOOL in, BOOL out)
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;
796 /* TYMED_NULL with pUnkForRelease */
798 Test_Unknown.refs = 1;
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);
808 med.tymed = TYMED_NULL;
809 U(med).pstg = NULL;
810 med.pUnkForRelease = unk;
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);
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");
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;
829 Test_Unknown2.refs = 1;
830 med2.tymed = TYMED_NULL;
831 U(med2).pstm = NULL;
832 med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
834 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
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);
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);
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);
852 ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs);
854 HeapFree(GetProcessHeap(), 0, expect_buffer);
856 /* TYMED_ISTREAM with pUnkForRelease */
858 Test_Unknown.refs = 1;
859 Test_Stream.refs = 1;
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);
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);
875 med.tymed = TYMED_ISTREAM;
876 U(med).pstm = stm;
877 med.pUnkForRelease = unk;
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);
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");
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;
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;
904 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
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);
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);
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);
924 ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs);
925 ok(Test_Stream.refs == 1, "got %d\n", Test_Stream.refs);
927 HeapFree(GetProcessHeap(), 0, expect_buffer);
929 /* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */
931 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
932 expect_size = 3 * sizeof(DWORD);
934 med.tymed = TYMED_ISTREAM;
935 U(med).pstm = NULL;
936 med.pUnkForRelease = NULL;
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);
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));
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;
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;
962 STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
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);
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);
975 static void test_marshal_STGMEDIUM(void)
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);
988 static void test_marshal_SNB(void)
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;
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);
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);
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);
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);
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);
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);
1031 /* block with actual data */
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);
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);
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);
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));
1064 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1066 g_expect_user_alloc = TRUE;
1067 snb2 = NULL;
1068 SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
1069 g_expect_user_alloc = FALSE;
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);
1078 HeapFree(GetProcessHeap(), 0, buffer);
1079 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1081 g_expect_user_free = TRUE;
1082 SNB_UserFree(&umcb.Flags, &snb2);
1083 g_expect_user_free = FALSE;
1085 HeapFree(GetProcessHeap(), 0, src);
1088 static void test_marshal_HDC(void)
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;
1095 wireHDC wirehdc;
1096 ULONG size;
1098 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1099 size = HDC_UserSize(&umcb.Flags, 0, &hdc);
1100 ok(size == sizeof(*wirehdc), "Wrong size %d\n", size);
1102 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1103 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1104 HDC_UserMarshal(&umcb.Flags, buffer, &hdc);
1105 wirehdc = (wireHDC)buffer;
1106 ok(wirehdc->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehdc->fContext);
1107 ok(wirehdc->u.hInproc == (LONG_PTR)hdc, "Marshaled value should be %p instead of %x\n", hdc, wirehdc->u.hRemote);
1109 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1110 HDC_UserUnmarshal(&umcb.Flags, buffer, &hdc2);
1111 ok(hdc == hdc2, "Didn't unmarshal properly\n");
1112 HeapFree(GetProcessHeap(), 0, buffer);
1114 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1115 HDC_UserFree(&umcb.Flags, &hdc2);
1116 ReleaseDC(0, hdc);
1119 static void test_marshal_HICON(void)
1121 static const BYTE bmp_bits[1024];
1122 MIDL_STUB_MESSAGE stub_msg;
1123 HICON hIcon, hIcon2;
1124 USER_MARSHAL_CB umcb;
1125 RPC_MESSAGE rpc_msg;
1126 unsigned char *buffer;
1127 wireHICON wirehicon;
1128 ULONG size;
1130 hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
1131 ok(hIcon != 0, "CreateIcon failed\n");
1133 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1134 size = HICON_UserSize(&umcb.Flags, 0, &hIcon);
1135 ok(size == sizeof(*wirehicon), "Wrong size %d\n", size);
1137 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1138 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1139 HICON_UserMarshal(&umcb.Flags, buffer, &hIcon);
1140 wirehicon = (wireHICON)buffer;
1141 ok(wirehicon->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehicon->fContext);
1142 ok(wirehicon->u.hInproc == (LONG_PTR)hIcon, "Marshaled value should be %p instead of %x\n", hIcon, wirehicon->u.hRemote);
1144 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1145 HICON_UserUnmarshal(&umcb.Flags, buffer, &hIcon2);
1146 ok(hIcon == hIcon2, "Didn't unmarshal properly\n");
1147 HeapFree(GetProcessHeap(), 0, buffer);
1149 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1150 HICON_UserFree(&umcb.Flags, &hIcon2);
1151 DestroyIcon(hIcon);
1154 static void test_marshal_HBRUSH(void)
1156 MIDL_STUB_MESSAGE stub_msg;
1157 HBRUSH hBrush, hBrush2;
1158 USER_MARSHAL_CB umcb;
1159 RPC_MESSAGE rpc_msg;
1160 unsigned char *buffer;
1161 LOGBRUSH logbrush;
1162 wireHBRUSH wirehbrush;
1163 ULONG size;
1165 logbrush.lbStyle = BS_SOLID;
1166 logbrush.lbColor = RGB(0, 0, 0);
1167 logbrush.lbHatch = 0;
1169 hBrush = CreateBrushIndirect(&logbrush);
1170 ok(hBrush != 0, "CreateBrushIndirect failed\n");
1172 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1173 size = HBRUSH_UserSize(&umcb.Flags, 0, &hBrush);
1174 ok(size == sizeof(*wirehbrush), "Wrong size %d\n", size);
1176 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1177 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1178 HBRUSH_UserMarshal(&umcb.Flags, buffer, &hBrush);
1179 wirehbrush = (wireHBRUSH)buffer;
1180 ok(wirehbrush->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehbrush->fContext);
1181 ok(wirehbrush->u.hInproc == (LONG_PTR)hBrush, "Marshaled value should be %p instead of %x\n", hBrush, wirehbrush->u.hRemote);
1183 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1184 HBRUSH_UserUnmarshal(&umcb.Flags, buffer, &hBrush2);
1185 ok(hBrush == hBrush2, "Didn't unmarshal properly\n");
1186 HeapFree(GetProcessHeap(), 0, buffer);
1188 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1189 HBRUSH_UserFree(&umcb.Flags, &hBrush2);
1190 DeleteObject(hBrush);
1193 struct obj
1195 IDataObject IDataObject_iface;
1198 static HRESULT WINAPI obj_QueryInterface(IDataObject *iface, REFIID iid, void **obj)
1200 *obj = NULL;
1202 if (IsEqualGUID(iid, &IID_IUnknown) ||
1203 IsEqualGUID(iid, &IID_IDataObject))
1204 *obj = iface;
1206 if (*obj)
1208 IDataObject_AddRef(iface);
1209 return S_OK;
1212 return E_NOINTERFACE;
1215 static ULONG WINAPI obj_AddRef(IDataObject *iface)
1217 return 2;
1220 static ULONG WINAPI obj_Release(IDataObject *iface)
1222 return 1;
1225 static HRESULT WINAPI obj_DO_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1226 STGMEDIUM *med)
1228 ok( med->pUnkForRelease == NULL, "got %p\n", med->pUnkForRelease );
1230 if (fmt->cfFormat == 2)
1232 IStream_Release(U(med)->pstm);
1233 U(med)->pstm = &Test_Stream2.IStream_iface;
1236 return S_OK;
1239 static const IDataObjectVtbl obj_data_object_vtbl =
1241 obj_QueryInterface,
1242 obj_AddRef,
1243 obj_Release,
1244 NULL, /* GetData */
1245 obj_DO_GetDataHere,
1246 NULL, /* QueryGetData */
1247 NULL, /* GetCanonicalFormatEtc */
1248 NULL, /* SetData */
1249 NULL, /* EnumFormatEtc */
1250 NULL, /* DAdvise */
1251 NULL, /* DUnadvise */
1252 NULL /* EnumDAdvise */
1255 static struct obj obj =
1257 {&obj_data_object_vtbl}
1260 static void test_GetDataHere_Proxy(void)
1262 HRESULT hr;
1263 IStream *stm;
1264 HANDLE thread;
1265 DWORD tid;
1266 static const LARGE_INTEGER zero;
1267 IDataObject *data;
1268 FORMATETC fmt;
1269 STGMEDIUM med;
1271 hr = CreateStreamOnHGlobal( NULL, TRUE, &stm );
1272 ok( hr == S_OK, "got %08x\n", hr );
1273 tid = start_host_object2( stm, &IID_IDataObject, (IUnknown *)&obj.IDataObject_iface, MSHLFLAGS_NORMAL, NULL, &thread );
1275 IStream_Seek( stm, zero, STREAM_SEEK_SET, NULL );
1276 hr = CoUnmarshalInterface( stm, &IID_IDataObject, (void **)&data );
1277 ok( hr == S_OK, "got %08x\n", hr );
1278 IStream_Release( stm );
1280 Test_Stream.refs = 1;
1281 Test_Stream2.refs = 1;
1282 Test_Unknown.refs = 1;
1284 fmt.cfFormat = 1;
1285 fmt.ptd = NULL;
1286 fmt.dwAspect = DVASPECT_CONTENT;
1287 fmt.lindex = -1;
1288 U(med).pstm = NULL;
1289 med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1291 fmt.tymed = med.tymed = TYMED_NULL;
1292 hr = IDataObject_GetDataHere( data, &fmt, &med );
1293 ok( hr == DV_E_TYMED, "got %08x\n", hr );
1295 for (fmt.tymed = TYMED_HGLOBAL; fmt.tymed <= TYMED_ENHMF; fmt.tymed <<= 1)
1297 med.tymed = fmt.tymed;
1298 hr = IDataObject_GetDataHere( data, &fmt, &med );
1299 ok( hr == (fmt.tymed <= TYMED_ISTORAGE ? S_OK : DV_E_TYMED), "got %08x for tymed %d\n", hr, fmt.tymed );
1300 ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
1303 fmt.tymed = TYMED_ISTREAM;
1304 med.tymed = TYMED_ISTORAGE;
1305 hr = IDataObject_GetDataHere( data, &fmt, &med );
1306 ok( hr == DV_E_TYMED, "got %08x\n", hr );
1308 fmt.tymed = med.tymed = TYMED_ISTREAM;
1309 U(med).pstm = &Test_Stream.IStream_iface;
1310 med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1312 hr = IDataObject_GetDataHere( data, &fmt, &med );
1313 ok( hr == S_OK, "got %08x\n", hr );
1315 ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
1316 ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" );
1318 ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs );
1319 ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
1321 fmt.cfFormat = 2;
1322 fmt.tymed = med.tymed = TYMED_ISTREAM;
1323 U(med).pstm = &Test_Stream.IStream_iface;
1324 med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1326 hr = IDataObject_GetDataHere( data, &fmt, &med );
1327 ok( hr == S_OK, "got %08x\n", hr );
1329 ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
1330 ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" );
1332 ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs );
1333 ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
1334 ok( Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs );
1336 IDataObject_Release( data );
1337 end_host_object( tid, thread );
1340 START_TEST(usrmarshal)
1342 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1344 test_marshal_CLIPFORMAT();
1345 test_marshal_HWND();
1346 test_marshal_HGLOBAL();
1347 test_marshal_HENHMETAFILE();
1348 test_marshal_HMETAFILE();
1349 test_marshal_HMETAFILEPICT();
1350 test_marshal_WdtpInterfacePointer();
1351 test_marshal_STGMEDIUM();
1352 test_marshal_SNB();
1353 test_marshal_HDC();
1354 test_marshal_HICON();
1355 test_marshal_HBRUSH();
1357 test_GetDataHere_Proxy();
1359 CoUninitialize();