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 static void * WINAPI
user_allocate(SIZE_T size
)
49 return CoTaskMemAlloc(size
);
52 static void WINAPI
user_free(void *p
)
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 static const char cf_marshaled
[] =
91 static void test_marshal_CLIPFORMAT(void)
94 MIDL_STUB_MESSAGE stub_msg
;
96 unsigned char *buffer
;
98 CLIPFORMAT cf
= RegisterClipboardFormatA("MyFormat");
101 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
102 size
= CLIPFORMAT_UserSize(&umcb
.Flags
, 0, &cf
);
103 ok(size
== 8 + sizeof(cf_marshaled
) ||
104 broken(size
== 12 + sizeof(cf_marshaled
)) || /* win64 adds 4 extra (unused) bytes */
105 broken(size
== 8 + sizeof(cf_marshaled
) - 2), /* win9x and winnt don't include the '\0' */
106 "CLIPFORMAT: Wrong size %d\n", size
);
108 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
109 memset( buffer
, 0xcc, size
);
110 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
111 CLIPFORMAT_UserMarshal(&umcb
.Flags
, buffer
, &cf
);
112 ok(*(LONG
*)(buffer
+ 0) == WDT_REMOTE_CALL
, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(LONG
*)(buffer
+ 0));
113 ok(*(DWORD
*)(buffer
+ 4) == cf
, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04x\n", cf
, *(DWORD
*)(buffer
+ 4));
114 ok(!memcmp(buffer
+ 8, cf_marshaled
, min( sizeof(cf_marshaled
), size
-8 )), "Marshaled data differs\n");
115 if (size
> sizeof(cf_marshaled
) + 8) /* make sure the extra bytes are not used */
116 for (i
= sizeof(cf_marshaled
) + 8; i
< size
; i
++)
117 ok( buffer
[i
] == 0xcc, "buffer offset %u has been set to %x\n", i
, buffer
[i
] );
119 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
120 CLIPFORMAT_UserUnmarshal(&umcb
.Flags
, buffer
, &cf2
);
121 ok(cf
== cf2
, "CLIPFORMAT: Didn't unmarshal properly\n");
122 HeapFree(GetProcessHeap(), 0, buffer
);
124 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
125 CLIPFORMAT_UserFree(&umcb
.Flags
, &cf2
);
128 static void test_marshal_HWND(void)
130 USER_MARSHAL_CB umcb
;
131 MIDL_STUB_MESSAGE stub_msg
;
133 unsigned char *buffer
;
135 HWND hwnd
= GetDesktopWindow();
139 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
140 size
= HWND_UserSize(&umcb
.Flags
, 0, &hwnd
);
141 ok(size
== sizeof(*wirehwnd
), "Wrong size %d\n", size
);
143 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
144 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
145 HWND_UserMarshal(&umcb
.Flags
, buffer
, &hwnd
);
146 wirehwnd
= (wireHWND
)buffer
;
147 ok(wirehwnd
->fContext
== WDT_INPROC_CALL
, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehwnd
->fContext
);
148 ok(wirehwnd
->u
.hInproc
== (LONG_PTR
)hwnd
, "Marshaled value should be %p instead of %x\n", hwnd
, wirehwnd
->u
.hRemote
);
150 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
151 HWND_UserUnmarshal(&umcb
.Flags
, buffer
, &hwnd2
);
152 ok(hwnd
== hwnd2
, "Didn't unmarshal properly\n");
153 HeapFree(GetProcessHeap(), 0, buffer
);
155 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
156 HWND_UserFree(&umcb
.Flags
, &hwnd2
);
159 static void test_marshal_HGLOBAL(void)
161 USER_MARSHAL_CB umcb
;
162 MIDL_STUB_MESSAGE stub_msg
;
164 unsigned char *buffer
;
165 ULONG size
, block_size
;
168 unsigned char *wirehglobal
;
172 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
173 size
= HGLOBAL_UserSize(&umcb
.Flags
, 0, &hglobal
);
174 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
175 * here - Wine doesn't have to emulate that */
176 ok((size
== 8) || broken(size
== 12) || broken(size
== 16), "Size should be 8, instead of %d\n", size
);
177 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
178 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
179 HGLOBAL_UserMarshal(&umcb
.Flags
, buffer
, &hglobal
);
180 wirehglobal
= buffer
;
181 ok(*(ULONG
*)wirehglobal
== WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)wirehglobal
);
182 wirehglobal
+= sizeof(ULONG
);
183 ok(*(ULONG
*)wirehglobal
== 0, "buffer+4 should be HGLOBAL\n");
184 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
185 HGLOBAL_UserUnmarshal(&umcb
.Flags
, buffer
, &hglobal2
);
186 ok(hglobal2
== hglobal
, "Didn't unmarshal properly\n");
187 HeapFree(GetProcessHeap(), 0, buffer
);
188 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
189 HGLOBAL_UserFree(&umcb
.Flags
, &hglobal2
);
192 for(block_size
= 0; block_size
<= 17; block_size
++)
194 ULONG actual_size
, expected_size
;
196 hglobal
= GlobalAlloc(0, block_size
);
197 buffer
= GlobalLock(hglobal
);
198 for (i
= 0; i
< block_size
; i
++)
200 GlobalUnlock(hglobal
);
201 actual_size
= GlobalSize(hglobal
);
202 expected_size
= actual_size
+ 5 * sizeof(DWORD
);
203 trace("%d: actual size %d\n", block_size
, actual_size
);
204 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
205 size
= HGLOBAL_UserSize(&umcb
.Flags
, 0, &hglobal
);
206 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
207 * here - Wine doesn't have to emulate that */
208 ok(size
== expected_size
||
209 broken(size
== expected_size
+ 4) ||
210 broken(size
== expected_size
+ 8),
211 "%d: got size %d\n", block_size
, size
);
212 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
213 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
214 HGLOBAL_UserMarshal(&umcb
.Flags
, buffer
, &hglobal
);
215 wirehglobal
= buffer
;
216 ok(*(ULONG
*)wirehglobal
== WDT_REMOTE_CALL
, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG
*)wirehglobal
);
217 wirehglobal
+= sizeof(ULONG
);
218 ok(*(ULONG
*)wirehglobal
== (ULONG
)(ULONG_PTR
)hglobal
, "buffer+0x4 should be HGLOBAL\n");
219 wirehglobal
+= sizeof(ULONG
);
220 ok(*(ULONG
*)wirehglobal
== actual_size
, "%d: buffer+0x8 %08x\n", block_size
, *(ULONG
*)wirehglobal
);
221 wirehglobal
+= sizeof(ULONG
);
222 ok(*(ULONG
*)wirehglobal
== (ULONG
)(ULONG_PTR
)hglobal
, "buffer+0xc should be HGLOBAL\n");
223 wirehglobal
+= sizeof(ULONG
);
224 ok(*(ULONG
*)wirehglobal
== actual_size
, "%d: buffer+0x10 %08x\n", block_size
, *(ULONG
*)wirehglobal
);
225 wirehglobal
+= sizeof(ULONG
);
226 for (i
= 0; i
< block_size
; i
++)
227 ok(wirehglobal
[i
] == i
, "buffer+0x%x should be %d\n", 0x10 + i
, i
);
229 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_LOCAL
);
230 HGLOBAL_UserUnmarshal(&umcb
.Flags
, buffer
, &hglobal2
);
231 ok(hglobal2
!= NULL
, "Didn't unmarshal properly\n");
232 HeapFree(GetProcessHeap(), 0, buffer
);
233 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_LOCAL
);
234 HGLOBAL_UserFree(&umcb
.Flags
, &hglobal2
);
239 static HENHMETAFILE
create_emf(void)
241 const RECT rect
= {0, 0, 100, 100};
242 HDC hdc
= CreateEnhMetaFile(NULL
, NULL
, &rect
, "HENHMETAFILE Marshaling Test\0Test\0\0");
243 ExtTextOut(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
244 return CloseEnhMetaFile(hdc
);
247 static void test_marshal_HENHMETAFILE(void)
249 USER_MARSHAL_CB umcb
;
250 MIDL_STUB_MESSAGE stub_msg
;
252 unsigned char *buffer
;
255 HENHMETAFILE hemf2
= NULL
;
256 unsigned char *wirehemf
;
260 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
261 size
= HENHMETAFILE_UserSize(&umcb
.Flags
, 0, &hemf
);
262 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
263 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
264 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
265 HENHMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hemf
);
267 ok(*(DWORD
*)wirehemf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehemf
);
268 wirehemf
+= sizeof(DWORD
);
269 ok(*(DWORD
*)wirehemf
== (DWORD
)(DWORD_PTR
)hemf
, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD
*)wirehemf
);
270 wirehemf
+= sizeof(DWORD
);
271 ok(*(DWORD
*)wirehemf
== (size
- 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehemf
);
272 wirehemf
+= sizeof(DWORD
);
273 ok(*(DWORD
*)wirehemf
== (size
- 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehemf
);
274 wirehemf
+= sizeof(DWORD
);
275 ok(*(DWORD
*)wirehemf
== EMR_HEADER
, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD
*)wirehemf
);
276 wirehemf
+= sizeof(DWORD
);
277 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
280 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
281 HENHMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hemf2
);
282 ok(hemf2
!= NULL
, "HENHMETAFILE didn't unmarshal\n");
283 HeapFree(GetProcessHeap(), 0, buffer
);
284 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
285 HENHMETAFILE_UserFree(&umcb
.Flags
, &hemf2
);
286 DeleteEnhMetaFile(hemf
);
291 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
292 size
= HENHMETAFILE_UserSize(&umcb
.Flags
, 0, &hemf
);
293 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
294 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
295 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
296 HENHMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hemf
);
298 ok(*(DWORD
*)wirehemf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehemf
);
299 wirehemf
+= sizeof(DWORD
);
300 ok(*(DWORD
*)wirehemf
== (DWORD
)(DWORD_PTR
)hemf
, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD
*)wirehemf
);
301 wirehemf
+= sizeof(DWORD
);
303 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
304 HENHMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hemf2
);
305 ok(hemf2
== NULL
, "NULL HENHMETAFILE didn't unmarshal\n");
306 HeapFree(GetProcessHeap(), 0, buffer
);
307 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
308 HENHMETAFILE_UserFree(&umcb
.Flags
, &hemf2
);
311 static HMETAFILE
create_mf(void)
313 RECT rect
= {0, 0, 100, 100};
314 HDC hdc
= CreateMetaFile(NULL
);
315 ExtTextOut(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
316 return CloseMetaFile(hdc
);
319 static void test_marshal_HMETAFILE(void)
321 USER_MARSHAL_CB umcb
;
322 MIDL_STUB_MESSAGE stub_msg
;
324 unsigned char *buffer
;
327 HMETAFILE hmf2
= NULL
;
328 unsigned char *wirehmf
;
332 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
333 size
= HMETAFILE_UserSize(&umcb
.Flags
, 0, &hmf
);
334 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
335 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
336 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
337 HMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hmf
);
339 ok(*(DWORD
*)wirehmf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmf
);
340 wirehmf
+= sizeof(DWORD
);
341 ok(*(DWORD
*)wirehmf
== (DWORD
)(DWORD_PTR
)hmf
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmf
);
342 wirehmf
+= sizeof(DWORD
);
343 ok(*(DWORD
*)wirehmf
== (size
- 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
344 wirehmf
+= sizeof(DWORD
);
345 ok(*(DWORD
*)wirehmf
== (size
- 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
346 wirehmf
+= sizeof(DWORD
);
347 ok(*(WORD
*)wirehmf
== 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmf
);
348 wirehmf
+= sizeof(DWORD
);
349 /* ... rest of data not tested - refer to tests for GetMetaFileBits
352 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
353 HMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hmf2
);
354 ok(hmf2
!= NULL
, "HMETAFILE didn't unmarshal\n");
355 HeapFree(GetProcessHeap(), 0, buffer
);
356 HMETAFILE_UserFree(&umcb
.Flags
, &hmf2
);
362 size
= HMETAFILE_UserSize(&umcb
.Flags
, 0, &hmf
);
363 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
364 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
365 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
366 HMETAFILE_UserMarshal(&umcb
.Flags
, buffer
, &hmf
);
368 ok(*(DWORD
*)wirehmf
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmf
);
369 wirehmf
+= sizeof(DWORD
);
370 ok(*(DWORD
*)wirehmf
== (DWORD
)(DWORD_PTR
)hmf
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmf
);
371 wirehmf
+= sizeof(DWORD
);
373 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
374 HMETAFILE_UserUnmarshal(&umcb
.Flags
, buffer
, &hmf2
);
375 ok(hmf2
== NULL
, "NULL HMETAFILE didn't unmarshal\n");
376 HeapFree(GetProcessHeap(), 0, buffer
);
377 HMETAFILE_UserFree(&umcb
.Flags
, &hmf2
);
380 #define USER_MARSHAL_PTR_PREFIX \
381 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
382 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
384 static void test_marshal_HMETAFILEPICT(void)
386 USER_MARSHAL_CB umcb
;
387 MIDL_STUB_MESSAGE stub_msg
;
389 unsigned char *buffer
, *buffer_end
;
392 HMETAFILEPICT hmfp2
= NULL
;
394 unsigned char *wirehmfp
;
396 hmfp
= GlobalAlloc(GMEM_MOVEABLE
, sizeof(*pmfp
));
397 pmfp
= GlobalLock(hmfp
);
398 pmfp
->mm
= MM_ISOTROPIC
;
401 pmfp
->hMF
= create_mf();
404 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
405 size
= HMETAFILEPICT_UserSize(&umcb
.Flags
, 0, &hmfp
);
406 ok(size
> 20, "size should be at least 20 bytes, not %d\n", size
);
407 trace("size is %d\n", size
);
408 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
409 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
410 buffer_end
= HMETAFILEPICT_UserMarshal(&umcb
.Flags
, buffer
, &hmfp
);
412 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
413 wirehmfp
+= sizeof(DWORD
);
414 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)hmfp
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
415 wirehmfp
+= sizeof(DWORD
);
416 ok(*(DWORD
*)wirehmfp
== MM_ISOTROPIC
, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
417 wirehmfp
+= sizeof(DWORD
);
418 ok(*(DWORD
*)wirehmfp
== 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
419 wirehmfp
+= sizeof(DWORD
);
420 ok(*(DWORD
*)wirehmfp
== 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
421 wirehmfp
+= sizeof(DWORD
);
422 ok(*(DWORD
*)wirehmfp
== USER_MARSHAL_PTR_PREFIX
, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
423 wirehmfp
+= sizeof(DWORD
);
424 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
425 wirehmfp
+= sizeof(DWORD
);
426 pmfp
= GlobalLock(hmfp
);
427 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)pmfp
->hMF
, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
429 wirehmfp
+= sizeof(DWORD
);
430 /* Note use (buffer_end - buffer) instead of size here, because size is an
431 * overestimate with native */
432 ok(*(DWORD
*)wirehmfp
== (buffer_end
- buffer
- 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
433 wirehmfp
+= sizeof(DWORD
);
434 ok(*(DWORD
*)wirehmfp
== (buffer_end
- buffer
- 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
435 wirehmfp
+= sizeof(DWORD
);
436 ok(*(WORD
*)wirehmfp
== 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
437 wirehmfp
+= sizeof(DWORD
);
438 /* ... rest of data not tested - refer to tests for GetMetaFileBits
441 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
442 HMETAFILEPICT_UserUnmarshal(&umcb
.Flags
, buffer
, &hmfp2
);
443 ok(hmfp2
!= NULL
, "HMETAFILEPICT didn't unmarshal\n");
444 HeapFree(GetProcessHeap(), 0, buffer
);
445 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
446 HMETAFILEPICT_UserFree(&umcb
.Flags
, &hmfp2
);
447 pmfp
= GlobalLock(hmfp
);
448 DeleteMetaFile(pmfp
->hMF
);
455 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
456 size
= HMETAFILEPICT_UserSize(&umcb
.Flags
, 0, &hmfp
);
457 ok(size
== 8, "size should be 8 bytes, not %d\n", size
);
458 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
459 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
460 HMETAFILEPICT_UserMarshal(&umcb
.Flags
, buffer
, &hmfp
);
462 ok(*(DWORD
*)wirehmfp
== WDT_REMOTE_CALL
, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
463 wirehmfp
+= sizeof(DWORD
);
464 ok(*(DWORD
*)wirehmfp
== (DWORD
)(DWORD_PTR
)hmfp
, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD
*)wirehmfp
);
465 wirehmfp
+= sizeof(DWORD
);
468 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
469 HMETAFILEPICT_UserUnmarshal(&umcb
.Flags
, buffer
, &hmfp2
);
470 ok(hmfp2
== NULL
, "NULL HMETAFILE didn't unmarshal\n");
471 HeapFree(GetProcessHeap(), 0, buffer
);
472 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
473 HMETAFILEPICT_UserFree(&umcb
.Flags
, &hmfp2
);
476 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
481 if (ppvObj
== NULL
) return E_POINTER
;
483 if (IsEqualGUID(riid
, &IID_IUnknown
))
486 IUnknown_AddRef(iface
);
491 return E_NOINTERFACE
;
494 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
496 return 2; /* non-heap-based object */
499 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
501 return 1; /* non-heap-based object */
504 static const IUnknownVtbl TestUnknown_Vtbl
=
506 Test_IUnknown_QueryInterface
,
507 Test_IUnknown_AddRef
,
508 Test_IUnknown_Release
,
511 static HRESULT WINAPI
Test_IStream_QueryInterface(IStream
*iface
,
512 REFIID riid
, LPVOID
*ppvObj
)
514 if (ppvObj
== NULL
) return E_POINTER
;
516 if (IsEqualIID(riid
, &IID_IUnknown
) ||
517 IsEqualIID(riid
, &IID_IStream
))
520 IStream_AddRef(iface
);
525 return E_NOINTERFACE
;
528 static ULONG WINAPI
Test_IStream_AddRef(IStream
*iface
)
530 return 2; /* non-heap-based object */
533 static ULONG WINAPI
Test_IStream_Release(IStream
*iface
)
535 return 1; /* non-heap-based object */
538 static const IStreamVtbl TestStream_Vtbl
=
540 Test_IStream_QueryInterface
,
543 /* the rest can be NULLs */
546 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
547 static IStream Test_Stream
= { &TestStream_Vtbl
};
549 ULONG __RPC_USER
WdtpInterfacePointer_UserSize(ULONG
*, ULONG
, ULONG
, IUnknown
*, REFIID
);
550 unsigned char * __RPC_USER
WdtpInterfacePointer_UserMarshal(ULONG
*, ULONG
, unsigned char *, IUnknown
*, REFIID
);
551 unsigned char * __RPC_USER
WdtpInterfacePointer_UserUnmarshal(ULONG
*, unsigned char *, IUnknown
**, REFIID
);
552 void __RPC_USER
WdtpInterfacePointer_UserFree(IUnknown
*);
554 static void marshal_WdtpInterfacePointer(DWORD umcb_ctx
, DWORD ctx
)
556 USER_MARSHAL_CB umcb
;
557 MIDL_STUB_MESSAGE stub_msg
;
559 unsigned char *buffer
, *buffer_end
;
563 unsigned char *wireip
;
564 HGLOBAL h
= GlobalAlloc(GMEM_MOVEABLE
, 0);
571 /* shows that the WdtpInterfacePointer functions don't marshal anything for
572 * NULL pointers, so code using these functions must handle that case
576 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, umcb_ctx
);
577 size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, ctx
, 0, unk
, &IID_IUnknown
);
578 ok(size
== 0, "size should be 0 bytes, not %d\n", size
);
579 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
580 buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, ctx
, buffer
, unk
, &IID_IUnknown
);
582 HeapFree(GetProcessHeap(), 0, buffer
);
584 /* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then
585 the result of CoMarshalInterface called with the LOWORD of the ctx */
589 CreateStreamOnHGlobal(h
, TRUE
, &stm
);
590 CoMarshalInterface(stm
, &IID_IUnknown
, unk
, LOWORD(ctx
), NULL
, MSHLFLAGS_NORMAL
);
592 IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &pos
);
593 marshal_size
= pos
.u
.LowPart
;
594 marshal_data
= GlobalLock(h
);
595 trace("marshal_size %x\n", marshal_size
);
597 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, umcb_ctx
);
598 size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, ctx
, 0, unk
, &IID_IUnknown
);
599 ok(size
>= marshal_size
+ 2 * sizeof(DWORD
), "marshal size %x got %x\n", marshal_size
, size
);
600 trace("WdtpInterfacePointer_UserSize returned %x\n", size
);
601 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
602 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, umcb_ctx
);
603 buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, ctx
, buffer
, unk
, &IID_IUnknown
);
606 ok(buffer_end
== buffer
+ marshal_size
+ 2 * sizeof(DWORD
), "buffer_end %p buffer %p (diff %x)\n", buffer_end
, buffer
, buffer_end
- buffer
);
608 ok(*(DWORD
*)wireip
== marshal_size
, "wireip + 0x0 should be %x instead of %x\n", marshal_size
, *(DWORD
*)wireip
);
609 wireip
+= sizeof(DWORD
);
610 ok(*(DWORD
*)wireip
== marshal_size
, "wireip + 0x4 should be %x instead of %x\n", marshal_size
, *(DWORD
*)wireip
);
611 wireip
+= sizeof(DWORD
);
613 ok(!memcmp(marshal_data
, wireip
, marshal_size
), "buffer mismatch\n");
616 IStream_Seek(stm
, zero
, STREAM_SEEK_SET
, NULL
);
617 CoReleaseMarshalData(stm
);
618 IStream_Release(stm
);
621 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, umcb_ctx
);
622 WdtpInterfacePointer_UserUnmarshal(&umcb
.Flags
, buffer
, &unk2
, &IID_IUnknown
);
623 ok(unk2
!= NULL
, "IUnknown object didn't unmarshal properly\n");
624 HeapFree(GetProcessHeap(), 0, buffer
);
625 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_INPROC
);
626 WdtpInterfacePointer_UserFree(unk2
);
629 static void test_marshal_WdtpInterfacePointer(void)
632 * There are two places where we can pass the marshalling ctx: as
633 * part of the umcb and as a separate flag. The loword of that
634 * separate flag field is what matters.
637 /* All three are marshalled as inproc */
638 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_INPROC
);
639 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE
, MSHCTX_INPROC
);
640 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MAKELONG(MSHCTX_INPROC
, 0xffff));
642 /* All three are marshalled as remote */
643 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MSHCTX_DIFFERENTMACHINE
);
644 marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE
, MSHCTX_DIFFERENTMACHINE
);
645 marshal_WdtpInterfacePointer(MSHCTX_INPROC
, MAKELONG(MSHCTX_DIFFERENTMACHINE
, 0xffff));
648 static void test_marshal_STGMEDIUM(void)
650 USER_MARSHAL_CB umcb
;
651 MIDL_STUB_MESSAGE stub_msg
;
653 unsigned char *buffer
, *buffer_end
, *expect_buffer
, *expect_buffer_end
;
654 ULONG size
, expect_size
;
656 IUnknown
*unk
= &Test_Unknown
;
657 IStream
*stm
= &Test_Stream
;
659 /* TYMED_NULL with pUnkForRelease */
661 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
662 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, 2 * sizeof(DWORD
), unk
, &IID_IUnknown
);
663 expect_buffer
= HeapAlloc(GetProcessHeap(), 0, expect_size
);
664 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
665 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer
+ 2 * sizeof(DWORD
), unk
, &IID_IUnknown
);
667 med
.tymed
= TYMED_NULL
;
669 med
.pUnkForRelease
= unk
;
671 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
672 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
673 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
675 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
676 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
677 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
678 ok(buffer_end
- buffer
== expect_buffer_end
- expect_buffer
, "buffer size mismatch\n");
679 ok(*(DWORD
*)buffer
== TYMED_NULL
, "got %08x\n", *(DWORD
*)buffer
);
680 ok(*((DWORD
*)buffer
+1) != 0, "got %08x\n", *((DWORD
*)buffer
+1));
681 ok(!memcmp(buffer
+8, expect_buffer
+ 8, expect_buffer_end
- expect_buffer
- 8), "buffer mismatch\n");
683 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
685 /* native crashes if this is uninitialised, presumably because it
686 tries to release it */
687 med2
.tymed
= TYMED_NULL
;
689 med2
.pUnkForRelease
= NULL
;
691 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
693 ok(med2
.tymed
== TYMED_NULL
, "got tymed %x\n", med2
.tymed
);
694 ok(med2
.pUnkForRelease
!= NULL
, "Incorrectly unmarshalled\n");
696 HeapFree(GetProcessHeap(), 0, buffer
);
697 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
698 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
700 HeapFree(GetProcessHeap(), 0, expect_buffer
);
702 /* TYMED_ISTREAM with pUnkForRelease */
704 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
705 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, 3 * sizeof(DWORD
), (IUnknown
*)stm
, &IID_IStream
);
706 expect_size
= WdtpInterfacePointer_UserSize(&umcb
.Flags
, umcb
.Flags
, expect_size
, unk
, &IID_IUnknown
);
708 expect_buffer
= HeapAlloc(GetProcessHeap(), 0, expect_size
);
709 /* There may be a hole between the two interfaces so init the buffer to something */
710 memset(expect_buffer
, 0xcc, expect_size
);
711 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, expect_buffer
, expect_size
, MSHCTX_DIFFERENTMACHINE
);
712 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer
+ 3 * sizeof(DWORD
), (IUnknown
*)stm
, &IID_IStream
);
713 expect_buffer_end
= WdtpInterfacePointer_UserMarshal(&umcb
.Flags
, umcb
.Flags
, expect_buffer_end
, unk
, &IID_IUnknown
);
715 med
.tymed
= TYMED_ISTREAM
;
717 med
.pUnkForRelease
= unk
;
719 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
720 size
= STGMEDIUM_UserSize(&umcb
.Flags
, 0, &med
);
721 ok(size
== expect_size
, "size %d should be %d bytes\n", size
, expect_size
);
723 buffer
= HeapAlloc(GetProcessHeap(), 0, size
);
724 memset(buffer
, 0xcc, size
);
725 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
726 buffer_end
= STGMEDIUM_UserMarshal(&umcb
.Flags
, buffer
, &med
);
727 ok(buffer_end
- buffer
== expect_buffer_end
- expect_buffer
, "buffer size mismatch\n");
728 ok(*(DWORD
*)buffer
== TYMED_ISTREAM
, "got %08x\n", *(DWORD
*)buffer
);
729 ok(*((DWORD
*)buffer
+1) != 0, "got %08x\n", *((DWORD
*)buffer
+1));
730 ok(*((DWORD
*)buffer
+2) != 0, "got %08x\n", *((DWORD
*)buffer
+2));
731 ok(!memcmp(buffer
+ 12, expect_buffer
+ 12, (buffer_end
- buffer
) - 12), "buffer mismatch\n");
733 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, buffer
, size
, MSHCTX_DIFFERENTMACHINE
);
735 /* native crashes if this is uninitialised, presumably because it
736 tries to release it */
737 med2
.tymed
= TYMED_NULL
;
739 med2
.pUnkForRelease
= NULL
;
741 STGMEDIUM_UserUnmarshal(&umcb
.Flags
, buffer
, &med2
);
743 ok(med2
.tymed
== TYMED_ISTREAM
, "got tymed %x\n", med2
.tymed
);
744 ok(U(med2
).pstm
!= NULL
, "Incorrectly unmarshalled\n");
745 ok(med2
.pUnkForRelease
!= NULL
, "Incorrectly unmarshalled\n");
747 HeapFree(GetProcessHeap(), 0, buffer
);
748 init_user_marshal_cb(&umcb
, &stub_msg
, &rpc_msg
, NULL
, 0, MSHCTX_DIFFERENTMACHINE
);
749 STGMEDIUM_UserFree(&umcb
.Flags
, &med2
);
751 HeapFree(GetProcessHeap(), 0, expect_buffer
);
754 START_TEST(usrmarshal
)
758 test_marshal_CLIPFORMAT();
760 test_marshal_HGLOBAL();
761 test_marshal_HENHMETAFILE();
762 test_marshal_HMETAFILE();
763 test_marshal_HMETAFILEPICT();
764 test_marshal_WdtpInterfacePointer();
765 test_marshal_STGMEDIUM();