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