mshtml: COM cleanup for the IHTMLDOMNode iface.
[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 #define COBJMACROS
22 #define CONST_VTABLE
23
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
29 #include "propidl.h" /* for LPSAFEARRAY_User* routines */
30
31 #include "wine/test.h"
32
33 #if (__STDC__ && !defined(_FORCENAMELESSUNION)) || defined(NONAMELESSUNION)
34 # define V_U2(A)  ((A)->n1.n2)
35 #else
36 # define V_U2(A)  (*(A))
37 #endif
38
39 #define LPSAFEARRAY_UNMARSHAL_WORKS 1
40 #define BSTR_UNMARSHAL_WORKS 1
41 #define VARIANT_UNMARSHAL_WORKS 1
42
43 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
44 {
45     VARTYPE vt;
46     HRESULT hr;
47
48     hr = SafeArrayGetVartype(psa, &vt);
49     if (FAILED(hr))
50     {
51         if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
52
53         switch(psa->cbElements)
54         {
55         case 1: vt = VT_I1; break;
56         case 2: vt = VT_I2; break;
57         case 4: vt = VT_I4; break;
58         case 8: vt = VT_I8; break;
59         default: return 0;
60         }
61     }
62
63     if (psa->fFeatures & FADF_HAVEIID)
64         return SF_HAVEIID;
65
66     switch (vt)
67     {
68     case VT_I1:
69     case VT_UI1:      return SF_I1;
70     case VT_BOOL:
71     case VT_I2:
72     case VT_UI2:      return SF_I2;
73     case VT_INT:
74     case VT_UINT:
75     case VT_I4:
76     case VT_UI4:
77     case VT_R4:       return SF_I4;
78     case VT_DATE:
79     case VT_CY:
80     case VT_R8:
81     case VT_I8:
82     case VT_UI8:      return SF_I8;
83     case VT_INT_PTR:
84     case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
85     case VT_BSTR:     return SF_BSTR;
86     case VT_DISPATCH: return SF_DISPATCH;
87     case VT_VARIANT:  return SF_VARIANT;
88     case VT_UNKNOWN:  return SF_UNKNOWN;
89     /* Note: Return a non-zero size to indicate vt is valid. The actual size
90      * of a UDT is taken from the result of IRecordInfo_GetSize().
91      */
92     case VT_RECORD:   return SF_RECORD;
93     default:          return SF_ERROR;
94     }
95 }
96
97 static ULONG get_cell_count(const SAFEARRAY *psa)
98 {
99     const SAFEARRAYBOUND* psab = psa->rgsabound;
100     USHORT cCount = psa->cDims;
101     ULONG ulNumCells = 1;
102
103     while (cCount--)
104     {
105          if (!psab->cElements)
106             return 0;
107         ulNumCells *= psab->cElements;
108         psab++;
109     }
110     return ulNumCells;
111 }
112
113 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
114 {
115     if (sftype == SF_BSTR)
116         return sizeof(DWORD);
117     else
118         return lpsa->cbElements;
119 }
120
121 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
122 {
123     unsigned char *wiresa = buffer;
124     const SAFEARRAYBOUND *bounds;
125     VARTYPE vt;
126     SF_TYPE sftype;
127     ULONG cell_count;
128     int i;
129
130     if(!lpsa)
131     {
132         ok(*(DWORD *)wiresa == 0, "wiresa + 0x0 should be NULL instead of 0x%08x\n", *(DWORD *)wiresa);
133         return;
134     }
135
136     if(FAILED(SafeArrayGetVartype(lpsa, &vt)))
137         vt = 0;
138
139     sftype = get_union_type(lpsa);
140     cell_count = get_cell_count(lpsa);
141
142     ok(*(DWORD *)wiresa, "wiresa + 0x0 should be non-NULL instead of 0x%08x\n", *(DWORD *)wiresa); /* win2k: this is lpsa. winxp: this is 0x00000001 */
143     wiresa += sizeof(DWORD);
144     ok(*(DWORD *)wiresa == lpsa->cDims, "wiresa + 0x4 should be lpsa->cDims instead of 0x%08x\n", *(DWORD *)wiresa);
145     wiresa += sizeof(DWORD);
146     ok(*(WORD *)wiresa == lpsa->cDims, "wiresa + 0x8 should be lpsa->cDims instead of 0x%04x\n", *(WORD *)wiresa);
147     wiresa += sizeof(WORD);
148     ok(*(WORD *)wiresa == lpsa->fFeatures, "wiresa + 0xa should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
149     wiresa += sizeof(WORD);
150     ok(*(DWORD *)wiresa == elem_wire_size(lpsa, sftype), "wiresa + 0xc should be 0x%08x instead of 0x%08x\n", elem_wire_size(lpsa, sftype), *(DWORD *)wiresa);
151     wiresa += sizeof(DWORD);
152     ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x10 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
153     wiresa += sizeof(WORD);
154     ok(*(WORD *)wiresa == vt, "wiresa + 0x12 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
155     wiresa += sizeof(WORD);
156     ok(*(DWORD *)wiresa == sftype, "wiresa + 0x14 should be %08x instead of 0x%08x\n", (DWORD)sftype, *(DWORD *)wiresa);
157     wiresa += sizeof(DWORD);
158     ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x18 should be %u instead of %u\n", cell_count, *(DWORD *)wiresa);
159     wiresa += sizeof(DWORD);
160     ok(*(DWORD *)wiresa, "wiresa + 0x1c should be non-zero instead of 0x%08x\n", *(DWORD *)wiresa);
161     wiresa += sizeof(DWORD);
162     if(sftype == SF_HAVEIID)
163     {
164         GUID guid;
165         SafeArrayGetIID(lpsa, &guid);
166         ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
167         wiresa += sizeof(GUID);
168     }
169
170     /* bounds are marshaled in natural dimensions order */
171     bounds = (SAFEARRAYBOUND*)wiresa;
172     for(i=0; i<lpsa->cDims; i++)
173     {
174         ok(memcmp(bounds, &lpsa->rgsabound[lpsa->cDims-i-1], sizeof(SAFEARRAYBOUND)) == 0,
175            "bounds mismatch for dimension %d, got (%d,%d), expected (%d,%d)\n", i,
176             bounds->lLbound, bounds->cElements, lpsa->rgsabound[lpsa->cDims-i-1].lLbound,
177             lpsa->rgsabound[lpsa->cDims-i-1].cElements);
178         bounds++;
179     }
180
181     wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
182
183     ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x28 should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
184     wiresa += sizeof(DWORD);
185     /* elements are now pointed to by wiresa */
186 }
187
188 static void * WINAPI user_allocate(SIZE_T size)
189 {
190     return CoTaskMemAlloc(size);
191 }
192
193 static void WINAPI user_free(void *p)
194 {
195     CoTaskMemFree(p);
196 }
197
198 static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
199                                  PMIDL_STUB_MESSAGE stub_msg,
200                                  PRPC_MESSAGE rpc_msg, unsigned char *buffer,
201                                  unsigned int size, MSHCTX context)
202 {
203     memset(rpc_msg, 0, sizeof(*rpc_msg));
204     rpc_msg->Buffer = buffer;
205     rpc_msg->BufferLength = size;
206
207     memset(stub_msg, 0, sizeof(*stub_msg));
208     stub_msg->RpcMsg = rpc_msg;
209     stub_msg->Buffer = buffer;
210     stub_msg->pfnAllocate = user_allocate;
211     stub_msg->pfnFree = user_free;
212
213     memset(umcb, 0, sizeof(*umcb));
214     umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION);
215     umcb->pStubMsg = stub_msg;
216     umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
217     umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
218 }
219
220 static void test_marshal_LPSAFEARRAY(void)
221 {
222     unsigned char *buffer, *next;
223     ULONG size, expected;
224     LPSAFEARRAY lpsa;
225     LPSAFEARRAY lpsa2 = NULL;
226     SAFEARRAYBOUND sab[2];
227     RPC_MESSAGE rpc_msg;
228     MIDL_STUB_MESSAGE stub_msg;
229     USER_MARSHAL_CB umcb;
230     HRESULT hr;
231     VARTYPE vt;
232     OLECHAR *values[10];
233     int expected_bstr_size;
234     int i;
235     LONG indices[1];
236
237     sab[0].lLbound = 5;
238     sab[0].cElements = 10;
239
240     lpsa = SafeArrayCreate(VT_I2, 1, sab);
241     *(DWORD *)lpsa->pvData = 0xcafebabe;
242
243     lpsa->cLocks = 7;
244     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
245     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
246     expected = (44 + 1 + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
247     expected += sab[0].cElements * sizeof(USHORT);
248     ok(size == expected || size == expected + 12, /* win64 */
249        "size should be %u bytes, not %u\n", expected, size);
250     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
251     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
252     expected = 44 + sab[0].cElements * sizeof(USHORT);
253     ok(size == expected || size == expected + 12, /* win64 */
254        "size should be %u bytes, not %u\n", expected, size);
255     buffer = HeapAlloc(GetProcessHeap(), 0, size);
256     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
257     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
258     ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
259
260     check_safearray(buffer, lpsa);
261
262     if (LPSAFEARRAY_UNMARSHAL_WORKS)
263     {
264         VARTYPE vt, vt2;
265         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
266         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
267         ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
268         SafeArrayGetVartype(lpsa, &vt);
269         SafeArrayGetVartype(lpsa2, &vt2);
270         ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
271         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
272         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
273     }
274     HeapFree(GetProcessHeap(), 0, buffer);
275     lpsa->cLocks = 0;
276     SafeArrayDestroy(lpsa);
277
278     /* use two dimensions */
279     sab[0].lLbound = 5;
280     sab[0].cElements = 10;
281     sab[1].lLbound = 1;
282     sab[1].cElements = 2;
283
284     lpsa = SafeArrayCreate(VT_I2, 2, sab);
285     *(DWORD *)lpsa->pvData = 0xcafebabe;
286
287     lpsa->cLocks = 7;
288     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
289     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
290     expected = (44 + 1 + +sizeof(SAFEARRAYBOUND) + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
291     expected += max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
292     ok(size == expected || size == expected + 12, /* win64 */
293        "size should be %u bytes, not %u\n", expected, size);
294     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
295     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
296     expected = 52 + max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
297     ok(size == expected || size == expected + 12, /* win64 */
298        "size should be %u bytes, not %u\n", expected, size);
299     buffer = HeapAlloc(GetProcessHeap(), 0, size);
300     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
301     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
302     ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
303
304     check_safearray(buffer, lpsa);
305
306     if (LPSAFEARRAY_UNMARSHAL_WORKS)
307     {
308         VARTYPE vt, vt2;
309         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
310         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
311         ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
312         SafeArrayGetVartype(lpsa, &vt);
313         SafeArrayGetVartype(lpsa2, &vt2);
314         ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
315         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
316         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
317     }
318     HeapFree(GetProcessHeap(), 0, buffer);
319     lpsa->cLocks = 0;
320     SafeArrayDestroy(lpsa);
321
322     /* test NULL safe array */
323     lpsa = NULL;
324
325     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
326     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
327     expected = 4;
328     ok(size == expected, "size should be 4 bytes, not %d\n", size);
329     buffer = HeapAlloc(GetProcessHeap(), 0, size);
330     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
331     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
332     ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
333     check_safearray(buffer, lpsa);
334
335     if (LPSAFEARRAY_UNMARSHAL_WORKS)
336     {
337         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
338         LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
339         ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
340         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
341         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
342     }
343     HeapFree(GetProcessHeap(), 0, buffer);
344
345     sab[0].lLbound = 5;
346     sab[0].cElements = 10;
347
348     lpsa = SafeArrayCreate(VT_R8, 1, sab);
349     *(double *)lpsa->pvData = 3.1415;
350
351     lpsa->cLocks = 7;
352     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
353     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
354     expected = (44 + 1 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
355     expected += sab[0].cElements * sizeof(double);
356     ok(size == expected || size == expected + 16, /* win64 */
357        "size should be %u bytes, not %u\n", expected, size);
358     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
359     expected = (44 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
360     expected += sab[0].cElements * sizeof(double);
361     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
362     ok(size == expected || size == expected + 8, /* win64 */
363        "size should be %u bytes, not %u\n", expected, size);
364     buffer = HeapAlloc(GetProcessHeap(), 0, size);
365     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
366     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
367     ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
368             "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
369
370     check_safearray(buffer, lpsa);
371
372     HeapFree(GetProcessHeap(), 0, buffer);
373     lpsa->cLocks = 0;
374     SafeArrayDestroy(lpsa);
375
376     /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
377     hr = SafeArrayAllocDescriptor(1, &lpsa);
378     ok(hr == S_OK, "saad failed %08x\n", hr);
379     lpsa->cbElements = 8;
380     lpsa->rgsabound[0].lLbound = 2;
381     lpsa->rgsabound[0].cElements = 48;
382     hr = SafeArrayAllocData(lpsa);
383     ok(hr == S_OK, "saad failed %08x\n", hr);
384
385     hr = SafeArrayGetVartype(lpsa, &vt);
386     ok(hr == E_INVALIDARG, "ret %08x\n", hr);
387
388     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
389     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
390     expected = (44 + lpsa->cbElements - 1) & ~(lpsa->cbElements - 1);
391     expected += lpsa->cbElements * lpsa->rgsabound[0].cElements;
392     ok(size == expected || size == expected + 8,  /* win64 */
393        "size should be %u bytes, not %u\n", expected, size);
394     buffer = HeapAlloc(GetProcessHeap(), 0, size);
395     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
396     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
397     ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
398             "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
399     check_safearray(buffer, lpsa);
400     HeapFree(GetProcessHeap(), 0, buffer);
401     SafeArrayDestroyData(lpsa);
402     SafeArrayDestroyDescriptor(lpsa);
403
404     /* Test an array of VT_BSTR */
405     sab[0].lLbound = 3;
406     sab[0].cElements = sizeof(values) / sizeof(values[0]);
407
408     lpsa = SafeArrayCreate(VT_BSTR, 1, sab);
409     expected_bstr_size = 0;
410     for (i = 0; i < sab[0].cElements; i++)
411     {
412         int j;
413         WCHAR buf[128];
414         for (j = 0; j <= i; j++)
415             buf[j] = 'a' + j;
416         buf[j] = 0;
417         indices[0] = i + sab[0].lLbound;
418         values[i] = SysAllocString(buf);
419         hr = SafeArrayPutElement(lpsa, indices, values[i]);
420         ok(hr == S_OK, "Failed to put bstr element hr 0x%x\n", hr);
421         expected_bstr_size += (j * sizeof(WCHAR)) + (3 * sizeof(DWORD));
422         if (i % 2 == 0) /* Account for DWORD padding.  Works so long as cElements is even */
423             expected_bstr_size += sizeof(WCHAR);
424     }
425
426     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
427     size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
428     expected = 44 + (sab[0].cElements * sizeof(DWORD)) + expected_bstr_size;
429     todo_wine
430     ok(size == expected + sizeof(DWORD) || size  == (expected + sizeof(DWORD) + 12 /* win64 */),
431             "size should be %u bytes, not %u\n", expected + (ULONG) sizeof(DWORD), size);
432     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
433     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
434     todo_wine
435     ok(size == expected || size  == (expected + 12 /* win64 */),
436         "size should be %u bytes, not %u\n", expected, size);
437     buffer = HeapAlloc(GetProcessHeap(), 0, size);
438     memset(buffer, 0xcc, size);
439     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
440     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
441     todo_wine
442     ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
443
444     check_safearray(buffer, lpsa);
445
446     lpsa2 = NULL;
447     if (LPSAFEARRAY_UNMARSHAL_WORKS)
448     {
449         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
450         next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
451         todo_wine
452         ok(next - buffer == expected, "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
453         ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
454     }
455
456     for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
457     {
458         BSTR gotvalue = NULL;
459
460         if (lpsa2)
461         {
462             indices[0] = i + sab[0].lLbound;
463             hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
464             ok(hr == S_OK, "Failed to get bstr element at hres 0x%x\n", hr);
465             if (hr == S_OK)
466             {
467                 ok(VarBstrCmp(values[i], gotvalue, 0, 0) == VARCMP_EQ, "String %d does not match\n", i);
468                 SysFreeString(gotvalue);
469             }
470         }
471
472         SysFreeString(values[i]);
473     }
474
475     if (LPSAFEARRAY_UNMARSHAL_WORKS)
476     {
477         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
478         LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
479     }
480
481     HeapFree(GetProcessHeap(), 0, buffer);
482     SafeArrayDestroy(lpsa);
483
484     /* VARTYPE-less arrays with FADF_VARIANT */
485     hr = SafeArrayAllocDescriptor(1, &lpsa);
486     ok(hr == S_OK, "saad failed %08x\n", hr);
487     lpsa->cbElements = sizeof(VARIANT);
488     lpsa->fFeatures = FADF_VARIANT;
489     lpsa->rgsabound[0].lLbound = 2;
490     lpsa->rgsabound[0].cElements = 48;
491     hr = SafeArrayAllocData(lpsa);
492     ok(hr == S_OK, "saad failed %08x\n", hr);
493
494     hr = SafeArrayGetVartype(lpsa, &vt);
495     ok(hr == E_INVALIDARG, "ret %08x\n", hr);
496
497     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
498     size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
499     expected = 44 + 28 * lpsa->rgsabound[0].cElements;
500     todo_wine
501     ok(size == expected || size == expected + 8,  /* win64 */
502        "size should be %u bytes, not %u\n", expected, size);
503     buffer = HeapAlloc(GetProcessHeap(), 0, size);
504     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
505     next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
506     todo_wine
507     ok(next - buffer == expected || broken(next - buffer + sizeof(DWORD) == expected),
508             "Marshaled %u bytes, expected %u\n", (ULONG) (next - buffer), expected);
509     lpsa->cbElements = 16;  /* VARIANT wire size */
510     check_safearray(buffer, lpsa);
511     HeapFree(GetProcessHeap(), 0, buffer);
512     SafeArrayDestroyData(lpsa);
513     SafeArrayDestroyDescriptor(lpsa);
514 }
515
516 static void check_bstr(void *buffer, BSTR b)
517 {
518     DWORD *wireb = buffer;
519     DWORD len = SysStringByteLen(b);
520
521     ok(*wireb == (len + 1) / 2, "wv[0] %08x\n", *wireb);
522     wireb++;
523     if(b)
524         ok(*wireb == len, "wv[1] %08x\n", *wireb);
525     else
526         ok(*wireb == 0xffffffff, "wv[1] %08x\n", *wireb);
527     wireb++;
528     ok(*wireb == (len + 1) / 2, "wv[2] %08x\n", *wireb);
529     if(len)
530     {
531         wireb++;
532         ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
533     }
534     return;
535 }
536
537 static void test_marshal_BSTR(void)
538 {
539     ULONG size;
540     RPC_MESSAGE rpc_msg;
541     MIDL_STUB_MESSAGE stub_msg;
542     USER_MARSHAL_CB umcb;
543     unsigned char *buffer, *next;
544     BSTR b, b2;
545     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
546     DWORD len;
547
548     b = SysAllocString(str);
549     len = SysStringLen(b);
550     ok(len == 13, "get %d\n", len);
551
552     /* BSTRs are DWORD aligned */
553
554     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
555     size = BSTR_UserSize(&umcb.Flags, 1, &b);
556     ok(size == 42, "size %d\n", size);
557
558     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
559     size = BSTR_UserSize(&umcb.Flags, 0, &b);
560     ok(size == 38, "size %d\n", size);
561
562     buffer = HeapAlloc(GetProcessHeap(), 0, size);
563     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
564     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
565     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
566     check_bstr(buffer, b);
567
568     if (BSTR_UNMARSHAL_WORKS)
569     {
570         b2 = NULL;
571         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
572         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
573         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
574         ok(b2 != NULL, "BSTR didn't unmarshal\n");
575         ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
576         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
577         BSTR_UserFree(&umcb.Flags, &b2);
578     }
579
580     HeapFree(GetProcessHeap(), 0, buffer);
581     SysFreeString(b);
582
583     b = NULL;
584     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
585     size = BSTR_UserSize(&umcb.Flags, 0, &b);
586     ok(size == 12, "size %d\n", size);
587
588     buffer = HeapAlloc(GetProcessHeap(), 0, size);
589     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
590     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
591     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
592
593     check_bstr(buffer, b);
594     if (BSTR_UNMARSHAL_WORKS)
595     {
596         b2 = NULL;
597         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
598         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
599         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
600         ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
601         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
602         BSTR_UserFree(&umcb.Flags, &b2);
603     }
604     HeapFree(GetProcessHeap(), 0, buffer);
605
606     b = SysAllocStringByteLen("abc", 3);
607     *(((char*)b) + 3) = 'd';
608     len = SysStringLen(b);
609     ok(len == 1, "get %d\n", len);
610     len = SysStringByteLen(b);
611     ok(len == 3, "get %d\n", len);
612
613     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
614     size = BSTR_UserSize(&umcb.Flags, 0, &b);
615     ok(size == 16, "size %d\n", size);
616
617     buffer = HeapAlloc(GetProcessHeap(), 0, size);
618     memset(buffer, 0xcc, size);
619     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
620     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
621     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
622     check_bstr(buffer, b);
623     ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
624
625     if (BSTR_UNMARSHAL_WORKS)
626     {
627         b2 = NULL;
628         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
629         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
630         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
631         ok(b2 != NULL, "BSTR didn't unmarshal\n");
632         ok(!memcmp(b, b2, len), "strings differ\n");
633         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
634         BSTR_UserFree(&umcb.Flags, &b2);
635     }
636     HeapFree(GetProcessHeap(), 0, buffer);
637     SysFreeString(b);
638
639     b = SysAllocStringByteLen("", 0);
640     len = SysStringLen(b);
641     ok(len == 0, "get %d\n", len);
642     len = SysStringByteLen(b);
643     ok(len == 0, "get %d\n", len);
644
645     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
646     size = BSTR_UserSize(&umcb.Flags, 0, &b);
647     ok(size == 12, "size %d\n", size);
648
649     buffer = HeapAlloc(GetProcessHeap(), 0, size);
650     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
651     next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
652     ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
653     check_bstr(buffer, b);
654
655     if (BSTR_UNMARSHAL_WORKS)
656     {
657         b2 = NULL;
658         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
659         next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
660         ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
661         ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
662         len = SysStringByteLen(b2);
663         ok(len == 0, "byte len %d\n", len);
664         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
665         BSTR_UserFree(&umcb.Flags, &b2);
666     }
667     HeapFree(GetProcessHeap(), 0, buffer);
668     SysFreeString(b);
669 }
670
671 typedef struct
672 {
673     IUnknown IUnknown_iface;
674     ULONG refs;
675 } HeapUnknown;
676
677 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
678 {
679     return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
680 }
681
682 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
683 {
684     if (IsEqualIID(riid, &IID_IUnknown))
685     {
686         IUnknown_AddRef(iface);
687         *ppv = iface;
688         return S_OK;
689     }
690     *ppv = NULL;
691     return E_NOINTERFACE;
692 }
693
694 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
695 {
696     HeapUnknown *This = impl_from_IUnknown(iface);
697     return InterlockedIncrement((LONG*)&This->refs);
698 }
699
700 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
701 {
702     HeapUnknown *This = impl_from_IUnknown(iface);
703     ULONG refs = InterlockedDecrement((LONG*)&This->refs);
704     if (!refs) HeapFree(GetProcessHeap(), 0, This);
705     return refs;
706 }
707
708 static const IUnknownVtbl HeapUnknown_Vtbl =
709 {
710     HeapUnknown_QueryInterface,
711     HeapUnknown_AddRef,
712     HeapUnknown_Release
713 };
714
715 static void check_variant_header(DWORD *wirev, VARIANT *v, ULONG size)
716 {
717     WORD *wp;
718     DWORD switch_is;
719
720     ok(*wirev == (size + 7) >> 3, "wv[0] %08x, expected %08x\n", *wirev, (size + 7) >> 3);
721     wirev++;
722     ok(*wirev == 0, "wv[1] %08x\n", *wirev);
723     wirev++;
724     wp = (WORD*)wirev;
725     ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
726     wp++;
727     ok(*wp == V_U2(v).wReserved1, "res1 %04x expected %04x\n", *wp, V_U2(v).wReserved1);
728     wp++;
729     ok(*wp == V_U2(v).wReserved2, "res2 %04x expected %04x\n", *wp, V_U2(v).wReserved2);
730     wp++;
731     ok(*wp == V_U2(v).wReserved3, "res3 %04x expected %04x\n", *wp, V_U2(v).wReserved3);
732     wp++;
733     wirev = (DWORD*)wp;
734     switch_is = V_VT(v);
735     if(switch_is & VT_ARRAY)
736         switch_is &= ~VT_TYPEMASK;
737     ok(*wirev == switch_is, "switch_is %08x expected %08x\n", *wirev, switch_is);
738 }
739
740 /* Win9x and WinME don't always align as needed. Variants have
741  * an alignment of 8.
742  */
743 static void *alloc_aligned(SIZE_T size, void **buf)
744 {
745     *buf = HeapAlloc(GetProcessHeap(), 0, size + 7);
746     return (void *)(((UINT_PTR)*buf + 7) & ~7);
747 }
748
749 static void test_marshal_VARIANT(void)
750 {
751     VARIANT v, v2;
752     MIDL_STUB_MESSAGE stubMsg = { 0 };
753     RPC_MESSAGE rpcMsg = { 0 };
754     USER_MARSHAL_CB umcb = { 0 };
755     unsigned char *buffer, *next;
756     void *oldbuffer;
757     ULONG ul;
758     short s;
759     double d;
760     DWORD *wirev;
761     BSTR b;
762     WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
763     SAFEARRAYBOUND sab;
764     LPSAFEARRAY lpsa;
765     DECIMAL dec, dec2;
766     HeapUnknown *heap_unknown;
767     DWORD expected;
768
769     stubMsg.RpcMsg = &rpcMsg;
770
771     umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
772     umcb.pStubMsg = &stubMsg;
773     umcb.pReserve = NULL;
774     umcb.Signature = USER_MARSHAL_CB_SIGNATURE;
775     umcb.CBType = USER_MARSHAL_CB_UNMARSHALL;
776
777     /*** I1 ***/
778     VariantInit(&v);
779     V_VT(&v) = VT_I1;
780     V_I1(&v) = 0x12;
781
782     /* check_variant_header tests wReserved[123], so initialize to unique values.
783      * (Could probably also do this by setting the variant to a known DECIMAL.)
784      */
785     V_U2(&v).wReserved1 = 0x1234;
786     V_U2(&v).wReserved2 = 0x5678;
787     V_U2(&v).wReserved3 = 0x9abc;
788
789     /* Variants have an alignment of 8 */
790     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v);
791     ok(stubMsg.BufferLength == 29, "size %d\n", stubMsg.BufferLength);
792
793     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
794     ok(stubMsg.BufferLength == 21, "size %d\n", stubMsg.BufferLength);
795
796     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
797     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
798     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
799     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
800     wirev = (DWORD*)buffer;
801     
802     check_variant_header(wirev, &v, stubMsg.BufferLength);
803     wirev += 5;
804     ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev);
805     if (VARIANT_UNMARSHAL_WORKS)
806     {
807         VariantInit(&v2);
808         stubMsg.Buffer = buffer;
809         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
810         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
811         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
812         ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
813
814         VARIANT_UserFree(&umcb.Flags, &v2);
815     }
816     HeapFree(GetProcessHeap(), 0, oldbuffer);
817
818     /*** I2 ***/
819     VariantInit(&v);
820     V_VT(&v) = VT_I2;
821     V_I2(&v) = 0x1234;
822
823     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
824     ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
825
826     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
827     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
828     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
829     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
830     wirev = (DWORD*)buffer;
831
832     check_variant_header(wirev, &v, stubMsg.BufferLength);
833     wirev += 5;
834     ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev);
835     if (VARIANT_UNMARSHAL_WORKS)
836     {
837         VariantInit(&v2);
838         stubMsg.Buffer = buffer;
839         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
840         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
841         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
842         ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
843
844         VARIANT_UserFree(&umcb.Flags, &v2);
845     }
846     HeapFree(GetProcessHeap(), 0, oldbuffer);
847
848     /*** I2 BYREF ***/
849     VariantInit(&v);
850     V_VT(&v) = VT_I2 | VT_BYREF;
851     s = 0x1234;
852     V_I2REF(&v) = &s;
853
854     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
855     ok(stubMsg.BufferLength == 26, "size %d\n", stubMsg.BufferLength);
856
857     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
858     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
859     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
860     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
861     wirev = (DWORD*)buffer;
862
863     check_variant_header(wirev, &v, stubMsg.BufferLength);
864     wirev += 5;
865     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
866     wirev++;
867     ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
868     if (VARIANT_UNMARSHAL_WORKS)
869     {
870         void *mem;
871         VariantInit(&v2);
872         V_VT(&v2) = VT_I2 | VT_BYREF;
873         V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2)));
874         stubMsg.Buffer = buffer;
875         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
876         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
877         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
878         ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n");
879         ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
880
881         VARIANT_UserFree(&umcb.Flags, &v2);
882     }
883     HeapFree(GetProcessHeap(), 0, oldbuffer);
884
885     /*** I4 ***/
886     VariantInit(&v);
887     V_VT(&v) = VT_I4;
888     V_I4(&v) = 0x1234;
889
890     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
891     ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
892
893     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
894     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
895     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
896     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
897     wirev = (DWORD*)buffer;
898     
899     check_variant_header(wirev, &v, stubMsg.BufferLength);
900     wirev += 5;
901     ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev);
902
903     if (VARIANT_UNMARSHAL_WORKS)
904     {
905         VariantInit(&v2);
906         stubMsg.Buffer = buffer;
907         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
908         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
909         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
910         ok(V_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2));
911
912         VARIANT_UserFree(&umcb.Flags, &v2);
913     }
914     HeapFree(GetProcessHeap(), 0, oldbuffer);
915
916     /*** UI4 ***/
917     VariantInit(&v);
918     V_VT(&v) = VT_UI4;
919     V_UI4(&v) = 0x1234;
920
921     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
922     ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
923
924     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
925     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
926     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
927     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
928     wirev = (DWORD*)buffer;
929     
930     check_variant_header(wirev, &v, stubMsg.BufferLength);
931     wirev += 5;
932     ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev);
933     if (VARIANT_UNMARSHAL_WORKS)
934     {
935         VariantInit(&v2);
936         stubMsg.Buffer = buffer;
937         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
938         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
939         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
940         ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2));
941
942         VARIANT_UserFree(&umcb.Flags, &v2);
943     }
944     HeapFree(GetProcessHeap(), 0, oldbuffer);
945
946     /*** UI4 BYREF ***/
947     VariantInit(&v);
948     V_VT(&v) = VT_UI4 | VT_BYREF;
949     ul = 0x1234;
950     V_UI4REF(&v) = &ul;
951
952     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
953     ok(stubMsg.BufferLength == 28, "size %d\n", stubMsg.BufferLength);
954
955     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
956     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
957     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
958     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
959     wirev = (DWORD*)buffer;
960     
961     check_variant_header(wirev, &v, stubMsg.BufferLength);
962     wirev += 5;
963     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
964     wirev++;
965     ok(*wirev == ul, "wv[6] %08x\n", *wirev);
966
967     if (VARIANT_UNMARSHAL_WORKS)
968     {
969         VariantInit(&v2);
970         stubMsg.Buffer = buffer;
971         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
972         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
973         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
974         ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2));
975
976         VARIANT_UserFree(&umcb.Flags, &v2);
977     }
978     HeapFree(GetProcessHeap(), 0, oldbuffer);
979
980     /*** R4 ***/
981     VariantInit(&v);
982     V_VT(&v) = VT_R4;
983     V_R8(&v) = 3.1415;
984
985     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
986     ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
987
988     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
989     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
990     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
991     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
992     wirev = (DWORD*)buffer;
993      
994     check_variant_header(wirev, &v, stubMsg.BufferLength);
995     wirev += 5;
996     ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev);
997     if (VARIANT_UNMARSHAL_WORKS)
998     {
999         VariantInit(&v2);
1000         stubMsg.Buffer = buffer;
1001         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1002         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1003         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1004         ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
1005
1006         VARIANT_UserFree(&umcb.Flags, &v2);
1007     }
1008     HeapFree(GetProcessHeap(), 0, oldbuffer);
1009
1010     /*** R8 ***/
1011     VariantInit(&v);
1012     V_VT(&v) = VT_R8;
1013     V_R8(&v) = 3.1415;
1014
1015     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1016     ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1017
1018     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1019     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1020     memset(buffer, 0xcc, stubMsg.BufferLength);
1021     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1022     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1023     wirev = (DWORD*)buffer;
1024     
1025     check_variant_header(wirev, &v, stubMsg.BufferLength);
1026     wirev += 5;
1027     ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
1028     wirev++;
1029     ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1));
1030     if (VARIANT_UNMARSHAL_WORKS)
1031     {
1032         VariantInit(&v2);
1033         stubMsg.Buffer = buffer;
1034         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1035         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1036         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1037         ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
1038
1039         VARIANT_UserFree(&umcb.Flags, &v2);
1040     }
1041     HeapFree(GetProcessHeap(), 0, oldbuffer);
1042
1043     /*** R8 BYREF ***/
1044     VariantInit(&v);
1045     V_VT(&v) = VT_R8 | VT_BYREF;
1046     d = 3.1415;
1047     V_R8REF(&v) = &d;
1048
1049     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1050     ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
1051
1052     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1053     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1054     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1055     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1056     wirev = (DWORD*)buffer;
1057     
1058     check_variant_header(wirev, &v, stubMsg.BufferLength);
1059     wirev += 5;
1060     ok(*wirev == 8, "wv[5] %08x\n", *wirev);
1061     wirev++;
1062     ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1063     if (VARIANT_UNMARSHAL_WORKS)
1064     {
1065         VariantInit(&v2);
1066         stubMsg.Buffer = buffer;
1067         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1068         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1069         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1070         ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
1071
1072         VARIANT_UserFree(&umcb.Flags, &v2);
1073     }
1074     HeapFree(GetProcessHeap(), 0, oldbuffer);
1075
1076     /*** VARIANT_BOOL ***/
1077     VariantInit(&v);
1078     V_VT(&v) = VT_BOOL;
1079     V_BOOL(&v) = 0x1234;
1080
1081     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1082     ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
1083
1084     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1085     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1086     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1087     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1088     wirev = (DWORD*)buffer;
1089     
1090     check_variant_header(wirev, &v, stubMsg.BufferLength);
1091     wirev += 5;
1092     ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
1093     if (VARIANT_UNMARSHAL_WORKS)
1094     {
1095         VariantInit(&v2);
1096         stubMsg.Buffer = buffer;
1097         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1098         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1099         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1100         ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
1101
1102         VARIANT_UserFree(&umcb.Flags, &v2);
1103     }
1104     HeapFree(GetProcessHeap(), 0, oldbuffer);
1105
1106     /*** DECIMAL ***/
1107     VarDecFromI4(0x12345678, &dec);
1108     dec.wReserved = 0xfedc;          /* Also initialize reserved field, as we check it later */
1109     VariantInit(&v);
1110     V_DECIMAL(&v) = dec;
1111     V_VT(&v) = VT_DECIMAL;
1112
1113     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1114     ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1115
1116     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1117     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1118     memset(buffer, 0xcc, stubMsg.BufferLength);
1119     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1120     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1121     wirev = (DWORD*)buffer;
1122
1123     check_variant_header(wirev, &v, stubMsg.BufferLength);
1124     wirev += 5;
1125     ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */
1126     wirev++;
1127     dec2 = dec;
1128     dec2.wReserved = VT_DECIMAL;
1129     ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n",
1130        *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
1131     if (VARIANT_UNMARSHAL_WORKS)
1132     {
1133         VariantInit(&v2);
1134         stubMsg.Buffer = buffer;
1135         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1136         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1137         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1138         ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
1139
1140         VARIANT_UserFree(&umcb.Flags, &v2);
1141     }
1142     HeapFree(GetProcessHeap(), 0, oldbuffer);
1143
1144     /*** DECIMAL BYREF ***/
1145     VariantInit(&v);
1146     V_VT(&v) = VT_DECIMAL | VT_BYREF;
1147     V_DECIMALREF(&v) = &dec;
1148
1149     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1150     ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
1151
1152     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1153     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1154     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1155     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1156     wirev = (DWORD*)buffer;
1157     
1158     check_variant_header(wirev, &v, stubMsg.BufferLength);
1159     wirev += 5;
1160     ok(*wirev == 16, "wv[5] %08x\n", *wirev);
1161     wirev++;
1162     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));
1163     if (VARIANT_UNMARSHAL_WORKS)
1164     {
1165         VariantInit(&v2);
1166         /* check_variant_header tests wReserved[123], so initialize to unique values.
1167          * (Could probably also do this by setting the variant to a known DECIMAL.)
1168          */
1169         V_U2(&v2).wReserved1 = 0x0123;
1170         V_U2(&v2).wReserved2 = 0x4567;
1171         V_U2(&v2).wReserved3 = 0x89ab;
1172
1173         stubMsg.Buffer = buffer;
1174         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1175         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1176         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1177         ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
1178
1179         VARIANT_UserFree(&umcb.Flags, &v2);
1180     }
1181     HeapFree(GetProcessHeap(), 0, oldbuffer);
1182
1183     /*** EMPTY ***/
1184     VariantInit(&v);
1185     V_VT(&v) = VT_EMPTY;
1186
1187     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1188     ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1189
1190     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1191     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1192     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1193     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1194     wirev = (DWORD*)buffer;
1195
1196     check_variant_header(wirev, &v, stubMsg.BufferLength);
1197     if (VARIANT_UNMARSHAL_WORKS)
1198     {
1199         VariantInit(&v2);
1200         stubMsg.Buffer = buffer;
1201         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1202         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1203         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1204
1205         VARIANT_UserFree(&umcb.Flags, &v2);
1206     }
1207     HeapFree(GetProcessHeap(), 0, oldbuffer);
1208
1209     /*** NULL ***/
1210     VariantInit(&v);
1211     V_VT(&v) = VT_NULL;
1212
1213     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1214     ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1215
1216     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1217     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1218     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1219     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1220     wirev = (DWORD*)buffer;
1221
1222     check_variant_header(wirev, &v, stubMsg.BufferLength);
1223     if (VARIANT_UNMARSHAL_WORKS)
1224     {
1225         VariantInit(&v2);
1226         stubMsg.Buffer = buffer;
1227         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1228         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1229         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1230
1231         VARIANT_UserFree(&umcb.Flags, &v2);
1232     }
1233     HeapFree(GetProcessHeap(), 0, oldbuffer);
1234
1235     /*** BSTR ***/
1236     b = SysAllocString(str);
1237     VariantInit(&v);
1238     V_VT(&v) = VT_BSTR;
1239     V_BSTR(&v) = b;
1240
1241     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1242     ok(stubMsg.BufferLength == 60, "size %d\n", stubMsg.BufferLength);
1243     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1244     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1245     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1246     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1247     wirev = (DWORD*)buffer;
1248     
1249     check_variant_header(wirev, &v, stubMsg.BufferLength);
1250     wirev += 5;
1251     ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1252     wirev++;
1253     check_bstr(wirev, V_BSTR(&v));
1254     if (VARIANT_UNMARSHAL_WORKS)
1255     {
1256         VariantInit(&v2);
1257         stubMsg.Buffer = buffer;
1258         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1259         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1260         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1261         ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
1262         ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
1263
1264         VARIANT_UserFree(&umcb.Flags, &v2);
1265     }
1266     HeapFree(GetProcessHeap(), 0, oldbuffer);
1267
1268     /*** BSTR BYREF ***/
1269     VariantInit(&v);
1270     V_VT(&v) = VT_BSTR | VT_BYREF;
1271     V_BSTRREF(&v) = &b;
1272
1273     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1274     ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1275     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1276     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1277     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1278     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1279     wirev = (DWORD*)buffer;
1280     
1281     check_variant_header(wirev, &v, stubMsg.BufferLength);
1282     wirev += 5;
1283     ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1284     wirev++;
1285     ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1286     wirev++;
1287     check_bstr(wirev, b);
1288     if (VARIANT_UNMARSHAL_WORKS)
1289     {
1290         VariantInit(&v2);
1291         stubMsg.Buffer = buffer;
1292         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1293         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1294         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1295         ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
1296         ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
1297
1298         VARIANT_UserFree(&umcb.Flags, &v2);
1299     }
1300     HeapFree(GetProcessHeap(), 0, oldbuffer);
1301     SysFreeString(b);
1302
1303     /*** ARRAY ***/
1304     sab.lLbound = 5;
1305     sab.cElements = 10;
1306
1307     lpsa = SafeArrayCreate(VT_R8, 1, &sab);
1308     *(DWORD *)lpsa->pvData = 0xcafebabe;
1309     *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
1310
1311     VariantInit(&v);
1312     V_VT(&v) = VT_UI4 | VT_ARRAY;
1313     V_ARRAY(&v) = lpsa;
1314
1315     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1316     expected = 152;
1317     ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 8, /* win64 */
1318        "size %u instead of %u\n", stubMsg.BufferLength, expected);
1319     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1320     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1321     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1322     ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1323     wirev = (DWORD*)buffer;
1324     
1325     check_variant_header(wirev, &v, expected);
1326     wirev += 5;
1327     ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1328     wirev++;
1329     check_safearray(wirev, lpsa);
1330     if (VARIANT_UNMARSHAL_WORKS)
1331     {
1332         LONG bound, bound2;
1333         VARTYPE vt, vt2;
1334         VariantInit(&v2);
1335         stubMsg.Buffer = buffer;
1336         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1337         ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1338         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1339         ok(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");  
1340         SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
1341         SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
1342         ok(bound == bound2, "array lbounds differ\n");
1343         SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
1344         SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
1345         ok(bound == bound2, "array ubounds differ\n");
1346         SafeArrayGetVartype(V_ARRAY(&v), &vt);
1347         SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
1348         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1349         VARIANT_UserFree(&umcb.Flags, &v2);
1350     }
1351     HeapFree(GetProcessHeap(), 0, oldbuffer);
1352
1353     /*** ARRAY BYREF ***/
1354     VariantInit(&v);
1355     V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1356     V_ARRAYREF(&v) = &lpsa;
1357
1358     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1359     expected = 152;
1360     ok(stubMsg.BufferLength == expected || stubMsg.BufferLength == expected + 16, /* win64 */
1361        "size %u instead of %u\n", stubMsg.BufferLength, expected);
1362     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1363     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1364     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1365     ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1366     wirev = (DWORD*)buffer;
1367
1368     check_variant_header(wirev, &v, expected);
1369     wirev += 5;
1370     ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1371     wirev++;
1372     ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1373     wirev++;
1374     check_safearray(wirev, lpsa);
1375     if (VARIANT_UNMARSHAL_WORKS)
1376     {
1377         LONG bound, bound2;
1378         VARTYPE vt, vt2;
1379         VariantInit(&v2);
1380         stubMsg.Buffer = buffer;
1381         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1382         ok(next == buffer + expected, "got %p expect %p\n", next, buffer + expected);
1383         ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1384         ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");  
1385         SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1386         SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1387         ok(bound == bound2, "array lbounds differ\n");
1388         SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1389         SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1390         ok(bound == bound2, "array ubounds differ\n");
1391         SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1392         SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1393         ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1394         VARIANT_UserFree(&umcb.Flags, &v2);
1395     }
1396     HeapFree(GetProcessHeap(), 0, oldbuffer);
1397     SafeArrayDestroy(lpsa);
1398
1399     /*** VARIANT BYREF ***/
1400     VariantInit(&v);
1401     VariantInit(&v2);
1402     V_VT(&v2) = VT_R8;
1403     V_R8(&v2) = 3.1415;
1404     V_VT(&v) = VT_VARIANT | VT_BYREF;
1405     V_VARIANTREF(&v) = &v2;
1406
1407     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1408     ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1409     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1410     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1411     memset(buffer, 0xcc, stubMsg.BufferLength);
1412     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1413     ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1414     wirev = (DWORD*)buffer;
1415     check_variant_header(wirev, &v, stubMsg.BufferLength);
1416     wirev += 5;
1417
1418     ok(*wirev == sizeof(VARIANT), "wv[5] %08x\n", *wirev);
1419     wirev++;
1420     ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */
1421     wirev++;
1422     ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */
1423     wirev++;
1424     check_variant_header(wirev, &v2, stubMsg.BufferLength - 32);
1425     wirev += 5;
1426     ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */
1427     wirev++;
1428     ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1429     if (VARIANT_UNMARSHAL_WORKS)
1430     {
1431         VARIANT v3;
1432         VariantInit(&v3);
1433         stubMsg.Buffer = buffer;
1434         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1435         ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1436         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1437         ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1438            V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3))); 
1439         ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n"); 
1440         VARIANT_UserFree(&umcb.Flags, &v3);
1441     }
1442     HeapFree(GetProcessHeap(), 0, oldbuffer);
1443
1444     /*** UNKNOWN ***/
1445     heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1446     heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1447     heap_unknown->refs = 1;
1448     VariantInit(&v);
1449     VariantInit(&v2);
1450     V_VT(&v) = VT_UNKNOWN;
1451     V_UNKNOWN(&v) = &heap_unknown->IUnknown_iface;
1452
1453     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1454     ok(stubMsg.BufferLength > 32, "size %d\n", stubMsg.BufferLength);
1455     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1456     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1457     memset(buffer, 0xcc, stubMsg.BufferLength);
1458     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1459     wirev = (DWORD*)buffer;
1460     check_variant_header(wirev, &v, next - buffer);
1461     wirev += 5;
1462
1463     todo_wine
1464     ok(*wirev == (DWORD_PTR)V_UNKNOWN(&v) /* Win9x */ ||
1465        *wirev == (DWORD_PTR)V_UNKNOWN(&v) + 1 /* NT */, "wv[5] %08x\n", *wirev);
1466     wirev++;
1467     todo_wine
1468     ok(*wirev == next - buffer - 0x20, "wv[6] %08x\n", *wirev);
1469     wirev++;
1470     todo_wine
1471     ok(*wirev == next - buffer - 0x20, "wv[7] %08x\n", *wirev);
1472     wirev++;
1473     todo_wine
1474     ok(*wirev == 0x574f454d, "wv[8] %08x\n", *wirev);
1475     if (VARIANT_UNMARSHAL_WORKS)
1476     {
1477         VARIANT v3;
1478         VariantInit(&v3);
1479         V_VT(&v3) = VT_UNKNOWN;
1480         V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface;
1481         IUnknown_AddRef(V_UNKNOWN(&v3));
1482         stubMsg.Buffer = buffer;
1483         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1484         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1485         ok(V_UNKNOWN(&v) == V_UNKNOWN(&v3), "got %p expect %p\n", V_UNKNOWN(&v), V_UNKNOWN(&v3));
1486         VARIANT_UserFree(&umcb.Flags, &v3);
1487         ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1488         IUnknown_Release(&heap_unknown->IUnknown_iface);
1489     }
1490     HeapFree(GetProcessHeap(), 0, oldbuffer);
1491
1492     /*** NULL UNKNOWN ***/
1493     VariantInit(&v);
1494     V_VT(&v) = VT_UNKNOWN;
1495     V_UNKNOWN(&v) = NULL;
1496
1497     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1498     ok(stubMsg.BufferLength >= 24, "size %d\n", stubMsg.BufferLength);
1499     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1500     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1501     memset(buffer, 0xcc, stubMsg.BufferLength);
1502     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1503     wirev = (DWORD*)buffer;
1504     check_variant_header(wirev, &v, next - buffer);
1505     wirev += 5;
1506     ok(*wirev == 0, "wv[5] %08x\n", *wirev);
1507
1508     VariantInit(&v2);
1509     stubMsg.Buffer = buffer;
1510     next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1511     ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1512     ok(V_UNKNOWN(&v2) == NULL, "got %p expect NULL\n", V_UNKNOWN(&v2));
1513     VARIANT_UserFree(&umcb.Flags, &v2);
1514     HeapFree(GetProcessHeap(), 0, oldbuffer);
1515
1516     /*** UNKNOWN BYREF ***/
1517     heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1518     heap_unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1519     heap_unknown->refs = 1;
1520     VariantInit(&v);
1521     VariantInit(&v2);
1522     V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1523     V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
1524
1525     rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1526     ok(stubMsg.BufferLength > 36, "size %d\n", stubMsg.BufferLength);
1527     buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer);
1528     stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1529     memset(buffer, 0xcc, stubMsg.BufferLength);
1530     next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1531     wirev = (DWORD*)buffer;
1532     check_variant_header(wirev, &v, next - buffer);
1533     wirev += 5;
1534
1535     ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1536     wirev++;
1537     todo_wine
1538     ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ ||
1539        *wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev);
1540     wirev++;
1541     todo_wine
1542     ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev);
1543     wirev++;
1544     todo_wine
1545     ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev);
1546     wirev++;
1547     todo_wine
1548     ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev);
1549     if (VARIANT_UNMARSHAL_WORKS)
1550     {
1551         VARIANT v3;
1552         VariantInit(&v3);
1553         V_VT(&v3) = VT_UNKNOWN;
1554         V_UNKNOWN(&v3) = &heap_unknown->IUnknown_iface;
1555         IUnknown_AddRef(V_UNKNOWN(&v3));
1556         stubMsg.Buffer = buffer;
1557         next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1558         ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1559         ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
1560         VARIANT_UserFree(&umcb.Flags, &v3);
1561         ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1562         IUnknown_Release(&heap_unknown->IUnknown_iface);
1563     }
1564     HeapFree(GetProcessHeap(), 0, oldbuffer);
1565 }
1566
1567
1568 START_TEST(usrmarshal)
1569 {
1570     CoInitialize(NULL);
1571
1572     test_marshal_LPSAFEARRAY();
1573     test_marshal_BSTR();
1574     test_marshal_VARIANT();
1575
1576     CoUninitialize();
1577 }