diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 7729928b31..c440a02ebd 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,36 @@ The license applies to all entries newer than 2009-04-28. */ +2012-09-17 12:23 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * harbour/contrib/hbwin/hbwinole.h + * harbour/contrib/hbwin/olecore.c + + added new public C functions: + VARIANT * hb_oleItemGetVariant( PHB_ITEM pItem ); + PHB_ITEM hb_oleItemPutVariant( PHB_ITEM pItem, VARIANT * pVariant, + HB_BOOL fMove ); + + added new PRG functions: + create variant pointer item of given OLE type and + initialize it with + __oleVariant( [, ] ) -> + extract Harbour value from variant pointer item + __oleVariantValue( ) -> + return OLE type of given variant pointer item + __oleVariantType( ) -> + + added support for variant pointer items passed as parameters to + OLE methods + ! removed AddRef() sent to object returned by QueryInterface() + when VT_UNKNOWN Variant was updated. QueryInterface() should + already increase reference count for the returned object. + * modified default translation rule for VT_[U]I8 | VT_ARRAY variants. + Now they are converted to harbour strings items without any CP + translations. Before such variants were converted to array of + integers. + Warning! this modification is not backward compatible. If some + needs previous behavior then he should change create conversion + functions. + ; Please test it. I made all this modifications in Linux without + any real tests. + 2012-09-16 16:47 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) * contrib/gtwvg/gtwvg.c + hb_gtInfo( HB_GTI_SETPOSANDSIZE ) returns the existing position diff --git a/harbour/contrib/hbwin/hbwinole.h b/harbour/contrib/hbwin/hbwinole.h index b09736759a..00d208ce18 100644 --- a/harbour/contrib/hbwin/hbwinole.h +++ b/harbour/contrib/hbwin/hbwinole.h @@ -148,20 +148,22 @@ typedef void ( * HB_OLE_DESTRUCTOR_FUNC )( void * ); extern HB_EXPORT HB_BOOL hb_oleInit( void ); extern HB_EXPORT HRESULT hb_oleGetError( void ); extern HB_EXPORT void hb_oleSetError( HRESULT lOleError ); -extern HB_EXPORT void hb_oleDispatchToItem( PHB_ITEM pItem, IDispatch* pdispVal, HB_USHORT uiClass ); +extern HB_EXPORT void hb_oleDispatchToItem( PHB_ITEM pItem, IDispatch * pdispVal, HB_USHORT uiClass ); extern HB_EXPORT IDispatch* hb_oleItemGetDispatch( PHB_ITEM pItem ); extern HB_EXPORT void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT * pVariant ); extern HB_EXPORT void hb_oleVariantToItemEx( PHB_ITEM pItem, VARIANT* pVariant, HB_USHORT uiClass ); extern HB_EXPORT void hb_oleItemToVariant( VARIANT * pVariant, PHB_ITEM pItem ); -extern HB_EXPORT void hb_oleItemToVariantEx( VARIANT* pVariant, PHB_ITEM pItem, HB_OLEOBJ_FUNC pObjFunc ); +extern HB_EXPORT void hb_oleItemToVariantEx( VARIANT * pVariant, PHB_ITEM pItem, HB_OLEOBJ_FUNC pObjFunc ); extern HB_EXPORT void hb_oleVariantUpdate( VARIANT * pVariant, PHB_ITEM pItem, HB_OLEOBJ_FUNC pObjFunc ); +extern HB_EXPORT VARIANT * hb_oleItemGetVariant( PHB_ITEM pItem ); +extern HB_EXPORT PHB_ITEM hb_oleItemPutVariant( PHB_ITEM pItem, VARIANT * pVariant, HB_BOOL fMove ); extern HB_EXPORT IDispatch* hb_oleParam( int iParam ); extern HB_EXPORT IDispatch* hb_oleItemGet( PHB_ITEM pItem ); extern HB_EXPORT PHB_ITEM hb_oleItemPut( PHB_ITEM pItem, IDispatch * pDisp ); extern HB_EXPORT PHB_ITEM hb_oleItemGetCallBack( PHB_ITEM pItem ); extern HB_EXPORT void hb_oleItemSetCallBack( PHB_ITEM pItem, PHB_ITEM * pCallBack ); extern HB_EXPORT HB_BOOL hb_oleDispInvoke( PHB_SYMB pSym, PHB_ITEM pObject, PHB_ITEM pParam, - DISPPARAMS * pParams, VARIANT* pVarResult, + DISPPARAMS * pParams, VARIANT * pVarResult, HB_OLEOBJ_FUNC pObjFunc, HB_USHORT uiClass ); extern HB_EXPORT void hb_oleItemSetDestructor( PHB_ITEM pItem, HB_OLE_DESTRUCTOR_FUNC pFunc, void * cargo ); diff --git a/harbour/contrib/hbwin/olecore.c b/harbour/contrib/hbwin/olecore.c index c28410f0f5..0ca5e05c04 100644 --- a/harbour/contrib/hbwin/olecore.c +++ b/harbour/contrib/hbwin/olecore.c @@ -217,6 +217,20 @@ static const HB_GC_FUNCS s_gcOleenumFuncs = }; +static HB_GARBAGE_FUNC( hb_olevariant_destructor ) +{ + VARIANT * pVariant = ( VARIANT * ) Cargo; + + VariantClear( pVariant ); +} + +static const HB_GC_FUNCS s_gcVariantFuncs = +{ + hb_olevariant_destructor, + hb_gcDummyMark +}; + + static void hb_errRT_OLE( HB_ERRCODE errGenCode, HB_ERRCODE errSubCode, HB_ERRCODE errOsCode, const char * szDescription, const char * szOperation, const char * szFileName ) { PHB_ITEM pError; @@ -364,6 +378,83 @@ static IEnumVARIANT* hb_oleenumParam( int iParam ) } +static SAFEARRAY * hb_oleSafeArrayFromString( PHB_ITEM pItem, VARTYPE vt ) +{ + UINT cElements = ( UINT ) hb_itemGetCLen( pItem ); + SAFEARRAY * pSafeArray = SafeArrayCreateVector( vt, 0, cElements ); + + if( pSafeArray ) + { + void * pData; + if( SafeArrayAccessData( pSafeArray, &pData ) == S_OK ) + { + memcpy( pData, hb_itemGetCPtr( pItem ), cElements ); + SafeArrayUnaccessData( pSafeArray ); + } + else + { + SafeArrayDestroy( pSafeArray ); + pSafeArray = NULL; + } + } + return pSafeArray; +} + +static HB_BOOL hb_oleSafeArrayToString( PHB_ITEM pItem, SAFEARRAY * pSafeArray ) +{ + long lFrom, lTo; + + if( SafeArrayGetElemsize( pSafeArray ) == 1 && + SafeArrayGetLBound( pSafeArray, 1, &lFrom ) == S_OK && + SafeArrayGetUBound( pSafeArray, 1, &lTo ) == S_OK && + lFrom <= lTo + 1 ) /* accept empty arrays */ + { + void * pData; + if( SafeArrayAccessData( pSafeArray, &pData ) == S_OK ) + { + hb_itemPutCL( pItem, ( const char * ) pData, lTo - lFrom + 1 ); + SafeArrayUnaccessData( pSafeArray ); + return HB_TRUE; + } + } + return HB_FALSE; +} +static VARIANT * hb_oleVariantParam( int iParam ) +{ + VARIANT * pVariant = ( VARIANT * ) hb_parptrGC( &s_gcVariantFuncs, iParam ); + + if( !pVariant ) + hb_errRT_OLE( EG_ARG, 1017, 0, NULL, HB_ERR_FUNCNAME, NULL ); + + return pVariant; +} + + +VARIANT * hb_oleItemGetVariant( PHB_ITEM pItem ) +{ + return ( VARIANT * ) hb_itemGetPtrGC( pItem, &s_gcVariantFuncs ); +} + + +PHB_ITEM hb_oleItemPutVariant( PHB_ITEM pItem, VARIANT * pVariant, HB_BOOL fMove ) +{ + VARIANT * pDestVariant = ( VARIANT * ) hb_gcAllocate( sizeof( VARIANT ), &s_gcOleFuncs ); + + if( fMove ) + { + *pDestVariant = *pVariant; + VariantInit( pVariant ); + } + else + { + VariantInit( pDestVariant ); + VariantCopy( pDestVariant, pVariant ); + } + + return hb_itemPutPtrGC( pItem, pDestVariant ); +} + + /* Unicode string management */ static wchar_t* AnsiToWide( const char* szString ) @@ -536,10 +627,22 @@ static void hb_oleItemToVariantRef( VARIANT* pVariant, PHB_ITEM pItem, case HB_IT_POINTER: { - IDispatch * pDisp = hb_oleItemGet( pItem ); + IDispatch * pDisp; + VARIANT * pVarPtr; - if( pDisp ) + if( ( pDisp = hb_oleItemGet( pItem ) ) != NULL ) hb_oleDispatchToVariant( pVariant, pDisp, pVarRef ); + else if( ( pVarPtr = hb_oleItemGetVariant( pItem ) ) != NULL ) + { + if( pVarRef ) + { + /* TODO: use real type reference instead of VT_VARIANT */ + V_VT( pVarRef ) = VT_VARIANT | VT_BYREF; + V_BYREF( pVarRef ) = pVarPtr; + } + else + VariantCopy( pVariant, pVarPtr ); + } #ifdef HB_OLE_PASS_POINTERS else { @@ -972,16 +1075,19 @@ void hb_oleVariantToItemEx( PHB_ITEM pItem, VARIANT* pVariant, HB_USHORT uiClass V_ARRAY( pVariant ); if( pSafeArray ) { - int iDim; + int iDim = ( int ) SafeArrayGetDim( pSafeArray ); - if( ( iDim = ( int ) SafeArrayGetDim( pSafeArray ) ) >= 1 ) + if( iDim >= 1 ) { - long * plIndex = ( long * ) hb_xgrab( iDim * sizeof( long ) ); + if( iDim > 1 || !hb_oleSafeArrayToString( pItem, pSafeArray ) ) + { + long * plIndex = ( long * ) hb_xgrab( iDim * sizeof( long ) ); - hb_oleSafeArrayToItem( pItem, pSafeArray, iDim, plIndex, + hb_oleSafeArrayToItem( pItem, pSafeArray, iDim, plIndex, ( VARTYPE ) ( V_VT( pVariant ) & ~( VT_ARRAY | VT_BYREF ) ), uiClass ); - hb_xfree( plIndex ); + hb_xfree( plIndex ); + } } else hb_arrayNew( pItem, 0 ); @@ -1048,13 +1154,9 @@ void hb_oleVariantUpdate( VARIANT* pVariant, PHB_ITEM pItem, ( void** ) ( void * ) &pUnk ) == S_OK ) { IUnknown* punkVal = *V_UNKNOWNREF( pVariant ); - if( punkVal != pUnk ) - { - HB_VTBL( pUnk )->AddRef( HB_THIS( pUnk ) ); - *V_UNKNOWNREF( pVariant ) = pUnk; - if( punkVal ) - HB_VTBL( punkVal )->Release( HB_THIS( punkVal ) ); - } + if( punkVal ) + HB_VTBL( punkVal )->Release( HB_THIS( punkVal ) ); + *V_UNKNOWNREF( pVariant ) = pUnk; } } else if( pObjFunc && HB_IS_OBJECT( pItem ) ) @@ -1973,6 +2075,247 @@ HB_FUNC( __OLEINVOKEPUT ) } +/* __oleVariantValue( ) -> */ +HB_FUNC( __OLEVARIANTVALUE ) +{ + VARIANT * pVariant = hb_oleVariantParam( 1 ); + + if( pVariant ) + hb_oleVariantToItemEx( hb_stackReturnItem(), pVariant, 0 ); +} + +/* __oleVariantType( ) -> */ +HB_FUNC( __OLEVARIANTTYPE ) +{ + VARIANT * pVariant = hb_oleVariantParam( 1 ); + + if( pVariant ) + hb_retni( V_VT( pVariant ) ); +} + +/* __oleVariant( [, ] ) -> */ +HB_FUNC( __OLEVARIANT ) +{ + int iType = hb_parni( 1 ); + PHB_ITEM pInit = hb_param( 2, HB_IT_ANY ); + IDispatch* pDisp; + VARIANT variant; + + V_VT( &variant ) = VT_ILLEGAL; + + switch( iType ) + { + case VT_EMPTY: + case VT_NULL: + V_VT( &variant ) = ( VARTYPE ) ( iType ); + break; + + case VT_BOOL: + if( pInit == NULL || HB_IS_LOGICAL( pInit ) ) + { + V_VT( &variant ) = VT_BOOL; + V_BOOL( &variant ) = hb_itemGetL( pInit ) ? TRUE : FALSE; + } + break; + + case VT_I1: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_I1; + V_I1( &variant ) = ( signed char ) hb_itemGetNI( pInit ); + } + break; + + case VT_I2: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_I2; + V_I2( &variant ) = ( short ) hb_itemGetNI( pInit ); + } + break; + + case VT_I4: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_I4; + V_I4( &variant ) = hb_itemGetNL( pInit ); + } + break; + + case VT_I8: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_I8; +#if defined( HB_OLE_NO_LL ) + /* workaround for wrong OLE variant structure definition */ + * ( ( HB_LONGLONG * ) &V_I4( &variant ) ) = hb_itemGetNInt( pInit ); +#else + V_I8( &variant ) = hb_itemGetNInt( pInit ); +#endif + } + break; + + case VT_UI1: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_UI1; + V_UI1( &variant ) = ( unsigned char ) hb_itemGetNI( pInit ); + } + break; + + case VT_UI2: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_UI2; + V_UI2( &variant ) = ( unsigned short ) hb_itemGetNI( pInit ); + } + break; + + case VT_UI4: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_UI4; + V_UI4( &variant ) = hb_itemGetNL( pInit ); + } + break; + + case VT_UI8: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_UI8; +#if defined( HB_OLE_NO_LL ) + /* workaround for wrong OLE variant structure definition */ + * ( ( HB_ULONGLONG * ) &V_I4( &variant ) ) = hb_itemGetNInt( pInit ); +#else + V_UI8( &variant ) = hb_itemGetNInt( pInit ); +#endif + } + break; + + case VT_INT: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_INT; + V_INT( &variant ) = hb_itemGetNI( pInit ); + } + break; + + case VT_UINT: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_UINT; + V_UINT( &variant ) = ( UINT ) hb_itemGetNI( pInit ); + } + break; + + case VT_ERROR: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_ERROR; + V_ERROR( &variant ) = ( SCODE ) hb_itemGetNL( pInit ); + } + break; + + case VT_R4: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_R4; + V_R4( &variant ) = ( float ) hb_itemGetND( pInit ); + } + break; + + case VT_R8: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_R8; + V_R8( &variant ) = hb_itemGetND( pInit ); + } + break; + + case VT_CY: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_CY; + VarCyFromR8( hb_itemGetND( pInit ), &V_CY( &variant ) ); + } + break; + + case VT_DECIMAL: + if( pInit == NULL || HB_IS_NUMERIC( pInit ) ) + { + V_VT( &variant ) = VT_DECIMAL; + VarDecFromR8( hb_itemGetND( pInit ), &V_DECIMAL( &variant ) ); + } + break; + + case VT_DATE: + if( pInit == NULL || HB_IS_DATETIME( pInit ) ) + { + V_VT( &variant ) = VT_DATE; + V_R8( &variant ) = hb_itemGetTD( pInit ) - HB_OLE_DATE_BASE; + } + break; + +#ifdef HB_OLE_PASS_POINTERS + case VT_PTR: + if( pInit == NULL || HB_IS_POINTER( pInit ) ) + { + V_VT( &variant ) = VT_PTR; + V_BYREF( &variant ) = hb_itemGetPtr( pInit ); + } + break; +#endif + + case VT_BSTR: + if( pInit == NULL || HB_IS_STRING( pInit ) ) + { + V_VT( &variant ) = VT_BSTR; + V_BSTR( &variant ) = hb_oleItemToString( pInit ); + } + break; + + case VT_I1 | VT_ARRAY: + case VT_UI1 | VT_ARRAY: + if( pInit == NULL || HB_IS_STRING( pInit ) ) + { + V_ARRAY( &variant ) = hb_oleSafeArrayFromString( pInit, + ( VARTYPE ) ( iType & VT_TYPEMASK ) ); + if( V_ARRAY( &variant ) ) + V_VT( &variant ) = ( VARTYPE ) iType; + } + break; + + case VT_UNKNOWN: + pDisp = hb_oleItemGetDispatch( pInit ); + if( pDisp ) + { + if( HB_VTBL( pDisp )->QueryInterface( HB_THIS_( pDisp ) + HB_ID_REF( IID_IEnumVARIANT ), + ( void** ) ( void * ) &V_UNKNOWN( &variant ) ) == S_OK ) + { + V_VT( &variant ) = VT_UNKNOWN; + } + } + break; + + case VT_DISPATCH: + pDisp = hb_oleItemGetDispatch( pInit ); + if( pDisp ) + { + V_VT( &variant ) = VT_DISPATCH; + V_DISPATCH( &variant ) = pDisp; + HB_VTBL( pDisp )->AddRef( HB_THIS( pDisp ) ); + } + break; + } + + if( V_VT( &variant ) != VT_ILLEGAL ) + hb_oleItemPutVariant( hb_stackReturnItem(), &variant, HB_TRUE ); + else + hb_errRT_OLE( EG_ARG, 1018, 0, NULL, HB_ERR_FUNCNAME, NULL ); +} + + HB_CALL_ON_STARTUP_BEGIN( _hb_olecore_init_ ) hb_vmAtInit( hb_olecore_init, NULL ); HB_CALL_ON_STARTUP_END( _hb_olecore_init_ )