ole32: Fix the test of the size returned from WdtpInterfacePointer_UserSize.
[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 static const char cf_marshaled[] =
38 {
39     0x9, 0x0, 0x0, 0x0,
40     0x0, 0x0, 0x0, 0x0,
41     0x9, 0x0, 0x0, 0x0,
42     'M', 0x0, 'y', 0x0,
43     'F', 0x0, 'o', 0x0,
44     'r', 0x0, 'm', 0x0,
45     'a', 0x0, 't', 0x0,
46     0x0, 0x0
47 };
48
49 static void test_marshal_CLIPFORMAT(void)
50 {
51     unsigned char *buffer;
52     ULONG size;
53     ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
54     wireCLIPFORMAT wirecf;
55     CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
56     CLIPFORMAT cf2;
57
58     size = CLIPFORMAT_UserSize(&flags, 0, &cf);
59     ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Wrong size %d\n", size);
60
61     buffer = HeapAlloc(GetProcessHeap(), 0, size);
62     CLIPFORMAT_UserMarshal(&flags, buffer, &cf);
63     wirecf = (wireCLIPFORMAT)buffer;
64     ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext);
65     ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04x\n", cf, wirecf->u.dwValue);
66     ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n");
67
68     CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2);
69     ok(cf == cf2, "Didn't unmarshal properly\n");
70     HeapFree(GetProcessHeap(), 0, buffer);
71
72     CLIPFORMAT_UserFree(&flags, &cf2);
73 }
74
75 static void test_marshal_HWND(void)
76 {
77     unsigned char *buffer;
78     ULONG size;
79     ULONG flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
80     HWND hwnd = GetDesktopWindow();
81     HWND hwnd2;
82     wireHWND wirehwnd;
83
84     size = HWND_UserSize(&flags, 0, &hwnd);
85     ok(size == sizeof(*wirehwnd), "Wrong size %d\n", size);
86
87     buffer = HeapAlloc(GetProcessHeap(), 0, size);
88     HWND_UserMarshal(&flags, buffer, &hwnd);
89     wirehwnd = (wireHWND)buffer;
90     ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
91     ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
92
93     HWND_UserUnmarshal(&flags, buffer, &hwnd2);
94     ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
95     HeapFree(GetProcessHeap(), 0, buffer);
96
97     HWND_UserFree(&flags, &hwnd2);
98 }
99
100 static void test_marshal_HGLOBAL(void)
101 {
102     unsigned char *buffer;
103     ULONG size;
104     ULONG flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
105     HGLOBAL hglobal;
106     HGLOBAL hglobal2;
107     unsigned char *wirehglobal;
108     int i;
109
110     hglobal = NULL;
111     flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
112     size = HGLOBAL_UserSize(&flags, 0, &hglobal);
113     /* native is poorly programmed and allocates 4 bytes more than it needs to
114      * here - Wine doesn't have to emulate that */
115     ok((size == 8) || (size == 12), "Size should be 12, instead of %d\n", size);
116     buffer = HeapAlloc(GetProcessHeap(), 0, size);
117     HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
118     wirehglobal = buffer;
119     ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
120     wirehglobal += sizeof(ULONG);
121     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n");
122     HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
123     ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
124     HeapFree(GetProcessHeap(), 0, buffer);
125     HGLOBAL_UserFree(&flags, &hglobal2);
126
127     hglobal = GlobalAlloc(0, 4);
128     buffer = GlobalLock(hglobal);
129     for (i = 0; i < 4; i++)
130         buffer[i] = i;
131     GlobalUnlock(hglobal);
132     flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
133     size = HGLOBAL_UserSize(&flags, 0, &hglobal);
134     /* native is poorly programmed and allocates 4 bytes more than it needs to
135      * here - Wine doesn't have to emulate that */
136     ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %d\n", size);
137     buffer = HeapAlloc(GetProcessHeap(), 0, size);
138     HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
139     wirehglobal = buffer;
140     ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
141     wirehglobal += sizeof(ULONG);
142     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n");
143     wirehglobal += sizeof(ULONG);
144     ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n");
145     wirehglobal += sizeof(ULONG);
146     ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n");
147     wirehglobal += sizeof(ULONG);
148     ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n");
149     wirehglobal += sizeof(ULONG);
150     for (i = 0; i < 4; i++)
151         ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
152     HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
153     ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
154     HeapFree(GetProcessHeap(), 0, buffer);
155     HGLOBAL_UserFree(&flags, &hglobal2);
156     GlobalFree(hglobal);
157 }
158
159 static HENHMETAFILE create_emf(void)
160 {
161     RECT rect = {0, 0, 100, 100};
162     HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
163     ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL);
164     return CloseEnhMetaFile(hdc);
165 }
166
167 static void test_marshal_HENHMETAFILE(void)
168 {
169     unsigned char *buffer;
170     ULONG size;
171     ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
172     HENHMETAFILE hemf;
173     HENHMETAFILE hemf2 = NULL;
174     unsigned char *wirehemf;
175
176     hemf = create_emf();
177
178     size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
179     ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
180     buffer = HeapAlloc(GetProcessHeap(), 0, size);
181     HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
182     wirehemf = buffer;
183     ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
184     wirehemf += sizeof(DWORD);
185     ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
186     wirehemf += sizeof(DWORD);
187     ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
188     wirehemf += sizeof(DWORD);
189     ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
190     wirehemf += sizeof(DWORD);
191     ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf);
192     wirehemf += sizeof(DWORD);
193     /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
194      * at this point */
195
196     HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
197     ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
198     HeapFree(GetProcessHeap(), 0, buffer);
199     HENHMETAFILE_UserFree(&flags, &hemf2);
200     DeleteEnhMetaFile(hemf);
201
202     /* test NULL emf */
203     hemf = NULL;
204
205     size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
206     ok(size == 8, "size should be 8 bytes, not %d\n", size);
207     buffer = HeapAlloc(GetProcessHeap(), 0, size);
208     HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
209     wirehemf = buffer;
210     ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
211     wirehemf += sizeof(DWORD);
212     ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
213     wirehemf += sizeof(DWORD);
214
215     HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
216     ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
217     HeapFree(GetProcessHeap(), 0, buffer);
218     HENHMETAFILE_UserFree(&flags, &hemf2);
219 }
220
221 static HMETAFILE create_mf(void)
222 {
223     RECT rect = {0, 0, 100, 100};
224     HDC hdc = CreateMetaFile(NULL);
225     ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
226     return CloseMetaFile(hdc);
227 }
228
229 static void test_marshal_HMETAFILE(void)
230 {
231     unsigned char *buffer;
232     ULONG size;
233     ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
234     HMETAFILE hmf;
235     HMETAFILE hmf2 = NULL;
236     unsigned char *wirehmf;
237
238     hmf = create_mf();
239
240     size = HMETAFILE_UserSize(&flags, 0, &hmf);
241     ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
242     buffer = HeapAlloc(GetProcessHeap(), 0, size);
243     HMETAFILE_UserMarshal(&flags, buffer, &hmf);
244     wirehmf = buffer;
245     ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
246     wirehmf += sizeof(DWORD);
247     ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
248     wirehmf += sizeof(DWORD);
249     ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
250     wirehmf += sizeof(DWORD);
251     ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
252     wirehmf += sizeof(DWORD);
253     ok(*(WORD *)wirehmf == 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmf);
254     wirehmf += sizeof(DWORD);
255     /* ... rest of data not tested - refer to tests for GetMetaFileBits
256      * at this point */
257
258     HMETAFILE_UserUnmarshal(&flags, buffer, &hmf2);
259     ok(hmf2 != NULL, "HMETAFILE didn't unmarshal\n");
260     HeapFree(GetProcessHeap(), 0, buffer);
261     HMETAFILE_UserFree(&flags, &hmf2);
262     DeleteMetaFile(hmf);
263
264     /* test NULL emf */
265     hmf = NULL;
266
267     size = HMETAFILE_UserSize(&flags, 0, &hmf);
268     ok(size == 8, "size should be 8 bytes, not %d\n", size);
269     buffer = HeapAlloc(GetProcessHeap(), 0, size);
270     HMETAFILE_UserMarshal(&flags, buffer, &hmf);
271     wirehmf = buffer;
272     ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
273     wirehmf += sizeof(DWORD);
274     ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
275     wirehmf += sizeof(DWORD);
276
277     HMETAFILE_UserUnmarshal(&flags, buffer, &hmf2);
278     ok(hmf2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
279     HeapFree(GetProcessHeap(), 0, buffer);
280     HMETAFILE_UserFree(&flags, &hmf2);
281 }
282
283 #define USER_MARSHAL_PTR_PREFIX \
284   ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
285   ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
286
287 static void test_marshal_HMETAFILEPICT(void)
288 {
289     unsigned char *buffer, *buffer_end;
290     ULONG size;
291     ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
292     HMETAFILEPICT hmfp;
293     HMETAFILEPICT hmfp2 = NULL;
294     METAFILEPICT *pmfp;
295     unsigned char *wirehmfp;
296
297     hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(*pmfp));
298     pmfp = GlobalLock(hmfp);
299     pmfp->mm = MM_ISOTROPIC;
300     pmfp->xExt = 1;
301     pmfp->yExt = 2;
302     pmfp->hMF = create_mf();
303     GlobalUnlock(hmfp);
304
305     size = HMETAFILEPICT_UserSize(&flags, 0, &hmfp);
306     ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
307     trace("size is %d\n", size);
308     buffer = HeapAlloc(GetProcessHeap(), 0, size);
309     buffer_end = HMETAFILEPICT_UserMarshal(&flags, buffer, &hmfp);
310     wirehmfp = buffer;
311     ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
312     wirehmfp += sizeof(DWORD);
313     ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
314     wirehmfp += sizeof(DWORD);
315     ok(*(DWORD *)wirehmfp == MM_ISOTROPIC, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD *)wirehmfp);
316     wirehmfp += sizeof(DWORD);
317     ok(*(DWORD *)wirehmfp == 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
318     wirehmfp += sizeof(DWORD);
319     ok(*(DWORD *)wirehmfp == 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD *)wirehmfp);
320     wirehmfp += sizeof(DWORD);
321     ok(*(DWORD *)wirehmfp == USER_MARSHAL_PTR_PREFIX, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD *)wirehmfp);
322     wirehmfp += sizeof(DWORD);
323     ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
324     wirehmfp += sizeof(DWORD);
325     pmfp = GlobalLock(hmfp);
326     ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)pmfp->hMF, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD *)wirehmfp);
327     GlobalUnlock(hmfp);
328     wirehmfp += sizeof(DWORD);
329     /* Note use (buffer_end - buffer) instead of size here, because size is an
330      * overestimate with native */
331     ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
332     wirehmfp += sizeof(DWORD);
333     ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
334     wirehmfp += sizeof(DWORD);
335     ok(*(WORD *)wirehmfp == 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
336     wirehmfp += sizeof(DWORD);
337     /* ... rest of data not tested - refer to tests for GetMetaFileBits
338      * at this point */
339
340     HMETAFILEPICT_UserUnmarshal(&flags, buffer, &hmfp2);
341     ok(hmfp2 != NULL, "HMETAFILEPICT didn't unmarshal\n");
342     HeapFree(GetProcessHeap(), 0, buffer);
343     HMETAFILEPICT_UserFree(&flags, &hmfp2);
344     pmfp = GlobalLock(hmfp);
345     DeleteMetaFile(pmfp->hMF);
346     GlobalUnlock(hmfp);
347     GlobalFree(hmfp);
348
349     /* test NULL emf */
350     hmfp = NULL;
351
352     size = HMETAFILEPICT_UserSize(&flags, 0, &hmfp);
353     ok(size == 8, "size should be 8 bytes, not %d\n", size);
354     buffer = HeapAlloc(GetProcessHeap(), 0, size);
355     HMETAFILEPICT_UserMarshal(&flags, buffer, &hmfp);
356     wirehmfp = buffer;
357     ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
358     wirehmfp += sizeof(DWORD);
359     ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
360     wirehmfp += sizeof(DWORD);
361
362     hmfp2 = NULL;
363     HMETAFILEPICT_UserUnmarshal(&flags, buffer, &hmfp2);
364     ok(hmfp2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
365     HeapFree(GetProcessHeap(), 0, buffer);
366     HMETAFILEPICT_UserFree(&flags, &hmfp2);
367 }
368
369 static HRESULT WINAPI Test_IUnknown_QueryInterface(
370                                                    LPUNKNOWN iface,
371                                                    REFIID riid,
372                                                    LPVOID *ppvObj)
373 {
374     if (ppvObj == NULL) return E_POINTER;
375
376     if (IsEqualGUID(riid, &IID_IUnknown))
377     {
378         *ppvObj = (LPVOID)iface;
379         IUnknown_AddRef(iface);
380         return S_OK;
381     }
382
383     *ppvObj = NULL;
384     return E_NOINTERFACE;
385 }
386
387 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
388 {
389     return 2; /* non-heap-based object */
390 }
391
392 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
393 {
394     return 1; /* non-heap-based object */
395 }
396
397 static const IUnknownVtbl TestUnknown_Vtbl =
398 {
399     Test_IUnknown_QueryInterface,
400     Test_IUnknown_AddRef,
401     Test_IUnknown_Release,
402 };
403
404 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
405
406 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *, REFIID);
407 unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG *, ULONG, unsigned char *, IUnknown *, REFIID);
408 unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG *, unsigned char *, IUnknown **, REFIID);
409 void __RPC_USER WdtpInterfacePointer_UserFree(IUnknown *);
410
411 static void test_marshal_WdtpInterfacePointer(void)
412 {
413     unsigned char *buffer, *buffer_end;
414     ULONG size;
415     MIDL_STUB_MESSAGE stubmsg;
416     USER_MARSHAL_CB umcb;
417     IUnknown *unk;
418     IUnknown *unk2;
419     unsigned char *wireip;
420     const IID *iid;
421
422     memset(&stubmsg, 0xcc, sizeof(stubmsg));
423     stubmsg.dwDestContext = MSHCTX_INPROC;
424     stubmsg.pvDestContext = NULL;
425
426     memset(&umcb, 0xcc, sizeof(umcb));
427     umcb.Flags = MAKELONG(MSHCTX_INPROC, NDR_LOCAL_DATA_REPRESENTATION);
428     umcb.pStubMsg = &stubmsg;
429
430     /* shows that the WdtpInterfacePointer functions don't marshal anything for
431      * NULL pointers, so code using these functions must handle that case
432      * itself */
433     unk = NULL;
434     size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 0, unk, &IID_IUnknown);
435     ok(size == 0, "size should be 0 bytes, not %d\n", size);
436     buffer = HeapAlloc(GetProcessHeap(), 0, size);
437     buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, buffer, unk, &IID_IUnknown);
438     wireip = buffer;
439     HeapFree(GetProcessHeap(), 0, buffer);
440
441     unk = &Test_Unknown;
442     size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 0, unk, &IID_IUnknown);
443     todo_wine
444     ok(size > 28, "size should be > 28 bytes, not %d\n", size);
445     trace("WdtpInterfacePointer_UserSize returned %d\n", size);
446     buffer = HeapAlloc(GetProcessHeap(), 0, size);
447     buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, buffer, unk, &IID_IUnknown);
448     wireip = buffer;
449     if (size >= 28)
450     {
451         ok(*(DWORD *)wireip == 0x44, "wireip + 0x0 should be 0x44 instead of 0x%08x\n", *(DWORD *)wireip);
452         wireip += sizeof(DWORD);
453         ok(*(DWORD *)wireip == 0x44, "wireip + 0x4 should be 0x44 instead of 0x%08x\n", *(DWORD *)wireip);
454         wireip += sizeof(DWORD);
455         ok(*(DWORD *)wireip == 0x574f454d /* 'MEOW' */, "wireip + 0x8 should be 0x574f454d instead of 0x%08x\n", *(DWORD *)wireip);
456         wireip += sizeof(DWORD);
457         ok(*(DWORD *)wireip == 0x1, "wireip + 0xc should be 0x1 instead of 0x%08x\n", *(DWORD *)wireip);
458         wireip += sizeof(DWORD);
459         iid = (const IID *)wireip;
460         ok(IsEqualIID(iid, &IID_IUnknown),
461            "wireip + 0x10 should be IID_IUnknown instead of {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
462            iid->Data1, iid->Data2, iid->Data3,
463            iid->Data4[0], iid->Data4[1], iid->Data4[2], iid->Data4[3],
464            iid->Data4[4], iid->Data4[5], iid->Data4[6], iid->Data4[7]);
465         wireip += sizeof(IID);
466         ok(*(DWORD *)wireip == 0, "wireip + 0x1c should be 0 instead of 0x%08x\n", *(DWORD *)wireip);
467         wireip += sizeof(DWORD);
468         ok(*(DWORD *)wireip == 5, "wireip + 0x20 should be 5 instead of %d\n", *(DWORD *)wireip);
469         wireip += sizeof(DWORD);
470         /* the rest is dynamic so can't really be tested */
471     }
472
473     unk2 = NULL;
474     WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown);
475     todo_wine
476     ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n");
477     HeapFree(GetProcessHeap(), 0, buffer);
478     WdtpInterfacePointer_UserFree(unk2);
479 }
480
481 START_TEST(usrmarshal)
482 {
483     CoInitialize(NULL);
484
485     test_marshal_CLIPFORMAT();
486     test_marshal_HWND();
487     test_marshal_HGLOBAL();
488     test_marshal_HENHMETAFILE();
489     test_marshal_HMETAFILE();
490     test_marshal_HMETAFILEPICT();
491     test_marshal_WdtpInterfacePointer();
492
493     CoUninitialize();
494 }