oleaut32: Preserve the 'auto' features before copying over the masked unmarshaled...
[wine] / dlls / oleaut32 / tests / usrmarshal.c
1 /*
2  * Marshaling Tests
3  *
4  * Copyright 2004 Robert Shearman
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
26 #include "propidl.h" /* for LPSAFEARRAY_User* routines */
27
28 #include "wine/test.h"
29
30 /* doesn't work on Windows due to needing more of the
31  * MIDL_STUB_MESSAGE structure to be filled out */
32 #define LPSAFEARRAY_UNMARSHAL_WORKS 0
33 #define BSTR_UNMARSHAL_WORKS 0
34 #define VARIANT_UNMARSHAL_WORKS 0
35
36 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
37 {
38     VARTYPE vt;
39     HRESULT hr;
40
41     hr = SafeArrayGetVartype(psa, &vt);
42     if (FAILED(hr))
43         return 0;
44
45     if (psa->fFeatures & FADF_HAVEIID)
46         return SF_HAVEIID;
47
48     switch (vt)
49     {
50     case VT_I1:
51     case VT_UI1:      return SF_I1;
52     case VT_BOOL:
53     case VT_I2:
54     case VT_UI2:      return SF_I2;
55     case VT_INT:
56     case VT_UINT:
57     case VT_I4:
58     case VT_UI4:
59     case VT_R4:       return SF_I4;
60     case VT_DATE:
61     case VT_CY:
62     case VT_R8:
63     case VT_I8:
64     case VT_UI8:      return SF_I8;
65     case VT_INT_PTR:
66     case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
67     case VT_BSTR:     return SF_BSTR;
68     case VT_DISPATCH: return SF_DISPATCH;
69     case VT_VARIANT:  return SF_VARIANT;
70     case VT_UNKNOWN:  return SF_UNKNOWN;
71     /* Note: Return a non-zero size to indicate vt is valid. The actual size
72      * of a UDT is taken from the result of IRecordInfo_GetSize().
73      */
74     case VT_RECORD:   return SF_RECORD;
75     default:          return SF_ERROR;
76     }
77 }
78
79 static ULONG get_cell_count(const SAFEARRAY *psa)
80 {
81     const SAFEARRAYBOUND* psab = psa->rgsabound;
82     USHORT cCount = psa->cDims;
83     ULONG ulNumCells = 1;
84
85     while (cCount--)
86     {
87          if (!psab->cElements)
88             return 0;
89         ulNumCells *= psab->cElements;
90         psab++;
91     }
92     return ulNumCells;
93 }
94
95 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
96 {
97     unsigned char *wiresa = buffer;
98     VARTYPE vt;
99     SF_TYPE sftype;
100     ULONG cell_count;
101
102     if(!lpsa)
103     {
104         ok(*(void **)wiresa == NULL, "wiresa + 0x0 should be NULL instead of 0x%08lx\n", *(DWORD *)wiresa);
105         return;
106     }
107
108     SafeArrayGetVartype(lpsa, &vt);
109     sftype = get_union_type(lpsa);
110     cell_count = get_cell_count(lpsa);
111
112     ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08lx\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
113     wiresa += sizeof(DWORD);
114     ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08lx\n", *(DWORD *)wiresa);
115     wiresa += sizeof(DWORD);
116     ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
117     wiresa += sizeof(WORD);
118     ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xc should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
119     wiresa += sizeof(WORD);
120     ok(*(DWORD *)wiresa == lpsa->cbElements, "wiresa + 0x10 should be lpsa->cbElements instead of 0x%08lx\n", *(DWORD *)wiresa);
121     wiresa += sizeof(DWORD);
122     ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x16 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
123     wiresa += sizeof(WORD);
124     ok(*(WORD *)wiresa == vt, "wiresa + 0x14 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
125     wiresa += sizeof(WORD);
126     ok(*(DWORD *)wiresa == sftype, "wiresa + 0x18 should be %08lx instead of 0x%08lx\n", (DWORD)sftype, *(DWORD *)wiresa);
127     wiresa += sizeof(DWORD);
128     ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x1c should be %lu instead of %lu\n", cell_count, *(DWORD *)wiresa);
129     wiresa += sizeof(DWORD);
130     ok(*(DWORD_PTR *)wiresa == (DWORD_PTR)lpsa->pvData, "wiresa + 0x20 should be lpsa->pvData instead of 0x%08lx\n", *(DWORD_PTR *)wiresa);
131     wiresa += sizeof(DWORD_PTR);
132     if(sftype == SF_HAVEIID)
133     {
134         GUID guid;
135         SafeArrayGetIID(lpsa, &guid);
136         ok(IsEqualGUID(&guid, (GUID*)wiresa), "guid mismatch\n");
137         wiresa += sizeof(GUID);
138     }
139     ok(!memcmp(wiresa, lpsa->rgsabound, sizeof(lpsa->rgsabound[0]) * lpsa->cDims), "bounds mismatch\n");
140     wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
141
142     ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x2c should be %lu instead of %lu\n", cell_count, *(DWORD*)wiresa);
143     wiresa += sizeof(DWORD);
144     /* elements are now pointed to by wiresa */
145 }
146
147 static void test_marshal_LPSAFEARRAY(void)
148 {
149     unsigned char *buffer;
150     unsigned long size;
151     LPSAFEARRAY lpsa;
152     LPSAFEARRAY lpsa2 = NULL;
153     SAFEARRAYBOUND sab;
154     MIDL_STUB_MESSAGE stubMsg = { 0 };
155     USER_MARSHAL_CB umcb = { 0 };
156
157     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
158     umcb.pReserve = NULL;
159     umcb.pStubMsg = &stubMsg;
160
161     sab.lLbound = 5;
162     sab.cElements = 10;
163
164     lpsa = SafeArrayCreate(VT_I2, 1, &sab);
165     *(DWORD *)lpsa->pvData = 0xcafebabe;
166
167     lpsa->cLocks = 7;
168     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
169     ok(size == 68, "size should be 68 bytes, not %ld\n", size);
170     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
171     ok(size == 64, "size should be 64 bytes, not %ld\n", size);
172     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
173     LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
174
175     check_safearray(buffer, lpsa);
176
177     if (LPSAFEARRAY_UNMARSHAL_WORKS)
178     {
179         VARTYPE vt, vt2;
180         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
181         ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
182         SafeArrayGetVartype(lpsa, &vt);
183         SafeArrayGetVartype(lpsa2, &vt2);
184         ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
185         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
186     }
187     HeapFree(GetProcessHeap(), 0, buffer);
188     SafeArrayDestroy(lpsa);
189
190     /* test NULL safe array */
191     lpsa = NULL;
192
193     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
194     ok(size == 4, "size should be 4 bytes, not %ld\n", size);
195     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
196     LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
197     check_safearray(buffer, lpsa);
198
199     if (LPSAFEARRAY_UNMARSHAL_WORKS)
200     {
201         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
202         ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
203         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
204     }
205     HeapFree(GetProcessHeap(), 0, buffer);
206
207     sab.lLbound = 5;
208     sab.cElements = 10;
209
210     lpsa = SafeArrayCreate(VT_R8, 1, &sab);
211     *(double *)lpsa->pvData = 3.1415;
212
213     lpsa->cLocks = 7;
214     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
215     ok(size == 128, "size should be 128 bytes, not %ld\n", size);
216     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
217     ok(size == 128, "size should be 128 bytes, not %ld\n", size);
218     buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
219     LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
220
221     check_safearray(buffer, lpsa);
222
223     HeapFree(GetProcessHeap(), 0, buffer);
224     SafeArrayDestroy(lpsa);
225 }
226
227 static void check_bstr(void *buffer, BSTR b)
228 {
229     DWORD *wireb = buffer;
230     DWORD len = SysStringLen(b);
231
232     ok(*wireb == len, "wv[0] %08lx\n", *wireb);
233     wireb++;
234     if(len)
235         ok(*wireb == len * 2, "wv[1] %08lx\n", *wireb);
236     else
237         ok(*wireb == 0xffffffff, "wv[1] %08lx\n", *wireb);
238     wireb++;
239     ok(*wireb == len, "wv[2] %08lx\n", *wireb);
240     if(len)
241     {
242         wireb++;
243         ok(!memcmp(wireb, b, len * 2), "strings differ\n");
244     }
245     return;
246 }
247
248 static void test_marshal_BSTR(void)
249 {
250     unsigned long size;
251     MIDL_STUB_MESSAGE stubMsg = { 0 };
252     USER_MARSHAL_CB umcb = { 0 };
253     unsigned char *buffer;
254     BSTR b, b2;
255     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
256     DWORD len;
257
258     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
259     umcb.pReserve = NULL;
260     umcb.pStubMsg = &stubMsg;
261
262     b = SysAllocString(str);
263     len = SysStringLen(b);
264     ok(len == 13, "get %ld\n", len);
265
266     /* BSTRs are DWORD aligned */
267     size = BSTR_UserSize(&umcb.Flags, 1, &b);
268     ok(size == 42, "size %ld\n", size);
269
270     size = BSTR_UserSize(&umcb.Flags, 0, &b);
271     ok(size == 38, "size %ld\n", size);
272
273     buffer = HeapAlloc(GetProcessHeap(), 0, size);
274     BSTR_UserMarshal(&umcb.Flags, buffer, &b);
275     check_bstr(buffer, b);
276
277     if (BSTR_UNMARSHAL_WORKS)
278     {
279         b2 = NULL;
280         BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
281         ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
282         ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
283         BSTR_UserFree(&umcb.Flags, &b2);
284     }
285
286     HeapFree(GetProcessHeap(), 0, buffer);
287     SysFreeString(b);
288
289     b = NULL;
290     size = BSTR_UserSize(&umcb.Flags, 0, &b);
291     ok(size == 12, "size %ld\n", size);
292
293     buffer = HeapAlloc(GetProcessHeap(), 0, size);
294     BSTR_UserMarshal(&umcb.Flags, buffer, &b);
295
296     check_bstr(buffer, b);
297     HeapFree(GetProcessHeap(), 0, buffer);
298
299 }
300
301 static void check_variant_header(DWORD *wirev, VARIANT *v, unsigned long size)
302 {
303     WORD *wp;
304     DWORD switch_is;
305
306     ok(*wirev == (size + 7) >> 3, "wv[0] %08lx, expected %08lx\n", *wirev, (size + 7) >> 3);
307     wirev++;
308     ok(*wirev == 0, "wv[1] %08lx\n", *wirev);
309     wirev++;
310     wp = (WORD*)wirev;
311     ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
312     wp++;
313     ok(*wp == v->n1.n2.wReserved1, "res1 %04x expected %04x\n", *wp, v->n1.n2.wReserved1);
314     wp++;
315     ok(*wp == v->n1.n2.wReserved2, "res2 %04x expected %04x\n", *wp, v->n1.n2.wReserved2);
316     wp++;
317     ok(*wp == v->n1.n2.wReserved3, "res3 %04x expected %04x\n", *wp, v->n1.n2.wReserved3);
318     wp++;
319     wirev = (DWORD*)wp;
320     switch_is = V_VT(v);
321     if(switch_is & VT_ARRAY)
322         switch_is &= ~VT_TYPEMASK;
323     ok(*wirev == switch_is, "switch_is %08lx expected %08lx\n", *wirev, switch_is);
324 }
325
326 static void test_marshal_VARIANT(void)
327 {
328     unsigned long size;
329     VARIANT v, v2;
330     MIDL_STUB_MESSAGE stubMsg = { 0 };
331     USER_MARSHAL_CB umcb = { 0 };
332     unsigned char *buffer, *next;
333     unsigned long ul;
334     short s;
335     double d;
336     DWORD *wirev;
337     BSTR b;
338     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
339     SAFEARRAYBOUND sab;
340     LPSAFEARRAY lpsa;
341     DECIMAL dec, dec2;
342
343     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
344     umcb.pReserve = NULL;
345     umcb.pStubMsg = &stubMsg;
346
347     /*** I1 ***/
348     VariantInit(&v);
349     V_VT(&v) = VT_I1;
350     V_I1(&v) = 0x12;
351
352     /* Variants have an alignment of 8 */
353     size = VARIANT_UserSize(&umcb.Flags, 1, &v);
354     ok(size == 29, "size %ld\n", size);
355
356     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
357     ok(size == 21, "size %ld\n", size);
358
359     buffer = HeapAlloc(GetProcessHeap(), 0, size);
360     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
361     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
362     wirev = (DWORD*)buffer;
363     
364     check_variant_header(wirev, &v, size);
365     wirev += 5;
366     ok(*(char*)wirev == V_I1(&v), "wv[5] %08lx\n", *wirev);
367     if (VARIANT_UNMARSHAL_WORKS)
368     {
369         VariantInit(&v2);
370         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
371         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
372         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
373         ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
374
375         VARIANT_UserFree(&umcb.Flags, &v2);
376     }
377     HeapFree(GetProcessHeap(), 0, buffer);
378
379     /*** I2 ***/
380     VariantInit(&v);
381     V_VT(&v) = VT_I2;
382     V_I2(&v) = 0x1234;
383
384     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
385     ok(size == 22, "size %ld\n", size);
386
387     buffer = HeapAlloc(GetProcessHeap(), 0, size);
388     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
389     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
390     wirev = (DWORD*)buffer;
391
392     check_variant_header(wirev, &v, size);
393     wirev += 5;
394     ok(*(short*)wirev == V_I2(&v), "wv[5] %08lx\n", *wirev);
395     if (VARIANT_UNMARSHAL_WORKS)
396     {
397         VariantInit(&v2);
398         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
399         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
400         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
401         ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
402
403         VARIANT_UserFree(&umcb.Flags, &v2);
404     }
405     HeapFree(GetProcessHeap(), 0, buffer);
406
407     /*** I2 BYREF ***/
408     VariantInit(&v);
409     V_VT(&v) = VT_I2 | VT_BYREF;
410     s = 0x1234;
411     V_I2REF(&v) = &s;
412
413     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
414     ok(size == 26, "size %ld\n", size);
415
416     buffer = HeapAlloc(GetProcessHeap(), 0, size);
417     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
418     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
419     wirev = (DWORD*)buffer;
420
421     check_variant_header(wirev, &v, size);
422     wirev += 5;
423     ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
424     wirev++;
425     ok(*(short*)wirev == s, "wv[6] %08lx\n", *wirev);
426     if (VARIANT_UNMARSHAL_WORKS)
427     {
428         VariantInit(&v2);
429         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
430         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
431         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
432         ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
433
434         VARIANT_UserFree(&umcb.Flags, &v2);
435     }
436     HeapFree(GetProcessHeap(), 0, buffer);
437
438     /*** I4 ***/
439     VariantInit(&v);
440     V_VT(&v) = VT_I4;
441     V_I4(&v) = 0x1234;
442
443     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
444     ok(size == 24, "size %ld\n", size);
445
446     buffer = HeapAlloc(GetProcessHeap(), 0, size);
447     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
448     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
449     wirev = (DWORD*)buffer;
450     
451     check_variant_header(wirev, &v, size);
452     wirev += 5;
453     ok(*wirev == V_I4(&v), "wv[5] %08lx\n", *wirev);
454
455     if (VARIANT_UNMARSHAL_WORKS)
456     {
457         VariantInit(&v2);
458         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
459         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
460         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
461         ok(V_I4(&v) == V_I4(&v2), "got i4 %lx expect %lx\n", V_I4(&v), V_I4(&v2));
462
463         VARIANT_UserFree(&umcb.Flags, &v2);
464     }
465
466     HeapFree(GetProcessHeap(), 0, buffer);
467
468     /*** UI4 ***/
469     VariantInit(&v);
470     V_VT(&v) = VT_UI4;
471     V_UI4(&v) = 0x1234;
472
473     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
474     ok(size == 24, "size %ld\n", size);
475
476     buffer = HeapAlloc(GetProcessHeap(), 0, size);
477     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
478     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
479     wirev = (DWORD*)buffer;
480     
481     check_variant_header(wirev, &v, size);
482     wirev += 5;
483     ok(*wirev == 0x1234, "wv[5] %08lx\n", *wirev);
484     if (VARIANT_UNMARSHAL_WORKS)
485     {
486         VariantInit(&v2);
487         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
488         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
489         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
490         ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %lx expect %lx\n", V_UI4(&v), V_UI4(&v2));
491
492         VARIANT_UserFree(&umcb.Flags, &v2);
493     }
494
495     HeapFree(GetProcessHeap(), 0, buffer);
496
497     /*** UI4 BYREF ***/
498     VariantInit(&v);
499     V_VT(&v) = VT_UI4 | VT_BYREF;
500     ul = 0x1234;
501     V_UI4REF(&v) = &ul;
502
503     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
504     ok(size == 28, "size %ld\n", size);
505
506     buffer = HeapAlloc(GetProcessHeap(), 0, size);
507     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
508     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
509     wirev = (DWORD*)buffer;
510     
511     check_variant_header(wirev, &v, size);
512     wirev += 5;
513     ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
514     wirev++;
515     ok(*wirev == ul, "wv[6] %08lx\n", *wirev);
516
517     if (VARIANT_UNMARSHAL_WORKS)
518     {
519         VariantInit(&v2);
520         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
521         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
522         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
523         ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %lx expect ui4 ref %lx\n", *V_UI4REF(&v), *V_UI4REF(&v2));
524
525         VARIANT_UserFree(&umcb.Flags, &v2);
526     }
527     HeapFree(GetProcessHeap(), 0, buffer);
528
529     /*** R4 ***/
530     VariantInit(&v);
531     V_VT(&v) = VT_R4;
532     V_R8(&v) = 3.1415;
533
534     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
535     ok(size == 24, "size %ld\n", size);
536
537     buffer = HeapAlloc(GetProcessHeap(), 0, size);
538     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
539     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
540     wirev = (DWORD*)buffer;
541      
542     check_variant_header(wirev, &v, size);
543     wirev += 5;
544     ok(*(float*)wirev == V_R4(&v), "wv[5] %08lx\n", *wirev);
545     if (VARIANT_UNMARSHAL_WORKS)
546     {
547         VariantInit(&v2);
548         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
549         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
550         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
551         ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
552
553         VARIANT_UserFree(&umcb.Flags, &v2);
554     }
555     HeapFree(GetProcessHeap(), 0, buffer);
556
557     /*** R8 ***/
558     VariantInit(&v);
559     V_VT(&v) = VT_R8;
560     V_R8(&v) = 3.1415;
561
562     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
563     ok(size == 32, "size %ld\n", size);
564
565     buffer = HeapAlloc(GetProcessHeap(), 0, size);
566     memset(buffer, 0xcc, size);
567     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
568     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
569     wirev = (DWORD*)buffer;
570     
571     check_variant_header(wirev, &v, size);
572     wirev += 5;
573     ok(*wirev == 0xcccccccc, "wv[5] %08lx\n", *wirev); /* pad */
574     wirev++;
575     ok(*(double*)wirev == V_R8(&v), "wv[6] %08lx, wv[7] %08lx\n", *wirev, *(wirev+1));
576     if (VARIANT_UNMARSHAL_WORKS)
577     {
578         VariantInit(&v2);
579         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
580         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
581         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
582         ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
583
584         VARIANT_UserFree(&umcb.Flags, &v2);
585     }
586     HeapFree(GetProcessHeap(), 0, buffer);
587
588     /*** R8 BYREF ***/
589     VariantInit(&v);
590     V_VT(&v) = VT_R8 | VT_BYREF;
591     d = 3.1415;
592     V_R8REF(&v) = &d;
593
594     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
595     ok(size == 32, "size %ld\n", size);
596
597     buffer = HeapAlloc(GetProcessHeap(), 0, size);
598     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
599     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
600     wirev = (DWORD*)buffer;
601     
602     check_variant_header(wirev, &v, size);
603     wirev += 5;
604     ok(*wirev == 8, "wv[5] %08lx\n", *wirev);
605     wirev++;
606     ok(*(double*)wirev == d, "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
607     if (VARIANT_UNMARSHAL_WORKS)
608     {
609         VariantInit(&v2);
610         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
611         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
612         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
613         ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
614
615         VARIANT_UserFree(&umcb.Flags, &v2);
616     }
617     HeapFree(GetProcessHeap(), 0, buffer);
618
619     /*** VARIANT_BOOL ***/
620     VariantInit(&v);
621     V_VT(&v) = VT_BOOL;
622     V_BOOL(&v) = 0x1234;
623
624     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
625     ok(size == 22, "size %ld\n", size);
626
627     buffer = HeapAlloc(GetProcessHeap(), 0, size);
628     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
629     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
630     wirev = (DWORD*)buffer;
631     
632     check_variant_header(wirev, &v, size);
633     wirev += 5;
634     ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
635     if (VARIANT_UNMARSHAL_WORKS)
636     {
637         VariantInit(&v2);
638         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
639         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
640         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
641         ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
642
643         VARIANT_UserFree(&umcb.Flags, &v2);
644     }
645     HeapFree(GetProcessHeap(), 0, buffer);
646
647     /*** DECIMAL ***/
648     VarDecFromI4(0x12345678, &dec);
649     VariantInit(&v);
650     V_DECIMAL(&v) = dec;
651     V_VT(&v) = VT_DECIMAL;
652
653     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
654     ok(size == 40, "size %ld\n", size);
655
656     buffer = HeapAlloc(GetProcessHeap(), 0, size);
657     memset(buffer, 0xcc, size);
658     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
659     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
660     wirev = (DWORD*)buffer;
661
662     check_variant_header(wirev, &v, size);
663     wirev += 5;
664     ok(*wirev == 0xcccccccc, "wirev[5] %08lx\n", *wirev); /* pad */
665     wirev++;
666     dec2 = dec;
667     dec2.wReserved = VT_DECIMAL;
668     ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n",
669        *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
670     if (VARIANT_UNMARSHAL_WORKS)
671     {
672         VariantInit(&v2);
673         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
674         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
675         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
676         ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
677
678         VARIANT_UserFree(&umcb.Flags, &v2);
679     }
680     HeapFree(GetProcessHeap(), 0, buffer);
681
682     /*** DECIMAL BYREF ***/
683     VariantInit(&v);
684     V_VT(&v) = VT_DECIMAL | VT_BYREF;
685     V_DECIMALREF(&v) = &dec;
686
687     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
688     ok(size == 40, "size %ld\n", size);
689
690     buffer = HeapAlloc(GetProcessHeap(), 0, size);
691     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
692     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
693     wirev = (DWORD*)buffer;
694     
695     check_variant_header(wirev, &v, size);
696     wirev += 5;
697     ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
698     wirev++;
699     ok(!memcmp(wirev, &dec, sizeof(dec)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n", *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
700     if (VARIANT_UNMARSHAL_WORKS)
701     {
702         VariantInit(&v2);
703         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
704         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
705         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
706         ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
707
708         VARIANT_UserFree(&umcb.Flags, &v2);
709     }
710     HeapFree(GetProcessHeap(), 0, buffer);
711
712     /*** EMPTY ***/
713     VariantInit(&v);
714     V_VT(&v) = VT_EMPTY;
715
716     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
717     ok(size == 20, "size %ld\n", size);
718
719     buffer = HeapAlloc(GetProcessHeap(), 0, size);
720     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
721     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
722     wirev = (DWORD*)buffer;
723
724     check_variant_header(wirev, &v, size);
725     if (VARIANT_UNMARSHAL_WORKS)
726     {
727         VariantInit(&v2);
728         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
729         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
730         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
731
732         VARIANT_UserFree(&umcb.Flags, &v2);
733     }
734     HeapFree(GetProcessHeap(), 0, buffer);
735
736     /*** NULL ***/
737     VariantInit(&v);
738     V_VT(&v) = VT_NULL;
739
740     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
741     ok(size == 20, "size %ld\n", size);
742
743     buffer = HeapAlloc(GetProcessHeap(), 0, size);
744     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
745     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
746     wirev = (DWORD*)buffer;
747
748     check_variant_header(wirev, &v, size);
749     if (VARIANT_UNMARSHAL_WORKS)
750     {
751         VariantInit(&v2);
752         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
753         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
754         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
755
756         VARIANT_UserFree(&umcb.Flags, &v2);
757     }
758     HeapFree(GetProcessHeap(), 0, buffer);
759
760     /*** BSTR ***/
761     b = SysAllocString(str);
762     VariantInit(&v);
763     V_VT(&v) = VT_BSTR;
764     V_BSTR(&v) = b;
765
766     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
767     ok(size == 60, "size %ld\n", size);
768     buffer = HeapAlloc(GetProcessHeap(), 0, size);
769     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
770     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
771     wirev = (DWORD*)buffer;
772     
773     check_variant_header(wirev, &v, size);
774     wirev += 5;
775     ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
776     wirev++;
777     check_bstr(wirev, V_BSTR(&v));
778     if (VARIANT_UNMARSHAL_WORKS)
779     {
780         VariantInit(&v2);
781         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
782         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
783         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
784         ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
785         ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
786
787         VARIANT_UserFree(&umcb.Flags, &v2);
788     }
789     HeapFree(GetProcessHeap(), 0, buffer);
790
791     /*** BSTR BYREF ***/
792     VariantInit(&v);
793     V_VT(&v) = VT_BSTR | VT_BYREF;
794     V_BSTRREF(&v) = &b;
795
796     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
797     ok(size == 64, "size %ld\n", size);
798     buffer = HeapAlloc(GetProcessHeap(), 0, size);
799     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
800     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
801     wirev = (DWORD*)buffer;
802     
803     check_variant_header(wirev, &v, size);
804     wirev += 5;
805     ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
806     wirev++;
807     ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
808     wirev++;
809     check_bstr(wirev, b);
810     if (VARIANT_UNMARSHAL_WORKS)
811     {
812         VariantInit(&v2);
813         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
814         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
815         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
816         ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
817         ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
818
819         VARIANT_UserFree(&umcb.Flags, &v2);
820     }
821     HeapFree(GetProcessHeap(), 0, buffer);
822     SysFreeString(b);
823
824     /*** ARRAY ***/
825     sab.lLbound = 5;
826     sab.cElements = 10;
827
828     lpsa = SafeArrayCreate(VT_R8, 1, &sab);
829     *(DWORD *)lpsa->pvData = 0xcafebabe;
830     *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
831     lpsa->cLocks = 7;
832
833     VariantInit(&v);
834     V_VT(&v) = VT_UI4 | VT_ARRAY;
835     V_ARRAY(&v) = lpsa;
836
837     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
838     ok(size == 152, "size %ld\n", size);
839     buffer = HeapAlloc(GetProcessHeap(), 0, size);
840     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
841     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
842     wirev = (DWORD*)buffer;
843     
844     check_variant_header(wirev, &v, size);
845     wirev += 5;
846     ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
847     wirev++;
848     check_safearray(wirev, lpsa);
849     if (VARIANT_UNMARSHAL_WORKS)
850     {
851         long bound, bound2;
852         VARTYPE vt, vt2;
853         VariantInit(&v2);
854         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
855         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
856         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
857         ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");  
858         SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
859         SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
860         ok(bound == bound2, "array lbounds differ\n");
861         SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
862         SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
863         ok(bound == bound2, "array ubounds differ\n");
864         SafeArrayGetVartype(V_ARRAY(&v), &vt);
865         SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
866         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
867         VARIANT_UserFree(&umcb.Flags, &v2);
868     }
869     HeapFree(GetProcessHeap(), 0, buffer);
870
871     /*** ARRAY BYREF ***/
872     VariantInit(&v);
873     V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
874     V_ARRAYREF(&v) = &lpsa;
875
876     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
877     ok(size == 152, "size %ld\n", size);
878     buffer = HeapAlloc(GetProcessHeap(), 0, size);
879     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
880     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
881     wirev = (DWORD*)buffer;
882     
883     check_variant_header(wirev, &v, size);
884     wirev += 5;
885     ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
886     wirev++;
887     ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
888     wirev++;
889     check_safearray(wirev, lpsa);
890     if (VARIANT_UNMARSHAL_WORKS)
891     {
892         long bound, bound2;
893         VARTYPE vt, vt2;
894         VariantInit(&v2);
895         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
896         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
897         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
898         ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");  
899         SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
900         SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
901         ok(bound == bound2, "array lbounds differ\n");
902         SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
903         SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
904         ok(bound == bound2, "array ubounds differ\n");
905         SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
906         SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
907         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
908         VARIANT_UserFree(&umcb.Flags, &v2);
909     }
910     HeapFree(GetProcessHeap(), 0, buffer);
911     SafeArrayDestroy(lpsa);
912
913     /*** VARIANT BYREF ***/
914     VariantInit(&v);
915     VariantInit(&v2);
916     V_VT(&v2) = VT_R8;
917     V_R8(&v2) = 3.1415;
918     V_VT(&v) = VT_VARIANT | VT_BYREF;
919     V_VARIANTREF(&v) = &v2;
920
921     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
922     ok(size == 64, "size %ld\n", size);
923     buffer = HeapAlloc(GetProcessHeap(), 0, size);
924     memset(buffer, 0xcc, size);
925     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
926     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
927     wirev = (DWORD*)buffer;
928     check_variant_header(wirev, &v, size);
929     wirev += 5;
930
931     ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
932     wirev++;
933     ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08lx\n", *wirev); /* 'User' */
934     wirev++;
935     ok(*wirev == 0xcccccccc, "wv[7] %08lx\n", *wirev); /* pad */
936     wirev++;
937     check_variant_header(wirev, &v2, size - 32);
938     wirev += 5;
939     ok(*wirev == 0xcccccccc, "wv[13] %08lx\n", *wirev); /* pad for VT_R8 */
940     wirev++;
941     ok(*(double*)wirev == V_R8(&v2), "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
942     if (VARIANT_UNMARSHAL_WORKS)
943     {
944         VARIANT v3;
945         VariantInit(&v3);
946         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
947         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
948         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
949         ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
950            V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3))); 
951         ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n"); 
952         VARIANT_UserFree(&umcb.Flags, &v3);
953     }
954     HeapFree(GetProcessHeap(), 0, buffer);
955 }
956
957
958 START_TEST(usrmarshal)
959 {
960     CoInitialize(NULL);
961
962     test_marshal_LPSAFEARRAY();
963     test_marshal_BSTR();
964     test_marshal_VARIANT();
965
966     CoUninitialize();
967 }