/************************************************************************ * SafeArrayCreateVectorEx (OLEAUT32.411) * * Create a one dimensional, contiguous SafeArray. * * PARAMS * vt [I] Type to store in the safe array * lLbound [I] Lower bound of the array * cElements [I] Number of elements in the array * pvExtra [I] Extra data * * RETURNS * Success: A pointer to a new array object. * Failure: NULL, if any parameter is invalid or memory allocation fails. * * NOTES * See SafeArray. */ SAFEARRAY* WINAPI SafeArrayCreateVectorEx(VARTYPE vt, LONG lLbound, ULONG cElements, LPVOID pvExtra) { ULONG ulSize; IRecordInfo* iRecInfo = pvExtra; SAFEARRAY* psa; TRACE("(%d->%s,%d,%d,%p\n", vt, debugstr_vt(vt), lLbound, cElements, pvExtra); if (vt == VT_RECORD) { if (!iRecInfo) return NULL; IRecordInfo_GetSize(iRecInfo, &ulSize); } else ulSize = SAFEARRAY_GetVTSize(vt); psa = SAFEARRAY_CreateVector(vt, lLbound, cElements, ulSize); if (pvExtra) { switch(vt) { case VT_RECORD: SafeArraySetRecordInfo(psa, iRecInfo); break; case VT_UNKNOWN: case VT_DISPATCH: SafeArraySetIID(psa, pvExtra); break; } } return psa; }
/************************************************************************* * SafeArrayCreateEx (OLEAUT32.15) * * Create a new SafeArray. * * PARAMS * vt [I] Type to store in the safe array * cDims [I] Number of array dimensions * rgsabound [I] Bounds of the array dimensions * pvExtra [I] Extra data * * RETURNS * Success: A pointer to a new array object. * Failure: NULL, if any parameter is invalid or memory allocation fails. * * NOTES * See SafeArray. */ SAFEARRAY* WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound, LPVOID pvExtra) { ULONG ulSize = 0; IRecordInfo* iRecInfo = pvExtra; SAFEARRAY* psa; TRACE("(%d->%s,%d,%p,%p)\n", vt, debugstr_vt(vt), cDims, rgsabound, pvExtra); if (vt == VT_RECORD) { if (!iRecInfo) return NULL; IRecordInfo_GetSize(iRecInfo, &ulSize); } psa = SAFEARRAY_Create(vt, cDims, rgsabound, ulSize); if (pvExtra) { switch(vt) { case VT_RECORD: SafeArraySetRecordInfo(psa, pvExtra); break; case VT_UNKNOWN: case VT_DISPATCH: SafeArraySetIID(psa, pvExtra); break; } } return psa; }
/************************************************************************* * SafeArrayDestroyDescriptor (OLEAUT32.38) * * Destroy a SafeArray. * * PARAMS * psa [I] SafeArray to destroy. * * RETURNS * Success: S_OK. The resources used by the array are freed. * Failure: An HRESULT error code indicating the error. * * NOTES * See SafeArray. */ HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa) { TRACE("(%p)\n", psa); if (psa) { LPVOID lpv = (char*)psa - SAFEARRAY_HIDDEN_SIZE; if (psa->cLocks) return DISP_E_ARRAYISLOCKED; /* Can't destroy a locked array */ if (psa->fFeatures & FADF_RECORD) SafeArraySetRecordInfo(psa, NULL); if (psa->fFeatures & FADF_CREATEVECTOR && !(psa->fFeatures & FADF_DATADELETED)) SAFEARRAY_DestroyData(psa, 0); /* Data not previously deleted */ SAFEARRAY_Free(lpv); } return S_OK; }
/* Copy data items from one array to another. Destination data is freed before copy. */ static HRESULT SAFEARRAY_CopyData(SAFEARRAY *psa, SAFEARRAY *dest) { HRESULT hr = S_OK; if (!psa->pvData) return S_OK; if (!dest->pvData || psa->fFeatures & FADF_DATADELETED) return E_INVALIDARG; else { ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); dest->fFeatures = (dest->fFeatures & FADF_CREATEVECTOR) | (psa->fFeatures & ~ignored_copy_features); if (psa->fFeatures & FADF_VARIANT) { VARIANT *src_var = psa->pvData; VARIANT *dest_var = dest->pvData; while(ulCellCount--) { HRESULT hRet; /* destination is cleared automatically */ hRet = VariantCopy(dest_var, src_var); if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%08x, element %u\n", hRet, ulCellCount); src_var++; dest_var++; } } else if (psa->fFeatures & FADF_BSTR) { BSTR *src_bstr = psa->pvData; BSTR *dest_bstr = dest->pvData; while(ulCellCount--) { SysFreeString(*dest_bstr); if (*src_bstr) { *dest_bstr = SysAllocStringByteLen((char*)*src_bstr, SysStringByteLen(*src_bstr)); if (!*dest_bstr) return E_OUTOFMEMORY; } else *dest_bstr = NULL; src_bstr++; dest_bstr++; } } else if (psa->fFeatures & FADF_RECORD) { BYTE *dest_data = dest->pvData; BYTE *src_data = psa->pvData; IRecordInfo *record; SafeArrayGetRecordInfo(psa, &record); while (ulCellCount--) { /* RecordCopy() clears destination record */ hr = IRecordInfo_RecordCopy(record, src_data, dest_data); if (FAILED(hr)) break; src_data += psa->cbElements; dest_data += psa->cbElements; } SafeArraySetRecordInfo(dest, record); /* This value is set to 32 bytes by default on descriptor creation, update with actual structure size. */ dest->cbElements = psa->cbElements; IRecordInfo_Release(record); } else if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH)) { IUnknown **dest_unk = dest->pvData; IUnknown **src_unk = psa->pvData; /* release old iface, addref new one */ while (ulCellCount--) { if (*dest_unk) IUnknown_Release(*dest_unk); *dest_unk = *src_unk; if (*dest_unk) IUnknown_AddRef(*dest_unk); src_unk++; dest_unk++; } } else { /* Copy the data over */ memcpy(dest->pvData, psa->pvData, ulCellCount * psa->cbElements); } if (psa->fFeatures & FADF_HAVEIID) { GUID guid; SafeArrayGetIID(psa, &guid); SafeArraySetIID(dest, &guid); } else if (psa->fFeatures & FADF_HAVEVARTYPE) { SAFEARRAY_SetHiddenDWORD(dest, SAFEARRAY_GetHiddenDWORD(psa)); } } return hr; }