NT4/private/oleauto/tests/disptest/cinvsary.cpp
2020-09-30 17:12:29 +02:00

642 lines
19 KiB
C++

/***
*cinvsary.cpp
*
* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
* Information Contained Herein Is Proprietary and Confidential.
*
*Purpose:
* This file implements the CInvokeSafeArraySuite test object.
*
*Revision History:
*
* [00] 30-Oct-92 bradlo: Created.
*
*Implementation Notes:
*
*****************************************************************************/
#include "disptest.h"
#include "tstsuite.h"
ASSERTDATA
#if VBA2
static OLECHAR FAR* rgszUI1SafeArray[] = {OLESTR("ui1safearray"), OLESTR("psa")};
#endif //VBA2
static OLECHAR FAR* rgszI2SafeArray[] = {OLESTR("i2safearray"), OLESTR("psa")};
static OLECHAR FAR* rgszI4SafeArray[] = {OLESTR("i4safearray"), OLESTR("psa")};
static OLECHAR FAR* rgszR4SafeArray[] = {OLESTR("r4safearray"), OLESTR("psa")};
static OLECHAR FAR* rgszR8SafeArray[] = {OLESTR("r8safearray"), OLESTR("psa")};
static OLECHAR FAR* rgszCySafeArray[] = {OLESTR("cysafearray"), OLESTR("psa")};
static OLECHAR FAR* rgszDateSafeArray[] = {OLESTR("datesafearray"), OLESTR("psa")};
static OLECHAR FAR* rgszBstrSafeArray[] = {OLESTR("bstrsafearray"), OLESTR("psa")};
static OLECHAR FAR* rgszScodeSafeArray[] = {OLESTR("scodesafearray"), OLESTR("psa")};
static OLECHAR FAR* rgszBoolSafeArray[] = {OLESTR("boolsafearray"), OLESTR("psa")};
static OLECHAR FAR* rgszVarSafeArray[] = {OLESTR("varsafearray"), OLESTR("psa")};
// REVIEW: DispSafeArray() ?
#if VBA2
static OLECHAR FAR* rgszUI1SafeArrayRef[] = {OLESTR("ui1safearrayref"), OLESTR("psa")};
#endif //VBA2
static OLECHAR FAR* rgszI2SafeArrayRef[] = {OLESTR("i2safearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszI4SafeArrayRef[] = {OLESTR("i4safearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszR4SafeArrayRef[] = {OLESTR("r4safearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszR8SafeArrayRef[] = {OLESTR("r8safearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszCySafeArrayRef[] = {OLESTR("cysafearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszDateSafeArrayRef[] = {OLESTR("datesafearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszBstrSafeArrayRef[] = {OLESTR("bstrsafearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszScodeSafeArrayRef[] = {OLESTR("scodesafearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszBoolSafeArrayRef[] = {OLESTR("boolsafearrayref"), OLESTR("psa")};
static OLECHAR FAR* rgszVarSafeArrayRef[] = {OLESTR("varsafearrayref"), OLESTR("psa")};
#if VBA2
static OLECHAR FAR* rgszUI1SafeArrayErase[] = {OLESTR("ui1safearrayerase"), OLESTR("psa")};
#endif //VBA2
static OLECHAR FAR* rgszI2SafeArrayErase[] = {OLESTR("i2safearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszI4SafeArrayErase[] = {OLESTR("i4safearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszR4SafeArrayErase[] = {OLESTR("r4safearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszR8SafeArrayErase[] = {OLESTR("r8safearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszCySafeArrayErase[] = {OLESTR("cysafearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszDateSafeArrayErase[] = {OLESTR("datesafearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszBstrSafeArrayErase[] = {OLESTR("bstrsafearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszScodeSafeArrayErase[] = {OLESTR("scodesafearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszBoolSafeArrayErase[] = {OLESTR("boolsafearrayerase"), OLESTR("psa")};
static OLECHAR FAR* rgszVarSafeArrayErase[] = {OLESTR("varsafearrayerase"), OLESTR("psa")};
#if VBA2
static OLECHAR FAR* rgszUI1SafeArrayAlloc[] = {OLESTR("ui1safearrayalloc"), OLESTR("psa")};
#endif //VBA2
static OLECHAR FAR* rgszI2SafeArrayAlloc[] = {OLESTR("i2safearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszI4SafeArrayAlloc[] = {OLESTR("i4safearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszR4SafeArrayAlloc[] = {OLESTR("r4safearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszR8SafeArrayAlloc[] = {OLESTR("r8safearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszCySafeArrayAlloc[] = {OLESTR("cysafearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszDateSafeArrayAlloc[] = {OLESTR("datesafearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszBstrSafeArrayAlloc[] = {OLESTR("bstrsafearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszScodeSafeArrayAlloc[] = {OLESTR("scodesafearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszBoolSafeArrayAlloc[] = {OLESTR("boolsafearrayalloc"), OLESTR("psa")};
static OLECHAR FAR* rgszVarSafeArrayAlloc[] = {OLESTR("varsafearrayalloc"), OLESTR("psa")};
extern OLECHAR FAR* g_szCSArray;
// REVIEW: DispSafeArrayRef() ?
struct TEST {
HRESULT (*pfnTest)(TEST FAR* ptinfo);
NAMEDESC namedesc;
OLECHAR FAR* szName; // test name
VARTYPE vt;
};
HRESULT DefSafeArrayTest(TEST FAR* ptinfo);
HRESULT EraseSafeArrayTest(TEST FAR* ptinfo);
HRESULT AllocSafeArrayTest(TEST FAR* ptinfo);
HRESULT SafeArrayCalleeRedim(TEST FAR* ptinfoDummy);
HRESULT SafeArrayReturn(TEST FAR* ptinfoDummy);
#if OE_WIN32
#define TESTCASE(X,Y) X, {rgsz ## Y, DIM( rgsz ## Y)}, L#Y
#else
#define TESTCASE(X,Y) X, {rgsz ## Y, DIM( rgsz ## Y)}, #Y
#endif
static TEST rgtest[] =
{
{TESTCASE(DefSafeArrayTest, I2SafeArray), VT_I2}
#if VBA2
, {TESTCASE(DefSafeArrayTest, UI1SafeArray), VT_UI1}
#endif //VBA2
, {TESTCASE(DefSafeArrayTest, I4SafeArray), VT_I4}
, {TESTCASE(DefSafeArrayTest, R4SafeArray), VT_R4}
, {TESTCASE(DefSafeArrayTest, R8SafeArray), VT_R8}
, {TESTCASE(DefSafeArrayTest, CySafeArray), VT_CY}
, {TESTCASE(DefSafeArrayTest, DateSafeArray), VT_DATE}
, {TESTCASE(DefSafeArrayTest, BstrSafeArray), VT_BSTR}
, {TESTCASE(DefSafeArrayTest, ScodeSafeArray), VT_ERROR}
, {TESTCASE(DefSafeArrayTest, BoolSafeArray), VT_BOOL}
, {TESTCASE(DefSafeArrayTest, VarSafeArray), VT_VARIANT}
, {TESTCASE(DefSafeArrayTest, I2SafeArrayRef), VT_BYREF|VT_I2}
#if VBA2
, {TESTCASE(DefSafeArrayTest, UI1SafeArrayRef), VT_BYREF|VT_UI1}
#endif //VBA2
, {TESTCASE(DefSafeArrayTest, I4SafeArrayRef), VT_BYREF|VT_I4}
, {TESTCASE(DefSafeArrayTest, R4SafeArrayRef), VT_BYREF|VT_R4}
, {TESTCASE(DefSafeArrayTest, R8SafeArrayRef), VT_BYREF|VT_R8}
, {TESTCASE(DefSafeArrayTest, CySafeArrayRef), VT_BYREF|VT_CY}
, {TESTCASE(DefSafeArrayTest, DateSafeArrayRef), VT_BYREF|VT_DATE}
, {TESTCASE(DefSafeArrayTest, BstrSafeArrayRef), VT_BYREF|VT_BSTR}
, {TESTCASE(DefSafeArrayTest, ScodeSafeArrayRef), VT_BYREF|VT_ERROR}
, {TESTCASE(DefSafeArrayTest, BoolSafeArrayRef), VT_BYREF|VT_BOOL}
, {TESTCASE(DefSafeArrayTest, VarSafeArrayRef), VT_BYREF|VT_VARIANT}
, {SafeArrayCalleeRedim, {NULL, 0}, OLESTR("SafeArray callee redim"), 0}
, {SafeArrayReturn, {NULL, 0}, OLESTR("SafeArray return"), 0}
, {TESTCASE(EraseSafeArrayTest, I2SafeArrayErase), VT_BYREF|VT_I2}
#if VBA2
, {TESTCASE(EraseSafeArrayTest, UI1SafeArrayErase), VT_BYREF|VT_UI1}
#endif //VBA2
, {TESTCASE(EraseSafeArrayTest, I4SafeArrayErase), VT_BYREF|VT_I4}
, {TESTCASE(EraseSafeArrayTest, R4SafeArrayErase), VT_BYREF|VT_R4}
, {TESTCASE(EraseSafeArrayTest, R8SafeArrayErase), VT_BYREF|VT_R8}
, {TESTCASE(EraseSafeArrayTest, CySafeArrayErase), VT_BYREF|VT_CY}
, {TESTCASE(EraseSafeArrayTest, DateSafeArrayErase),VT_BYREF|VT_DATE}
, {TESTCASE(EraseSafeArrayTest, BstrSafeArrayErase),VT_BYREF|VT_BSTR}
, {TESTCASE(EraseSafeArrayTest, ScodeSafeArrayErase),VT_BYREF|VT_ERROR}
, {TESTCASE(EraseSafeArrayTest, BoolSafeArrayErase),VT_BYREF|VT_BOOL}
, {TESTCASE(EraseSafeArrayTest, VarSafeArrayErase), VT_BYREF|VT_VARIANT}
, {TESTCASE(AllocSafeArrayTest, I2SafeArrayAlloc), VT_BYREF|VT_I2}
#if VBA2
, {TESTCASE(AllocSafeArrayTest, UI1SafeArrayAlloc), VT_BYREF|VT_UI1}
#endif //VBA2
, {TESTCASE(AllocSafeArrayTest, I4SafeArrayAlloc), VT_BYREF|VT_I4}
, {TESTCASE(AllocSafeArrayTest, R4SafeArrayAlloc), VT_BYREF|VT_R4}
, {TESTCASE(AllocSafeArrayTest, R8SafeArrayAlloc), VT_BYREF|VT_R8}
, {TESTCASE(AllocSafeArrayTest, CySafeArrayAlloc), VT_BYREF|VT_CY}
, {TESTCASE(AllocSafeArrayTest, DateSafeArrayAlloc),VT_BYREF|VT_DATE}
, {TESTCASE(AllocSafeArrayTest, BstrSafeArrayAlloc),VT_BYREF|VT_BSTR}
, {TESTCASE(AllocSafeArrayTest, ScodeSafeArrayAlloc),VT_BYREF|VT_ERROR}
, {TESTCASE(AllocSafeArrayTest, BoolSafeArrayAlloc),VT_BYREF|VT_BOOL}
, {TESTCASE(AllocSafeArrayTest, VarSafeArrayAlloc), VT_BYREF|VT_VARIANT}
};
static SARRAYDESC
rgsarraydesc[] =
{
{0, {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
, {1, {{2,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
, {1, {{1024,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
, {2, {{2,0}, {2,0}, {0,0}, {0,0}, {0,0}}}
, {2, {{32,0}, {32,0}, {0,0}, {0,0}, {0,0}}}
, {3, {{2,0}, {2,0}, {2,0}, {0,0}, {0,0}}}
, {3, {{10,0}, {10,0}, {10,0}, {0,0}, {0,0}}}
, {4, {{2,0}, {2,0}, {2,0}, {2,0}, {0,0}}}
, {4, {{6,0}, {6,0}, {6,0}, {6,0}, {0,0}}}
};
SUITE_CONSTRUCTION_IMPL(CInvokeSafeArraySuite)
SUITE_IUNKNOWN_IMPL(CInvokeSafeArraySuite)
//---------------------------------------------------------------------
// ITestSuite Methods
//---------------------------------------------------------------------
STDMETHODIMP
CInvokeSafeArraySuite::GetNameOfSuite(BSTR FAR* pbstr)
{
return ErrBstrAlloc(OLESTR("Invoke SafeArray"), pbstr);
}
STDMETHODIMP
CInvokeSafeArraySuite::GetNameOfLogfile(BSTR FAR* pbstr)
{
return ErrBstrAlloc(OLESTR("invsary.log"), pbstr);
}
STDMETHODIMP
CInvokeSafeArraySuite::GetTestCount(unsigned int FAR* pcTests)
{
*pcTests = DIM(rgtest);
return NOERROR;
}
STDMETHODIMP
CInvokeSafeArraySuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
{
if(iTest >= DIM(rgtest))
return RESULT(E_INVALIDARG);
return BuildBstr(
pbstr,
rgtest[iTest].szName);
}
/***
*HRESULT CInvokeSafeArraySuite::DoTest(unsigned int)
*Purpose:
* Execute a single CInvokeSafeArraySuite test.
*
*Entry:
* iTest = the index of the test to execute
*
*Exit:
* return value = HRESULT
*
***********************************************************************/
STDMETHODIMP
CInvokeSafeArraySuite::DoTest(unsigned int iTest)
{
if(iTest >= DIM(rgtest))
return RESULT(E_INVALIDARG);
IfFailRet(rgtest[iTest].pfnTest(&rgtest[iTest]));
return NOERROR;
}
HRESULT
DefSafeArrayTest(TEST FAR* ptinfo)
{
long ofs;
unsigned long rcnt;
int i, fNames;
HRESULT hresult;
VARTYPE vt, vtBase;
VARIANT varResult;
SAFEARRAY FAR* psa;
DISPID FAR* rgdispid;
IDispatch FAR* pdisp;
VARIANTARG rgvarg[1];
DISPPARAMS dispparams;
SARRAYDESC FAR* psadesc;
// REVIEW : This is really ugly! The use of templates or abstract
// classes would be much cleaner.
vt = ptinfo->vt;
vtBase = vt & ~VT_BYREF;
// if this is a ByRef array test then the "identity offset" is 1,
// because we know that all ByRef methods that we invoke add 1
// to each element of their given array. (this is how the test
// is defined).
//
ofs = (vt & VT_BYREF) ? 1 : 0;
IfFailRet(CreateObject(g_szCSArray, &pdisp));
IfFailGo(GetDISPIDs(pdisp, &ptinfo->namedesc, &rgdispid), LError1);
VariantInit(&varResult);
for(fNames = 0; fNames <= 1; ++fNames)
{
for(i = 0; i < DIM(rgsarraydesc); ++i)
{
psadesc = &rgsarraydesc[i];
if(psadesc->cDims == 0){
psa = NULL;
}else{
IfFailGo(SafeArrayCreateIdentity(vtBase, psadesc, &psa), LError2);
}
V_VT(rgvarg) = VT_ARRAY | vt;
if(vt & VT_BYREF){
V_ARRAYREF(rgvarg) = &psa;
}else{
V_ARRAY(rgvarg) = psa;
}
dispparams.cArgs = 1;
dispparams.rgvarg = rgvarg;
if(fNames){
dispparams.cNamedArgs = 1;
dispparams.rgdispidNamedArgs = &rgdispid[1];
}else{
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
}
IfFailGo(
DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
LError2);
if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR)
hresult = RESULT(E_FAIL);
VariantClear(&varResult);
if(HRESULT_FAILED(hresult))
goto LError2;
if(psa != NULL){
IfFailGo(SafeArrayValidateIdentity(vtBase, psa, ofs), LError2);
IfFailGo(SafeArrayDestroy(psa), LError2);
}
}
}
hresult = NOERROR;
LError2:;
delete rgdispid;
LError1:;
rcnt = pdisp->Release();
//ASSERT(rcnt == 0);
return hresult;
}
// Call ByRef SafeArray methods where the callee erases the given array
//
HRESULT
EraseSafeArrayTest(TEST FAR* ptinfo)
{
int i, fNames;
HRESULT hresult;
unsigned long rcnt;
VARTYPE vt, vtBase;
VARIANT varResult;
SAFEARRAY FAR* psa;
DISPID FAR* rgdispid;
IDispatch FAR* pdisp;
VARIANTARG rgvarg[1];
DISPPARAMS dispparams;
SARRAYDESC FAR* psadesc;
vt = ptinfo->vt;
vtBase = vt & ~VT_BYREF;
IfFailRet(CreateObject(g_szCSArray, &pdisp));
IfFailGo(GetDISPIDs(pdisp, &ptinfo->namedesc, &rgdispid), LError1);
VariantInit(&varResult);
for(fNames = 0; fNames <= 1; ++fNames)
{
for(i = 0; i < DIM(rgsarraydesc); ++i)
{
psadesc = &rgsarraydesc[i];
if(psadesc->cDims == 0){
psa = NULL;
}else{
IfFailGo(SafeArrayCreateIdentity(vtBase, psadesc, &psa), LError2);
}
ASSERT((vt & VT_BYREF) != 0);
V_VT(rgvarg) = VT_ARRAY | vt;
V_ARRAYREF(rgvarg) = &psa;
dispparams.cArgs = 1;
dispparams.rgvarg = rgvarg;
if(fNames){
dispparams.cNamedArgs = 1;
dispparams.rgdispidNamedArgs = &rgdispid[1];
}else{
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
}
IfFailGo(
DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
LError2);
if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR)
hresult = RESULT(E_FAIL);
VariantClear(&varResult);
if(HRESULT_FAILED(hresult))
goto LError2;
// These methods are supposed to erase the passed array
if(*V_ARRAYREF(&dispparams.rgvarg[0]) != NULL){
hresult = RESULT(E_FAIL);
goto LError2;
}
}
}
hresult = NOERROR;
LError2:;
delete rgdispid;
LError1:;
rcnt = pdisp->Release();
//ASSERT(rcnt == 0);
return hresult;
}
// Call ByRef SafeArray methods where the callee erases the given array
//
HRESULT
AllocSafeArrayTest(TEST FAR* ptinfo)
{
unsigned long rcnt;
int i, fNames;
HRESULT hresult;
VARTYPE vt, vtBase;
VARIANT varResult;
SAFEARRAY FAR* psa;
DISPID FAR* rgdispid;
IDispatch FAR* pdisp;
VARIANTARG rgvarg[1];
DISPPARAMS dispparams;
SARRAYDESC FAR* psadesc;
vt = ptinfo->vt;
vtBase = vt & ~VT_BYREF;
IfFailRet(CreateObject(g_szCSArray, &pdisp));
IfFailGo(GetDISPIDs(pdisp, &ptinfo->namedesc, &rgdispid), LError1);
VariantInit(&varResult);
for(fNames = 0; fNames <= 1; ++fNames)
{
for(i = 0; i < DIM(rgsarraydesc); ++i)
{
psadesc = &rgsarraydesc[i];
ASSERT((vt & VT_BYREF) != 0);
psa = NULL;
V_VT(rgvarg) = VT_ARRAY | vt;
V_ARRAYREF(rgvarg) = &psa;
dispparams.cArgs = 1;
dispparams.rgvarg = rgvarg;
if(fNames){
dispparams.cNamedArgs = 1;
dispparams.rgdispidNamedArgs = &rgdispid[1];
}else{
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
}
IfFailGo(
DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
LError2);
if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR)
hresult = RESULT(E_FAIL);
VariantClear(&varResult);
if(HRESULT_FAILED(hresult))
goto LError2;
// These methods are supposed to allocate an array, and return
// via the out param.
psa = *V_ARRAYREF(&dispparams.rgvarg[0]);
if(psa == NULL){
hresult = RESULT(E_FAIL);
goto LError2;
}
IfFailGo(SafeArrayValidateIdentity(vtBase, psa, 0L), LError2);
IfFailGo(SafeArrayDestroy(psa), LError2);
}
}
hresult = NOERROR;
LError2:;
delete rgdispid;
LError1:;
rcnt = pdisp->Release();
//ASSERT(rcnt == 0);
return hresult;
}
HRESULT
SafeArrayCalleeRedim(TEST FAR* ptinfoDummy)
{
int i;
unsigned long rcnt;
VARTYPE vt;
HRESULT hresult;
SAFEARRAY FAR* psa;
DISPID FAR* rgdispid;
IDispatch FAR* pdisp;
VARIANTARG rgvarg[2];
DISPPARAMS dispparams;
VARIANT varResult;
SARRAYDESC FAR* psadesc;
static OLECHAR FAR* rgszNames[] = {OLESTR("safearrayredim"), OLESTR("vt"), OLESTR("ppsa")};
static NAMEDESC namedesc = {rgszNames, DIM(rgszNames)};
UNUSED(ptinfoDummy);
vt = VT_VARIANT;
IfFailRet(CreateObject(g_szCSArray, &pdisp));
IfFailGo(GetDISPIDs(pdisp, &namedesc, &rgdispid), LError1);
VariantInit(&varResult);
for(i = 0; i < DIM(rgsarraydesc); ++i){
psadesc = &rgsarraydesc[i];
if(psadesc->cDims == 0) // ignore this one
continue;
IfFailGo(SafeArrayCreateIdentity(vt, psadesc, &psa), LError2);
V_VT(&rgvarg[0]) = VT_ARRAY | VT_BYREF | vt;
V_ARRAYREF(&rgvarg[0]) = &psa;
V_VT(&rgvarg[1]) = VT_I2;
V_I2(&rgvarg[1]) = vt;
dispparams.cArgs = 2;
dispparams.rgvarg = rgvarg;
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
IfFailGo(
DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
LError2);
if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR)
hresult = RESULT(E_FAIL);
VariantClear(&varResult);
if(HRESULT_FAILED(hresult))
goto LError2;
IfFailGo(SafeArrayValidateIdentity(vt, psa, 0L), LError2);
IfFailGo(SafeArrayDestroy(psa), LError2);
}
hresult = NOERROR;
LError2:;
delete rgdispid;
LError1:;
rcnt = pdisp->Release();
//ASSERT(rcnt == 0);
return hresult;
}
// test invoking a method that returns a SafeArray
HRESULT
SafeArrayReturn(TEST FAR* ptinfoDummy)
{
unsigned long rcnt;
VARTYPE vt;
NAMEDESC namedesc;
SARRAYDESC sadesc;
VARIANT varResult;
SAFEARRAY FAR* psa;
DISPID FAR* rgdispid;
IDispatch FAR* pdisp;
VARIANTARG rgvarg[2];
DISPPARAMS dispparams;
HRESULT hresult, hrTmp;
static OLECHAR FAR* rgszNames[] = {OLESTR("i2safearrayret"), OLESTR("var")};
UNUSED(ptinfoDummy);
namedesc.rgszNames = rgszNames;
namedesc.cNames = DIM(rgszNames);
sadesc.cDims = 1;
sadesc.rgsabound[0].lLbound = 0;
sadesc.rgsabound[0].cElements = 2;
vt = VT_I2;
psa = NULL;
rgdispid = NULL;
VariantInit(&varResult);
IfFailGo(CreateObject(g_szCSArray, &pdisp), LError0);
IfFailGo(GetDISPIDs(pdisp, &namedesc, &rgdispid), LError0);
IfFailGo(SafeArrayCreateIdentity(vt, &sadesc, &psa), LError0);
V_VT(&rgvarg[0]) = VT_ARRAY | vt;
V_ARRAY(&rgvarg[0]) = psa;
dispparams.cArgs = 1;
dispparams.rgvarg = rgvarg;
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
IfFailGo(DoInvoke(pdisp, rgdispid[0], &dispparams,
&varResult, NULL, NULL),
LError0);
if(V_VT(&varResult) != (VT_ARRAY | VT_I2)){
hresult = RESULT(E_FAIL);
goto LError0;
}
IfFailGo(SafeArrayValidateIdentity(vt, psa, 0L), LError0);
hresult = NOERROR;
LError0:;
VariantClear(&varResult);
if(psa != NULL){
hrTmp = SafeArrayDestroy(psa);
ASSERT(hrTmp == NOERROR);
}
if(pdisp != NULL){
rcnt = pdisp->Release();
//ASSERT(rcnt == 0);
}
if(rgdispid != NULL)
delete rgdispid;
return hresult;
}