Update the address of the Free Software Foundation.
[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 /* 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 = SysStringByteLen(b);
231
232     ok(*wireb == (len + 1) / 2, "wv[0] %08lx\n", *wireb);
233     wireb++;
234     if(b)
235         ok(*wireb == len, "wv[1] %08lx\n", *wireb);
236     else
237         ok(*wireb == 0xffffffff, "wv[1] %08lx\n", *wireb);
238     wireb++;
239     ok(*wireb == (len + 1) / 2, "wv[2] %08lx\n", *wireb);
240     if(len)
241     {
242         wireb++;
243         ok(!memcmp(wireb, b, (len + 1) & ~1), "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, *next;
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     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
275     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
276     check_bstr(buffer, b);
277
278     if (BSTR_UNMARSHAL_WORKS)
279     {
280         b2 = NULL;
281         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
282         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
283         ok(b2 != NULL, "BSTR didn't unmarshal\n");
284         ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
285         BSTR_UserFree(&umcb.Flags, &b2);
286     }
287
288     HeapFree(GetProcessHeap(), 0, buffer);
289     SysFreeString(b);
290
291     b = NULL;
292     size = BSTR_UserSize(&umcb.Flags, 0, &b);
293     ok(size == 12, "size %ld\n", size);
294
295     buffer = HeapAlloc(GetProcessHeap(), 0, size);
296     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
297     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
298
299     check_bstr(buffer, b);
300     if (BSTR_UNMARSHAL_WORKS)
301     {
302         b2 = NULL;
303         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
304         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
305         ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
306         BSTR_UserFree(&umcb.Flags, &b2);
307     }
308     HeapFree(GetProcessHeap(), 0, buffer);
309
310     b = SysAllocStringByteLen("abc", 3);
311     *(((char*)b) + 3) = 'd';
312     len = SysStringLen(b);
313     ok(len == 1, "get %ld\n", len);
314     len = SysStringByteLen(b);
315     ok(len == 3, "get %ld\n", len);
316
317     size = BSTR_UserSize(&umcb.Flags, 0, &b);
318     ok(size == 16, "size %ld\n", size);
319
320     buffer = HeapAlloc(GetProcessHeap(), 0, size);
321     memset(buffer, 0xcc, size);
322     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
323     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
324     check_bstr(buffer, b);
325     ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
326
327     if (BSTR_UNMARSHAL_WORKS)
328     {
329         b2 = NULL;
330         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
331         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
332         ok(b2 != NULL, "BSTR didn't unmarshal\n");
333         ok(!memcmp(b, b2, len), "strings differ\n");
334         BSTR_UserFree(&umcb.Flags, &b2);
335     }
336     HeapFree(GetProcessHeap(), 0, buffer);
337     SysFreeString(b);
338
339     b = SysAllocStringByteLen("", 0);
340     len = SysStringLen(b);
341     ok(len == 0, "get %ld\n", len);
342     len = SysStringByteLen(b);
343     ok(len == 0, "get %ld\n", len);
344
345     size = BSTR_UserSize(&umcb.Flags, 0, &b);
346     ok(size == 12, "size %ld\n", size);
347
348     buffer = HeapAlloc(GetProcessHeap(), 0, size);
349     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
350     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
351     check_bstr(buffer, b);
352
353     if (BSTR_UNMARSHAL_WORKS)
354     {
355         b2 = NULL;
356         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
357         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
358         ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
359         len = SysStringByteLen(b2);
360         ok(len == 0, "byte len %ld\n", len);
361         BSTR_UserFree(&umcb.Flags, &b2);
362     }
363     HeapFree(GetProcessHeap(), 0, buffer);
364     SysFreeString(b);
365 }
366
367 static void check_variant_header(DWORD *wirev, VARIANT *v, unsigned long size)
368 {
369     WORD *wp;
370     DWORD switch_is;
371
372     ok(*wirev == (size + 7) >> 3, "wv[0] %08lx, expected %08lx\n", *wirev, (size + 7) >> 3);
373     wirev++;
374     ok(*wirev == 0, "wv[1] %08lx\n", *wirev);
375     wirev++;
376     wp = (WORD*)wirev;
377     ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
378     wp++;
379     ok(*wp == v->n1.n2.wReserved1, "res1 %04x expected %04x\n", *wp, v->n1.n2.wReserved1);
380     wp++;
381     ok(*wp == v->n1.n2.wReserved2, "res2 %04x expected %04x\n", *wp, v->n1.n2.wReserved2);
382     wp++;
383     ok(*wp == v->n1.n2.wReserved3, "res3 %04x expected %04x\n", *wp, v->n1.n2.wReserved3);
384     wp++;
385     wirev = (DWORD*)wp;
386     switch_is = V_VT(v);
387     if(switch_is & VT_ARRAY)
388         switch_is &= ~VT_TYPEMASK;
389     ok(*wirev == switch_is, "switch_is %08lx expected %08lx\n", *wirev, switch_is);
390 }
391
392 static void test_marshal_VARIANT(void)
393 {
394     unsigned long size;
395     VARIANT v, v2;
396     MIDL_STUB_MESSAGE stubMsg = { 0 };
397     USER_MARSHAL_CB umcb = { 0 };
398     unsigned char *buffer, *next;
399     unsigned long ul;
400     short s;
401     double d;
402     DWORD *wirev;
403     BSTR b;
404     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
405     SAFEARRAYBOUND sab;
406     LPSAFEARRAY lpsa;
407     DECIMAL dec, dec2;
408
409     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
410     umcb.pReserve = NULL;
411     umcb.pStubMsg = &stubMsg;
412
413     /*** I1 ***/
414     VariantInit(&v);
415     V_VT(&v) = VT_I1;
416     V_I1(&v) = 0x12;
417
418     /* Variants have an alignment of 8 */
419     size = VARIANT_UserSize(&umcb.Flags, 1, &v);
420     ok(size == 29, "size %ld\n", size);
421
422     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
423     ok(size == 21, "size %ld\n", size);
424
425     buffer = HeapAlloc(GetProcessHeap(), 0, size);
426     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
427     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
428     wirev = (DWORD*)buffer;
429     
430     check_variant_header(wirev, &v, size);
431     wirev += 5;
432     ok(*(char*)wirev == V_I1(&v), "wv[5] %08lx\n", *wirev);
433     if (VARIANT_UNMARSHAL_WORKS)
434     {
435         VariantInit(&v2);
436         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
437         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
438         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
439         ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
440
441         VARIANT_UserFree(&umcb.Flags, &v2);
442     }
443     HeapFree(GetProcessHeap(), 0, buffer);
444
445     /*** I2 ***/
446     VariantInit(&v);
447     V_VT(&v) = VT_I2;
448     V_I2(&v) = 0x1234;
449
450     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
451     ok(size == 22, "size %ld\n", size);
452
453     buffer = HeapAlloc(GetProcessHeap(), 0, size);
454     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
455     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
456     wirev = (DWORD*)buffer;
457
458     check_variant_header(wirev, &v, size);
459     wirev += 5;
460     ok(*(short*)wirev == V_I2(&v), "wv[5] %08lx\n", *wirev);
461     if (VARIANT_UNMARSHAL_WORKS)
462     {
463         VariantInit(&v2);
464         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
465         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
466         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
467         ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
468
469         VARIANT_UserFree(&umcb.Flags, &v2);
470     }
471     HeapFree(GetProcessHeap(), 0, buffer);
472
473     /*** I2 BYREF ***/
474     VariantInit(&v);
475     V_VT(&v) = VT_I2 | VT_BYREF;
476     s = 0x1234;
477     V_I2REF(&v) = &s;
478
479     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
480     ok(size == 26, "size %ld\n", size);
481
482     buffer = HeapAlloc(GetProcessHeap(), 0, size);
483     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
484     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
485     wirev = (DWORD*)buffer;
486
487     check_variant_header(wirev, &v, size);
488     wirev += 5;
489     ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
490     wirev++;
491     ok(*(short*)wirev == s, "wv[6] %08lx\n", *wirev);
492     if (VARIANT_UNMARSHAL_WORKS)
493     {
494         VariantInit(&v2);
495         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
496         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
497         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
498         ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
499
500         VARIANT_UserFree(&umcb.Flags, &v2);
501     }
502     HeapFree(GetProcessHeap(), 0, buffer);
503
504     /*** I4 ***/
505     VariantInit(&v);
506     V_VT(&v) = VT_I4;
507     V_I4(&v) = 0x1234;
508
509     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
510     ok(size == 24, "size %ld\n", size);
511
512     buffer = HeapAlloc(GetProcessHeap(), 0, size);
513     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
514     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
515     wirev = (DWORD*)buffer;
516     
517     check_variant_header(wirev, &v, size);
518     wirev += 5;
519     ok(*wirev == V_I4(&v), "wv[5] %08lx\n", *wirev);
520
521     if (VARIANT_UNMARSHAL_WORKS)
522     {
523         VariantInit(&v2);
524         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
525         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
526         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
527         ok(V_I4(&v) == V_I4(&v2), "got i4 %lx expect %lx\n", V_I4(&v), V_I4(&v2));
528
529         VARIANT_UserFree(&umcb.Flags, &v2);
530     }
531
532     HeapFree(GetProcessHeap(), 0, buffer);
533
534     /*** UI4 ***/
535     VariantInit(&v);
536     V_VT(&v) = VT_UI4;
537     V_UI4(&v) = 0x1234;
538
539     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
540     ok(size == 24, "size %ld\n", size);
541
542     buffer = HeapAlloc(GetProcessHeap(), 0, size);
543     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
544     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
545     wirev = (DWORD*)buffer;
546     
547     check_variant_header(wirev, &v, size);
548     wirev += 5;
549     ok(*wirev == 0x1234, "wv[5] %08lx\n", *wirev);
550     if (VARIANT_UNMARSHAL_WORKS)
551     {
552         VariantInit(&v2);
553         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
554         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
555         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
556         ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %lx expect %lx\n", V_UI4(&v), V_UI4(&v2));
557
558         VARIANT_UserFree(&umcb.Flags, &v2);
559     }
560
561     HeapFree(GetProcessHeap(), 0, buffer);
562
563     /*** UI4 BYREF ***/
564     VariantInit(&v);
565     V_VT(&v) = VT_UI4 | VT_BYREF;
566     ul = 0x1234;
567     V_UI4REF(&v) = &ul;
568
569     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
570     ok(size == 28, "size %ld\n", size);
571
572     buffer = HeapAlloc(GetProcessHeap(), 0, size);
573     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
574     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
575     wirev = (DWORD*)buffer;
576     
577     check_variant_header(wirev, &v, size);
578     wirev += 5;
579     ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
580     wirev++;
581     ok(*wirev == ul, "wv[6] %08lx\n", *wirev);
582
583     if (VARIANT_UNMARSHAL_WORKS)
584     {
585         VariantInit(&v2);
586         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
587         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
588         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
589         ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %lx expect ui4 ref %lx\n", *V_UI4REF(&v), *V_UI4REF(&v2));
590
591         VARIANT_UserFree(&umcb.Flags, &v2);
592     }
593     HeapFree(GetProcessHeap(), 0, buffer);
594
595     /*** R4 ***/
596     VariantInit(&v);
597     V_VT(&v) = VT_R4;
598     V_R8(&v) = 3.1415;
599
600     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
601     ok(size == 24, "size %ld\n", size);
602
603     buffer = HeapAlloc(GetProcessHeap(), 0, size);
604     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
605     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
606     wirev = (DWORD*)buffer;
607      
608     check_variant_header(wirev, &v, size);
609     wirev += 5;
610     ok(*(float*)wirev == V_R4(&v), "wv[5] %08lx\n", *wirev);
611     if (VARIANT_UNMARSHAL_WORKS)
612     {
613         VariantInit(&v2);
614         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
615         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
616         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
617         ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
618
619         VARIANT_UserFree(&umcb.Flags, &v2);
620     }
621     HeapFree(GetProcessHeap(), 0, buffer);
622
623     /*** R8 ***/
624     VariantInit(&v);
625     V_VT(&v) = VT_R8;
626     V_R8(&v) = 3.1415;
627
628     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
629     ok(size == 32, "size %ld\n", size);
630
631     buffer = HeapAlloc(GetProcessHeap(), 0, size);
632     memset(buffer, 0xcc, size);
633     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
634     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
635     wirev = (DWORD*)buffer;
636     
637     check_variant_header(wirev, &v, size);
638     wirev += 5;
639     ok(*wirev == 0xcccccccc, "wv[5] %08lx\n", *wirev); /* pad */
640     wirev++;
641     ok(*(double*)wirev == V_R8(&v), "wv[6] %08lx, wv[7] %08lx\n", *wirev, *(wirev+1));
642     if (VARIANT_UNMARSHAL_WORKS)
643     {
644         VariantInit(&v2);
645         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
646         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
647         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
648         ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
649
650         VARIANT_UserFree(&umcb.Flags, &v2);
651     }
652     HeapFree(GetProcessHeap(), 0, buffer);
653
654     /*** R8 BYREF ***/
655     VariantInit(&v);
656     V_VT(&v) = VT_R8 | VT_BYREF;
657     d = 3.1415;
658     V_R8REF(&v) = &d;
659
660     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
661     ok(size == 32, "size %ld\n", size);
662
663     buffer = HeapAlloc(GetProcessHeap(), 0, size);
664     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
665     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
666     wirev = (DWORD*)buffer;
667     
668     check_variant_header(wirev, &v, size);
669     wirev += 5;
670     ok(*wirev == 8, "wv[5] %08lx\n", *wirev);
671     wirev++;
672     ok(*(double*)wirev == d, "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
673     if (VARIANT_UNMARSHAL_WORKS)
674     {
675         VariantInit(&v2);
676         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
677         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
678         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
679         ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
680
681         VARIANT_UserFree(&umcb.Flags, &v2);
682     }
683     HeapFree(GetProcessHeap(), 0, buffer);
684
685     /*** VARIANT_BOOL ***/
686     VariantInit(&v);
687     V_VT(&v) = VT_BOOL;
688     V_BOOL(&v) = 0x1234;
689
690     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
691     ok(size == 22, "size %ld\n", size);
692
693     buffer = HeapAlloc(GetProcessHeap(), 0, size);
694     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
695     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
696     wirev = (DWORD*)buffer;
697     
698     check_variant_header(wirev, &v, size);
699     wirev += 5;
700     ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
701     if (VARIANT_UNMARSHAL_WORKS)
702     {
703         VariantInit(&v2);
704         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
705         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
706         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
707         ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
708
709         VARIANT_UserFree(&umcb.Flags, &v2);
710     }
711     HeapFree(GetProcessHeap(), 0, buffer);
712
713     /*** DECIMAL ***/
714     VarDecFromI4(0x12345678, &dec);
715     VariantInit(&v);
716     V_DECIMAL(&v) = dec;
717     V_VT(&v) = VT_DECIMAL;
718
719     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
720     ok(size == 40, "size %ld\n", size);
721
722     buffer = HeapAlloc(GetProcessHeap(), 0, size);
723     memset(buffer, 0xcc, size);
724     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
725     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
726     wirev = (DWORD*)buffer;
727
728     check_variant_header(wirev, &v, size);
729     wirev += 5;
730     ok(*wirev == 0xcccccccc, "wirev[5] %08lx\n", *wirev); /* pad */
731     wirev++;
732     dec2 = dec;
733     dec2.wReserved = VT_DECIMAL;
734     ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08lx wirev[7] %08lx wirev[8] %08lx wirev[9] %08lx\n",
735        *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
736     if (VARIANT_UNMARSHAL_WORKS)
737     {
738         VariantInit(&v2);
739         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
740         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
741         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
742         ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
743
744         VARIANT_UserFree(&umcb.Flags, &v2);
745     }
746     HeapFree(GetProcessHeap(), 0, buffer);
747
748     /*** DECIMAL BYREF ***/
749     VariantInit(&v);
750     V_VT(&v) = VT_DECIMAL | VT_BYREF;
751     V_DECIMALREF(&v) = &dec;
752
753     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
754     ok(size == 40, "size %ld\n", size);
755
756     buffer = HeapAlloc(GetProcessHeap(), 0, size);
757     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
758     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
759     wirev = (DWORD*)buffer;
760     
761     check_variant_header(wirev, &v, size);
762     wirev += 5;
763     ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
764     wirev++;
765     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));
766     if (VARIANT_UNMARSHAL_WORKS)
767     {
768         VariantInit(&v2);
769         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
770         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
771         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
772         ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
773
774         VARIANT_UserFree(&umcb.Flags, &v2);
775     }
776     HeapFree(GetProcessHeap(), 0, buffer);
777
778     /*** EMPTY ***/
779     VariantInit(&v);
780     V_VT(&v) = VT_EMPTY;
781
782     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
783     ok(size == 20, "size %ld\n", size);
784
785     buffer = HeapAlloc(GetProcessHeap(), 0, size);
786     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
787     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
788     wirev = (DWORD*)buffer;
789
790     check_variant_header(wirev, &v, size);
791     if (VARIANT_UNMARSHAL_WORKS)
792     {
793         VariantInit(&v2);
794         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
795         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
796         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
797
798         VARIANT_UserFree(&umcb.Flags, &v2);
799     }
800     HeapFree(GetProcessHeap(), 0, buffer);
801
802     /*** NULL ***/
803     VariantInit(&v);
804     V_VT(&v) = VT_NULL;
805
806     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
807     ok(size == 20, "size %ld\n", size);
808
809     buffer = HeapAlloc(GetProcessHeap(), 0, size);
810     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
811     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
812     wirev = (DWORD*)buffer;
813
814     check_variant_header(wirev, &v, size);
815     if (VARIANT_UNMARSHAL_WORKS)
816     {
817         VariantInit(&v2);
818         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
819         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
820         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
821
822         VARIANT_UserFree(&umcb.Flags, &v2);
823     }
824     HeapFree(GetProcessHeap(), 0, buffer);
825
826     /*** BSTR ***/
827     b = SysAllocString(str);
828     VariantInit(&v);
829     V_VT(&v) = VT_BSTR;
830     V_BSTR(&v) = b;
831
832     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
833     ok(size == 60, "size %ld\n", size);
834     buffer = HeapAlloc(GetProcessHeap(), 0, size);
835     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
836     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
837     wirev = (DWORD*)buffer;
838     
839     check_variant_header(wirev, &v, size);
840     wirev += 5;
841     ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
842     wirev++;
843     check_bstr(wirev, V_BSTR(&v));
844     if (VARIANT_UNMARSHAL_WORKS)
845     {
846         VariantInit(&v2);
847         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
848         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
849         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
850         ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
851         ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
852
853         VARIANT_UserFree(&umcb.Flags, &v2);
854     }
855     HeapFree(GetProcessHeap(), 0, buffer);
856
857     /*** BSTR BYREF ***/
858     VariantInit(&v);
859     V_VT(&v) = VT_BSTR | VT_BYREF;
860     V_BSTRREF(&v) = &b;
861
862     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
863     ok(size == 64, "size %ld\n", size);
864     buffer = HeapAlloc(GetProcessHeap(), 0, size);
865     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
866     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
867     wirev = (DWORD*)buffer;
868     
869     check_variant_header(wirev, &v, size);
870     wirev += 5;
871     ok(*wirev == 0x4, "wv[5] %08lx\n", *wirev);
872     wirev++;
873     ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
874     wirev++;
875     check_bstr(wirev, b);
876     if (VARIANT_UNMARSHAL_WORKS)
877     {
878         VariantInit(&v2);
879         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
880         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
881         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
882         ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
883         ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
884
885         VARIANT_UserFree(&umcb.Flags, &v2);
886     }
887     HeapFree(GetProcessHeap(), 0, buffer);
888     SysFreeString(b);
889
890     /*** ARRAY ***/
891     sab.lLbound = 5;
892     sab.cElements = 10;
893
894     lpsa = SafeArrayCreate(VT_R8, 1, &sab);
895     *(DWORD *)lpsa->pvData = 0xcafebabe;
896     *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
897     lpsa->cLocks = 7;
898
899     VariantInit(&v);
900     V_VT(&v) = VT_UI4 | VT_ARRAY;
901     V_ARRAY(&v) = lpsa;
902
903     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
904     ok(size == 152, "size %ld\n", size);
905     buffer = HeapAlloc(GetProcessHeap(), 0, size);
906     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
907     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
908     wirev = (DWORD*)buffer;
909     
910     check_variant_header(wirev, &v, size);
911     wirev += 5;
912     ok(*wirev, "wv[5] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
913     wirev++;
914     check_safearray(wirev, lpsa);
915     if (VARIANT_UNMARSHAL_WORKS)
916     {
917         long bound, bound2;
918         VARTYPE vt, vt2;
919         VariantInit(&v2);
920         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
921         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
922         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
923         ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");  
924         SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
925         SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
926         ok(bound == bound2, "array lbounds differ\n");
927         SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
928         SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
929         ok(bound == bound2, "array ubounds differ\n");
930         SafeArrayGetVartype(V_ARRAY(&v), &vt);
931         SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
932         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
933         VARIANT_UserFree(&umcb.Flags, &v2);
934     }
935     HeapFree(GetProcessHeap(), 0, buffer);
936
937     /*** ARRAY BYREF ***/
938     VariantInit(&v);
939     V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
940     V_ARRAYREF(&v) = &lpsa;
941
942     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
943     ok(size == 152, "size %ld\n", size);
944     buffer = HeapAlloc(GetProcessHeap(), 0, size);
945     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
946     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
947     wirev = (DWORD*)buffer;
948     
949     check_variant_header(wirev, &v, size);
950     wirev += 5;
951     ok(*wirev == 4, "wv[5] %08lx\n", *wirev);
952     wirev++;
953     ok(*wirev, "wv[6] %08lx\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
954     wirev++;
955     check_safearray(wirev, lpsa);
956     if (VARIANT_UNMARSHAL_WORKS)
957     {
958         long bound, bound2;
959         VARTYPE vt, vt2;
960         VariantInit(&v2);
961         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
962         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
963         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
964         ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");  
965         SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
966         SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
967         ok(bound == bound2, "array lbounds differ\n");
968         SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
969         SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
970         ok(bound == bound2, "array ubounds differ\n");
971         SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
972         SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
973         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
974         VARIANT_UserFree(&umcb.Flags, &v2);
975     }
976     HeapFree(GetProcessHeap(), 0, buffer);
977     SafeArrayDestroy(lpsa);
978
979     /*** VARIANT BYREF ***/
980     VariantInit(&v);
981     VariantInit(&v2);
982     V_VT(&v2) = VT_R8;
983     V_R8(&v2) = 3.1415;
984     V_VT(&v) = VT_VARIANT | VT_BYREF;
985     V_VARIANTREF(&v) = &v2;
986
987     size = VARIANT_UserSize(&umcb.Flags, 0, &v);
988     ok(size == 64, "size %ld\n", size);
989     buffer = HeapAlloc(GetProcessHeap(), 0, size);
990     memset(buffer, 0xcc, size);
991     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
992     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
993     wirev = (DWORD*)buffer;
994     check_variant_header(wirev, &v, size);
995     wirev += 5;
996
997     ok(*wirev == 16, "wv[5] %08lx\n", *wirev);
998     wirev++;
999     ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08lx\n", *wirev); /* 'User' */
1000     wirev++;
1001     ok(*wirev == 0xcccccccc, "wv[7] %08lx\n", *wirev); /* pad */
1002     wirev++;
1003     check_variant_header(wirev, &v2, size - 32);
1004     wirev += 5;
1005     ok(*wirev == 0xcccccccc, "wv[13] %08lx\n", *wirev); /* pad for VT_R8 */
1006     wirev++;
1007     ok(*(double*)wirev == V_R8(&v2), "wv[6] %08lx wv[7] %08lx\n", *wirev, *(wirev+1));
1008     if (VARIANT_UNMARSHAL_WORKS)
1009     {
1010         VARIANT v3;
1011         VariantInit(&v3);
1012         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1013         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
1014         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1015         ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1016            V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3))); 
1017         ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n"); 
1018         VARIANT_UserFree(&umcb.Flags, &v3);
1019     }
1020     HeapFree(GetProcessHeap(), 0, buffer);
1021 }
1022
1023
1024 START_TEST(usrmarshal)
1025 {
1026     CoInitialize(NULL);
1027
1028     test_marshal_LPSAFEARRAY();
1029     test_marshal_BSTR();
1030     test_marshal_VARIANT();
1031
1032     CoUninitialize();
1033 }