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