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 WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
33 //#include "objbase.h"
36 #include <wine/test.h>
38 ULONG __RPC_USER
HMETAFILE_UserSize(ULONG
*, ULONG
, HMETAFILE
*);
39 unsigned char * __RPC_USER
HMETAFILE_UserMarshal(ULONG
*, unsigned char *, HMETAFILE
*);
40 unsigned char * __RPC_USER
HMETAFILE_UserUnmarshal(ULONG
*, unsigned char *, HMETAFILE
*);
41 void __RPC_USER
HMETAFILE_UserFree(ULONG
*, HMETAFILE
*);
43 ULONG __RPC_USER
HENHMETAFILE_UserSize(ULONG
*, ULONG
, HENHMETAFILE
*);
44 unsigned char * __RPC_USER
HENHMETAFILE_UserMarshal (ULONG
*, unsigned char *, HENHMETAFILE
*);
45 unsigned char * __RPC_USER
HENHMETAFILE_UserUnmarshal(ULONG
*, unsigned char *, HENHMETAFILE
*);
46 void __RPC_USER
HENHMETAFILE_UserFree(ULONG
*, HENHMETAFILE
*);
48 ULONG __RPC_USER
HMETAFILEPICT_UserSize(ULONG
*, ULONG
, HMETAFILEPICT
*);
49 unsigned char * __RPC_USER
HMETAFILEPICT_UserMarshal (ULONG
*, unsigned char *, HMETAFILEPICT
*);
50 unsigned char * __RPC_USER
HMETAFILEPICT_UserUnmarshal(ULONG
*, unsigned char *, HMETAFILEPICT
*);
51 void __RPC_USER
HMETAFILEPICT_UserFree(ULONG
*, HMETAFILEPICT
*);
53 ULONG __RPC_USER
HBRUSH_UserSize(ULONG
*, ULONG
, HBRUSH
*);
54 unsigned char * __RPC_USER
HBRUSH_UserMarshal(ULONG
*, unsigned char *, HBRUSH
*);
55 unsigned char * __RPC_USER
HBRUSH_UserUnmarshal(ULONG
*, unsigned char *, HBRUSH
*);
56 void __RPC_USER
HBRUSH_UserFree(ULONG
*, HBRUSH
*);
58 static BOOL g_expect_user_alloc
;
59 static void * WINAPI
user_allocate(SIZE_T size
)
61 ok(g_expect_user_alloc
, "unexpected user_allocate call\n");
62 return CoTaskMemAlloc(size
);
65 static BOOL g_expect_user_free
;
66 static void WINAPI
user_free(void *p
)
68 ok(g_expect_user_free
, "unexpected user_free call\n");
72 static void init_user_marshal_cb(USER_MARSHAL_CB
*umcb
,
73 PMIDL_STUB_MESSAGE stub_msg
,
74 PRPC_MESSAGE rpc_msg
, unsigned char *buffer
,
75 unsigned int size
, MSHCTX context
)
77 memset(rpc_msg
, 0, sizeof(*rpc_msg
));
78 rpc_msg
->Buffer
= buffer
;
79 rpc_msg
->BufferLength
= size
;
81 memset(stub_msg
, 0, sizeof(*stub_msg
));
82 stub_msg
->RpcMsg
= rpc_msg
;
83 stub_msg
->Buffer
= buffer
;
84 stub_msg
->pfnAllocate
= user_allocate
;
85 stub_msg
->pfnFree
= user_free
;
87 memset(umcb
, 0, sizeof(*umcb
));
88 umcb
->Flags
= MAKELONG(context
, NDR_LOCAL_DATA_REPRESENTATION
);
89 umcb
->pStubMsg
= stub_msg
;
90 umcb
->Signature
= USER_MARSHAL_CB_SIGNATURE
;
91 umcb
->CBType
= buffer
? USER_MARSHAL_CB_UNMARSHALL
: USER_MARSHAL_CB_BUFFER_SIZE
;
94 #define RELEASEMARSHALDATA WM_USER
96 struct host_object_data
101 MSHLFLAGS marshal_flags
;
102 HANDLE marshal_event
;
103 IMessageFilter
*filter
;
106 static DWORD CALLBACK
host_object_proc(LPVOID p
)
108 struct host_object_data
*data
= p
;
112 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
116 IMessageFilter
* prev_filter
= NULL
;
117 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
118 if (prev_filter
) IMessageFilter_Release(prev_filter
);
119 ok(hr
== S_OK
, "got %08x\n", hr
);
122 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
123 ok(hr
== S_OK
, "got %08x\n", hr
);
125 /* force the message queue to be created before signaling parent thread */
126 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
128 SetEvent(data
->marshal_event
);
130 while (GetMessageA(&msg
, NULL
, 0, 0))
132 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
134 CoReleaseMarshalData(data
->stream
);
135 SetEvent((HANDLE
)msg
.lParam
);
138 DispatchMessageA(&msg
);
141 HeapFree(GetProcessHeap(), 0, data
);
148 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
151 HANDLE marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
152 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
154 data
->stream
= stream
;
156 data
->object
= object
;
157 data
->marshal_flags
= marshal_flags
;
158 data
->marshal_event
= marshal_event
;
159 data
->filter
= filter
;
161 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
163 /* wait for marshaling to complete before returning */
164 ok( !WaitForSingleObject(marshal_event
, 10000), "wait timed out\n" );
165 CloseHandle(marshal_event
);
170 static void end_host_object(DWORD tid
, HANDLE thread
)
172 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
173 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
174 /* be careful of races - don't return until hosting thread has terminated */
175 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
179 static const char cf_marshaled
[] =
191 static void test_marshal_CLIPFORMAT(void)
193 USER_MARSHAL_CB umcb
;
194 MIDL_STUB_MESSAGE stub_msg
;
196 unsigned char *buffer
;
198 CLIPFORMAT cf
= RegisterClipboardFormatA("MyFormat");
201 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
202 size
= CLIPFORMAT_UserSize(&umcb
.Flags
, 0, &cf
);
203 ok(size
== 8 + sizeof(cf_marshaled
) ||
204 broken(size
== 12 + sizeof(cf_marshaled
)) || /* win64 adds 4 extra (unused) bytes */
205 broken(size
== 8 + sizeof(cf_marshaled
) - 2), /* win9x and winnt don't include the '\0' */
206 "CLIPFORMAT: Wrong size %d\n", size
);
208 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
209 memset( buffer
, 0xcc, size
);
210 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
211 CLIPFORMAT_UserMarshal(&umcb
.Flags
, buffer
, &cf
);
212 ok(*(LONG
*)(buffer
+ 0) == WDT_REMOTE_CALL
, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(LONG
*)(buffer
+ 0));
213 ok(*(DWORD
*)(buffer
+ 4) == cf
, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04x\n", cf
, *(DWORD
*)(buffer
+ 4));
214 ok(!memcmp(buffer
+ 8, cf_marshaled
, min( sizeof(cf_marshaled
), size
-8 )), "Marshaled data differs\n");
215 if (size
> sizeof(cf_marshaled
) + 8) /* make sure the extra bytes are not used */
216 for (i
= sizeof(cf_marshaled
) + 8; i
< size
; i
++)
217 ok( buffer
[i
] == 0xcc, "buffer offset %u has been set to %x\n", i
, buffer
[i
] );
219 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
220 CLIPFORMAT_UserUnmarshal(&umcb
.Flags
, buffer
, &cf2
);
221 ok(cf
== cf2
, "CLIPFORMAT: Didn't unmarshal properly\n");
222 HeapFree(GetProcessHeap(), 0, buffer
);
224 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
225 CLIPFORMAT_UserFree(&umcb
.Flags
, &cf2
);
228 static void test_marshal_HWND(void)
230 USER_MARSHAL_CB umcb
;
231 MIDL_STUB_MESSAGE stub_msg
;
233 unsigned char *buffer
;
235 HWND hwnd
= GetDesktopWindow();
239 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
240 size
= HWND_UserSize(&umcb
.Flags
, 0, &hwnd
);
241 ok(size
== sizeof(*wirehwnd
), "Wrong size %d\n", size
);
243 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
244 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
245 HWND_UserMarshal(&umcb
.Flags
, buffer
, &hwnd
);
246 wirehwnd
= (wireHWND
)buffer
;
247 ok(wirehwnd
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehwnd
->fContext
);
248 ok(wirehwnd
->u
.hInproc
== (LONG_PTR
)hwnd
, "Marshaled value should be %p instead of %x\n", hwnd
, wirehwnd
->u
.hRemote
);
250 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
251 HWND_UserUnmarshal(&umcb
.Flags
, buffer
, &hwnd2
);
252 ok(hwnd
== hwnd2
, "Didn't unmarshal properly\n");
253 HeapFree(GetProcessHeap(), 0, buffer
);
255 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
256 HWND_UserFree(&umcb
.Flags
, &hwnd2
);
259 static void test_marshal_HGLOBAL(void)
261 USER_MARSHAL_CB umcb
;
262 MIDL_STUB_MESSAGE stub_msg
;
264 unsigned char *buffer
;
265 ULONG size
, block_size
;
268 unsigned char *wirehglobal
;
272 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
273 size
= HGLOBAL_UserSize(&umcb
.Flags
, 0, &hglobal
);
274 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
275 * here - Wine doesn't have to emulate that */
276 ok((size
== 8) || broken(size
== 12) || broken(size
== 16), "Size should be 8, instead of %d\n", size
);
277 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
278 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
279 HGLOBAL_UserMarshal(&umcb
.Flags
, buffer
, &hglobal
);
280 wirehglobal
= buffer
;
281 ok(*(ULONG
*)wirehglobal
== WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)wirehglobal
);
282 wirehglobal
+= sizeof(ULONG
);
283 ok(*(ULONG
*)wirehglobal
== 0, "buffer+4 should be HGLOBAL\n");
284 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
286 HGLOBAL_UserUnmarshal(&umcb
.Flags
, buffer
, &hglobal2
);
287 ok(hglobal2
== hglobal
, "Didn't unmarshal properly\n");
288 HeapFree(GetProcessHeap(), 0, buffer
);
289 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
290 HGLOBAL_UserFree(&umcb
.Flags
, &hglobal2
);
293 for(block_size
= 0; block_size
<= 17; block_size
++)
295 ULONG actual_size
, expected_size
;
297 hglobal
= GlobalAlloc(0, block_size
);
298 buffer
= GlobalLock(hglobal
);
299 for (i
= 0; i
< block_size
; i
++)
301 GlobalUnlock(hglobal
);
302 actual_size
= GlobalSize(hglobal
);
303 expected_size
= actual_size
+ 5 * sizeof(DWORD
);
304 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
305 size
= HGLOBAL_UserSize(&umcb
.Flags
, 0, &hglobal
);
306 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
307 * here - Wine doesn't have to emulate that */
308 ok(size
== expected_size
||
309 broken(size
== expected_size
+ 4) ||
310 broken(size
== expected_size
+ 8),
311 "%d: got size %d\n", block_size
, size
);
312 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
313 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
314 HGLOBAL_UserMarshal(&umcb
.Flags
, buffer
, &hglobal
);
315 wirehglobal
= buffer
;
316 ok(*(ULONG
*)wirehglobal
== WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)wirehglobal
);
317 wirehglobal
+= sizeof(ULONG
);
318 ok(*(ULONG
*)wirehglobal
== (ULONG
)(ULONG_PTR
)hglobal
, "buffer+0x4 should be HGLOBAL\n");
319 wirehglobal
+= sizeof(ULONG
);
320 ok(*(ULONG
*)wirehglobal
== actual_size
, "%d: buffer+0x8 %08x\n", block_size
, *(ULONG
*)wirehglobal
);
321 wirehglobal
+= sizeof(ULONG
);
322 ok(*(ULONG
*)wirehglobal
== (ULONG
)(ULONG_PTR
)hglobal
, "buffer+0xc should be HGLOBAL\n");
323 wirehglobal
+= sizeof(ULONG
);
324 ok(*(ULONG
*)wirehglobal
== actual_size
, "%d: buffer+0x10 %08x\n", block_size
, *(ULONG
*)wirehglobal
);
325 wirehglobal
+= sizeof(ULONG
);
326 for (i
= 0; i
< block_size
; i
++)
327 ok(wirehglobal
[i
] == i
, "buffer+0x%x should be %d\n", 0x10 + i
, i
);
329 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
331 HGLOBAL_UserUnmarshal(&umcb
.Flags
, buffer
, &hglobal2
);
332 ok(hglobal2
!= NULL
, "Didn't unmarshal properly\n");
333 HeapFree(GetProcessHeap(), 0, buffer
);
334 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
335 HGLOBAL_UserFree(&umcb
.Flags
, &hglobal2
);
340 static HENHMETAFILE
create_emf(void)
342 const RECT rect
= {0, 0, 100, 100};
343 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Marshaling Test\0Test\0\0");
344 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
345 return CloseEnhMetaFile(hdc
);
348 static void test_marshal_HENHMETAFILE(void)
350 USER_MARSHAL_CB umcb
;
351 MIDL_STUB_MESSAGE stub_msg
;
353 unsigned char *buffer
;
356 HENHMETAFILE hemf2
= NULL
;
357 unsigned char *wirehemf
;
361 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
362 size
= HENHMETAFILE_UserSize(&umcb
.Flags
, 0, &hemf
);
363 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
364 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
365 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
366 HENHMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hemf
);
368 ok(*(DWORD
*)wirehemf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehemf
);
369 wirehemf
+= sizeof(DWORD
);
370 ok(*(DWORD
*)wirehemf
== (DWORD
)(DWORD_PTR
)hemf
, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD
*)wirehemf
);
371 wirehemf
+= sizeof(DWORD
);
372 ok(*(DWORD
*)wirehemf
== (size
- 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehemf
);
373 wirehemf
+= sizeof(DWORD
);
374 ok(*(DWORD
*)wirehemf
== (size
- 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehemf
);
375 wirehemf
+= sizeof(DWORD
);
376 ok(*(DWORD
*)wirehemf
== EMR_HEADER
, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD
*)wirehemf
);
377 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
380 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
381 HENHMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hemf2
);
382 ok(hemf2
!= NULL
, "HENHMETAFILE didn't unmarshal\n");
383 HeapFree(GetProcessHeap(), 0, buffer
);
384 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
385 HENHMETAFILE_UserFree(&umcb
.Flags
, &hemf2
);
386 DeleteEnhMetaFile(hemf
);
391 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
392 size
= HENHMETAFILE_UserSize(&umcb
.Flags
, 0, &hemf
);
393 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
394 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
395 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
396 HENHMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hemf
);
398 ok(*(DWORD
*)wirehemf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehemf
);
399 wirehemf
+= sizeof(DWORD
);
400 ok(*(DWORD
*)wirehemf
== (DWORD
)(DWORD_PTR
)hemf
, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD
*)wirehemf
);
402 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
403 HENHMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hemf2
);
404 ok(hemf2
== NULL
, "NULL HENHMETAFILE didn't unmarshal\n");
405 HeapFree(GetProcessHeap(), 0, buffer
);
406 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
407 HENHMETAFILE_UserFree(&umcb
.Flags
, &hemf2
);
410 static HMETAFILE
create_mf(void)
412 RECT rect
= {0, 0, 100, 100};
413 HDC hdc
= CreateMetaFileA(NULL
);
414 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
415 return CloseMetaFile(hdc
);
418 static void test_marshal_HMETAFILE(void)
420 USER_MARSHAL_CB umcb
;
421 MIDL_STUB_MESSAGE stub_msg
;
423 unsigned char *buffer
;
426 HMETAFILE hmf2
= NULL
;
427 unsigned char *wirehmf
;
431 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
432 size
= HMETAFILE_UserSize(&umcb
.Flags
, 0, &hmf
);
433 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
434 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
435 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
436 HMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hmf
);
438 ok(*(DWORD
*)wirehmf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmf
);
439 wirehmf
+= sizeof(DWORD
);
440 ok(*(DWORD
*)wirehmf
== (DWORD
)(DWORD_PTR
)hmf
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmf
);
441 wirehmf
+= sizeof(DWORD
);
442 ok(*(DWORD
*)wirehmf
== (size
- 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
443 wirehmf
+= sizeof(DWORD
);
444 ok(*(DWORD
*)wirehmf
== (size
- 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
445 wirehmf
+= sizeof(DWORD
);
446 ok(*(WORD
*)wirehmf
== 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
447 wirehmf
+= sizeof(DWORD
);
448 /* ... rest of data not tested - refer to tests for GetMetaFileBits
451 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
452 HMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hmf2
);
453 ok(hmf2
!= NULL
, "HMETAFILE didn't unmarshal\n");
454 HeapFree(GetProcessHeap(), 0, buffer
);
455 HMETAFILE_UserFree(&umcb
.Flags
, &hmf2
);
461 size
= HMETAFILE_UserSize(&umcb
.Flags
, 0, &hmf
);
462 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
463 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
464 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
465 HMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hmf
);
467 ok(*(DWORD
*)wirehmf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmf
);
468 wirehmf
+= sizeof(DWORD
);
469 ok(*(DWORD
*)wirehmf
== (DWORD
)(DWORD_PTR
)hmf
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmf
);
470 wirehmf
+= sizeof(DWORD
);
472 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
473 HMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hmf2
);
474 ok(hmf2
== NULL
, "NULL HMETAFILE didn't unmarshal\n");
475 HeapFree(GetProcessHeap(), 0, buffer
);
476 HMETAFILE_UserFree(&umcb
.Flags
, &hmf2
);
479 #define USER_MARSHAL_PTR_PREFIX \
480 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
481 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
483 static void test_marshal_HMETAFILEPICT(void)
485 USER_MARSHAL_CB umcb
;
486 MIDL_STUB_MESSAGE stub_msg
;
488 unsigned char *buffer
, *buffer_end
;
491 HMETAFILEPICT hmfp2
= NULL
;
493 unsigned char *wirehmfp
;
495 hmfp
= GlobalAlloc(GMEM_MOVEABLE
, sizeof(*pmfp
));
496 pmfp
= GlobalLock(hmfp
);
497 pmfp
->mm
= MM_ISOTROPIC
;
500 pmfp
->hMF
= create_mf();
503 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
504 size
= HMETAFILEPICT_UserSize(&umcb
.Flags
, 0, &hmfp
);
505 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
506 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
507 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
508 buffer_end
= HMETAFILEPICT_UserMarshal(&umcb
.Flags
, buffer
, &hmfp
);
510 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
511 wirehmfp
+= sizeof(DWORD
);
512 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)hmfp
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
513 wirehmfp
+= sizeof(DWORD
);
514 ok(*(DWORD
*)wirehmfp
== MM_ISOTROPIC
, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
515 wirehmfp
+= sizeof(DWORD
);
516 ok(*(DWORD
*)wirehmfp
== 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
517 wirehmfp
+= sizeof(DWORD
);
518 ok(*(DWORD
*)wirehmfp
== 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
519 wirehmfp
+= sizeof(DWORD
);
520 ok(*(DWORD
*)wirehmfp
== USER_MARSHAL_PTR_PREFIX
, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
521 wirehmfp
+= sizeof(DWORD
);
522 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
523 wirehmfp
+= sizeof(DWORD
);
524 pmfp
= GlobalLock(hmfp
);
525 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)pmfp
->hMF
, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
527 wirehmfp
+= sizeof(DWORD
);
528 /* Note use (buffer_end - buffer) instead of size here, because size is an
529 * overestimate with native */
530 ok(*(DWORD
*)wirehmfp
== (buffer_end
- buffer
- 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
531 wirehmfp
+= sizeof(DWORD
);
532 ok(*(DWORD
*)wirehmfp
== (buffer_end
- buffer
- 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
533 wirehmfp
+= sizeof(DWORD
);
534 ok(*(WORD
*)wirehmfp
== 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
535 /* ... rest of data not tested - refer to tests for GetMetaFileBits
538 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
539 HMETAFILEPICT_UserUnmarshal(&umcb
.Flags
, buffer
, &hmfp2
);
540 ok(hmfp2
!= NULL
, "HMETAFILEPICT didn't unmarshal\n");
541 HeapFree(GetProcessHeap(), 0, buffer
);
542 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
543 HMETAFILEPICT_UserFree(&umcb
.Flags
, &hmfp2
);
544 pmfp
= GlobalLock(hmfp
);
545 DeleteMetaFile(pmfp
->hMF
);
552 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
553 size
= HMETAFILEPICT_UserSize(&umcb
.Flags
, 0, &hmfp
);
554 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
555 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
556 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
557 HMETAFILEPICT_UserMarshal(&umcb
.Flags
, buffer
, &hmfp
);
559 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
560 wirehmfp
+= sizeof(DWORD
);
561 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)hmfp
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
562 wirehmfp
+= sizeof(DWORD
);
565 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
566 HMETAFILEPICT_UserUnmarshal(&umcb
.Flags
, buffer
, &hmfp2
);
567 ok(hmfp2
== NULL
, "NULL HMETAFILE didn't unmarshal\n");
568 HeapFree(GetProcessHeap(), 0, buffer
);
569 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
570 HMETAFILEPICT_UserFree(&umcb
.Flags
, &hmfp2
);
575 IUnknown IUnknown_iface
;
579 static inline TestUnknown
*impl_from_IUnknown(IUnknown
*iface
)
581 return CONTAINING_RECORD(iface
, TestUnknown
, IUnknown_iface
);
584 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
589 if (ppvObj
== NULL
) return E_POINTER
;
591 if (IsEqualGUID(riid
, &IID_IUnknown
))
594 IUnknown_AddRef(iface
);
599 return E_NOINTERFACE
;
602 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
604 TestUnknown
*This
= impl_from_IUnknown(iface
);
605 return InterlockedIncrement(&This
->refs
);
608 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
610 TestUnknown
*This
= impl_from_IUnknown(iface
);
611 return InterlockedDecrement(&This
->refs
);
614 static const IUnknownVtbl TestUnknown_Vtbl
=
616 Test_IUnknown_QueryInterface
,
617 Test_IUnknown_AddRef
,
618 Test_IUnknown_Release
,
623 IStream IStream_iface
;
627 static inline struct test_stream
*impl_from_IStream(IStream
*iface
)
629 return CONTAINING_RECORD(iface
, struct test_stream
, IStream_iface
);
632 static HRESULT WINAPI
Test_IStream_QueryInterface(IStream
*iface
,
633 REFIID riid
, LPVOID
*ppvObj
)
635 if (ppvObj
== NULL
) return E_POINTER
;
637 if (IsEqualIID(riid
, &IID_IUnknown
) ||
638 IsEqualIID(riid
, &IID_IStream
))
641 IStream_AddRef(iface
);
646 return E_NOINTERFACE
;
649 static ULONG WINAPI
Test_IStream_AddRef(IStream
*iface
)
651 struct test_stream
*This
= impl_from_IStream(iface
);
652 return InterlockedIncrement(&This
->refs
);
655 static ULONG WINAPI
Test_IStream_Release(IStream
*iface
)
657 struct test_stream
*This
= impl_from_IStream(iface
);
658 return InterlockedDecrement(&This
->refs
);
661 static const IStreamVtbl TestStream_Vtbl
=
663 Test_IStream_QueryInterface
,
666 /* the rest can be NULLs */
669 static TestUnknown Test_Unknown
= { {&TestUnknown_Vtbl
}, 1 };
670 static TestUnknown Test_Unknown2
= { {&TestUnknown_Vtbl
}, 1 };
671 static struct test_stream Test_Stream
= { {&TestStream_Vtbl
}, 1 };
672 static struct test_stream Test_Stream2
= { {&TestStream_Vtbl
}, 1 };
674 ULONG __RPC_USER
WdtpInterfacePointer_UserSize(ULONG
*, ULONG
, ULONG
, IUnknown
*, REFIID
);
675 unsigned char * __RPC_USER
WdtpInterfacePointer_UserMarshal(ULONG
*, ULONG
, unsigned char *, IUnknown
*, REFIID
);
676 unsigned char * __RPC_USER
WdtpInterfacePointer_UserUnmarshal(ULONG
*, unsigned char *, IUnknown
**, REFIID
);
678 static void marshal_WdtpInterfacePointer(DWORD umcb_ctx
, DWORD ctx
, BOOL client
, BOOL in
, BOOL out
)
680 USER_MARSHAL_CB umcb
;
681 MIDL_STUB_MESSAGE stub_msg
;
683 unsigned char *buffer
, *buffer_end
;
687 unsigned char *wireip
;
688 HGLOBAL h
= GlobalAlloc(GMEM_MOVEABLE
, 0);
695 /* shows that the WdtpInterfacePointer functions don't marshal anything for
696 * NULL pointers, so code using these functions must handle that case
700 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, umcb_ctx
);
701 size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, ctx
, 0, unk
, &IID_IUnknown
);
702 ok(size
== 0, "size should be 0 bytes, not %d\n", size
);
703 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
704 buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, ctx
, buffer
, unk
, &IID_IUnknown
);
705 ok(buffer_end
== buffer
, "buffer_end %p buffer %p\n", buffer_end
, buffer
);
706 HeapFree(GetProcessHeap(), 0, buffer
);
708 /* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then
709 the result of CoMarshalInterface called with the LOWORD of the ctx */
711 unk
= &Test_Unknown
.IUnknown_iface
;
712 Test_Unknown
.refs
= 1;
714 CreateStreamOnHGlobal(h
, TRUE
, &stm
);
715 CoMarshalInterface(stm
, &IID_IUnknown
, unk
, LOWORD(ctx
), NULL
, MSHLFLAGS_NORMAL
);
717 IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &pos
);
718 marshal_size
= pos
.u
.LowPart
;
719 marshal_data
= GlobalLock(h
);
721 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
723 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, umcb_ctx
);
724 size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, ctx
, 0, unk
, &IID_IUnknown
);
725 ok(size
>= marshal_size
+ 2 * sizeof(DWORD
), "marshal size %x got %x\n", marshal_size
, size
);
726 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
727 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, umcb_ctx
);
728 buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, ctx
, buffer
, unk
, &IID_IUnknown
);
730 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
733 ok(buffer_end
== buffer
+ marshal_size
+ 2 * sizeof(DWORD
), "buffer_end %p buffer %p\n", buffer_end
, buffer
);
735 ok(*(DWORD
*)wireip
== marshal_size
, "wireip + 0x0 should be %x instead of %x\n", marshal_size
, *(DWORD
*)wireip
);
736 wireip
+= sizeof(DWORD
);
737 ok(*(DWORD
*)wireip
== marshal_size
, "wireip + 0x4 should be %x instead of %x\n", marshal_size
, *(DWORD
*)wireip
);
738 wireip
+= sizeof(DWORD
);
740 ok(!memcmp(marshal_data
, wireip
, marshal_size
), "buffer mismatch\n");
743 IStream_Seek(stm
, zero
, STREAM_SEEK_SET
, NULL
);
744 CoReleaseMarshalData(stm
);
745 IStream_Release(stm
);
747 Test_Unknown2
.refs
= 1;
748 unk2
= &Test_Unknown2
.IUnknown_iface
;
749 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, umcb_ctx
);
750 umcb
.pStubMsg
->IsClient
= client
;
751 umcb
.pStubMsg
->fIsIn
= in
;
752 umcb
.pStubMsg
->fIsOut
= out
;
754 WdtpInterfacePointer_UserUnmarshal(&umcb
.Flags
, buffer
, &unk2
, &IID_IUnknown
);
755 ok(unk2
!= NULL
, "IUnknown object didn't unmarshal properly\n");
756 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
757 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
758 HeapFree(GetProcessHeap(), 0, buffer
);
759 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_INPROC
);
760 IUnknown_Release(unk2
);
763 static void test_marshal_WdtpInterfacePointer(void)
766 * There are two places where we can pass the marshalling ctx: as
767 * part of the umcb and as a separate flag. The loword of that
768 * separate flag field is what matters.
771 /* All three are marshalled as inproc */
772 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_INPROC
, 0,0,0);
773 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE
, MSHCTX_INPROC
,0,0,0);
774 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MAKELONG(MSHCTX_INPROC
, 0xffff),0,0,0);
776 /* All three are marshalled as remote */
777 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,0,0);
778 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE
, MSHCTX_DIFFERENTMACHINE
,0,0,0);
779 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MAKELONG(MSHCTX_DIFFERENTMACHINE
, 0xffff),0,0,0);
781 /* Test different combinations of client, in and out */
782 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,0,1);
783 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,1,0);
784 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,1,1);
785 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,0,0);
786 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,0,1);
787 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,1,0);
788 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,1,1);
791 static void marshal_STGMEDIUM(BOOL client
, BOOL in
, BOOL out
)
793 USER_MARSHAL_CB umcb
;
794 MIDL_STUB_MESSAGE stub_msg
;
796 unsigned char *buffer
, *buffer_end
, *expect_buffer
, *expect_buffer_end
;
797 ULONG size
, expect_size
;
799 IUnknown
*unk
= &Test_Unknown
.IUnknown_iface
;
800 IStream
*stm
= &Test_Stream
.IStream_iface
;
802 /* TYMED_NULL with pUnkForRelease */
804 Test_Unknown
.refs
= 1;
806 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
807 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, 2 * sizeof(DWORD
), unk
, &IID_IUnknown
);
808 expect_buffer
= HeapAlloc(GetProcessHeap(), 0, expect_size
);
809 *(DWORD
*)expect_buffer
= TYMED_NULL
;
810 *((DWORD
*)expect_buffer
+ 1) = 0xdeadbeef;
811 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
812 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer
+ 2 * sizeof(DWORD
), unk
, &IID_IUnknown
);
814 med
.tymed
= TYMED_NULL
;
816 med
.pUnkForRelease
= unk
;
818 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
819 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
820 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
822 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
823 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
824 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
825 ok(buffer_end
- buffer
== expect_buffer_end
- expect_buffer
, "buffer size mismatch\n");
826 ok(*(DWORD
*)buffer
== TYMED_NULL
, "got %08x\n", *(DWORD
*)buffer
);
827 ok(*((DWORD
*)buffer
+1) != 0, "got %08x\n", *((DWORD
*)buffer
+1));
828 ok(!memcmp(buffer
+8, expect_buffer
+ 8, expect_buffer_end
- expect_buffer
- 8), "buffer mismatch\n");
830 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
831 umcb
.pStubMsg
->IsClient
= client
;
832 umcb
.pStubMsg
->fIsIn
= in
;
833 umcb
.pStubMsg
->fIsOut
= out
;
835 Test_Unknown2
.refs
= 1;
836 med2
.tymed
= TYMED_NULL
;
838 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
840 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
842 ok(med2
.tymed
== TYMED_NULL
, "got tymed %x\n", med2
.tymed
);
843 ok(med2
.pUnkForRelease
!= NULL
, "Incorrectly unmarshalled\n");
844 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
846 HeapFree(GetProcessHeap(), 0, buffer
);
847 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
848 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
850 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
851 med2
.tymed
= TYMED_NULL
;
853 med2
.pUnkForRelease
= NULL
;
854 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, expect_buffer
, &med2
);
855 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
856 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
858 ok(Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
860 HeapFree(GetProcessHeap(), 0, expect_buffer
);
862 /* TYMED_ISTREAM with pUnkForRelease */
864 Test_Unknown
.refs
= 1;
865 Test_Stream
.refs
= 1;
867 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
868 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, 3 * sizeof(DWORD
), (IUnknown
*)stm
, &IID_IStream
);
869 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, expect_size
, unk
, &IID_IUnknown
);
871 expect_buffer
= HeapAlloc(GetProcessHeap(), 0, expect_size
);
872 /* There may be a hole between the two interfaces so init the buffer to something */
873 memset(expect_buffer
, 0xcc, expect_size
);
874 *(DWORD
*)expect_buffer
= TYMED_ISTREAM
;
875 *((DWORD
*)expect_buffer
+ 1) = 0xdeadbeef;
876 *((DWORD
*)expect_buffer
+ 2) = 0xcafe;
877 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
878 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer
+ 3 * sizeof(DWORD
), (IUnknown
*)stm
, &IID_IStream
);
879 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer_end
, unk
, &IID_IUnknown
);
881 med
.tymed
= TYMED_ISTREAM
;
883 med
.pUnkForRelease
= unk
;
885 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
886 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
887 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
889 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
890 memset(buffer
, 0xcc, size
);
891 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
892 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
893 ok(buffer_end
- buffer
== expect_buffer_end
- expect_buffer
, "buffer size mismatch\n");
894 ok(*(DWORD
*)buffer
== TYMED_ISTREAM
, "got %08x\n", *(DWORD
*)buffer
);
895 ok(*((DWORD
*)buffer
+1) != 0, "got %08x\n", *((DWORD
*)buffer
+1));
896 ok(*((DWORD
*)buffer
+2) != 0, "got %08x\n", *((DWORD
*)buffer
+2));
897 ok(!memcmp(buffer
+ 12, expect_buffer
+ 12, (buffer_end
- buffer
) - 12), "buffer mismatch\n");
899 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
900 umcb
.pStubMsg
->IsClient
= client
;
901 umcb
.pStubMsg
->fIsIn
= in
;
902 umcb
.pStubMsg
->fIsOut
= out
;
904 Test_Stream2
.refs
= 1;
905 Test_Unknown2
.refs
= 1;
906 med2
.tymed
= TYMED_ISTREAM
;
907 U(med2
).pstm
= &Test_Stream2
.IStream_iface
;
908 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
910 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
912 ok(med2
.tymed
== TYMED_ISTREAM
, "got tymed %x\n", med2
.tymed
);
913 ok(U(med2
).pstm
!= NULL
, "Incorrectly unmarshalled\n");
914 ok(med2
.pUnkForRelease
!= NULL
, "Incorrectly unmarshalled\n");
915 ok(Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
916 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
918 HeapFree(GetProcessHeap(), 0, buffer
);
919 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
920 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
922 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
923 med2
.tymed
= TYMED_NULL
;
925 med2
.pUnkForRelease
= NULL
;
926 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, expect_buffer
, &med2
);
927 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
928 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
930 ok(Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
931 ok(Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
933 HeapFree(GetProcessHeap(), 0, expect_buffer
);
935 /* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */
937 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
938 expect_size
= 3 * sizeof(DWORD
);
940 med
.tymed
= TYMED_ISTREAM
;
942 med
.pUnkForRelease
= NULL
;
944 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
945 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
946 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
948 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
949 memset(buffer
, 0xcc, size
);
950 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
951 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
952 ok(buffer_end
- buffer
== expect_size
, "buffer size mismatch\n");
953 ok(*(DWORD
*)buffer
== TYMED_ISTREAM
, "got %08x\n", *(DWORD
*)buffer
);
954 ok(*((DWORD
*)buffer
+1) == 0, "got %08x\n", *((DWORD
*)buffer
+1));
955 ok(*((DWORD
*)buffer
+2) == 0, "got %08x\n", *((DWORD
*)buffer
+2));
957 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
958 umcb
.pStubMsg
->IsClient
= client
;
959 umcb
.pStubMsg
->fIsIn
= in
;
960 umcb
.pStubMsg
->fIsOut
= out
;
962 Test_Stream2
.refs
= 1;
963 Test_Unknown2
.refs
= 1;
964 med2
.tymed
= TYMED_ISTREAM
;
965 U(med2
).pstm
= &Test_Stream2
.IStream_iface
;
966 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
968 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
970 ok(med2
.tymed
== TYMED_ISTREAM
, "got tymed %x\n", med2
.tymed
);
971 ok(U(med2
).pstm
== NULL
, "Incorrectly unmarshalled\n");
972 ok(med2
.pUnkForRelease
== &Test_Unknown2
.IUnknown_iface
, "Incorrectly unmarshalled\n");
973 ok(Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
974 ok(Test_Unknown2
.refs
== 1, "got %d\n", Test_Unknown2
.refs
);
976 HeapFree(GetProcessHeap(), 0, buffer
);
977 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
978 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
981 static void test_marshal_STGMEDIUM(void)
983 marshal_STGMEDIUM(0, 0, 0);
984 marshal_STGMEDIUM(0, 0, 1);
985 marshal_STGMEDIUM(0, 1, 0);
986 marshal_STGMEDIUM(0, 1, 1);
987 /* For Windows versions post 2003, client side, non-[in,out] STGMEDIUMs get zero-initialised.
988 However since inline stubs don't set fIsIn or fIsOut this behaviour would break
989 ref counting in GetDataHere_Proxy for example, as we'd end up not releasing the original
990 interface. For simplicity we don't test or implement this. */
991 marshal_STGMEDIUM(1, 1, 1);
994 static void test_marshal_SNB(void)
996 static const WCHAR str1W
[] = {'s','t','r','i','n','g','1',0};
997 static const WCHAR str2W
[] = {'s','t','r','2',0};
998 unsigned char *buffer
, *src
, *mbuf
;
999 MIDL_STUB_MESSAGE stub_msg
;
1000 WCHAR
**ptrW
, *dataW
;
1001 USER_MARSHAL_CB umcb
;
1002 RPC_MESSAGE rpc_msg
;
1007 /* 4 bytes alignment */
1009 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1010 size
= SNB_UserSize(&umcb
.Flags
, 3, &snb
);
1011 ok(size
== 16, "Size should be 16, instead of %d\n", size
);
1014 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1015 size
= SNB_UserSize(&umcb
.Flags
, 0, &snb
);
1016 ok(size
== 12, "Size should be 12, instead of %d\n", size
);
1018 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1019 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1020 mbuf
= SNB_UserMarshal(&umcb
.Flags
, buffer
, &snb
);
1021 ok(mbuf
== buffer
+ size
, "got %p, %p\n", mbuf
, buffer
+ size
);
1023 wiresnb
= (RemSNB
*)buffer
;
1024 ok(wiresnb
->ulCntStr
== 0, "got %u\n", wiresnb
->ulCntStr
);
1025 ok(wiresnb
->ulCntChar
== 0, "got %u\n", wiresnb
->ulCntChar
);
1026 ok(*(ULONG
*)wiresnb
->rgString
== 0, "got %u\n", *(ULONG
*)wiresnb
->rgString
);
1029 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1030 SNB_UserUnmarshal(&umcb
.Flags
, buffer
, &snb2
);
1031 ok(snb2
== NULL
, "got %p\n", snb2
);
1033 HeapFree(GetProcessHeap(), 0, buffer
);
1034 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1035 SNB_UserFree(&umcb
.Flags
, &snb2
);
1037 /* block with actual data */
1039 /* allocate source block, n+1 pointers first, then data */
1040 src
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
*)*3 + sizeof(str1W
) + sizeof(str2W
));
1041 ptrW
= (WCHAR
**)src
;
1042 dataW
= *ptrW
= (WCHAR
*)(src
+ 3*sizeof(WCHAR
*));
1044 *ptrW
= (WCHAR
*)(src
+ 3*sizeof(WCHAR
*) + sizeof(str1W
));
1047 lstrcpyW(dataW
, str1W
);
1048 dataW
+= lstrlenW(str1W
) + 1;
1049 lstrcpyW(dataW
, str2W
);
1052 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1053 size
= SNB_UserSize(&umcb
.Flags
, 0, &snb
);
1054 ok(size
== 38, "Size should be 38, instead of %d\n", size
);
1056 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1057 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1058 SNB_UserMarshal(&umcb
.Flags
, buffer
, &snb
);
1060 wiresnb
= (RemSNB
*)buffer
;
1061 ok(wiresnb
->ulCntStr
== 13, "got %u\n", wiresnb
->ulCntStr
);
1062 ok(wiresnb
->ulCntChar
== 2, "got %u\n", wiresnb
->ulCntChar
);
1063 /* payload length is stored one more time, as ULONG */
1064 ok(*(ULONG
*)wiresnb
->rgString
== wiresnb
->ulCntStr
, "got %u\n", *(ULONG
*)wiresnb
->rgString
);
1065 dataW
= &wiresnb
->rgString
[2];
1066 ok(!lstrcmpW(dataW
, str1W
), "marshalled string 0: %s\n", wine_dbgstr_w(dataW
));
1067 dataW
+= sizeof(str1W
)/sizeof(WCHAR
);
1068 ok(!lstrcmpW(dataW
, str2W
), "marshalled string 1: %s\n", wine_dbgstr_w(dataW
));
1070 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1072 g_expect_user_alloc
= TRUE
;
1074 SNB_UserUnmarshal(&umcb
.Flags
, buffer
, &snb2
);
1075 g_expect_user_alloc
= FALSE
;
1078 ok(!lstrcmpW(*ptrW
, str1W
), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW
));
1080 ok(!lstrcmpW(*ptrW
, str2W
), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW
));
1082 ok(*ptrW
== NULL
, "expected terminating NULL ptr, got %p, start %p\n", *ptrW
, snb2
);
1084 HeapFree(GetProcessHeap(), 0, buffer
);
1085 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1087 g_expect_user_free
= TRUE
;
1088 SNB_UserFree(&umcb
.Flags
, &snb2
);
1089 g_expect_user_free
= FALSE
;
1091 HeapFree(GetProcessHeap(), 0, src
);
1094 static void test_marshal_HDC(void)
1096 MIDL_STUB_MESSAGE stub_msg
;
1097 HDC hdc
= GetDC(0), hdc2
;
1098 USER_MARSHAL_CB umcb
;
1099 RPC_MESSAGE rpc_msg
;
1100 unsigned char *buffer
;
1104 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1105 size
= HDC_UserSize(&umcb
.Flags
, 0, &hdc
);
1106 ok(size
== sizeof(*wirehdc
), "Wrong size %d\n", size
);
1108 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1109 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1110 HDC_UserMarshal(&umcb
.Flags
, buffer
, &hdc
);
1111 wirehdc
= (wireHDC
)buffer
;
1112 ok(wirehdc
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehdc
->fContext
);
1113 ok(wirehdc
->u
.hInproc
== (LONG_PTR
)hdc
, "Marshaled value should be %p instead of %x\n", hdc
, wirehdc
->u
.hRemote
);
1115 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1116 HDC_UserUnmarshal(&umcb
.Flags
, buffer
, &hdc2
);
1117 ok(hdc
== hdc2
, "Didn't unmarshal properly\n");
1118 HeapFree(GetProcessHeap(), 0, buffer
);
1120 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1121 HDC_UserFree(&umcb
.Flags
, &hdc2
);
1125 static void test_marshal_HICON(void)
1127 static const BYTE bmp_bits
[1024];
1128 MIDL_STUB_MESSAGE stub_msg
;
1129 HICON hIcon
, hIcon2
;
1130 USER_MARSHAL_CB umcb
;
1131 RPC_MESSAGE rpc_msg
;
1132 unsigned char *buffer
;
1133 wireHICON wirehicon
;
1136 hIcon
= CreateIcon(0, 16, 16, 1, 1, bmp_bits
, bmp_bits
);
1137 ok(hIcon
!= 0, "CreateIcon failed\n");
1139 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1140 size
= HICON_UserSize(&umcb
.Flags
, 0, &hIcon
);
1141 ok(size
== sizeof(*wirehicon
), "Wrong size %d\n", size
);
1143 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1144 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1145 HICON_UserMarshal(&umcb
.Flags
, buffer
, &hIcon
);
1146 wirehicon
= (wireHICON
)buffer
;
1147 ok(wirehicon
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehicon
->fContext
);
1148 ok(wirehicon
->u
.hInproc
== (LONG_PTR
)hIcon
, "Marshaled value should be %p instead of %x\n", hIcon
, wirehicon
->u
.hRemote
);
1150 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1151 HICON_UserUnmarshal(&umcb
.Flags
, buffer
, &hIcon2
);
1152 ok(hIcon
== hIcon2
, "Didn't unmarshal properly\n");
1153 HeapFree(GetProcessHeap(), 0, buffer
);
1155 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1156 HICON_UserFree(&umcb
.Flags
, &hIcon2
);
1160 static void test_marshal_HBRUSH(void)
1162 MIDL_STUB_MESSAGE stub_msg
;
1163 HBRUSH hBrush
, hBrush2
;
1164 USER_MARSHAL_CB umcb
;
1165 RPC_MESSAGE rpc_msg
;
1166 unsigned char *buffer
;
1168 wireHBRUSH wirehbrush
;
1171 logbrush
.lbStyle
= BS_SOLID
;
1172 logbrush
.lbColor
= RGB(0, 0, 0);
1173 logbrush
.lbHatch
= 0;
1175 hBrush
= CreateBrushIndirect(&logbrush
);
1176 ok(hBrush
!= 0, "CreateBrushIndirect failed\n");
1178 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1179 size
= HBRUSH_UserSize(&umcb
.Flags
, 0, &hBrush
);
1180 ok(size
== sizeof(*wirehbrush
), "Wrong size %d\n", size
);
1182 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1183 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1184 HBRUSH_UserMarshal(&umcb
.Flags
, buffer
, &hBrush
);
1185 wirehbrush
= (wireHBRUSH
)buffer
;
1186 ok(wirehbrush
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehbrush
->fContext
);
1187 ok(wirehbrush
->u
.hInproc
== (LONG_PTR
)hBrush
, "Marshaled value should be %p instead of %x\n", hBrush
, wirehbrush
->u
.hRemote
);
1189 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1190 HBRUSH_UserUnmarshal(&umcb
.Flags
, buffer
, &hBrush2
);
1191 ok(hBrush
== hBrush2
, "Didn't unmarshal properly\n");
1192 HeapFree(GetProcessHeap(), 0, buffer
);
1194 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1195 HBRUSH_UserFree(&umcb
.Flags
, &hBrush2
);
1196 DeleteObject(hBrush
);
1201 IDataObject IDataObject_iface
;
1204 static HRESULT WINAPI
obj_QueryInterface(IDataObject
*iface
, REFIID iid
, void **obj
)
1208 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
1209 IsEqualGUID(iid
, &IID_IDataObject
))
1214 IDataObject_AddRef(iface
);
1218 return E_NOINTERFACE
;
1221 static ULONG WINAPI
obj_AddRef(IDataObject
*iface
)
1226 static ULONG WINAPI
obj_Release(IDataObject
*iface
)
1231 static HRESULT WINAPI
obj_DO_GetDataHere(IDataObject
*iface
, FORMATETC
*fmt
,
1234 ok( med
->pUnkForRelease
== NULL
, "got %p\n", med
->pUnkForRelease
);
1236 if (fmt
->cfFormat
== 2)
1238 IStream_Release(U(med
)->pstm
);
1239 U(med
)->pstm
= &Test_Stream2
.IStream_iface
;
1245 static const IDataObjectVtbl obj_data_object_vtbl
=
1252 NULL
, /* QueryGetData */
1253 NULL
, /* GetCanonicalFormatEtc */
1255 NULL
, /* EnumFormatEtc */
1257 NULL
, /* DUnadvise */
1258 NULL
/* EnumDAdvise */
1261 static struct obj obj
=
1263 {&obj_data_object_vtbl
}
1266 static void test_GetDataHere_Proxy(void)
1272 static const LARGE_INTEGER zero
;
1277 hr
= CreateStreamOnHGlobal( NULL
, TRUE
, &stm
);
1278 ok( hr
== S_OK
, "got %08x\n", hr
);
1279 tid
= start_host_object2( stm
, &IID_IDataObject
, (IUnknown
*)&obj
.IDataObject_iface
, MSHLFLAGS_NORMAL
, NULL
, &thread
);
1281 IStream_Seek( stm
, zero
, STREAM_SEEK_SET
, NULL
);
1282 hr
= CoUnmarshalInterface( stm
, &IID_IDataObject
, (void **)&data
);
1283 ok( hr
== S_OK
, "got %08x\n", hr
);
1284 IStream_Release( stm
);
1286 Test_Stream
.refs
= 1;
1287 Test_Stream2
.refs
= 1;
1288 Test_Unknown
.refs
= 1;
1292 fmt
.dwAspect
= DVASPECT_CONTENT
;
1295 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1297 fmt
.tymed
= med
.tymed
= TYMED_NULL
;
1298 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1299 ok( hr
== DV_E_TYMED
, "got %08x\n", hr
);
1301 for (fmt
.tymed
= TYMED_HGLOBAL
; fmt
.tymed
<= TYMED_ENHMF
; fmt
.tymed
<<= 1)
1303 med
.tymed
= fmt
.tymed
;
1304 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1305 ok( hr
== (fmt
.tymed
<= TYMED_ISTORAGE
? S_OK
: DV_E_TYMED
), "got %08x for tymed %d\n", hr
, fmt
.tymed
);
1306 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1309 fmt
.tymed
= TYMED_ISTREAM
;
1310 med
.tymed
= TYMED_ISTORAGE
;
1311 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1312 ok( hr
== DV_E_TYMED
, "got %08x\n", hr
);
1314 fmt
.tymed
= med
.tymed
= TYMED_ISTREAM
;
1315 U(med
).pstm
= &Test_Stream
.IStream_iface
;
1316 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1318 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1319 ok( hr
== S_OK
, "got %08x\n", hr
);
1321 ok( U(med
).pstm
== &Test_Stream
.IStream_iface
, "stm changed\n" );
1322 ok( med
.pUnkForRelease
== &Test_Unknown
.IUnknown_iface
, "punk changed\n" );
1324 ok( Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
1325 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1328 fmt
.tymed
= med
.tymed
= TYMED_ISTREAM
;
1329 U(med
).pstm
= &Test_Stream
.IStream_iface
;
1330 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1332 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1333 ok( hr
== S_OK
, "got %08x\n", hr
);
1335 ok( U(med
).pstm
== &Test_Stream
.IStream_iface
, "stm changed\n" );
1336 ok( med
.pUnkForRelease
== &Test_Unknown
.IUnknown_iface
, "punk changed\n" );
1338 ok( Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
1339 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1340 ok( Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
1342 IDataObject_Release( data
);
1343 end_host_object( tid
, thread
);
1346 START_TEST(usrmarshal
)
1348 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1350 test_marshal_CLIPFORMAT();
1351 test_marshal_HWND();
1352 test_marshal_HGLOBAL();
1353 test_marshal_HENHMETAFILE();
1354 test_marshal_HMETAFILE();
1355 test_marshal_HMETAFILEPICT();
1356 test_marshal_WdtpInterfacePointer();
1357 test_marshal_STGMEDIUM();
1360 test_marshal_HICON();
1361 test_marshal_HBRUSH();
1363 test_GetDataHere_Proxy();