Implemented support for arrays and safe arrays in VARIANT data
structures. Also moved the SAFEARRAY definition (yet again) to the
obj_oleaut.h file.
diff --git a/ole/variant.c b/ole/variant.c
index 348cdc0..045e2a8 100644
--- a/ole/variant.c
+++ b/ole/variant.c
@@ -1644,14 +1644,12 @@
*/
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 @@
*/
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 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 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;
}
/******************************************************************************