📄 safearray.c
字号:
if (vt == VT_RECORD)
return NULL;
return SAFEARRAY_Create(vt, cDims, rgsabound, 0);
}
/*************************************************************************
* 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 = (IRecordInfo*)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;
}
/************************************************************************
* SafeArrayCreateVector (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
*
* 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 SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
{
TRACE("(%d->%s,%d,%d\n", vt, debugstr_vt(vt), lLbound, cElements);
if (vt == VT_RECORD)
return NULL;
return SAFEARRAY_CreateVector(vt, lLbound, cElements, SAFEARRAY_GetVTSize(vt));
}
/************************************************************************
* 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 = (IRecordInfo*)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;
}
/*************************************************************************
* 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 */
if (!SAFEARRAY_Free(lpv))
return E_UNEXPECTED;
}
return S_OK;
}
/*************************************************************************
* SafeArrayLock (OLEAUT32.21)
*
* Increment the lock counter of a SafeArray.
*
* PARAMS
* psa [O] SafeArray to lock
*
* RETURNS
* Success: S_OK. The array lock is incremented.
* Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if too many locks
* are held on the array at once.
*
* NOTES
* In Win32 these locks are not thread safe.
* See SafeArray.
*/
HRESULT WINAPI SafeArrayLock(SAFEARRAY *psa)
{
ULONG ulLocks;
TRACE("(%p)\n", psa);
if (!psa)
return E_INVALIDARG;
ulLocks = InterlockedIncrement( (LONG*) &psa->cLocks);
if (ulLocks > 0xffff) /* Maximum of 16384 locks at a time */
{
WARN("Out of locks!\n");
InterlockedDecrement( (LONG*) &psa->cLocks);
return E_UNEXPECTED;
}
return S_OK;
}
/*************************************************************************
* SafeArrayUnlock (OLEAUT32.22)
*
* Decrement the lock counter of a SafeArray.
*
* PARAMS
* psa [O] SafeArray to unlock
*
* RETURNS
* Success: S_OK. The array lock is decremented.
* Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if no locks are
* held on the array.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayUnlock(SAFEARRAY *psa)
{
TRACE("(%p)\n", psa);
if (!psa)
return E_INVALIDARG;
if ((LONG)InterlockedDecrement( (LONG*) &psa->cLocks) < 0)
{
WARN("Unlocked but no lock held!\n");
InterlockedIncrement( (LONG*) &psa->cLocks);
return E_UNEXPECTED;
}
return S_OK;
}
/*************************************************************************
* SafeArrayPutElement (OLEAUT32.26)
*
* Put an item into a SafeArray.
*
* PARAMS
* psa [I] SafeArray to insert into
* rgIndices [I] Indices to insert at
* pvData [I] Data to insert
*
* RETURNS
* Success: S_OK. The item is inserted
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
{
HRESULT hRet;
TRACE("(%p,%p,%p)\n", psa, rgIndices, pvData);
if (!psa || !rgIndices)
return E_INVALIDARG;
hRet = SafeArrayLock(psa);
if (SUCCEEDED(hRet))
{
PVOID lpvDest;
hRet = SafeArrayPtrOfIndex(psa, rgIndices, &lpvDest);
if (SUCCEEDED(hRet))
{
if (psa->fFeatures & FADF_VARIANT)
{
VARIANT* lpVariant = (VARIANT*)pvData;
VARIANT* lpDest = (VARIANT*)lpvDest;
hRet = VariantClear(lpDest);
if (FAILED(hRet)) FIXME("VariantClear failed with 0x%x\n", hRet);
hRet = VariantCopy(lpDest, lpVariant);
if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet);
}
else if (psa->fFeatures & FADF_BSTR)
{
BSTR lpBstr = (BSTR)pvData;
BSTR* lpDest = (BSTR*)lpvDest;
if (*lpDest)
SysFreeString(*lpDest);
*lpDest = SysAllocStringByteLen((char*)lpBstr, SysStringByteLen(lpBstr));
if (!*lpDest)
hRet = E_OUTOFMEMORY;
}
else
{
if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
{
LPUNKNOWN lpUnknown = (LPUNKNOWN)pvData;
LPUNKNOWN *lpDest = (LPUNKNOWN *)lpvDest;
if (lpUnknown)
IUnknown_AddRef(lpUnknown);
if (*lpDest)
IUnknown_Release(*lpDest);
*lpDest = lpUnknown;
} else {
/* Copy the data over */
memcpy(lpvDest, pvData, psa->cbElements);
}
}
}
SafeArrayUnlock(psa);
}
return hRet;
}
/*************************************************************************
* SafeArrayGetElement (OLEAUT32.25)
*
* Get an item from a SafeArray.
*
* PARAMS
* psa [I] SafeArray to get from
* rgIndices [I] Indices to get from
* pvData [O] Destination for data
*
* RETURNS
* Success: S_OK. The item data is returned in pvData.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
{
HRESULT hRet;
TRACE("(%p,%p,%p)\n", psa, rgIndices, pvData);
if (!psa || !rgIndices || !pvData)
return E_INVALIDARG;
hRet = SafeArrayLock(psa);
if (SUCCEEDED(hRet))
{
PVOID lpvSrc;
hRet = SafeArrayPtrOfIndex(psa, rgIndices, &lpvSrc);
if (SUCCEEDED(hRet))
{
if (psa->fFeatures & FADF_VARIANT)
{
VARIANT* lpVariant = (VARIANT*)lpvSrc;
VARIANT* lpDest = (VARIANT*)pvData;
/* The original content of pvData is ignored. */
V_VT(lpDest) = VT_EMPTY;
hRet = VariantCopy(lpDest, lpVariant);
if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet);
}
else if (psa->fFeatures & FADF_BSTR)
{
BSTR* lpBstr = (BSTR*)lpvSrc;
BSTR* lpDest = (BSTR*)pvData;
if (*lpBstr)
{
*lpDest = SysAllocStringByteLen((char*)*lpBstr, SysStringByteLen(*lpBstr));
if (!*lpBstr)
hRet = E_OUTOFMEMORY;
}
else
*lpDest = NULL;
}
else
{
if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
{
LPUNKNOWN *lpUnknown = (LPUNKNOWN *)lpvSrc;
if (*lpUnknown)
IUnknown_AddRef(*lpUnknown);
}
/* Copy the data over */
memcpy(pvData, lpvSrc, psa->cbElements);
}
}
SafeArrayUnlock(psa);
}
return hRet;
}
/*************************************************************************
* SafeArrayGetUBound (OLEAUT32.19)
*
* Get the upper bound for a given SafeArray dimension
*
* PARAMS
* psa [I] Array to get dimension upper bound from
* nDim [I] The dimension number to get the upper bound of
* plUbound [O] Destination for the upper bound
*
* RETURNS
* Success: S_OK. plUbound contains the dimensions upper bound.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
{
TRACE("(%p,%d,%p)\n", psa, nDim, plUbound);
if (!psa || !plUbound)
return E_INVALIDARG;
if(!nDim || nDim > psa->cDims)
return DISP_E_BADINDEX;
*plUbound = psa->rgsabound[psa->cDims - nDim].lLbound +
psa->rgsabound[psa->cDims - nDim].cElements - 1;
return S_OK;
}
/*************************************************************************
* SafeArrayGetLBound (OLEAUT32.20)
*
* Get the lower bound for a given SafeArray dimension
*
* PARAMS
* psa [I] Array to get dimension lower bound from
* nDim [I] The dimension number to get the lowe bound of
* plLbound [O] Destination for the lower bound
*
* RETURNS
* Success: S_OK. plUbound contains the dimensions lower bound.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
{
TRACE("(%p,%d,%p)\n", psa, nDim, plLbound);
if (!psa || !plLbound)
return E_INVALIDARG;
if(!nDim || nDim > psa->cDims)
return DISP_E_BADINDEX;
*plLbound = psa->rgsabound[psa->cDims - nDim].lLbound;
return S_OK;
}
/*************************************************************************
* SafeArrayGetDim (OLEAUT32.17)
*
* Get the number of dimensions in a SafeArray.
*
* PARAMS
* psa [I] Array to get the dimensions of
*
* RETURNS
* The number of array dimensions in psa, or 0 if psa is NULL.
*
* NOTES
* See SafeArray.
*/
UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa)
{
TRACE("(%p) returning %d\n", psa, psa ? psa->cDims : 0u);
return psa ? psa->cDims : 0;
}
/*************************************************************************
* SafeArrayGetElemsize (OLEAUT32.18)
*
* Get the size of an element in a SafeArray.
*
* PARAMS
* psa [I] Array to get the element size from
*
* RETURNS
* The size of a single element in psa, or 0 if psa is NULL.
*
* NOTES
* See SafeArray.
*/
UINT WINAPI SafeArrayGetElemsize(SAFEARRAY *psa)
{
TRACE("(%p) returning %d\n", psa, psa ? psa->cbElements : 0u);
return psa ? psa->cbElements : 0;
}
/*************************************************************************
* SafeArrayAccessData (OLEAUT32.23)
*
* Lock a SafeArray and return a pointer to its data.
*
* PARAMS
* psa [I] Array to get the data pointer from
* ppvData [O] Destination for the arrays data pointer
*
* RETURNS
* Success: S_OK. ppvData contains the arrays data pointer, and the array
* is locked.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData)
{
TRACE("(%p,%p)\n", psa, ppvData);
if(!psa || !ppvData)
return E_INVALIDARG;
if (SUCCEEDED(SafeArrayLock(psa)))
{
*ppvData = psa->pvData;
return S_OK;
}
*ppvData = NULL;
return E_UNEXPECTED;
}
/*************************************************************************
* SafeArrayUnaccessData (OLEAUT32.24)
*
* Unlock a SafeArray after accessing its data.
*
* PARAMS
* psa [I] Array to unlock
*
* RETURNS
* Success: S_OK. The array is unlocked.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa)
{
TRACE("(%p)\n", psa);
return SafeArrayUnlock(psa);
}
/************************************************************************
* SafeArrayPtrOfIndex (OLEAUT32.148)
*
* Get the address of an item in a SafeArray.
*
* PARAMS
* psa [I] Array to get the items address from
* rgIndices [I] Index of the item in the array
* ppvData [O] Destination for item address
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -