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