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 */
|
||||
#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 {
|
||||
CC_CDECL = 1,
|
||||
CC_MSCPASCAL = CC_CDECL + 1,
|
||||
|
|
|
@ -65,6 +65,37 @@ typedef struct ISupportErrorInfo ISupportErrorInfo,*LPSUPPORTERRORINFO;
|
|||
* 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.
|
||||
*/
|
||||
|
@ -175,8 +206,8 @@ struct tagVARIANT {
|
|||
DECIMAL decVal;
|
||||
IUnknown* punkVal;
|
||||
IDispatch* pdispVal;
|
||||
SAFEARRAY* parray;
|
||||
*/
|
||||
SAFEARRAY* parray;
|
||||
|
||||
/* By reference
|
||||
*/
|
||||
|
@ -201,8 +232,8 @@ struct tagVARIANT {
|
|||
DECIMAL* pdecVal;
|
||||
IUnknown** ppunkVal;
|
||||
IDispatch** ppdispVal;
|
||||
SAFEARRAY** pparray;
|
||||
*/
|
||||
SAFEARRAY** pparray;
|
||||
} _wine_tagVARIANT_UNION_NAME;
|
||||
};
|
||||
|
||||
|
|
|
@ -387,6 +387,13 @@ HRESULT WINAPI SafeArrayGetLBound(
|
|||
UINT WINAPI SafeArrayGetDim(
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -396,6 +403,13 @@ UINT WINAPI SafeArrayGetDim(
|
|||
UINT WINAPI SafeArrayGetElemsize(
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -728,6 +742,12 @@ static BOOL validArg(
|
|||
LONG descSize = 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
|
||||
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)
|
||||
{
|
||||
TRACE(ole,"(%p),stub\n",pvarg);
|
||||
TRACE(ole,"(%p),stub\n",pvarg);
|
||||
|
||||
pvarg->vt = VT_EMPTY;
|
||||
pvarg->wReserved1 = 0;
|
||||
pvarg->wReserved2= 0;
|
||||
pvarg->wReserved3= 0;
|
||||
memset(pvarg, 0, sizeof (VARIANTARG));
|
||||
pvarg->vt = VT_EMPTY;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -1664,41 +1662,51 @@ void WINAPI VariantInit(VARIANTARG* pvarg)
|
|||
*/
|
||||
HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
|
||||
{
|
||||
HRESULT res = S_OK;
|
||||
TRACE(ole,"(%p),stub\n",pvarg);
|
||||
HRESULT res = S_OK;
|
||||
TRACE(ole,"(%p)\n",pvarg);
|
||||
|
||||
res = ValidateVariantType( pvarg->vt );
|
||||
if( res == S_OK )
|
||||
res = ValidateVariantType( pvarg->vt );
|
||||
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 ) )
|
||||
{
|
||||
switch( pvarg->vt & VT_TYPEMASK )
|
||||
{
|
||||
case( VT_BSTR ):
|
||||
SysFreeString( pvarg->u.bstrVal );
|
||||
break;
|
||||
case( VT_DISPATCH ):
|
||||
break;
|
||||
case( VT_VARIANT ):
|
||||
break;
|
||||
case( VT_UNKNOWN ):
|
||||
break;
|
||||
case( VT_SAFEARRAY ):
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the fields to empty.
|
||||
*/
|
||||
pvarg->wReserved1 = 0;
|
||||
pvarg->wReserved2 = 0;
|
||||
pvarg->wReserved3 = 0;
|
||||
pvarg->vt = VT_EMPTY;
|
||||
case( VT_BSTR ):
|
||||
SysFreeString( pvarg->u.bstrVal );
|
||||
break;
|
||||
case( VT_DISPATCH ):
|
||||
break;
|
||||
case( VT_VARIANT ):
|
||||
break;
|
||||
case( VT_UNKNOWN ):
|
||||
break;
|
||||
case( VT_SAFEARRAY ):
|
||||
SafeArrayDestroy(pvarg->u.parray);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 res = S_OK;
|
||||
TRACE(ole,"(%p, %p),stub\n", pvargDest, pvargSrc);
|
||||
HRESULT res = S_OK;
|
||||
|
||||
res = ValidateVariantType( pvargSrc->vt );
|
||||
/* If the pointer are to the same variant we don't need
|
||||
* to do anything.
|
||||
TRACE(ole,"(%p, %p)\n", pvargDest, pvargSrc);
|
||||
|
||||
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 );
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
|
||||
}
|
||||
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 res = S_OK;
|
||||
TRACE(ole,"(%p, %p),stub\n", pvargDest, pvargSrc);
|
||||
HRESULT res = S_OK;
|
||||
|
||||
res = ValidateVariantType( pvargSrc->vt );
|
||||
if( res != S_OK )
|
||||
return res;
|
||||
|
||||
if( pvargSrc->vt & VT_BYREF )
|
||||
TRACE(ole,"(%p, %p)\n", pvargDest, pvargSrc);
|
||||
|
||||
res = ValidateVariantType( pvargSrc->vt );
|
||||
|
||||
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;
|
||||
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 );
|
||||
SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
|
||||
}
|
||||
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