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