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
23 ULONG __RPC_USER
HMETAFILE_UserSize(ULONG
*, ULONG
, HMETAFILE
*);
24 unsigned char * __RPC_USER
HMETAFILE_UserMarshal(ULONG
*, unsigned char *, HMETAFILE
*);
25 unsigned char * __RPC_USER
HMETAFILE_UserUnmarshal(ULONG
*, unsigned char *, HMETAFILE
*);
26 void __RPC_USER
HMETAFILE_UserFree(ULONG
*, HMETAFILE
*);
28 ULONG __RPC_USER
HENHMETAFILE_UserSize(ULONG
*, ULONG
, HENHMETAFILE
*);
29 unsigned char * __RPC_USER
HENHMETAFILE_UserMarshal (ULONG
*, unsigned char *, HENHMETAFILE
*);
30 unsigned char * __RPC_USER
HENHMETAFILE_UserUnmarshal(ULONG
*, unsigned char *, HENHMETAFILE
*);
31 void __RPC_USER
HENHMETAFILE_UserFree(ULONG
*, HENHMETAFILE
*);
33 ULONG __RPC_USER
HMETAFILEPICT_UserSize(ULONG
*, ULONG
, HMETAFILEPICT
*);
34 unsigned char * __RPC_USER
HMETAFILEPICT_UserMarshal (ULONG
*, unsigned char *, HMETAFILEPICT
*);
35 unsigned char * __RPC_USER
HMETAFILEPICT_UserUnmarshal(ULONG
*, unsigned char *, HMETAFILEPICT
*);
36 void __RPC_USER
HMETAFILEPICT_UserFree(ULONG
*, HMETAFILEPICT
*);
38 ULONG __RPC_USER
HBRUSH_UserSize(ULONG
*, ULONG
, HBRUSH
*);
39 unsigned char * __RPC_USER
HBRUSH_UserMarshal(ULONG
*, unsigned char *, HBRUSH
*);
40 unsigned char * __RPC_USER
HBRUSH_UserUnmarshal(ULONG
*, unsigned char *, HBRUSH
*);
41 void __RPC_USER
HBRUSH_UserFree(ULONG
*, HBRUSH
*);
43 static BOOL g_expect_user_alloc
;
44 static void * WINAPI
user_allocate(SIZE_T size
)
46 ok(g_expect_user_alloc
, "unexpected user_allocate call\n");
47 return CoTaskMemAlloc(size
);
50 static BOOL g_expect_user_free
;
51 static void WINAPI
user_free(void *p
)
53 ok(g_expect_user_free
, "unexpected user_free call\n");
57 static void init_user_marshal_cb(USER_MARSHAL_CB
*umcb
,
58 PMIDL_STUB_MESSAGE stub_msg
,
59 PRPC_MESSAGE rpc_msg
, unsigned char *buffer
,
60 unsigned int size
, MSHCTX context
)
62 memset(rpc_msg
, 0, sizeof(*rpc_msg
));
63 rpc_msg
->Buffer
= buffer
;
64 rpc_msg
->BufferLength
= size
;
66 memset(stub_msg
, 0, sizeof(*stub_msg
));
67 stub_msg
->RpcMsg
= rpc_msg
;
68 stub_msg
->Buffer
= buffer
;
69 stub_msg
->pfnAllocate
= user_allocate
;
70 stub_msg
->pfnFree
= user_free
;
72 memset(umcb
, 0, sizeof(*umcb
));
73 umcb
->Flags
= MAKELONG(context
, NDR_LOCAL_DATA_REPRESENTATION
);
74 umcb
->pStubMsg
= stub_msg
;
75 umcb
->Signature
= USER_MARSHAL_CB_SIGNATURE
;
76 umcb
->CBType
= buffer
? USER_MARSHAL_CB_UNMARSHALL
: USER_MARSHAL_CB_BUFFER_SIZE
;
79 #define RELEASEMARSHALDATA WM_USER
81 struct host_object_data
86 MSHLFLAGS marshal_flags
;
88 IMessageFilter
*filter
;
91 static DWORD CALLBACK
host_object_proc(LPVOID p
)
93 struct host_object_data
*data
= p
;
97 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
101 IMessageFilter
* prev_filter
= NULL
;
102 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
103 if (prev_filter
) IMessageFilter_Release(prev_filter
);
104 ok(hr
== S_OK
, "got %08x\n", hr
);
107 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
108 ok(hr
== S_OK
, "got %08x\n", hr
);
110 /* force the message queue to be created before signaling parent thread */
111 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
113 SetEvent(data
->marshal_event
);
115 while (GetMessageA(&msg
, NULL
, 0, 0))
117 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
119 CoReleaseMarshalData(data
->stream
);
120 SetEvent((HANDLE
)msg
.lParam
);
123 DispatchMessageA(&msg
);
126 HeapFree(GetProcessHeap(), 0, data
);
133 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
136 HANDLE marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
137 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
139 data
->stream
= stream
;
141 data
->object
= object
;
142 data
->marshal_flags
= marshal_flags
;
143 data
->marshal_event
= marshal_event
;
144 data
->filter
= filter
;
146 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
148 /* wait for marshaling to complete before returning */
149 ok( !WaitForSingleObject(marshal_event
, 10000), "wait timed out\n" );
150 CloseHandle(marshal_event
);
155 static void end_host_object(DWORD tid
, HANDLE thread
)
157 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
158 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
159 /* be careful of races - don't return until hosting thread has terminated */
160 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
164 static const char cf_marshaled
[] =
176 static void test_marshal_CLIPFORMAT(void)
178 USER_MARSHAL_CB umcb
;
179 MIDL_STUB_MESSAGE stub_msg
;
181 unsigned char *buffer
;
183 CLIPFORMAT cf
= RegisterClipboardFormatA("MyFormat");
186 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
187 size
= CLIPFORMAT_UserSize(&umcb
.Flags
, 0, &cf
);
188 ok(size
== 8 + sizeof(cf_marshaled
) ||
189 broken(size
== 12 + sizeof(cf_marshaled
)) || /* win64 adds 4 extra (unused) bytes */
190 broken(size
== 8 + sizeof(cf_marshaled
) - 2), /* win9x and winnt don't include the '\0' */
191 "CLIPFORMAT: Wrong size %d\n", size
);
193 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
194 memset( buffer
, 0xcc, size
);
195 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
196 CLIPFORMAT_UserMarshal(&umcb
.Flags
, buffer
, &cf
);
197 ok(*(LONG
*)(buffer
+ 0) == WDT_REMOTE_CALL
, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(LONG
*)(buffer
+ 0));
198 ok(*(DWORD
*)(buffer
+ 4) == cf
, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04x\n", cf
, *(DWORD
*)(buffer
+ 4));
199 ok(!memcmp(buffer
+ 8, cf_marshaled
, min( sizeof(cf_marshaled
), size
-8 )), "Marshaled data differs\n");
200 if (size
> sizeof(cf_marshaled
) + 8) /* make sure the extra bytes are not used */
201 for (i
= sizeof(cf_marshaled
) + 8; i
< size
; i
++)
202 ok( buffer
[i
] == 0xcc, "buffer offset %u has been set to %x\n", i
, buffer
[i
] );
204 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
205 CLIPFORMAT_UserUnmarshal(&umcb
.Flags
, buffer
, &cf2
);
206 ok(cf
== cf2
, "CLIPFORMAT: Didn't unmarshal properly\n");
207 HeapFree(GetProcessHeap(), 0, buffer
);
209 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
210 CLIPFORMAT_UserFree(&umcb
.Flags
, &cf2
);
213 static void test_marshal_HWND(void)
215 USER_MARSHAL_CB umcb
;
216 MIDL_STUB_MESSAGE stub_msg
;
218 unsigned char *buffer
;
220 HWND hwnd
= GetDesktopWindow();
224 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
225 size
= HWND_UserSize(&umcb
.Flags
, 0, &hwnd
);
226 ok(size
== sizeof(*wirehwnd
), "Wrong size %d\n", size
);
228 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
229 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
230 HWND_UserMarshal(&umcb
.Flags
, buffer
, &hwnd
);
231 wirehwnd
= (wireHWND
)buffer
;
232 ok(wirehwnd
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehwnd
->fContext
);
233 ok(wirehwnd
->u
.hInproc
== (LONG_PTR
)hwnd
, "Marshaled value should be %p instead of %x\n", hwnd
, wirehwnd
->u
.hRemote
);
235 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
236 HWND_UserUnmarshal(&umcb
.Flags
, buffer
, &hwnd2
);
237 ok(hwnd
== hwnd2
, "Didn't unmarshal properly\n");
238 HeapFree(GetProcessHeap(), 0, buffer
);
240 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
241 HWND_UserFree(&umcb
.Flags
, &hwnd2
);
244 static void test_marshal_HGLOBAL(void)
246 USER_MARSHAL_CB umcb
;
247 MIDL_STUB_MESSAGE stub_msg
;
249 unsigned char *buffer
;
250 ULONG size
, block_size
;
253 unsigned char *wirehglobal
;
257 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
258 size
= HGLOBAL_UserSize(&umcb
.Flags
, 0, &hglobal
);
259 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
260 * here - Wine doesn't have to emulate that */
261 ok((size
== 8) || broken(size
== 12) || broken(size
== 16), "Size should be 8, instead of %d\n", size
);
262 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
263 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
264 HGLOBAL_UserMarshal(&umcb
.Flags
, buffer
, &hglobal
);
265 wirehglobal
= buffer
;
266 ok(*(ULONG
*)wirehglobal
== WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)wirehglobal
);
267 wirehglobal
+= sizeof(ULONG
);
268 ok(*(ULONG
*)wirehglobal
== 0, "buffer+4 should be HGLOBAL\n");
269 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
271 HGLOBAL_UserUnmarshal(&umcb
.Flags
, buffer
, &hglobal2
);
272 ok(hglobal2
== hglobal
, "Didn't unmarshal properly\n");
273 HeapFree(GetProcessHeap(), 0, buffer
);
274 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
275 HGLOBAL_UserFree(&umcb
.Flags
, &hglobal2
);
278 for(block_size
= 0; block_size
<= 17; block_size
++)
280 ULONG actual_size
, expected_size
;
282 hglobal
= GlobalAlloc(0, block_size
);
283 buffer
= GlobalLock(hglobal
);
284 for (i
= 0; i
< block_size
; i
++)
286 GlobalUnlock(hglobal
);
287 actual_size
= GlobalSize(hglobal
);
288 expected_size
= actual_size
+ 5 * sizeof(DWORD
);
289 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
290 size
= HGLOBAL_UserSize(&umcb
.Flags
, 0, &hglobal
);
291 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
292 * here - Wine doesn't have to emulate that */
293 ok(size
== expected_size
||
294 broken(size
== expected_size
+ 4) ||
295 broken(size
== expected_size
+ 8),
296 "%d: got size %d\n", block_size
, size
);
297 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
298 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
299 HGLOBAL_UserMarshal(&umcb
.Flags
, buffer
, &hglobal
);
300 wirehglobal
= buffer
;
301 ok(*(ULONG
*)wirehglobal
== WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)wirehglobal
);
302 wirehglobal
+= sizeof(ULONG
);
303 ok(*(ULONG
*)wirehglobal
== (ULONG
)(ULONG_PTR
)hglobal
, "buffer+0x4 should be HGLOBAL\n");
304 wirehglobal
+= sizeof(ULONG
);
305 ok(*(ULONG
*)wirehglobal
== actual_size
, "%d: buffer+0x8 %08x\n", block_size
, *(ULONG
*)wirehglobal
);
306 wirehglobal
+= sizeof(ULONG
);
307 ok(*(ULONG
*)wirehglobal
== (ULONG
)(ULONG_PTR
)hglobal
, "buffer+0xc should be HGLOBAL\n");
308 wirehglobal
+= sizeof(ULONG
);
309 ok(*(ULONG
*)wirehglobal
== actual_size
, "%d: buffer+0x10 %08x\n", block_size
, *(ULONG
*)wirehglobal
);
310 wirehglobal
+= sizeof(ULONG
);
311 for (i
= 0; i
< block_size
; i
++)
312 ok(wirehglobal
[i
] == i
, "buffer+0x%x should be %d\n", 0x10 + i
, i
);
314 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
316 HGLOBAL_UserUnmarshal(&umcb
.Flags
, buffer
, &hglobal2
);
317 ok(hglobal2
!= NULL
, "Didn't unmarshal properly\n");
318 HeapFree(GetProcessHeap(), 0, buffer
);
319 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
320 HGLOBAL_UserFree(&umcb
.Flags
, &hglobal2
);
325 static HENHMETAFILE
create_emf(void)
327 const RECT rect
= {0, 0, 100, 100};
328 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Marshaling Test\0Test\0\0");
329 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
330 return CloseEnhMetaFile(hdc
);
333 static void test_marshal_HENHMETAFILE(void)
335 USER_MARSHAL_CB umcb
;
336 MIDL_STUB_MESSAGE stub_msg
;
338 unsigned char *buffer
;
341 HENHMETAFILE hemf2
= NULL
;
342 unsigned char *wirehemf
;
346 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
347 size
= HENHMETAFILE_UserSize(&umcb
.Flags
, 0, &hemf
);
348 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
349 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
350 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
351 HENHMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hemf
);
353 ok(*(DWORD
*)wirehemf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehemf
);
354 wirehemf
+= sizeof(DWORD
);
355 ok(*(DWORD
*)wirehemf
== (DWORD
)(DWORD_PTR
)hemf
, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD
*)wirehemf
);
356 wirehemf
+= sizeof(DWORD
);
357 ok(*(DWORD
*)wirehemf
== (size
- 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehemf
);
358 wirehemf
+= sizeof(DWORD
);
359 ok(*(DWORD
*)wirehemf
== (size
- 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehemf
);
360 wirehemf
+= sizeof(DWORD
);
361 ok(*(DWORD
*)wirehemf
== EMR_HEADER
, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD
*)wirehemf
);
362 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
365 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
366 HENHMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hemf2
);
367 ok(hemf2
!= NULL
, "HENHMETAFILE didn't unmarshal\n");
368 HeapFree(GetProcessHeap(), 0, buffer
);
369 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
370 HENHMETAFILE_UserFree(&umcb
.Flags
, &hemf2
);
371 DeleteEnhMetaFile(hemf
);
376 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
377 size
= HENHMETAFILE_UserSize(&umcb
.Flags
, 0, &hemf
);
378 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
379 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
380 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
381 HENHMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hemf
);
383 ok(*(DWORD
*)wirehemf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehemf
);
384 wirehemf
+= sizeof(DWORD
);
385 ok(*(DWORD
*)wirehemf
== (DWORD
)(DWORD_PTR
)hemf
, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD
*)wirehemf
);
387 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
388 HENHMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hemf2
);
389 ok(hemf2
== NULL
, "NULL HENHMETAFILE didn't unmarshal\n");
390 HeapFree(GetProcessHeap(), 0, buffer
);
391 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
392 HENHMETAFILE_UserFree(&umcb
.Flags
, &hemf2
);
395 static HMETAFILE
create_mf(void)
397 RECT rect
= {0, 0, 100, 100};
398 HDC hdc
= CreateMetaFileA(NULL
);
399 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
400 return CloseMetaFile(hdc
);
403 static void test_marshal_HMETAFILE(void)
405 USER_MARSHAL_CB umcb
;
406 MIDL_STUB_MESSAGE stub_msg
;
408 unsigned char *buffer
;
411 HMETAFILE hmf2
= NULL
;
412 unsigned char *wirehmf
;
416 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
417 size
= HMETAFILE_UserSize(&umcb
.Flags
, 0, &hmf
);
418 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
419 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
420 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
421 HMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hmf
);
423 ok(*(DWORD
*)wirehmf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmf
);
424 wirehmf
+= sizeof(DWORD
);
425 ok(*(DWORD
*)wirehmf
== (DWORD
)(DWORD_PTR
)hmf
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmf
);
426 wirehmf
+= sizeof(DWORD
);
427 ok(*(DWORD
*)wirehmf
== (size
- 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
428 wirehmf
+= sizeof(DWORD
);
429 ok(*(DWORD
*)wirehmf
== (size
- 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
430 wirehmf
+= sizeof(DWORD
);
431 ok(*(WORD
*)wirehmf
== 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
432 wirehmf
+= sizeof(DWORD
);
433 /* ... rest of data not tested - refer to tests for GetMetaFileBits
436 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
437 HMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hmf2
);
438 ok(hmf2
!= NULL
, "HMETAFILE didn't unmarshal\n");
439 HeapFree(GetProcessHeap(), 0, buffer
);
440 HMETAFILE_UserFree(&umcb
.Flags
, &hmf2
);
446 size
= HMETAFILE_UserSize(&umcb
.Flags
, 0, &hmf
);
447 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
448 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
449 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
450 HMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hmf
);
452 ok(*(DWORD
*)wirehmf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmf
);
453 wirehmf
+= sizeof(DWORD
);
454 ok(*(DWORD
*)wirehmf
== (DWORD
)(DWORD_PTR
)hmf
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmf
);
455 wirehmf
+= sizeof(DWORD
);
457 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
458 HMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hmf2
);
459 ok(hmf2
== NULL
, "NULL HMETAFILE didn't unmarshal\n");
460 HeapFree(GetProcessHeap(), 0, buffer
);
461 HMETAFILE_UserFree(&umcb
.Flags
, &hmf2
);
464 #define USER_MARSHAL_PTR_PREFIX \
465 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
466 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
468 static void test_marshal_HMETAFILEPICT(void)
470 USER_MARSHAL_CB umcb
;
471 MIDL_STUB_MESSAGE stub_msg
;
473 unsigned char *buffer
, *buffer_end
;
476 HMETAFILEPICT hmfp2
= NULL
;
478 unsigned char *wirehmfp
;
480 hmfp
= GlobalAlloc(GMEM_MOVEABLE
, sizeof(*pmfp
));
481 pmfp
= GlobalLock(hmfp
);
482 pmfp
->mm
= MM_ISOTROPIC
;
485 pmfp
->hMF
= create_mf();
488 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
489 size
= HMETAFILEPICT_UserSize(&umcb
.Flags
, 0, &hmfp
);
490 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
491 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
492 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
493 buffer_end
= HMETAFILEPICT_UserMarshal(&umcb
.Flags
, buffer
, &hmfp
);
495 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
496 wirehmfp
+= sizeof(DWORD
);
497 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)hmfp
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
498 wirehmfp
+= sizeof(DWORD
);
499 ok(*(DWORD
*)wirehmfp
== MM_ISOTROPIC
, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
500 wirehmfp
+= sizeof(DWORD
);
501 ok(*(DWORD
*)wirehmfp
== 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
502 wirehmfp
+= sizeof(DWORD
);
503 ok(*(DWORD
*)wirehmfp
== 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
504 wirehmfp
+= sizeof(DWORD
);
505 ok(*(DWORD
*)wirehmfp
== USER_MARSHAL_PTR_PREFIX
, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
506 wirehmfp
+= sizeof(DWORD
);
507 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
508 wirehmfp
+= sizeof(DWORD
);
509 pmfp
= GlobalLock(hmfp
);
510 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)pmfp
->hMF
, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
512 wirehmfp
+= sizeof(DWORD
);
513 /* Note use (buffer_end - buffer) instead of size here, because size is an
514 * overestimate with native */
515 ok(*(DWORD
*)wirehmfp
== (buffer_end
- buffer
- 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
516 wirehmfp
+= sizeof(DWORD
);
517 ok(*(DWORD
*)wirehmfp
== (buffer_end
- buffer
- 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
518 wirehmfp
+= sizeof(DWORD
);
519 ok(*(WORD
*)wirehmfp
== 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
520 /* ... rest of data not tested - refer to tests for GetMetaFileBits
523 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
524 HMETAFILEPICT_UserUnmarshal(&umcb
.Flags
, buffer
, &hmfp2
);
525 ok(hmfp2
!= NULL
, "HMETAFILEPICT didn't unmarshal\n");
526 HeapFree(GetProcessHeap(), 0, buffer
);
527 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
528 HMETAFILEPICT_UserFree(&umcb
.Flags
, &hmfp2
);
529 pmfp
= GlobalLock(hmfp
);
530 DeleteMetaFile(pmfp
->hMF
);
537 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
538 size
= HMETAFILEPICT_UserSize(&umcb
.Flags
, 0, &hmfp
);
539 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
540 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
541 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
542 HMETAFILEPICT_UserMarshal(&umcb
.Flags
, buffer
, &hmfp
);
544 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
545 wirehmfp
+= sizeof(DWORD
);
546 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)hmfp
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
547 wirehmfp
+= sizeof(DWORD
);
550 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
551 HMETAFILEPICT_UserUnmarshal(&umcb
.Flags
, buffer
, &hmfp2
);
552 ok(hmfp2
== NULL
, "NULL HMETAFILE didn't unmarshal\n");
553 HeapFree(GetProcessHeap(), 0, buffer
);
554 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
555 HMETAFILEPICT_UserFree(&umcb
.Flags
, &hmfp2
);
560 IUnknown IUnknown_iface
;
564 static inline TestUnknown
*impl_from_IUnknown(IUnknown
*iface
)
566 return CONTAINING_RECORD(iface
, TestUnknown
, IUnknown_iface
);
569 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
574 if (ppvObj
== NULL
) return E_POINTER
;
576 if (IsEqualGUID(riid
, &IID_IUnknown
))
579 IUnknown_AddRef(iface
);
584 return E_NOINTERFACE
;
587 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
589 TestUnknown
*This
= impl_from_IUnknown(iface
);
590 return InterlockedIncrement(&This
->refs
);
593 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
595 TestUnknown
*This
= impl_from_IUnknown(iface
);
596 return InterlockedDecrement(&This
->refs
);
599 static const IUnknownVtbl TestUnknown_Vtbl
=
601 Test_IUnknown_QueryInterface
,
602 Test_IUnknown_AddRef
,
603 Test_IUnknown_Release
,
608 IStream IStream_iface
;
612 static inline struct test_stream
*impl_from_IStream(IStream
*iface
)
614 return CONTAINING_RECORD(iface
, struct test_stream
, IStream_iface
);
617 static HRESULT WINAPI
Test_IStream_QueryInterface(IStream
*iface
,
618 REFIID riid
, LPVOID
*ppvObj
)
620 if (ppvObj
== NULL
) return E_POINTER
;
622 if (IsEqualIID(riid
, &IID_IUnknown
) ||
623 IsEqualIID(riid
, &IID_IStream
))
626 IStream_AddRef(iface
);
631 return E_NOINTERFACE
;
634 static ULONG WINAPI
Test_IStream_AddRef(IStream
*iface
)
636 struct test_stream
*This
= impl_from_IStream(iface
);
637 return InterlockedIncrement(&This
->refs
);
640 static ULONG WINAPI
Test_IStream_Release(IStream
*iface
)
642 struct test_stream
*This
= impl_from_IStream(iface
);
643 return InterlockedDecrement(&This
->refs
);
646 static const IStreamVtbl TestStream_Vtbl
=
648 Test_IStream_QueryInterface
,
651 /* the rest can be NULLs */
654 static TestUnknown Test_Unknown
= { {&TestUnknown_Vtbl
}, 1 };
655 static TestUnknown Test_Unknown2
= { {&TestUnknown_Vtbl
}, 1 };
656 static struct test_stream Test_Stream
= { {&TestStream_Vtbl
}, 1 };
657 static struct test_stream Test_Stream2
= { {&TestStream_Vtbl
}, 1 };
659 ULONG __RPC_USER
WdtpInterfacePointer_UserSize(ULONG
*, ULONG
, ULONG
, IUnknown
*, REFIID
);
660 unsigned char * __RPC_USER
WdtpInterfacePointer_UserMarshal(ULONG
*, ULONG
, unsigned char *, IUnknown
*, REFIID
);
661 unsigned char * __RPC_USER
WdtpInterfacePointer_UserUnmarshal(ULONG
*, unsigned char *, IUnknown
**, REFIID
);
663 static void marshal_WdtpInterfacePointer(DWORD umcb_ctx
, DWORD ctx
, BOOL client
, BOOL in
, BOOL out
)
665 USER_MARSHAL_CB umcb
;
666 MIDL_STUB_MESSAGE stub_msg
;
668 unsigned char *buffer
, *buffer_end
;
672 unsigned char *wireip
;
673 HGLOBAL h
= GlobalAlloc(GMEM_MOVEABLE
, 0);
680 /* shows that the WdtpInterfacePointer functions don't marshal anything for
681 * NULL pointers, so code using these functions must handle that case
685 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, umcb_ctx
);
686 size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, ctx
, 0, unk
, &IID_IUnknown
);
687 ok(size
== 0, "size should be 0 bytes, not %d\n", size
);
688 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
689 buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, ctx
, buffer
, unk
, &IID_IUnknown
);
690 ok(buffer_end
== buffer
, "buffer_end %p buffer %p\n", buffer_end
, buffer
);
691 HeapFree(GetProcessHeap(), 0, buffer
);
693 /* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then
694 the result of CoMarshalInterface called with the LOWORD of the ctx */
696 unk
= &Test_Unknown
.IUnknown_iface
;
697 Test_Unknown
.refs
= 1;
699 CreateStreamOnHGlobal(h
, TRUE
, &stm
);
700 CoMarshalInterface(stm
, &IID_IUnknown
, unk
, LOWORD(ctx
), NULL
, MSHLFLAGS_NORMAL
);
702 IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &pos
);
703 marshal_size
= pos
.u
.LowPart
;
704 marshal_data
= GlobalLock(h
);
706 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
708 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, umcb_ctx
);
709 size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, ctx
, 0, unk
, &IID_IUnknown
);
710 ok(size
>= marshal_size
+ 2 * sizeof(DWORD
), "marshal size %x got %x\n", marshal_size
, size
);
711 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
712 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, umcb_ctx
);
713 buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, ctx
, buffer
, unk
, &IID_IUnknown
);
715 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
718 ok(buffer_end
== buffer
+ marshal_size
+ 2 * sizeof(DWORD
), "buffer_end %p buffer %p\n", buffer_end
, buffer
);
720 ok(*(DWORD
*)wireip
== marshal_size
, "wireip + 0x0 should be %x instead of %x\n", marshal_size
, *(DWORD
*)wireip
);
721 wireip
+= sizeof(DWORD
);
722 ok(*(DWORD
*)wireip
== marshal_size
, "wireip + 0x4 should be %x instead of %x\n", marshal_size
, *(DWORD
*)wireip
);
723 wireip
+= sizeof(DWORD
);
725 ok(!memcmp(marshal_data
, wireip
, marshal_size
), "buffer mismatch\n");
728 IStream_Seek(stm
, zero
, STREAM_SEEK_SET
, NULL
);
729 CoReleaseMarshalData(stm
);
730 IStream_Release(stm
);
732 Test_Unknown2
.refs
= 1;
733 unk2
= &Test_Unknown2
.IUnknown_iface
;
734 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, umcb_ctx
);
735 umcb
.pStubMsg
->IsClient
= client
;
736 umcb
.pStubMsg
->fIsIn
= in
;
737 umcb
.pStubMsg
->fIsOut
= out
;
739 WdtpInterfacePointer_UserUnmarshal(&umcb
.Flags
, buffer
, &unk2
, &IID_IUnknown
);
740 ok(unk2
!= NULL
, "IUnknown object didn't unmarshal properly\n");
741 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
742 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
743 HeapFree(GetProcessHeap(), 0, buffer
);
744 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_INPROC
);
745 IUnknown_Release(unk2
);
748 static void test_marshal_WdtpInterfacePointer(void)
751 * There are two places where we can pass the marshalling ctx: as
752 * part of the umcb and as a separate flag. The loword of that
753 * separate flag field is what matters.
756 /* All three are marshalled as inproc */
757 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_INPROC
, 0,0,0);
758 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE
, MSHCTX_INPROC
,0,0,0);
759 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MAKELONG(MSHCTX_INPROC
, 0xffff),0,0,0);
761 /* All three are marshalled as remote */
762 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,0,0);
763 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE
, MSHCTX_DIFFERENTMACHINE
,0,0,0);
764 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MAKELONG(MSHCTX_DIFFERENTMACHINE
, 0xffff),0,0,0);
766 /* Test different combinations of client, in and out */
767 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,0,1);
768 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,1,0);
769 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,1,1);
770 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,0,0);
771 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,0,1);
772 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,1,0);
773 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,1,1);
776 static void marshal_STGMEDIUM(BOOL client
, BOOL in
, BOOL out
)
778 USER_MARSHAL_CB umcb
;
779 MIDL_STUB_MESSAGE stub_msg
;
781 unsigned char *buffer
, *buffer_end
, *expect_buffer
, *expect_buffer_end
;
782 ULONG size
, expect_size
;
784 IUnknown
*unk
= &Test_Unknown
.IUnknown_iface
;
785 IStream
*stm
= &Test_Stream
.IStream_iface
;
787 /* TYMED_NULL with pUnkForRelease */
789 Test_Unknown
.refs
= 1;
791 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
792 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, 2 * sizeof(DWORD
), unk
, &IID_IUnknown
);
793 expect_buffer
= HeapAlloc(GetProcessHeap(), 0, expect_size
);
794 *(DWORD
*)expect_buffer
= TYMED_NULL
;
795 *((DWORD
*)expect_buffer
+ 1) = 0xdeadbeef;
796 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
797 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer
+ 2 * sizeof(DWORD
), unk
, &IID_IUnknown
);
799 med
.tymed
= TYMED_NULL
;
801 med
.pUnkForRelease
= unk
;
803 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
804 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
805 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
807 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
808 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
809 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
810 ok(buffer_end
- buffer
== expect_buffer_end
- expect_buffer
, "buffer size mismatch\n");
811 ok(*(DWORD
*)buffer
== TYMED_NULL
, "got %08x\n", *(DWORD
*)buffer
);
812 ok(*((DWORD
*)buffer
+1) != 0, "got %08x\n", *((DWORD
*)buffer
+1));
813 ok(!memcmp(buffer
+8, expect_buffer
+ 8, expect_buffer_end
- expect_buffer
- 8), "buffer mismatch\n");
815 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
816 umcb
.pStubMsg
->IsClient
= client
;
817 umcb
.pStubMsg
->fIsIn
= in
;
818 umcb
.pStubMsg
->fIsOut
= out
;
820 Test_Unknown2
.refs
= 1;
821 med2
.tymed
= TYMED_NULL
;
823 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
825 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
827 ok(med2
.tymed
== TYMED_NULL
, "got tymed %x\n", med2
.tymed
);
828 ok(med2
.pUnkForRelease
!= NULL
, "Incorrectly unmarshalled\n");
829 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
831 HeapFree(GetProcessHeap(), 0, buffer
);
832 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
833 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
835 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
836 med2
.tymed
= TYMED_NULL
;
838 med2
.pUnkForRelease
= NULL
;
839 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, expect_buffer
, &med2
);
840 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
841 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
843 ok(Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
845 HeapFree(GetProcessHeap(), 0, expect_buffer
);
847 /* TYMED_ISTREAM with pUnkForRelease */
849 Test_Unknown
.refs
= 1;
850 Test_Stream
.refs
= 1;
852 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
853 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, 3 * sizeof(DWORD
), (IUnknown
*)stm
, &IID_IStream
);
854 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, expect_size
, unk
, &IID_IUnknown
);
856 expect_buffer
= HeapAlloc(GetProcessHeap(), 0, expect_size
);
857 /* There may be a hole between the two interfaces so init the buffer to something */
858 memset(expect_buffer
, 0xcc, expect_size
);
859 *(DWORD
*)expect_buffer
= TYMED_ISTREAM
;
860 *((DWORD
*)expect_buffer
+ 1) = 0xdeadbeef;
861 *((DWORD
*)expect_buffer
+ 2) = 0xcafe;
862 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
863 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer
+ 3 * sizeof(DWORD
), (IUnknown
*)stm
, &IID_IStream
);
864 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer_end
, unk
, &IID_IUnknown
);
866 med
.tymed
= TYMED_ISTREAM
;
868 med
.pUnkForRelease
= unk
;
870 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
871 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
872 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
874 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
875 memset(buffer
, 0xcc, size
);
876 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
877 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
878 ok(buffer_end
- buffer
== expect_buffer_end
- expect_buffer
, "buffer size mismatch\n");
879 ok(*(DWORD
*)buffer
== TYMED_ISTREAM
, "got %08x\n", *(DWORD
*)buffer
);
880 ok(*((DWORD
*)buffer
+1) != 0, "got %08x\n", *((DWORD
*)buffer
+1));
881 ok(*((DWORD
*)buffer
+2) != 0, "got %08x\n", *((DWORD
*)buffer
+2));
882 ok(!memcmp(buffer
+ 12, expect_buffer
+ 12, (buffer_end
- buffer
) - 12), "buffer mismatch\n");
884 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
885 umcb
.pStubMsg
->IsClient
= client
;
886 umcb
.pStubMsg
->fIsIn
= in
;
887 umcb
.pStubMsg
->fIsOut
= out
;
889 Test_Stream2
.refs
= 1;
890 Test_Unknown2
.refs
= 1;
891 med2
.tymed
= TYMED_ISTREAM
;
892 U(med2
).pstm
= &Test_Stream2
.IStream_iface
;
893 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
895 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
897 ok(med2
.tymed
== TYMED_ISTREAM
, "got tymed %x\n", med2
.tymed
);
898 ok(U(med2
).pstm
!= NULL
, "Incorrectly unmarshalled\n");
899 ok(med2
.pUnkForRelease
!= NULL
, "Incorrectly unmarshalled\n");
900 ok(Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
901 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
903 HeapFree(GetProcessHeap(), 0, buffer
);
904 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
905 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
907 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
908 med2
.tymed
= TYMED_NULL
;
910 med2
.pUnkForRelease
= NULL
;
911 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, expect_buffer
, &med2
);
912 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
913 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
915 ok(Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
916 ok(Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
918 HeapFree(GetProcessHeap(), 0, expect_buffer
);
920 /* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */
922 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
923 expect_size
= 3 * sizeof(DWORD
);
925 med
.tymed
= TYMED_ISTREAM
;
927 med
.pUnkForRelease
= NULL
;
929 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
930 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
931 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
933 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
934 memset(buffer
, 0xcc, size
);
935 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
936 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
937 ok(buffer_end
- buffer
== expect_size
, "buffer size mismatch\n");
938 ok(*(DWORD
*)buffer
== TYMED_ISTREAM
, "got %08x\n", *(DWORD
*)buffer
);
939 ok(*((DWORD
*)buffer
+1) == 0, "got %08x\n", *((DWORD
*)buffer
+1));
940 ok(*((DWORD
*)buffer
+2) == 0, "got %08x\n", *((DWORD
*)buffer
+2));
942 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
943 umcb
.pStubMsg
->IsClient
= client
;
944 umcb
.pStubMsg
->fIsIn
= in
;
945 umcb
.pStubMsg
->fIsOut
= out
;
947 Test_Stream2
.refs
= 1;
948 Test_Unknown2
.refs
= 1;
949 med2
.tymed
= TYMED_ISTREAM
;
950 U(med2
).pstm
= &Test_Stream2
.IStream_iface
;
951 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
953 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
955 ok(med2
.tymed
== TYMED_ISTREAM
, "got tymed %x\n", med2
.tymed
);
956 ok(U(med2
).pstm
== NULL
, "Incorrectly unmarshalled\n");
957 ok(med2
.pUnkForRelease
== &Test_Unknown2
.IUnknown_iface
, "Incorrectly unmarshalled\n");
958 ok(Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
959 ok(Test_Unknown2
.refs
== 1, "got %d\n", Test_Unknown2
.refs
);
961 HeapFree(GetProcessHeap(), 0, buffer
);
962 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
963 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
966 static void test_marshal_STGMEDIUM(void)
968 marshal_STGMEDIUM(0, 0, 0);
969 marshal_STGMEDIUM(0, 0, 1);
970 marshal_STGMEDIUM(0, 1, 0);
971 marshal_STGMEDIUM(0, 1, 1);
972 /* For Windows versions post 2003, client side, non-[in,out] STGMEDIUMs get zero-initialised.
973 However since inline stubs don't set fIsIn or fIsOut this behaviour would break
974 ref counting in GetDataHere_Proxy for example, as we'd end up not releasing the original
975 interface. For simplicity we don't test or implement this. */
976 marshal_STGMEDIUM(1, 1, 1);
979 static void test_marshal_SNB(void)
981 static const WCHAR str1W
[] = {'s','t','r','i','n','g','1',0};
982 static const WCHAR str2W
[] = {'s','t','r','2',0};
983 unsigned char *buffer
, *src
, *mbuf
;
984 MIDL_STUB_MESSAGE stub_msg
;
985 WCHAR
**ptrW
, *dataW
;
986 USER_MARSHAL_CB umcb
;
992 /* 4 bytes alignment */
994 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
995 size
= SNB_UserSize(&umcb
.Flags
, 3, &snb
);
996 ok(size
== 16, "Size should be 16, instead of %d\n", size
);
999 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1000 size
= SNB_UserSize(&umcb
.Flags
, 0, &snb
);
1001 ok(size
== 12, "Size should be 12, instead of %d\n", size
);
1003 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1004 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1005 mbuf
= SNB_UserMarshal(&umcb
.Flags
, buffer
, &snb
);
1006 ok(mbuf
== buffer
+ size
, "got %p, %p\n", mbuf
, buffer
+ size
);
1008 wiresnb
= (RemSNB
*)buffer
;
1009 ok(wiresnb
->ulCntStr
== 0, "got %u\n", wiresnb
->ulCntStr
);
1010 ok(wiresnb
->ulCntChar
== 0, "got %u\n", wiresnb
->ulCntChar
);
1011 ok(*(ULONG
*)wiresnb
->rgString
== 0, "got %u\n", *(ULONG
*)wiresnb
->rgString
);
1014 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1015 SNB_UserUnmarshal(&umcb
.Flags
, buffer
, &snb2
);
1016 ok(snb2
== NULL
, "got %p\n", snb2
);
1018 HeapFree(GetProcessHeap(), 0, buffer
);
1019 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1020 SNB_UserFree(&umcb
.Flags
, &snb2
);
1022 /* block with actual data */
1024 /* allocate source block, n+1 pointers first, then data */
1025 src
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
*)*3 + sizeof(str1W
) + sizeof(str2W
));
1026 ptrW
= (WCHAR
**)src
;
1027 dataW
= *ptrW
= (WCHAR
*)(src
+ 3*sizeof(WCHAR
*));
1029 *ptrW
= (WCHAR
*)(src
+ 3*sizeof(WCHAR
*) + sizeof(str1W
));
1032 lstrcpyW(dataW
, str1W
);
1033 dataW
+= lstrlenW(str1W
) + 1;
1034 lstrcpyW(dataW
, str2W
);
1037 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1038 size
= SNB_UserSize(&umcb
.Flags
, 0, &snb
);
1039 ok(size
== 38, "Size should be 38, instead of %d\n", size
);
1041 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1042 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1043 SNB_UserMarshal(&umcb
.Flags
, buffer
, &snb
);
1045 wiresnb
= (RemSNB
*)buffer
;
1046 ok(wiresnb
->ulCntStr
== 13, "got %u\n", wiresnb
->ulCntStr
);
1047 ok(wiresnb
->ulCntChar
== 2, "got %u\n", wiresnb
->ulCntChar
);
1048 /* payload length is stored one more time, as ULONG */
1049 ok(*(ULONG
*)wiresnb
->rgString
== wiresnb
->ulCntStr
, "got %u\n", *(ULONG
*)wiresnb
->rgString
);
1050 dataW
= &wiresnb
->rgString
[2];
1051 ok(!lstrcmpW(dataW
, str1W
), "marshalled string 0: %s\n", wine_dbgstr_w(dataW
));
1052 dataW
+= sizeof(str1W
)/sizeof(WCHAR
);
1053 ok(!lstrcmpW(dataW
, str2W
), "marshalled string 1: %s\n", wine_dbgstr_w(dataW
));
1055 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1057 g_expect_user_alloc
= TRUE
;
1059 SNB_UserUnmarshal(&umcb
.Flags
, buffer
, &snb2
);
1060 g_expect_user_alloc
= FALSE
;
1063 ok(!lstrcmpW(*ptrW
, str1W
), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW
));
1065 ok(!lstrcmpW(*ptrW
, str2W
), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW
));
1067 ok(*ptrW
== NULL
, "expected terminating NULL ptr, got %p, start %p\n", *ptrW
, snb2
);
1069 HeapFree(GetProcessHeap(), 0, buffer
);
1070 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1072 g_expect_user_free
= TRUE
;
1073 SNB_UserFree(&umcb
.Flags
, &snb2
);
1074 g_expect_user_free
= FALSE
;
1076 HeapFree(GetProcessHeap(), 0, src
);
1079 static void test_marshal_HDC(void)
1081 MIDL_STUB_MESSAGE stub_msg
;
1082 HDC hdc
= GetDC(0), hdc2
;
1083 USER_MARSHAL_CB umcb
;
1084 RPC_MESSAGE rpc_msg
;
1085 unsigned char *buffer
;
1089 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1090 size
= HDC_UserSize(&umcb
.Flags
, 0, &hdc
);
1091 ok(size
== sizeof(*wirehdc
), "Wrong size %d\n", size
);
1093 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1094 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1095 HDC_UserMarshal(&umcb
.Flags
, buffer
, &hdc
);
1096 wirehdc
= (wireHDC
)buffer
;
1097 ok(wirehdc
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehdc
->fContext
);
1098 ok(wirehdc
->u
.hInproc
== (LONG_PTR
)hdc
, "Marshaled value should be %p instead of %x\n", hdc
, wirehdc
->u
.hRemote
);
1100 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1101 HDC_UserUnmarshal(&umcb
.Flags
, buffer
, &hdc2
);
1102 ok(hdc
== hdc2
, "Didn't unmarshal properly\n");
1103 HeapFree(GetProcessHeap(), 0, buffer
);
1105 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1106 HDC_UserFree(&umcb
.Flags
, &hdc2
);
1110 static void test_marshal_HICON(void)
1112 static const BYTE bmp_bits
[1024];
1113 MIDL_STUB_MESSAGE stub_msg
;
1114 HICON hIcon
, hIcon2
;
1115 USER_MARSHAL_CB umcb
;
1116 RPC_MESSAGE rpc_msg
;
1117 unsigned char *buffer
;
1118 wireHICON wirehicon
;
1121 hIcon
= CreateIcon(0, 16, 16, 1, 1, bmp_bits
, bmp_bits
);
1122 ok(hIcon
!= 0, "CreateIcon failed\n");
1124 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1125 size
= HICON_UserSize(&umcb
.Flags
, 0, &hIcon
);
1126 ok(size
== sizeof(*wirehicon
), "Wrong size %d\n", size
);
1128 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1129 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1130 HICON_UserMarshal(&umcb
.Flags
, buffer
, &hIcon
);
1131 wirehicon
= (wireHICON
)buffer
;
1132 ok(wirehicon
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehicon
->fContext
);
1133 ok(wirehicon
->u
.hInproc
== (LONG_PTR
)hIcon
, "Marshaled value should be %p instead of %x\n", hIcon
, wirehicon
->u
.hRemote
);
1135 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1136 HICON_UserUnmarshal(&umcb
.Flags
, buffer
, &hIcon2
);
1137 ok(hIcon
== hIcon2
, "Didn't unmarshal properly\n");
1138 HeapFree(GetProcessHeap(), 0, buffer
);
1140 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1141 HICON_UserFree(&umcb
.Flags
, &hIcon2
);
1145 static void test_marshal_HBRUSH(void)
1147 MIDL_STUB_MESSAGE stub_msg
;
1148 HBRUSH hBrush
, hBrush2
;
1149 USER_MARSHAL_CB umcb
;
1150 RPC_MESSAGE rpc_msg
;
1151 unsigned char *buffer
;
1153 wireHBRUSH wirehbrush
;
1156 logbrush
.lbStyle
= BS_SOLID
;
1157 logbrush
.lbColor
= RGB(0, 0, 0);
1158 logbrush
.lbHatch
= 0;
1160 hBrush
= CreateBrushIndirect(&logbrush
);
1161 ok(hBrush
!= 0, "CreateBrushIndirect failed\n");
1163 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1164 size
= HBRUSH_UserSize(&umcb
.Flags
, 0, &hBrush
);
1165 ok(size
== sizeof(*wirehbrush
), "Wrong size %d\n", size
);
1167 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1168 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1169 HBRUSH_UserMarshal(&umcb
.Flags
, buffer
, &hBrush
);
1170 wirehbrush
= (wireHBRUSH
)buffer
;
1171 ok(wirehbrush
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehbrush
->fContext
);
1172 ok(wirehbrush
->u
.hInproc
== (LONG_PTR
)hBrush
, "Marshaled value should be %p instead of %x\n", hBrush
, wirehbrush
->u
.hRemote
);
1174 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1175 HBRUSH_UserUnmarshal(&umcb
.Flags
, buffer
, &hBrush2
);
1176 ok(hBrush
== hBrush2
, "Didn't unmarshal properly\n");
1177 HeapFree(GetProcessHeap(), 0, buffer
);
1179 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1180 HBRUSH_UserFree(&umcb
.Flags
, &hBrush2
);
1181 DeleteObject(hBrush
);
1186 IDataObject IDataObject_iface
;
1189 static HRESULT WINAPI
obj_QueryInterface(IDataObject
*iface
, REFIID iid
, void **obj
)
1193 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
1194 IsEqualGUID(iid
, &IID_IDataObject
))
1199 IDataObject_AddRef(iface
);
1203 return E_NOINTERFACE
;
1206 static ULONG WINAPI
obj_AddRef(IDataObject
*iface
)
1211 static ULONG WINAPI
obj_Release(IDataObject
*iface
)
1216 static HRESULT WINAPI
obj_DO_GetDataHere(IDataObject
*iface
, FORMATETC
*fmt
,
1219 ok( med
->pUnkForRelease
== NULL
, "got %p\n", med
->pUnkForRelease
);
1221 if (fmt
->cfFormat
== 2)
1223 IStream_Release(U(med
)->pstm
);
1224 U(med
)->pstm
= &Test_Stream2
.IStream_iface
;
1230 static const IDataObjectVtbl obj_data_object_vtbl
=
1237 NULL
, /* QueryGetData */
1238 NULL
, /* GetCanonicalFormatEtc */
1240 NULL
, /* EnumFormatEtc */
1242 NULL
, /* DUnadvise */
1243 NULL
/* EnumDAdvise */
1246 static struct obj obj
=
1248 {&obj_data_object_vtbl
}
1251 static void test_GetDataHere_Proxy(void)
1257 static const LARGE_INTEGER zero
;
1262 hr
= CreateStreamOnHGlobal( NULL
, TRUE
, &stm
);
1263 ok( hr
== S_OK
, "got %08x\n", hr
);
1264 tid
= start_host_object2( stm
, &IID_IDataObject
, (IUnknown
*)&obj
.IDataObject_iface
, MSHLFLAGS_NORMAL
, NULL
, &thread
);
1266 IStream_Seek( stm
, zero
, STREAM_SEEK_SET
, NULL
);
1267 hr
= CoUnmarshalInterface( stm
, &IID_IDataObject
, (void **)&data
);
1268 ok( hr
== S_OK
, "got %08x\n", hr
);
1269 IStream_Release( stm
);
1271 Test_Stream
.refs
= 1;
1272 Test_Stream2
.refs
= 1;
1273 Test_Unknown
.refs
= 1;
1277 fmt
.dwAspect
= DVASPECT_CONTENT
;
1280 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1282 fmt
.tymed
= med
.tymed
= TYMED_NULL
;
1283 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1284 ok( hr
== DV_E_TYMED
, "got %08x\n", hr
);
1286 for (fmt
.tymed
= TYMED_HGLOBAL
; fmt
.tymed
<= TYMED_ENHMF
; fmt
.tymed
<<= 1)
1288 med
.tymed
= fmt
.tymed
;
1289 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1290 ok( hr
== (fmt
.tymed
<= TYMED_ISTORAGE
? S_OK
: DV_E_TYMED
), "got %08x for tymed %d\n", hr
, fmt
.tymed
);
1291 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1294 fmt
.tymed
= TYMED_ISTREAM
;
1295 med
.tymed
= TYMED_ISTORAGE
;
1296 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1297 ok( hr
== DV_E_TYMED
, "got %08x\n", hr
);
1299 fmt
.tymed
= med
.tymed
= TYMED_ISTREAM
;
1300 U(med
).pstm
= &Test_Stream
.IStream_iface
;
1301 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1303 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1304 ok( hr
== S_OK
, "got %08x\n", hr
);
1306 ok( U(med
).pstm
== &Test_Stream
.IStream_iface
, "stm changed\n" );
1307 ok( med
.pUnkForRelease
== &Test_Unknown
.IUnknown_iface
, "punk changed\n" );
1309 ok( Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
1310 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1313 fmt
.tymed
= med
.tymed
= TYMED_ISTREAM
;
1314 U(med
).pstm
= &Test_Stream
.IStream_iface
;
1315 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1317 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1318 ok( hr
== S_OK
, "got %08x\n", hr
);
1320 ok( U(med
).pstm
== &Test_Stream
.IStream_iface
, "stm changed\n" );
1321 ok( med
.pUnkForRelease
== &Test_Unknown
.IUnknown_iface
, "punk changed\n" );
1323 ok( Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
1324 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1325 ok( Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
1327 IDataObject_Release( data
);
1328 end_host_object( tid
, thread
);
1331 START_TEST(usrmarshal
)
1333 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1335 test_marshal_CLIPFORMAT();
1336 test_marshal_HWND();
1337 test_marshal_HGLOBAL();
1338 test_marshal_HENHMETAFILE();
1339 test_marshal_HMETAFILE();
1340 test_marshal_HMETAFILEPICT();
1341 test_marshal_WdtpInterfacePointer();
1342 test_marshal_STGMEDIUM();
1345 test_marshal_HICON();
1346 test_marshal_HBRUSH();
1348 test_GetDataHere_Proxy();