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