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/safearray.c b/ole/safearray.c index 1f45159..45e19da 100644 --- a/ole/safearray.c +++ b/ole/safearray.c
@@ -387,6 +387,13 @@ 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 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 @@ 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... */
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; } /******************************************************************************