3411cc283b193062a8dfd86ad1ea16c059b53721
[reactos.git] / rostests / winetests / ole32 / usrmarshal.c
1 /*
2 * User Marshaling Tests
3 *
4 * Copyright 2004-2006 Robert Shearman for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define COBJMACROS
22 #define CONST_VTABLE
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "objidl.h"
29
30 #include "wine/test.h"
31
32 ULONG __RPC_USER HMETAFILE_UserSize(ULONG *, unsigned long, 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 *);
36
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 *);
41
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 *);
46
47 static void * WINAPI user_allocate(SIZE_T size)
48 {
49 return CoTaskMemAlloc(size);
50 }
51
52 static void WINAPI user_free(void *p)
53 {
54 CoTaskMemFree(p);
55 }
56
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)
61 {
62 memset(rpc_msg, 0, sizeof(*rpc_msg));
63 rpc_msg->Buffer = buffer;
64 rpc_msg->BufferLength = size;
65
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;
71
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;
77 }
78
79 static const char cf_marshaled[] =
80 {
81 0x9, 0x0, 0x0, 0x0,
82 0x0, 0x0, 0x0, 0x0,
83 0x9, 0x0, 0x0, 0x0,
84 'M', 0x0, 'y', 0x0,
85 'F', 0x0, 'o', 0x0,
86 'r', 0x0, 'm', 0x0,
87 'a', 0x0, 't', 0x0,
88 0x0, 0x0
89 };
90
91 static void test_marshal_CLIPFORMAT(void)
92 {
93 USER_MARSHAL_CB umcb;
94 MIDL_STUB_MESSAGE stub_msg;
95 RPC_MESSAGE rpc_msg;
96 unsigned char *buffer;
97 ULONG i, size;
98 CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
99 CLIPFORMAT cf2;
100
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);
107
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] );
118
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);
123
124 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
125 CLIPFORMAT_UserFree(&umcb.Flags, &cf2);
126 }
127
128 static void test_marshal_HWND(void)
129 {
130 USER_MARSHAL_CB umcb;
131 MIDL_STUB_MESSAGE stub_msg;
132 RPC_MESSAGE rpc_msg;
133 unsigned char *buffer;
134 ULONG size;
135 HWND hwnd = GetDesktopWindow();
136 HWND hwnd2;
137 wireHWND wirehwnd;
138
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);
142
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 %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
149
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);
154
155 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
156 HWND_UserFree(&umcb.Flags, &hwnd2);
157 }
158
159 static void test_marshal_HGLOBAL(void)
160 {
161 USER_MARSHAL_CB umcb;
162 MIDL_STUB_MESSAGE stub_msg;
163 RPC_MESSAGE rpc_msg;
164 unsigned char *buffer;
165 ULONG size;
166 HGLOBAL hglobal;
167 HGLOBAL hglobal2;
168 unsigned char *wirehglobal;
169 int i;
170
171 hglobal = NULL;
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);
190
191 hglobal = GlobalAlloc(0, 4);
192 buffer = GlobalLock(hglobal);
193 for (i = 0; i < 4; i++)
194 buffer[i] = i;
195 GlobalUnlock(hglobal);
196 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
197 size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
198 /* native is poorly programmed and allocates 4/8 bytes more than it needs to
199 * here - Wine doesn't have to emulate that */
200 ok((size == 24) || broken(size == 28) || broken(size == 32), "Size should be 24, instead of %d\n", size);
201 buffer = HeapAlloc(GetProcessHeap(), 0, size);
202 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
203 HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
204 wirehglobal = buffer;
205 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
206 wirehglobal += sizeof(ULONG);
207 ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0x4 should be HGLOBAL\n");
208 wirehglobal += sizeof(ULONG);
209 ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL instead of %d\n", *(ULONG *)wirehglobal);
210 wirehglobal += sizeof(ULONG);
211 ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0xc should be HGLOBAL\n");
212 wirehglobal += sizeof(ULONG);
213 ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL instead of %d\n", *(ULONG *)wirehglobal);
214 wirehglobal += sizeof(ULONG);
215 for (i = 0; i < 4; i++)
216 ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
217 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
218 HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
219 ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
220 HeapFree(GetProcessHeap(), 0, buffer);
221 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
222 HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
223 GlobalFree(hglobal);
224 }
225
226 static HENHMETAFILE create_emf(void)
227 {
228 const RECT rect = {0, 0, 100, 100};
229 HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
230 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
231 return CloseEnhMetaFile(hdc);
232 }
233
234 static void test_marshal_HENHMETAFILE(void)
235 {
236 USER_MARSHAL_CB umcb;
237 MIDL_STUB_MESSAGE stub_msg;
238 RPC_MESSAGE rpc_msg;
239 unsigned char *buffer;
240 ULONG size;
241 HENHMETAFILE hemf;
242 HENHMETAFILE hemf2 = NULL;
243 unsigned char *wirehemf;
244
245 hemf = create_emf();
246
247 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
248 size = HENHMETAFILE_UserSize(&umcb.Flags, 0, &hemf);
249 ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
250 buffer = HeapAlloc(GetProcessHeap(), 0, size);
251 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
252 HENHMETAFILE_UserMarshal(&umcb.Flags, buffer, &hemf);
253 wirehemf = buffer;
254 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
255 wirehemf += sizeof(DWORD);
256 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
257 wirehemf += sizeof(DWORD);
258 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
259 wirehemf += sizeof(DWORD);
260 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
261 wirehemf += sizeof(DWORD);
262 ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf);
263 wirehemf += sizeof(DWORD);
264 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
265 * at this point */
266
267 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
268 HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hemf2);
269 ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
270 HeapFree(GetProcessHeap(), 0, buffer);
271 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
272 HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
273 DeleteEnhMetaFile(hemf);
274
275 /* test NULL emf */
276 hemf = NULL;
277
278 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
279 size = HENHMETAFILE_UserSize(&umcb.Flags, 0, &hemf);
280 ok(size == 8, "size should be 8 bytes, not %d\n", size);
281 buffer = HeapAlloc(GetProcessHeap(), 0, size);
282 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
283 HENHMETAFILE_UserMarshal(&umcb.Flags, buffer, &hemf);
284 wirehemf = buffer;
285 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
286 wirehemf += sizeof(DWORD);
287 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
288 wirehemf += sizeof(DWORD);
289
290 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
291 HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hemf2);
292 ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
293 HeapFree(GetProcessHeap(), 0, buffer);
294 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
295 HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
296 }
297
298 static HMETAFILE create_mf(void)
299 {
300 RECT rect = {0, 0, 100, 100};
301 HDC hdc = CreateMetaFile(NULL);
302 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
303 return CloseMetaFile(hdc);
304 }
305
306 static void test_marshal_HMETAFILE(void)
307 {
308 USER_MARSHAL_CB umcb;
309 MIDL_STUB_MESSAGE stub_msg;
310 RPC_MESSAGE rpc_msg;
311 unsigned char *buffer;
312 ULONG size;
313 HMETAFILE hmf;
314 HMETAFILE hmf2 = NULL;
315 unsigned char *wirehmf;
316
317 hmf = create_mf();
318
319 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
320 size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
321 ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
322 buffer = HeapAlloc(GetProcessHeap(), 0, size);
323 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
324 HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
325 wirehmf = buffer;
326 ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
327 wirehmf += sizeof(DWORD);
328 ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
329 wirehmf += sizeof(DWORD);
330 ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
331 wirehmf += sizeof(DWORD);
332 ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
333 wirehmf += sizeof(DWORD);
334 ok(*(WORD *)wirehmf == 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmf);
335 wirehmf += sizeof(DWORD);
336 /* ... rest of data not tested - refer to tests for GetMetaFileBits
337 * at this point */
338
339 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
340 HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
341 ok(hmf2 != NULL, "HMETAFILE didn't unmarshal\n");
342 HeapFree(GetProcessHeap(), 0, buffer);
343 HMETAFILE_UserFree(&umcb.Flags, &hmf2);
344 DeleteMetaFile(hmf);
345
346 /* test NULL emf */
347 hmf = NULL;
348
349 size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
350 ok(size == 8, "size should be 8 bytes, not %d\n", size);
351 buffer = HeapAlloc(GetProcessHeap(), 0, size);
352 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
353 HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
354 wirehmf = buffer;
355 ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
356 wirehmf += sizeof(DWORD);
357 ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
358 wirehmf += sizeof(DWORD);
359
360 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
361 HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
362 ok(hmf2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
363 HeapFree(GetProcessHeap(), 0, buffer);
364 HMETAFILE_UserFree(&umcb.Flags, &hmf2);
365 }
366
367 #define USER_MARSHAL_PTR_PREFIX \
368 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
369 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
370
371 static void test_marshal_HMETAFILEPICT(void)
372 {
373 USER_MARSHAL_CB umcb;
374 MIDL_STUB_MESSAGE stub_msg;
375 RPC_MESSAGE rpc_msg;
376 unsigned char *buffer, *buffer_end;
377 ULONG size;
378 HMETAFILEPICT hmfp;
379 HMETAFILEPICT hmfp2 = NULL;
380 METAFILEPICT *pmfp;
381 unsigned char *wirehmfp;
382
383 hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(*pmfp));
384 pmfp = GlobalLock(hmfp);
385 pmfp->mm = MM_ISOTROPIC;
386 pmfp->xExt = 1;
387 pmfp->yExt = 2;
388 pmfp->hMF = create_mf();
389 GlobalUnlock(hmfp);
390
391 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
392 size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp);
393 ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
394 trace("size is %d\n", size);
395 buffer = HeapAlloc(GetProcessHeap(), 0, size);
396 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
397 buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp);
398 wirehmfp = buffer;
399 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
400 wirehmfp += sizeof(DWORD);
401 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
402 wirehmfp += sizeof(DWORD);
403 ok(*(DWORD *)wirehmfp == MM_ISOTROPIC, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD *)wirehmfp);
404 wirehmfp += sizeof(DWORD);
405 ok(*(DWORD *)wirehmfp == 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
406 wirehmfp += sizeof(DWORD);
407 ok(*(DWORD *)wirehmfp == 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD *)wirehmfp);
408 wirehmfp += sizeof(DWORD);
409 ok(*(DWORD *)wirehmfp == USER_MARSHAL_PTR_PREFIX, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD *)wirehmfp);
410 wirehmfp += sizeof(DWORD);
411 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
412 wirehmfp += sizeof(DWORD);
413 pmfp = GlobalLock(hmfp);
414 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)pmfp->hMF, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD *)wirehmfp);
415 GlobalUnlock(hmfp);
416 wirehmfp += sizeof(DWORD);
417 /* Note use (buffer_end - buffer) instead of size here, because size is an
418 * overestimate with native */
419 ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
420 wirehmfp += sizeof(DWORD);
421 ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
422 wirehmfp += sizeof(DWORD);
423 ok(*(WORD *)wirehmfp == 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
424 wirehmfp += sizeof(DWORD);
425 /* ... rest of data not tested - refer to tests for GetMetaFileBits
426 * at this point */
427
428 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
429 HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer, &hmfp2);
430 ok(hmfp2 != NULL, "HMETAFILEPICT didn't unmarshal\n");
431 HeapFree(GetProcessHeap(), 0, buffer);
432 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
433 HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
434 pmfp = GlobalLock(hmfp);
435 DeleteMetaFile(pmfp->hMF);
436 GlobalUnlock(hmfp);
437 GlobalFree(hmfp);
438
439 /* test NULL emf */
440 hmfp = NULL;
441
442 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
443 size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp);
444 ok(size == 8, "size should be 8 bytes, not %d\n", size);
445 buffer = HeapAlloc(GetProcessHeap(), 0, size);
446 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
447 HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp);
448 wirehmfp = buffer;
449 ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
450 wirehmfp += sizeof(DWORD);
451 ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
452 wirehmfp += sizeof(DWORD);
453
454 hmfp2 = NULL;
455 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
456 HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer, &hmfp2);
457 ok(hmfp2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
458 HeapFree(GetProcessHeap(), 0, buffer);
459 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
460 HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
461 }
462
463 static HRESULT WINAPI Test_IUnknown_QueryInterface(
464 LPUNKNOWN iface,
465 REFIID riid,
466 LPVOID *ppvObj)
467 {
468 if (ppvObj == NULL) return E_POINTER;
469
470 if (IsEqualGUID(riid, &IID_IUnknown))
471 {
472 *ppvObj = iface;
473 IUnknown_AddRef(iface);
474 return S_OK;
475 }
476
477 *ppvObj = NULL;
478 return E_NOINTERFACE;
479 }
480
481 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
482 {
483 return 2; /* non-heap-based object */
484 }
485
486 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
487 {
488 return 1; /* non-heap-based object */
489 }
490
491 static const IUnknownVtbl TestUnknown_Vtbl =
492 {
493 Test_IUnknown_QueryInterface,
494 Test_IUnknown_AddRef,
495 Test_IUnknown_Release,
496 };
497
498 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
499
500 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *, REFIID);
501 unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG *, ULONG, unsigned char *, IUnknown *, REFIID);
502 unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG *, unsigned char *, IUnknown **, REFIID);
503 void __RPC_USER WdtpInterfacePointer_UserFree(IUnknown *);
504
505 static void test_marshal_WdtpInterfacePointer(void)
506 {
507 USER_MARSHAL_CB umcb;
508 MIDL_STUB_MESSAGE stub_msg;
509 RPC_MESSAGE rpc_msg;
510 unsigned char *buffer, *buffer_end;
511 ULONG size;
512 IUnknown *unk;
513 IUnknown *unk2;
514 unsigned char *wireip;
515 const IID *iid;
516
517 /* shows that the WdtpInterfacePointer functions don't marshal anything for
518 * NULL pointers, so code using these functions must handle that case
519 * itself */
520 unk = NULL;
521 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
522 size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 0, unk, &IID_IUnknown);
523 ok(size == 0, "size should be 0 bytes, not %d\n", size);
524 buffer = HeapAlloc(GetProcessHeap(), 0, size);
525 buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, buffer, unk, &IID_IUnknown);
526 wireip = buffer;
527 HeapFree(GetProcessHeap(), 0, buffer);
528
529 unk = &Test_Unknown;
530 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
531 size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 0, unk, &IID_IUnknown);
532 todo_wine
533 ok(size > 28, "size should be > 28 bytes, not %d\n", size);
534 trace("WdtpInterfacePointer_UserSize returned %d\n", size);
535 buffer = HeapAlloc(GetProcessHeap(), 0, size);
536 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
537 buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, buffer, unk, &IID_IUnknown);
538 wireip = buffer;
539 if (size >= 28)
540 {
541 ok(*(DWORD *)wireip == 0x44, "wireip + 0x0 should be 0x44 instead of 0x%08x\n", *(DWORD *)wireip);
542 wireip += sizeof(DWORD);
543 ok(*(DWORD *)wireip == 0x44, "wireip + 0x4 should be 0x44 instead of 0x%08x\n", *(DWORD *)wireip);
544 wireip += sizeof(DWORD);
545 ok(*(DWORD *)wireip == 0x574f454d /* 'MEOW' */, "wireip + 0x8 should be 0x574f454d instead of 0x%08x\n", *(DWORD *)wireip);
546 wireip += sizeof(DWORD);
547 ok(*(DWORD *)wireip == 0x1, "wireip + 0xc should be 0x1 instead of 0x%08x\n", *(DWORD *)wireip);
548 wireip += sizeof(DWORD);
549 iid = (const IID *)wireip;
550 ok(IsEqualIID(iid, &IID_IUnknown),
551 "wireip + 0x10 should be IID_IUnknown instead of {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
552 iid->Data1, iid->Data2, iid->Data3,
553 iid->Data4[0], iid->Data4[1], iid->Data4[2], iid->Data4[3],
554 iid->Data4[4], iid->Data4[5], iid->Data4[6], iid->Data4[7]);
555 wireip += sizeof(IID);
556 ok(*(DWORD *)wireip == 0, "wireip + 0x1c should be 0 instead of 0x%08x\n", *(DWORD *)wireip);
557 wireip += sizeof(DWORD);
558 ok(*(DWORD *)wireip == 5, "wireip + 0x20 should be 5 instead of %d\n", *(DWORD *)wireip);
559 wireip += sizeof(DWORD);
560 /* the rest is dynamic so can't really be tested */
561 }
562
563 unk2 = NULL;
564 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
565 WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown);
566 todo_wine
567 ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n");
568 HeapFree(GetProcessHeap(), 0, buffer);
569 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
570 WdtpInterfacePointer_UserFree(unk2);
571 }
572
573 START_TEST(usrmarshal)
574 {
575 CoInitialize(NULL);
576
577 test_marshal_CLIPFORMAT();
578 test_marshal_HWND();
579 test_marshal_HGLOBAL();
580 test_marshal_HENHMETAFILE();
581 test_marshal_HMETAFILE();
582 test_marshal_HMETAFILEPICT();
583 test_marshal_WdtpInterfacePointer();
584
585 CoUninitialize();
586 }