Implemented support for arrays and safe arrays in VARIANT data
structures. Also moved the SAFEARRAY definition (yet again) to the obj_oleaut.h file.
This commit is contained in:
parent
11db496578
commit
bc5477f7d2
|
@ -7,38 +7,6 @@
|
||||||
/* the following depend only on obj_base.h */
|
/* the following depend only on obj_base.h */
|
||||||
#include "wine/obj_oleaut.h"
|
#include "wine/obj_oleaut.h"
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************
|
|
||||||
* SafeArray defines and structs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FADF_AUTO ( 0x1 )
|
|
||||||
#define FADF_STATIC ( 0x2 )
|
|
||||||
#define FADF_EMBEDDED ( 0x4 )
|
|
||||||
#define FADF_FIXEDSIZE ( 0x10 )
|
|
||||||
#define FADF_BSTR ( 0x100 )
|
|
||||||
#define FADF_UNKNOWN ( 0x200 )
|
|
||||||
#define FADF_DISPATCH ( 0x400 )
|
|
||||||
#define FADF_VARIANT ( 0x800 )
|
|
||||||
#define FADF_RESERVED ( 0xf0e8 )
|
|
||||||
|
|
||||||
typedef struct tagSAFEARRAYBOUND
|
|
||||||
{
|
|
||||||
ULONG cElements; /* Number of elements in dimension */
|
|
||||||
LONG lLbound; /* Lower bound of dimension */
|
|
||||||
} SAFEARRAYBOUND;
|
|
||||||
|
|
||||||
typedef struct tagSAFEARRAY
|
|
||||||
{
|
|
||||||
USHORT cDims; /* Count of array dimension */
|
|
||||||
USHORT fFeatures; /* Flags describing the array */
|
|
||||||
ULONG cbElements; /* Size of each element */
|
|
||||||
ULONG cLocks; /* Number of lock on array */
|
|
||||||
PVOID pvData; /* Pointer to data valid when cLocks > 0 */
|
|
||||||
SAFEARRAYBOUND rgsabound[ 1 ]; /* One bound for each dimension */
|
|
||||||
} SAFEARRAY, *LPSAFEARRAY;
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum tagCALLCONV {
|
typedef enum tagCALLCONV {
|
||||||
CC_CDECL = 1,
|
CC_CDECL = 1,
|
||||||
CC_MSCPASCAL = CC_CDECL + 1,
|
CC_MSCPASCAL = CC_CDECL + 1,
|
||||||
|
|
|
@ -65,6 +65,37 @@ typedef struct ISupportErrorInfo ISupportErrorInfo,*LPSUPPORTERRORINFO;
|
||||||
* Automation data types
|
* Automation data types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
* SafeArray defines and structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FADF_AUTO ( 0x1 )
|
||||||
|
#define FADF_STATIC ( 0x2 )
|
||||||
|
#define FADF_EMBEDDED ( 0x4 )
|
||||||
|
#define FADF_FIXEDSIZE ( 0x10 )
|
||||||
|
#define FADF_BSTR ( 0x100 )
|
||||||
|
#define FADF_UNKNOWN ( 0x200 )
|
||||||
|
#define FADF_DISPATCH ( 0x400 )
|
||||||
|
#define FADF_VARIANT ( 0x800 )
|
||||||
|
#define FADF_RESERVED ( 0xf0e8 )
|
||||||
|
|
||||||
|
typedef struct tagSAFEARRAYBOUND
|
||||||
|
{
|
||||||
|
ULONG cElements; /* Number of elements in dimension */
|
||||||
|
LONG lLbound; /* Lower bound of dimension */
|
||||||
|
} SAFEARRAYBOUND;
|
||||||
|
|
||||||
|
typedef struct tagSAFEARRAY
|
||||||
|
{
|
||||||
|
USHORT cDims; /* Count of array dimension */
|
||||||
|
USHORT fFeatures; /* Flags describing the array */
|
||||||
|
ULONG cbElements; /* Size of each element */
|
||||||
|
ULONG cLocks; /* Number of lock on array */
|
||||||
|
PVOID pvData; /* Pointer to data valid when cLocks > 0 */
|
||||||
|
SAFEARRAYBOUND rgsabound[ 1 ]; /* One bound for each dimension */
|
||||||
|
} SAFEARRAY, *LPSAFEARRAY;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data types for Variants.
|
* Data types for Variants.
|
||||||
*/
|
*/
|
||||||
|
@ -175,8 +206,8 @@ struct tagVARIANT {
|
||||||
DECIMAL decVal;
|
DECIMAL decVal;
|
||||||
IUnknown* punkVal;
|
IUnknown* punkVal;
|
||||||
IDispatch* pdispVal;
|
IDispatch* pdispVal;
|
||||||
SAFEARRAY* parray;
|
|
||||||
*/
|
*/
|
||||||
|
SAFEARRAY* parray;
|
||||||
|
|
||||||
/* By reference
|
/* By reference
|
||||||
*/
|
*/
|
||||||
|
@ -201,8 +232,8 @@ struct tagVARIANT {
|
||||||
DECIMAL* pdecVal;
|
DECIMAL* pdecVal;
|
||||||
IUnknown** ppunkVal;
|
IUnknown** ppunkVal;
|
||||||
IDispatch** ppdispVal;
|
IDispatch** ppdispVal;
|
||||||
SAFEARRAY** pparray;
|
|
||||||
*/
|
*/
|
||||||
|
SAFEARRAY** pparray;
|
||||||
} _wine_tagVARIANT_UNION_NAME;
|
} _wine_tagVARIANT_UNION_NAME;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -387,6 +387,13 @@ HRESULT WINAPI SafeArrayGetLBound(
|
||||||
UINT WINAPI SafeArrayGetDim(
|
UINT WINAPI SafeArrayGetDim(
|
||||||
SAFEARRAY * psa)
|
SAFEARRAY * psa)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* A quick test in Windows shows that the behavior here for an invalid
|
||||||
|
* pointer is to return 0.
|
||||||
|
*/
|
||||||
|
if(! validArg(psa))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return psa->cDims;
|
return psa->cDims;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,6 +403,13 @@ UINT WINAPI SafeArrayGetDim(
|
||||||
UINT WINAPI SafeArrayGetElemsize(
|
UINT WINAPI SafeArrayGetElemsize(
|
||||||
SAFEARRAY * psa)
|
SAFEARRAY * psa)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* A quick test in Windows shows that the behavior here for an invalid
|
||||||
|
* pointer is to return 0.
|
||||||
|
*/
|
||||||
|
if(! validArg(psa))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return psa->cbElements;
|
return psa->cbElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,6 +742,12 @@ static BOOL validArg(
|
||||||
LONG descSize = 0;
|
LONG descSize = 0;
|
||||||
LONG fullSize = 0;
|
LONG fullSize = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let's check for the null pointer just in case.
|
||||||
|
*/
|
||||||
|
if (psa == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* Check whether the size of the chunk make sens... That's the only thing
|
/* Check whether the size of the chunk make sens... That's the only thing
|
||||||
I can think of now... */
|
I can think of now... */
|
||||||
|
|
||||||
|
|
392
ole/variant.c
392
ole/variant.c
|
@ -1644,14 +1644,12 @@ static HRESULT WINAPI ValidateVt( VARTYPE vt )
|
||||||
*/
|
*/
|
||||||
void WINAPI VariantInit(VARIANTARG* pvarg)
|
void WINAPI VariantInit(VARIANTARG* pvarg)
|
||||||
{
|
{
|
||||||
TRACE(ole,"(%p),stub\n",pvarg);
|
TRACE(ole,"(%p),stub\n",pvarg);
|
||||||
|
|
||||||
pvarg->vt = VT_EMPTY;
|
memset(pvarg, 0, sizeof (VARIANTARG));
|
||||||
pvarg->wReserved1 = 0;
|
pvarg->vt = VT_EMPTY;
|
||||||
pvarg->wReserved2= 0;
|
|
||||||
pvarg->wReserved3= 0;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -1664,41 +1662,51 @@ void WINAPI VariantInit(VARIANTARG* pvarg)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
|
HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
|
||||||
{
|
{
|
||||||
HRESULT res = S_OK;
|
HRESULT res = S_OK;
|
||||||
TRACE(ole,"(%p),stub\n",pvarg);
|
TRACE(ole,"(%p)\n",pvarg);
|
||||||
|
|
||||||
res = ValidateVariantType( pvarg->vt );
|
res = ValidateVariantType( pvarg->vt );
|
||||||
if( res == S_OK )
|
if( res == S_OK )
|
||||||
|
{
|
||||||
|
if( !( pvarg->vt & VT_BYREF ) )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The VT_ARRAY flag is a special case of a safe array.
|
||||||
|
*/
|
||||||
|
if ( (pvarg->vt & VT_ARRAY) != 0)
|
||||||
|
{
|
||||||
|
SafeArrayDestroy(pvarg->u.parray);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch( pvarg->vt & VT_TYPEMASK )
|
||||||
{
|
{
|
||||||
if( !( pvarg->vt & VT_BYREF ) )
|
case( VT_BSTR ):
|
||||||
{
|
SysFreeString( pvarg->u.bstrVal );
|
||||||
switch( pvarg->vt & VT_TYPEMASK )
|
break;
|
||||||
{
|
case( VT_DISPATCH ):
|
||||||
case( VT_BSTR ):
|
break;
|
||||||
SysFreeString( pvarg->u.bstrVal );
|
case( VT_VARIANT ):
|
||||||
break;
|
break;
|
||||||
case( VT_DISPATCH ):
|
case( VT_UNKNOWN ):
|
||||||
break;
|
break;
|
||||||
case( VT_VARIANT ):
|
case( VT_SAFEARRAY ):
|
||||||
break;
|
SafeArrayDestroy(pvarg->u.parray);
|
||||||
case( VT_UNKNOWN ):
|
break;
|
||||||
break;
|
default:
|
||||||
case( VT_SAFEARRAY ):
|
break;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the fields to empty.
|
|
||||||
*/
|
|
||||||
pvarg->wReserved1 = 0;
|
|
||||||
pvarg->wReserved2 = 0;
|
|
||||||
pvarg->wReserved3 = 0;
|
|
||||||
pvarg->vt = VT_EMPTY;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empty all the fields and mark the type as empty.
|
||||||
|
*/
|
||||||
|
memset(pvarg, 0, sizeof (VARIANTARG));
|
||||||
|
pvarg->vt = VT_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -1708,59 +1716,72 @@ HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
|
HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
|
||||||
{
|
{
|
||||||
HRESULT res = S_OK;
|
HRESULT res = S_OK;
|
||||||
TRACE(ole,"(%p, %p),stub\n", pvargDest, pvargSrc);
|
|
||||||
|
|
||||||
res = ValidateVariantType( pvargSrc->vt );
|
TRACE(ole,"(%p, %p)\n", pvargDest, pvargSrc);
|
||||||
/* If the pointer are to the same variant we don't need
|
|
||||||
* to do anything.
|
res = ValidateVariantType( pvargSrc->vt );
|
||||||
|
|
||||||
|
/* If the pointer are to the same variant we don't need
|
||||||
|
* to do anything.
|
||||||
|
*/
|
||||||
|
if( pvargDest != pvargSrc && res == S_OK )
|
||||||
|
{
|
||||||
|
res = VariantClear( pvargDest );
|
||||||
|
|
||||||
|
if( res == S_OK )
|
||||||
|
{
|
||||||
|
if( pvargSrc->vt & VT_BYREF )
|
||||||
|
{
|
||||||
|
/* In the case of byreference we only need
|
||||||
|
* to copy the pointer.
|
||||||
*/
|
*/
|
||||||
if( pvargDest != pvargSrc && res == S_OK )
|
pvargDest->u = pvargSrc->u;
|
||||||
|
pvargDest->vt = pvargSrc->vt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The VT_ARRAY flag is another way to designate a safe array.
|
||||||
|
*/
|
||||||
|
if (pvargSrc->vt & VT_ARRAY)
|
||||||
{
|
{
|
||||||
res = VariantClear( pvargDest );
|
SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
|
||||||
|
|
||||||
if( res == S_OK )
|
|
||||||
{
|
|
||||||
if( pvargSrc->vt & VT_BYREF )
|
|
||||||
{
|
|
||||||
/* In the case of byreference we only need
|
|
||||||
* to copy the pointer.
|
|
||||||
*/
|
|
||||||
pvargDest->u = pvargSrc->u;
|
|
||||||
pvargDest->vt = pvargSrc->vt;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* In the case of by value we need to
|
|
||||||
* copy the actuall value. In the case of
|
|
||||||
* VT_BSTR a copy of the string is made,
|
|
||||||
* if VT_ARRAY the entire array is copied
|
|
||||||
* if VT_DISPATCH or VT_IUNKNOWN AddReff is
|
|
||||||
* called to increment the object's reference count.
|
|
||||||
*/
|
|
||||||
switch( pvargSrc->vt & VT_TYPEMASK )
|
|
||||||
{
|
|
||||||
case( VT_BSTR ):
|
|
||||||
pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
|
|
||||||
break;
|
|
||||||
case( VT_DISPATCH ):
|
|
||||||
break;
|
|
||||||
case( VT_VARIANT ):
|
|
||||||
break;
|
|
||||||
case( VT_UNKNOWN ):
|
|
||||||
break;
|
|
||||||
case( VT_SAFEARRAY ):
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pvargDest->u = pvargSrc->u;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pvargDest->vt = pvargSrc->vt;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res;
|
else
|
||||||
|
{
|
||||||
|
/* In the case of by value we need to
|
||||||
|
* copy the actuall value. In the case of
|
||||||
|
* VT_BSTR a copy of the string is made,
|
||||||
|
* if VT_DISPATCH or VT_IUNKNOWN AddReff is
|
||||||
|
* called to increment the object's reference count.
|
||||||
|
*/
|
||||||
|
switch( pvargSrc->vt & VT_TYPEMASK )
|
||||||
|
{
|
||||||
|
case( VT_BSTR ):
|
||||||
|
pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
|
||||||
|
break;
|
||||||
|
case( VT_DISPATCH ):
|
||||||
|
break;
|
||||||
|
case( VT_VARIANT ):
|
||||||
|
break;
|
||||||
|
case( VT_UNKNOWN ):
|
||||||
|
break;
|
||||||
|
case( VT_SAFEARRAY ):
|
||||||
|
SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pvargDest->u = pvargSrc->u;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pvargDest->vt = pvargSrc->vt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1772,101 +1793,122 @@ HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
|
HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
|
||||||
{
|
{
|
||||||
HRESULT res = S_OK;
|
HRESULT res = S_OK;
|
||||||
TRACE(ole,"(%p, %p),stub\n", pvargDest, pvargSrc);
|
|
||||||
|
|
||||||
res = ValidateVariantType( pvargSrc->vt );
|
TRACE(ole,"(%p, %p)\n", pvargDest, pvargSrc);
|
||||||
if( res != S_OK )
|
|
||||||
return res;
|
res = ValidateVariantType( pvargSrc->vt );
|
||||||
|
|
||||||
if( pvargSrc->vt & VT_BYREF )
|
if( res != S_OK )
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if( pvargSrc->vt & VT_BYREF )
|
||||||
|
{
|
||||||
|
VARIANTARG varg;
|
||||||
|
VariantInit( &varg );
|
||||||
|
|
||||||
|
/* handle the in place copy.
|
||||||
|
*/
|
||||||
|
if( pvargDest == pvargSrc )
|
||||||
|
{
|
||||||
|
/* we will use a copy of the source instead.
|
||||||
|
*/
|
||||||
|
res = VariantCopy( &varg, pvargSrc );
|
||||||
|
pvargSrc = &varg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( res == S_OK )
|
||||||
|
{
|
||||||
|
res = VariantClear( pvargDest );
|
||||||
|
|
||||||
|
if( res == S_OK )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The VT_ARRAY flag is another way to designate a safearray variant.
|
||||||
|
*/
|
||||||
|
if ( pvargSrc->vt & VT_ARRAY)
|
||||||
{
|
{
|
||||||
VARIANTARG varg;
|
SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
|
||||||
VariantInit( &varg );
|
|
||||||
/* handle the in place copy.
|
|
||||||
*/
|
|
||||||
if( pvargDest == pvargSrc )
|
|
||||||
{
|
|
||||||
/* we will use a copy of the source instead.
|
|
||||||
*/
|
|
||||||
res = VariantCopy( &varg, pvargSrc );
|
|
||||||
pvargSrc = &varg;
|
|
||||||
}
|
|
||||||
if( res == S_OK )
|
|
||||||
{
|
|
||||||
res = VariantClear( pvargDest );
|
|
||||||
if( res == S_OK )
|
|
||||||
{
|
|
||||||
/* In the case of by reference we need
|
|
||||||
* to copy the date pointed to by the variant.
|
|
||||||
*/
|
|
||||||
/* Get the variant type.
|
|
||||||
*/
|
|
||||||
switch( pvargSrc->vt & VT_TYPEMASK )
|
|
||||||
{
|
|
||||||
case( VT_BSTR ):
|
|
||||||
pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
|
|
||||||
break;
|
|
||||||
case( VT_DISPATCH ):
|
|
||||||
break;
|
|
||||||
case( VT_VARIANT ):
|
|
||||||
{
|
|
||||||
/* Prevent from cycling. According to tests on
|
|
||||||
* VariantCopyInd in Windows and the documentation
|
|
||||||
* this API dereferences the inner Variants to only one depth.
|
|
||||||
* If the inner Variant itself contains an
|
|
||||||
* other inner variant the E_INVALIDARG error is
|
|
||||||
* returned.
|
|
||||||
*/
|
|
||||||
if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
|
|
||||||
{
|
|
||||||
/* If we get here we are attempting to deference
|
|
||||||
* an inner variant that that is itself contained
|
|
||||||
* in an inner variant so report E_INVALIDARG error.
|
|
||||||
*/
|
|
||||||
res = E_INVALIDARG;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set the processing inner variant flag.
|
|
||||||
* We will set this flag in the inner variant
|
|
||||||
* that will be passed to the VariantCopyInd function.
|
|
||||||
*/
|
|
||||||
(pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
|
|
||||||
/* Dereference the inner variant.
|
|
||||||
*/
|
|
||||||
res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case( VT_UNKNOWN ):
|
|
||||||
break;
|
|
||||||
case( VT_SAFEARRAY ):
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* This is a by reference Variant which means that the union
|
|
||||||
* part of the Variant contains a pointer to some data of
|
|
||||||
* type "pvargSrc->vt & VT_TYPEMASK".
|
|
||||||
* We will deference this data in a generic fashion using
|
|
||||||
* the void pointer "Variant.u.byref".
|
|
||||||
* We will copy this data into the union of the destination
|
|
||||||
* Variant.
|
|
||||||
*/
|
|
||||||
memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* this should not fail.
|
|
||||||
*/
|
|
||||||
VariantClear( &varg );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = VariantCopy( pvargDest, pvargSrc );
|
/* In the case of by reference we need
|
||||||
|
* to copy the date pointed to by the variant.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Get the variant type.
|
||||||
|
*/
|
||||||
|
switch( pvargSrc->vt & VT_TYPEMASK )
|
||||||
|
{
|
||||||
|
case( VT_BSTR ):
|
||||||
|
pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
|
||||||
|
break;
|
||||||
|
case( VT_DISPATCH ):
|
||||||
|
break;
|
||||||
|
case( VT_VARIANT ):
|
||||||
|
{
|
||||||
|
/* Prevent from cycling. According to tests on
|
||||||
|
* VariantCopyInd in Windows and the documentation
|
||||||
|
* this API dereferences the inner Variants to only one depth.
|
||||||
|
* If the inner Variant itself contains an
|
||||||
|
* other inner variant the E_INVALIDARG error is
|
||||||
|
* returned.
|
||||||
|
*/
|
||||||
|
if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
|
||||||
|
{
|
||||||
|
/* If we get here we are attempting to deference
|
||||||
|
* an inner variant that that is itself contained
|
||||||
|
* in an inner variant so report E_INVALIDARG error.
|
||||||
|
*/
|
||||||
|
res = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the processing inner variant flag.
|
||||||
|
* We will set this flag in the inner variant
|
||||||
|
* that will be passed to the VariantCopyInd function.
|
||||||
|
*/
|
||||||
|
(pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
|
||||||
|
|
||||||
|
/* Dereference the inner variant.
|
||||||
|
*/
|
||||||
|
res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case( VT_UNKNOWN ):
|
||||||
|
break;
|
||||||
|
case( VT_SAFEARRAY ):
|
||||||
|
SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* This is a by reference Variant which means that the union
|
||||||
|
* part of the Variant contains a pointer to some data of
|
||||||
|
* type "pvargSrc->vt & VT_TYPEMASK".
|
||||||
|
* We will deference this data in a generic fashion using
|
||||||
|
* the void pointer "Variant.u.byref".
|
||||||
|
* We will copy this data into the union of the destination
|
||||||
|
* Variant.
|
||||||
|
*/
|
||||||
|
memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
|
pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this should not fail.
|
||||||
|
*/
|
||||||
|
VariantClear( &varg );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = VariantCopy( pvargDest, pvargSrc );
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
|
Loading…
Reference in New Issue