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<sizeof(vttypes)/sizeof(vttypes[0]);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 < sizeof(vttypes)/sizeof(vttypes[0]); 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 int 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) == (UINT)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 int dimension; 832 833 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0])) 834 835 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++) 836 { 837 sab[dimension].lLbound = 0; 838 sab[dimension].cElements = 8; 839 } 840 841 /* Failure cases */ 842 /* This test crashes very early versions with no error checking... 843 sa = SafeArrayCreate(VT_UI1, 1, NULL); 844 ok(sa == NULL, "NULL bounds didn't fail\n"); 845 */ 846 sa = SafeArrayCreate(VT_UI1, 65536, sab); 847 ok(!sa, "Max bounds didn't fail\n"); 848 849 memset(sab, 0, sizeof(sab)); 850 851 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */ 852 853 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++) 854 sab[dimension].cElements = 8; 855 856 /* Test all VARTYPES in 1-4 dimensions */ 857 for (dimension = 1; dimension < 4; dimension++) 858 { 859 for (vt = VT_EMPTY; vt < VT_CLSID; vt++) 860 { 861 DWORD dwLen = SAFEARRAY_GetVTSize(vt); 862 863 sa = SafeArrayCreate(vt, dimension, sab); 864 865 if (dwLen) 866 ok(sa != NULL, "VARTYPE %d (@%d dimensions) failed\n", vt, dimension); 867 else 868 ok(sa == NULL || vt == VT_R8, 869 "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension); 870 871 if (sa) 872 { 873 ok(SafeArrayGetDim(sa) == (UINT)dimension, 874 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n", 875 vt, dimension, SafeArrayGetDim(sa), dimension); 876 ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8, 877 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n", 878 vt, dimension, SafeArrayGetElemsize(sa), dwLen); 879 880 if (vt != VT_UNKNOWN && vt != VT_DISPATCH) 881 { 882 ok((sa->fFeatures & FADF_HAVEIID) == 0, 883 "Non interface type should not have FADF_HAVEIID\n"); 884 hres = SafeArraySetIID(sa, &IID_IUnknown); 885 ok(hres == E_INVALIDARG, "Unexpected ret value %#x.\n", hres); 886 if (vt != VT_RECORD) 887 { 888 VARTYPE aVt; 889 890 ok(sa->fFeatures & FADF_HAVEVARTYPE, 891 "Non interface type should have FADF_HAVEVARTYPE\n"); 892 if (pSafeArrayGetVartype) 893 { 894 hres = pSafeArrayGetVartype(sa, &aVt); 895 ok(hres == S_OK && aVt == vt, 896 "Non interface type %d: bad type %d, hres %x\n", vt, aVt, hres); 897 } 898 } 899 } 900 else 901 { 902 ok(sa->fFeatures & FADF_HAVEIID, "Interface type should have FADF_HAVEIID\n"); 903 hres = SafeArraySetIID(sa, &IID_IUnknown); 904 ok(hres == S_OK, "Failed to set array IID, hres %#x.\n", hres); 905 ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0, 906 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt); 907 } 908 909 hres = SafeArrayLock(sa); 910 ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n", 911 vt, dimension, hres); 912 913 if (hres == S_OK) 914 { 915 hres = SafeArrayDestroy(sa); 916 ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %x\n", hres); 917 918 hres = SafeArrayDestroyData(sa); 919 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %x\n", hres); 920 921 hres = SafeArrayDestroyDescriptor(sa); 922 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %x\n", hres); 923 924 hres = SafeArrayUnlock(sa); 925 ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n", 926 vt, dimension, hres); 927 928 hres = SafeArrayDestroy(sa); 929 ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%x\n", 930 vt, dimension, hres); 931 } 932 } 933 } 934 } 935 } 936 937 static void test_VectorCreateLockDestroy(void) 938 { 939 SAFEARRAY *sa; 940 HRESULT hres; 941 VARTYPE vt; 942 int element; 943 944 if (!pSafeArrayCreateVector) 945 { 946 win_skip("SafeArrayCreateVector not supported\n"); 947 return; 948 } 949 sa = pSafeArrayCreateVector(VT_UI1, 0, 0); 950 ok(sa != NULL, "SACV with 0 elements failed.\n"); 951 952 hres = SafeArrayDestroy(sa); 953 ok(hres == S_OK, "SafeArrayDestroy failed with hres %x\n",hres); 954 955 /* Test all VARTYPES in different lengths */ 956 for (element = 1; element <= 101; element += 10) 957 { 958 for (vt = VT_EMPTY; vt < VT_CLSID; vt++) 959 { 960 DWORD dwLen = SAFEARRAY_GetVTSize(vt); 961 962 sa = pSafeArrayCreateVector(vt, 0, element); 963 964 if (dwLen) 965 ok(sa != NULL, "VARTYPE %d (@%d elements) failed\n", vt, element); 966 else 967 ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element); 968 969 if (sa) 970 { 971 ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n", 972 vt, element, SafeArrayGetDim(sa)); 973 ok(SafeArrayGetElemsize(sa) == dwLen, 974 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n", 975 vt, element, SafeArrayGetElemsize(sa), dwLen); 976 977 hres = SafeArrayLock(sa); 978 ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n", 979 vt, element, hres); 980 981 if (hres == S_OK) 982 { 983 hres = SafeArrayUnlock(sa); 984 ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n", 985 vt, element, hres); 986 987 hres = SafeArrayDestroy(sa); 988 ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n", 989 vt, element, hres); 990 } 991 } 992 } 993 } 994 } 995 996 static void test_LockUnlock(void) 997 { 998 SAFEARRAYBOUND sab[4]; 999 SAFEARRAY *sa; 1000 HRESULT hres; 1001 BOOL bVector = FALSE; 1002 int dimension; 1003 1004 /* Failure cases */ 1005 hres = SafeArrayLock(NULL); 1006 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres); 1007 hres = SafeArrayUnlock(NULL); 1008 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres); 1009 1010 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++) 1011 { 1012 sab[dimension].lLbound = 0; 1013 sab[dimension].cElements = 8; 1014 } 1015 1016 sa = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab); 1017 1018 /* Test maximum locks */ 1019 test_LockUnlock_Vector: 1020 if (sa) 1021 { 1022 int count = 0; 1023 1024 hres = SafeArrayUnlock(sa); 1025 ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%x\n", 1026 bVector ? "vector " : "\n", hres); 1027 1028 while ((hres = SafeArrayLock(sa)) == S_OK) 1029 count++; 1030 ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%x\n", 1031 bVector ? "vector " : "\n", count, hres); 1032 1033 if (count == 65535 && hres == E_UNEXPECTED) 1034 { 1035 while ((hres = SafeArrayUnlock(sa)) == S_OK) 1036 count--; 1037 ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%x\n", 1038 bVector ? "vector " : "\n", count, hres); 1039 } 1040 1041 hres = SafeArrayDestroy(sa); 1042 ok(hres == S_OK, "got 0x%08x\n", hres); 1043 } 1044 1045 if (bVector == FALSE && pSafeArrayCreateVector) 1046 { 1047 /* Test again with a vector */ 1048 sa = pSafeArrayCreateVector(VT_UI1, 0, 100); 1049 bVector = TRUE; 1050 goto test_LockUnlock_Vector; 1051 } 1052 } 1053 1054 static void test_SafeArrayGetPutElement(void) 1055 { 1056 SAFEARRAYBOUND sab[4]; 1057 LONG indices[NUM_DIMENSIONS], index; 1058 SAFEARRAY *sa; 1059 HRESULT hres; 1060 int value = 0, gotvalue, dimension; 1061 IRecordInfoImpl *irec; 1062 unsigned int x,y,z,a; 1063 1064 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++) 1065 { 1066 sab[dimension].lLbound = dimension * 2 + 1; 1067 sab[dimension].cElements = dimension * 3 + 1; 1068 } 1069 1070 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab); 1071 if (!sa) 1072 return; /* Some early versions can't handle > 3 dims */ 1073 1074 ok(sa->cbElements == sizeof(value), "int size mismatch\n"); 1075 1076 /* Failure cases */ 1077 for (x = 0; x < NUM_DIMENSIONS; x++) 1078 { 1079 indices[0] = sab[0].lLbound; 1080 indices[1] = sab[1].lLbound; 1081 indices[2] = sab[2].lLbound; 1082 indices[3] = sab[3].lLbound; 1083 1084 indices[x] = indices[x] - 1; 1085 hres = SafeArrayPutElement(sa, indices, &value); 1086 ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x); 1087 hres = SafeArrayGetElement(sa, indices, &value); 1088 ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x); 1089 1090 indices[x] = sab[x].lLbound + sab[x].cElements; 1091 hres = SafeArrayPutElement(sa, indices, &value); 1092 ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x); 1093 hres = SafeArrayGetElement(sa, indices, &value); 1094 ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x); 1095 } 1096 1097 indices[0] = sab[0].lLbound; 1098 indices[1] = sab[1].lLbound; 1099 indices[2] = sab[2].lLbound; 1100 indices[3] = sab[3].lLbound; 1101 1102 hres = SafeArrayPutElement(NULL, indices, &value); 1103 ok(hres == E_INVALIDARG, "Put NULL array hres 0x%x\n", hres); 1104 hres = SafeArrayGetElement(NULL, indices, &value); 1105 ok(hres == E_INVALIDARG, "Get NULL array hres 0x%x\n", hres); 1106 1107 hres = SafeArrayPutElement(sa, NULL, &value); 1108 ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%x\n", hres); 1109 hres = SafeArrayGetElement(sa, NULL, &value); 1110 ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%x\n", hres); 1111 1112 if (0) 1113 { 1114 /* This is retarded. Windows checks every case of invalid parameters 1115 * except the following, which crashes. We ERR this in Wine. 1116 */ 1117 hres = SafeArrayPutElement(sa, indices, NULL); 1118 ok(hres == E_INVALIDARG, "Put NULL value hres 0x%x\n", hres); 1119 } 1120 1121 hres = SafeArrayGetElement(sa, indices, NULL); 1122 ok(hres == E_INVALIDARG, "Get NULL value hres 0x%x\n", hres); 1123 1124 value = 0; 1125 1126 /* Make sure we can read and get back the correct values in 4 dimensions, 1127 * Each with a different size and lower bound. 1128 */ 1129 for (x = 0; x < sab[0].cElements; x++) 1130 { 1131 indices[0] = sab[0].lLbound + x; 1132 for (y = 0; y < sab[1].cElements; y++) 1133 { 1134 indices[1] = sab[1].lLbound + y; 1135 for (z = 0; z < sab[2].cElements; z++) 1136 { 1137 indices[2] = sab[2].lLbound + z; 1138 for (a = 0; a < sab[3].cElements; a++) 1139 { 1140 indices[3] = sab[3].lLbound + a; 1141 hres = SafeArrayPutElement(sa, indices, &value); 1142 ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n", 1143 x, y, z, a, hres); 1144 value++; 1145 } 1146 } 1147 } 1148 } 1149 1150 value = 0; 1151 1152 for (x = 0; x < sab[0].cElements; x++) 1153 { 1154 indices[0] = sab[0].lLbound + x; 1155 for (y = 0; y < sab[1].cElements; y++) 1156 { 1157 indices[1] = sab[1].lLbound + y; 1158 for (z = 0; z < sab[2].cElements; z++) 1159 { 1160 indices[2] = sab[2].lLbound + z; 1161 for (a = 0; a < sab[3].cElements; a++) 1162 { 1163 indices[3] = sab[3].lLbound + a; 1164 gotvalue = value / 3; 1165 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1166 ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n", 1167 x, y, z, a, hres); 1168 if (hres == S_OK) 1169 ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n", 1170 gotvalue, value, x, y, z, a); 1171 value++; 1172 } 1173 } 1174 } 1175 } 1176 hres = SafeArrayDestroy(sa); 1177 ok(hres == S_OK, "got 0x%08x\n", hres); 1178 1179 /* VT_RECORD array */ 1180 irec = IRecordInfoImpl_Construct(); 1181 irec->ref = 1; 1182 1183 sab[0].lLbound = 0; 1184 sab[0].cElements = 8; 1185 1186 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &irec->IRecordInfo_iface); 1187 ok(sa != NULL, "failed to create array\n"); 1188 ok(irec->ref == 2, "got %d\n", irec->ref); 1189 1190 index = 0; 1191 irec->recordcopy = 0; 1192 hres = SafeArrayPutElement(sa, &index, (void*)0xdeadbeef); 1193 ok(hres == S_OK, "got 0x%08x\n", hres); 1194 ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy); 1195 1196 index = 0; 1197 irec->recordcopy = 0; 1198 hres = SafeArrayGetElement(sa, &index, (void*)0xdeadbeef); 1199 ok(hres == S_OK, "got 0x%08x\n", hres); 1200 ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy); 1201 1202 hres = SafeArrayDestroy(sa); 1203 ok(hres == S_OK, "got 0x%08x\n", hres); 1204 ok(irec->ref == 1, "got %d\n", irec->ref); 1205 IRecordInfo_Release(&irec->IRecordInfo_iface); 1206 } 1207 1208 static void test_SafeArrayGetPutElement_BSTR(void) 1209 { 1210 SAFEARRAYBOUND sab; 1211 LONG indices[1]; 1212 SAFEARRAY *sa; 1213 HRESULT hres; 1214 BSTR value = 0, gotvalue; 1215 const OLECHAR szTest[5] = { 'T','e','s','t','\0' }; 1216 1217 sab.lLbound = 1; 1218 sab.cElements = 1; 1219 1220 sa = SafeArrayCreate(VT_BSTR, 1, &sab); 1221 ok(sa != NULL, "BSTR test couldn't create array\n"); 1222 if (!sa) 1223 return; 1224 1225 ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n"); 1226 1227 indices[0] = sab.lLbound; 1228 value = SysAllocString(szTest); 1229 ok (value != NULL, "Expected non-NULL\n"); 1230 hres = SafeArrayPutElement(sa, indices, value); 1231 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres); 1232 gotvalue = NULL; 1233 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1234 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres); 1235 if (hres == S_OK) 1236 ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value)); 1237 hres = SafeArrayDestroy(sa); 1238 ok(hres == S_OK, "got 0x%08x\n", hres); 1239 SysFreeString(value); 1240 SysFreeString(gotvalue); 1241 } 1242 1243 struct xtunk_impl { 1244 IUnknown IUnknown_iface; 1245 LONG ref; 1246 }; 1247 static const IUnknownVtbl xtunk_vtbl; 1248 1249 static struct xtunk_impl xtunk = {{&xtunk_vtbl}, 0}; 1250 1251 static HRESULT WINAPI tunk_QueryInterface(IUnknown *punk, REFIID riid, void **x) 1252 { 1253 return E_FAIL; 1254 } 1255 1256 static ULONG WINAPI tunk_AddRef(IUnknown *punk) 1257 { 1258 return ++xtunk.ref; 1259 } 1260 1261 static ULONG WINAPI tunk_Release(IUnknown *punk) 1262 { 1263 return --xtunk.ref; 1264 } 1265 1266 static const IUnknownVtbl xtunk_vtbl = { 1267 tunk_QueryInterface, 1268 tunk_AddRef, 1269 tunk_Release 1270 }; 1271 1272 static void test_SafeArrayGetPutElement_IUnknown(void) 1273 { 1274 SAFEARRAYBOUND sab; 1275 LONG indices[1]; 1276 SAFEARRAY *sa; 1277 HRESULT hres; 1278 IUnknown *gotvalue; 1279 1280 sab.lLbound = 1; 1281 sab.cElements = 1; 1282 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab); 1283 ok(sa != NULL, "UNKNOWN test couldn't create array\n"); 1284 if (!sa) 1285 return; 1286 1287 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n"); 1288 1289 indices[0] = sab.lLbound; 1290 xtunk.ref = 1; 1291 hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface); 1292 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres); 1293 ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n"); 1294 gotvalue = NULL; 1295 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1296 ok(xtunk.ref == 3,"Failed to increment refcount of iface.\n"); 1297 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres); 1298 if (hres == S_OK) 1299 ok(gotvalue == &xtunk.IUnknown_iface, "Got %p instead of %p\n", gotvalue, &xtunk.IUnknown_iface); 1300 hres = SafeArrayDestroy(sa); 1301 ok(hres == S_OK, "got 0x%08x\n", hres); 1302 ok(xtunk.ref == 2,"Failed to decrement refcount of iface.\n"); 1303 } 1304 1305 static void test_SafeArrayRedim_IUnknown(void) 1306 { 1307 SAFEARRAYBOUND sab; 1308 LONG indices[1]; 1309 SAFEARRAY *sa; 1310 HRESULT hres; 1311 1312 sab.lLbound = 1; 1313 sab.cElements = 2; 1314 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab); 1315 ok(sa != NULL, "UNKNOWN test couldn't create array\n"); 1316 if (!sa) 1317 return; 1318 1319 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n"); 1320 1321 indices[0] = 2; 1322 xtunk.ref = 1; 1323 hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface); 1324 ok(hres == S_OK, "Failed to put IUnknown element hres 0x%x\n", hres); 1325 ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n"); 1326 sab.cElements = 1; 1327 hres = SafeArrayRedim(sa, &sab); 1328 ok(hres == S_OK, "Failed to shrink array hres 0x%x\n", hres); 1329 ok(xtunk.ref == 1, "Failed to decrement refcount\n"); 1330 hres = SafeArrayDestroy(sa); 1331 ok(hres == S_OK, "got 0x%08x\n", hres); 1332 } 1333 1334 static void test_SafeArrayGetPutElement_VARIANT(void) 1335 { 1336 SAFEARRAYBOUND sab; 1337 LONG indices[1]; 1338 SAFEARRAY *sa; 1339 HRESULT hres; 1340 VARIANT value, gotvalue; 1341 1342 sab.lLbound = 1; 1343 sab.cElements = 1; 1344 sa = SafeArrayCreate(VT_VARIANT, 1, &sab); 1345 ok(sa != NULL, "VARIANT test couldn't create array\n"); 1346 if (!sa) 1347 return; 1348 1349 ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n"); 1350 1351 indices[0] = sab.lLbound; 1352 V_VT(&value) = VT_I4; 1353 V_I4(&value) = 0x42424242; 1354 hres = SafeArrayPutElement(sa, indices, &value); 1355 ok(hres == S_OK, "Failed to put Variant I4 element hres 0x%x\n", hres); 1356 1357 V_VT(&gotvalue) = 0xdead; 1358 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1359 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres); 1360 1361 V_VT(&gotvalue) = VT_EMPTY; 1362 hres = SafeArrayGetElement(sa, indices, &gotvalue); 1363 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres); 1364 if (hres == S_OK) { 1365 ok(V_VT(&value) == V_VT(&gotvalue), "Got type 0x%x instead of 0x%x\n", V_VT(&value), V_VT(&gotvalue)); 1366 if (V_VT(&value) == V_VT(&gotvalue)) 1367 ok(V_I4(&value) == V_I4(&gotvalue), "Got %d instead of %d\n", V_I4(&value), V_VT(&gotvalue)); 1368 } 1369 hres = SafeArrayDestroy(sa); 1370 ok(hres == S_OK, "got 0x%08x\n", hres); 1371 } 1372 1373 static void test_SafeArrayCopyData(void) 1374 { 1375 SAFEARRAYBOUND sab[4]; 1376 SAFEARRAY *sa; 1377 SAFEARRAY *sacopy; 1378 HRESULT hres; 1379 int dimension, size = 1, i; 1380 1381 if (!pSafeArrayCopyData) 1382 { 1383 win_skip("SafeArrayCopyData not supported\n"); 1384 return; 1385 } 1386 1387 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++) 1388 { 1389 sab[dimension].lLbound = dimension * 2 + 2; 1390 sab[dimension].cElements = dimension * 3 + 1; 1391 size *= sab[dimension].cElements; 1392 } 1393 1394 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab); 1395 ok(sa != NULL, "Copy test couldn't create array\n"); 1396 sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab); 1397 ok(sacopy != NULL, "Copy test couldn't create copy array\n"); 1398 1399 if (!sa || !sacopy) 1400 return; 1401 1402 ok(sa->cbElements == sizeof(int), "int size mismatch\n"); 1403 1404 /* Fill the source array with some data; it doesn't matter what */ 1405 for (dimension = 0; dimension < size; dimension++) 1406 { 1407 int* data = sa->pvData; 1408 data[dimension] = dimension; 1409 } 1410 1411 hres = pSafeArrayCopyData(sa, sacopy); 1412 ok(hres == S_OK, "copy data failed hres 0x%x\n", hres); 1413 if (hres == S_OK) 1414 { 1415 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n"); 1416 } 1417 1418 /* Failure cases */ 1419 hres = pSafeArrayCopyData(NULL, sacopy); 1420 ok(hres == E_INVALIDARG, "Null copy source hres 0x%x\n", hres); 1421 hres = pSafeArrayCopyData(sa, NULL); 1422 ok(hres == E_INVALIDARG, "Null copy hres 0x%x\n", hres); 1423 1424 sacopy->rgsabound[0].cElements += 1; 1425 hres = pSafeArrayCopyData(sa, sacopy); 1426 ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%x\n", hres); 1427 1428 sacopy->rgsabound[0].cElements -= 2; 1429 hres = pSafeArrayCopyData(sa, sacopy); 1430 ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%x\n", hres); 1431 sacopy->rgsabound[0].cElements += 1; 1432 1433 sacopy->rgsabound[3].cElements += 1; 1434 hres = pSafeArrayCopyData(sa, sacopy); 1435 ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%x\n", hres); 1436 1437 sacopy->rgsabound[3].cElements -= 2; 1438 hres = pSafeArrayCopyData(sa, sacopy); 1439 ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%x\n", hres); 1440 sacopy->rgsabound[3].cElements += 1; 1441 1442 hres = SafeArrayDestroy(sacopy); 1443 ok(hres == S_OK, "got 0x%08x\n", hres); 1444 sacopy = NULL; 1445 hres = pSafeArrayCopyData(sa, sacopy); 1446 ok(hres == E_INVALIDARG, "->Null copy hres 0x%x\n", hres); 1447 1448 hres = SafeArrayCopy(sa, &sacopy); 1449 ok(hres == S_OK, "copy failed hres 0x%x\n", hres); 1450 ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n"); 1451 ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n"); 1452 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n"); 1453 hres = SafeArrayDestroy(sacopy); 1454 ok(hres == S_OK, "got 0x%08x\n", hres); 1455 1456 sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab); 1457 ok(sacopy != NULL, "Copy test couldn't create copy array\n"); 1458 ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures); 1459 1460 for (i = 0; i < sizeof(ignored_copy_features)/sizeof(USHORT); i++) 1461 { 1462 USHORT feature = ignored_copy_features[i]; 1463 USHORT orig = sacopy->fFeatures; 1464 1465 sa->fFeatures |= feature; 1466 hres = SafeArrayCopyData(sa, sacopy); 1467 ok(hres == S_OK, "got 0x%08x\n", hres); 1468 ok(sacopy->fFeatures == orig && orig == FADF_HAVEVARTYPE, "got features 0x%04x\n", sacopy->fFeatures); 1469 sa->fFeatures &= ~feature; 1470 } 1471 1472 hres = SafeArrayDestroy(sacopy); 1473 ok(hres == S_OK, "got 0x%08x\n", hres); 1474 hres = SafeArrayDestroy(sa); 1475 ok(hres == S_OK, "got 0x%08x\n", hres); 1476 1477 /* copy data from a vector */ 1478 sa = SafeArrayCreateVector(VT_UI1, 0, 2); 1479 1480 sacopy = SafeArrayCreateVector(VT_UI1, 0, 2); 1481 ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) || 1482 broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */), 1483 "got 0x%08x\n", sa->fFeatures); 1484 ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) || 1485 broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */), 1486 "got 0x%08x\n", sacopy->fFeatures); 1487 hres = SafeArrayCopyData(sa, sacopy); 1488 ok(hres == S_OK, "got 0x%08x\n", hres); 1489 ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) || 1490 broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */), 1491 "got 0x%04x\n", sacopy->fFeatures); 1492 SafeArrayDestroy(sacopy); 1493 1494 sacopy = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab); 1495 ok(sacopy != NULL, "Copy test couldn't create copy array\n"); 1496 ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures); 1497 hres = SafeArrayCopyData(sa, sacopy); 1498 ok(hres == E_INVALIDARG, "got 0x%08x\n", hres); 1499 SafeArrayDestroy(sacopy); 1500 1501 SafeArrayDestroy(sa); 1502 } 1503 1504 static void test_SafeArrayCreateEx(void) 1505 { 1506 IRecordInfoImpl* iRec; 1507 SAFEARRAYBOUND sab[4]; 1508 SAFEARRAY *sa; 1509 HRESULT hres; 1510 int dimension; 1511 1512 if (!pSafeArrayCreateEx) 1513 { 1514 win_skip("SafeArrayCreateEx not supported\n"); 1515 return; 1516 } 1517 1518 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++) 1519 { 1520 sab[dimension].lLbound = 0; 1521 sab[dimension].cElements = 8; 1522 } 1523 1524 /* Failure cases */ 1525 sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL); 1526 ok(sa == NULL, "CreateEx NULL bounds didn't fail\n"); 1527 1528 /* test IID storage & defaulting */ 1529 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo); 1530 ok(sa != NULL, "CreateEx (ITypeInfo) failed\n"); 1531 1532 if (sa) 1533 { 1534 GUID guid; 1535 1536 hres = SafeArrayGetIID(sa, &guid); 1537 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres); 1538 ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n"); 1539 hres = SafeArraySetIID(sa, &IID_IUnknown); 1540 ok(hres == S_OK, "Failed to set IID, hres = %8x\n", hres); 1541 hres = SafeArrayGetIID(sa, &guid); 1542 ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n"); 1543 hres = SafeArrayDestroy(sa); 1544 ok(hres == S_OK, "got 0x%08x\n", hres); 1545 } 1546 1547 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL); 1548 ok(sa != NULL, "CreateEx (NULL) failed\n"); 1549 1550 if (sa) 1551 { 1552 GUID guid; 1553 1554 hres = SafeArrayGetIID(sa, &guid); 1555 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres); 1556 ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n"); 1557 hres = SafeArrayDestroy(sa); 1558 ok(hres == S_OK, "got 0x%08x\n", hres); 1559 } 1560 1561 sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL); 1562 ok(sa != NULL, "CreateEx (NULL-Unk) failed\n"); 1563 1564 if (sa) 1565 { 1566 GUID guid; 1567 1568 hres = SafeArrayGetIID(sa, &guid); 1569 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres); 1570 ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n"); 1571 hres = SafeArrayDestroy(sa); 1572 ok(hres == S_OK, "got 0x%08x\n", hres); 1573 } 1574 1575 /* VT_RECORD failure case */ 1576 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL); 1577 ok(sa == NULL, "CreateEx (NULL-Rec) succeeded\n"); 1578 1579 iRec = IRecordInfoImpl_Construct(); 1580 1581 /* Win32 doesn't care if GetSize fails */ 1582 fail_GetSize = TRUE; 1583 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface); 1584 ok(sa != NULL, "CreateEx (Fail Size) failed\n"); 1585 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref); 1586 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled); 1587 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled); 1588 if (sa) 1589 { 1590 ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %d\n", sa->cbElements); 1591 hres = SafeArrayDestroy(sa); 1592 ok(hres == S_OK, "got 0x%08x\n", hres); 1593 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled); 1594 ok(iRec->ref == START_REF_COUNT, "got %d, expected %d\n", iRec->ref, START_REF_COUNT); 1595 } 1596 1597 /* Test VT_RECORD array */ 1598 fail_GetSize = FALSE; 1599 iRec->ref = START_REF_COUNT; 1600 iRec->sizeCalled = 0; 1601 iRec->clearCalled = 0; 1602 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface); 1603 ok(sa != NULL, "CreateEx (Rec) failed\n"); 1604 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref); 1605 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled); 1606 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled); 1607 if (sa && pSafeArrayGetRecordInfo) 1608 { 1609 IRecordInfo* saRec = NULL; 1610 SAFEARRAY *sacopy; 1611 1612 hres = pSafeArrayGetRecordInfo(sa, &saRec); 1613 ok(hres == S_OK,"GRI failed\n"); 1614 ok(saRec == &iRec->IRecordInfo_iface, "Different saRec\n"); 1615 ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %d\n", iRec->ref); 1616 IRecordInfo_Release(saRec); 1617 1618 ok(sa->cbElements == RECORD_SIZE,"Elemsize is %d\n", sa->cbElements); 1619 1620 /* try to copy record based arrays */ 1621 sacopy = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface); 1622 iRec->recordcopy = 0; 1623 iRec->clearCalled = 0; 1624 /* array copy code doesn't explicitly clear a record */ 1625 hres = SafeArrayCopyData(sa, sacopy); 1626 ok(hres == S_OK, "got 0x%08x\n", hres); 1627 ok(iRec->recordcopy == sab[0].cElements, "got %d\n", iRec->recordcopy); 1628 ok(iRec->clearCalled == 0, "got %d\n", iRec->clearCalled); 1629 1630 hres = SafeArrayDestroy(sacopy); 1631 ok(hres == S_OK, "got 0x%08x\n", hres); 1632 1633 iRec->clearCalled = 0; 1634 iRec->sizeCalled = 0; 1635 hres = SafeArrayDestroy(sa); 1636 ok(hres == S_OK, "got 0x%08x\n", hres); 1637 ok(iRec->sizeCalled == 0, "Destroy->GetSize called %d times\n", iRec->sizeCalled); 1638 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled); 1639 ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %d\n", iRec->ref); 1640 } 1641 else 1642 { 1643 hres = SafeArrayDestroy(sa); 1644 ok(hres == S_OK, "got 0x%08x\n", hres); 1645 } 1646 1647 IRecordInfo_Release(&iRec->IRecordInfo_iface); 1648 } 1649 1650 static void test_SafeArrayClear(void) 1651 { 1652 SAFEARRAYBOUND sab; 1653 SAFEARRAY *sa; 1654 VARIANTARG v; 1655 HRESULT hres; 1656 1657 sab.lLbound = 0; 1658 sab.cElements = 10; 1659 sa = SafeArrayCreate(VT_UI1, 1, &sab); 1660 ok(sa != NULL, "Create() failed.\n"); 1661 if (!sa) 1662 return; 1663 1664 /* Test clearing non-NULL variants containing arrays */ 1665 V_VT(&v) = VT_ARRAY|VT_UI1; 1666 V_ARRAY(&v) = sa; 1667 hres = VariantClear(&v); 1668 ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%x, Type %d\n", hres, V_VT(&v)); 1669 ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n"); 1670 1671 sa = SafeArrayCreate(VT_UI1, 1, &sab); 1672 ok(sa != NULL, "Create() failed.\n"); 1673 if (!sa) 1674 return; 1675 1676 V_VT(&v) = VT_SAFEARRAY; 1677 V_ARRAY(&v) = sa; 1678 hres = VariantClear(&v); 1679 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres); 1680 1681 V_VT(&v) = VT_SAFEARRAY|VT_BYREF; 1682 V_ARRAYREF(&v) = &sa; 1683 hres = VariantClear(&v); 1684 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres); 1685 1686 hres = SafeArrayDestroy(sa); 1687 ok(hres == S_OK, "got 0x%08x\n", hres); 1688 } 1689 1690 static void test_SafeArrayCopy(void) 1691 { 1692 SAFEARRAYBOUND sab; 1693 SAFEARRAY *sa, *sa2; 1694 VARIANTARG vSrc, vDst; 1695 HRESULT hres; 1696 int i; 1697 1698 sab.lLbound = 0; 1699 sab.cElements = 10; 1700 sa = SafeArrayCreate(VT_UI1, 1, &sab); 1701 ok(sa != NULL, "Create() failed.\n"); 1702 if (!sa) 1703 return; 1704 1705 /* Test copying non-NULL variants containing arrays */ 1706 V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1); 1707 V_ARRAYREF(&vSrc) = &sa; 1708 V_VT(&vDst) = VT_EMPTY; 1709 1710 hres = VariantCopy(&vDst, &vSrc); 1711 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1), 1712 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst)); 1713 ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n"); 1714 1715 V_VT(&vSrc) = (VT_ARRAY|VT_UI1); 1716 V_ARRAY(&vSrc) = sa; 1717 V_VT(&vDst) = VT_EMPTY; 1718 1719 hres = VariantCopy(&vDst, &vSrc); 1720 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1), 1721 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst)); 1722 ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n"); 1723 1724 hres = SafeArrayDestroy(V_ARRAY(&vSrc)); 1725 ok(hres == S_OK, "got 0x%08x\n", hres); 1726 hres = SafeArrayDestroy(V_ARRAY(&vDst)); 1727 ok(hres == S_OK, "got 0x%08x\n", hres); 1728 1729 hres = SafeArrayAllocDescriptor(1, &sa); 1730 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres); 1731 1732 sa->cbElements = 16; 1733 hres = SafeArrayCopy(sa, &sa2); 1734 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres); 1735 ok(sa != sa2, "SafeArrayCopy performed shallow copy\n"); 1736 1737 hres = SafeArrayDestroy(sa2); 1738 ok(hres == S_OK, "got 0x%08x\n", hres); 1739 hres = SafeArrayDestroy(sa); 1740 ok(hres == S_OK, "got 0x%08x\n", hres); 1741 1742 sa2 = (void*)0xdeadbeef; 1743 hres = SafeArrayCopy(NULL, &sa2); 1744 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres); 1745 ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n"); 1746 1747 hres = SafeArrayAllocDescriptor(1, &sa); 1748 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres); 1749 1750 sa2 = (void*)0xdeadbeef; 1751 hres = SafeArrayCopy(sa, &sa2); 1752 ok(hres == E_INVALIDARG, 1753 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n", 1754 hres); 1755 ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n"); 1756 1757 hres = SafeArrayDestroy(sa2); 1758 ok(hres == S_OK, "got 0x%08x\n", hres); 1759 hres = SafeArrayDestroy(sa); 1760 ok(hres == S_OK, "got 0x%08x\n", hres); 1761 1762 /* test feature copy */ 1763 hres = SafeArrayAllocDescriptor(1, &sa); 1764 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres); 1765 ok(sa->fFeatures == 0, "got src features 0x%04x\n", sa->fFeatures); 1766 sa->cbElements = 16; 1767 1768 for (i = 0; i < sizeof(ignored_copy_features)/sizeof(USHORT); i++) 1769 { 1770 USHORT feature = ignored_copy_features[i]; 1771 1772 sa->fFeatures |= feature; 1773 hres = SafeArrayCopy(sa, &sa2); 1774 ok(hres == S_OK, "got 0x%08x\n", hres); 1775 ok(sa2->fFeatures == 0, "got features 0x%04x\n", sa2->fFeatures); 1776 hres = SafeArrayDestroy(sa2); 1777 ok(hres == S_OK, "got 0x%08x\n", hres); 1778 sa->fFeatures &= ~feature; 1779 } 1780 1781 SafeArrayDestroy(sa); 1782 1783 /* copy from a vector */ 1784 sa = SafeArrayCreateVector(VT_UI1, 0, 2); 1785 ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) || 1786 broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */), 1787 "got 0x%08x\n", sa->fFeatures); 1788 hres = SafeArrayCopy(sa, &sa2); 1789 ok(hres == S_OK, "got 0x%08x\n", hres); 1790 ok(sa2->fFeatures == FADF_HAVEVARTYPE || 1791 broken(!sa2->fFeatures /* W2k */), "got 0x%04x\n", 1792 sa2->fFeatures); 1793 1794 SafeArrayDestroy(sa2); 1795 SafeArrayDestroy(sa); 1796 } 1797 1798 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \ 1799 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \ 1800 if (!sa) return; \ 1801 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2) 1802 1803 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \ 1804 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \ 1805 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2) 1806 1807 static void test_SafeArrayChangeTypeEx(void) 1808 { 1809 static const char *szHello = "Hello World"; 1810 SAFEARRAYBOUND sab; 1811 SAFEARRAY *sa; 1812 VARIANTARG v,v2; 1813 VARTYPE vt; 1814 HRESULT hres; 1815 1816 /* VT_ARRAY|VT_UI1 -> VT_BSTR */ 1817 MKARRAY(0,strlen(szHello)+1,VT_UI1); 1818 memcpy(sa->pvData, szHello, strlen(szHello)+1); 1819 1820 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR); 1821 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres); 1822 if (hres == S_OK) 1823 { 1824 ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2)); 1825 ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello, 1826 (char*)V_BSTR(&v2)); 1827 VariantClear(&v2); 1828 } 1829 1830 /* VT_VECTOR|VT_UI1 -> VT_BSTR */ 1831 hres = SafeArrayDestroy(sa); 1832 ok(hres == S_OK, "got 0x%08x\n", hres); 1833 if (pSafeArrayCreateVector) 1834 { 1835 sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1); 1836 ok(sa != NULL, "CreateVector() failed.\n"); 1837 if (!sa) 1838 return; 1839 1840 memcpy(sa->pvData, szHello, strlen(szHello)+1); 1841 V_VT(&v) = VT_VECTOR|VT_UI1; 1842 V_ARRAY(&v) = sa; 1843 VariantInit(&v2); 1844 1845 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR); 1846 ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres); 1847 1848 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */ 1849 V_VT(&v) = VT_ARRAY|VT_UI1; 1850 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR); 1851 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres); 1852 if (hres == S_OK) 1853 { 1854 ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v)); 1855 ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello, 1856 (char*)V_BSTR(&v)); 1857 VariantClear(&v); 1858 } 1859 } 1860 1861 /* To/from BSTR only works with arrays of VT_UI1 */ 1862 for (vt = VT_EMPTY; vt <= VT_CLSID; vt++) 1863 { 1864 if (vt == VT_UI1) 1865 continue; 1866 1867 sab.lLbound = 0; 1868 sab.cElements = 1; 1869 sa = SafeArrayCreate(vt, 1, &sab); 1870 if (!sa) continue; 1871 1872 V_VT(&v) = VT_ARRAY|vt; 1873 V_ARRAY(&v) = sa; 1874 VariantInit(&v2); 1875 1876 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR); 1877 if (vt == VT_INT_PTR || vt == VT_UINT_PTR) 1878 { 1879 ok(hres == DISP_E_BADVARTYPE, "expected DISP_E_BADVARTYPE, got 0x%08x\n", hres); 1880 SafeArrayDestroy(sa); 1881 } 1882 else 1883 { 1884 ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x for vt=%d, instead of DISP_E_TYPEMISMATCH\n", hres, vt); 1885 hres = VariantClear(&v); 1886 ok(hres == S_OK, "expected S_OK, got 0x%08x\n", hres); 1887 } 1888 VariantClear(&v2); 1889 } 1890 1891 /* Can't change an array of one type into array of another type , even 1892 * if the other type is the same size 1893 */ 1894 if (pSafeArrayCreateVector) 1895 { 1896 sa = pSafeArrayCreateVector(VT_UI1, 0, 1); 1897 ok(sa != NULL, "CreateVector() failed.\n"); 1898 if (!sa) 1899 return; 1900 1901 V_VT(&v) = VT_ARRAY|VT_UI1; 1902 V_ARRAY(&v) = sa; 1903 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1); 1904 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres); 1905 1906 /* But can change to the same array type */ 1907 hres = SafeArrayDestroy(sa); 1908 ok(hres == S_OK, "got 0x%08x\n", hres); 1909 sa = pSafeArrayCreateVector(VT_UI1, 0, 1); 1910 ok(sa != NULL, "CreateVector() failed.\n"); 1911 if (!sa) 1912 return; 1913 V_VT(&v) = VT_ARRAY|VT_UI1; 1914 V_ARRAY(&v) = sa; 1915 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1); 1916 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres); 1917 hres = SafeArrayDestroy(sa); 1918 ok(hres == S_OK, "got 0x%08x\n", hres); 1919 VariantClear(&v2); 1920 } 1921 1922 /* NULL/EMPTY */ 1923 MKARRAY(0,1,VT_UI1); 1924 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL); 1925 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres); 1926 VariantClear(&v); 1927 MKARRAY(0,1,VT_UI1); 1928 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY); 1929 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres); 1930 VariantClear(&v); 1931 } 1932 1933 static void test_SafeArrayDestroyData (void) 1934 { 1935 SAFEARRAYBOUND sab[2]; 1936 SAFEARRAY *sa; 1937 HRESULT hres; 1938 int value = 0xdeadbeef; 1939 LONG index[1]; 1940 void *temp_pvData; 1941 USHORT features; 1942 1943 sab[0].lLbound = 0; 1944 sab[0].cElements = 10; 1945 sa = SafeArrayCreate(VT_INT, 1, sab); 1946 ok(sa != NULL, "Create() failed.\n"); 1947 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures); 1948 1949 index[0] = 1; 1950 SafeArrayPutElement (sa, index, &value); 1951 1952 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */ 1953 features = (sa->fFeatures |= FADF_STATIC); 1954 temp_pvData = sa->pvData; 1955 hres = SafeArrayDestroyData(sa); 1956 ok(hres == S_OK, "SADData FADF_STATIC failed, error code %x.\n",hres); 1957 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures); 1958 ok(sa->pvData == temp_pvData, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n", 1959 sa->pvData, temp_pvData, sa->fFeatures); 1960 SafeArrayGetElement (sa, index, &value); 1961 ok(value == 0, "Data not cleared after SADData\n"); 1962 1963 /* Clear FADF_STATIC, now really destroy the data. */ 1964 features = (sa->fFeatures ^= FADF_STATIC); 1965 hres = SafeArrayDestroyData(sa); 1966 ok(hres == S_OK, "SADData !FADF_STATIC failed, error code %x.\n",hres); 1967 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures); 1968 ok(sa->pvData == NULL, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa->pvData); 1969 1970 hres = SafeArrayDestroy(sa); 1971 ok(hres == S_OK, "SAD failed, error code %x.\n", hres); 1972 1973 /* two dimensions */ 1974 sab[0].lLbound = 0; 1975 sab[0].cElements = 10; 1976 sab[1].lLbound = 0; 1977 sab[1].cElements = 10; 1978 1979 sa = SafeArrayCreate(VT_INT, 2, sab); 1980 ok(sa != NULL, "Create() failed.\n"); 1981 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures); 1982 1983 features = sa->fFeatures; 1984 hres = SafeArrayDestroyData(sa); 1985 ok(hres == S_OK, "got 0x%08x\n",hres); 1986 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures); 1987 1988 SafeArrayDestroy(sa); 1989 1990 /* try to destroy data from descriptor */ 1991 hres = SafeArrayAllocDescriptor(1, &sa); 1992 ok(hres == S_OK, "got 0x%08x\n", hres); 1993 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures); 1994 1995 hres = SafeArrayDestroyData(sa); 1996 ok(hres == S_OK, "got 0x%08x\n", hres); 1997 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures); 1998 1999 hres = SafeArrayDestroyDescriptor(sa); 2000 ok(hres == S_OK, "got 0x%08x\n", hres); 2001 2002 hres = SafeArrayAllocDescriptor(2, &sa); 2003 ok(hres == S_OK, "got 0x%08x\n", hres); 2004 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures); 2005 2006 hres = SafeArrayDestroyData(sa); 2007 ok(hres == S_OK, "got 0x%08x\n", hres); 2008 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures); 2009 2010 hres = SafeArrayDestroyDescriptor(sa); 2011 ok(hres == S_OK, "got 0x%08x\n", hres); 2012 2013 /* vector case */ 2014 sa = SafeArrayCreateVector(VT_I4, 0, 10); 2015 ok(sa != NULL, "got %p\n", sa); 2016 ok(sa->fFeatures == (FADF_CREATEVECTOR|FADF_HAVEVARTYPE), "got 0x%x\n", sa->fFeatures); 2017 2018 ok(sa->pvData != NULL, "got %p\n", sa->pvData); 2019 hres = SafeArrayDestroyData(sa); 2020 ok(hres == S_OK, "got 0x%08x\n", hres); 2021 todo_wine 2022 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures); 2023 ok(sa->pvData != NULL, "got %p\n", sa->pvData); 2024 /* There seems to be a bug on windows, especially visible on 64bit systems, 2025 probably double-free of similar issue. */ 2026 sa->pvData = NULL; 2027 SafeArrayDestroy(sa); 2028 } 2029 2030 static void test_safearray_layout(void) 2031 { 2032 IRecordInfoImpl *irec; 2033 IRecordInfo *record; 2034 GUID guid, *guidptr; 2035 SAFEARRAYBOUND sab; 2036 SAFEARRAY *sa; 2037 DWORD *dwptr; 2038 HRESULT hr; 2039 2040 sab.lLbound = 0; 2041 sab.cElements = 10; 2042 2043 /* GUID field */ 2044 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab); 2045 ok(sa != NULL, "got %p\n", sa); 2046 2047 guidptr = (GUID*)sa - 1; 2048 ok(IsEqualIID(guidptr, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(guidptr)); 2049 2050 hr = SafeArraySetIID(sa, &IID_IDispatch); 2051 ok(hr == S_OK, "got 0x%08x\n", hr); 2052 ok(IsEqualIID(guidptr, &IID_IDispatch), "got %s\n", wine_dbgstr_guid(guidptr)); 2053 2054 memcpy(guidptr, &IID_IUnknown, sizeof(GUID)); 2055 hr = SafeArrayGetIID(sa, &guid); 2056 ok(hr == S_OK, "got 0x%08x\n", hr); 2057 ok(IsEqualIID(&guid, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(&guid)); 2058 2059 hr = SafeArrayDestroy(sa); 2060 ok(hr == S_OK, "got 0x%08x\n", hr); 2061 2062 /* VARTYPE field */ 2063 sa = SafeArrayCreate(VT_UI1, 1, &sab); 2064 ok(sa != NULL, "got %p\n", sa); 2065 2066 dwptr = (DWORD*)sa - 1; 2067 ok(*dwptr == VT_UI1, "got %d\n", *dwptr); 2068 2069 hr = SafeArrayDestroy(sa); 2070 ok(hr == S_OK, "got 0x%08x\n", hr); 2071 2072 /* IRecordInfo pointer */ 2073 irec = IRecordInfoImpl_Construct(); 2074 irec->ref = 1; 2075 2076 sa = pSafeArrayCreateEx(VT_RECORD, 1, &sab, &irec->IRecordInfo_iface); 2077 ok(sa != NULL, "failed to create array\n"); 2078 2079 record = *((IRecordInfo**)sa - 1); 2080 ok(record == &irec->IRecordInfo_iface, "got %p\n", record); 2081 2082 hr = SafeArrayDestroy(sa); 2083 ok(hr == S_OK, "got 0x%08x\n", hr); 2084 IRecordInfo_Release(&irec->IRecordInfo_iface); 2085 } 2086 2087 START_TEST(safearray) 2088 { 2089 hOleaut32 = GetModuleHandleA("oleaut32.dll"); 2090 2091 has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL; 2092 2093 GETPTR(SafeArrayAllocDescriptorEx); 2094 GETPTR(SafeArrayCopyData); 2095 GETPTR(SafeArrayGetVartype); 2096 GETPTR(SafeArrayCreateEx); 2097 GETPTR(SafeArrayCreateVector); 2098 GETPTR(SafeArrayGetRecordInfo); 2099 2100 check_for_VT_INT_PTR(); 2101 test_safearray(); 2102 test_SafeArrayAllocDestroyDescriptor(); 2103 test_SafeArrayCreateLockDestroy(); 2104 test_VectorCreateLockDestroy(); 2105 test_LockUnlock(); 2106 test_SafeArrayChangeTypeEx(); 2107 test_SafeArrayCopy(); 2108 test_SafeArrayClear(); 2109 test_SafeArrayCreateEx(); 2110 test_SafeArrayCopyData(); 2111 test_SafeArrayDestroyData(); 2112 test_SafeArrayGetPutElement(); 2113 test_SafeArrayGetPutElement_BSTR(); 2114 test_SafeArrayGetPutElement_IUnknown(); 2115 test_SafeArrayRedim_IUnknown(); 2116 test_SafeArrayGetPutElement_VARIANT(); 2117 test_safearray_layout(); 2118 } 2119