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