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