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