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