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
, *buffer_end
;
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
, 1, &cf
);
188 ok(size
== 12 + sizeof(cf_marshaled
) ||
189 broken(size
== 16 + sizeof(cf_marshaled
)), /* win64 adds 4 extra (unused) bytes */
190 "CLIPFORMAT: Wrong size %d\n", size
);
192 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
193 memset( buffer
, 0xcc, size
);
194 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
195 buffer_end
= CLIPFORMAT_UserMarshal(&umcb
.Flags
, buffer
+ 1, &cf
);
196 ok(buffer_end
== buffer
+ 12 + sizeof(cf_marshaled
), "got %p buffer %p\n", buffer_end
, buffer
);
197 ok(*(LONG
*)(buffer
+ 4) == WDT_REMOTE_CALL
, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(LONG
*)(buffer
+ 0));
198 ok(*(DWORD
*)(buffer
+ 8) == cf
, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04x\n", cf
, *(DWORD
*)(buffer
+ 4));
199 ok(!memcmp(buffer
+ 12, cf_marshaled
, min( sizeof(cf_marshaled
), size
-12 )), "Marshaled data differs\n");
200 if (size
> sizeof(cf_marshaled
) + 12) /* make sure the extra bytes are not used */
201 for (i
= sizeof(cf_marshaled
) + 12; i
< size
; i
++)
202 ok( buffer
[i
] == 0xcc, "buffer offset %u has been set to %x\n", i
, buffer
[i
] );
204 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
205 buffer_end
= CLIPFORMAT_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &cf2
);
206 ok(buffer_end
== buffer
+ 12 + sizeof(cf_marshaled
), "got %p buffer %p\n", buffer_end
, buffer
);
207 ok(cf
== cf2
, "CLIPFORMAT: Didn't unmarshal properly\n");
208 HeapFree(GetProcessHeap(), 0, buffer
);
210 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
211 CLIPFORMAT_UserFree(&umcb
.Flags
, &cf2
);
214 static void test_marshal_HWND(void)
216 USER_MARSHAL_CB umcb
;
217 MIDL_STUB_MESSAGE stub_msg
;
219 unsigned char *buffer
, *buffer_end
;
221 HWND hwnd
= GetDesktopWindow();
225 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
226 size
= HWND_UserSize(&umcb
.Flags
, 1, &hwnd
);
227 ok(size
== 4 + sizeof(*wirehwnd
), "Wrong size %d\n", size
);
229 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
230 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
231 buffer_end
= HWND_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hwnd
);
232 ok(buffer_end
== buffer
+ size
, "got %p buffer %p\n", buffer_end
, buffer
);
233 wirehwnd
= (wireHWND
)(buffer
+ 4);
234 ok(wirehwnd
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehwnd
->fContext
);
235 ok(wirehwnd
->u
.hInproc
== (LONG_PTR
)hwnd
, "Marshaled value should be %p instead of %x\n", hwnd
, wirehwnd
->u
.hRemote
);
237 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
238 buffer_end
= HWND_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hwnd2
);
239 ok(buffer_end
== buffer
+ size
, "got %p buffer %p\n", buffer_end
, buffer
);
240 ok(hwnd
== hwnd2
, "Didn't unmarshal properly\n");
241 HeapFree(GetProcessHeap(), 0, buffer
);
243 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
244 HWND_UserFree(&umcb
.Flags
, &hwnd2
);
247 static void test_marshal_HGLOBAL(void)
249 USER_MARSHAL_CB umcb
;
250 MIDL_STUB_MESSAGE stub_msg
;
252 unsigned char *buffer
;
253 ULONG size
, block_size
;
256 unsigned char *wirehglobal
;
260 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
261 size
= HGLOBAL_UserSize(&umcb
.Flags
, 0, &hglobal
);
262 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
263 * here - Wine doesn't have to emulate that */
264 ok((size
== 8) || broken(size
== 12) || broken(size
== 16), "Size should be 8, instead of %d\n", size
);
265 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
266 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
267 HGLOBAL_UserMarshal(&umcb
.Flags
, buffer
, &hglobal
);
268 wirehglobal
= buffer
;
269 ok(*(ULONG
*)wirehglobal
== WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)wirehglobal
);
270 wirehglobal
+= sizeof(ULONG
);
271 ok(*(ULONG
*)wirehglobal
== 0, "buffer+4 should be HGLOBAL\n");
272 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
274 HGLOBAL_UserUnmarshal(&umcb
.Flags
, buffer
, &hglobal2
);
275 ok(hglobal2
== hglobal
, "Didn't unmarshal properly\n");
276 HeapFree(GetProcessHeap(), 0, buffer
);
277 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
278 HGLOBAL_UserFree(&umcb
.Flags
, &hglobal2
);
281 for(block_size
= 0; block_size
<= 17; block_size
++)
283 ULONG actual_size
, expected_size
;
285 hglobal
= GlobalAlloc(0, block_size
);
286 buffer
= GlobalLock(hglobal
);
287 for (i
= 0; i
< block_size
; i
++)
289 GlobalUnlock(hglobal
);
290 actual_size
= GlobalSize(hglobal
);
291 expected_size
= actual_size
+ 5 * sizeof(DWORD
);
292 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
293 size
= HGLOBAL_UserSize(&umcb
.Flags
, 0, &hglobal
);
294 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
295 * here - Wine doesn't have to emulate that */
296 ok(size
== expected_size
||
297 broken(size
== expected_size
+ 4) ||
298 broken(size
== expected_size
+ 8),
299 "%d: got size %d\n", block_size
, size
);
300 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
301 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
302 HGLOBAL_UserMarshal(&umcb
.Flags
, buffer
, &hglobal
);
303 wirehglobal
= buffer
;
304 ok(*(ULONG
*)wirehglobal
== WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)wirehglobal
);
305 wirehglobal
+= sizeof(ULONG
);
306 ok(*(ULONG
*)wirehglobal
== (ULONG
)(ULONG_PTR
)hglobal
, "buffer+0x4 should be HGLOBAL\n");
307 wirehglobal
+= sizeof(ULONG
);
308 ok(*(ULONG
*)wirehglobal
== actual_size
, "%d: buffer+0x8 %08x\n", block_size
, *(ULONG
*)wirehglobal
);
309 wirehglobal
+= sizeof(ULONG
);
310 ok(*(ULONG
*)wirehglobal
== (ULONG
)(ULONG_PTR
)hglobal
, "buffer+0xc should be HGLOBAL\n");
311 wirehglobal
+= sizeof(ULONG
);
312 ok(*(ULONG
*)wirehglobal
== actual_size
, "%d: buffer+0x10 %08x\n", block_size
, *(ULONG
*)wirehglobal
);
313 wirehglobal
+= sizeof(ULONG
);
314 for (i
= 0; i
< block_size
; i
++)
315 ok(wirehglobal
[i
] == i
, "buffer+0x%x should be %d\n", 0x10 + i
, i
);
317 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
319 HGLOBAL_UserUnmarshal(&umcb
.Flags
, buffer
, &hglobal2
);
320 ok(hglobal2
!= NULL
, "Didn't unmarshal properly\n");
321 HeapFree(GetProcessHeap(), 0, buffer
);
322 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
323 HGLOBAL_UserFree(&umcb
.Flags
, &hglobal2
);
328 static HENHMETAFILE
create_emf(void)
330 const RECT rect
= {0, 0, 100, 100};
331 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Marshaling Test\0Test\0\0");
332 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
333 return CloseEnhMetaFile(hdc
);
336 static void test_marshal_HENHMETAFILE(void)
338 USER_MARSHAL_CB umcb
;
339 MIDL_STUB_MESSAGE stub_msg
;
341 unsigned char *buffer
, *buffer_end
;
344 HENHMETAFILE hemf2
= NULL
;
345 unsigned char *wirehemf
;
349 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
350 size
= HENHMETAFILE_UserSize(&umcb
.Flags
, 1, &hemf
);
351 ok(size
> 24, "size should be at least 24 bytes, not %d\n", size
);
352 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
353 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
354 buffer_end
= HENHMETAFILE_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hemf
);
355 ok(buffer_end
== buffer
+ size
, "got %p buffer %p\n", buffer_end
, buffer
);
356 wirehemf
= buffer
+ 4;
357 ok(*(DWORD
*)wirehemf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehemf
);
358 wirehemf
+= sizeof(DWORD
);
359 ok(*(DWORD
*)wirehemf
== (DWORD
)(DWORD_PTR
)hemf
, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD
*)wirehemf
);
360 wirehemf
+= sizeof(DWORD
);
361 ok(*(DWORD
*)wirehemf
== (size
- 0x14), "wirestgm + 0x8 should be size - 0x14 instead of 0x%08x\n", *(DWORD
*)wirehemf
);
362 wirehemf
+= sizeof(DWORD
);
363 ok(*(DWORD
*)wirehemf
== (size
- 0x14), "wirestgm + 0xc should be size - 0x14 instead of 0x%08x\n", *(DWORD
*)wirehemf
);
364 wirehemf
+= sizeof(DWORD
);
365 ok(*(DWORD
*)wirehemf
== EMR_HEADER
, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD
*)wirehemf
);
366 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
369 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
370 buffer_end
= HENHMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hemf2
);
371 ok(buffer_end
== buffer
+ size
, "got %p buffer %p\n", buffer_end
, buffer
);
372 ok(hemf2
!= NULL
, "HENHMETAFILE didn't unmarshal\n");
373 HeapFree(GetProcessHeap(), 0, buffer
);
374 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
375 HENHMETAFILE_UserFree(&umcb
.Flags
, &hemf2
);
376 DeleteEnhMetaFile(hemf
);
381 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
382 size
= HENHMETAFILE_UserSize(&umcb
.Flags
, 1, &hemf
);
383 ok(size
== 12, "size should be 12 bytes, not %d\n", size
);
384 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
385 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
386 buffer_end
= HENHMETAFILE_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hemf
);
387 ok(buffer_end
== buffer
+ size
, "got %p buffer %p\n", buffer_end
, buffer
);
388 wirehemf
= buffer
+ 4;
389 ok(*(DWORD
*)wirehemf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehemf
);
390 wirehemf
+= sizeof(DWORD
);
391 ok(*(DWORD
*)wirehemf
== (DWORD
)(DWORD_PTR
)hemf
, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD
*)wirehemf
);
393 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
394 buffer_end
= HENHMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hemf2
);
395 ok(buffer_end
== buffer
+ size
, "got %p buffer %p\n", buffer_end
, buffer
);
396 ok(hemf2
== NULL
, "NULL HENHMETAFILE didn't unmarshal\n");
397 HeapFree(GetProcessHeap(), 0, buffer
);
398 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
399 HENHMETAFILE_UserFree(&umcb
.Flags
, &hemf2
);
402 static HMETAFILE
create_mf(void)
404 RECT rect
= {0, 0, 100, 100};
405 HDC hdc
= CreateMetaFileA(NULL
);
406 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
407 return CloseMetaFile(hdc
);
410 static void test_marshal_HMETAFILE(void)
412 USER_MARSHAL_CB umcb
;
413 MIDL_STUB_MESSAGE stub_msg
;
415 unsigned char *buffer
;
418 HMETAFILE hmf2
= NULL
;
419 unsigned char *wirehmf
;
423 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
424 size
= HMETAFILE_UserSize(&umcb
.Flags
, 0, &hmf
);
425 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
426 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
427 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
428 HMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hmf
);
430 ok(*(DWORD
*)wirehmf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmf
);
431 wirehmf
+= sizeof(DWORD
);
432 ok(*(DWORD
*)wirehmf
== (DWORD
)(DWORD_PTR
)hmf
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmf
);
433 wirehmf
+= sizeof(DWORD
);
434 ok(*(DWORD
*)wirehmf
== (size
- 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
435 wirehmf
+= sizeof(DWORD
);
436 ok(*(DWORD
*)wirehmf
== (size
- 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
437 wirehmf
+= sizeof(DWORD
);
438 ok(*(WORD
*)wirehmf
== 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
439 wirehmf
+= sizeof(DWORD
);
440 /* ... rest of data not tested - refer to tests for GetMetaFileBits
443 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
444 HMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hmf2
);
445 ok(hmf2
!= NULL
, "HMETAFILE didn't unmarshal\n");
446 HeapFree(GetProcessHeap(), 0, buffer
);
447 HMETAFILE_UserFree(&umcb
.Flags
, &hmf2
);
453 size
= HMETAFILE_UserSize(&umcb
.Flags
, 0, &hmf
);
454 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
455 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
456 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
457 HMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hmf
);
459 ok(*(DWORD
*)wirehmf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmf
);
460 wirehmf
+= sizeof(DWORD
);
461 ok(*(DWORD
*)wirehmf
== (DWORD
)(DWORD_PTR
)hmf
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmf
);
462 wirehmf
+= sizeof(DWORD
);
464 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
465 HMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hmf2
);
466 ok(hmf2
== NULL
, "NULL HMETAFILE didn't unmarshal\n");
467 HeapFree(GetProcessHeap(), 0, buffer
);
468 HMETAFILE_UserFree(&umcb
.Flags
, &hmf2
);
471 #define USER_MARSHAL_PTR_PREFIX \
472 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
473 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
475 static void test_marshal_HMETAFILEPICT(void)
477 USER_MARSHAL_CB umcb
;
478 MIDL_STUB_MESSAGE stub_msg
;
480 unsigned char *buffer
, *buffer_end
;
483 HMETAFILEPICT hmfp2
= NULL
;
485 unsigned char *wirehmfp
;
487 hmfp
= GlobalAlloc(GMEM_MOVEABLE
, sizeof(*pmfp
));
488 pmfp
= GlobalLock(hmfp
);
489 pmfp
->mm
= MM_ISOTROPIC
;
492 pmfp
->hMF
= create_mf();
495 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
496 size
= HMETAFILEPICT_UserSize(&umcb
.Flags
, 1, &hmfp
);
497 ok(size
> 24, "size should be at least 24 bytes, not %d\n", size
);
498 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
499 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
500 buffer_end
= HMETAFILEPICT_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hmfp
);
501 wirehmfp
= buffer
+ 4;
502 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
503 wirehmfp
+= sizeof(DWORD
);
504 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)hmfp
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
505 wirehmfp
+= sizeof(DWORD
);
506 ok(*(DWORD
*)wirehmfp
== MM_ISOTROPIC
, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
507 wirehmfp
+= sizeof(DWORD
);
508 ok(*(DWORD
*)wirehmfp
== 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
509 wirehmfp
+= sizeof(DWORD
);
510 ok(*(DWORD
*)wirehmfp
== 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
511 wirehmfp
+= sizeof(DWORD
);
512 ok(*(DWORD
*)wirehmfp
== USER_MARSHAL_PTR_PREFIX
, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
513 wirehmfp
+= sizeof(DWORD
);
514 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
515 wirehmfp
+= sizeof(DWORD
);
516 pmfp
= GlobalLock(hmfp
);
517 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)pmfp
->hMF
, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
519 wirehmfp
+= sizeof(DWORD
);
520 /* Note use (buffer_end - buffer) instead of size here, because size is an
521 * overestimate with native */
522 ok(*(DWORD
*)wirehmfp
== (buffer_end
- buffer
- 0x2c), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
523 wirehmfp
+= sizeof(DWORD
);
524 ok(*(DWORD
*)wirehmfp
== (buffer_end
- buffer
- 0x2c), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
525 wirehmfp
+= sizeof(DWORD
);
526 ok(*(WORD
*)wirehmfp
== 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
527 /* ... rest of data not tested - refer to tests for GetMetaFileBits
530 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
531 HMETAFILEPICT_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hmfp2
);
532 ok(hmfp2
!= NULL
, "HMETAFILEPICT didn't unmarshal\n");
533 HeapFree(GetProcessHeap(), 0, buffer
);
534 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
535 HMETAFILEPICT_UserFree(&umcb
.Flags
, &hmfp2
);
536 pmfp
= GlobalLock(hmfp
);
537 DeleteMetaFile(pmfp
->hMF
);
544 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
545 size
= HMETAFILEPICT_UserSize(&umcb
.Flags
, 1, &hmfp
);
546 ok(size
== 12, "size should be 12 bytes, not %d\n", size
);
547 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
548 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
549 buffer_end
= HMETAFILEPICT_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hmfp
);
550 ok(buffer_end
== buffer
+ size
, "got %p buffer %p\n", buffer_end
, buffer
);
551 wirehmfp
= buffer
+ 4;
552 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
553 wirehmfp
+= sizeof(DWORD
);
554 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)hmfp
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
555 wirehmfp
+= sizeof(DWORD
);
558 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
559 buffer_end
= HMETAFILEPICT_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hmfp2
);
560 ok(buffer_end
== buffer
+ size
, "got %p buffer %p\n", buffer_end
, buffer
);
561 ok(hmfp2
== NULL
, "NULL HMETAFILE didn't unmarshal\n");
562 HeapFree(GetProcessHeap(), 0, buffer
);
563 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
564 HMETAFILEPICT_UserFree(&umcb
.Flags
, &hmfp2
);
569 IUnknown IUnknown_iface
;
573 static inline TestUnknown
*impl_from_IUnknown(IUnknown
*iface
)
575 return CONTAINING_RECORD(iface
, TestUnknown
, IUnknown_iface
);
578 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
583 if (ppvObj
== NULL
) return E_POINTER
;
585 if (IsEqualGUID(riid
, &IID_IUnknown
))
588 IUnknown_AddRef(iface
);
593 return E_NOINTERFACE
;
596 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
598 TestUnknown
*This
= impl_from_IUnknown(iface
);
599 return InterlockedIncrement(&This
->refs
);
602 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
604 TestUnknown
*This
= impl_from_IUnknown(iface
);
605 return InterlockedDecrement(&This
->refs
);
608 static const IUnknownVtbl TestUnknown_Vtbl
=
610 Test_IUnknown_QueryInterface
,
611 Test_IUnknown_AddRef
,
612 Test_IUnknown_Release
,
617 IStream IStream_iface
;
621 static inline struct test_stream
*impl_from_IStream(IStream
*iface
)
623 return CONTAINING_RECORD(iface
, struct test_stream
, IStream_iface
);
626 static HRESULT WINAPI
Test_IStream_QueryInterface(IStream
*iface
,
627 REFIID riid
, LPVOID
*ppvObj
)
629 if (ppvObj
== NULL
) return E_POINTER
;
631 if (IsEqualIID(riid
, &IID_IUnknown
) ||
632 IsEqualIID(riid
, &IID_IStream
))
635 IStream_AddRef(iface
);
640 return E_NOINTERFACE
;
643 static ULONG WINAPI
Test_IStream_AddRef(IStream
*iface
)
645 struct test_stream
*This
= impl_from_IStream(iface
);
646 return InterlockedIncrement(&This
->refs
);
649 static ULONG WINAPI
Test_IStream_Release(IStream
*iface
)
651 struct test_stream
*This
= impl_from_IStream(iface
);
652 return InterlockedDecrement(&This
->refs
);
655 static const IStreamVtbl TestStream_Vtbl
=
657 Test_IStream_QueryInterface
,
660 /* the rest can be NULLs */
663 static TestUnknown Test_Unknown
= { {&TestUnknown_Vtbl
}, 1 };
664 static TestUnknown Test_Unknown2
= { {&TestUnknown_Vtbl
}, 1 };
665 static struct test_stream Test_Stream
= { {&TestStream_Vtbl
}, 1 };
666 static struct test_stream Test_Stream2
= { {&TestStream_Vtbl
}, 1 };
668 ULONG __RPC_USER
WdtpInterfacePointer_UserSize(ULONG
*, ULONG
, ULONG
, IUnknown
*, REFIID
);
669 unsigned char * __RPC_USER
WdtpInterfacePointer_UserMarshal(ULONG
*, ULONG
, unsigned char *, IUnknown
*, REFIID
);
670 unsigned char * __RPC_USER
WdtpInterfacePointer_UserUnmarshal(ULONG
*, unsigned char *, IUnknown
**, REFIID
);
672 static void marshal_WdtpInterfacePointer(DWORD umcb_ctx
, DWORD ctx
, BOOL client
, BOOL in
, BOOL out
)
674 USER_MARSHAL_CB umcb
;
675 MIDL_STUB_MESSAGE stub_msg
;
677 unsigned char *buffer
, *buffer_end
;
681 unsigned char *wireip
;
682 HGLOBAL h
= GlobalAlloc(GMEM_MOVEABLE
, 0);
689 /* shows that the WdtpInterfacePointer functions don't marshal anything for
690 * NULL pointers, so code using these functions must handle that case
694 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, umcb_ctx
);
695 size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, ctx
, 0, unk
, &IID_IUnknown
);
696 ok(size
== 0, "size should be 0 bytes, not %d\n", size
);
697 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
698 buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, ctx
, buffer
, unk
, &IID_IUnknown
);
699 ok(buffer_end
== buffer
, "buffer_end %p buffer %p\n", buffer_end
, buffer
);
700 HeapFree(GetProcessHeap(), 0, buffer
);
702 /* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then
703 the result of CoMarshalInterface called with the LOWORD of the ctx */
705 unk
= &Test_Unknown
.IUnknown_iface
;
706 Test_Unknown
.refs
= 1;
708 CreateStreamOnHGlobal(h
, TRUE
, &stm
);
709 CoMarshalInterface(stm
, &IID_IUnknown
, unk
, LOWORD(ctx
), NULL
, MSHLFLAGS_NORMAL
);
711 IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &pos
);
712 marshal_size
= pos
.u
.LowPart
;
713 marshal_data
= GlobalLock(h
);
715 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
717 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, umcb_ctx
);
718 size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, ctx
, 0, unk
, &IID_IUnknown
);
719 ok(size
>= marshal_size
+ 2 * sizeof(DWORD
), "marshal size %x got %x\n", marshal_size
, size
);
720 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
721 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, umcb_ctx
);
722 buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, ctx
, buffer
, unk
, &IID_IUnknown
);
724 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
727 ok(buffer_end
== buffer
+ marshal_size
+ 2 * sizeof(DWORD
), "buffer_end %p buffer %p\n", buffer_end
, buffer
);
729 ok(*(DWORD
*)wireip
== marshal_size
, "wireip + 0x0 should be %x instead of %x\n", marshal_size
, *(DWORD
*)wireip
);
730 wireip
+= sizeof(DWORD
);
731 ok(*(DWORD
*)wireip
== marshal_size
, "wireip + 0x4 should be %x instead of %x\n", marshal_size
, *(DWORD
*)wireip
);
732 wireip
+= sizeof(DWORD
);
734 ok(!memcmp(marshal_data
, wireip
, marshal_size
), "buffer mismatch\n");
737 IStream_Seek(stm
, zero
, STREAM_SEEK_SET
, NULL
);
738 CoReleaseMarshalData(stm
);
739 IStream_Release(stm
);
741 Test_Unknown2
.refs
= 1;
742 unk2
= &Test_Unknown2
.IUnknown_iface
;
743 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, umcb_ctx
);
744 umcb
.pStubMsg
->IsClient
= client
;
745 umcb
.pStubMsg
->fIsIn
= in
;
746 umcb
.pStubMsg
->fIsOut
= out
;
748 WdtpInterfacePointer_UserUnmarshal(&umcb
.Flags
, buffer
, &unk2
, &IID_IUnknown
);
749 ok(unk2
!= NULL
, "IUnknown object didn't unmarshal properly\n");
750 ok(Test_Unknown
.refs
== 2, "got %d\n", Test_Unknown
.refs
);
751 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
752 HeapFree(GetProcessHeap(), 0, buffer
);
753 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_INPROC
);
754 IUnknown_Release(unk2
);
757 static void test_marshal_WdtpInterfacePointer(void)
760 * There are two places where we can pass the marshalling ctx: as
761 * part of the umcb and as a separate flag. The loword of that
762 * separate flag field is what matters.
765 /* All three are marshalled as inproc */
766 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_INPROC
, 0,0,0);
767 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE
, MSHCTX_INPROC
,0,0,0);
768 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MAKELONG(MSHCTX_INPROC
, 0xffff),0,0,0);
770 /* All three are marshalled as remote */
771 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,0,0);
772 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE
, MSHCTX_DIFFERENTMACHINE
,0,0,0);
773 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MAKELONG(MSHCTX_DIFFERENTMACHINE
, 0xffff),0,0,0);
775 /* Test different combinations of client, in and out */
776 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,0,1);
777 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,1,0);
778 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,0,1,1);
779 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,0,0);
780 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,0,1);
781 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,1,0);
782 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
,1,1,1);
785 static void marshal_STGMEDIUM(BOOL client
, BOOL in
, BOOL out
)
787 USER_MARSHAL_CB umcb
;
788 MIDL_STUB_MESSAGE stub_msg
;
790 unsigned char *buffer
, *buffer_end
, *expect_buffer
, *expect_buffer_end
;
791 ULONG size
, expect_size
;
793 IUnknown
*unk
= &Test_Unknown
.IUnknown_iface
;
794 IStream
*stm
= &Test_Stream
.IStream_iface
;
796 /* TYMED_NULL with pUnkForRelease */
798 Test_Unknown
.refs
= 1;
800 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
801 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, 2 * sizeof(DWORD
), unk
, &IID_IUnknown
);
802 expect_buffer
= HeapAlloc(GetProcessHeap(), 0, expect_size
);
803 *(DWORD
*)expect_buffer
= TYMED_NULL
;
804 *((DWORD
*)expect_buffer
+ 1) = 0xdeadbeef;
805 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
806 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer
+ 2 * sizeof(DWORD
), unk
, &IID_IUnknown
);
808 med
.tymed
= TYMED_NULL
;
810 med
.pUnkForRelease
= unk
;
812 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
813 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
814 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
816 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
817 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
818 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
819 ok(buffer_end
- buffer
== expect_buffer_end
- expect_buffer
, "buffer size mismatch\n");
820 ok(*(DWORD
*)buffer
== TYMED_NULL
, "got %08x\n", *(DWORD
*)buffer
);
821 ok(*((DWORD
*)buffer
+1) != 0, "got %08x\n", *((DWORD
*)buffer
+1));
822 ok(!memcmp(buffer
+8, expect_buffer
+ 8, expect_buffer_end
- expect_buffer
- 8), "buffer mismatch\n");
824 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
825 umcb
.pStubMsg
->IsClient
= client
;
826 umcb
.pStubMsg
->fIsIn
= in
;
827 umcb
.pStubMsg
->fIsOut
= out
;
829 Test_Unknown2
.refs
= 1;
830 med2
.tymed
= TYMED_NULL
;
832 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
834 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
836 ok(med2
.tymed
== TYMED_NULL
, "got tymed %x\n", med2
.tymed
);
837 ok(med2
.pUnkForRelease
!= NULL
, "Incorrectly unmarshalled\n");
838 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
840 HeapFree(GetProcessHeap(), 0, buffer
);
841 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
842 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
844 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
845 med2
.tymed
= TYMED_NULL
;
847 med2
.pUnkForRelease
= NULL
;
848 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, expect_buffer
, &med2
);
849 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
850 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
852 ok(Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
854 HeapFree(GetProcessHeap(), 0, expect_buffer
);
856 /* TYMED_ISTREAM with pUnkForRelease */
858 Test_Unknown
.refs
= 1;
859 Test_Stream
.refs
= 1;
861 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
862 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, 3 * sizeof(DWORD
), (IUnknown
*)stm
, &IID_IStream
);
863 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, expect_size
, unk
, &IID_IUnknown
);
865 expect_buffer
= HeapAlloc(GetProcessHeap(), 0, expect_size
);
866 /* There may be a hole between the two interfaces so init the buffer to something */
867 memset(expect_buffer
, 0xcc, expect_size
);
868 *(DWORD
*)expect_buffer
= TYMED_ISTREAM
;
869 *((DWORD
*)expect_buffer
+ 1) = 0xdeadbeef;
870 *((DWORD
*)expect_buffer
+ 2) = 0xcafe;
871 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
872 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer
+ 3 * sizeof(DWORD
), (IUnknown
*)stm
, &IID_IStream
);
873 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer_end
, unk
, &IID_IUnknown
);
875 med
.tymed
= TYMED_ISTREAM
;
877 med
.pUnkForRelease
= unk
;
879 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
880 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
881 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
883 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
884 memset(buffer
, 0xcc, size
);
885 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
886 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
887 ok(buffer_end
- buffer
== expect_buffer_end
- expect_buffer
, "buffer size mismatch\n");
888 ok(*(DWORD
*)buffer
== TYMED_ISTREAM
, "got %08x\n", *(DWORD
*)buffer
);
889 ok(*((DWORD
*)buffer
+1) != 0, "got %08x\n", *((DWORD
*)buffer
+1));
890 ok(*((DWORD
*)buffer
+2) != 0, "got %08x\n", *((DWORD
*)buffer
+2));
891 ok(!memcmp(buffer
+ 12, expect_buffer
+ 12, (buffer_end
- buffer
) - 12), "buffer mismatch\n");
893 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
894 umcb
.pStubMsg
->IsClient
= client
;
895 umcb
.pStubMsg
->fIsIn
= in
;
896 umcb
.pStubMsg
->fIsOut
= out
;
898 Test_Stream2
.refs
= 1;
899 Test_Unknown2
.refs
= 1;
900 med2
.tymed
= TYMED_ISTREAM
;
901 U(med2
).pstm
= &Test_Stream2
.IStream_iface
;
902 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
904 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
906 ok(med2
.tymed
== TYMED_ISTREAM
, "got tymed %x\n", med2
.tymed
);
907 ok(U(med2
).pstm
!= NULL
, "Incorrectly unmarshalled\n");
908 ok(med2
.pUnkForRelease
!= NULL
, "Incorrectly unmarshalled\n");
909 ok(Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
910 ok(Test_Unknown2
.refs
== 0, "got %d\n", Test_Unknown2
.refs
);
912 HeapFree(GetProcessHeap(), 0, buffer
);
913 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
914 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
916 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
917 med2
.tymed
= TYMED_NULL
;
919 med2
.pUnkForRelease
= NULL
;
920 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, expect_buffer
, &med2
);
921 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
922 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
924 ok(Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
925 ok(Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
927 HeapFree(GetProcessHeap(), 0, expect_buffer
);
929 /* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */
931 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
932 expect_size
= 3 * sizeof(DWORD
);
934 med
.tymed
= TYMED_ISTREAM
;
936 med
.pUnkForRelease
= NULL
;
938 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
939 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
940 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
942 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
943 memset(buffer
, 0xcc, size
);
944 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
945 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
946 ok(buffer_end
- buffer
== expect_size
, "buffer size mismatch\n");
947 ok(*(DWORD
*)buffer
== TYMED_ISTREAM
, "got %08x\n", *(DWORD
*)buffer
);
948 ok(*((DWORD
*)buffer
+1) == 0, "got %08x\n", *((DWORD
*)buffer
+1));
949 ok(*((DWORD
*)buffer
+2) == 0, "got %08x\n", *((DWORD
*)buffer
+2));
951 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
952 umcb
.pStubMsg
->IsClient
= client
;
953 umcb
.pStubMsg
->fIsIn
= in
;
954 umcb
.pStubMsg
->fIsOut
= out
;
956 Test_Stream2
.refs
= 1;
957 Test_Unknown2
.refs
= 1;
958 med2
.tymed
= TYMED_ISTREAM
;
959 U(med2
).pstm
= &Test_Stream2
.IStream_iface
;
960 med2
.pUnkForRelease
= &Test_Unknown2
.IUnknown_iface
;
962 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
964 ok(med2
.tymed
== TYMED_ISTREAM
, "got tymed %x\n", med2
.tymed
);
965 ok(U(med2
).pstm
== NULL
, "Incorrectly unmarshalled\n");
966 ok(med2
.pUnkForRelease
== &Test_Unknown2
.IUnknown_iface
, "Incorrectly unmarshalled\n");
967 ok(Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
968 ok(Test_Unknown2
.refs
== 1, "got %d\n", Test_Unknown2
.refs
);
970 HeapFree(GetProcessHeap(), 0, buffer
);
971 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
972 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
975 static void test_marshal_STGMEDIUM(void)
977 marshal_STGMEDIUM(0, 0, 0);
978 marshal_STGMEDIUM(0, 0, 1);
979 marshal_STGMEDIUM(0, 1, 0);
980 marshal_STGMEDIUM(0, 1, 1);
981 /* For Windows versions post 2003, client side, non-[in,out] STGMEDIUMs get zero-initialised.
982 However since inline stubs don't set fIsIn or fIsOut this behaviour would break
983 ref counting in GetDataHere_Proxy for example, as we'd end up not releasing the original
984 interface. For simplicity we don't test or implement this. */
985 marshal_STGMEDIUM(1, 1, 1);
988 static void test_marshal_SNB(void)
990 static const WCHAR str1W
[] = {'s','t','r','i','n','g','1',0};
991 static const WCHAR str2W
[] = {'s','t','r','2',0};
992 unsigned char *buffer
, *src
, *mbuf
;
993 MIDL_STUB_MESSAGE stub_msg
;
994 WCHAR
**ptrW
, *dataW
;
995 USER_MARSHAL_CB umcb
;
1001 /* 4 bytes alignment */
1003 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1004 size
= SNB_UserSize(&umcb
.Flags
, 3, &snb
);
1005 ok(size
== 16, "Size should be 16, instead of %d\n", size
);
1008 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1009 size
= SNB_UserSize(&umcb
.Flags
, 0, &snb
);
1010 ok(size
== 12, "Size should be 12, instead of %d\n", size
);
1012 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1013 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1014 mbuf
= SNB_UserMarshal(&umcb
.Flags
, buffer
, &snb
);
1015 ok(mbuf
== buffer
+ size
, "got %p, %p\n", mbuf
, buffer
+ size
);
1017 wiresnb
= (RemSNB
*)buffer
;
1018 ok(wiresnb
->ulCntStr
== 0, "got %u\n", wiresnb
->ulCntStr
);
1019 ok(wiresnb
->ulCntChar
== 0, "got %u\n", wiresnb
->ulCntChar
);
1020 ok(*(ULONG
*)wiresnb
->rgString
== 0, "got %u\n", *(ULONG
*)wiresnb
->rgString
);
1023 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1024 SNB_UserUnmarshal(&umcb
.Flags
, buffer
, &snb2
);
1025 ok(snb2
== NULL
, "got %p\n", snb2
);
1027 HeapFree(GetProcessHeap(), 0, buffer
);
1028 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1029 SNB_UserFree(&umcb
.Flags
, &snb2
);
1031 /* block with actual data */
1033 /* allocate source block, n+1 pointers first, then data */
1034 src
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
*)*3 + sizeof(str1W
) + sizeof(str2W
));
1035 ptrW
= (WCHAR
**)src
;
1036 dataW
= *ptrW
= (WCHAR
*)(src
+ 3*sizeof(WCHAR
*));
1038 *ptrW
= (WCHAR
*)(src
+ 3*sizeof(WCHAR
*) + sizeof(str1W
));
1041 lstrcpyW(dataW
, str1W
);
1042 dataW
+= lstrlenW(str1W
) + 1;
1043 lstrcpyW(dataW
, str2W
);
1046 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1047 size
= SNB_UserSize(&umcb
.Flags
, 0, &snb
);
1048 ok(size
== 38, "Size should be 38, instead of %d\n", size
);
1050 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1051 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1052 SNB_UserMarshal(&umcb
.Flags
, buffer
, &snb
);
1054 wiresnb
= (RemSNB
*)buffer
;
1055 ok(wiresnb
->ulCntStr
== 13, "got %u\n", wiresnb
->ulCntStr
);
1056 ok(wiresnb
->ulCntChar
== 2, "got %u\n", wiresnb
->ulCntChar
);
1057 /* payload length is stored one more time, as ULONG */
1058 ok(*(ULONG
*)wiresnb
->rgString
== wiresnb
->ulCntStr
, "got %u\n", *(ULONG
*)wiresnb
->rgString
);
1059 dataW
= &wiresnb
->rgString
[2];
1060 ok(!lstrcmpW(dataW
, str1W
), "marshalled string 0: %s\n", wine_dbgstr_w(dataW
));
1061 dataW
+= sizeof(str1W
)/sizeof(WCHAR
);
1062 ok(!lstrcmpW(dataW
, str2W
), "marshalled string 1: %s\n", wine_dbgstr_w(dataW
));
1064 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1066 g_expect_user_alloc
= TRUE
;
1068 SNB_UserUnmarshal(&umcb
.Flags
, buffer
, &snb2
);
1069 g_expect_user_alloc
= FALSE
;
1072 ok(!lstrcmpW(*ptrW
, str1W
), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW
));
1074 ok(!lstrcmpW(*ptrW
, str2W
), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW
));
1076 ok(*ptrW
== NULL
, "expected terminating NULL ptr, got %p, start %p\n", *ptrW
, snb2
);
1078 HeapFree(GetProcessHeap(), 0, buffer
);
1079 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1081 g_expect_user_free
= TRUE
;
1082 SNB_UserFree(&umcb
.Flags
, &snb2
);
1083 g_expect_user_free
= FALSE
;
1085 HeapFree(GetProcessHeap(), 0, src
);
1088 static void test_marshal_HDC(void)
1090 MIDL_STUB_MESSAGE stub_msg
;
1091 HDC hdc
= GetDC(0), hdc2
;
1092 USER_MARSHAL_CB umcb
;
1093 RPC_MESSAGE rpc_msg
;
1094 unsigned char *buffer
, *buffer_end
;
1098 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1099 size
= HDC_UserSize(&umcb
.Flags
, 1, &hdc
);
1100 ok(size
== 4 + sizeof(*wirehdc
), "Wrong size %d\n", size
);
1102 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1103 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1104 buffer_end
= HDC_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hdc
);
1105 ok(buffer_end
== buffer
+ 4 + sizeof(*wirehdc
), "got %p buffer %p\n", buffer_end
, buffer
);
1106 wirehdc
= (wireHDC
)(buffer
+ 4);
1107 ok(wirehdc
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehdc
->fContext
);
1108 ok(wirehdc
->u
.hInproc
== (LONG_PTR
)hdc
, "Marshaled value should be %p instead of %x\n", hdc
, wirehdc
->u
.hRemote
);
1110 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1111 buffer_end
= HDC_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hdc2
);
1112 ok(buffer_end
== buffer
+ 4 + sizeof(*wirehdc
), "got %p buffer %p\n", buffer_end
, buffer
);
1113 ok(hdc
== hdc2
, "Didn't unmarshal properly\n");
1114 HeapFree(GetProcessHeap(), 0, buffer
);
1116 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1117 HDC_UserFree(&umcb
.Flags
, &hdc2
);
1121 static void test_marshal_HICON(void)
1123 static const BYTE bmp_bits
[1024];
1124 MIDL_STUB_MESSAGE stub_msg
;
1125 HICON hIcon
, hIcon2
;
1126 USER_MARSHAL_CB umcb
;
1127 RPC_MESSAGE rpc_msg
;
1128 unsigned char *buffer
, *buffer_end
;
1129 wireHICON wirehicon
;
1132 hIcon
= CreateIcon(0, 16, 16, 1, 1, bmp_bits
, bmp_bits
);
1133 ok(hIcon
!= 0, "CreateIcon failed\n");
1135 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1136 size
= HICON_UserSize(&umcb
.Flags
, 1, &hIcon
);
1137 ok(size
== 4 + sizeof(*wirehicon
), "Wrong size %d\n", size
);
1139 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1140 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1141 buffer_end
= HICON_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hIcon
);
1142 ok(buffer_end
== buffer
+ 4 + sizeof(*wirehicon
), "got %p buffer %p\n", buffer_end
, buffer
);
1143 wirehicon
= (wireHICON
)(buffer
+ 4);
1144 ok(wirehicon
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehicon
->fContext
);
1145 ok(wirehicon
->u
.hInproc
== (LONG_PTR
)hIcon
, "Marshaled value should be %p instead of %x\n", hIcon
, wirehicon
->u
.hRemote
);
1147 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1148 buffer_end
= HICON_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hIcon2
);
1149 ok(buffer_end
== buffer
+ 4 + sizeof(*wirehicon
), "got %p buffer %p\n", buffer_end
, buffer
);
1150 ok(hIcon
== hIcon2
, "Didn't unmarshal properly\n");
1151 HeapFree(GetProcessHeap(), 0, buffer
);
1153 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1154 HICON_UserFree(&umcb
.Flags
, &hIcon2
);
1158 static void test_marshal_HBRUSH(void)
1160 MIDL_STUB_MESSAGE stub_msg
;
1161 HBRUSH hBrush
, hBrush2
;
1162 USER_MARSHAL_CB umcb
;
1163 RPC_MESSAGE rpc_msg
;
1164 unsigned char *buffer
, *buffer_end
;
1166 wireHBRUSH wirehbrush
;
1169 logbrush
.lbStyle
= BS_SOLID
;
1170 logbrush
.lbColor
= RGB(0, 0, 0);
1171 logbrush
.lbHatch
= 0;
1173 hBrush
= CreateBrushIndirect(&logbrush
);
1174 ok(hBrush
!= 0, "CreateBrushIndirect failed\n");
1176 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1177 size
= HBRUSH_UserSize(&umcb
.Flags
, 1, &hBrush
);
1178 ok(size
== 4 + sizeof(*wirehbrush
), "Wrong size %d\n", size
);
1180 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
1181 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1182 buffer_end
= HBRUSH_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hBrush
);
1183 ok(buffer_end
== buffer
+ 4 + sizeof(*wirehbrush
), "got %p buffer %p\n", buffer_end
, buffer
);
1184 wirehbrush
= (wireHBRUSH
)(buffer
+ 4);
1185 ok(wirehbrush
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehbrush
->fContext
);
1186 ok(wirehbrush
->u
.hInproc
== (LONG_PTR
)hBrush
, "Marshaled value should be %p instead of %x\n", hBrush
, wirehbrush
->u
.hRemote
);
1188 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1189 buffer_end
= HBRUSH_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hBrush2
);
1190 ok(buffer_end
== buffer
+ 4 + sizeof(*wirehbrush
), "got %p buffer %p\n", buffer_end
, buffer
);
1191 ok(hBrush
== hBrush2
, "Didn't unmarshal properly\n");
1192 HeapFree(GetProcessHeap(), 0, buffer
);
1194 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1195 HBRUSH_UserFree(&umcb
.Flags
, &hBrush2
);
1196 DeleteObject(hBrush
);
1199 static void test_marshal_HBITMAP(void)
1201 static const ULONG header_size
= FIELD_OFFSET(userBITMAP
, cbSize
);
1202 static BYTE bmp_bits
[1024];
1203 MIDL_STUB_MESSAGE stub_msg
;
1204 HBITMAP hBitmap
, hBitmap2
;
1205 USER_MARSHAL_CB umcb
;
1206 RPC_MESSAGE rpc_msg
;
1207 unsigned char *buffer
, *buffer_end
;
1208 unsigned char bitmap
[1024];
1209 ULONG size
, bitmap_size
;
1211 hBitmap
= CreateBitmap(16, 16, 1, 1, bmp_bits
);
1212 ok(hBitmap
!= 0, "CreateBitmap failed\n");
1213 size
= GetObjectA(hBitmap
, sizeof(bitmap
), bitmap
);
1214 ok(size
!= 0, "GetObject failed\n");
1215 bitmap_size
= GetBitmapBits(hBitmap
, 0, NULL
);
1216 ok(bitmap_size
!= 0, "GetBitmapBits failed\n");
1218 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_INPROC
);
1219 size
= HBITMAP_UserSize(&umcb
.Flags
, 1, &hBitmap
);
1220 ok(size
== 0xc, "Wrong size %d\n", size
);
1221 buffer
= HeapAlloc(GetProcessHeap(), 0, size
+ 4);
1222 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_INPROC
);
1223 buffer_end
= HBITMAP_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hBitmap
);
1224 ok(buffer_end
== buffer
+ 0xc, "HBITMAP_UserMarshal() returned wrong size %d\n", (LONG
)(buffer_end
- buffer
));
1225 ok(*(ULONG
*)(buffer
+ 0x4) == WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", *(ULONG
*)(buffer
+ 0x4));
1226 ok(*(ULONG
*)(buffer
+ 0x8) == (ULONG
)(ULONG_PTR
)hBitmap
, "wirestgm + 0x4 should be bitmap handle instead of 0x%08x\n", *(ULONG
*)(buffer
+ 0x8));
1228 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_INPROC
);
1229 HBITMAP_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hBitmap2
);
1230 ok(hBitmap2
!= NULL
, "Didn't unmarshal properly\n");
1231 HeapFree(GetProcessHeap(), 0, buffer
);
1233 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_INPROC
);
1234 HBITMAP_UserFree(&umcb
.Flags
, &hBitmap2
);
1236 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1237 size
= HBITMAP_UserSize(&umcb
.Flags
, 1, &hBitmap
);
1238 ok(size
== 0x10 + header_size
+ bitmap_size
||
1239 broken(size
== 0x14 + header_size
+ bitmap_size
), /* Windows adds 4 extra (unused) bytes */
1240 "Wrong size %d\n", size
);
1242 buffer
= HeapAlloc(GetProcessHeap(), 0, size
+ 4);
1243 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1244 buffer_end
= HBITMAP_UserMarshal(&umcb
.Flags
, buffer
+ 1, &hBitmap
);
1245 ok(buffer_end
== buffer
+ 0x10 + header_size
+ bitmap_size
, "HBITMAP_UserMarshal() returned wrong size %d\n", (LONG
)(buffer_end
- buffer
));
1246 ok(*(ULONG
*)(buffer
+ 0x4) == WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)buffer
);
1247 ok(*(ULONG
*)(buffer
+ 0x8) == (ULONG
)(ULONG_PTR
)hBitmap
, "wirestgm + 0x4 should be bitmap handle instead of 0x%08x\n", *(ULONG
*)(buffer
+ 0x4));
1248 ok(*(ULONG
*)(buffer
+ 0xc) == (ULONG
)(ULONG_PTR
)bitmap_size
, "wirestgm + 0x8 should be bitmap size instead of 0x%08x\n", *(ULONG
*)(buffer
+ 0x4));
1249 ok(!memcmp(buffer
+ 0x10, bitmap
, header_size
), "buffer mismatch\n");
1250 ok(!memcmp(buffer
+ 0x10 + header_size
, bmp_bits
, bitmap_size
), "buffer mismatch\n");
1252 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
1253 HBITMAP_UserUnmarshal(&umcb
.Flags
, buffer
+ 1, &hBitmap2
);
1254 ok(hBitmap2
!= NULL
, "Didn't unmarshal properly\n");
1255 HeapFree(GetProcessHeap(), 0, buffer
);
1257 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
1258 HBITMAP_UserFree(&umcb
.Flags
, &hBitmap2
);
1259 DeleteObject(hBitmap
);
1264 IDataObject IDataObject_iface
;
1267 static HRESULT WINAPI
obj_QueryInterface(IDataObject
*iface
, REFIID iid
, void **obj
)
1271 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
1272 IsEqualGUID(iid
, &IID_IDataObject
))
1277 IDataObject_AddRef(iface
);
1281 return E_NOINTERFACE
;
1284 static ULONG WINAPI
obj_AddRef(IDataObject
*iface
)
1289 static ULONG WINAPI
obj_Release(IDataObject
*iface
)
1294 static HRESULT WINAPI
obj_DO_GetDataHere(IDataObject
*iface
, FORMATETC
*fmt
,
1297 ok( med
->pUnkForRelease
== NULL
, "got %p\n", med
->pUnkForRelease
);
1299 if (fmt
->cfFormat
== 2)
1301 IStream_Release(U(med
)->pstm
);
1302 U(med
)->pstm
= &Test_Stream2
.IStream_iface
;
1308 static const IDataObjectVtbl obj_data_object_vtbl
=
1315 NULL
, /* QueryGetData */
1316 NULL
, /* GetCanonicalFormatEtc */
1318 NULL
, /* EnumFormatEtc */
1320 NULL
, /* DUnadvise */
1321 NULL
/* EnumDAdvise */
1324 static struct obj obj
=
1326 {&obj_data_object_vtbl
}
1329 static void test_GetDataHere_Proxy(void)
1335 static const LARGE_INTEGER zero
;
1340 hr
= CreateStreamOnHGlobal( NULL
, TRUE
, &stm
);
1341 ok( hr
== S_OK
, "got %08x\n", hr
);
1342 tid
= start_host_object2( stm
, &IID_IDataObject
, (IUnknown
*)&obj
.IDataObject_iface
, MSHLFLAGS_NORMAL
, NULL
, &thread
);
1344 IStream_Seek( stm
, zero
, STREAM_SEEK_SET
, NULL
);
1345 hr
= CoUnmarshalInterface( stm
, &IID_IDataObject
, (void **)&data
);
1346 ok( hr
== S_OK
, "got %08x\n", hr
);
1347 IStream_Release( stm
);
1349 Test_Stream
.refs
= 1;
1350 Test_Stream2
.refs
= 1;
1351 Test_Unknown
.refs
= 1;
1355 fmt
.dwAspect
= DVASPECT_CONTENT
;
1358 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1360 fmt
.tymed
= med
.tymed
= TYMED_NULL
;
1361 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1362 ok( hr
== DV_E_TYMED
, "got %08x\n", hr
);
1364 for (fmt
.tymed
= TYMED_HGLOBAL
; fmt
.tymed
<= TYMED_ENHMF
; fmt
.tymed
<<= 1)
1366 med
.tymed
= fmt
.tymed
;
1367 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1368 ok( hr
== (fmt
.tymed
<= TYMED_ISTORAGE
? S_OK
: DV_E_TYMED
), "got %08x for tymed %d\n", hr
, fmt
.tymed
);
1369 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1372 fmt
.tymed
= TYMED_ISTREAM
;
1373 med
.tymed
= TYMED_ISTORAGE
;
1374 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1375 ok( hr
== DV_E_TYMED
, "got %08x\n", hr
);
1377 fmt
.tymed
= med
.tymed
= TYMED_ISTREAM
;
1378 U(med
).pstm
= &Test_Stream
.IStream_iface
;
1379 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1381 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1382 ok( hr
== S_OK
, "got %08x\n", hr
);
1384 ok( U(med
).pstm
== &Test_Stream
.IStream_iface
, "stm changed\n" );
1385 ok( med
.pUnkForRelease
== &Test_Unknown
.IUnknown_iface
, "punk changed\n" );
1387 ok( Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
1388 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1391 fmt
.tymed
= med
.tymed
= TYMED_ISTREAM
;
1392 U(med
).pstm
= &Test_Stream
.IStream_iface
;
1393 med
.pUnkForRelease
= &Test_Unknown
.IUnknown_iface
;
1395 hr
= IDataObject_GetDataHere( data
, &fmt
, &med
);
1396 ok( hr
== S_OK
, "got %08x\n", hr
);
1398 ok( U(med
).pstm
== &Test_Stream
.IStream_iface
, "stm changed\n" );
1399 ok( med
.pUnkForRelease
== &Test_Unknown
.IUnknown_iface
, "punk changed\n" );
1401 ok( Test_Stream
.refs
== 1, "got %d\n", Test_Stream
.refs
);
1402 ok( Test_Unknown
.refs
== 1, "got %d\n", Test_Unknown
.refs
);
1403 ok( Test_Stream2
.refs
== 0, "got %d\n", Test_Stream2
.refs
);
1405 IDataObject_Release( data
);
1406 end_host_object( tid
, thread
);
1409 START_TEST(usrmarshal
)
1411 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1413 test_marshal_CLIPFORMAT();
1414 test_marshal_HWND();
1415 test_marshal_HGLOBAL();
1416 test_marshal_HENHMETAFILE();
1417 test_marshal_HMETAFILE();
1418 test_marshal_HMETAFILEPICT();
1419 test_marshal_WdtpInterfacePointer();
1420 test_marshal_STGMEDIUM();
1423 test_marshal_HICON();
1424 test_marshal_HBRUSH();
1425 test_marshal_HBITMAP();
1427 test_GetDataHere_Proxy();