Dimensions with cElements=0 are valid and needed by InstallShield.
SafeArrayGetElement: fixed BSTR and LPUNKNOWN handling. Added testcases for above cases.
This commit is contained in:
parent
09c8cc97f7
commit
e12ef562a8
|
@ -4,6 +4,7 @@
|
|||
* This file contains the implementation of the SafeArray functions.
|
||||
*
|
||||
* Copyright 1999 Sylvain St-Germain
|
||||
* Copyright 2002-2003 Marcus Meissner
|
||||
* Copyright 2003 Jon Griffiths
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
@ -84,9 +85,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
|||
/* Undocumented hidden space before the start of a SafeArray descriptor */
|
||||
#define SAFEARRAY_HIDDEN_SIZE sizeof(GUID)
|
||||
|
||||
/* Value returned by SAFEARRAY_GetCellCount if a dimension is invalid */
|
||||
#define SAFEARRAY_INVALID_CELLS ~0UL
|
||||
|
||||
/* Allocate memory */
|
||||
static inline LPVOID SAFEARRAY_Malloc(ULONG ulSize)
|
||||
{
|
||||
|
@ -162,11 +160,9 @@ static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
|
|||
|
||||
while (cCount--)
|
||||
{
|
||||
/* This is a valid bordercase. See testcases. -Marcus */
|
||||
if (!psab->cElements)
|
||||
{
|
||||
ERR("Dimension has size=0! Please report.\n");
|
||||
return SAFEARRAY_INVALID_CELLS;
|
||||
}
|
||||
return 0;
|
||||
ulNumCells *= psab->cElements;
|
||||
psab++;
|
||||
}
|
||||
|
@ -263,7 +259,7 @@ static SAFEARRAY* SAFEARRAY_CreateVector(VARTYPE vt, LONG lLbound, ULONG cElemen
|
|||
{
|
||||
SAFEARRAY *psa = NULL;
|
||||
|
||||
if (cElements && (vt == VT_RECORD || ulSize))
|
||||
if (ulSize || (vt == VT_RECORD))
|
||||
{
|
||||
/* Allocate the header and data together */
|
||||
if (SUCCEEDED(SAFEARRAY_AllocDescriptor(sizeof(SAFEARRAY) + ulSize * cElements, &psa)))
|
||||
|
@ -286,10 +282,6 @@ static SAFEARRAY* SAFEARRAY_CreateVector(VARTYPE vt, LONG lLbound, ULONG cElemen
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (!cElements)
|
||||
{
|
||||
ERR("Creating vector of size 0! Please report.\n");
|
||||
}
|
||||
return psa;
|
||||
}
|
||||
|
||||
|
@ -300,8 +292,10 @@ static HRESULT SAFEARRAY_DestroyData(SAFEARRAY *psa, ULONG ulStartCell)
|
|||
{
|
||||
ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
|
||||
|
||||
if (ulCellCount == SAFEARRAY_INVALID_CELLS || ulStartCell > ulCellCount)
|
||||
if (ulStartCell > ulCellCount) {
|
||||
FIXME("unexpted ulcellcount %ld, start %ld\n",ulCellCount,ulStartCell);
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ulCellCount -= ulStartCell;
|
||||
|
||||
|
@ -365,9 +359,6 @@ static HRESULT SAFEARRAY_CopyData(SAFEARRAY *psa, SAFEARRAY *dest)
|
|||
{
|
||||
ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
|
||||
|
||||
if (ulCellCount == SAFEARRAY_INVALID_CELLS)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
dest->fFeatures = (dest->fFeatures & FADF_CREATEVECTOR) |
|
||||
(psa->fFeatures & ~(FADF_CREATEVECTOR|FADF_DATADELETED));
|
||||
|
||||
|
@ -554,7 +545,7 @@ HRESULT WINAPI SafeArrayAllocData(SAFEARRAY *psa)
|
|||
|
||||
hRet = E_OUTOFMEMORY;
|
||||
|
||||
if (ulSize != SAFEARRAY_INVALID_CELLS && psa->cbElements)
|
||||
if (psa->cbElements)
|
||||
{
|
||||
psa->pvData = SAFEARRAY_Malloc(ulSize * psa->cbElements);
|
||||
|
||||
|
@ -888,15 +879,15 @@ HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData
|
|||
}
|
||||
else if (psa->fFeatures & FADF_BSTR)
|
||||
{
|
||||
BSTR* lpBstr = (BSTR*)pvData;
|
||||
BSTR lpBstr = (BSTR)pvData;
|
||||
BSTR* lpDest = (BSTR*)lpvDest;
|
||||
|
||||
if (*lpDest)
|
||||
SysFreeString(*lpDest);
|
||||
|
||||
if (*lpBstr)
|
||||
if (lpBstr)
|
||||
{
|
||||
*lpDest = SysAllocStringLen(*lpBstr, SysStringLen(*lpBstr));
|
||||
*lpDest = SysAllocStringLen(lpBstr, SysStringLen(lpBstr));
|
||||
if (!*lpDest)
|
||||
hRet = E_OUTOFMEMORY;
|
||||
}
|
||||
|
@ -907,16 +898,18 @@ HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData
|
|||
{
|
||||
if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
|
||||
{
|
||||
LPUNKNOWN *lpUnknown = (LPUNKNOWN *)pvData;
|
||||
LPUNKNOWN lpUnknown = (LPUNKNOWN)pvData;
|
||||
LPUNKNOWN *lpDest = (LPUNKNOWN *)lpvDest;
|
||||
|
||||
if (*lpUnknown)
|
||||
IUnknown_AddRef(*lpUnknown);
|
||||
if (lpUnknown)
|
||||
IUnknown_AddRef(lpUnknown);
|
||||
if (*lpDest)
|
||||
IUnknown_Release(*lpDest);
|
||||
}
|
||||
/* Copy the data over */
|
||||
memcpy(lpvDest, pvData, psa->cbElements);
|
||||
*lpDest = lpUnknown;
|
||||
} else {
|
||||
/* Copy the data over */
|
||||
memcpy(lpvDest, pvData, psa->cbElements);
|
||||
}
|
||||
}
|
||||
}
|
||||
SafeArrayUnlock(psa);
|
||||
|
@ -1024,7 +1017,7 @@ HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
|
|||
if (!psa || !plUbound)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if(!nDim || nDim > psa->cDims || !psa->rgsabound[nDim - 1].cElements)
|
||||
if(!nDim || nDim > psa->cDims)
|
||||
return DISP_E_BADINDEX;
|
||||
|
||||
*plUbound = psa->rgsabound[nDim - 1].lLbound +
|
||||
|
@ -1057,7 +1050,7 @@ HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
|
|||
if (!psa || !plLbound)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if(!nDim || nDim > psa->cDims || !psa->rgsabound[nDim - 1].cElements)
|
||||
if(!nDim || nDim > psa->cDims)
|
||||
return DISP_E_BADINDEX;
|
||||
|
||||
*plLbound = psa->rgsabound[nDim - 1].lLbound;
|
||||
|
@ -1436,7 +1429,7 @@ HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound)
|
|||
|
||||
TRACE("(%p,%p)\n", psa, psabound);
|
||||
|
||||
if (!psa || psa->fFeatures & FADF_FIXEDSIZE || !psabound || !psabound->cElements)
|
||||
if (!psa || psa->fFeatures & FADF_FIXEDSIZE || !psabound)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (psa->cLocks > 0)
|
||||
|
@ -1465,10 +1458,16 @@ HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound)
|
|||
PVOID pvNewData;
|
||||
|
||||
ulOldSize = SAFEARRAY_GetCellCount(psa);
|
||||
ulNewSize = (ulOldSize / oldBounds->cElements) * psabound->cElements;
|
||||
if (ulOldSize)
|
||||
ulNewSize = (ulOldSize / oldBounds->cElements) * psabound->cElements;
|
||||
else {
|
||||
int oldelems = oldBounds->cElements;
|
||||
oldBounds->cElements = psabound->cElements;
|
||||
ulNewSize = SAFEARRAY_GetCellCount(psa);
|
||||
oldBounds->cElements = oldelems;
|
||||
}
|
||||
|
||||
if (ulOldSize == SAFEARRAY_INVALID_CELLS ||
|
||||
!(pvNewData = SAFEARRAY_Malloc(ulNewSize)))
|
||||
if (!(pvNewData = SAFEARRAY_Malloc(ulNewSize)))
|
||||
{
|
||||
SafeArrayUnlock(psa);
|
||||
return E_UNEXPECTED;
|
||||
|
|
|
@ -251,6 +251,34 @@ static void test_safearray(void)
|
|||
a = SafeArrayCreate(-1, 1, &bound);
|
||||
ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
|
||||
|
||||
bound.cElements = 0;
|
||||
bound.lLbound = 42;
|
||||
a = SafeArrayCreate(VT_I4, 1, &bound);
|
||||
ok(NULL != a,"SAC(VT_I4,1,[0,0]) failed.\n");
|
||||
|
||||
hres = SafeArrayGetLBound(a, 1, &l);
|
||||
ok(hres == S_OK, "SAGLB of 0 size dimensioned array failed with %lx\n",hres);
|
||||
ok(l == 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %ld\n",l);
|
||||
hres = SafeArrayGetUBound(a, 1, &l);
|
||||
ok(hres == S_OK, "SAGUB of 0 size dimensioned array failed with %lx\n",hres);
|
||||
ok(l == 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %ld\n",l);
|
||||
bound.cElements = 2;
|
||||
hres = SafeArrayRedim(a, &bound);
|
||||
ok(hres == S_OK,"SAR of a 0 elements dimension failed with hres %lx\n", hres);
|
||||
bound.cElements = 0;
|
||||
hres = SafeArrayRedim(a, &bound);
|
||||
ok(hres == S_OK,"SAR to a 0 elements dimension failed with hres %lx\n", hres);
|
||||
hres = SafeArrayDestroy(a);
|
||||
ok(hres == S_OK,"SAD of 0 dim array faild with hres %lx\n", hres);
|
||||
|
||||
bounds[0].cElements = 0; bounds[0].lLbound = 1;
|
||||
bounds[1].cElements = 2; bounds[1].lLbound = 23;
|
||||
a = SafeArrayCreate(VT_I4,2,bounds);
|
||||
ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
|
||||
bounds[0].cElements = 1; bounds[0].lLbound = 1;
|
||||
bounds[1].cElements = 0; bounds[1].lLbound = 23;
|
||||
a = SafeArrayCreate(VT_I4,2,bounds);
|
||||
ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
|
||||
|
||||
bounds[0].cElements = 42; bounds[0].lLbound = 1;
|
||||
bounds[1].cElements = 2; bounds[1].lLbound = 23;
|
||||
|
@ -689,14 +717,8 @@ static void test_VectorCreateLockDestroy(void)
|
|||
VARTYPE vt;
|
||||
int element;
|
||||
|
||||
#if 0
|
||||
/* Native allows you to to create 0 sized vectors. Its an ERR in Wine, lets
|
||||
* see if anyone reports it before supporting this brain damage. Actually
|
||||
* using the returned array just crashes in native anyway.
|
||||
*/
|
||||
sa = SafeArrayCreateVector(VT_UI1, 0, 0);
|
||||
ok(sa == NULL, "0 elements didn't fail\n");
|
||||
#endif
|
||||
ok(sa != NULL, "SACV with 0 elements failed.\n");
|
||||
|
||||
/* Test all VARTYPES in different lengths */
|
||||
for (element = 1; element <= 101; element += 10)
|
||||
|
@ -922,6 +944,101 @@ static void test_SafeArrayGetPutElement(void)
|
|||
SafeArrayDestroy(sa);
|
||||
}
|
||||
|
||||
static void test_SafeArrayGetPutElement_BSTR(void)
|
||||
{
|
||||
SAFEARRAYBOUND sab;
|
||||
LONG indices[1];
|
||||
SAFEARRAY *sa;
|
||||
HRESULT hres;
|
||||
BSTR value = 0, gotvalue;
|
||||
const OLECHAR szTest[5] = { 'T','e','s','t','\0' };
|
||||
|
||||
sab.lLbound = 1;
|
||||
sab.cElements = 1;
|
||||
|
||||
sa = SafeArrayCreate(VT_BSTR, 1, &sab);
|
||||
ok(sa != NULL, "BSTR test couldn't create array\n");
|
||||
if (!sa)
|
||||
return;
|
||||
|
||||
ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
|
||||
if (sa->cbElements != sizeof(BSTR))
|
||||
return;
|
||||
|
||||
indices[0] = sab.lLbound;
|
||||
value = SysAllocString(szTest);
|
||||
ok (value != NULL, "Expected non-NULL\n");
|
||||
hres = SafeArrayPutElement(sa, indices, value);
|
||||
ok(hres == S_OK, "Failed to put bstr element hres 0x%lx\n", hres);
|
||||
gotvalue = NULL;
|
||||
hres = SafeArrayGetElement(sa, indices, &gotvalue);
|
||||
ok(hres == S_OK, "Failed to get bstr element at hres 0x%lx\n", hres);
|
||||
if (hres == S_OK)
|
||||
ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value));
|
||||
SafeArrayDestroy(sa);
|
||||
}
|
||||
|
||||
static int tunk_xref = 0;
|
||||
static HRESULT WINAPI tunk_QueryInterface(LPUNKNOWN punk,REFIID riid, LPVOID *x) {
|
||||
return E_FAIL;
|
||||
}
|
||||
static ULONG WINAPI tunk_AddRef(LPUNKNOWN punk) {
|
||||
return ++tunk_xref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI tunk_Release(LPUNKNOWN punk) {
|
||||
return --tunk_xref;
|
||||
}
|
||||
|
||||
static ICOM_VTABLE(IUnknown) xtunk_vtbl = {
|
||||
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
||||
tunk_QueryInterface,
|
||||
tunk_AddRef,
|
||||
tunk_Release
|
||||
};
|
||||
|
||||
static struct xtunk_iface {
|
||||
ICOM_VTABLE(IUnknown) *lpvtbl;
|
||||
} xtunk_iface;
|
||||
|
||||
|
||||
static void test_SafeArrayGetPutElement_IUnknown(void)
|
||||
{
|
||||
SAFEARRAYBOUND sab;
|
||||
LONG indices[1];
|
||||
SAFEARRAY *sa;
|
||||
HRESULT hres;
|
||||
LPUNKNOWN value = 0, gotvalue;
|
||||
|
||||
sab.lLbound = 1;
|
||||
sab.cElements = 1;
|
||||
sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
|
||||
ok(sa != NULL, "UNKNOWN test couldn't create array\n");
|
||||
if (!sa)
|
||||
return;
|
||||
|
||||
ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
|
||||
if (sa->cbElements != sizeof(LPUNKNOWN))
|
||||
return;
|
||||
|
||||
indices[0] = sab.lLbound;
|
||||
xtunk_iface.lpvtbl = &xtunk_vtbl;
|
||||
value = (LPUNKNOWN)&xtunk_iface;
|
||||
tunk_xref = 1;
|
||||
ok (value != NULL, "Expected non-NULL\n");
|
||||
hres = SafeArrayPutElement(sa, indices, value);
|
||||
ok(hres == S_OK, "Failed to put bstr element hres 0x%lx\n", hres);
|
||||
ok(tunk_xref == 2,"Failed to increment refcount of iface.\n");
|
||||
gotvalue = NULL;
|
||||
hres = SafeArrayGetElement(sa, indices, &gotvalue);
|
||||
ok(tunk_xref == 3,"Failed to increment refcount of iface.\n");
|
||||
ok(hres == S_OK, "Failed to get bstr element at hres 0x%lx\n", hres);
|
||||
if (hres == S_OK)
|
||||
ok(value == gotvalue, "Got %p instead of %p\n", gotvalue, value);
|
||||
SafeArrayDestroy(sa);
|
||||
ok(tunk_xref == 2,"Failed to decrement refcount of iface.\n");
|
||||
}
|
||||
|
||||
static void test_SafeArrayCopyData(void)
|
||||
{
|
||||
SAFEARRAYBOUND sab[4];
|
||||
|
@ -1346,4 +1463,6 @@ START_TEST(safearray)
|
|||
test_SafeArrayCreateEx();
|
||||
test_SafeArrayCopyData();
|
||||
test_SafeArrayGetPutElement();
|
||||
test_SafeArrayGetPutElement_BSTR();
|
||||
test_SafeArrayGetPutElement_IUnknown();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue