push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / dlls / oleaut32 / tests / usrmarshal.c
blob38827b1dcd97cba08ecece0a9bc6a542edfcde43
1 /*
2 * Marshaling Tests
4 * Copyright 2004 Robert Shearman
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.
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.
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
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "propidl.h" /* for LPSAFEARRAY_User* routines */
30 #include "wine/test.h"
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
38 #define LPSAFEARRAY_UNMARSHAL_WORKS 1
39 #define BSTR_UNMARSHAL_WORKS 1
40 #define VARIANT_UNMARSHAL_WORKS 1
42 static inline SF_TYPE get_union_type(SAFEARRAY *psa)
44 VARTYPE vt;
45 HRESULT hr;
47 hr = SafeArrayGetVartype(psa, &vt);
48 if (FAILED(hr))
50 if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
52 switch(psa->cbElements)
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;
62 if (psa->fFeatures & FADF_HAVEIID)
63 return SF_HAVEIID;
65 switch (vt)
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().
91 case VT_RECORD: return SF_RECORD;
92 default: return SF_ERROR;
96 static ULONG get_cell_count(const SAFEARRAY *psa)
98 const SAFEARRAYBOUND* psab = psa->rgsabound;
99 USHORT cCount = psa->cDims;
100 ULONG ulNumCells = 1;
102 while (cCount--)
104 if (!psab->cElements)
105 return 0;
106 ulNumCells *= psab->cElements;
107 psab++;
109 return ulNumCells;
112 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
114 unsigned char *wiresa = buffer;
115 VARTYPE vt;
116 SF_TYPE sftype;
117 ULONG cell_count;
119 if(!lpsa)
121 ok(*(void **)wiresa == NULL, "wiresa + 0x0 should be NULL instead of 0x%08x\n", *(DWORD *)wiresa);
122 return;
125 if(FAILED(SafeArrayGetVartype(lpsa, &vt)))
126 vt = 0;
128 sftype = get_union_type(lpsa);
129 cell_count = get_cell_count(lpsa);
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 + 0xc should be lpsa->fFeatures instead of 0x%08x\n", *(WORD *)wiresa);
138 wiresa += sizeof(WORD);
139 ok(*(DWORD *)wiresa == lpsa->cbElements, "wiresa + 0x10 should be lpsa->cbElements instead of 0x%08x\n", *(DWORD *)wiresa);
140 wiresa += sizeof(DWORD);
141 ok(*(WORD *)wiresa == lpsa->cLocks, "wiresa + 0x16 should be lpsa->cLocks instead of 0x%04x\n", *(WORD *)wiresa);
142 wiresa += sizeof(WORD);
143 ok(*(WORD *)wiresa == vt, "wiresa + 0x14 should be %04x instead of 0x%04x\n", vt, *(WORD *)wiresa);
144 wiresa += sizeof(WORD);
145 ok(*(DWORD *)wiresa == sftype, "wiresa + 0x18 should be %08x instead of 0x%08x\n", (DWORD)sftype, *(DWORD *)wiresa);
146 wiresa += sizeof(DWORD);
147 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x1c should be %u instead of %u\n", cell_count, *(DWORD *)wiresa);
148 wiresa += sizeof(DWORD);
149 ok(*(DWORD *)wiresa, "wiresa + 0x20 should be non-zero instead of 0x%08x\n", *(DWORD *)wiresa);
150 wiresa += sizeof(DWORD);
151 if(sftype == SF_HAVEIID)
153 GUID guid;
154 SafeArrayGetIID(lpsa, &guid);
155 ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
156 wiresa += sizeof(GUID);
158 ok(!memcmp(wiresa, lpsa->rgsabound, sizeof(lpsa->rgsabound[0]) * lpsa->cDims), "bounds mismatch\n");
159 wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
161 ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x2c should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
162 wiresa += sizeof(DWORD);
163 /* elements are now pointed to by wiresa */
166 static void * WINAPI user_allocate(SIZE_T size)
168 return CoTaskMemAlloc(size);
171 static void WINAPI user_free(void *p)
173 CoTaskMemFree(p);
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)
181 memset(rpc_msg, 0, sizeof(*rpc_msg));
182 rpc_msg->Buffer = buffer;
183 rpc_msg->BufferLength = size;
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;
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;
198 static void test_marshal_LPSAFEARRAY(void)
200 unsigned char *buffer;
201 ULONG size;
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;
211 sab.lLbound = 5;
212 sab.cElements = 10;
214 lpsa = SafeArrayCreate(VT_I2, 1, &sab);
215 *(DWORD *)lpsa->pvData = 0xcafebabe;
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 ok(size == 68, "size should be 68 bytes, not %d\n", size);
221 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
222 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
223 ok(size == 64, "size should be 64 bytes, not %d\n", size);
224 buffer = HeapAlloc(GetProcessHeap(), 0, size);
225 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
226 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
228 check_safearray(buffer, lpsa);
230 if (LPSAFEARRAY_UNMARSHAL_WORKS)
232 VARTYPE vt, vt2;
233 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
234 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
235 ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
236 SafeArrayGetVartype(lpsa, &vt);
237 SafeArrayGetVartype(lpsa2, &vt2);
238 ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
239 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
240 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
242 HeapFree(GetProcessHeap(), 0, buffer);
243 lpsa->cLocks = 0;
244 SafeArrayDestroy(lpsa);
246 /* test NULL safe array */
247 lpsa = NULL;
249 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
250 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
251 ok(size == 4, "size should be 4 bytes, not %d\n", size);
252 buffer = HeapAlloc(GetProcessHeap(), 0, size);
253 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
254 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
255 check_safearray(buffer, lpsa);
257 if (LPSAFEARRAY_UNMARSHAL_WORKS)
259 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
260 LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
261 ok(lpsa2 == NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
262 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
263 LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
265 HeapFree(GetProcessHeap(), 0, buffer);
267 sab.lLbound = 5;
268 sab.cElements = 10;
270 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
271 *(double *)lpsa->pvData = 3.1415;
273 lpsa->cLocks = 7;
274 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
275 size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
276 ok(size == 128, "size should be 128 bytes, not %d\n", size);
277 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
278 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
279 ok(size == 128, "size should be 128 bytes, not %d\n", size);
280 buffer = HeapAlloc(GetProcessHeap(), 0, size);
281 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
282 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
284 check_safearray(buffer, lpsa);
286 HeapFree(GetProcessHeap(), 0, buffer);
287 lpsa->cLocks = 0;
288 SafeArrayDestroy(lpsa);
290 /* VARTYPE-less arrays can be marshaled if cbElements is 1,2,4 or 8 as type SF_In */
291 hr = SafeArrayAllocDescriptor(1, &lpsa);
292 ok(hr == S_OK, "saad failed %08x\n", hr);
293 lpsa->cbElements = 8;
294 lpsa->rgsabound[0].lLbound = 2;
295 lpsa->rgsabound[0].cElements = 48;
296 hr = SafeArrayAllocData(lpsa);
297 ok(hr == S_OK, "saad failed %08x\n", hr);
299 hr = SafeArrayGetVartype(lpsa, &vt);
300 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
302 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
303 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
304 ok(size == 432, "size %d\n", size);
305 buffer = HeapAlloc(GetProcessHeap(), 0, size);
306 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
307 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
308 check_safearray(buffer, lpsa);
309 HeapFree(GetProcessHeap(), 0, buffer);
310 SafeArrayDestroyData(lpsa);
311 SafeArrayDestroyDescriptor(lpsa);
313 /* VARTYPE-less arrays with FADF_VARIANT */
314 hr = SafeArrayAllocDescriptor(1, &lpsa);
315 ok(hr == S_OK, "saad failed %08x\n", hr);
316 lpsa->cbElements = 16;
317 lpsa->fFeatures = FADF_VARIANT;
318 lpsa->rgsabound[0].lLbound = 2;
319 lpsa->rgsabound[0].cElements = 48;
320 hr = SafeArrayAllocData(lpsa);
321 ok(hr == S_OK, "saad failed %08x\n", hr);
323 hr = SafeArrayGetVartype(lpsa, &vt);
324 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
326 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
327 size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
328 todo_wine
329 ok(size == 1388, "size %d\n", size);
330 buffer = HeapAlloc(GetProcessHeap(), 0, size);
331 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
332 LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
333 check_safearray(buffer, lpsa);
334 HeapFree(GetProcessHeap(), 0, buffer);
335 SafeArrayDestroyData(lpsa);
336 SafeArrayDestroyDescriptor(lpsa);
339 static void check_bstr(void *buffer, BSTR b)
341 DWORD *wireb = buffer;
342 DWORD len = SysStringByteLen(b);
344 ok(*wireb == (len + 1) / 2, "wv[0] %08x\n", *wireb);
345 wireb++;
346 if(b)
347 ok(*wireb == len, "wv[1] %08x\n", *wireb);
348 else
349 ok(*wireb == 0xffffffff, "wv[1] %08x\n", *wireb);
350 wireb++;
351 ok(*wireb == (len + 1) / 2, "wv[2] %08x\n", *wireb);
352 if(len)
354 wireb++;
355 ok(!memcmp(wireb, b, (len + 1) & ~1), "strings differ\n");
357 return;
360 static void test_marshal_BSTR(void)
362 ULONG size;
363 RPC_MESSAGE rpc_msg;
364 MIDL_STUB_MESSAGE stub_msg;
365 USER_MARSHAL_CB umcb;
366 unsigned char *buffer, *next;
367 BSTR b, b2;
368 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t','1',0};
369 DWORD len;
371 b = SysAllocString(str);
372 len = SysStringLen(b);
373 ok(len == 13, "get %d\n", len);
375 /* BSTRs are DWORD aligned */
377 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
378 size = BSTR_UserSize(&umcb.Flags, 1, &b);
379 ok(size == 42, "size %d\n", size);
381 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
382 size = BSTR_UserSize(&umcb.Flags, 0, &b);
383 ok(size == 38, "size %d\n", size);
385 buffer = HeapAlloc(GetProcessHeap(), 0, size);
386 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
387 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
388 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
389 check_bstr(buffer, b);
391 if (BSTR_UNMARSHAL_WORKS)
393 b2 = NULL;
394 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
395 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
396 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
397 ok(b2 != NULL, "BSTR didn't unmarshal\n");
398 ok(!memcmp(b, b2, (len + 1) * 2), "strings differ\n");
399 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
400 BSTR_UserFree(&umcb.Flags, &b2);
403 HeapFree(GetProcessHeap(), 0, buffer);
404 SysFreeString(b);
406 b = NULL;
407 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
408 size = BSTR_UserSize(&umcb.Flags, 0, &b);
409 ok(size == 12, "size %d\n", size);
411 buffer = HeapAlloc(GetProcessHeap(), 0, size);
412 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
413 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
414 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
416 check_bstr(buffer, b);
417 if (BSTR_UNMARSHAL_WORKS)
419 b2 = NULL;
420 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
421 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
422 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
423 ok(b2 == NULL, "NULL BSTR didn't unmarshal\n");
424 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
425 BSTR_UserFree(&umcb.Flags, &b2);
427 HeapFree(GetProcessHeap(), 0, buffer);
429 b = SysAllocStringByteLen("abc", 3);
430 *(((char*)b) + 3) = 'd';
431 len = SysStringLen(b);
432 ok(len == 1, "get %d\n", len);
433 len = SysStringByteLen(b);
434 ok(len == 3, "get %d\n", len);
436 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
437 size = BSTR_UserSize(&umcb.Flags, 0, &b);
438 ok(size == 16, "size %d\n", size);
440 buffer = HeapAlloc(GetProcessHeap(), 0, size);
441 memset(buffer, 0xcc, size);
442 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
443 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
444 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
445 check_bstr(buffer, b);
446 ok(buffer[15] == 'd', "buffer[15] %02x\n", buffer[15]);
448 if (BSTR_UNMARSHAL_WORKS)
450 b2 = NULL;
451 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
452 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
453 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
454 ok(b2 != NULL, "BSTR didn't unmarshal\n");
455 ok(!memcmp(b, b2, len), "strings differ\n");
456 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
457 BSTR_UserFree(&umcb.Flags, &b2);
459 HeapFree(GetProcessHeap(), 0, buffer);
460 SysFreeString(b);
462 b = SysAllocStringByteLen("", 0);
463 len = SysStringLen(b);
464 ok(len == 0, "get %d\n", len);
465 len = SysStringByteLen(b);
466 ok(len == 0, "get %d\n", len);
468 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
469 size = BSTR_UserSize(&umcb.Flags, 0, &b);
470 ok(size == 12, "size %d\n", size);
472 buffer = HeapAlloc(GetProcessHeap(), 0, size);
473 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
474 next = BSTR_UserMarshal(&umcb.Flags, buffer, &b);
475 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
476 check_bstr(buffer, b);
478 if (BSTR_UNMARSHAL_WORKS)
480 b2 = NULL;
481 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
482 next = BSTR_UserUnmarshal(&umcb.Flags, buffer, &b2);
483 ok(next == buffer + size, "got %p expect %p\n", next, buffer + size);
484 ok(b2 != NULL, "NULL LPSAFEARRAY didn't unmarshal\n");
485 len = SysStringByteLen(b2);
486 ok(len == 0, "byte len %d\n", len);
487 init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
488 BSTR_UserFree(&umcb.Flags, &b2);
490 HeapFree(GetProcessHeap(), 0, buffer);
491 SysFreeString(b);
494 typedef struct
496 const IUnknownVtbl *lpVtbl;
497 ULONG refs;
498 } HeapUnknown;
500 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
502 if (IsEqualIID(riid, &IID_IUnknown))
504 IUnknown_AddRef(iface);
505 *ppv = iface;
506 return S_OK;
508 *ppv = NULL;
509 return E_NOINTERFACE;
512 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
514 HeapUnknown *This = (HeapUnknown *)iface;
515 return InterlockedIncrement((LONG*)&This->refs);
518 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
520 HeapUnknown *This = (HeapUnknown *)iface;
521 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
522 if (!refs) HeapFree(GetProcessHeap(), 0, This);
523 return refs;
526 static const IUnknownVtbl HeapUnknown_Vtbl =
528 HeapUnknown_QueryInterface,
529 HeapUnknown_AddRef,
530 HeapUnknown_Release
533 static void check_variant_header(DWORD *wirev, VARIANT *v, ULONG size)
535 WORD *wp;
536 DWORD switch_is;
538 ok(*wirev == (size + 7) >> 3, "wv[0] %08x, expected %08x\n", *wirev, (size + 7) >> 3);
539 wirev++;
540 ok(*wirev == 0, "wv[1] %08x\n", *wirev);
541 wirev++;
542 wp = (WORD*)wirev;
543 ok(*wp == V_VT(v), "vt %04x expected %04x\n", *wp, V_VT(v));
544 wp++;
545 ok(*wp == V_U2(v).wReserved1, "res1 %04x expected %04x\n", *wp, V_U2(v).wReserved1);
546 wp++;
547 ok(*wp == V_U2(v).wReserved2, "res2 %04x expected %04x\n", *wp, V_U2(v).wReserved2);
548 wp++;
549 ok(*wp == V_U2(v).wReserved3, "res3 %04x expected %04x\n", *wp, V_U2(v).wReserved3);
550 wp++;
551 wirev = (DWORD*)wp;
552 switch_is = V_VT(v);
553 if(switch_is & VT_ARRAY)
554 switch_is &= ~VT_TYPEMASK;
555 ok(*wirev == switch_is, "switch_is %08x expected %08x\n", *wirev, switch_is);
558 static void test_marshal_VARIANT(void)
560 VARIANT v, v2;
561 MIDL_STUB_MESSAGE stubMsg = { 0 };
562 RPC_MESSAGE rpcMsg = { 0 };
563 USER_MARSHAL_CB umcb = { 0 };
564 unsigned char *buffer, *next;
565 ULONG ul;
566 short s;
567 double d;
568 DWORD *wirev;
569 BSTR b;
570 WCHAR str[] = {'m','a','r','s','h','a','l',' ','t','e','s','t',0};
571 SAFEARRAYBOUND sab;
572 LPSAFEARRAY lpsa;
573 DECIMAL dec, dec2;
574 HeapUnknown *heap_unknown;
576 stubMsg.RpcMsg = &rpcMsg;
578 umcb.Flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
579 umcb.pStubMsg = &stubMsg;
580 umcb.pReserve = NULL;
581 umcb.Signature = USER_MARSHAL_CB_SIGNATURE;
582 umcb.CBType = USER_MARSHAL_CB_UNMARSHALL;
584 /*** I1 ***/
585 VariantInit(&v);
586 V_VT(&v) = VT_I1;
587 V_I1(&v) = 0x12;
589 /* check_variant_header tests wReserved[123], so initialize to unique values.
590 * (Could probably also do this by setting the variant to a known DECIMAL.)
592 V_U2(&v).wReserved1 = 0x1234;
593 V_U2(&v).wReserved2 = 0x5678;
594 V_U2(&v).wReserved3 = 0x9abc;
596 /* Variants have an alignment of 8 */
597 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 1, &v);
598 ok(stubMsg.BufferLength == 29, "size %d\n", stubMsg.BufferLength);
600 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
601 ok(stubMsg.BufferLength == 21, "size %d\n", stubMsg.BufferLength);
603 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
604 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
605 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
606 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
607 wirev = (DWORD*)buffer;
609 check_variant_header(wirev, &v, stubMsg.BufferLength);
610 wirev += 5;
611 ok(*(char*)wirev == V_I1(&v), "wv[5] %08x\n", *wirev);
612 if (VARIANT_UNMARSHAL_WORKS)
614 VariantInit(&v2);
615 stubMsg.Buffer = buffer;
616 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
617 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
618 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
619 ok(V_I1(&v) == V_I1(&v2), "got i1 %x expect %x\n", V_I1(&v), V_I1(&v2));
621 VARIANT_UserFree(&umcb.Flags, &v2);
623 HeapFree(GetProcessHeap(), 0, buffer);
625 /*** I2 ***/
626 VariantInit(&v);
627 V_VT(&v) = VT_I2;
628 V_I2(&v) = 0x1234;
630 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
631 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
633 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
634 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
635 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
636 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
637 wirev = (DWORD*)buffer;
639 check_variant_header(wirev, &v, stubMsg.BufferLength);
640 wirev += 5;
641 ok(*(short*)wirev == V_I2(&v), "wv[5] %08x\n", *wirev);
642 if (VARIANT_UNMARSHAL_WORKS)
644 VariantInit(&v2);
645 stubMsg.Buffer = buffer;
646 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
647 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
648 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
649 ok(V_I2(&v) == V_I2(&v2), "got i2 %x expect %x\n", V_I2(&v), V_I2(&v2));
651 VARIANT_UserFree(&umcb.Flags, &v2);
653 HeapFree(GetProcessHeap(), 0, buffer);
655 /*** I2 BYREF ***/
656 VariantInit(&v);
657 V_VT(&v) = VT_I2 | VT_BYREF;
658 s = 0x1234;
659 V_I2REF(&v) = &s;
661 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
662 ok(stubMsg.BufferLength == 26, "size %d\n", stubMsg.BufferLength);
664 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
665 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
666 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
667 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
668 wirev = (DWORD*)buffer;
670 check_variant_header(wirev, &v, stubMsg.BufferLength);
671 wirev += 5;
672 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
673 wirev++;
674 ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
675 if (VARIANT_UNMARSHAL_WORKS)
677 void *mem;
678 VariantInit(&v2);
679 V_VT(&v2) = VT_I2 | VT_BYREF;
680 V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2)));
681 stubMsg.Buffer = buffer;
682 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
683 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
684 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
685 ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n");
686 ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
688 VARIANT_UserFree(&umcb.Flags, &v2);
690 HeapFree(GetProcessHeap(), 0, buffer);
692 /*** I4 ***/
693 VariantInit(&v);
694 V_VT(&v) = VT_I4;
695 V_I4(&v) = 0x1234;
697 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
698 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
700 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
701 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
702 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
703 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
704 wirev = (DWORD*)buffer;
706 check_variant_header(wirev, &v, stubMsg.BufferLength);
707 wirev += 5;
708 ok(*wirev == V_I4(&v), "wv[5] %08x\n", *wirev);
710 if (VARIANT_UNMARSHAL_WORKS)
712 VariantInit(&v2);
713 stubMsg.Buffer = buffer;
714 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
715 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
716 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
717 ok(V_I4(&v) == V_I4(&v2), "got i4 %x expect %x\n", V_I4(&v), V_I4(&v2));
719 VARIANT_UserFree(&umcb.Flags, &v2);
722 HeapFree(GetProcessHeap(), 0, buffer);
724 /*** UI4 ***/
725 VariantInit(&v);
726 V_VT(&v) = VT_UI4;
727 V_UI4(&v) = 0x1234;
729 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
730 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
732 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
733 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
734 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
735 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
736 wirev = (DWORD*)buffer;
738 check_variant_header(wirev, &v, stubMsg.BufferLength);
739 wirev += 5;
740 ok(*wirev == 0x1234, "wv[5] %08x\n", *wirev);
741 if (VARIANT_UNMARSHAL_WORKS)
743 VariantInit(&v2);
744 stubMsg.Buffer = buffer;
745 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
746 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
747 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
748 ok(V_UI4(&v) == V_UI4(&v2), "got ui4 %x expect %x\n", V_UI4(&v), V_UI4(&v2));
750 VARIANT_UserFree(&umcb.Flags, &v2);
753 HeapFree(GetProcessHeap(), 0, buffer);
755 /*** UI4 BYREF ***/
756 VariantInit(&v);
757 V_VT(&v) = VT_UI4 | VT_BYREF;
758 ul = 0x1234;
759 V_UI4REF(&v) = &ul;
761 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
762 ok(stubMsg.BufferLength == 28, "size %d\n", stubMsg.BufferLength);
764 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
765 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
766 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
767 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
768 wirev = (DWORD*)buffer;
770 check_variant_header(wirev, &v, stubMsg.BufferLength);
771 wirev += 5;
772 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
773 wirev++;
774 ok(*wirev == ul, "wv[6] %08x\n", *wirev);
776 if (VARIANT_UNMARSHAL_WORKS)
778 VariantInit(&v2);
779 stubMsg.Buffer = buffer;
780 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
781 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
782 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
783 ok(*V_UI4REF(&v) == *V_UI4REF(&v2), "got ui4 ref %x expect ui4 ref %x\n", *V_UI4REF(&v), *V_UI4REF(&v2));
785 VARIANT_UserFree(&umcb.Flags, &v2);
787 HeapFree(GetProcessHeap(), 0, buffer);
789 /*** R4 ***/
790 VariantInit(&v);
791 V_VT(&v) = VT_R4;
792 V_R8(&v) = 3.1415;
794 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
795 ok(stubMsg.BufferLength == 24, "size %d\n", stubMsg.BufferLength);
797 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
798 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
799 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
800 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
801 wirev = (DWORD*)buffer;
803 check_variant_header(wirev, &v, stubMsg.BufferLength);
804 wirev += 5;
805 ok(*(float*)wirev == V_R4(&v), "wv[5] %08x\n", *wirev);
806 if (VARIANT_UNMARSHAL_WORKS)
808 VariantInit(&v2);
809 stubMsg.Buffer = buffer;
810 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
811 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
812 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
813 ok(V_R4(&v) == V_R4(&v2), "got r4 %f expect %f\n", V_R4(&v), V_R4(&v2));
815 VARIANT_UserFree(&umcb.Flags, &v2);
817 HeapFree(GetProcessHeap(), 0, buffer);
819 /*** R8 ***/
820 VariantInit(&v);
821 V_VT(&v) = VT_R8;
822 V_R8(&v) = 3.1415;
824 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
825 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
827 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
828 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
829 memset(buffer, 0xcc, stubMsg.BufferLength);
830 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
831 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
832 wirev = (DWORD*)buffer;
834 check_variant_header(wirev, &v, stubMsg.BufferLength);
835 wirev += 5;
836 ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */
837 wirev++;
838 ok(*(double*)wirev == V_R8(&v), "wv[6] %08x, wv[7] %08x\n", *wirev, *(wirev+1));
839 if (VARIANT_UNMARSHAL_WORKS)
841 VariantInit(&v2);
842 stubMsg.Buffer = buffer;
843 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
844 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
845 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
846 ok(V_R8(&v) == V_R8(&v2), "got r8 %f expect %f\n", V_R8(&v), V_R8(&v2));
848 VARIANT_UserFree(&umcb.Flags, &v2);
850 HeapFree(GetProcessHeap(), 0, buffer);
852 /*** R8 BYREF ***/
853 VariantInit(&v);
854 V_VT(&v) = VT_R8 | VT_BYREF;
855 d = 3.1415;
856 V_R8REF(&v) = &d;
858 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
859 ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength);
861 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
862 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
863 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
864 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
865 wirev = (DWORD*)buffer;
867 check_variant_header(wirev, &v, stubMsg.BufferLength);
868 wirev += 5;
869 ok(*wirev == 8, "wv[5] %08x\n", *wirev);
870 wirev++;
871 ok(*(double*)wirev == d, "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
872 if (VARIANT_UNMARSHAL_WORKS)
874 VariantInit(&v2);
875 stubMsg.Buffer = buffer;
876 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
877 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
878 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
879 ok(*V_R8REF(&v) == *V_R8REF(&v2), "got r8 ref %f expect %f\n", *V_R8REF(&v), *V_R8REF(&v2));
881 VARIANT_UserFree(&umcb.Flags, &v2);
883 HeapFree(GetProcessHeap(), 0, buffer);
885 /*** VARIANT_BOOL ***/
886 VariantInit(&v);
887 V_VT(&v) = VT_BOOL;
888 V_BOOL(&v) = 0x1234;
890 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
891 ok(stubMsg.BufferLength == 22, "size %d\n", stubMsg.BufferLength);
893 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
894 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
895 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
896 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
897 wirev = (DWORD*)buffer;
899 check_variant_header(wirev, &v, stubMsg.BufferLength);
900 wirev += 5;
901 ok(*(short*)wirev == V_BOOL(&v), "wv[5] %04x\n", *(WORD*)wirev);
902 if (VARIANT_UNMARSHAL_WORKS)
904 VariantInit(&v2);
905 stubMsg.Buffer = buffer;
906 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
907 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
908 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
909 ok(V_BOOL(&v) == V_BOOL(&v2), "got bool %x expect %x\n", V_BOOL(&v), V_BOOL(&v2));
911 VARIANT_UserFree(&umcb.Flags, &v2);
913 HeapFree(GetProcessHeap(), 0, buffer);
915 /*** DECIMAL ***/
916 VarDecFromI4(0x12345678, &dec);
917 dec.wReserved = 0xfedc; /* Also initialize reserved field, as we check it later */
918 VariantInit(&v);
919 V_DECIMAL(&v) = dec;
920 V_VT(&v) = VT_DECIMAL;
922 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
923 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
925 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
926 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
927 memset(buffer, 0xcc, stubMsg.BufferLength);
928 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
929 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
930 wirev = (DWORD*)buffer;
932 check_variant_header(wirev, &v, stubMsg.BufferLength);
933 wirev += 5;
934 ok(*wirev == 0xcccccccc, "wirev[5] %08x\n", *wirev); /* pad */
935 wirev++;
936 dec2 = dec;
937 dec2.wReserved = VT_DECIMAL;
938 ok(!memcmp(wirev, &dec2, sizeof(dec2)), "wirev[6] %08x wirev[7] %08x wirev[8] %08x wirev[9] %08x\n",
939 *wirev, *(wirev + 1), *(wirev + 2), *(wirev + 3));
940 if (VARIANT_UNMARSHAL_WORKS)
942 VariantInit(&v2);
943 stubMsg.Buffer = buffer;
944 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
945 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
946 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
947 ok(!memcmp(&V_DECIMAL(&v), & V_DECIMAL(&v2), sizeof(DECIMAL)), "decimals differ\n");
949 VARIANT_UserFree(&umcb.Flags, &v2);
951 HeapFree(GetProcessHeap(), 0, buffer);
953 /*** DECIMAL BYREF ***/
954 VariantInit(&v);
955 V_VT(&v) = VT_DECIMAL | VT_BYREF;
956 V_DECIMALREF(&v) = &dec;
958 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
959 ok(stubMsg.BufferLength == 40, "size %d\n", stubMsg.BufferLength);
961 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
962 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
963 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
964 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
965 wirev = (DWORD*)buffer;
967 check_variant_header(wirev, &v, stubMsg.BufferLength);
968 wirev += 5;
969 ok(*wirev == 16, "wv[5] %08x\n", *wirev);
970 wirev++;
971 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));
972 if (VARIANT_UNMARSHAL_WORKS)
974 VariantInit(&v2);
975 /* check_variant_header tests wReserved[123], so initialize to unique values.
976 * (Could probably also do this by setting the variant to a known DECIMAL.)
978 V_U2(&v2).wReserved1 = 0x0123;
979 V_U2(&v2).wReserved2 = 0x4567;
980 V_U2(&v2).wReserved3 = 0x89ab;
982 stubMsg.Buffer = buffer;
983 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
984 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
985 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
986 ok(!memcmp(V_DECIMALREF(&v), V_DECIMALREF(&v2), sizeof(DECIMAL)), "decimals differ\n");
988 VARIANT_UserFree(&umcb.Flags, &v2);
990 HeapFree(GetProcessHeap(), 0, buffer);
992 /*** EMPTY ***/
993 VariantInit(&v);
994 V_VT(&v) = VT_EMPTY;
996 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
997 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
999 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1000 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1001 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1002 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1003 wirev = (DWORD*)buffer;
1005 check_variant_header(wirev, &v, stubMsg.BufferLength);
1006 if (VARIANT_UNMARSHAL_WORKS)
1008 VariantInit(&v2);
1009 stubMsg.Buffer = buffer;
1010 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1011 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1012 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1014 VARIANT_UserFree(&umcb.Flags, &v2);
1016 HeapFree(GetProcessHeap(), 0, buffer);
1018 /*** NULL ***/
1019 VariantInit(&v);
1020 V_VT(&v) = VT_NULL;
1022 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1023 ok(stubMsg.BufferLength == 20, "size %d\n", stubMsg.BufferLength);
1025 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
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;
1031 check_variant_header(wirev, &v, stubMsg.BufferLength);
1032 if (VARIANT_UNMARSHAL_WORKS)
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));
1040 VARIANT_UserFree(&umcb.Flags, &v2);
1042 HeapFree(GetProcessHeap(), 0, buffer);
1044 /*** BSTR ***/
1045 b = SysAllocString(str);
1046 VariantInit(&v);
1047 V_VT(&v) = VT_BSTR;
1048 V_BSTR(&v) = b;
1050 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1051 ok(stubMsg.BufferLength == 60, "size %d\n", stubMsg.BufferLength);
1052 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1053 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1054 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1055 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1056 wirev = (DWORD*)buffer;
1058 check_variant_header(wirev, &v, stubMsg.BufferLength);
1059 wirev += 5;
1060 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1061 wirev++;
1062 check_bstr(wirev, V_BSTR(&v));
1063 if (VARIANT_UNMARSHAL_WORKS)
1065 VariantInit(&v2);
1066 stubMsg.Buffer = buffer;
1067 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1068 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1069 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1070 ok(SysStringByteLen(V_BSTR(&v)) == SysStringByteLen(V_BSTR(&v2)), "bstr string lens differ\n");
1071 ok(!memcmp(V_BSTR(&v), V_BSTR(&v2), SysStringByteLen(V_BSTR(&v))), "bstrs differ\n");
1073 VARIANT_UserFree(&umcb.Flags, &v2);
1075 HeapFree(GetProcessHeap(), 0, buffer);
1077 /*** BSTR BYREF ***/
1078 VariantInit(&v);
1079 V_VT(&v) = VT_BSTR | VT_BYREF;
1080 V_BSTRREF(&v) = &b;
1082 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1083 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1084 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1085 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1086 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1087 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1088 wirev = (DWORD*)buffer;
1090 check_variant_header(wirev, &v, stubMsg.BufferLength);
1091 wirev += 5;
1092 ok(*wirev == 0x4, "wv[5] %08x\n", *wirev);
1093 wirev++;
1094 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is b. winxp: this is (char*)b + 1 */
1095 wirev++;
1096 check_bstr(wirev, b);
1097 if (VARIANT_UNMARSHAL_WORKS)
1099 VariantInit(&v2);
1100 stubMsg.Buffer = buffer;
1101 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1102 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1103 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1104 ok(SysStringByteLen(*V_BSTRREF(&v)) == SysStringByteLen(*V_BSTRREF(&v2)), "bstr string lens differ\n");
1105 ok(!memcmp(*V_BSTRREF(&v), *V_BSTRREF(&v2), SysStringByteLen(*V_BSTRREF(&v))), "bstrs differ\n");
1107 VARIANT_UserFree(&umcb.Flags, &v2);
1109 HeapFree(GetProcessHeap(), 0, buffer);
1110 SysFreeString(b);
1112 /*** ARRAY ***/
1113 sab.lLbound = 5;
1114 sab.cElements = 10;
1116 lpsa = SafeArrayCreate(VT_R8, 1, &sab);
1117 *(DWORD *)lpsa->pvData = 0xcafebabe;
1118 *((DWORD *)lpsa->pvData + 1) = 0xdeadbeef;
1120 VariantInit(&v);
1121 V_VT(&v) = VT_UI4 | VT_ARRAY;
1122 V_ARRAY(&v) = lpsa;
1124 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1125 ok(stubMsg.BufferLength == 152, "size %d\n", stubMsg.BufferLength);
1126 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1127 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1128 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1129 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1130 wirev = (DWORD*)buffer;
1132 check_variant_header(wirev, &v, stubMsg.BufferLength);
1133 wirev += 5;
1134 ok(*wirev, "wv[5] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1135 wirev++;
1136 check_safearray(wirev, lpsa);
1137 if (VARIANT_UNMARSHAL_WORKS)
1139 LONG bound, bound2;
1140 VARTYPE vt, vt2;
1141 VariantInit(&v2);
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(SafeArrayGetDim(V_ARRAY(&v)) == SafeArrayGetDim(V_ARRAY(&v)), "array dims differ\n");
1147 SafeArrayGetLBound(V_ARRAY(&v), 1, &bound);
1148 SafeArrayGetLBound(V_ARRAY(&v2), 1, &bound2);
1149 ok(bound == bound2, "array lbounds differ\n");
1150 SafeArrayGetUBound(V_ARRAY(&v), 1, &bound);
1151 SafeArrayGetUBound(V_ARRAY(&v2), 1, &bound2);
1152 ok(bound == bound2, "array ubounds differ\n");
1153 SafeArrayGetVartype(V_ARRAY(&v), &vt);
1154 SafeArrayGetVartype(V_ARRAY(&v2), &vt2);
1155 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1156 VARIANT_UserFree(&umcb.Flags, &v2);
1158 HeapFree(GetProcessHeap(), 0, buffer);
1160 /*** ARRAY BYREF ***/
1161 VariantInit(&v);
1162 V_VT(&v) = VT_UI4 | VT_ARRAY | VT_BYREF;
1163 V_ARRAYREF(&v) = &lpsa;
1165 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1166 ok(stubMsg.BufferLength == 152, "size %d\n", stubMsg.BufferLength);
1167 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1168 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1169 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1170 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1171 wirev = (DWORD*)buffer;
1173 check_variant_header(wirev, &v, stubMsg.BufferLength);
1174 wirev += 5;
1175 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1176 wirev++;
1177 ok(*wirev, "wv[6] %08x\n", *wirev); /* win2k: this is lpsa. winxp: this is (char*)lpsa + 1 */
1178 wirev++;
1179 check_safearray(wirev, lpsa);
1180 if (VARIANT_UNMARSHAL_WORKS)
1182 LONG bound, bound2;
1183 VARTYPE vt, vt2;
1184 VariantInit(&v2);
1185 stubMsg.Buffer = buffer;
1186 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
1187 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1188 ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
1189 ok(SafeArrayGetDim(*V_ARRAYREF(&v)) == SafeArrayGetDim(*V_ARRAYREF(&v)), "array dims differ\n");
1190 SafeArrayGetLBound(*V_ARRAYREF(&v), 1, &bound);
1191 SafeArrayGetLBound(*V_ARRAYREF(&v2), 1, &bound2);
1192 ok(bound == bound2, "array lbounds differ\n");
1193 SafeArrayGetUBound(*V_ARRAYREF(&v), 1, &bound);
1194 SafeArrayGetUBound(*V_ARRAYREF(&v2), 1, &bound2);
1195 ok(bound == bound2, "array ubounds differ\n");
1196 SafeArrayGetVartype(*V_ARRAYREF(&v), &vt);
1197 SafeArrayGetVartype(*V_ARRAYREF(&v2), &vt2);
1198 ok(vt == vt2, "array vts differ %x %x\n", vt, vt2);
1199 VARIANT_UserFree(&umcb.Flags, &v2);
1201 HeapFree(GetProcessHeap(), 0, buffer);
1202 SafeArrayDestroy(lpsa);
1204 /*** VARIANT BYREF ***/
1205 VariantInit(&v);
1206 VariantInit(&v2);
1207 V_VT(&v2) = VT_R8;
1208 V_R8(&v2) = 3.1415;
1209 V_VT(&v) = VT_VARIANT | VT_BYREF;
1210 V_VARIANTREF(&v) = &v2;
1212 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1213 ok(stubMsg.BufferLength == 64, "size %d\n", stubMsg.BufferLength);
1214 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1215 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1216 memset(buffer, 0xcc, stubMsg.BufferLength);
1217 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1218 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1219 wirev = (DWORD*)buffer;
1220 check_variant_header(wirev, &v, stubMsg.BufferLength);
1221 wirev += 5;
1223 ok(*wirev == 16, "wv[5] %08x\n", *wirev);
1224 wirev++;
1225 ok(*wirev == ('U' | 's' << 8 | 'e' << 16 | 'r' << 24), "wv[6] %08x\n", *wirev); /* 'User' */
1226 wirev++;
1227 ok(*wirev == 0xcccccccc, "wv[7] %08x\n", *wirev); /* pad */
1228 wirev++;
1229 check_variant_header(wirev, &v2, stubMsg.BufferLength - 32);
1230 wirev += 5;
1231 ok(*wirev == 0xcccccccc, "wv[13] %08x\n", *wirev); /* pad for VT_R8 */
1232 wirev++;
1233 ok(*(double*)wirev == V_R8(&v2), "wv[6] %08x wv[7] %08x\n", *wirev, *(wirev+1));
1234 if (VARIANT_UNMARSHAL_WORKS)
1236 VARIANT v3;
1237 VariantInit(&v3);
1238 stubMsg.Buffer = buffer;
1239 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1240 ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
1241 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1242 ok(V_VT(V_VARIANTREF(&v)) == V_VT(V_VARIANTREF(&v3)), "vts differ %x %x\n",
1243 V_VT(V_VARIANTREF(&v)), V_VT(V_VARIANTREF(&v3)));
1244 ok(V_R8(V_VARIANTREF(&v)) == V_R8(V_VARIANTREF(&v3)), "r8s differ\n");
1245 VARIANT_UserFree(&umcb.Flags, &v3);
1247 HeapFree(GetProcessHeap(), 0, buffer);
1249 /*** UNKNOWN ***/
1250 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1251 heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
1252 heap_unknown->refs = 1;
1253 VariantInit(&v);
1254 VariantInit(&v2);
1255 V_VT(&v) = VT_UNKNOWN;
1256 V_UNKNOWN(&v) = (IUnknown *)heap_unknown;
1258 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1259 ok(stubMsg.BufferLength > 32, "size %d\n", stubMsg.BufferLength);
1260 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1261 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1262 memset(buffer, 0xcc, stubMsg.BufferLength);
1263 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1264 wirev = (DWORD*)buffer;
1265 check_variant_header(wirev, &v, next - buffer);
1266 wirev += 5;
1268 todo_wine
1269 ok(*wirev == (DWORD_PTR)V_UNKNOWN(&v) /* Win9x */ ||
1270 *wirev == (DWORD_PTR)V_UNKNOWN(&v) + 1 /* NT */, "wv[5] %08x\n", *wirev);
1271 wirev++;
1272 todo_wine
1273 ok(*wirev == next - buffer - 0x20, "wv[6] %08x\n", *wirev);
1274 wirev++;
1275 todo_wine
1276 ok(*wirev == next - buffer - 0x20, "wv[7] %08x\n", *wirev);
1277 wirev++;
1278 todo_wine
1279 ok(*wirev == 0x574f454d, "wv[8] %08x\n", *wirev);
1280 if (VARIANT_UNMARSHAL_WORKS)
1282 VARIANT v3;
1283 VariantInit(&v3);
1284 V_VT(&v3) = VT_UNKNOWN;
1285 V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
1286 IUnknown_AddRef(V_UNKNOWN(&v3));
1287 stubMsg.Buffer = buffer;
1288 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1289 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1290 ok(V_UNKNOWN(&v) == V_UNKNOWN(&v3), "got %p expect %p\n", V_UNKNOWN(&v), V_UNKNOWN(&v3));
1291 VARIANT_UserFree(&umcb.Flags, &v3);
1292 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1293 IUnknown_Release((IUnknown *)heap_unknown);
1295 HeapFree(GetProcessHeap(), 0, buffer);
1297 /*** UNKNOWN BYREF ***/
1298 heap_unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*heap_unknown));
1299 heap_unknown->lpVtbl = &HeapUnknown_Vtbl;
1300 heap_unknown->refs = 1;
1301 VariantInit(&v);
1302 VariantInit(&v2);
1303 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
1304 V_UNKNOWNREF(&v) = (IUnknown **)&heap_unknown;
1306 rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v);
1307 ok(stubMsg.BufferLength > 36, "size %d\n", stubMsg.BufferLength);
1308 buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = HeapAlloc(GetProcessHeap(), 0, stubMsg.BufferLength);
1309 stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength;
1310 memset(buffer, 0xcc, stubMsg.BufferLength);
1311 next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v);
1312 wirev = (DWORD*)buffer;
1313 check_variant_header(wirev, &v, next - buffer);
1314 wirev += 5;
1316 ok(*wirev == 4, "wv[5] %08x\n", *wirev);
1317 wirev++;
1318 todo_wine
1319 ok(*wirev == (DWORD_PTR)heap_unknown /* Win9x, Win2000 */ ||
1320 *wirev == (DWORD_PTR)heap_unknown + 1 /* XP */, "wv[6] %08x\n", *wirev);
1321 wirev++;
1322 todo_wine
1323 ok(*wirev == next - buffer - 0x24, "wv[7] %08x\n", *wirev);
1324 wirev++;
1325 todo_wine
1326 ok(*wirev == next - buffer - 0x24, "wv[8] %08x\n", *wirev);
1327 wirev++;
1328 todo_wine
1329 ok(*wirev == 0x574f454d, "wv[9] %08x\n", *wirev);
1330 if (VARIANT_UNMARSHAL_WORKS)
1332 VARIANT v3;
1333 VariantInit(&v3);
1334 V_VT(&v3) = VT_UNKNOWN;
1335 V_UNKNOWN(&v3) = (IUnknown *)heap_unknown;
1336 IUnknown_AddRef(V_UNKNOWN(&v3));
1337 stubMsg.Buffer = buffer;
1338 next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v3);
1339 ok(V_VT(&v) == V_VT(&v3), "got vt %d expect %d\n", V_VT(&v), V_VT(&v3));
1340 ok(*V_UNKNOWNREF(&v) == *V_UNKNOWNREF(&v3), "got %p expect %p\n", *V_UNKNOWNREF(&v), *V_UNKNOWNREF(&v3));
1341 VARIANT_UserFree(&umcb.Flags, &v3);
1342 ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1);
1343 IUnknown_Release((IUnknown *)heap_unknown);
1345 HeapFree(GetProcessHeap(), 0, buffer);
1349 START_TEST(usrmarshal)
1351 CoInitialize(NULL);
1353 test_marshal_LPSAFEARRAY();
1354 test_marshal_BSTR();
1355 test_marshal_VARIANT();
1357 CoUninitialize();