1 /* 2 * SafeArray test program 3 * 4 * Copyright 2002 Marcus Meissner 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 22 #include <stdarg.h> 23 #include <stdio.h> 24 #include <math.h> 25 #include <float.h> 26 27 #define COBJMACROS 28 #define CONST_VTABLE 29 #include "wine/test.h" 30 #include "windef.h" 31 #include "winbase.h" 32 #include "winuser.h" 33 #include "wingdi.h" 34 #include "winnls.h" 35 #include "winsock2.h" 36 #include "winerror.h" 37 #include "winnt.h" 38 39 #include "wtypes.h" 40 #include "oleauto.h" 41 42 #ifndef FADF_CREATEVECTOR 43 const USHORT FADF_CREATEVECTOR = 0x2000; 44 #endif 45 46 static HMODULE hOleaut32; 47 48 static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**); 49 static HRESULT (WINAPI *pSafeArrayCopyData)(SAFEARRAY*,SAFEARRAY*); 50 static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*); 51 static HRESULT (WINAPI *pSafeArrayGetRecordInfo)(SAFEARRAY*,IRecordInfo**); 52 static SAFEARRAY* (WINAPI *pSafeArrayCreateEx)(VARTYPE,UINT,SAFEARRAYBOUND*,LPVOID); 53 static SAFEARRAY* (WINAPI *pSafeArrayCreateVector)(VARTYPE,LONG,ULONG); 54 55 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func) 56 57 /* Has I8/UI8 data type? */ 58 static BOOL has_i8; 59 /* Has INT_PTR/UINT_PTR type? */ 60 static BOOL has_int_ptr; 61 62 static const USHORT ignored_copy_features[] = 63 { 64 FADF_AUTO, 65 FADF_STATIC, 66 FADF_EMBEDDED, 67 FADF_FIXEDSIZE 68 }; 69 70 #define START_REF_COUNT 1 71 #define RECORD_SIZE 64 72 #define RECORD_SIZE_FAIL 17 73 /************************************************************************ 74 * Dummy IRecordInfo Implementation 75 */ 76 typedef struct IRecordInfoImpl 77 { 78 IRecordInfo IRecordInfo_iface; 79 LONG ref; 80 unsigned int sizeCalled; 81 unsigned int clearCalled; 82 unsigned int recordcopy; 83 } IRecordInfoImpl; 84 85 static inline IRecordInfoImpl *impl_from_IRecordInfo(IRecordInfo *iface) 86 { 87 return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface); 88 } 89 90 static HRESULT WINAPI RecordInfo_QueryInterface(IRecordInfo *iface, REFIID riid, void **obj) 91 { 92 *obj = NULL; 93 94 if (IsEqualIID(riid, &IID_IUnknown) || 95 IsEqualIID(riid, &IID_IRecordInfo)) 96 { 97 *obj = iface; 98 IRecordInfo_AddRef(iface); 99 return S_OK; 100 } 101 102 return E_NOINTERFACE; 103 } 104 105 static ULONG WINAPI RecordInfo_AddRef(IRecordInfo *iface) 106 { 107 IRecordInfoImpl* This = impl_from_IRecordInfo(iface); 108 return InterlockedIncrement(&This->ref); 109 } 110 111 static ULONG WINAPI RecordInfo_Release(IRecordInfo *iface) 112 { 113 IRecordInfoImpl* This = impl_from_IRecordInfo(iface); 114 ULONG ref = InterlockedDecrement(&This->ref); 115 116 if (!ref) 117 HeapFree(GetProcessHeap(), 0, This); 118 119 return ref; 120 } 121 122 static HRESULT WINAPI RecordInfo_RecordInit(IRecordInfo *iface, PVOID pvNew) 123 { 124 ok(0, "unexpected call\n"); 125 return E_NOTIMPL; 126 } 127 128 static BOOL fail_GetSize; /* Whether to fail the GetSize call */ 129 130 static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, PVOID pvExisting) 131 { 132 IRecordInfoImpl* This = impl_from_IRecordInfo(iface); 133 This->clearCalled++; 134 return S_OK; 135 } 136 137 static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew) 138 { 139 IRecordInfoImpl* This = impl_from_IRecordInfo(iface); 140 This->recordcopy++; 141 return S_OK; 142 } 143 144 static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid) 145 { 146 ok(0, "unexpected call\n"); 147 return E_NOTIMPL; 148 } 149 150 static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName) 151 { 152 ok(0, "unexpected call\n"); 153 return E_NOTIMPL; 154 } 155 156 static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG* size) 157 { 158 IRecordInfoImpl* This = impl_from_IRecordInfo(iface); 159 This->sizeCalled++; 160 if (fail_GetSize) 161 { 162 *size = RECORD_SIZE_FAIL; 163 return E_UNEXPECTED; 164 } 165 *size = RECORD_SIZE; 166 return S_OK; 167 } 168 169 static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo) 170 { 171 ok(0, "unexpected call\n"); 172 return E_NOTIMPL; 173 } 174 175 static HRESULT WINAPI RecordInfo_GetField(IRecordInfo *iface, PVOID pvData, 176 LPCOLESTR szFieldName, VARIANT *pvarField) 177 { 178 ok(0, "unexpected call\n"); 179 return E_NOTIMPL; 180 } 181 182 static HRESULT WINAPI RecordInfo_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData, 183 LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray) 184 { 185 ok(0, "unexpected call\n"); 186 return E_NOTIMPL; 187 } 188 189 static HRESULT WINAPI RecordInfo_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData, 190 LPCOLESTR szFieldName, VARIANT *pvarField) 191 { 192 ok(0, "unexpected call\n"); 193 return E_NOTIMPL; 194 } 195 196 static HRESULT WINAPI RecordInfo_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags, 197 PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField) 198 { 199 ok(0, "unexpected call\n"); 200 return E_NOTIMPL; 201 } 202 203 static HRESULT WINAPI RecordInfo_GetFieldNames(IRecordInfo *iface, ULONG *pcNames, 204 BSTR *rgBstrNames) 205 { 206 ok(0, "unexpected call\n"); 207 return E_NOTIMPL; 208 } 209 210 static BOOL WINAPI RecordInfo_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2) 211 { 212 ok(0, "unexpected call\n"); 213 return FALSE; 214 } 215 216 static PVOID WINAPI RecordInfo_RecordCreate(IRecordInfo *iface) 217 { 218 ok(0, "unexpected call\n"); 219 return NULL; 220 } 221 222 static HRESULT WINAPI RecordInfo_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource, 223 PVOID *ppvDest) 224 { 225 ok(0, "unexpected call\n"); 226 return E_NOTIMPL; 227 } 228 229 static HRESULT WINAPI RecordInfo_RecordDestroy(IRecordInfo *iface, PVOID pvRecord) 230 { 231 ok(0, "unexpected call\n"); 232 return E_NOTIMPL; 233 } 234 235 static const IRecordInfoVtbl RecordInfoVtbl = 236 { 237 RecordInfo_QueryInterface, 238 RecordInfo_AddRef, 239 RecordInfo_Release, 240 RecordInfo_RecordInit, 241 RecordInfo_RecordClear, 242 RecordInfo_RecordCopy, 243 RecordInfo_GetGuid, 244 RecordInfo_GetName, 245 RecordInfo_GetSize, 246 RecordInfo_GetTypeInfo, 247 RecordInfo_GetField, 248 RecordInfo_GetFieldNoCopy, 249 RecordInfo_PutField, 250 RecordInfo_PutFieldNoCopy, 251 RecordInfo_GetFieldNames, 252 RecordInfo_IsMatchingType, 253 RecordInfo_RecordCreate, 254 RecordInfo_RecordCreateCopy, 255 RecordInfo_RecordDestroy 256 }; 257 258 static IRecordInfoImpl *IRecordInfoImpl_Construct(void) 259 { 260 IRecordInfoImpl *rec; 261 262 rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl)); 263 rec->IRecordInfo_iface.lpVtbl = &RecordInfoVtbl; 264 rec->ref = START_REF_COUNT; 265 rec->clearCalled = 0; 266 rec->sizeCalled = 0; 267 return rec; 268 } 269 270 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt) 271 { 272 switch (vt) 273 { 274 case VT_I1: 275 case VT_UI1: return sizeof(BYTE); 276 case VT_BOOL: 277 case VT_I2: 278 case VT_UI2: return sizeof(SHORT); 279 case VT_I4: 280 case VT_UI4: 281 case VT_R4: 282 case VT_ERROR: return sizeof(LONG); 283 case VT_R8: return sizeof(LONG64); 284 case VT_I8: 285 case VT_UI8: 286 if (has_i8) 287 return sizeof(LONG64); 288 break; 289 case VT_INT: 290 case VT_UINT: return sizeof(INT); 291 case VT_INT_PTR: 292 case VT_UINT_PTR: 293 if (has_int_ptr) 294 return sizeof(UINT_PTR); 295 break; 296 case VT_CY: return sizeof(CY); 297 case VT_DATE: return sizeof(DATE); 298 case VT_BSTR: return sizeof(BSTR); 299 case VT_DISPATCH: return sizeof(LPDISPATCH); 300 case VT_VARIANT: return sizeof(VARIANT); 301 case VT_UNKNOWN: return sizeof(LPUNKNOWN); 302 case VT_DECIMAL: return sizeof(DECIMAL); 303 } 304 return 0; 305 } 306 307 static void check_for_VT_INT_PTR(void) 308 { 309 /* Set a global flag if VT_INT_PTR is supported */ 310 311 SAFEARRAY* a; 312 SAFEARRAYBOUND bound; 313 bound.cElements = 0; 314 bound.lLbound = 0; 315 a = SafeArrayCreate(VT_INT_PTR, 1, &bound); 316 if (a) { 317 HRESULT hres; 318 trace("VT_INT_PTR is supported\n"); 319 has_int_ptr = TRUE; 320 hres = SafeArrayDestroy(a); 321 ok(hres == S_OK, "got 0x%08x\n", hres); 322 } 323 else { 324 trace("VT_INT_PTR is not supported\n"); 325 has_int_ptr = FALSE; 326 } 327 } 328 329 #define VARTYPE_NOT_SUPPORTED 0 330 static struct { 331 VARTYPE vt; /* VT */ 332 UINT elemsize; /* elementsize by VT */ 333 UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */ 334 UINT addflags; /* additional fFeatures from SafeArrayCreate */ 335 } vttypes[] = { 336 {VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 337 {VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 338 {VT_I2, 2, FADF_HAVEVARTYPE,0}, 339 {VT_I4, 4, FADF_HAVEVARTYPE,0}, 340 {VT_R4, 4, FADF_HAVEVARTYPE,0}, 341 {VT_R8, 8, FADF_HAVEVARTYPE,0}, 342 {VT_CY, 8, FADF_HAVEVARTYPE,0}, 343 {VT_DATE, 8, FADF_HAVEVARTYPE,0}, 344 {VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR}, 345 {VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH}, 346 {VT_ERROR, 4, FADF_HAVEVARTYPE,0}, 347 {VT_BOOL, 2, FADF_HAVEVARTYPE,0}, 348 {VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT}, 349 {VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN}, 350 {VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0}, 351 {15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */ 352 {VT_I1, 1, FADF_HAVEVARTYPE,0}, 353 {VT_UI1, 1, FADF_HAVEVARTYPE,0}, 354 {VT_UI2, 2, FADF_HAVEVARTYPE,0}, 355 {VT_UI4, 4, FADF_HAVEVARTYPE,0}, 356 {VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 357 {VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 358 {VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0}, 359 {VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0}, 360 {VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 361 {VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 362 {VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 363 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 364 {VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 365 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 366 {VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 367 {VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 368 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 369 {VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0}, 370 {VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 371 {VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 372 {VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 373 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 374 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 375 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 376 {VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 377 {VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, 378 }; 379 380 static void test_safearray(void) 381 { 382 SAFEARRAY *a, b, *c; 383 unsigned int i, diff; 384 LONG indices[2]; 385 HRESULT hres; 386 SAFEARRAYBOUND bound, bounds[2]; 387 VARIANT v,d; 388 LPVOID data; 389 IID iid; 390 VARTYPE vt; 391 LONG l; 392 unsigned char *ptr1, *ptr2; 393 394 hres = SafeArrayDestroy( NULL); 395 ok( hres == S_OK, "SafeArrayDestroy( NULL) returned 0x%x\n", hres); 396 397 bound.cElements = 1; 398 bound.lLbound = 0; 399 a = SafeArrayCreate(-1, 1, &bound); 400 ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n"); 401 402 bound.cElements = 0; 403 bound.lLbound = 42; 404 a = SafeArrayCreate(VT_I4, 1, &bound); 405 ok(NULL != a,"SAC(VT_I4,1,[0,0]) failed.\n"); 406 407 hres = SafeArrayGetLBound(a, 1, &l); 408 ok(hres == S_OK, "SAGLB of 0 size dimensioned array failed with %x\n",hres); 409 ok(l == 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %d\n",l); 410 hres = SafeArrayGetUBound(a, 1, &l); 411 ok(hres == S_OK, "SAGUB of 0 size dimensioned array failed with %x\n",hres); 412 ok(l == 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %d\n",l); 413 414 hres = SafeArrayAccessData(a, &data); 415 ok(hres == S_OK, "SafeArrayAccessData of 0 size dimensioned array failed with %x\n", hres); 416 SafeArrayUnaccessData(a); 417 418 bound.cElements = 2; 419 hres = SafeArrayRedim(a, &bound); 420 ok(hres == S_OK,"SAR of a 0 elements dimension failed with hres %x\n", hres); 421 bound.cElements = 0; 422 hres = SafeArrayRedim(a, &bound); 423 ok(hres == S_OK || hres == E_OUTOFMEMORY, 424 "SAR to a 0 elements dimension failed with hres %x\n", hres); 425 hres = SafeArrayDestroy(a); 426 ok(hres == S_OK,"SAD of 0 dim array failed with hres %x\n", hres); 427 428 SafeArrayAllocDescriptor(2, &a); 429 a->rgsabound[0].cElements = 2; 430 a->rgsabound[0].lLbound = 1; 431 a->rgsabound[1].cElements = 4; 432 a->rgsabound[1].lLbound = 1; 433 a->cbElements = 2; 434 hres = SafeArrayAllocData(a); 435 ok(hres == S_OK, "SafeArrayAllocData failed with hres %x\n", hres); 436 437 indices[0] = 4; 438 indices[1] = 2; 439 hres = SafeArrayPtrOfIndex(a, indices, (void **)&ptr1); 440 ok(hres == S_OK, "SAPOI failed with hres %x\n", hres); 441 SafeArrayAccessData(a, (void **)&ptr2); 442 ok(ptr1 - ptr2 == 14, "SAPOI got wrong ptr\n"); 443 *(WORD *)ptr1 = 0x55aa; 444 SafeArrayUnaccessData(a); 445 446 bound.cElements = 10; 447 bound.lLbound = 1; 448 SafeArrayRedim(a, &bound); 449 ptr1 = NULL; 450 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1); 451 ok(*(WORD *)ptr1 == 0x55aa, "Data not preserved when resizing array\n"); 452 453 bound.cElements = 10; 454 bound.lLbound = 0; 455 SafeArrayRedim(a, &bound); 456 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1); 457 ok(*(WORD *)ptr1 == 0 || 458 broken(*(WORD *)ptr1 != 0), /* Win 2003 */ 459 "Expanded area not zero-initialized\n"); 460 461 indices[1] = 1; 462 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1); 463 ok(*(WORD *)ptr1 == 0x55aa || 464 broken(*(WORD *)ptr1 != 0x55aa), /* Win 2003 */ 465 "Data not preserved when resizing array\n"); 466 467 hres = SafeArrayDestroy(a); 468 ok(hres == S_OK,"SAD failed with hres %x\n", hres); 469 470 bounds[0].cElements = 0; bounds[0].lLbound = 1; 471 bounds[1].cElements = 2; bounds[1].lLbound = 23; 472 a = SafeArrayCreate(VT_I4,2,bounds); 473 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n"); 474 475 hres = SafeArrayDestroy(a); 476 ok(hres == S_OK,"SAD failed with hres %x\n", hres); 477 bounds[0].cElements = 1; bounds[0].lLbound = 1; 478 bounds[1].cElements = 0; bounds[1].lLbound = 23; 479 a = SafeArrayCreate(VT_I4,2,bounds); 480 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n"); 481 482 hres = SafeArrayDestroy(a); 483 ok(hres == S_OK,"SAD failed with hres %x\n", hres); 484 485 bounds[0].cElements = 42; bounds[0].lLbound = 1; 486 bounds[1].cElements = 2; bounds[1].lLbound = 23; 487 a = SafeArrayCreate(VT_I4,2,bounds); 488 ok(a != NULL,"SAC(VT_INT32,2,...) failed.\n"); 489 490 hres = SafeArrayGetLBound (a, 0, &l); 491 ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %x\n", hres); 492 hres = SafeArrayGetLBound (a, 1, &l); 493 ok (hres == S_OK, "SAGLB 1 failed with %x\n", hres); 494 ok (l == 1, "SAGLB 1 returned %d instead of 1\n", l); 495 hres = SafeArrayGetLBound (a, 2, &l); 496 ok (hres == S_OK, "SAGLB 2 failed with %x\n", hres); 497 ok (l == 23, "SAGLB 2 returned %d instead of 23\n", l); 498 hres = SafeArrayGetLBound (a, 3, &l); 499 ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %x\n", hres); 500 501 hres = SafeArrayGetUBound (a, 0, &l); 502 ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %x\n", hres); 503 hres = SafeArrayGetUBound (a, 1, &l); 504 ok (hres == S_OK, "SAGUB 1 failed with %x\n", hres); 505 ok (l == 42, "SAGUB 1 returned %d instead of 42\n", l); 506 hres = SafeArrayGetUBound (a, 2, &l); 507 ok (hres == S_OK, "SAGUB 2 failed with %x\n", hres); 508 ok (l == 24, "SAGUB 2 returned %d instead of 24\n", l); 509 hres = SafeArrayGetUBound (a, 3, &l); 510 ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %x\n", hres); 511 512 i = SafeArrayGetDim(a); 513 ok(i == 2, "getdims of 2 din array returned %d\n",i); 514 515 indices[0] = 0; 516 indices[1] = 23; 517 hres = SafeArrayGetElement(a, indices, &i); 518 ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%x\n",hres); 519 520 indices[0] = 1; 521 indices[1] = 22; 522 hres = SafeArrayGetElement(a, indices, &i); 523 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%x\n",hres); 524 525 indices[0] = 1; 526 indices[1] = 23; 527 hres = SafeArrayGetElement(a, indices, &i); 528 ok(S_OK == hres,"SAGE failed [1,23], hres 0x%x\n",hres); 529 530 indices[0] = 1; 531 indices[1] = 25; 532 hres = SafeArrayGetElement(a, indices, &i); 533 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%x\n",hres); 534 535 indices[0] = 3; 536 indices[1] = 23; 537 hres = SafeArrayGetElement(a, indices, &i); 538 ok(S_OK == hres,"SAGE failed [42,23], hres 0x%x\n",hres); 539 540 hres = SafeArrayAccessData(a, (void**)&ptr1); 541 ok(S_OK == hres, "SAAD failed with 0x%x\n", hres); 542 543 indices[0] = 3; 544 indices[1] = 23; 545 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2); 546 ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%x\n",hres); 547 diff = ptr2 - ptr1; 548 ok(diff == 8,"ptr difference is not 8, but %d (%p vs %p)\n", diff, ptr2, ptr1); 549 550 indices[0] = 3; 551 indices[1] = 24; 552 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2); 553 ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%x\n",hres); 554 diff = ptr2 - ptr1; 555 ok(diff == 176,"ptr difference is not 176, but %d (%p vs %p)\n", diff, ptr2, ptr1); 556 557 indices[0] = 20; 558 indices[1] = 23; 559 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2); 560 ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%x\n",hres); 561 diff = ptr2 - ptr1; 562 ok(diff == 76,"ptr difference is not 76, but %d (%p vs %p)\n", diff, ptr2, ptr1); 563 564 hres = SafeArrayUnaccessData(a); 565 ok(S_OK == hres, "SAUAD failed with 0x%x\n", hres); 566 567 hres = SafeArrayDestroy(a); 568 ok(hres == S_OK,"SAD failed with hres %x\n", hres); 569 570 for (i = 0; i < ARRAY_SIZE(vttypes); i++) { 571 if ((i == VT_I8 || i == VT_UI8) && has_i8) 572 { 573 vttypes[i].elemsize = sizeof(LONG64); 574 } 575 576 a = SafeArrayCreate(vttypes[i].vt, 1, &bound); 577 578 ok((!a && !vttypes[i].elemsize) || 579 (a && vttypes[i].elemsize == a->cbElements), 580 "SAC(%d,1,[1,0]), %p result %d, expected %d\n", 581 vttypes[i].vt,a,(a?a->cbElements:0),vttypes[i].elemsize); 582 583 if (a) 584 { 585 ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags), 586 "SAC of %d returned feature flags %x, expected %x\n", 587 vttypes[i].vt, a->fFeatures, 588 vttypes[i].expflags|vttypes[i].addflags); 589 ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize, 590 "SAGE for vt %d returned elemsize %d instead of expected %d\n", 591 vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize); 592 } 593 594 if (!a) continue; 595 596 if (pSafeArrayGetVartype) 597 { 598 hres = pSafeArrayGetVartype(a, &vt); 599 ok(hres == S_OK, "SAGVT of arra y with vt %d failed with %x\n", vttypes[i].vt, hres); 600 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */ 601 ok(broken(vt == VT_UNKNOWN) || vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt); 602 } 603 604 hres = SafeArrayCopy(a, &c); 605 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %x\n", vttypes[i].vt, hres); 606 607 ok(vttypes[i].elemsize == c->cbElements,"copy of SAC(%d,1,[1,0]), result %d, expected %d\n",vttypes[i].vt,(c?c->cbElements:0),vttypes[i].elemsize 608 ); 609 ok(c->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),"SAC of %d returned feature flags %x, expected %x\n", vttypes[i].vt, c->fFeatures, vttypes[i].expflags|vttypes[i].addflags); 610 ok(SafeArrayGetElemsize(c) == vttypes[i].elemsize,"SAGE for vt %d returned elemsize %d instead of expected %d\n",vttypes[i].vt, SafeArrayGetElemsize(c),vttypes[i].elemsize); 611 612 if (pSafeArrayGetVartype) { 613 hres = pSafeArrayGetVartype(c, &vt); 614 ok(hres == S_OK, "SAGVT of array with vt %d failed with %x\n", vttypes[i].vt, hres); 615 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */ 616 ok(broken(vt == VT_UNKNOWN) || vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt); 617 } 618 619 if (pSafeArrayCopyData) { 620 hres = pSafeArrayCopyData(a, c); 621 ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %x\n", vttypes[i].vt, hres); 622 623 hres = SafeArrayDestroyData(c); 624 ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %x\n", vttypes[i].vt, hres); 625 } 626 627 hres = SafeArrayDestroy(c); 628 ok(hres == S_OK,"SAD failed with hres %x\n", hres); 629 630 hres = SafeArrayDestroy(a); 631 ok(hres == S_OK,"SAD of array with vt %d failed with hres %x\n", vttypes[i].vt, hres); 632 } 633 634 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */ 635 bound.lLbound = 0; 636 bound.cElements = 10; 637 a = SafeArrayCreate(VT_UI1, 1, &bound); 638 ok(a != NULL, "SAC failed.\n"); 639 ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed\n"); 640 memcpy(data,"Hello World\n",10); 641 ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed\n"); 642 V_VT(&v) = VT_ARRAY|VT_UI1; 643 V_ARRAY(&v) = a; 644 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR); 645 ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n",hres); 646 ok(V_VT(&v) == VT_BSTR,"CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.v\n",V_VT(&v)); 647 ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v)[0]); 648 VariantClear(&v); 649 650 VariantInit(&d); 651 V_VT(&v) = VT_BSTR; 652 V_BSTR(&v) = SysAllocStringLen(NULL, 0); 653 hres = VariantChangeTypeEx(&d, &v, 0, 0, VT_UI1|VT_ARRAY); 654 ok(hres==S_OK, "CTE VT_BSTR -> VT_UI1|VT_ARRAY failed with %x\n",hres); 655 ok(V_VT(&d) == (VT_UI1|VT_ARRAY),"CTE BSTR -> VT_UI1|VT_ARRAY did not return VT_UI1|VT_ARRAY, but %d.v\n",V_VT(&v)); 656 VariantClear(&v); 657 VariantClear(&d); 658 659 /* check locking functions */ 660 a = SafeArrayCreate(VT_I4, 1, &bound); 661 ok(a!=NULL,"SAC should not fail\n"); 662 663 hres = SafeArrayAccessData(a, &data); 664 ok(hres == S_OK,"SAAD failed with hres %x\n",hres); 665 666 hres = SafeArrayDestroy(a); 667 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres); 668 669 hres = SafeArrayDestroyData(a); 670 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres); 671 672 hres = SafeArrayDestroyDescriptor(a); 673 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres); 674 675 hres = SafeArrayUnaccessData(a); 676 ok(hres == S_OK,"SAUD failed after lock/destroy test\n"); 677 678 hres = SafeArrayDestroy(a); 679 ok(hres == S_OK,"SAD failed after lock/destroy test\n"); 680 681 /* Test if we need to destroy data before descriptor */ 682 a = SafeArrayCreate(VT_I4, 1, &bound); 683 ok(a!=NULL,"SAC should not fail\n"); 684 hres = SafeArrayDestroyDescriptor(a); 685 ok(hres == S_OK,"SADD with data in array failed with hres %x\n",hres); 686 687 /* IID functions */ 688 /* init a small stack safearray */ 689 memset(&b, 0, sizeof(b)); 690 b.cDims = 1; 691 memset(&iid, 0x42, sizeof(IID)); 692 hres = SafeArraySetIID(&b, &iid); 693 ok(hres == E_INVALIDARG, "Unexpected ret value %#x.\n", hres); 694 695 hres = SafeArrayAllocDescriptor(1, &a); 696 ok(hres == S_OK, "Failed to allocate array descriptor, hr %#x.\n", hres); 697 ok((a->fFeatures & FADF_HAVEIID) == 0, "Unexpected features mask %#x.\n", a->fFeatures); 698 hres = SafeArraySetIID(a, &iid); 699 ok(hres == E_INVALIDARG, "Unexpected ret value %#x.\n", hres); 700 701 hres = SafeArrayDestroyDescriptor(a); 702 ok(hres == S_OK,"SADD failed with hres %x\n",hres); 703 704 if (!pSafeArrayAllocDescriptorEx) 705 return; 706 707 for (i = 0; i < ARRAY_SIZE(vttypes); i++) { 708 a = NULL; 709 hres = pSafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a); 710 ok(hres == S_OK, "SafeArrayAllocDescriptorEx gave hres 0x%x\n", hres); 711 ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags); 712 if (a->fFeatures & FADF_HAVEIID) { 713 hres = SafeArrayGetIID(a, &iid); 714 ok(hres == S_OK,"SAGIID failed for vt %d with hres %x\n", vttypes[i].vt,hres); 715 switch (vttypes[i].vt) { 716 case VT_UNKNOWN: 717 ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown\n"); 718 ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown\n"); 719 break; 720 case VT_DISPATCH: 721 ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch\n"); 722 ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch\n"); 723 break; 724 default: 725 ok(FALSE,"unknown vt %d with FADF_HAVEIID\n",vttypes[i].vt); 726 break; 727 } 728 } else { 729 hres = SafeArrayGetIID(a, &iid); 730 ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %x\n", vttypes[i].vt,hres); 731 } 732 if (a->fFeatures & FADF_RECORD) { 733 ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d\n",vttypes[i].vt); 734 } 735 if (a->fFeatures & FADF_HAVEVARTYPE) { 736 ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %d\n",vttypes[i].vt,((DWORD*)a)[-1]); 737 } 738 739 hres = pSafeArrayGetVartype(a, &vt); 740 ok(hres == S_OK, "SAGVT of array with vt %d failed with %x\n", vttypes[i].vt, hres); 741 742 if (vttypes[i].vt == VT_DISPATCH) { 743 /* Special case. Checked against Windows. */ 744 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt); 745 } else { 746 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt); 747 } 748 749 if (a->fFeatures & FADF_HAVEIID) { 750 hres = SafeArraySetIID(a, &IID_IStorage); /* random IID */ 751 ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres); 752 hres = SafeArrayGetIID(a, &iid); 753 ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres); 754 ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage\n"); 755 } else { 756 hres = SafeArraySetIID(a, &IID_IStorage); /* random IID */ 757 ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres); 758 } 759 hres = SafeArrayDestroyDescriptor(a); 760 ok(hres == S_OK,"SADD failed with hres %x\n",hres); 761 } 762 } 763 764 static void test_SafeArrayAllocDestroyDescriptor(void) 765 { 766 SAFEARRAY *sa; 767 HRESULT hres; 768 UINT i; 769 770 /* Failure cases */ 771 hres = SafeArrayAllocDescriptor(0, &sa); 772 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres); 773 774 hres = SafeArrayAllocDescriptor(65536, &sa); 775 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres); 776 777 if (0) 778 { 779 /* Crashes on 95: XP & Wine return E_POINTER */ 780 hres=SafeArrayAllocDescriptor(1, NULL); 781 ok(hres == E_POINTER,"NULL parm gave hres 0x%x\n", hres); 782 } 783 784 /* Test up to the dimension boundary case */ 785 for (i = 5; i <= 65535; i += 30) 786 { 787 hres = SafeArrayAllocDescriptor(i, &sa); 788 ok(hres == S_OK, "%d dimensions failed; hres 0x%x\n", i, hres); 789 790 if (hres == S_OK) 791 { 792 ok(SafeArrayGetDim(sa) == i, "Dimension is %d; should be %d\n", 793 SafeArrayGetDim(sa), i); 794 795 hres = SafeArrayDestroyDescriptor(sa); 796 ok(hres == S_OK, "destroy failed; hres 0x%x\n", hres); 797 } 798 } 799 800 if (!pSafeArrayAllocDescriptorEx) 801 return; 802 803 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 0, &sa); 804 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres); 805 806 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 65536, &sa); 807 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres); 808 809 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 1, NULL); 810 ok(hres == E_POINTER,"NULL parm gave hres 0x%x\n", hres); 811 812 hres = pSafeArrayAllocDescriptorEx(-1, 1, &sa); 813 ok(hres == S_OK, "VT = -1 gave hres 0x%x\n", hres); 814 815 sa->rgsabound[0].cElements = 0; 816 sa->rgsabound[0].lLbound = 1; 817 818 hres = SafeArrayAllocData(sa); 819 ok(hres == S_OK, "SafeArrayAllocData gave hres 0x%x\n", hres); 820 821 hres = SafeArrayDestroy(sa); 822 ok(hres == S_OK,"SafeArrayDestroy failed with hres %x\n",hres); 823 } 824 825 static void test_SafeArrayCreateLockDestroy(void) 826 { 827 SAFEARRAYBOUND sab[4]; 828 SAFEARRAY *sa; 829 HRESULT hres; 830 VARTYPE vt; 831 UINT dimension; 832 833 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++) 834 { 835 sab[dimension].lLbound = 0; 836 sab[dimension].cElements = 8; 837 } 838 839 /* Failure cases */ 840 /* This test crashes very early versions with no error checking... 841 sa = SafeArrayCreate(VT_UI1, 1, NULL); 842 ok(sa == NULL, "NULL bounds didn't fail\n"); 843 */ 844 sa = SafeArrayCreate(VT_UI1, 65536, sab); 845 ok(!sa, "Max bounds didn't fail\n"); 846 847 memset(sab, 0, sizeof(sab)); 848 849 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */ 850 851 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++) 852 sab[dimension].cElements = 8; 853 854 /* Test all VARTYPES in 1-4 dimensions */ 855 for (dimension = 1; dimension < 4; dimension++) 856 { 857 for (vt = VT_EMPTY; vt < VT_CLSID; vt++) 858 { 859 DWORD dwLen = SAFEARRAY_GetVTSize(vt); 860 861 sa = SafeArrayCreate(vt, dimension, sab); 862 863 if (dwLen) 864 ok(sa != NULL, "VARTYPE %d (@%d dimensions) failed\n", vt, dimension); 865 else 866 ok(sa == NULL || vt == VT_R8, 867 "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension); 868 869 if (sa) 870 { 871 ok(SafeArrayGetDim(sa) == dimension, 872 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n", 873 vt, dimension, SafeArrayGetDim(sa), dimension); 874 ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8, 875 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n", 876 vt, dimension, SafeArrayGetElemsize(sa), dwLen); 877 878 if (vt != VT_UNKNOWN && vt != VT_DISPATCH) 879 { 880 ok((sa->fFeatures & FADF_HAVEIID) == 0, 881 "Non interface type should not have FADF_HAVEIID\n"); 882 hres = SafeArraySetIID(sa, &IID_IUnknown); 883 ok(hres == E_INVALIDARG, "Unexpected ret value %#x.\n", hres); 884 if (vt != VT_RECORD) 885 { 886 VARTYPE aVt; 887 888 ok(sa->fFeatures & FADF_HAVEVARTYPE, 889 "Non interface type should have FADF_HAVEVARTYPE\n"); 890 if (pSafeArrayGetVartype) 891 { 892 hres = pSafeArrayGetVartype(sa, &aVt); 893 ok(hres == S_OK && aVt == vt, 894 "Non interface type %d: bad type %d, hres %x\n", vt, aVt, hres); 895 } 896 } 897 } 898 else 899 { 900 ok(sa->fFeatures & FADF_HAVEIID, "Interface type should have FADF_HAVEIID\n"); 901 hres = SafeArraySetIID(sa, &IID_IUnknown); 902 ok(hres == S_OK, "Failed to set array IID, hres %#x.\n", hres); 903 ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0, 904 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt); 905 } 906 907 hres = SafeArrayLock(sa); 908 ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n", 909 vt, dimension, hres); 910 911 if (hres == S_OK) 912 { 913 hres = SafeArrayDestroy(sa); 914 ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %x\n", hres); 915 916 hres = SafeArrayDestroyData(sa); 917 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %x\n", hres); 918 919 hres = SafeArrayDestroyDescriptor(sa); 920 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %x\n", hres); 921 922 hres = SafeArrayUnlock(sa); 923 ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n", 924 vt, dimension, hres); 925 926 hres = SafeArrayDestroy(sa); 927 ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%x\n", 928 vt, dimension, hres); 929 } 930 } 931 } 932 } 933 } 934 935 static void test_VectorCreateLockDestroy(void) 936 { 937 SAFEARRAY *sa; 938 HRESULT hres; 939 VARTYPE vt; 940 int element; 941 942 if (!pSafeArrayCreateVector) 943 { 944 win_skip("SafeArrayCreateVector not supported\n"); 945 return; 946 } 947 sa = pSafeArrayCreateVector(VT_UI1, 0, 0); 948 ok(sa != NULL, "SACV with 0 elements failed.\n"); 949 950 hres = SafeArrayDestroy(sa); 951 ok(hres == S_OK, "SafeArrayDestroy failed with hres %x\n",hres); 952 953 /* Test all VARTYPES in different lengths */ 954 for (element = 1; element <= 101; element += 10) 955 { 956 for (vt = VT_EMPTY; vt < VT_CLSID; vt++) 957 { 958 DWORD dwLen = SAFEARRAY_GetVTSize(vt); 959 960 sa = pSafeArrayCreateVector(vt, 0, element); 961 962 if (dwLen) 963 ok(sa != NULL, "VARTYPE %d (@%d elements) failed\n", vt, element); 964 else 965 ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element); 966 967 if (sa) 968 { 969 ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n", 970 vt, element, SafeArrayGetDim(sa)); 971 ok(SafeArrayGetElemsize(sa) == dwLen, 972 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n", 973 vt, element, SafeArrayGetElemsize(sa), dwLen); 974 975 hres = SafeArrayLock(sa); 976 ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n", 977 vt, element, hres); 978 979 if (hres == S_OK) 980 { 981 hres = SafeArrayUnlock(sa); 982 ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n", 983 vt, element, hres); 984 985 hres = SafeArrayDestroy(sa); 986 ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n", 987 vt, element, hres); 988 } 989 } 990 } 991 } 992 } 993 994 static void test_LockUnlock(void) 995 { 996 SAFEARRAYBOUND sab[4]; 997 SAFEARRAY *sa; 998 HRESULT hres; 999 BOOL bVector = FALSE; 1000 int dimension; 1001 1002 /* Failure cases */ 1003 hres = SafeArrayLock(NULL); 1004 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres); 1005 hres = SafeArrayUnlock(NULL); 1006 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres); 1007 1008 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++) 1009 { 1010 sab[dimension].lLbound = 0; 1011 sab[dimension].cElements = 8; 1012 } 1013 1014 sa = SafeArrayCreate(VT_UI1, ARRAY_SIZE(sab), sab); 1015 1016 /* Test maximum locks */ 1017 test_LockUnlock_Vector: 1018 if (sa) 1019 { 1020 int count = 0; 1021 1022 hres = SafeArrayUnlock(sa); 1023 ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%x\n", 1024 bVector ? "vector " : "\n", hres); 1025 1026 while ((hres = SafeArrayLock(sa)) == S_OK) 1027 count++; 1028 ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%x\n", 1029 bVector ? "vector " : "\n", count, hres); 1030 1031 if (count == 65535 && hres == E_UNEXPECTED) 1032 { 1033 while ((hres = SafeArrayUnlock(sa)) == S_OK) 1034 count--; 1035 ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%x\n", 1036 bVector ? "vector " : "\n", count, hres); 1037 } 1038 1039 hres = SafeArrayDestroy(sa); 1040 ok(hres == S_OK, "got 0x%08x\n", hres); 1041 } 1042 1043 if (bVector == FALSE && pSafeArrayCreateVector) 1044 { 1045 /* Test again with a vector */ 1046 sa = pSafeArrayCreateVector(VT_UI1, 0, 100); 1047 bVector = TRUE; 1048 goto test_LockUnlock_Vector; 1049 } 1050 } 1051 1052 static void test_SafeArrayGetPutElement(void) 1053 { 1054 SAFEARRAYBOUND sab[4]; 1055 LONG indices[ARRAY_SIZE(sab)], index; 1056 SAFEARRAY *sa; 1057 HRESULT hres; 1058 int value = 0, gotvalue, dimension; 1059 IRecordInfoImpl *irec; 1060 unsigned int x,y,z,a; 1061 1062 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++) 1063 { 1064 sab[dimension].lLbound = dimension * 2 + 1; 1065 sab[dimension].cElements = dimension * 3 + 1; 1066 } 1067 1068 sa = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab); 1069 if (!sa) 1070 return; /* Some early versions can't handle > 3 dims */ 1071 1072 ok(sa->cbElements == sizeof(value), "int size mismatch\n"); 1073 1074 /* Failure cases */ 1075 for (x = 0; x < ARRAY_SIZE(sab); x++) 1076 { 1077 indices[0] = sab[0].lLbound; 1078 indices[1] = sab[1].lLbound; 1079 indices[2] = sab[2].lLbound; 1080 indices[3] = sab[3].lLbound; 1081 1082 indices[x] = indices[x] - 1; 1083 hres = SafeArrayPutElement(sa, indices, &value); 1084 ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x); 1085 hres = SafeArrayGetElement(sa, indices, &value); 1086 ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x); 1087 1088 indices[x] = sab[x].lLbound + sab[x].cElements; 1089 hres = SafeArrayPutElement(sa, indices, &value); 1090 ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x); 1091 hres = SafeArrayGetElement(sa, indices, &value); 1092 ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x); 1093 } 1094 1095 indices[0] = sab[0].lLbound; 1096 indices[1] = sab[1].lLbound; 1097 indices[2] = sab[2].lLbound; 1098 indices[3] = sab[3].lLbound; 1099 1100 hres = SafeArrayPutElement(NULL, indices, &value); 1101 ok(hres == E_INVALIDARG, "Put NULL array hres 0x%x\n", hres); 1102 hres = SafeArrayGetElement(NULL, indices, &value); 1103 ok(hres == E_INVALIDARG, "Get NULL array hres 0x%x\n", hres); 1104 1105 hres = SafeArrayPutElement(sa, NULL, &value); 1106 ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%x\n", hres); 1107 hres = SafeArrayGetElement(sa, NULL, &value); 1108 ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%x\n", hres); 1109 1110 if (0) 1111 { 1112 /* This is retarded. Windows checks every case of invalid parameters 1113 * except the following, which crashes. We ERR this in Wine. 1114 */ 1115 hres = SafeArrayPutElement(sa, indices, NULL); 1116 ok(hres == E_INVALIDARG, "Put NULL value hres 0x%x\n", hres); 1117 } 1118 1119 hres = SafeArrayGetElement(sa, indices, NULL); 1120 ok(hres == E_INVALIDARG, "Get NULL value hres 0x%x\n", hres); 1121 1122 value = 0; 1123 1124 /* Make sure we can read and get back the correct values in 4 dimensions, 1125 * Each with a different size and lower bound. 1126 */ 1127 for (x = 0; x < sab[0].cElements; x++) 1128 { 1129 indices[0] = sab[0].lLbound + x; 1130 for (y = 0; y < sab[1].cElements; y++) 1131 { 1132 indices[1] = sab[1].lLbound + y; 1133 for (z = 0; z < sab[2].cElements; z++) 1134 { 1135 indices[2] = sab[2].lLbound + z; 1136 for (a = 0; a < sab[3].cElements; a++) 1137 { 1138 indices[3] = sab[3].lLbound + a; 1139 hres = SafeArrayPutElement(sa, indices, &value); 1140 ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n", 1141 x, y, z, a, hres); 1142 value++; 1143 } 1144 } 1145 } 1146 } 1147 1148 value = 0; 1149 1150 for (x = 0; x < sab[0].cElements; x++) 1151 { 1152 indices[0] = sab[0].lLbound + x; 1153 for (y = 0; y < sab[1].cElements; y++) 1154 { 1155 indices[1] = sab[1].lLbound + y; 1156 for (z = 0; z < sab[2].cElements; z++) 1157 { 1158 indices[2] = sab[2].lLbound + z; 1159 for (a = 0; a < sab[3].cElements; a++) 1160 { 1161 indices[3] = sab[3].lLbound + a; 1162 gotvalue = value / 3; 1163 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1164 ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n", 1165 x, y, z, a, hres); 1166 if (hres == S_OK) 1167 ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n", 1168 gotvalue, value, x, y, z, a); 1169 value++; 1170 } 1171 } 1172 } 1173 } 1174 hres = SafeArrayDestroy(sa); 1175 ok(hres == S_OK, "got 0x%08x\n", hres); 1176 1177 /* VT_RECORD array */ 1178 irec = IRecordInfoImpl_Construct(); 1179 irec->ref = 1; 1180 1181 sab[0].lLbound = 0; 1182 sab[0].cElements = 8; 1183 1184 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &irec->IRecordInfo_iface); 1185 ok(sa != NULL, "failed to create array\n"); 1186 ok(irec->ref == 2, "got %d\n", irec->ref); 1187 1188 index = 0; 1189 irec->recordcopy = 0; 1190 hres = SafeArrayPutElement(sa, &index, (void*)0xdeadbeef); 1191 ok(hres == S_OK, "got 0x%08x\n", hres); 1192 ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy); 1193 1194 index = 0; 1195 irec->recordcopy = 0; 1196 hres = SafeArrayGetElement(sa, &index, (void*)0xdeadbeef); 1197 ok(hres == S_OK, "got 0x%08x\n", hres); 1198 ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy); 1199 1200 hres = SafeArrayDestroy(sa); 1201 ok(hres == S_OK, "got 0x%08x\n", hres); 1202 ok(irec->ref == 1, "got %d\n", irec->ref); 1203 IRecordInfo_Release(&irec->IRecordInfo_iface); 1204 } 1205 1206 static void test_SafeArrayGetPutElement_BSTR(void) 1207 { 1208 SAFEARRAYBOUND sab; 1209 LONG indices[1]; 1210 SAFEARRAY *sa; 1211 HRESULT hres; 1212 BSTR value = 0, gotvalue; 1213 const OLECHAR szTest[5] = { 'T','e','s','t','\0' }; 1214 1215 sab.lLbound = 1; 1216 sab.cElements = 1; 1217 1218 sa = SafeArrayCreate(VT_BSTR, 1, &sab); 1219 ok(sa != NULL, "BSTR test couldn't create array\n"); 1220 if (!sa) 1221 return; 1222 1223 ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n"); 1224 1225 indices[0] = sab.lLbound; 1226 value = SysAllocString(szTest); 1227 ok (value != NULL, "Expected non-NULL\n"); 1228 hres = SafeArrayPutElement(sa, indices, value); 1229 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres); 1230 gotvalue = NULL; 1231 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1232 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres); 1233 if (hres == S_OK) 1234 ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value)); 1235 hres = SafeArrayDestroy(sa); 1236 ok(hres == S_OK, "got 0x%08x\n", hres); 1237 SysFreeString(value); 1238 SysFreeString(gotvalue); 1239 } 1240 1241 struct xtunk_impl { 1242 IUnknown IUnknown_iface; 1243 LONG ref; 1244 }; 1245 static const IUnknownVtbl xtunk_vtbl; 1246 1247 static struct xtunk_impl xtunk = {{&xtunk_vtbl}, 0}; 1248 1249 static HRESULT WINAPI tunk_QueryInterface(IUnknown *punk, REFIID riid, void **x) 1250 { 1251 return E_FAIL; 1252 } 1253 1254 static ULONG WINAPI tunk_AddRef(IUnknown *punk) 1255 { 1256 return ++xtunk.ref; 1257 } 1258 1259 static ULONG WINAPI tunk_Release(IUnknown *punk) 1260 { 1261 return --xtunk.ref; 1262 } 1263 1264 static const IUnknownVtbl xtunk_vtbl = { 1265 tunk_QueryInterface, 1266 tunk_AddRef, 1267 tunk_Release 1268 }; 1269 1270 static void test_SafeArrayGetPutElement_IUnknown(void) 1271 { 1272 SAFEARRAYBOUND sab; 1273 LONG indices[1]; 1274 SAFEARRAY *sa; 1275 HRESULT hres; 1276 IUnknown *gotvalue; 1277 1278 sab.lLbound = 1; 1279 sab.cElements = 1; 1280 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab); 1281 ok(sa != NULL, "UNKNOWN test couldn't create array\n"); 1282 if (!sa) 1283 return; 1284 1285 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n"); 1286 1287 indices[0] = sab.lLbound; 1288 xtunk.ref = 1; 1289 hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface); 1290 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres); 1291 ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n"); 1292 gotvalue = NULL; 1293 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1294 ok(xtunk.ref == 3,"Failed to increment refcount of iface.\n"); 1295 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres); 1296 if (hres == S_OK) 1297 ok(gotvalue == &xtunk.IUnknown_iface, "Got %p instead of %p\n", gotvalue, &xtunk.IUnknown_iface); 1298 hres = SafeArrayDestroy(sa); 1299 ok(hres == S_OK, "got 0x%08x\n", hres); 1300 ok(xtunk.ref == 2,"Failed to decrement refcount of iface.\n"); 1301 } 1302 1303 static void test_SafeArrayRedim_IUnknown(void) 1304 { 1305 SAFEARRAYBOUND sab; 1306 LONG indices[1]; 1307 SAFEARRAY *sa; 1308 HRESULT hres; 1309 1310 sab.lLbound = 1; 1311 sab.cElements = 2; 1312 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab); 1313 ok(sa != NULL, "UNKNOWN test couldn't create array\n"); 1314 if (!sa) 1315 return; 1316 1317 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n"); 1318 1319 indices[0] = 2; 1320 xtunk.ref = 1; 1321 hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface); 1322 ok(hres == S_OK, "Failed to put IUnknown element hres 0x%x\n", hres); 1323 ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n"); 1324 sab.cElements = 1; 1325 hres = SafeArrayRedim(sa, &sab); 1326 ok(hres == S_OK, "Failed to shrink array hres 0x%x\n", hres); 1327 ok(xtunk.ref == 1, "Failed to decrement refcount\n"); 1328 hres = SafeArrayDestroy(sa); 1329 ok(hres == S_OK, "got 0x%08x\n", hres); 1330 } 1331 1332 static void test_SafeArrayGetPutElement_VARIANT(void) 1333 { 1334 SAFEARRAYBOUND sab; 1335 LONG indices[1]; 1336 SAFEARRAY *sa; 1337 HRESULT hres; 1338 VARIANT value, gotvalue; 1339 1340 sab.lLbound = 1; 1341 sab.cElements = 1; 1342 sa = SafeArrayCreate(VT_VARIANT, 1, &sab); 1343 ok(sa != NULL, "VARIANT test couldn't create array\n"); 1344 if (!sa) 1345 return; 1346 1347 ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n"); 1348 1349 indices[0] = sab.lLbound; 1350 V_VT(&value) = VT_I4; 1351 V_I4(&value) = 0x42424242; 1352 hres = SafeArrayPutElement(sa, indices, &value); 1353 ok(hres == S_OK, "Failed to put Variant I4 element hres 0x%x\n", hres); 1354 1355 V_VT(&gotvalue) = 0xdead; 1356 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1357 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres); 1358 1359 V_VT(&gotvalue) = VT_EMPTY; 1360 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1361 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres); 1362 if (hres == S_OK) { 1363 ok(V_VT(&value) == V_VT(&gotvalue), "Got type 0x%x instead of 0x%x\n", V_VT(&value), V_VT(&gotvalue)); 1364 if (V_VT(&value) == V_VT(&gotvalue)) 1365 ok(V_I4(&value) == V_I4(&gotvalue), "Got %d instead of %d\n", V_I4(&value), V_VT(&gotvalue)); 1366 } 1367 hres = SafeArrayDestroy(sa); 1368 ok(hres == S_OK, "got 0x%08x\n", hres); 1369 } 1370 1371 static void test_SafeArrayCopyData(void) 1372 { 1373 SAFEARRAYBOUND sab[4]; 1374 SAFEARRAY *sa; 1375 SAFEARRAY *sacopy; 1376 HRESULT hres; 1377 int dimension, size = 1, i; 1378 1379 if (!pSafeArrayCopyData) 1380 { 1381 win_skip("SafeArrayCopyData not supported\n"); 1382 return; 1383 } 1384 1385 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++) 1386 { 1387 sab[dimension].lLbound = dimension * 2 + 2; 1388 sab[dimension].cElements = dimension * 3 + 1; 1389 size *= sab[dimension].cElements; 1390 } 1391 1392 sa = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab); 1393 ok(sa != NULL, "Copy test couldn't create array\n"); 1394 sacopy = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab); 1395 ok(sacopy != NULL, "Copy test couldn't create copy array\n"); 1396 1397 if (!sa || !sacopy) 1398 return; 1399 1400 ok(sa->cbElements == sizeof(int), "int size mismatch\n"); 1401 1402 /* Fill the source array with some data; it doesn't matter what */ 1403 for (dimension = 0; dimension < size; dimension++) 1404 { 1405 int* data = sa->pvData; 1406 data[dimension] = dimension; 1407 } 1408 1409 hres = pSafeArrayCopyData(sa, sacopy); 1410 ok(hres == S_OK, "copy data failed hres 0x%x\n", hres); 1411 if (hres == S_OK) 1412 { 1413 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n"); 1414 } 1415 1416 /* Failure cases */ 1417 hres = pSafeArrayCopyData(NULL, sacopy); 1418 ok(hres == E_INVALIDARG, "Null copy source hres 0x%x\n", hres); 1419 hres = pSafeArrayCopyData(sa, NULL); 1420 ok(hres == E_INVALIDARG, "Null copy hres 0x%x\n", hres); 1421 1422 sacopy->rgsabound[0].cElements += 1; 1423 hres = pSafeArrayCopyData(sa, sacopy); 1424 ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%x\n", hres); 1425 1426 sacopy->rgsabound[0].cElements -= 2; 1427 hres = pSafeArrayCopyData(sa, sacopy); 1428 ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%x\n", hres); 1429 sacopy->rgsabound[0].cElements += 1; 1430 1431 sacopy->rgsabound[3].cElements += 1; 1432 hres = pSafeArrayCopyData(sa, sacopy); 1433 ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%x\n", hres); 1434 1435 sacopy->rgsabound[3].cElements -= 2; 1436 hres = pSafeArrayCopyData(sa, sacopy); 1437 ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%x\n", hres); 1438 sacopy->rgsabound[3].cElements += 1; 1439 1440 hres = SafeArrayDestroy(sacopy); 1441 ok(hres == S_OK, "got 0x%08x\n", hres); 1442 sacopy = NULL; 1443 hres = pSafeArrayCopyData(sa, sacopy); 1444 ok(hres == E_INVALIDARG, "->Null copy hres 0x%x\n", hres); 1445 1446 hres = SafeArrayCopy(sa, &sacopy); 1447 ok(hres == S_OK, "copy failed hres 0x%x\n", hres); 1448 ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n"); 1449 ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n"); 1450 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n"); 1451 hres = SafeArrayDestroy(sacopy); 1452 ok(hres == S_OK, "got 0x%08x\n", hres); 1453 1454 sacopy = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab); 1455 ok(sacopy != NULL, "Copy test couldn't create copy array\n"); 1456 ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures); 1457 1458 for (i = 0; i < ARRAY_SIZE(ignored_copy_features); i++) 1459 { 1460 USHORT feature = ignored_copy_features[i]; 1461 USHORT orig = sacopy->fFeatures; 1462 1463 sa->fFeatures |= feature; 1464 hres = SafeArrayCopyData(sa, sacopy); 1465 ok(hres == S_OK, "got 0x%08x\n", hres); 1466 ok(sacopy->fFeatures == orig && orig == FADF_HAVEVARTYPE, "got features 0x%04x\n", sacopy->fFeatures); 1467 sa->fFeatures &= ~feature; 1468 } 1469 1470 hres = SafeArrayDestroy(sacopy); 1471 ok(hres == S_OK, "got 0x%08x\n", hres); 1472 hres = SafeArrayDestroy(sa); 1473 ok(hres == S_OK, "got 0x%08x\n", hres); 1474 1475 /* copy data from a vector */ 1476 sa = SafeArrayCreateVector(VT_UI1, 0, 2); 1477 1478 sacopy = SafeArrayCreateVector(VT_UI1, 0, 2); 1479 ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) || 1480 broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */), 1481 "got 0x%08x\n", sa->fFeatures); 1482 ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) || 1483 broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */), 1484 "got 0x%08x\n", sacopy->fFeatures); 1485 hres = SafeArrayCopyData(sa, sacopy); 1486 ok(hres == S_OK, "got 0x%08x\n", hres); 1487 ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) || 1488 broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */), 1489 "got 0x%04x\n", sacopy->fFeatures); 1490 SafeArrayDestroy(sacopy); 1491 1492 sacopy = SafeArrayCreate(VT_UI1, ARRAY_SIZE(sab), sab); 1493 ok(sacopy != NULL, "Copy test couldn't create copy array\n"); 1494 ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures); 1495 hres = SafeArrayCopyData(sa, sacopy); 1496 ok(hres == E_INVALIDARG, "got 0x%08x\n", hres); 1497 SafeArrayDestroy(sacopy); 1498 1499 SafeArrayDestroy(sa); 1500 } 1501 1502 static void test_SafeArrayCreateEx(void) 1503 { 1504 IRecordInfoImpl* iRec; 1505 SAFEARRAYBOUND sab[4]; 1506 SAFEARRAY *sa; 1507 HRESULT hres; 1508 UINT dimension; 1509 1510 if (!pSafeArrayCreateEx) 1511 { 1512 win_skip("SafeArrayCreateEx not supported\n"); 1513 return; 1514 } 1515 1516 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++) 1517 { 1518 sab[dimension].lLbound = 0; 1519 sab[dimension].cElements = 8; 1520 } 1521 1522 /* Failure cases */ 1523 sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL); 1524 ok(sa == NULL, "CreateEx NULL bounds didn't fail\n"); 1525 1526 /* test IID storage & defaulting */ 1527 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo); 1528 ok(sa != NULL, "CreateEx (ITypeInfo) failed\n"); 1529 1530 if (sa) 1531 { 1532 GUID guid; 1533 1534 hres = SafeArrayGetIID(sa, &guid); 1535 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres); 1536 ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n"); 1537 hres = SafeArraySetIID(sa, &IID_IUnknown); 1538 ok(hres == S_OK, "Failed to set IID, hres = %8x\n", hres); 1539 hres = SafeArrayGetIID(sa, &guid); 1540 ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n"); 1541 hres = SafeArrayDestroy(sa); 1542 ok(hres == S_OK, "got 0x%08x\n", hres); 1543 } 1544 1545 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL); 1546 ok(sa != NULL, "CreateEx (NULL) failed\n"); 1547 1548 if (sa) 1549 { 1550 GUID guid; 1551 1552 hres = SafeArrayGetIID(sa, &guid); 1553 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres); 1554 ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n"); 1555 hres = SafeArrayDestroy(sa); 1556 ok(hres == S_OK, "got 0x%08x\n", hres); 1557 } 1558 1559 sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL); 1560 ok(sa != NULL, "CreateEx (NULL-Unk) failed\n"); 1561 1562 if (sa) 1563 { 1564 GUID guid; 1565 1566 hres = SafeArrayGetIID(sa, &guid); 1567 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres); 1568 ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n"); 1569 hres = SafeArrayDestroy(sa); 1570 ok(hres == S_OK, "got 0x%08x\n", hres); 1571 } 1572 1573 /* VT_RECORD failure case */ 1574 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL); 1575 ok(sa == NULL, "CreateEx (NULL-Rec) succeeded\n"); 1576 1577 iRec = IRecordInfoImpl_Construct(); 1578 1579 /* Win32 doesn't care if GetSize fails */ 1580 fail_GetSize = TRUE; 1581 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface); 1582 ok(sa != NULL, "CreateEx (Fail Size) failed\n"); 1583 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref); 1584 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled); 1585 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled); 1586 if (sa) 1587 { 1588 ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %d\n", sa->cbElements); 1589 hres = SafeArrayDestroy(sa); 1590 ok(hres == S_OK, "got 0x%08x\n", hres); 1591 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled); 1592 ok(iRec->ref == START_REF_COUNT, "got %d, expected %d\n", iRec->ref, START_REF_COUNT); 1593 } 1594 1595 /* Test VT_RECORD array */ 1596 fail_GetSize = FALSE; 1597 iRec->ref = START_REF_COUNT; 1598 iRec->sizeCalled = 0; 1599 iRec->clearCalled = 0; 1600 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface); 1601 ok(sa != NULL, "CreateEx (Rec) failed\n"); 1602 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref); 1603 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled); 1604 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled); 1605 if (sa && pSafeArrayGetRecordInfo) 1606 { 1607 IRecordInfo* saRec = NULL; 1608 SAFEARRAY *sacopy; 1609 1610 hres = pSafeArrayGetRecordInfo(sa, &saRec); 1611 ok(hres == S_OK,"GRI failed\n"); 1612 ok(saRec == &iRec->IRecordInfo_iface, "Different saRec\n"); 1613 ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %d\n", iRec->ref); 1614 IRecordInfo_Release(saRec); 1615 1616 ok(sa->cbElements == RECORD_SIZE,"Elemsize is %d\n", sa->cbElements); 1617 1618 /* try to copy record based arrays */ 1619 sacopy = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface); 1620 iRec->recordcopy = 0; 1621 iRec->clearCalled = 0; 1622 /* array copy code doesn't explicitly clear a record */ 1623 hres = SafeArrayCopyData(sa, sacopy); 1624 ok(hres == S_OK, "got 0x%08x\n", hres); 1625 ok(iRec->recordcopy == sab[0].cElements, "got %d\n", iRec->recordcopy); 1626 ok(iRec->clearCalled == 0, "got %d\n", iRec->clearCalled); 1627 1628 hres = SafeArrayDestroy(sacopy); 1629 ok(hres == S_OK, "got 0x%08x\n", hres); 1630 1631 iRec->clearCalled = 0; 1632 iRec->sizeCalled = 0; 1633 hres = SafeArrayDestroy(sa); 1634 ok(hres == S_OK, "got 0x%08x\n", hres); 1635 ok(iRec->sizeCalled == 0, "Destroy->GetSize called %d times\n", iRec->sizeCalled); 1636 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled); 1637 ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %d\n", iRec->ref); 1638 } 1639 else 1640 { 1641 hres = SafeArrayDestroy(sa); 1642 ok(hres == S_OK, "got 0x%08x\n", hres); 1643 } 1644 1645 IRecordInfo_Release(&iRec->IRecordInfo_iface); 1646 } 1647 1648 static void test_SafeArrayClear(void) 1649 { 1650 SAFEARRAYBOUND sab; 1651 SAFEARRAY *sa; 1652 VARIANTARG v; 1653 HRESULT hres; 1654 1655 sab.lLbound = 0; 1656 sab.cElements = 10; 1657 sa = SafeArrayCreate(VT_UI1, 1, &sab); 1658 ok(sa != NULL, "Create() failed.\n"); 1659 if (!sa) 1660 return; 1661 1662 /* Test clearing non-NULL variants containing arrays */ 1663 V_VT(&v) = VT_ARRAY|VT_UI1; 1664 V_ARRAY(&v) = sa; 1665 hres = VariantClear(&v); 1666 ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%x, Type %d\n", hres, V_VT(&v)); 1667 ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n"); 1668 1669 sa = SafeArrayCreate(VT_UI1, 1, &sab); 1670 ok(sa != NULL, "Create() failed.\n"); 1671 if (!sa) 1672 return; 1673 1674 V_VT(&v) = VT_SAFEARRAY; 1675 V_ARRAY(&v) = sa; 1676 hres = VariantClear(&v); 1677 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres); 1678 1679 V_VT(&v) = VT_SAFEARRAY|VT_BYREF; 1680 V_ARRAYREF(&v) = &sa; 1681 hres = VariantClear(&v); 1682 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres); 1683 1684 hres = SafeArrayDestroy(sa); 1685 ok(hres == S_OK, "got 0x%08x\n", hres); 1686 } 1687 1688 static void test_SafeArrayCopy(void) 1689 { 1690 SAFEARRAYBOUND sab; 1691 SAFEARRAY *sa, *sa2; 1692 VARIANTARG vSrc, vDst; 1693 HRESULT hres; 1694 int i; 1695 1696 sab.lLbound = 0; 1697 sab.cElements = 10; 1698 sa = SafeArrayCreate(VT_UI1, 1, &sab); 1699 ok(sa != NULL, "Create() failed.\n"); 1700 if (!sa) 1701 return; 1702 1703 /* Test copying non-NULL variants containing arrays */ 1704 V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1); 1705 V_ARRAYREF(&vSrc) = &sa; 1706 V_VT(&vDst) = VT_EMPTY; 1707 1708 hres = VariantCopy(&vDst, &vSrc); 1709 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1), 1710 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst)); 1711 ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n"); 1712 1713 V_VT(&vSrc) = (VT_ARRAY|VT_UI1); 1714 V_ARRAY(&vSrc) = sa; 1715 V_VT(&vDst) = VT_EMPTY; 1716 1717 hres = VariantCopy(&vDst, &vSrc); 1718 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1), 1719 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst)); 1720 ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n"); 1721 1722 hres = SafeArrayDestroy(V_ARRAY(&vSrc)); 1723 ok(hres == S_OK, "got 0x%08x\n", hres); 1724 hres = SafeArrayDestroy(V_ARRAY(&vDst)); 1725 ok(hres == S_OK, "got 0x%08x\n", hres); 1726 1727 hres = SafeArrayAllocDescriptor(1, &sa); 1728 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres); 1729 1730 sa->cbElements = 16; 1731 hres = SafeArrayCopy(sa, &sa2); 1732 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres); 1733 ok(sa != sa2, "SafeArrayCopy performed shallow copy\n"); 1734 1735 hres = SafeArrayDestroy(sa2); 1736 ok(hres == S_OK, "got 0x%08x\n", hres); 1737 hres = SafeArrayDestroy(sa); 1738 ok(hres == S_OK, "got 0x%08x\n", hres); 1739 1740 sa2 = (void*)0xdeadbeef; 1741 hres = SafeArrayCopy(NULL, &sa2); 1742 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres); 1743 ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n"); 1744 1745 hres = SafeArrayAllocDescriptor(1, &sa); 1746 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres); 1747 1748 sa2 = (void*)0xdeadbeef; 1749 hres = SafeArrayCopy(sa, &sa2); 1750 ok(hres == E_INVALIDARG, 1751 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n", 1752 hres); 1753 ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n"); 1754 1755 hres = SafeArrayDestroy(sa2); 1756 ok(hres == S_OK, "got 0x%08x\n", hres); 1757 hres = SafeArrayDestroy(sa); 1758 ok(hres == S_OK, "got 0x%08x\n", hres); 1759 1760 /* test feature copy */ 1761 hres = SafeArrayAllocDescriptor(1, &sa); 1762 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres); 1763 ok(sa->fFeatures == 0, "got src features 0x%04x\n", sa->fFeatures); 1764 sa->cbElements = 16; 1765 1766 for (i = 0; i < ARRAY_SIZE(ignored_copy_features); i++) 1767 { 1768 USHORT feature = ignored_copy_features[i]; 1769 1770 sa->fFeatures |= feature; 1771 hres = SafeArrayCopy(sa, &sa2); 1772 ok(hres == S_OK, "got 0x%08x\n", hres); 1773 ok(sa2->fFeatures == 0, "got features 0x%04x\n", sa2->fFeatures); 1774 hres = SafeArrayDestroy(sa2); 1775 ok(hres == S_OK, "got 0x%08x\n", hres); 1776 sa->fFeatures &= ~feature; 1777 } 1778 1779 SafeArrayDestroy(sa); 1780 1781 /* copy from a vector */ 1782 sa = SafeArrayCreateVector(VT_UI1, 0, 2); 1783 ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) || 1784 broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */), 1785 "got 0x%08x\n", sa->fFeatures); 1786 hres = SafeArrayCopy(sa, &sa2); 1787 ok(hres == S_OK, "got 0x%08x\n", hres); 1788 ok(sa2->fFeatures == FADF_HAVEVARTYPE || 1789 broken(!sa2->fFeatures /* W2k */), "got 0x%04x\n", 1790 sa2->fFeatures); 1791 1792 SafeArrayDestroy(sa2); 1793 SafeArrayDestroy(sa); 1794 } 1795 1796 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \ 1797 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \ 1798 if (!sa) return; \ 1799 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2) 1800 1801 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \ 1802 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \ 1803 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2) 1804 1805 static void test_SafeArrayChangeTypeEx(void) 1806 { 1807 static const char *szHello = "Hello World"; 1808 SAFEARRAYBOUND sab; 1809 SAFEARRAY *sa; 1810 VARIANTARG v,v2; 1811 VARTYPE vt; 1812 HRESULT hres; 1813 1814 /* VT_ARRAY|VT_UI1 -> VT_BSTR */ 1815 MKARRAY(0,strlen(szHello)+1,VT_UI1); 1816 memcpy(sa->pvData, szHello, strlen(szHello)+1); 1817 1818 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR); 1819 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres); 1820 if (hres == S_OK) 1821 { 1822 ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2)); 1823 ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello, 1824 (char*)V_BSTR(&v2)); 1825 VariantClear(&v2); 1826 } 1827 1828 /* VT_VECTOR|VT_UI1 -> VT_BSTR */ 1829 hres = SafeArrayDestroy(sa); 1830 ok(hres == S_OK, "got 0x%08x\n", hres); 1831 if (pSafeArrayCreateVector) 1832 { 1833 sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1); 1834 ok(sa != NULL, "CreateVector() failed.\n"); 1835 if (!sa) 1836 return; 1837 1838 memcpy(sa->pvData, szHello, strlen(szHello)+1); 1839 V_VT(&v) = VT_VECTOR|VT_UI1; 1840 V_ARRAY(&v) = sa; 1841 VariantInit(&v2); 1842 1843 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR); 1844 ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres); 1845 1846 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */ 1847 V_VT(&v) = VT_ARRAY|VT_UI1; 1848 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR); 1849 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres); 1850 if (hres == S_OK) 1851 { 1852 ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v)); 1853 ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello, 1854 (char*)V_BSTR(&v)); 1855 VariantClear(&v); 1856 } 1857 } 1858 1859 /* To/from BSTR only works with arrays of VT_UI1 */ 1860 for (vt = VT_EMPTY; vt <= VT_CLSID; vt++) 1861 { 1862 if (vt == VT_UI1) 1863 continue; 1864 1865 sab.lLbound = 0; 1866 sab.cElements = 1; 1867 sa = SafeArrayCreate(vt, 1, &sab); 1868 if (!sa) continue; 1869 1870 V_VT(&v) = VT_ARRAY|vt; 1871 V_ARRAY(&v) = sa; 1872 VariantInit(&v2); 1873 1874 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR); 1875 if (vt == VT_INT_PTR || vt == VT_UINT_PTR) 1876 { 1877 ok(hres == DISP_E_BADVARTYPE, "expected DISP_E_BADVARTYPE, got 0x%08x\n", hres); 1878 SafeArrayDestroy(sa); 1879 } 1880 else 1881 { 1882 ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x for vt=%d, instead of DISP_E_TYPEMISMATCH\n", hres, vt); 1883 hres = VariantClear(&v); 1884 ok(hres == S_OK, "expected S_OK, got 0x%08x\n", hres); 1885 } 1886 VariantClear(&v2); 1887 } 1888 1889 /* Can't change an array of one type into array of another type , even 1890 * if the other type is the same size 1891 */ 1892 if (pSafeArrayCreateVector) 1893 { 1894 sa = pSafeArrayCreateVector(VT_UI1, 0, 1); 1895 ok(sa != NULL, "CreateVector() failed.\n"); 1896 if (!sa) 1897 return; 1898 1899 V_VT(&v) = VT_ARRAY|VT_UI1; 1900 V_ARRAY(&v) = sa; 1901 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1); 1902 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres); 1903 1904 /* But can change to the same array type */ 1905 hres = SafeArrayDestroy(sa); 1906 ok(hres == S_OK, "got 0x%08x\n", hres); 1907 sa = pSafeArrayCreateVector(VT_UI1, 0, 1); 1908 ok(sa != NULL, "CreateVector() failed.\n"); 1909 if (!sa) 1910 return; 1911 V_VT(&v) = VT_ARRAY|VT_UI1; 1912 V_ARRAY(&v) = sa; 1913 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1); 1914 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres); 1915 hres = SafeArrayDestroy(sa); 1916 ok(hres == S_OK, "got 0x%08x\n", hres); 1917 VariantClear(&v2); 1918 } 1919 1920 /* NULL/EMPTY */ 1921 MKARRAY(0,1,VT_UI1); 1922 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL); 1923 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres); 1924 VariantClear(&v); 1925 MKARRAY(0,1,VT_UI1); 1926 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY); 1927 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres); 1928 VariantClear(&v); 1929 } 1930 1931 static void test_SafeArrayDestroyData (void) 1932 { 1933 SAFEARRAYBOUND sab[2]; 1934 SAFEARRAY *sa; 1935 HRESULT hres; 1936 int value = 0xdeadbeef; 1937 LONG index[1]; 1938 void *temp_pvData; 1939 USHORT features; 1940 1941 sab[0].lLbound = 0; 1942 sab[0].cElements = 10; 1943 sa = SafeArrayCreate(VT_INT, 1, sab); 1944 ok(sa != NULL, "Create() failed.\n"); 1945 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures); 1946 1947 index[0] = 1; 1948 SafeArrayPutElement (sa, index, &value); 1949 1950 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */ 1951 features = (sa->fFeatures |= FADF_STATIC); 1952 temp_pvData = sa->pvData; 1953 hres = SafeArrayDestroyData(sa); 1954 ok(hres == S_OK, "SADData FADF_STATIC failed, error code %x.\n",hres); 1955 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures); 1956 ok(sa->pvData == temp_pvData, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n", 1957 sa->pvData, temp_pvData, sa->fFeatures); 1958 SafeArrayGetElement (sa, index, &value); 1959 ok(value == 0, "Data not cleared after SADData\n"); 1960 1961 /* Clear FADF_STATIC, now really destroy the data. */ 1962 features = (sa->fFeatures ^= FADF_STATIC); 1963 hres = SafeArrayDestroyData(sa); 1964 ok(hres == S_OK, "SADData !FADF_STATIC failed, error code %x.\n",hres); 1965 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures); 1966 ok(sa->pvData == NULL, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa->pvData); 1967 1968 hres = SafeArrayDestroy(sa); 1969 ok(hres == S_OK, "SAD failed, error code %x.\n", hres); 1970 1971 /* two dimensions */ 1972 sab[0].lLbound = 0; 1973 sab[0].cElements = 10; 1974 sab[1].lLbound = 0; 1975 sab[1].cElements = 10; 1976 1977 sa = SafeArrayCreate(VT_INT, 2, sab); 1978 ok(sa != NULL, "Create() failed.\n"); 1979 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures); 1980 1981 features = sa->fFeatures; 1982 hres = SafeArrayDestroyData(sa); 1983 ok(hres == S_OK, "got 0x%08x\n",hres); 1984 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures); 1985 1986 SafeArrayDestroy(sa); 1987 1988 /* try to destroy data from descriptor */ 1989 hres = SafeArrayAllocDescriptor(1, &sa); 1990 ok(hres == S_OK, "got 0x%08x\n", hres); 1991 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures); 1992 1993 hres = SafeArrayDestroyData(sa); 1994 ok(hres == S_OK, "got 0x%08x\n", hres); 1995 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures); 1996 1997 hres = SafeArrayDestroyDescriptor(sa); 1998 ok(hres == S_OK, "got 0x%08x\n", hres); 1999 2000 hres = SafeArrayAllocDescriptor(2, &sa); 2001 ok(hres == S_OK, "got 0x%08x\n", hres); 2002 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures); 2003 2004 hres = SafeArrayDestroyData(sa); 2005 ok(hres == S_OK, "got 0x%08x\n", hres); 2006 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures); 2007 2008 hres = SafeArrayDestroyDescriptor(sa); 2009 ok(hres == S_OK, "got 0x%08x\n", hres); 2010 2011 /* vector case */ 2012 sa = SafeArrayCreateVector(VT_I4, 0, 10); 2013 ok(sa != NULL, "got %p\n", sa); 2014 ok(sa->fFeatures == (FADF_CREATEVECTOR|FADF_HAVEVARTYPE), "got 0x%x\n", sa->fFeatures); 2015 2016 ok(sa->pvData != NULL, "got %p\n", sa->pvData); 2017 hres = SafeArrayDestroyData(sa); 2018 ok(hres == S_OK, "got 0x%08x\n", hres); 2019 todo_wine 2020 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures); 2021 todo_wine 2022 ok(sa->pvData == NULL || broken(sa->pvData != NULL), "got %p\n", sa->pvData); 2023 /* There was a bug on windows, especially visible on 64bit systems, 2024 probably double-free or similar issue. */ 2025 sa->pvData = NULL; 2026 SafeArrayDestroy(sa); 2027 } 2028 2029 static void test_safearray_layout(void) 2030 { 2031 IRecordInfoImpl *irec; 2032 IRecordInfo *record; 2033 GUID guid, *guidptr; 2034 SAFEARRAYBOUND sab; 2035 SAFEARRAY *sa; 2036 DWORD *dwptr; 2037 HRESULT hr; 2038 2039 sab.lLbound = 0; 2040 sab.cElements = 10; 2041 2042 /* GUID field */ 2043 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab); 2044 ok(sa != NULL, "got %p\n", sa); 2045 2046 guidptr = (GUID*)sa - 1; 2047 ok(IsEqualIID(guidptr, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(guidptr)); 2048 2049 hr = SafeArraySetIID(sa, &IID_IDispatch); 2050 ok(hr == S_OK, "got 0x%08x\n", hr); 2051 ok(IsEqualIID(guidptr, &IID_IDispatch), "got %s\n", wine_dbgstr_guid(guidptr)); 2052 2053 memcpy(guidptr, &IID_IUnknown, sizeof(GUID)); 2054 hr = SafeArrayGetIID(sa, &guid); 2055 ok(hr == S_OK, "got 0x%08x\n", hr); 2056 ok(IsEqualIID(&guid, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(&guid)); 2057 2058 hr = SafeArrayDestroy(sa); 2059 ok(hr == S_OK, "got 0x%08x\n", hr); 2060 2061 /* VARTYPE field */ 2062 sa = SafeArrayCreate(VT_UI1, 1, &sab); 2063 ok(sa != NULL, "got %p\n", sa); 2064 2065 dwptr = (DWORD*)sa - 1; 2066 ok(*dwptr == VT_UI1, "got %d\n", *dwptr); 2067 2068 hr = SafeArrayDestroy(sa); 2069 ok(hr == S_OK, "got 0x%08x\n", hr); 2070 2071 /* IRecordInfo pointer */ 2072 irec = IRecordInfoImpl_Construct(); 2073 irec->ref = 1; 2074 2075 sa = pSafeArrayCreateEx(VT_RECORD, 1, &sab, &irec->IRecordInfo_iface); 2076 ok(sa != NULL, "failed to create array\n"); 2077 2078 record = *((IRecordInfo**)sa - 1); 2079 ok(record == &irec->IRecordInfo_iface, "got %p\n", record); 2080 2081 hr = SafeArrayDestroy(sa); 2082 ok(hr == S_OK, "got 0x%08x\n", hr); 2083 IRecordInfo_Release(&irec->IRecordInfo_iface); 2084 } 2085 2086 START_TEST(safearray) 2087 { 2088 hOleaut32 = GetModuleHandleA("oleaut32.dll"); 2089 2090 has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL; 2091 2092 GETPTR(SafeArrayAllocDescriptorEx); 2093 GETPTR(SafeArrayCopyData); 2094 GETPTR(SafeArrayGetVartype); 2095 GETPTR(SafeArrayCreateEx); 2096 GETPTR(SafeArrayCreateVector); 2097 GETPTR(SafeArrayGetRecordInfo); 2098 2099 check_for_VT_INT_PTR(); 2100 test_safearray(); 2101 test_SafeArrayAllocDestroyDescriptor(); 2102 test_SafeArrayCreateLockDestroy(); 2103 test_VectorCreateLockDestroy(); 2104 test_LockUnlock(); 2105 test_SafeArrayChangeTypeEx(); 2106 test_SafeArrayCopy(); 2107 test_SafeArrayClear(); 2108 test_SafeArrayCreateEx(); 2109 test_SafeArrayCopyData(); 2110 test_SafeArrayDestroyData(); 2111 test_SafeArrayGetPutElement(); 2112 test_SafeArrayGetPutElement_BSTR(); 2113 test_SafeArrayGetPutElement_IUnknown(); 2114 test_SafeArrayRedim_IUnknown(); 2115 test_SafeArrayGetPutElement_VARIANT(); 2116 test_safearray_layout(); 2117 } 2118