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