1 /************************************************************************* 2 * OLE Automation - SafeArray 3 * 4 * This file contains the implementation of the SafeArray functions. 5 * 6 * Copyright 1999 Sylvain St-Germain 7 * Copyright 2002-2003 Marcus Meissner 8 * Copyright 2003 Jon Griffiths 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 */ 24 /* Memory Layout of a SafeArray: 25 * 26 * -0x10: start of memory. 27 * -0x10: GUID for VT_DISPATCH and VT_UNKNOWN safearrays (if FADF_HAVEIID) 28 * -0x04: DWORD varianttype; (for all others, except VT_RECORD) (if FADF_HAVEVARTYPE) 29 * -0x4: IRecordInfo* iface; (if FADF_RECORD, for VT_RECORD (can be NULL)) 30 * 0x00: SAFEARRAY, 31 * 0x10: SAFEARRAYBOUNDS[0...] 32 */ 33 34 #include <string.h> 35 #include <stdarg.h> 36 #include <stdio.h> 37 38 #define COBJMACROS 39 40 #include "windef.h" 41 #include "winerror.h" 42 #include "winbase.h" 43 #include "variant.h" 44 #include "wine/debug.h" 45 46 WINE_DEFAULT_DEBUG_CHANNEL(variant); 47 48 /************************************************************************ 49 * SafeArray {OLEAUT32} 50 * 51 * NOTES 52 * The SafeArray data type provides the underlying interface for Ole 53 * Automations arrays, used for example to represent array types in 54 * Visual Basic(tm) and to gather user defined parameters for invocation through 55 * an IDispatch interface. 56 * 57 * Safe arrays provide bounds checking and automatically manage the data 58 * types they contain, for example handing reference counting and copying 59 * of interface pointers. User defined types can be stored in arrays 60 * using the IRecordInfo interface. 61 * 62 * There are two types of SafeArray, normal and vectors. Normal arrays can have 63 * multiple dimensions and the data for the array is allocated separately from 64 * the array header. This is the most flexible type of array. Vectors, on the 65 * other hand, are fixed in size and consist of a single allocated block, and a 66 * single dimension. 67 * 68 * DATATYPES 69 * The following types of data can be stored within a SafeArray. 70 * Numeric: 71 *| VT_I1, VT_UI1, VT_I2, VT_UI2, VT_I4, VT_UI4, VT_I8, VT_UI8, VT_INT, VT_UINT, 72 *| VT_R4, VT_R8, VT_CY, VT_DECIMAL 73 * Interfaces: 74 *| VT_DISPATCH, VT_UNKNOWN, VT_RECORD 75 * Other: 76 *| VT_VARIANT, VT_INT_PTR, VT_UINT_PTR, VT_BOOL, VT_ERROR, VT_DATE, VT_BSTR 77 * 78 * FUNCTIONS 79 * BstrFromVector() 80 * VectorFromBstr() 81 */ 82 83 /* Undocumented hidden space before the start of a SafeArray descriptor */ 84 #define SAFEARRAY_HIDDEN_SIZE sizeof(GUID) 85 86 /* features listed here are not propagated to newly created array or data copy 87 created with SafeArrayCopy()/SafeArrayCopyData() */ 88 static const USHORT ignored_copy_features = 89 FADF_AUTO | 90 FADF_STATIC | 91 FADF_EMBEDDED | 92 FADF_FIXEDSIZE | 93 FADF_CREATEVECTOR; 94 95 /* Allocate memory */ 96 static inline void* SAFEARRAY_Malloc(ULONG size) 97 { 98 void *ret = CoTaskMemAlloc(size); 99 if (ret) 100 memset(ret, 0, size); 101 return ret; 102 } 103 104 /* Free memory */ 105 static inline void SAFEARRAY_Free(void *ptr) 106 { 107 CoTaskMemFree(ptr); 108 } 109 110 /* Get the size of a supported VT type (0 means unsupported) */ 111 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt) 112 { 113 switch (vt) 114 { 115 case VT_I1: 116 case VT_UI1: return sizeof(BYTE); 117 case VT_BOOL: 118 case VT_I2: 119 case VT_UI2: return sizeof(SHORT); 120 case VT_I4: 121 case VT_UI4: 122 case VT_R4: 123 case VT_ERROR: return sizeof(LONG); 124 case VT_R8: 125 case VT_I8: 126 case VT_UI8: return sizeof(LONG64); 127 case VT_INT: 128 case VT_UINT: return sizeof(INT); 129 case VT_INT_PTR: 130 case VT_UINT_PTR: return sizeof(UINT_PTR); 131 case VT_CY: return sizeof(CY); 132 case VT_DATE: return sizeof(DATE); 133 case VT_BSTR: return sizeof(BSTR); 134 case VT_DISPATCH: return sizeof(LPDISPATCH); 135 case VT_VARIANT: return sizeof(VARIANT); 136 case VT_UNKNOWN: return sizeof(LPUNKNOWN); 137 case VT_DECIMAL: return sizeof(DECIMAL); 138 /* Note: Return a non-zero size to indicate vt is valid. The actual size 139 * of a UDT is taken from the result of IRecordInfo_GetSize(). 140 */ 141 case VT_RECORD: return 32; 142 } 143 return 0; 144 } 145 146 /* Set the hidden data for an array */ 147 static inline void SAFEARRAY_SetHiddenDWORD(SAFEARRAY* psa, DWORD dw) 148 { 149 /* Implementation data is stored in the 4 bytes before the header */ 150 LPDWORD lpDw = (LPDWORD)psa; 151 lpDw[-1] = dw; 152 } 153 154 /* Get the hidden data from an array */ 155 static inline DWORD SAFEARRAY_GetHiddenDWORD(SAFEARRAY* psa) 156 { 157 LPDWORD lpDw = (LPDWORD)psa; 158 return lpDw[-1]; 159 } 160 161 /* Get the number of cells in a SafeArray */ 162 static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa) 163 { 164 const SAFEARRAYBOUND* psab = psa->rgsabound; 165 USHORT cCount = psa->cDims; 166 ULONG ulNumCells = 1; 167 168 while (cCount--) 169 { 170 /* This is a valid bordercase. See testcases. -Marcus */ 171 if (!psab->cElements) 172 return 0; 173 ulNumCells *= psab->cElements; 174 psab++; 175 } 176 return ulNumCells; 177 } 178 179 /* Allocate a descriptor for an array */ 180 static HRESULT SAFEARRAY_AllocDescriptor(ULONG ulSize, SAFEARRAY **ppsaOut) 181 { 182 char *ptr = SAFEARRAY_Malloc(ulSize + SAFEARRAY_HIDDEN_SIZE); 183 184 if (!ptr) 185 { 186 *ppsaOut = NULL; 187 return E_OUTOFMEMORY; 188 } 189 190 *ppsaOut = (SAFEARRAY*)(ptr + SAFEARRAY_HIDDEN_SIZE); 191 return S_OK; 192 } 193 194 /* Set the features of an array */ 195 static void SAFEARRAY_SetFeatures(VARTYPE vt, SAFEARRAY *psa) 196 { 197 /* Set the IID if we have one, otherwise set the type */ 198 if (vt == VT_DISPATCH) 199 { 200 psa->fFeatures = FADF_HAVEIID; 201 SafeArraySetIID(psa, &IID_IDispatch); 202 } 203 else if (vt == VT_UNKNOWN) 204 { 205 psa->fFeatures = FADF_HAVEIID; 206 SafeArraySetIID(psa, &IID_IUnknown); 207 } 208 else if (vt == VT_RECORD) 209 psa->fFeatures = FADF_RECORD; 210 else 211 { 212 psa->fFeatures = FADF_HAVEVARTYPE; 213 SAFEARRAY_SetHiddenDWORD(psa, vt); 214 } 215 } 216 217 /* Create an array */ 218 static SAFEARRAY* SAFEARRAY_Create(VARTYPE vt, UINT cDims, const SAFEARRAYBOUND *rgsabound, ULONG ulSize) 219 { 220 SAFEARRAY *psa = NULL; 221 unsigned int i; 222 223 if (!rgsabound) 224 return NULL; 225 226 if (SUCCEEDED(SafeArrayAllocDescriptorEx(vt, cDims, &psa))) 227 { 228 switch (vt) 229 { 230 case VT_BSTR: psa->fFeatures |= FADF_BSTR; break; 231 case VT_UNKNOWN: psa->fFeatures |= FADF_UNKNOWN; break; 232 case VT_DISPATCH: psa->fFeatures |= FADF_DISPATCH; break; 233 case VT_VARIANT: psa->fFeatures |= FADF_VARIANT; break; 234 } 235 236 for (i = 0; i < cDims; i++) 237 memcpy(psa->rgsabound + i, rgsabound + cDims - 1 - i, sizeof(SAFEARRAYBOUND)); 238 239 if (ulSize) 240 psa->cbElements = ulSize; 241 242 if (!psa->cbElements || FAILED(SafeArrayAllocData(psa))) 243 { 244 SafeArrayDestroyDescriptor(psa); 245 psa = NULL; 246 } 247 } 248 return psa; 249 } 250 251 /* Create an array as a vector */ 252 static SAFEARRAY* SAFEARRAY_CreateVector(VARTYPE vt, LONG lLbound, ULONG cElements, ULONG ulSize) 253 { 254 SAFEARRAY *psa = NULL; 255 256 if (ulSize || (vt == VT_RECORD)) 257 { 258 /* Allocate the header and data together */ 259 if (SUCCEEDED(SAFEARRAY_AllocDescriptor(sizeof(SAFEARRAY) + ulSize * cElements, &psa))) 260 { 261 SAFEARRAY_SetFeatures(vt, psa); 262 263 psa->cDims = 1; 264 psa->fFeatures |= FADF_CREATEVECTOR; 265 psa->pvData = &psa[1]; /* Data follows the header */ 266 psa->cbElements = ulSize; 267 psa->rgsabound[0].cElements = cElements; 268 psa->rgsabound[0].lLbound = lLbound; 269 270 switch (vt) 271 { 272 case VT_BSTR: psa->fFeatures |= FADF_BSTR; break; 273 case VT_UNKNOWN: psa->fFeatures |= FADF_UNKNOWN; break; 274 case VT_DISPATCH: psa->fFeatures |= FADF_DISPATCH; break; 275 case VT_VARIANT: psa->fFeatures |= FADF_VARIANT; break; 276 } 277 } 278 } 279 return psa; 280 } 281 282 /* Free data items in an array */ 283 static HRESULT SAFEARRAY_DestroyData(SAFEARRAY *psa, ULONG ulStartCell) 284 { 285 if (psa->pvData && !(psa->fFeatures & FADF_DATADELETED)) 286 { 287 ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); 288 289 if (ulStartCell > ulCellCount) { 290 FIXME("unexpected ulCellCount %d, start %d\n",ulCellCount,ulStartCell); 291 return E_UNEXPECTED; 292 } 293 294 ulCellCount -= ulStartCell; 295 296 if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH)) 297 { 298 LPUNKNOWN *lpUnknown = (LPUNKNOWN *)psa->pvData + ulStartCell; 299 300 while(ulCellCount--) 301 { 302 if (*lpUnknown) 303 IUnknown_Release(*lpUnknown); 304 lpUnknown++; 305 } 306 } 307 else if (psa->fFeatures & FADF_RECORD) 308 { 309 IRecordInfo *lpRecInfo; 310 311 if (SUCCEEDED(SafeArrayGetRecordInfo(psa, &lpRecInfo))) 312 { 313 PBYTE pRecordData = psa->pvData; 314 while(ulCellCount--) 315 { 316 IRecordInfo_RecordClear(lpRecInfo, pRecordData); 317 pRecordData += psa->cbElements; 318 } 319 IRecordInfo_Release(lpRecInfo); 320 } 321 } 322 else if (psa->fFeatures & FADF_BSTR) 323 { 324 BSTR* lpBstr = (BSTR*)psa->pvData + ulStartCell; 325 326 while(ulCellCount--) 327 { 328 SysFreeString(*lpBstr); 329 lpBstr++; 330 } 331 } 332 else if (psa->fFeatures & FADF_VARIANT) 333 { 334 VARIANT* lpVariant = (VARIANT*)psa->pvData + ulStartCell; 335 336 while(ulCellCount--) 337 { 338 HRESULT hRet = VariantClear(lpVariant); 339 340 if (FAILED(hRet)) FIXME("VariantClear of element failed!\n"); 341 lpVariant++; 342 } 343 } 344 } 345 return S_OK; 346 } 347 348 /* Copy data items from one array to another. Destination data is freed before copy. */ 349 static HRESULT SAFEARRAY_CopyData(SAFEARRAY *psa, SAFEARRAY *dest) 350 { 351 HRESULT hr = S_OK; 352 353 if (!psa->pvData) 354 return S_OK; 355 356 if (!dest->pvData || psa->fFeatures & FADF_DATADELETED) 357 return E_INVALIDARG; 358 else 359 { 360 ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); 361 362 dest->fFeatures = (dest->fFeatures & FADF_CREATEVECTOR) | (psa->fFeatures & ~ignored_copy_features); 363 364 if (psa->fFeatures & FADF_VARIANT) 365 { 366 VARIANT *src_var = psa->pvData; 367 VARIANT *dest_var = dest->pvData; 368 369 while(ulCellCount--) 370 { 371 HRESULT hRet; 372 373 /* destination is cleared automatically */ 374 hRet = VariantCopy(dest_var, src_var); 375 if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%08x, element %u\n", hRet, ulCellCount); 376 src_var++; 377 dest_var++; 378 } 379 } 380 else if (psa->fFeatures & FADF_BSTR) 381 { 382 BSTR *src_bstr = psa->pvData; 383 BSTR *dest_bstr = dest->pvData; 384 385 while(ulCellCount--) 386 { 387 SysFreeString(*dest_bstr); 388 if (*src_bstr) 389 { 390 *dest_bstr = SysAllocStringByteLen((char*)*src_bstr, SysStringByteLen(*src_bstr)); 391 if (!*dest_bstr) 392 return E_OUTOFMEMORY; 393 } 394 else 395 *dest_bstr = NULL; 396 src_bstr++; 397 dest_bstr++; 398 } 399 } 400 else if (psa->fFeatures & FADF_RECORD) 401 { 402 BYTE *dest_data = dest->pvData; 403 BYTE *src_data = psa->pvData; 404 IRecordInfo *record; 405 406 SafeArrayGetRecordInfo(psa, &record); 407 while (ulCellCount--) 408 { 409 /* RecordCopy() clears destination record */ 410 hr = IRecordInfo_RecordCopy(record, src_data, dest_data); 411 if (FAILED(hr)) break; 412 src_data += psa->cbElements; 413 dest_data += psa->cbElements; 414 } 415 416 SafeArraySetRecordInfo(dest, record); 417 /* This value is set to 32 bytes by default on descriptor creation, 418 update with actual structure size. */ 419 dest->cbElements = psa->cbElements; 420 IRecordInfo_Release(record); 421 } 422 else if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH)) 423 { 424 IUnknown **dest_unk = dest->pvData; 425 IUnknown **src_unk = psa->pvData; 426 427 /* release old iface, addref new one */ 428 while (ulCellCount--) 429 { 430 if (*dest_unk) 431 IUnknown_Release(*dest_unk); 432 *dest_unk = *src_unk; 433 if (*dest_unk) 434 IUnknown_AddRef(*dest_unk); 435 src_unk++; 436 dest_unk++; 437 } 438 } 439 else 440 { 441 /* Copy the data over */ 442 memcpy(dest->pvData, psa->pvData, ulCellCount * psa->cbElements); 443 } 444 445 if (psa->fFeatures & FADF_HAVEIID) 446 { 447 GUID guid; 448 SafeArrayGetIID(psa, &guid); 449 SafeArraySetIID(dest, &guid); 450 } 451 else if (psa->fFeatures & FADF_HAVEVARTYPE) 452 { 453 SAFEARRAY_SetHiddenDWORD(dest, SAFEARRAY_GetHiddenDWORD(psa)); 454 } 455 } 456 457 return hr; 458 } 459 460 /************************************************************************* 461 * SafeArrayAllocDescriptor (OLEAUT32.36) 462 * 463 * Allocate and initialise a descriptor for a SafeArray. 464 * 465 * PARAMS 466 * cDims [I] Number of dimensions of the array 467 * ppsaOut [O] Destination for new descriptor 468 * 469 * RETURNS 470 * Success: S_OK. ppsaOut is filled with a newly allocated descriptor. 471 * Failure: An HRESULT error code indicating the error. 472 * 473 * NOTES 474 * See SafeArray. 475 */ 476 HRESULT WINAPI SafeArrayAllocDescriptor(UINT cDims, SAFEARRAY **ppsaOut) 477 { 478 LONG allocSize; 479 HRESULT hr; 480 481 TRACE("(%d,%p)\n", cDims, ppsaOut); 482 483 if (!cDims || cDims >= 0x10000) /* Maximum 65535 dimensions */ 484 return E_INVALIDARG; 485 486 if (!ppsaOut) 487 return E_POINTER; 488 489 /* We need enough space for the header and its bounds */ 490 allocSize = sizeof(SAFEARRAY) + sizeof(SAFEARRAYBOUND) * (cDims - 1); 491 492 hr = SAFEARRAY_AllocDescriptor(allocSize, ppsaOut); 493 if (FAILED(hr)) 494 return hr; 495 496 (*ppsaOut)->cDims = cDims; 497 498 TRACE("(%d): %u bytes allocated for descriptor.\n", cDims, allocSize); 499 return S_OK; 500 } 501 502 /************************************************************************* 503 * SafeArrayAllocDescriptorEx (OLEAUT32.41) 504 * 505 * Allocate and initialise a descriptor for a SafeArray of a given type. 506 * 507 * PARAMS 508 * vt [I] The type of items to store in the array 509 * cDims [I] Number of dimensions of the array 510 * ppsaOut [O] Destination for new descriptor 511 * 512 * RETURNS 513 * Success: S_OK. ppsaOut is filled with a newly allocated descriptor. 514 * Failure: An HRESULT error code indicating the error. 515 * 516 * NOTES 517 * - This function does not check that vt is an allowed VARTYPE. 518 * - Unlike SafeArrayAllocDescriptor(), vt is associated with the array. 519 * See SafeArray. 520 */ 521 HRESULT WINAPI SafeArrayAllocDescriptorEx(VARTYPE vt, UINT cDims, SAFEARRAY **ppsaOut) 522 { 523 ULONG cbElements; 524 HRESULT hRet; 525 526 TRACE("(%s,%u,%p)\n", debugstr_vt(vt), cDims, ppsaOut); 527 528 cbElements = SAFEARRAY_GetVTSize(vt); 529 if (!cbElements) 530 WARN("Creating a descriptor with an invalid VARTYPE!\n"); 531 532 hRet = SafeArrayAllocDescriptor(cDims, ppsaOut); 533 534 if (SUCCEEDED(hRet)) 535 { 536 SAFEARRAY_SetFeatures(vt, *ppsaOut); 537 (*ppsaOut)->cbElements = cbElements; 538 } 539 return hRet; 540 } 541 542 /************************************************************************* 543 * SafeArrayAllocData (OLEAUT32.37) 544 * 545 * Allocate the data area of a SafeArray. 546 * 547 * PARAMS 548 * psa [I] SafeArray to allocate the data area of. 549 * 550 * RETURNS 551 * Success: S_OK. The data area is allocated and initialised. 552 * Failure: An HRESULT error code indicating the error. 553 * 554 * NOTES 555 * See SafeArray. 556 */ 557 HRESULT WINAPI SafeArrayAllocData(SAFEARRAY *psa) 558 { 559 HRESULT hRet = E_INVALIDARG; 560 561 TRACE("(%p)\n", psa); 562 563 if (psa) 564 { 565 ULONG ulSize = SAFEARRAY_GetCellCount(psa); 566 567 psa->pvData = SAFEARRAY_Malloc(ulSize * psa->cbElements); 568 569 if (psa->pvData) 570 { 571 hRet = S_OK; 572 TRACE("%u bytes allocated for data at %p (%u objects).\n", 573 ulSize * psa->cbElements, psa->pvData, ulSize); 574 } 575 else 576 hRet = E_OUTOFMEMORY; 577 } 578 return hRet; 579 } 580 581 /************************************************************************* 582 * SafeArrayCreate (OLEAUT32.15) 583 * 584 * Create a new SafeArray. 585 * 586 * PARAMS 587 * vt [I] Type to store in the safe array 588 * cDims [I] Number of array dimensions 589 * rgsabound [I] Bounds of the array dimensions 590 * 591 * RETURNS 592 * Success: A pointer to a new array object. 593 * Failure: NULL, if any parameter is invalid or memory allocation fails. 594 * 595 * NOTES 596 * Win32 allows arrays with 0 sized dimensions. This bug is not reproduced 597 * in the Wine implementation. 598 * See SafeArray. 599 */ 600 SAFEARRAY* WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound) 601 { 602 TRACE("(%s,%u,%p)\n", debugstr_vt(vt), cDims, rgsabound); 603 604 if (vt == VT_RECORD) 605 return NULL; 606 607 return SAFEARRAY_Create(vt, cDims, rgsabound, 0); 608 } 609 610 /************************************************************************* 611 * SafeArrayCreateEx (OLEAUT32.15) 612 * 613 * Create a new SafeArray. 614 * 615 * PARAMS 616 * vt [I] Type to store in the safe array 617 * cDims [I] Number of array dimensions 618 * rgsabound [I] Bounds of the array dimensions 619 * pvExtra [I] Extra data 620 * 621 * RETURNS 622 * Success: A pointer to a new array object. 623 * Failure: NULL, if any parameter is invalid or memory allocation fails. 624 * 625 * NOTES 626 * See SafeArray. 627 */ 628 SAFEARRAY* WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound, LPVOID pvExtra) 629 { 630 ULONG ulSize = 0; 631 IRecordInfo* iRecInfo = pvExtra; 632 SAFEARRAY* psa; 633 634 TRACE("(%s,%u,%p,%p)\n", debugstr_vt(vt), cDims, rgsabound, pvExtra); 635 636 if (vt == VT_RECORD) 637 { 638 if (!iRecInfo) 639 return NULL; 640 IRecordInfo_GetSize(iRecInfo, &ulSize); 641 } 642 psa = SAFEARRAY_Create(vt, cDims, rgsabound, ulSize); 643 644 if (pvExtra) 645 { 646 switch(vt) 647 { 648 case VT_RECORD: 649 SafeArraySetRecordInfo(psa, pvExtra); 650 break; 651 case VT_UNKNOWN: 652 case VT_DISPATCH: 653 SafeArraySetIID(psa, pvExtra); 654 break; 655 } 656 } 657 return psa; 658 } 659 660 /************************************************************************ 661 * SafeArrayCreateVector (OLEAUT32.411) 662 * 663 * Create a one dimensional, contiguous SafeArray. 664 * 665 * PARAMS 666 * vt [I] Type to store in the safe array 667 * lLbound [I] Lower bound of the array 668 * cElements [I] Number of elements in the array 669 * 670 * RETURNS 671 * Success: A pointer to a new array object. 672 * Failure: NULL, if any parameter is invalid or memory allocation fails. 673 * 674 * NOTES 675 * See SafeArray. 676 */ 677 SAFEARRAY* WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements) 678 { 679 TRACE("(%s,%d,%u)\n", debugstr_vt(vt), lLbound, cElements); 680 681 if (vt == VT_RECORD) 682 return NULL; 683 684 return SAFEARRAY_CreateVector(vt, lLbound, cElements, SAFEARRAY_GetVTSize(vt)); 685 } 686 687 /************************************************************************ 688 * SafeArrayCreateVectorEx (OLEAUT32.411) 689 * 690 * Create a one dimensional, contiguous SafeArray. 691 * 692 * PARAMS 693 * vt [I] Type to store in the safe array 694 * lLbound [I] Lower bound of the array 695 * cElements [I] Number of elements in the array 696 * pvExtra [I] Extra data 697 * 698 * RETURNS 699 * Success: A pointer to a new array object. 700 * Failure: NULL, if any parameter is invalid or memory allocation fails. 701 * 702 * NOTES 703 * See SafeArray. 704 */ 705 SAFEARRAY* WINAPI SafeArrayCreateVectorEx(VARTYPE vt, LONG lLbound, ULONG cElements, LPVOID pvExtra) 706 { 707 ULONG ulSize; 708 IRecordInfo* iRecInfo = pvExtra; 709 SAFEARRAY* psa; 710 711 TRACE("(%s,%d,%u,%p)\n", debugstr_vt(vt), lLbound, cElements, pvExtra); 712 713 if (vt == VT_RECORD) 714 { 715 if (!iRecInfo) 716 return NULL; 717 IRecordInfo_GetSize(iRecInfo, &ulSize); 718 } 719 else 720 ulSize = SAFEARRAY_GetVTSize(vt); 721 722 psa = SAFEARRAY_CreateVector(vt, lLbound, cElements, ulSize); 723 724 if (pvExtra) 725 { 726 switch(vt) 727 { 728 case VT_RECORD: 729 SafeArraySetRecordInfo(psa, iRecInfo); 730 break; 731 case VT_UNKNOWN: 732 case VT_DISPATCH: 733 SafeArraySetIID(psa, pvExtra); 734 break; 735 } 736 } 737 return psa; 738 } 739 740 /************************************************************************* 741 * SafeArrayDestroyDescriptor (OLEAUT32.38) 742 * 743 * Destroy a SafeArray. 744 * 745 * PARAMS 746 * psa [I] SafeArray to destroy. 747 * 748 * RETURNS 749 * Success: S_OK. The resources used by the array are freed. 750 * Failure: An HRESULT error code indicating the error. 751 * 752 * NOTES 753 * See SafeArray. 754 */ 755 HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa) 756 { 757 TRACE("(%p)\n", psa); 758 759 if (psa) 760 { 761 LPVOID lpv = (char*)psa - SAFEARRAY_HIDDEN_SIZE; 762 763 if (psa->cLocks) 764 return DISP_E_ARRAYISLOCKED; /* Can't destroy a locked array */ 765 766 if (psa->fFeatures & FADF_RECORD) 767 SafeArraySetRecordInfo(psa, NULL); 768 769 if (psa->fFeatures & FADF_CREATEVECTOR && 770 !(psa->fFeatures & FADF_DATADELETED)) 771 SAFEARRAY_DestroyData(psa, 0); /* Data not previously deleted */ 772 773 SAFEARRAY_Free(lpv); 774 } 775 return S_OK; 776 } 777 778 /************************************************************************* 779 * SafeArrayLock (OLEAUT32.21) 780 * 781 * Increment the lock counter of a SafeArray. 782 * 783 * PARAMS 784 * psa [O] SafeArray to lock 785 * 786 * RETURNS 787 * Success: S_OK. The array lock is incremented. 788 * Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if too many locks 789 * are held on the array at once. 790 * 791 * NOTES 792 * In Win32 these locks are not thread safe. 793 * See SafeArray. 794 */ 795 HRESULT WINAPI SafeArrayLock(SAFEARRAY *psa) 796 { 797 ULONG ulLocks; 798 799 TRACE("(%p)\n", psa); 800 801 if (!psa) 802 return E_INVALIDARG; 803 804 ulLocks = InterlockedIncrement( (LONG*) &psa->cLocks); 805 806 if (ulLocks > 0xffff) /* Maximum of 16384 locks at a time */ 807 { 808 WARN("Out of locks!\n"); 809 InterlockedDecrement( (LONG*) &psa->cLocks); 810 return E_UNEXPECTED; 811 } 812 return S_OK; 813 } 814 815 /************************************************************************* 816 * SafeArrayUnlock (OLEAUT32.22) 817 * 818 * Decrement the lock counter of a SafeArray. 819 * 820 * PARAMS 821 * psa [O] SafeArray to unlock 822 * 823 * RETURNS 824 * Success: S_OK. The array lock is decremented. 825 * Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if no locks are 826 * held on the array. 827 * 828 * NOTES 829 * See SafeArray. 830 */ 831 HRESULT WINAPI SafeArrayUnlock(SAFEARRAY *psa) 832 { 833 TRACE("(%p)\n", psa); 834 835 if (!psa) 836 return E_INVALIDARG; 837 838 if (InterlockedDecrement( (LONG*) &psa->cLocks) < 0) 839 { 840 WARN("Unlocked but no lock held!\n"); 841 InterlockedIncrement( (LONG*) &psa->cLocks); 842 return E_UNEXPECTED; 843 } 844 return S_OK; 845 } 846 847 /************************************************************************* 848 * SafeArrayPutElement (OLEAUT32.26) 849 * 850 * Put an item into a SafeArray. 851 * 852 * PARAMS 853 * psa [I] SafeArray to insert into 854 * rgIndices [I] Indices to insert at 855 * pvData [I] Data to insert 856 * 857 * RETURNS 858 * Success: S_OK. The item is inserted 859 * Failure: An HRESULT error code indicating the error. 860 * 861 * NOTES 862 * See SafeArray. 863 */ 864 HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData) 865 { 866 HRESULT hRet; 867 868 TRACE("(%p,%p,%p)\n", psa, rgIndices, pvData); 869 870 if (!psa || !rgIndices) 871 return E_INVALIDARG; 872 873 hRet = SafeArrayLock(psa); 874 875 if (SUCCEEDED(hRet)) 876 { 877 PVOID lpvDest; 878 879 hRet = SafeArrayPtrOfIndex(psa, rgIndices, &lpvDest); 880 881 if (SUCCEEDED(hRet)) 882 { 883 if (psa->fFeatures & FADF_VARIANT) 884 { 885 VARIANT* lpVariant = pvData; 886 VARIANT* lpDest = lpvDest; 887 888 hRet = VariantCopy(lpDest, lpVariant); 889 if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet); 890 } 891 else if (psa->fFeatures & FADF_BSTR) 892 { 893 BSTR lpBstr = (BSTR)pvData; 894 BSTR* lpDest = lpvDest; 895 896 SysFreeString(*lpDest); 897 898 *lpDest = SysAllocStringByteLen((char*)lpBstr, SysStringByteLen(lpBstr)); 899 if (!*lpDest) 900 hRet = E_OUTOFMEMORY; 901 } 902 else if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH)) 903 { 904 IUnknown *lpUnknown = pvData; 905 IUnknown **lpDest = lpvDest; 906 907 if (lpUnknown) 908 IUnknown_AddRef(lpUnknown); 909 if (*lpDest) 910 IUnknown_Release(*lpDest); 911 *lpDest = lpUnknown; 912 } 913 else if (psa->fFeatures & FADF_RECORD) 914 { 915 IRecordInfo *record; 916 917 SafeArrayGetRecordInfo(psa, &record); 918 hRet = IRecordInfo_RecordCopy(record, pvData, lpvDest); 919 IRecordInfo_Release(record); 920 } else 921 /* Copy the data over */ 922 memcpy(lpvDest, pvData, psa->cbElements); 923 } 924 SafeArrayUnlock(psa); 925 } 926 return hRet; 927 } 928 929 930 /************************************************************************* 931 * SafeArrayGetElement (OLEAUT32.25) 932 * 933 * Get an item from a SafeArray. 934 * 935 * PARAMS 936 * psa [I] SafeArray to get from 937 * rgIndices [I] Indices to get from 938 * pvData [O] Destination for data 939 * 940 * RETURNS 941 * Success: S_OK. The item data is returned in pvData. 942 * Failure: An HRESULT error code indicating the error. 943 * 944 * NOTES 945 * See SafeArray. 946 */ 947 HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData) 948 { 949 HRESULT hRet; 950 951 TRACE("(%p,%p,%p)\n", psa, rgIndices, pvData); 952 953 if (!psa || !rgIndices || !pvData) 954 return E_INVALIDARG; 955 956 hRet = SafeArrayLock(psa); 957 958 if (SUCCEEDED(hRet)) 959 { 960 PVOID lpvSrc; 961 962 hRet = SafeArrayPtrOfIndex(psa, rgIndices, &lpvSrc); 963 964 if (SUCCEEDED(hRet)) 965 { 966 if (psa->fFeatures & FADF_VARIANT) 967 { 968 VARIANT* lpVariant = lpvSrc; 969 VARIANT* lpDest = pvData; 970 971 /* The original content of pvData is ignored. */ 972 V_VT(lpDest) = VT_EMPTY; 973 hRet = VariantCopy(lpDest, lpVariant); 974 if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet); 975 } 976 else if (psa->fFeatures & FADF_BSTR) 977 { 978 BSTR* lpBstr = lpvSrc; 979 BSTR* lpDest = pvData; 980 981 if (*lpBstr) 982 { 983 *lpDest = SysAllocStringByteLen((char*)*lpBstr, SysStringByteLen(*lpBstr)); 984 if (!*lpBstr) 985 hRet = E_OUTOFMEMORY; 986 } 987 else 988 *lpDest = NULL; 989 } 990 else if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH)) 991 { 992 IUnknown **src_unk = lpvSrc; 993 IUnknown **dest_unk = pvData; 994 995 if (*src_unk) 996 IUnknown_AddRef(*src_unk); 997 *dest_unk = *src_unk; 998 } 999 else if (psa->fFeatures & FADF_RECORD) 1000 { 1001 IRecordInfo *record; 1002 1003 SafeArrayGetRecordInfo(psa, &record); 1004 hRet = IRecordInfo_RecordCopy(record, lpvSrc, pvData); 1005 IRecordInfo_Release(record); 1006 } 1007 else 1008 /* Copy the data over */ 1009 memcpy(pvData, lpvSrc, psa->cbElements); 1010 } 1011 SafeArrayUnlock(psa); 1012 } 1013 return hRet; 1014 } 1015 1016 /************************************************************************* 1017 * SafeArrayGetUBound (OLEAUT32.19) 1018 * 1019 * Get the upper bound for a given SafeArray dimension 1020 * 1021 * PARAMS 1022 * psa [I] Array to get dimension upper bound from 1023 * nDim [I] The dimension number to get the upper bound of 1024 * plUbound [O] Destination for the upper bound 1025 * 1026 * RETURNS 1027 * Success: S_OK. plUbound contains the dimensions upper bound. 1028 * Failure: An HRESULT error code indicating the error. 1029 * 1030 * NOTES 1031 * See SafeArray. 1032 */ 1033 HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound) 1034 { 1035 TRACE("(%p,%d,%p)\n", psa, nDim, plUbound); 1036 1037 if (!psa || !plUbound) 1038 return E_INVALIDARG; 1039 1040 if(!nDim || nDim > psa->cDims) 1041 return DISP_E_BADINDEX; 1042 1043 *plUbound = psa->rgsabound[psa->cDims - nDim].lLbound + 1044 psa->rgsabound[psa->cDims - nDim].cElements - 1; 1045 1046 return S_OK; 1047 } 1048 1049 /************************************************************************* 1050 * SafeArrayGetLBound (OLEAUT32.20) 1051 * 1052 * Get the lower bound for a given SafeArray dimension 1053 * 1054 * PARAMS 1055 * psa [I] Array to get dimension lower bound from 1056 * nDim [I] The dimension number to get the lower bound of 1057 * plLbound [O] Destination for the lower bound 1058 * 1059 * RETURNS 1060 * Success: S_OK. plUbound contains the dimensions lower bound. 1061 * Failure: An HRESULT error code indicating the error. 1062 * 1063 * NOTES 1064 * See SafeArray. 1065 */ 1066 HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound) 1067 { 1068 TRACE("(%p,%d,%p)\n", psa, nDim, plLbound); 1069 1070 if (!psa || !plLbound) 1071 return E_INVALIDARG; 1072 1073 if(!nDim || nDim > psa->cDims) 1074 return DISP_E_BADINDEX; 1075 1076 *plLbound = psa->rgsabound[psa->cDims - nDim].lLbound; 1077 return S_OK; 1078 } 1079 1080 /************************************************************************* 1081 * SafeArrayGetDim (OLEAUT32.17) 1082 * 1083 * Get the number of dimensions in a SafeArray. 1084 * 1085 * PARAMS 1086 * psa [I] Array to get the dimensions of 1087 * 1088 * RETURNS 1089 * The number of array dimensions in psa, or 0 if psa is NULL. 1090 * 1091 * NOTES 1092 * See SafeArray. 1093 */ 1094 UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa) 1095 { 1096 TRACE("(%p) returning %d\n", psa, psa ? psa->cDims : 0u); 1097 return psa ? psa->cDims : 0; 1098 } 1099 1100 /************************************************************************* 1101 * SafeArrayGetElemsize (OLEAUT32.18) 1102 * 1103 * Get the size of an element in a SafeArray. 1104 * 1105 * PARAMS 1106 * psa [I] Array to get the element size from 1107 * 1108 * RETURNS 1109 * The size of a single element in psa, or 0 if psa is NULL. 1110 * 1111 * NOTES 1112 * See SafeArray. 1113 */ 1114 UINT WINAPI SafeArrayGetElemsize(SAFEARRAY *psa) 1115 { 1116 TRACE("(%p) returning %d\n", psa, psa ? psa->cbElements : 0u); 1117 return psa ? psa->cbElements : 0; 1118 } 1119 1120 /************************************************************************* 1121 * SafeArrayAccessData (OLEAUT32.23) 1122 * 1123 * Lock a SafeArray and return a pointer to its data. 1124 * 1125 * PARAMS 1126 * psa [I] Array to get the data pointer from 1127 * ppvData [O] Destination for the arrays data pointer 1128 * 1129 * RETURNS 1130 * Success: S_OK. ppvData contains the arrays data pointer, and the array 1131 * is locked. 1132 * Failure: An HRESULT error code indicating the error. 1133 * 1134 * NOTES 1135 * See SafeArray. 1136 */ 1137 HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData) 1138 { 1139 HRESULT hr; 1140 1141 TRACE("(%p,%p)\n", psa, ppvData); 1142 1143 if(!psa || !ppvData) 1144 return E_INVALIDARG; 1145 1146 hr = SafeArrayLock(psa); 1147 *ppvData = SUCCEEDED(hr) ? psa->pvData : NULL; 1148 1149 return hr; 1150 } 1151 1152 1153 /************************************************************************* 1154 * SafeArrayUnaccessData (OLEAUT32.24) 1155 * 1156 * Unlock a SafeArray after accessing its data. 1157 * 1158 * PARAMS 1159 * psa [I] Array to unlock 1160 * 1161 * RETURNS 1162 * Success: S_OK. The array is unlocked. 1163 * Failure: An HRESULT error code indicating the error. 1164 * 1165 * NOTES 1166 * See SafeArray. 1167 */ 1168 HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa) 1169 { 1170 TRACE("(%p)\n", psa); 1171 return SafeArrayUnlock(psa); 1172 } 1173 1174 /************************************************************************ 1175 * SafeArrayPtrOfIndex (OLEAUT32.148) 1176 * 1177 * Get the address of an item in a SafeArray. 1178 * 1179 * PARAMS 1180 * psa [I] Array to get the items address from 1181 * rgIndices [I] Index of the item in the array 1182 * ppvData [O] Destination for item address 1183 * 1184 * RETURNS 1185 * Success: S_OK. ppvData contains a pointer to the item. 1186 * Failure: An HRESULT error code indicating the error. 1187 * 1188 * NOTES 1189 * This function does not lock the array. 1190 * 1191 * NOTES 1192 * See SafeArray. 1193 */ 1194 HRESULT WINAPI SafeArrayPtrOfIndex(SAFEARRAY *psa, LONG *rgIndices, void **ppvData) 1195 { 1196 USHORT dim; 1197 ULONG cell = 0, dimensionSize = 1; 1198 SAFEARRAYBOUND* psab; 1199 LONG c1; 1200 1201 TRACE("(%p,%p,%p)\n", psa, rgIndices, ppvData); 1202 1203 /* The general formula for locating the cell number of an entry in an n 1204 * dimensional array (where cn = coordinate in dimension dn) is: 1205 * 1206 * c1 + c2 * sizeof(d1) + c3 * sizeof(d2) ... + cn * sizeof(c(n-1)) 1207 * 1208 * We calculate the size of the last dimension at each step through the 1209 * dimensions to avoid recursing to calculate the last dimensions size. 1210 */ 1211 if (!psa || !rgIndices || !ppvData) 1212 return E_INVALIDARG; 1213 1214 psab = psa->rgsabound + psa->cDims - 1; 1215 c1 = *rgIndices++; 1216 1217 if (c1 < psab->lLbound || c1 >= psab->lLbound + (LONG)psab->cElements) 1218 return DISP_E_BADINDEX; /* Initial index out of bounds */ 1219 1220 for (dim = 1; dim < psa->cDims; dim++) 1221 { 1222 dimensionSize *= psab->cElements; 1223 1224 psab--; 1225 1226 if (!psab->cElements || 1227 *rgIndices < psab->lLbound || 1228 *rgIndices >= psab->lLbound + (LONG)psab->cElements) 1229 return DISP_E_BADINDEX; /* Index out of bounds */ 1230 1231 cell += (*rgIndices - psab->lLbound) * dimensionSize; 1232 rgIndices++; 1233 } 1234 1235 cell += (c1 - psa->rgsabound[psa->cDims - 1].lLbound); 1236 1237 *ppvData = (char*)psa->pvData + cell * psa->cbElements; 1238 return S_OK; 1239 } 1240 1241 /************************************************************************ 1242 * SafeArrayDestroyData (OLEAUT32.39) 1243 * 1244 * Destroy the data associated with a SafeArray. 1245 * 1246 * PARAMS 1247 * psa [I] Array to delete the data from 1248 * 1249 * RETURNS 1250 * Success: S_OK. All items and the item data are freed. 1251 * Failure: An HRESULT error code indicating the error. 1252 * 1253 * NOTES 1254 * See SafeArray. 1255 */ 1256 HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa) 1257 { 1258 HRESULT hr; 1259 1260 TRACE("(%p)\n", psa); 1261 1262 if (!psa) 1263 return E_INVALIDARG; 1264 1265 if (psa->cLocks) 1266 return DISP_E_ARRAYISLOCKED; /* Can't delete a locked array */ 1267 1268 /* Delete the actual item data */ 1269 hr = SAFEARRAY_DestroyData(psa, 0); 1270 if (FAILED(hr)) 1271 return hr; 1272 1273 if (psa->pvData) 1274 { 1275 if (psa->fFeatures & FADF_STATIC) 1276 { 1277 ZeroMemory(psa->pvData, SAFEARRAY_GetCellCount(psa) * psa->cbElements); 1278 return S_OK; 1279 } 1280 /* If this is not a vector, free the data memory block */ 1281 if (!(psa->fFeatures & FADF_CREATEVECTOR)) 1282 { 1283 SAFEARRAY_Free(psa->pvData); 1284 psa->pvData = NULL; 1285 } 1286 else 1287 psa->fFeatures |= FADF_DATADELETED; /* Mark the data deleted */ 1288 1289 } 1290 return S_OK; 1291 } 1292 1293 /************************************************************************ 1294 * SafeArrayCopyData (OLEAUT32.412) 1295 * 1296 * Copy all data from one SafeArray to another. 1297 * 1298 * PARAMS 1299 * psaSource [I] Source for copy 1300 * psaTarget [O] Destination for copy 1301 * 1302 * RETURNS 1303 * Success: S_OK. psaTarget contains a copy of psaSource. 1304 * Failure: An HRESULT error code indicating the error. 1305 * 1306 * NOTES 1307 * The two arrays must have the same number of dimensions and elements. 1308 * 1309 * NOTES 1310 * See SafeArray. 1311 */ 1312 HRESULT WINAPI SafeArrayCopyData(SAFEARRAY *psaSource, SAFEARRAY *psaTarget) 1313 { 1314 int dim; 1315 1316 TRACE("(%p,%p)\n", psaSource, psaTarget); 1317 1318 if (!psaSource || !psaTarget || 1319 psaSource->cDims != psaTarget->cDims || 1320 psaSource->cbElements != psaTarget->cbElements) 1321 return E_INVALIDARG; 1322 1323 /* Each dimension must be the same size */ 1324 for (dim = psaSource->cDims - 1; dim >= 0 ; dim--) 1325 if (psaSource->rgsabound[dim].cElements != 1326 psaTarget->rgsabound[dim].cElements) 1327 return E_INVALIDARG; 1328 1329 return SAFEARRAY_CopyData(psaSource, psaTarget); 1330 } 1331 1332 /************************************************************************ 1333 * SafeArrayDestroy (OLEAUT32.16) 1334 * 1335 * Destroy a SafeArray. 1336 * 1337 * PARAMS 1338 * psa [I] Array to destroy 1339 * 1340 * RETURNS 1341 * Success: S_OK. All resources used by the array are freed. 1342 * Failure: An HRESULT error code indicating the error. 1343 * 1344 * NOTES 1345 * See SafeArray. 1346 */ 1347 HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa) 1348 { 1349 TRACE("(%p)\n", psa); 1350 1351 if(!psa) 1352 return S_OK; 1353 1354 if(psa->cLocks > 0) 1355 return DISP_E_ARRAYISLOCKED; 1356 1357 /* Native doesn't check to see if the free succeeds */ 1358 SafeArrayDestroyData(psa); 1359 SafeArrayDestroyDescriptor(psa); 1360 return S_OK; 1361 } 1362 1363 /************************************************************************ 1364 * SafeArrayCopy (OLEAUT32.27) 1365 * 1366 * Make a duplicate of a SafeArray. 1367 * 1368 * PARAMS 1369 * psa [I] Source for copy 1370 * ppsaOut [O] Destination for new copy 1371 * 1372 * RETURNS 1373 * Success: S_OK. ppsaOut contains a copy of the array. 1374 * Failure: An HRESULT error code indicating the error. 1375 * 1376 * NOTES 1377 * See SafeArray. 1378 */ 1379 HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut) 1380 { 1381 HRESULT hRet; 1382 1383 TRACE("(%p,%p)\n", psa, ppsaOut); 1384 1385 if (!ppsaOut) 1386 return E_INVALIDARG; 1387 1388 *ppsaOut = NULL; 1389 1390 if (!psa) 1391 return S_OK; /* Handles copying of NULL arrays */ 1392 1393 if (!psa->cbElements) 1394 return E_INVALIDARG; 1395 1396 if (psa->fFeatures & (FADF_RECORD|FADF_HAVEIID|FADF_HAVEVARTYPE)) 1397 { 1398 VARTYPE vt; 1399 1400 hRet = SafeArrayGetVartype(psa, &vt); 1401 if (SUCCEEDED(hRet)) 1402 hRet = SafeArrayAllocDescriptorEx(vt, psa->cDims, ppsaOut); 1403 } 1404 else 1405 { 1406 hRet = SafeArrayAllocDescriptor(psa->cDims, ppsaOut); 1407 if (SUCCEEDED(hRet)) 1408 { 1409 (*ppsaOut)->fFeatures = psa->fFeatures & ~ignored_copy_features; 1410 (*ppsaOut)->cbElements = psa->cbElements; 1411 } 1412 } 1413 1414 if (SUCCEEDED(hRet)) 1415 { 1416 /* Copy dimension bounds */ 1417 memcpy((*ppsaOut)->rgsabound, psa->rgsabound, psa->cDims * sizeof(SAFEARRAYBOUND)); 1418 1419 (*ppsaOut)->pvData = SAFEARRAY_Malloc(SAFEARRAY_GetCellCount(psa) * psa->cbElements); 1420 if (!(*ppsaOut)->pvData) 1421 { 1422 SafeArrayDestroyDescriptor(*ppsaOut); 1423 *ppsaOut = NULL; 1424 return E_OUTOFMEMORY; 1425 } 1426 1427 hRet = SAFEARRAY_CopyData(psa, *ppsaOut); 1428 if (FAILED(hRet)) 1429 { 1430 SAFEARRAY_Free((*ppsaOut)->pvData); 1431 SafeArrayDestroyDescriptor(*ppsaOut); 1432 *ppsaOut = NULL; 1433 return hRet; 1434 } 1435 } 1436 1437 return hRet; 1438 } 1439 1440 /************************************************************************ 1441 * SafeArrayRedim (OLEAUT32.40) 1442 * 1443 * Changes the characteristics of the last dimension of a SafeArray 1444 * 1445 * PARAMS 1446 * psa [I] Array to change 1447 * psabound [I] New bound details for the last dimension 1448 * 1449 * RETURNS 1450 * Success: S_OK. psa is updated to reflect the new bounds. 1451 * Failure: An HRESULT error code indicating the error. 1452 * 1453 * NOTES 1454 * See SafeArray. 1455 */ 1456 HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound) 1457 { 1458 SAFEARRAYBOUND *oldBounds; 1459 HRESULT hr; 1460 1461 TRACE("(%p,%p)\n", psa, psabound); 1462 1463 if (!psa || psa->fFeatures & FADF_FIXEDSIZE || !psabound) 1464 return E_INVALIDARG; 1465 1466 if (psa->cLocks > 0) 1467 return DISP_E_ARRAYISLOCKED; 1468 1469 hr = SafeArrayLock(psa); 1470 if (FAILED(hr)) 1471 return hr; 1472 1473 oldBounds = psa->rgsabound; 1474 oldBounds->lLbound = psabound->lLbound; 1475 1476 if (psabound->cElements != oldBounds->cElements) 1477 { 1478 if (psabound->cElements < oldBounds->cElements) 1479 { 1480 /* Shorten the final dimension. */ 1481 ULONG ulStartCell = psabound->cElements * 1482 (SAFEARRAY_GetCellCount(psa) / oldBounds->cElements); 1483 SAFEARRAY_DestroyData(psa, ulStartCell); 1484 } 1485 else 1486 { 1487 /* Lengthen the final dimension */ 1488 ULONG ulOldSize, ulNewSize; 1489 PVOID pvNewData; 1490 1491 ulOldSize = SAFEARRAY_GetCellCount(psa) * psa->cbElements; 1492 if (ulOldSize) 1493 ulNewSize = (ulOldSize / oldBounds->cElements) * psabound->cElements; 1494 else { 1495 int oldelems = oldBounds->cElements; 1496 oldBounds->cElements = psabound->cElements; 1497 ulNewSize = SAFEARRAY_GetCellCount(psa) * psa->cbElements; 1498 oldBounds->cElements = oldelems; 1499 } 1500 1501 if (!(pvNewData = SAFEARRAY_Malloc(ulNewSize))) 1502 { 1503 SafeArrayUnlock(psa); 1504 return E_OUTOFMEMORY; 1505 } 1506 1507 memcpy(pvNewData, psa->pvData, ulOldSize); 1508 SAFEARRAY_Free(psa->pvData); 1509 psa->pvData = pvNewData; 1510 } 1511 oldBounds->cElements = psabound->cElements; 1512 } 1513 1514 SafeArrayUnlock(psa); 1515 return S_OK; 1516 } 1517 1518 /************************************************************************ 1519 * SafeArrayGetVartype (OLEAUT32.77) 1520 * 1521 * Get the type of the items in a SafeArray. 1522 * 1523 * PARAMS 1524 * psa [I] Array to get the type from 1525 * pvt [O] Destination for the type 1526 * 1527 * RETURNS 1528 * Success: S_OK. pvt contains the type of the items. 1529 * Failure: An HRESULT error code indicating the error. 1530 * 1531 * NOTES 1532 * See SafeArray. 1533 */ 1534 HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY* psa, VARTYPE* pvt) 1535 { 1536 TRACE("(%p,%p)\n", psa, pvt); 1537 1538 if (!psa || !pvt) 1539 return E_INVALIDARG; 1540 1541 if (psa->fFeatures & FADF_RECORD) 1542 *pvt = VT_RECORD; 1543 else if ((psa->fFeatures & (FADF_HAVEIID|FADF_DISPATCH)) == (FADF_HAVEIID|FADF_DISPATCH)) 1544 *pvt = VT_DISPATCH; 1545 else if (psa->fFeatures & FADF_HAVEIID) 1546 *pvt = VT_UNKNOWN; 1547 else if (psa->fFeatures & FADF_HAVEVARTYPE) 1548 { 1549 VARTYPE vt = SAFEARRAY_GetHiddenDWORD(psa); 1550 *pvt = vt; 1551 } 1552 else 1553 return E_INVALIDARG; 1554 1555 return S_OK; 1556 } 1557 1558 /************************************************************************ 1559 * SafeArraySetRecordInfo (OLEAUT32.@) 1560 * 1561 * Set the record info for a SafeArray. 1562 * 1563 * PARAMS 1564 * psa [I] Array to set the record info for 1565 * pRinfo [I] Record info 1566 * 1567 * RETURNS 1568 * Success: S_OK. The record info is stored with the array. 1569 * Failure: An HRESULT error code indicating the error. 1570 * 1571 * NOTES 1572 * See SafeArray. 1573 */ 1574 HRESULT WINAPI SafeArraySetRecordInfo(SAFEARRAY *psa, IRecordInfo *pRinfo) 1575 { 1576 IRecordInfo** dest = (IRecordInfo**)psa; 1577 1578 TRACE("(%p,%p)\n", psa, pRinfo); 1579 1580 if (!psa || !(psa->fFeatures & FADF_RECORD)) 1581 return E_INVALIDARG; 1582 1583 if (pRinfo) 1584 IRecordInfo_AddRef(pRinfo); 1585 1586 if (dest[-1]) 1587 IRecordInfo_Release(dest[-1]); 1588 1589 dest[-1] = pRinfo; 1590 return S_OK; 1591 } 1592 1593 /************************************************************************ 1594 * SafeArrayGetRecordInfo (OLEAUT32.@) 1595 * 1596 * Get the record info from a SafeArray. 1597 * 1598 * PARAMS 1599 * psa [I] Array to get the record info from 1600 * pRinfo [O] Destination for the record info 1601 * 1602 * RETURNS 1603 * Success: S_OK. pRinfo contains the record info, or NULL if there was none. 1604 * Failure: An HRESULT error code indicating the error. 1605 * 1606 * NOTES 1607 * See SafeArray. 1608 */ 1609 HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY *psa, IRecordInfo **pRinfo) 1610 { 1611 IRecordInfo** src = (IRecordInfo**)psa; 1612 1613 TRACE("(%p,%p)\n", psa, pRinfo); 1614 1615 if (!psa || !pRinfo || !(psa->fFeatures & FADF_RECORD)) 1616 return E_INVALIDARG; 1617 1618 *pRinfo = src[-1]; 1619 1620 if (*pRinfo) 1621 IRecordInfo_AddRef(*pRinfo); 1622 return S_OK; 1623 } 1624 1625 /************************************************************************ 1626 * SafeArraySetIID (OLEAUT32.@) 1627 * 1628 * Set the IID for a SafeArray. 1629 * 1630 * PARAMS 1631 * psa [I] Array to set the IID from 1632 * guid [I] IID 1633 * 1634 * RETURNS 1635 * Success: S_OK. The IID is stored with the array 1636 * Failure: An HRESULT error code indicating the error. 1637 * 1638 * NOTES 1639 * See SafeArray. 1640 */ 1641 HRESULT WINAPI SafeArraySetIID(SAFEARRAY *psa, REFGUID guid) 1642 { 1643 GUID* dest = (GUID*)psa; 1644 1645 TRACE("(%p,%s)\n", psa, debugstr_guid(guid)); 1646 1647 if (!psa || !guid || !(psa->fFeatures & FADF_HAVEIID)) 1648 return E_INVALIDARG; 1649 1650 dest[-1] = *guid; 1651 return S_OK; 1652 } 1653 1654 /************************************************************************ 1655 * SafeArrayGetIID (OLEAUT32.@) 1656 * 1657 * Get the IID from a SafeArray. 1658 * 1659 * PARAMS 1660 * psa [I] Array to get the ID from 1661 * pGuid [O] Destination for the IID 1662 * 1663 * RETURNS 1664 * Success: S_OK. pRinfo contains the IID, or NULL if there was none. 1665 * Failure: An HRESULT error code indicating the error. 1666 * 1667 * NOTES 1668 * See SafeArray. 1669 */ 1670 HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid) 1671 { 1672 GUID* src = (GUID*)psa; 1673 1674 TRACE("(%p,%p)\n", psa, pGuid); 1675 1676 if (!psa || !pGuid || !(psa->fFeatures & FADF_HAVEIID)) 1677 return E_INVALIDARG; 1678 1679 *pGuid = src[-1]; 1680 return S_OK; 1681 } 1682 1683 /************************************************************************ 1684 * VectorFromBstr (OLEAUT32.@) 1685 * 1686 * Create a SafeArray Vector from the bytes of a BSTR. 1687 * 1688 * PARAMS 1689 * bstr [I] String to get bytes from 1690 * ppsa [O] Destination for the array 1691 * 1692 * RETURNS 1693 * Success: S_OK. ppsa contains the strings bytes as a VT_UI1 array. 1694 * Failure: An HRESULT error code indicating the error. 1695 * 1696 * NOTES 1697 * See SafeArray. 1698 */ 1699 HRESULT WINAPI VectorFromBstr(BSTR bstr, SAFEARRAY **ppsa) 1700 { 1701 SAFEARRAYBOUND sab; 1702 1703 TRACE("(%p,%p)\n", bstr, ppsa); 1704 1705 if (!ppsa) 1706 return E_INVALIDARG; 1707 1708 sab.lLbound = 0; 1709 sab.cElements = SysStringByteLen(bstr); 1710 1711 *ppsa = SAFEARRAY_Create(VT_UI1, 1, &sab, 0); 1712 1713 if (*ppsa) 1714 { 1715 memcpy((*ppsa)->pvData, bstr, sab.cElements); 1716 return S_OK; 1717 } 1718 return E_OUTOFMEMORY; 1719 } 1720 1721 /************************************************************************ 1722 * BstrFromVector (OLEAUT32.@) 1723 * 1724 * Create a BSTR from a SafeArray. 1725 * 1726 * PARAMS 1727 * psa [I] Source array 1728 * pbstr [O] Destination for output BSTR 1729 * 1730 * RETURNS 1731 * Success: S_OK. pbstr contains the arrays data. 1732 * Failure: An HRESULT error code indicating the error. 1733 * 1734 * NOTES 1735 * psa must be a 1 dimensional array of a 1 byte type. 1736 * 1737 * NOTES 1738 * See SafeArray. 1739 */ 1740 HRESULT WINAPI BstrFromVector(SAFEARRAY *psa, BSTR *pbstr) 1741 { 1742 TRACE("(%p,%p)\n", psa, pbstr); 1743 1744 if (!pbstr) 1745 return E_INVALIDARG; 1746 1747 *pbstr = NULL; 1748 1749 if (!psa || psa->cbElements != 1 || psa->cDims != 1) 1750 return E_INVALIDARG; 1751 1752 *pbstr = SysAllocStringByteLen(psa->pvData, psa->rgsabound[0].cElements); 1753 if (!*pbstr) 1754 return E_OUTOFMEMORY; 1755 return S_OK; 1756 } 1757