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