From a13eebf540db38f0bc8c9ef2b95798b2b5c18b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Wed, 10 May 2017 12:27:49 +0200 Subject: [PATCH] 2017-05-10 12:27 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/hbwin/olecore.c + automatically add WIN_VT_ARRAY bit in 1-st parameter of __oleVariantNew() when 2-nd parameter is an array + added support for typed variant arrays to __oleVariantNew() Now it's possible to create strong typed one dimensional arrays and pass them as parameters to foreign OLE code, i.e. oOle:setArrayOfStrings( ; __oleVariantNew( WIN_VT_BSTR, { "1-st", "2-nd", "3-rd" } ) ) oOle:setArrayOfIntegers( ; __oleVariantNew( WIN_VT_INT, { 1, 2, 3, 4 } ) + added support for array of integers initialization from strings passed to __oleVariantNew() in 2-nd parameter. Now it's possible to create strong typed one dimensional OLE array initialized with string bytes ASCII values, i.e. oOle:setUcharStr( ; __oleVariantNew( hb_bitOr( WIN_VT_ARRAY, WIN_VT_UI8 ), ; "ABCDEF" ) ) oOle:setArrayOfIntegers( ; __oleVariantNew( hb_bitOr( WIN_VT_ARRAY, WIN_VT_INT ), ; "ABCDEF" ) ) ; warning: code not tested at all, written in my Linux box, please make real life tests in MS-Windows --- ChangeLog.txt | 24 +++++ contrib/hbwin/olecore.c | 215 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 220 insertions(+), 19 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 2cd0272984..4ec3b426ec 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,30 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2017-05-10 12:27 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * contrib/hbwin/olecore.c + + automatically add WIN_VT_ARRAY bit in 1-st parameter of + __oleVariantNew() when 2-nd parameter is an array + + added support for typed variant arrays to __oleVariantNew() + Now it's possible to create strong typed one dimensional arrays and + pass them as parameters to foreign OLE code, i.e. + oOle:setArrayOfStrings( ; + __oleVariantNew( WIN_VT_BSTR, { "1-st", "2-nd", "3-rd" } ) ) + oOle:setArrayOfIntegers( ; + __oleVariantNew( WIN_VT_INT, { 1, 2, 3, 4 } ) + + added support for array of integers initialization from strings + passed to __oleVariantNew() in 2-nd parameter. + Now it's possible to create strong typed one dimensional OLE array + initialized with string bytes ASCII values, i.e. + oOle:setUcharStr( ; + __oleVariantNew( hb_bitOr( WIN_VT_ARRAY, WIN_VT_UI8 ), ; + "ABCDEF" ) ) + oOle:setArrayOfIntegers( ; + __oleVariantNew( hb_bitOr( WIN_VT_ARRAY, WIN_VT_INT ), ; + "ABCDEF" ) ) + ; warning: code not tested at all, written in my Linux box, + please make real life tests in MS-Windows + 2017-05-10 07:55 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/hbwin/olecore.c * minor modification in order of helper functions diff --git a/contrib/hbwin/olecore.c b/contrib/hbwin/olecore.c index 703a8ceff2..4e45702ebc 100644 --- a/contrib/hbwin/olecore.c +++ b/contrib/hbwin/olecore.c @@ -459,23 +459,194 @@ static void hb_oleStringToItem( BSTR strVal, PHB_ITEM pItem ) } -static SAFEARRAY * hb_oleSafeArrayFromString( PHB_ITEM pItem, VARTYPE vt ) +static SAFEARRAY * hb_oleSafeArrayFromItem( PHB_ITEM pItem, VARTYPE vt ) { - UINT cElements = ( UINT ) hb_itemGetCLen( pItem ); - SAFEARRAY * pSafeArray = SafeArrayCreateVector( vt, 0, cElements ); + SAFEARRAY * pSafeArray; + UINT cElements = 0; + + if( pItem ) + { + if( HB_IS_STRING( pItem ) ) + cElements = ( UINT ) hb_itemGetCLen( pItem ); + else if( HB_IS_ARRAY( pItem ) ) + cElements = ( UINT ) hb_arrayLen( pItem ); + else if( ! HB_IS_NIL( pItem ) ) + return NULL; + } + + pSafeArray = SafeArrayCreateVector( vt, 0, cElements ); if( pSafeArray && cElements > 0 ) { + const char * pStr; void * pData; - if( SafeArrayAccessData( pSafeArray, &pData ) == S_OK ) + + pStr = HB_IS_STRING( pItem ) ? hb_itemGetCPtr( pItem ) : NULL; + if( pStr && ( vt == VT_I1 || vt == VT_UI1 ) && + SafeArrayAccessData( pSafeArray, &pData ) == S_OK ) { - memcpy( pData, hb_itemGetCPtr( pItem ), cElements ); + memcpy( pData, pStr, cElements ); SafeArrayUnaccessData( pSafeArray ); } - else + else /* HB_IT_ARRAY */ { - SafeArrayDestroy( pSafeArray ); - pSafeArray = NULL; + UINT uiPos; + + for( uiPos = 1; uiPos <= cElements; ++uiPos ) + { + VARIANT v; + void * ptr = NULL; + + switch( vt ) + { + case VT_I1: + V_I1( &v ) = pStr ? ( HB_I8 ) ( signed char ) pStr[ uiPos - 1 ] : + ( HB_I8 ) hb_arrayGetNI( pItem, uiPos ); + ptr = &V_I1( &v ); + break; + case VT_UI1: + V_UI1( &v ) = pStr ? ( HB_U8 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_U8 ) hb_arrayGetNI( pItem, uiPos ); + ptr = &V_UI1( &v ); + break; + case VT_I2: + V_I2( &v ) = pStr ? ( HB_I16 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_I16 ) hb_arrayGetNI( pItem, uiPos ); + ptr = &V_I2( &v ); + break; + case VT_UI2: + V_UI2( &v ) = pStr ? ( HB_U16 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_U16 ) hb_arrayGetNI( pItem, uiPos ); + ptr = &V_UI2( &v ); + break; + case VT_I4: + V_I4( &v ) = pStr ? ( HB_I32 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_I32 ) hb_arrayGetNL( pItem, uiPos ); + ptr = &V_I4( &v ); + break; + case VT_UI4: + V_UI4( &v ) = pStr ? ( HB_U32 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_U32 ) hb_arrayGetNL( pItem, uiPos ); + ptr = &V_UI4( &v ); + break; +#if ! defined( HB_LONG_LONG_OFF ) + case VT_I8: +# if defined( HB_OLE_NO_LL ) + /* workaround for wrong OLE variant structure definition */ + ptr = &V_I4( &v ); + *( ( HB_LONGLONG * ) ptr ) = + pStr ? ( HB_I64 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_I64 ) hb_arrayGetNInt( pItem, uiPos ); +# else + V_I8( &v ) = pStr ? ( HB_I64 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_I64 ) hb_arrayGetNInt( pItem, uiPos ); + ptr = &V_I8( &v ); +# endif + break; + case VT_UI8: +# if defined( HB_OLE_NO_LL ) + /* workaround for wrong OLE variant structure definition */ + ptr = &V_UI4( &v ); + *( ( HB_ULONGLONG * ) ptr ) = + pStr ? ( HB_U64 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_U64 ) hb_arrayGetNInt( pItem, uiPos ); +# else + V_UI8( &v ) = pStr ? ( HB_U64 ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_U64 ) hb_arrayGetNInt( pItem, uiPos ); + ptr = &V_UI8( &v ); +# endif + break; +#endif + case VT_INT: + V_INT( &v ) = pStr ? ( HB_INT ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_INT ) hb_arrayGetNI( pItem, uiPos ); + ptr = &V_INT( &v ); + break; + case VT_UINT: + V_UINT( &v ) = pStr ? ( HB_UINT ) ( unsigned char ) pStr[ uiPos - 1 ] : + ( HB_UINT ) hb_arrayGetNI( pItem, uiPos ); + ptr = &V_UINT( &v ); + break; + case VT_ERROR: + if( pStr == NULL ) + { + V_ERROR( &v ) = ( SCODE ) hb_arrayGetNL( pItem, uiPos ); + ptr = &V_ERROR( &v ); + } + break; + case VT_BOOL: + if( pStr == NULL ) + { + V_BOOL( &v ) = hb_arrayGetL( pItem, uiPos ) ? TRUE : FALSE; + ptr = &V_BOOL( &v ); + } + break; + case VT_R4: + if( pStr == NULL ) + { + V_R4( &v ) = ( float ) hb_arrayGetND( pItem, uiPos ); + ptr = &V_R4( &v ); + } + break; + case VT_R8: + if( pStr == NULL ) + { + V_R8( &v ) = hb_arrayGetND( pItem, uiPos ); + ptr = &V_R8( &v ); + } + break; + case VT_CY: + if( pStr == NULL ) + { + VarCyFromR8( hb_arrayGetND( pItem, uiPos ), &V_CY( &v ) ); + ptr = &V_CY( &v ); + } + break; + case VT_DECIMAL: + if( pStr == NULL ) + { + VarDecFromR8( hb_arrayGetND( pItem, uiPos ), &HB_WIN_U1( &v, decVal ) /*&V_DECIMAL( &v )*/ ); + ptr = &HB_WIN_U1( &v, decVal ); /*&V_DECIMAL( &v )*/ + } + break; + case VT_DATE: + if( pStr == NULL ) + { + V_R8( &v ) = hb_arrayGetTD( pItem, uiPos ) - HB_OLE_DATE_BASE; + ptr = &V_R8( &v ); + } + break; +#ifdef HB_OLE_PASS_POINTERS + case VT_PTR: + if( pStr == NULL ) + { + V_BYREF( &v ) = hb_arrayGetPtr( pItem, uiPos ); + ptr = &V_BYREF( &v ); + } + break; +#endif + case VT_BSTR: + if( pStr == NULL ) + { + V_BSTR( &v ) = hb_oleItemToString( hb_arrayGetItemPtr( pItem, uiPos ) ); + ptr = &V_BSTR( &v ); + } + break; + } + + if( ptr != NULL ) + { + long lIndex[ 1 ]; + lIndex[ 0 ] = ( long ) uiPos; + SafeArrayPutElement( pSafeArray, lIndex, ptr ); + } + else + { + SafeArrayDestroy( pSafeArray ); + pSafeArray = NULL; + break; + } + } } } return pSafeArray; @@ -2232,6 +2403,9 @@ HB_FUNC( __OLEVARIANTNEW ) V_VT( &variant ) = VT_ILLEGAL; + if( pInit && HB_IS_ARRAY( pInit ) && iType == ( iType & VT_TYPEMASK ) ) + iType |= VT_ARRAY; + switch( iType ) { case VT_EMPTY: @@ -2403,17 +2577,6 @@ HB_FUNC( __OLEVARIANTNEW ) } 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 ) @@ -2436,6 +2599,20 @@ HB_FUNC( __OLEVARIANTNEW ) HB_VTBL( pDisp )->AddRef( HB_THIS( pDisp ) ); } break; + + default: + if( iType & VT_ARRAY ) + { + iType &= ~VT_ARRAY; + if( iType == ( iType & VT_TYPEMASK ) ) + { + V_ARRAY( &variant ) = hb_oleSafeArrayFromItem( pInit, ( VARTYPE ) iType ); + if( V_ARRAY( &variant ) ) + V_VT( &variant ) = ( VARTYPE ) ( iType | VT_ARRAY ); + break; + } + } + break; } if( V_VT( &variant ) != VT_ILLEGAL )