/* * OLE library * * Copyright 2000, 2003 Jose F. Gimenez (JFG) * Copyright 2008, 2009 Mindaugas Kavaliauskas * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file LICENSE.txt. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/). * * As a special exception, the Harbour Project gives permission for * additional uses of the text contained in its release of Harbour. * * The exception is that, if you link the Harbour libraries with other * files to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public License. * Your use of that executable is in no way restricted on account of * linking the Harbour library code into it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the GNU General Public License. * * This exception applies only to the code released by the Harbour * Project under the name Harbour. If you copy code from other * Harbour Project or Free Software Foundation releases into a copy of * Harbour, as the General Public License permits, the exception does * not apply to the code that you add in this way. To avoid misleading * anyone as to the status of such modified files, you must delete * this exception notice from them. * * If you write modifications of your own for Harbour, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. * */ #include "hbwinole.h" #include "hbapicdp.h" #include "hbapilng.h" #include "hbapistr.h" #include "hbinit.h" /* enable workaround for wrong OLE variant structure definition */ #if ( defined( __POCC__ ) && defined( HB_OS_WIN_CE ) ) || \ defined( __DMC__ ) || \ ( defined( _MSC_VER ) && ( _MSC_VER <= 1500 ) ) #define HB_OLE_NO_LL #endif #if ( defined( __POCC__ ) && defined( HB_OS_WIN_CE ) ) || \ ( defined( __WATCOMC__ ) && ( __WATCOMC__ < 1280 ) ) || \ defined( __MINGW32__ ) || \ defined( __DMC__ ) || \ ( defined( _MSC_VER ) && ( _MSC_VER <= 1500 ) ) #define HB_OLE_NO_LLREF #endif #if ! defined( HB_OLE_NO_SAFEARRAYGETVARTYPE ) && \ ( defined( __DMC__ ) || \ defined( __MINGW32CE__ ) || \ ( defined( __WATCOMC__ ) && ( __WATCOMC__ < 1270 ) ) ) #define HB_OLE_NO_SAFEARRAYGETVARTYPE #endif /* base date value in OLE (1899-12-30) as Julian day */ #define HB_OLE_DATE_BASE 0x0024D9AB static PHB_DYNS s_pDyns_hb_oleauto; static PHB_DYNS s_pDyns_hObjAccess; static PHB_DYNS s_pDyns_hObjAssign; typedef struct { IDispatch * pDisp; PHB_ITEM * pCallBack; HB_OLE_DESTRUCTOR_FUNC pDestructorFunc; void * cargo; } HB_OLE; typedef struct { HRESULT lOleError; HB_BOOL fNullDate; HB_BOOL fNil2Null; int iInit; } HB_OLEDATA, * PHB_OLEDATA; static void hb_oleDataInit( void * cargo ) { PHB_OLEDATA pOleData = ( PHB_OLEDATA ) cargo; /* default settings: */ pOleData->fNullDate = HB_FALSE; pOleData->fNil2Null = HB_FALSE; #if defined( HB_OS_WIN_CE ) if( CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ) == S_OK ) #else if( OleInitialize( NULL ) == S_OK ) #endif pOleData->iInit = 1; } static void hb_oleDataRelease( void * cargo ) { PHB_OLEDATA pOleData = ( PHB_OLEDATA ) cargo; if( pOleData->iInit ) { #if defined( HB_OS_WIN_CE ) CoUninitialize(); #else OleUninitialize(); #endif } } static HB_TSD_NEW( s_oleData, sizeof( HB_OLEDATA ), hb_oleDataInit, hb_oleDataRelease ); #define hb_getOleData() ( ( PHB_OLEDATA ) hb_stackGetTSD( &s_oleData ) ) HB_FUNC_EXTERN( WIN_OLEAUTO ); HB_BOOL hb_oleInit( void ) { return hb_getOleData()->iInit != 0; } void hb_oleSetError( HRESULT lOleError ) { hb_getOleData()->lOleError = lOleError; } HRESULT hb_oleGetError( void ) { return hb_getOleData()->lOleError; } static void hb_oleSetNullDateFlag( HB_BOOL fNullDate ) { hb_getOleData()->fNullDate = fNullDate; } static HB_BOOL hb_oleGetNullDateFlag( void ) { return hb_getOleData()->fNullDate; } static void hb_oleSetNil2NullFlag( HB_BOOL fNil2Null ) { hb_getOleData()->fNil2Null = fNil2Null; } static HB_BOOL hb_oleGetNil2NullFlag( void ) { return hb_getOleData()->fNil2Null; } static void hb_olecore_init( void * cargo ) { HB_SYMBOL_UNUSED( cargo ); s_pDyns_hb_oleauto = hb_dynsymGetCase( "WIN_OLEAUTO" ); s_pDyns_hObjAccess = hb_dynsymGetCase( "__HOBJ" ); s_pDyns_hObjAssign = hb_dynsymGetCase( "___HOBJ" ); if( s_pDyns_hObjAccess == s_pDyns_hObjAssign ) { /* Never executed. Just force linkage */ HB_FUNC_EXEC( WIN_OLEAUTO ); } } static HB_GARBAGE_FUNC( hb_ole_destructor ) { HB_OLE * pOle = ( HB_OLE * ) Cargo; IDispatch * pDisp = pOle->pDisp; if( pDisp ) { pOle->pDisp = NULL; if( pOle->pCallBack && *pOle->pCallBack ) { PHB_ITEM pCallBack = *pOle->pCallBack; *pOle->pCallBack = NULL; pOle->pCallBack = NULL; hb_itemRelease( pCallBack ); } if( pOle->pDestructorFunc ) { pOle->pDestructorFunc( pOle->cargo ); pOle->pDestructorFunc = NULL; } HB_VTBL( pDisp )->Release( HB_THIS( pDisp ) ); } } static HB_GARBAGE_FUNC( hb_ole_mark ) { HB_OLE * pOle = ( HB_OLE * ) Cargo; if( pOle->pCallBack && *pOle->pCallBack ) hb_gcMark( *pOle->pCallBack ); } static const HB_GC_FUNCS s_gcOleFuncs = { hb_ole_destructor, hb_ole_mark }; static HB_GARBAGE_FUNC( hb_oleenum_destructor ) { IEnumVARIANT** ppEnum = ( IEnumVARIANT** ) Cargo; IEnumVARIANT* pEnum = *ppEnum; if( pEnum ) { *ppEnum = NULL; HB_VTBL( pEnum )->Release( HB_THIS( pEnum ) ); } } static const HB_GC_FUNCS s_gcOleenumFuncs = { hb_oleenum_destructor, hb_gcDummyMark }; 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; pError = hb_errRT_New( ES_ERROR, "WINOLE", errGenCode, errSubCode, szDescription, szOperation, errOsCode, EF_NONE ); if( hb_pcount() != 0 ) { /* HB_ERR_ARGS_BASEPARAMS */ PHB_ITEM pArray = hb_arrayBaseParams(); hb_errPutArgsArray( pError, pArray ); hb_itemRelease( pArray ); } if( szFileName ) hb_errPutFileName( pError, szFileName ); hb_errLaunch( pError ); hb_errRelease( pError ); } static void hb_oleExcepDescription( EXCEPINFO * pExcep, char ** pszDescription, char ** pszSource ) { if( pExcep->pfnDeferredFillIn ) ( *pExcep->pfnDeferredFillIn )( pExcep ); if( pExcep->bstrSource ) { int iLen, iStrLen; iStrLen = ( int ) SysStringLen( pExcep->bstrSource ); iLen = WideCharToMultiByte( CP_ACP, 0, pExcep->bstrSource, iStrLen, NULL, 0, NULL, NULL ); * pszSource = ( char * ) hb_xgrab( ( iLen + 1 ) * sizeof( char ) ); WideCharToMultiByte( CP_ACP, 0, pExcep->bstrSource, iStrLen, * pszSource, iLen + 1, NULL, NULL ); ( * pszSource )[ iLen ] = '\0'; SysFreeString( pExcep->bstrSource ); } if( pExcep->bstrHelpFile ) SysFreeString( pExcep->bstrHelpFile ); if( pExcep->bstrDescription ) { int iLen, iStrLen; iStrLen = ( int ) SysStringLen( pExcep->bstrDescription ); iLen = WideCharToMultiByte( CP_ACP, 0, pExcep->bstrDescription, iStrLen, NULL, 0, NULL, NULL ); * pszDescription = ( char * ) hb_xgrab( ( iLen + 14 + 1 ) * sizeof( char ) ); WideCharToMultiByte( CP_ACP, 0, pExcep->bstrDescription, iStrLen, * pszDescription, iLen + 1, NULL, NULL ); ( * pszDescription )[ iLen ] = '\0'; SysFreeString( pExcep->bstrDescription ); } else { *pszDescription = ( char * ) hb_xgrab( ( 14 + 1 ) * sizeof( char ) ); ( *pszDescription )[ 0 ] = '\0'; } if( pExcep->wCode ) hb_snprintf( ( *pszDescription ) + strlen( *pszDescription ), 14, " (%d)", pExcep->wCode ); else hb_snprintf( ( *pszDescription ) + strlen( *pszDescription ), 14, " (0x%08lX)", pExcep->scode ); } IDispatch * hb_oleParam( int iParam ) { HB_OLE * pOle = ( HB_OLE * ) hb_parptrGC( &s_gcOleFuncs, iParam ); if( pOle && pOle->pDisp ) return pOle->pDisp; hb_errRT_OLE( EG_ARG, 1001, 0, NULL, HB_ERR_FUNCNAME, NULL ); return NULL; } IDispatch * hb_oleItemGet( PHB_ITEM pItem ) { HB_OLE * pOle = ( HB_OLE * ) hb_itemGetPtrGC( pItem, &s_gcOleFuncs ); return pOle ? pOle->pDisp : NULL; } PHB_ITEM hb_oleItemPut( PHB_ITEM pItem, IDispatch * pDisp ) { HB_OLE * pOle = ( HB_OLE * ) hb_gcAllocate( sizeof( HB_OLE ), &s_gcOleFuncs ); pOle->pDisp = pDisp; pOle->pCallBack = NULL; pOle->pDestructorFunc = NULL; pOle->cargo = NULL; return hb_itemPutPtrGC( pItem, pOle ); } PHB_ITEM hb_oleItemGetCallBack( PHB_ITEM pItem ) { HB_OLE * pOle = ( HB_OLE * ) hb_itemGetPtrGC( pItem, &s_gcOleFuncs ); return pOle && pOle->pCallBack ? *pOle->pCallBack : NULL; } void hb_oleItemSetCallBack( PHB_ITEM pItem, PHB_ITEM * pCallBack ) { HB_OLE * pOle = ( HB_OLE * ) hb_itemGetPtrGC( pItem, &s_gcOleFuncs ); if( pOle ) { if( pOle->pCallBack && *pOle->pCallBack ) { PHB_ITEM pCallBackPrev = *pOle->pCallBack; *pOle->pCallBack = NULL; pOle->pCallBack = NULL; hb_itemRelease( pCallBackPrev ); } if( pCallBack ) { pOle->pCallBack = pCallBack; hb_gcUnlock( *pCallBack ); } } } void hb_oleItemSetDestructor( PHB_ITEM pItem, HB_OLE_DESTRUCTOR_FUNC pFunc, void * cargo ) { HB_OLE * pOle = ( HB_OLE * ) hb_itemGetPtrGC( pItem, &s_gcOleFuncs ); if( pOle ) { pOle->pDestructorFunc = pFunc; pOle->cargo = cargo; } } static IEnumVARIANT * hb_oleenumParam( int iParam ) { IEnumVARIANT ** ppEnum = ( IEnumVARIANT ** ) hb_parptrGC( &s_gcOleenumFuncs, iParam ); if( ppEnum && *ppEnum ) return *ppEnum; hb_errRT_OLE( EG_ARG, 1002, 0, NULL, HB_ERR_FUNCNAME, NULL ); return NULL; } 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_gcVariantFuncs ); 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 ) { int iLen; wchar_t * szWide; iLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szString, -1, NULL, 0 ); szWide = ( wchar_t* ) hb_xgrab( iLen * sizeof( wchar_t ) ); MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szString, -1, szWide, iLen ); return szWide; } static void AnsiToWideBuffer( const char * szString, wchar_t * szWide, int iLen ) { MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szString, -1, szWide, iLen ); szWide[ iLen - 1 ] = L'\0'; } static BSTR hb_oleItemToString( PHB_ITEM pItem ) { UINT uiStrLen = ( UINT ) hb_itemCopyStrU16( pItem, HB_CDP_ENDIAN_NATIVE, NULL, UINT_MAX ); BSTR strVal = SysAllocStringLen( NULL, uiStrLen ); hb_itemCopyStrU16( pItem, HB_CDP_ENDIAN_NATIVE, strVal, uiStrLen + 1 ); return strVal; } static void hb_oleStringToItem( BSTR strVal, PHB_ITEM pItem ) { hb_itemPutStrLenU16( pItem, HB_CDP_ENDIAN_NATIVE, strVal, SysStringLen( strVal ) ); } static void hb_oleVariantRef( VARIANT * pVariant, VARIANT * pVarRef ) { if( V_VT( pVariant ) & VT_BYREF ) { VariantCopy( pVarRef, pVariant ); return; } V_VT( pVarRef ) = V_VT( pVariant ) | VT_BYREF; switch( V_VT( pVariant ) ) { case VT_I1: V_I1REF( pVarRef ) = &V_I1( pVariant ); break; case VT_UI1: V_UI1REF( pVarRef ) = &V_UI1( pVariant ); break; case VT_I2: V_I2REF( pVarRef ) = &V_I2( pVariant ); break; case VT_UI2: V_UI2REF( pVarRef ) = &V_UI2( pVariant ); break; case VT_I4: V_I4REF( pVarRef ) = &V_I4( pVariant ); break; case VT_UI4: V_UI4REF( pVarRef ) = &V_UI4( pVariant ); break; case VT_I8: #if defined( HB_OLE_NO_LLREF ) || defined( HB_OLE_NO_LL ) /* workaround for wrong OLE variant structure definition */ V_R8REF( pVarRef ) = &V_R8( pVariant ); #else V_I8REF( pVarRef ) = &V_I8( pVariant ); #endif break; case VT_UI8: #if defined( HB_OLE_NO_LLREF ) || defined( HB_OLE_NO_LL ) /* workaround for wrong OLE variant structure definition */ V_R8REF( pVarRef ) = &V_R8( pVariant ); #else V_I8REF( pVarRef ) = &V_I8( pVariant ); #endif break; case VT_INT: V_INTREF( pVarRef ) = &V_INT( pVariant ); break; case VT_UINT: V_UINTREF( pVarRef ) = &V_UINT( pVariant ); break; case VT_ERROR: V_ERRORREF( pVarRef ) = &V_ERROR( pVariant ); break; case VT_BOOL: V_BOOLREF( pVarRef ) = &V_BOOL( pVariant ); break; case VT_R4: V_R4REF( pVarRef ) = &V_R4( pVariant ); break; case VT_R8: V_R8REF( pVarRef ) = &V_R8( pVariant ); break; case VT_CY: V_CYREF( pVarRef ) = &V_CY( pVariant ); break; case VT_DATE: V_R8REF( pVarRef ) = &V_R8( pVariant ); break; case VT_BSTR: V_BSTRREF( pVarRef ) = &V_BSTR( pVariant ); break; default: if( V_VT( pVariant ) & VT_ARRAY ) V_ARRAYREF( pVarRef ) = &V_ARRAY( pVariant ); else { V_VT( pVarRef ) = VT_VARIANT | VT_BYREF; V_BYREF( pVarRef ) = pVariant; } break; } } static HB_BOOL hb_oleSafeArrayFill( SAFEARRAY * pSafeArray, VARTYPE vt, PHB_ITEM pItem, int iDims, int iDim, long * plSize, long * plIndex ) { const char * pStr; void * pData; UINT uiPos, cElements; if( pItem == NULL || HB_IS_NIL( pItem ) ) return HB_TRUE; if( HB_IS_STRING( pItem ) ) { pStr = hb_itemGetCPtr( pItem ); uiPos = ( UINT ) hb_itemGetCLen( pItem ); } else if( HB_IS_ARRAY( pItem ) ) { pStr = NULL; uiPos = ( UINT ) hb_arrayLen( pItem ); } else return HB_FALSE; cElements = ( UINT ) plSize[ iDim - 1 ]; if( uiPos < cElements ) cElements = uiPos; if( iDim < iDims ) { if( pStr ) return HB_FALSE; for( uiPos = 1; uiPos <= cElements; ++uiPos ) { plIndex[ iDim - 1 ] = ( long ) ( uiPos - 1 ); if( ! hb_oleSafeArrayFill( pSafeArray, vt, hb_arrayGetItemPtr( pItem, uiPos ), iDims, iDim + 1, plSize, plIndex ) ) return HB_FALSE; } return HB_TRUE; } if( pStr && ( vt == VT_I1 || vt == VT_UI1 ) && SafeArrayGetDim( pSafeArray ) == 1 && SafeArrayAccessData( pSafeArray, &pData ) == S_OK ) { memcpy( pData, pStr, cElements ); SafeArrayUnaccessData( pSafeArray ); return HB_TRUE; } 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_DATE: if( pStr == NULL ) { V_R8( &v ) = hb_arrayGetTD( pItem, uiPos ) - HB_OLE_DATE_BASE; ptr = &V_R8( &v ); } break; case VT_BSTR: if( pStr == NULL ) ptr = hb_oleItemToString( hb_arrayGetItemPtr( pItem, uiPos ) ); break; case VT_VARIANT: if( pStr == NULL ) { VariantInit( &v ); hb_oleItemToVariant( &v, hb_arrayGetItemPtr( pItem, uiPos ) ); ptr = &v; } break; } if( ptr != NULL ) { plIndex[ iDim - 1 ] = ( long ) ( uiPos - 1 ); SafeArrayPutElement( pSafeArray, plIndex, ptr ); if( vt == VT_VARIANT ) VariantClear( &v ); } else return HB_FALSE; } return HB_TRUE; } static SAFEARRAY * hb_oleSafeArrayFromItem( PHB_ITEM pItem, VARTYPE vt, int iDims, long * plSize ) { SAFEARRAYBOUND boundbuf[ 16 ], * sabound; SAFEARRAY * pSafeArray; long * plIndex; if( iDims == 0 ) { if( pItem ) { if( HB_IS_STRING( pItem ) ) plSize[ 0 ] = ( UINT ) hb_itemGetCLen( pItem ); else if( HB_IS_ARRAY( pItem ) ) plSize[ 0 ] = ( UINT ) hb_arrayLen( pItem ); else if( ! HB_IS_NIL( pItem ) ) return NULL; } iDims = 1; } sabound = iDims > ( int ) HB_SIZEOFARRAY( boundbuf ) ? ( SAFEARRAYBOUND * ) hb_xgrab( sizeof( SAFEARRAYBOUND ) * iDims ) : boundbuf; /* use the same buffer for dimensions and indexes */ plIndex = &sabound[ 0 ].lLbound; if( iDims == 1 && plSize[ 0 ] > 0 ) pSafeArray = SafeArrayCreateVector( vt, 0, plSize[ 0 ] ); else { int iDim; for( iDim = 0; iDim < iDims; ++iDim ) { sabound[ iDim ].lLbound = 0; sabound[ iDim ].cElements = plSize[ iDim ]; } pSafeArray = SafeArrayCreate( vt, iDims, sabound ); } if( pSafeArray && pItem && iDims && plSize[ 0 ] ) { if( ! hb_oleSafeArrayFill( pSafeArray, vt, pItem, iDims, 1, plSize, plIndex ) ) { SafeArrayDestroy( pSafeArray ); pSafeArray = NULL; } } if( sabound != boundbuf ) hb_xfree( sabound ); return pSafeArray; } static HB_BOOL hb_oleSafeArrayToString( PHB_ITEM pItem, SAFEARRAY * pSafeArray ) { long lFrom, lTo; VARTYPE vt = VT_UI1; if( SafeArrayGetElemsize( pSafeArray ) == 1 && #if ! defined( HB_OLE_NO_SAFEARRAYGETVARTYPE ) SafeArrayGetVartype( pSafeArray, &vt ) == S_OK && #endif ( vt == VT_I1 || vt == VT_UI1 ) && 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; } IDispatch * hb_oleItemGetDispatch( PHB_ITEM pItem ) { if( HB_IS_OBJECT( pItem ) ) { if( hb_objHasMessage( pItem, s_pDyns_hObjAccess ) ) { hb_vmPushDynSym( s_pDyns_hObjAccess ); hb_vmPush( pItem ); hb_vmSend( 0 ); return hb_oleParam( -1 ); } } return hb_oleItemGet( pItem ); } static void hb_oleDispatchToVariant( VARIANT * pVariant, IDispatch * pDisp, VARIANT * pVarRef ) { /* pVariant will be freed using VariantClear(). We increment reference count to keep OLE object alive */ HB_VTBL( pDisp )->AddRef( HB_THIS( pDisp ) ); V_VT( pVariant ) = VT_DISPATCH; V_DISPATCH( pVariant ) = pDisp; if( pVarRef ) { V_VT( pVarRef ) = VT_DISPATCH | VT_BYREF; V_DISPATCHREF( pVarRef ) = &V_DISPATCH( pVariant ); } } /* Item <-> Variant conversion */ static void hb_oleItemToVariantRef( VARIANT * pVariant, PHB_ITEM pItem, VARIANT * pVarRef, HB_OLEOBJ_FUNC pObjFunc ) { VariantClear( pVariant ); /* VT_T( pVariant ) = VT_EMPTY; */ switch( hb_itemType( pItem ) ) { case HB_IT_STRING: case HB_IT_MEMO: V_VT( pVariant ) = VT_BSTR; V_BSTR( pVariant ) = hb_oleItemToString( pItem ); if( pVarRef ) { V_VT( pVarRef ) = VT_BSTR | VT_BYREF; V_BSTRREF( pVarRef ) = &V_BSTR( pVariant ); } break; case HB_IT_LOGICAL: V_VT( pVariant ) = VT_BOOL; V_BOOL( pVariant ) = hb_itemGetL( pItem ) ? VARIANT_TRUE : VARIANT_FALSE; if( pVarRef ) { V_VT( pVarRef ) = VT_BOOL | VT_BYREF; V_BOOLREF( pVarRef ) = &V_BOOL( pVariant ); } break; case HB_IT_INTEGER: V_VT( pVariant ) = VT_I4; V_I4( pVariant ) = hb_itemGetNL( pItem ); if( pVarRef ) { V_VT( pVarRef ) = VT_I4 | VT_BYREF; V_I4REF( pVarRef ) = &V_I4( pVariant ); } break; case HB_IT_LONG: #if HB_VMLONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) V_VT( pVariant ) = VT_I4; V_I4( pVariant ) = hb_itemGetNL( pItem ); if( pVarRef ) { V_VT( pVarRef ) = VT_I4 | VT_BYREF; V_I4REF( pVarRef ) = &V_I4( pVariant ); } #else V_VT( pVariant ) = VT_I8; # if defined( HB_OLE_NO_LL ) /* workaround for wrong OLE variant structure definition */ * ( ( HB_LONGLONG * ) &V_I4( pVariant ) ) = hb_itemGetNInt( pItem ); # else V_I8( pVariant ) = hb_itemGetNInt( pItem ); # endif if( pVarRef ) { V_VT( pVarRef ) = VT_I8 | VT_BYREF; # if defined( HB_OLE_NO_LLREF ) || defined( HB_OLE_NO_LL ) /* workaround for wrong OLE variant structure definition */ V_R8REF( pVarRef ) = &V_R8( pVariant ); # else V_I8REF( pVarRef ) = &V_I8( pVariant ); # endif } #endif break; case HB_IT_DOUBLE: V_VT( pVariant ) = VT_R8; V_R8( pVariant ) = hb_itemGetND( pItem ); if( pVarRef ) { V_VT( pVarRef ) = VT_R8 | VT_BYREF; V_R8REF( pVarRef ) = &V_R8( pVariant ); } break; case HB_IT_DATE: { long lDate = hb_itemGetDL( pItem ); if( lDate == 0 && hb_oleGetNullDateFlag() ) { V_VT( pVariant ) = VT_NULL; if( pVarRef ) { V_VT( pVarRef ) = VT_VARIANT | VT_BYREF; V_VARIANTREF( pVarRef ) = pVariant; } } else { V_VT( pVariant ) = VT_DATE; V_R8( pVariant ) = ( double ) ( lDate - HB_OLE_DATE_BASE ); if( pVarRef ) { V_VT( pVarRef ) = VT_DATE | VT_BYREF; V_R8REF( pVarRef ) = &V_R8( pVariant ); } } break; } case HB_IT_TIMESTAMP: { double dDate = hb_itemGetTD( pItem ); if( dDate == 0 && hb_oleGetNullDateFlag() ) { V_VT( pVariant ) = VT_NULL; if( pVarRef ) { V_VT( pVarRef ) = VT_VARIANT | VT_BYREF; V_VARIANTREF( pVarRef ) = pVariant; } } else { V_VT( pVariant ) = VT_DATE; V_R8( pVariant ) = dDate - HB_OLE_DATE_BASE; if( pVarRef ) { V_VT( pVarRef ) = VT_DATE | VT_BYREF; V_R8REF( pVarRef ) = &V_R8( pVariant ); } } break; } case HB_IT_POINTER: { IDispatch * pDisp; VARIANT * pVarPtr; if( ( pDisp = hb_oleItemGet( pItem ) ) != NULL ) hb_oleDispatchToVariant( pVariant, pDisp, pVarRef ); else if( ( pVarPtr = hb_oleItemGetVariant( pItem ) ) != NULL ) { if( pVarRef ) hb_oleVariantRef( pVarPtr, pVarRef ); else VariantCopy( pVariant, pVarPtr ); } #ifdef HB_OLE_PASS_POINTERS else { V_VT( pVariant ) = VT_PTR; V_BYREF( pVariant ) = hb_itemGetPtr( pItem ); if( pVarRef ) { V_VT( pVarRef ) = VT_PTR | VT_BYREF; V_BYREF( pVarRef ) = &V_BYREF( pVariant ); } } #endif break; } case HB_IT_ARRAY: /* or OBJECT */ if( HB_IS_OBJECT( pItem ) ) { IDispatch * pDisp = hb_oleItemGetDispatch( pItem ); if( pDisp ) hb_oleDispatchToVariant( pVariant, pDisp, pVarRef ); else if( pObjFunc ) pObjFunc( pVariant, pItem ); } else { SAFEARRAY * pSafeArray; SAFEARRAYBOUND sabound[ 1 ]; HB_SIZE n, nLen; nLen = hb_arrayLen( pItem ); sabound[ 0 ].lLbound = 0; sabound[ 0 ].cElements = ( long ) nLen; pSafeArray = SafeArrayCreate( VT_VARIANT, 1, sabound ); V_VT( pVariant ) = VT_VARIANT | VT_ARRAY; V_ARRAY( pVariant ) = pSafeArray; if( pVarRef ) { V_VT( pVarRef ) = VT_VARIANT | VT_ARRAY | VT_BYREF; V_ARRAYREF( pVarRef ) = &V_ARRAY( pVariant ); } for( n = 0; n < nLen; n++ ) { VARIANT vItem; long lIndex[ 1 ]; VariantInit( &vItem ); hb_oleItemToVariantRef( &vItem, hb_arrayGetItemPtr( pItem, n + 1 ), NULL, pObjFunc ); lIndex[ 0 ] = ( long ) n; SafeArrayPutElement( pSafeArray, lIndex, &vItem ); VariantClear( &vItem ); } } break; case HB_IT_NIL: if( hb_oleGetNil2NullFlag() ) V_VT( pVariant ) = VT_NULL; /* fallthrough */ default: if( pVarRef ) { V_VT( pVarRef ) = VT_VARIANT | VT_BYREF; V_VARIANTREF( pVarRef ) = pVariant; } } /* enabling this code may allow to exchange parameters by reference * without strong typing restrictions but I do not know if such method * is honored by other OLE code */ #if 0 if( pVarRef ) { V_VT( pVarRef ) = VT_VARIANT | VT_BYREF; V_VARIANTREF( pVarRef ) = pVariant; } #endif } void hb_oleItemToVariant( VARIANT * pVariant, PHB_ITEM pItem ) { hb_oleItemToVariantRef( pVariant, pItem, NULL, NULL ); } void hb_oleItemToVariantEx( VARIANT * pVariant, PHB_ITEM pItem, HB_OLEOBJ_FUNC pObjFunc ) { hb_oleItemToVariantRef( pVariant, pItem, NULL, pObjFunc ); } static void hb_oleSafeArrayToItem( PHB_ITEM pItem, SAFEARRAY * pSafeArray, int iDims, int iDim, long * plIndex, VARTYPE vt, HB_USHORT uiClass ) { long lFrom, lTo; if( SafeArrayGetLBound( pSafeArray, iDim, &lFrom ) == S_OK && SafeArrayGetUBound( pSafeArray, iDim, &lTo ) == S_OK && lFrom <= lTo ) { HB_SIZE nIndex = 0; hb_arrayNew( pItem, lTo - lFrom + 1 ); if( iDim == iDims ) { VARIANT vItem; VariantInit( &vItem ); do { plIndex[ iDim - 1 ] = lFrom; /* hack: for non VT_VARIANT arrays create VARIANT dynamically * using pointer to union in variant structure which * holds all variant values except VT_DECIMAL which is * stored in different place. */ if( SafeArrayGetElement( pSafeArray, plIndex, vt == VT_VARIANT ? ( void * ) &vItem : ( vt == VT_DECIMAL ? ( void * ) &HB_WIN_U1( &vItem, decVal ) : ( void * ) &HB_WIN_U3( &vItem, bVal ) ) ) == S_OK ) { if( vt != VT_VARIANT ) V_VT( &vItem ) = vt; /* it's reserved in VT_DECIMAL structure */ hb_oleVariantToItemEx( hb_arrayGetItemPtr( pItem, ++nIndex ), &vItem, uiClass ); VariantClear( &vItem ); } } while( ++lFrom <= lTo ); } else { do { plIndex[ iDim - 1 ] = lFrom; hb_oleSafeArrayToItem( hb_arrayGetItemPtr( pItem, ++nIndex ), pSafeArray, iDims, iDim + 1, plIndex, vt, uiClass ); } while( ++lFrom <= lTo ); } } else hb_arrayNew( pItem, 0 ); } void hb_oleDispatchToItem( PHB_ITEM pItem, IDispatch * pdispVal, HB_USHORT uiClass ) { if( pdispVal ) { if( hb_vmRequestReenter() ) { PHB_SYMB pClassFunc; PHB_ITEM pObject, pPtrGC; pClassFunc = hb_clsFuncSym( uiClass ); if( ! pClassFunc ) pClassFunc = hb_dynsymSymbol( s_pDyns_hb_oleauto ); hb_vmPushSymbol( pClassFunc ); hb_vmPushNil(); hb_vmDo( 0 ); pObject = hb_itemNew( hb_stackReturnItem() ); pPtrGC = hb_oleItemPut( NULL, pdispVal ); /* Item is one more copy of the object */ HB_VTBL( pdispVal )->AddRef( HB_THIS( pdispVal ) ); hb_vmPushDynSym( s_pDyns_hObjAssign ); hb_vmPush( pObject ); hb_vmPush( pPtrGC ); hb_vmSend( 1 ); hb_itemRelease( pPtrGC ); hb_vmRequestRestore(); /* We should store object to pItem after hb_vmRequestRestore(), * because pItem actually can be stack's return item! */ hb_itemMove( pItem, pObject ); hb_itemRelease( pObject ); } } } void hb_oleVariantToItemEx( PHB_ITEM pItem, VARIANT * pVariant, HB_USHORT uiClass ) { if( V_VT( pVariant ) == ( VT_VARIANT | VT_BYREF ) ) pVariant = V_VARIANTREF( pVariant ); switch( V_VT( pVariant ) ) { case VT_UNKNOWN: case VT_UNKNOWN | VT_BYREF: { IDispatch * pdispVal = NULL; IUnknown * punkVal = V_VT( pVariant ) == VT_UNKNOWN ? V_UNKNOWN( pVariant ) : *V_UNKNOWNREF( pVariant ); hb_itemClear( pItem ); if( punkVal && HB_VTBL( punkVal )->QueryInterface( HB_THIS_( punkVal ) HB_ID_REF( IID_IDispatch ), ( void ** ) ( void * ) &pdispVal ) == S_OK ) { hb_oleDispatchToItem( pItem, pdispVal, uiClass ); HB_VTBL( pdispVal )->Release( HB_THIS( pdispVal ) ); } break; } case VT_DISPATCH: case VT_DISPATCH | VT_BYREF: hb_itemClear( pItem ); hb_oleDispatchToItem( pItem, V_VT( pVariant ) == VT_DISPATCH ? V_DISPATCH( pVariant ) : *V_DISPATCHREF( pVariant ), uiClass ); break; case VT_BSTR: hb_oleStringToItem( V_BSTR( pVariant ), pItem ); break; case VT_BSTR | VT_BYREF: hb_oleStringToItem( *V_BSTRREF( pVariant ), pItem ); break; case VT_BOOL: hb_itemPutL( pItem, V_BOOL( pVariant ) ? HB_TRUE : HB_FALSE ); break; case VT_BOOL | VT_BYREF: hb_itemPutL( pItem, *V_BOOLREF( pVariant ) ? HB_TRUE : HB_FALSE ); break; case VT_I1: hb_itemPutNI( pItem, ( signed char ) V_I1( pVariant ) ); break; case VT_I1 | VT_BYREF: hb_itemPutNI( pItem, ( signed char ) *V_I1REF( pVariant ) ); break; case VT_I2: hb_itemPutNI( pItem, ( short ) V_I2( pVariant ) ); break; case VT_I2 | VT_BYREF: hb_itemPutNI( pItem, ( short ) *V_I2REF( pVariant ) ); break; case VT_I4: hb_itemPutNL( pItem, V_I4( pVariant ) ); break; case VT_I4 | VT_BYREF: hb_itemPutNL( pItem, *V_I4REF( pVariant ) ); break; case VT_I8: #if HB_VMLONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) hb_itemPutNInt( pItem, ( HB_MAXINT ) V_I4( pVariant ) ); #elif defined( HB_OLE_NO_LL ) /* workaround for wrong OLE variant structure definition */ hb_itemPutNInt( pItem, *( ( HB_LONGLONG * ) &V_I4( pVariant ) ) ); #else hb_itemPutNInt( pItem, V_I8( pVariant ) ); #endif break; case VT_I8 | VT_BYREF: #if HB_VMLONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) hb_itemPutNInt( pItem, ( HB_MAXINT ) *V_I4REF( pVariant ) ); #elif defined( HB_OLE_NO_LLREF ) /* workaround for wrong OLE variant structure definition */ hb_itemPutNInt( pItem, *( HB_LONGLONG * ) V_R8REF( pVariant ) ); #else hb_itemPutNInt( pItem, *V_I8REF( pVariant ) ); #endif break; case VT_UI1: hb_itemPutNI( pItem, ( unsigned char ) V_UI1( pVariant ) ); break; case VT_UI1 | VT_BYREF: hb_itemPutNI( pItem, ( unsigned char ) *V_UI1REF( pVariant ) ); break; case VT_UI2: hb_itemPutNI( pItem, ( unsigned short ) V_UI2( pVariant ) ); break; case VT_UI2 | VT_BYREF: hb_itemPutNI( pItem, ( unsigned short ) *V_UI2REF( pVariant ) ); break; case VT_UI4: hb_itemPutNInt( pItem, V_UI4( pVariant ) ); break; case VT_UI4 | VT_BYREF: hb_itemPutNInt( pItem, *V_UI4REF( pVariant ) ); break; case VT_UI8: /* TODO: sign is lost. Conversion to double will lose significant digits. */ #if HB_VMLONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) hb_itemPutNInt( pItem, ( HB_MAXINT ) V_UI4( pVariant ) ); #elif defined( HB_OLE_NO_LL ) /* workaround for wrong OLE variant structure definition */ hb_itemPutNInt( pItem, *( ( HB_LONGLONG * ) &V_UI4( pVariant ) ) ); #else hb_itemPutNInt( pItem, ( HB_MAXINT ) V_UI8( pVariant ) ); #endif break; case VT_UI8 | VT_BYREF: /* TODO: sign is lost. Conversion to double will lose significant digits. */ #if HB_VMLONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) hb_itemPutNInt( pItem, ( HB_MAXINT ) *V_UI4REF( pVariant ) ); #elif defined( HB_OLE_NO_LLREF ) /* workaround for wrong OLE variant structure definition */ hb_itemPutNInt( pItem, *( HB_LONGLONG * ) V_R8REF( pVariant ) ); #else hb_itemPutNInt( pItem, ( HB_MAXINT ) *V_UI8REF( pVariant ) ); #endif break; case VT_INT: hb_itemPutNI( pItem, V_INT( pVariant ) ); break; case VT_INT | VT_BYREF: hb_itemPutNI( pItem, *V_INTREF( pVariant ) ); break; case VT_UINT: hb_itemPutNInt( pItem, V_UINT( pVariant ) ); break; case VT_UINT | VT_BYREF: hb_itemPutNInt( pItem, *V_UINTREF( pVariant ) ); break; case VT_ERROR: hb_itemPutNInt( pItem, V_ERROR( pVariant ) ); break; case VT_ERROR | VT_BYREF: hb_itemPutNInt( pItem, *V_ERRORREF( pVariant ) ); break; case VT_R4: hb_itemPutND( pItem, ( double ) V_R4( pVariant ) ); break; case VT_R4 | VT_BYREF: hb_itemPutND( pItem, ( double ) *V_R4REF( pVariant ) ); break; case VT_R8: hb_itemPutND( pItem, V_R8( pVariant ) ); break; case VT_R8 | VT_BYREF: hb_itemPutND( pItem, *V_R8REF( pVariant ) ); break; case VT_CY: case VT_CY | VT_BYREF: { double dblVal; if( VarR8FromCy( V_VT( pVariant ) == VT_CY ? V_CY( pVariant ) : *V_CYREF( pVariant ), &dblVal ) != S_OK ) dblVal = 0; hb_itemPutND( pItem, dblVal ); #if 0 hb_itemPutNDLen( pItem, dblVal, 0, 4 ); #endif break; } case VT_DECIMAL: case VT_DECIMAL | VT_BYREF: { double dblVal; if( VarR8FromDec( V_VT( pVariant ) == VT_DECIMAL ? &HB_WIN_U1( pVariant, decVal ) : V_DECIMALREF( pVariant ), &dblVal ) != S_OK ) dblVal = 0; hb_itemPutND( pItem, dblVal ); break; } case VT_DATE: case VT_DATE | VT_BYREF: { long lJulian, lMilliSec; double dblVal = V_VT( pVariant ) == VT_DATE ? V_R8( pVariant ) : *V_R8REF( pVariant ); hb_timeStampUnpackDT( dblVal + HB_OLE_DATE_BASE, &lJulian, &lMilliSec ); if( lMilliSec ) hb_itemPutTDT( pItem, lJulian, lMilliSec ); else hb_itemPutDL( pItem, lJulian ); break; } #ifdef HB_OLE_PASS_POINTERS case VT_PTR: case VT_PTR | VT_BYREF: case VT_BYREF: hb_itemPutPtr( pItem, V_BYREF( pVariant ) ); break; #endif case VT_EMPTY: case VT_EMPTY | VT_BYREF: case VT_NULL: case VT_NULL | VT_BYREF: hb_itemClear( pItem ); break; default: if( V_VT( pVariant ) & VT_ARRAY ) { SAFEARRAY * pSafeArray = ( V_VT( pVariant ) & VT_BYREF ) ? *V_ARRAYREF( pVariant ) : V_ARRAY( pVariant ); if( pSafeArray ) { int iDims = ( int ) SafeArrayGetDim( pSafeArray ); if( iDims >= 1 ) { if( iDims > 1 || ! hb_oleSafeArrayToString( pItem, pSafeArray ) ) { long * plIndex = ( long * ) hb_xgrab( iDims * sizeof( long ) ); hb_oleSafeArrayToItem( pItem, pSafeArray, iDims, 1, plIndex, ( VARTYPE ) ( V_VT( pVariant ) & ~( VT_ARRAY | VT_BYREF ) ), uiClass ); hb_xfree( plIndex ); } } else hb_arrayNew( pItem, 0 ); break; } } /* possible RT error - unsupported variant */ hb_itemClear( pItem ); } } void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT * pVariant ) { hb_oleVariantToItemEx( pItem, pVariant, 0 ); } void hb_oleVariantUpdate( VARIANT * pVariant, PHB_ITEM pItem, HB_OLEOBJ_FUNC pObjFunc ) { switch( V_VT( pVariant ) ) { case VT_DISPATCH | VT_BYREF: { IDispatch * pDisp = hb_oleItemGetDispatch( pItem ); if( pDisp ) { IDispatch * pdispVal = *V_DISPATCHREF( pVariant ); if( pdispVal != pDisp ) { HB_VTBL( pDisp )->AddRef( HB_THIS( pDisp ) ); *V_DISPATCHREF( pVariant ) = pDisp; if( pdispVal ) HB_VTBL( pdispVal )->Release( HB_THIS( pdispVal ) ); } } else if( pObjFunc && HB_IS_OBJECT( pItem ) ) { VARIANTARG variant; VariantInit( &variant ); if( pObjFunc( &variant, pItem ) ) { IDispatch * pdispVal = *V_DISPATCHREF( pVariant ); *V_DISPATCHREF( pVariant ) = V_DISPATCH( &variant ); if( pdispVal ) HB_VTBL( pdispVal )->Release( HB_THIS( pdispVal ) ); } } break; } case VT_UNKNOWN | VT_BYREF: { IDispatch * pDisp = hb_oleItemGetDispatch( pItem ); if( pDisp ) { IUnknown * pUnk = NULL; if( HB_VTBL( pDisp )->QueryInterface( HB_THIS_( pDisp ) HB_ID_REF( IID_IEnumVARIANT ), ( void ** ) ( void * ) &pUnk ) == S_OK ) { IUnknown * punkVal = *V_UNKNOWNREF( pVariant ); if( punkVal ) HB_VTBL( punkVal )->Release( HB_THIS( punkVal ) ); *V_UNKNOWNREF( pVariant ) = pUnk; } } else if( pObjFunc && HB_IS_OBJECT( pItem ) ) { VARIANTARG variant; VariantInit( &variant ); if( pObjFunc( &variant, pItem ) ) { IDispatch * pdispVal = *V_DISPATCHREF( pVariant ); *V_DISPATCHREF( pVariant ) = V_DISPATCH( &variant ); if( pdispVal ) HB_VTBL( pdispVal )->Release( HB_THIS( pdispVal ) ); } } break; } case VT_BSTR | VT_BYREF: SysFreeString( *V_BSTRREF( pVariant ) ); *V_BSTRREF( pVariant ) = hb_oleItemToString( pItem ); break; case VT_BOOL | VT_BYREF: *V_BOOLREF( pVariant ) = ( VARIANT_BOOL ) hb_itemGetL( pItem ); break; case VT_I1 | VT_BYREF: *V_I1REF( pVariant ) = ( signed char ) hb_itemGetNI( pItem ); break; case VT_I2 | VT_BYREF: *V_I2REF( pVariant ) = ( short ) hb_itemGetNI( pItem ); break; case VT_I4 | VT_BYREF: *V_I4REF( pVariant ) = hb_itemGetNL( pItem ); break; case VT_I8 | VT_BYREF: #if HB_VMLONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) *V_I4REF( pVariant ) = ( long ) hb_itemGetNInt( pItem ); #elif defined( HB_OLE_NO_LLREF ) /* workaround for wrong OLE variant structure definition */ *( HB_LONGLONG * ) V_R8REF( pVariant ) = ( HB_LONGLONG ) hb_itemGetNInt( pItem ); #else *V_I8REF( pVariant ) = ( HB_LONGLONG ) hb_itemGetNInt( pItem ); #endif break; case VT_UI1 | VT_BYREF: *V_UI1REF( pVariant ) = ( unsigned char ) hb_itemGetNI( pItem ); break; case VT_UI2 | VT_BYREF: *V_UI2REF( pVariant ) = ( unsigned short ) hb_itemGetNI( pItem ); break; case VT_UI4 | VT_BYREF: *V_UI4REF( pVariant ) = ( unsigned long ) hb_itemGetNL( pItem ); break; case VT_UI8 | VT_BYREF: #if HB_VMLONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) *V_UI4REF( pVariant ) = ( unsigned long ) hb_itemGetNInt( pItem ); #elif defined( HB_OLE_NO_LLREF ) /* workaround for wrong OLE variant structure definition */ *( HB_ULONGLONG * ) V_R8REF( pVariant ) = ( HB_ULONGLONG ) hb_itemGetNInt( pItem ); #else *V_UI8REF( pVariant ) = ( HB_ULONGLONG ) hb_itemGetNInt( pItem ); #endif break; case VT_INT | VT_BYREF: *V_INTREF( pVariant ) = hb_itemGetNI( pItem ); break; case VT_UINT | VT_BYREF: *V_UINTREF( pVariant ) = ( unsigned int ) hb_itemGetNI( pItem ); break; case VT_ERROR | VT_BYREF: *V_ERRORREF( pVariant ) = ( SCODE ) hb_itemGetNL( pItem ); break; case VT_R4 | VT_BYREF: *V_R4REF( pVariant ) = ( float ) hb_itemGetND( pItem ); break; case VT_R8 | VT_BYREF: *V_R8REF( pVariant ) = hb_itemGetND( pItem ); break; case VT_CY | VT_BYREF: VarCyFromR8( hb_itemGetND( pItem ), V_CYREF( pVariant ) ); break; case VT_DECIMAL | VT_BYREF: VarDecFromR8( hb_itemGetND( pItem ), V_DECIMALREF( pVariant ) ); break; case VT_DATE | VT_BYREF: *V_R8REF( pVariant ) = hb_itemGetTD( pItem ) - HB_OLE_DATE_BASE; break; #ifdef HB_OLE_PASS_POINTERS case VT_PTR | VT_BYREF: V_BYREF( pVariant ) = hb_itemGetPtr( pItem ); break; #endif case VT_BYREF | VT_VARIANT: hb_oleItemToVariantRef( V_VARIANTREF( pVariant ), pItem, NULL, pObjFunc ); break; case VT_VARIANT | VT_ARRAY | VT_BYREF: /* TODO: */ break; } } /* Invoke IDispatch method */ typedef struct { PHB_ITEM item; VARIANT * variant; } HB_OLE_PARAM_REF; HB_BOOL hb_oleDispInvoke( PHB_SYMB pSym, PHB_ITEM pObject, PHB_ITEM pParam, DISPPARAMS * pParams, VARIANT * pVarResult, HB_OLEOBJ_FUNC pObjFunc, HB_USHORT uiClass ) { if( ! pSym && HB_IS_SYMBOL( pObject ) ) { pSym = hb_itemGetSymbol( pObject ); pObject = NULL; } if( ( pSym || pObject ) && hb_vmRequestReenter() ) { HB_OLE_PARAM_REF refArray[ 32 ]; int i, ii, iParams, iCount, iRefs; iParams = iCount = pParams->cArgs; for( i = iRefs = 0; i < iCount && iRefs < ( int ) HB_SIZEOFARRAY( refArray ); i++ ) { if( V_VT( &pParams->rgvarg[ i ] ) & VT_BYREF ) refArray[ iRefs++ ].item = hb_stackAllocItem(); } if( pSym ) hb_vmPushSymbol( pSym ); else hb_vmPushEvalSym(); if( pObject ) hb_vmPush( pObject ); else hb_vmPushNil(); if( pParam ) { hb_vmPush( pParam ); iParams++; } for( i = 1, ii = 0; i <= iCount; i++ ) { if( ( V_VT( &pParams->rgvarg[ iCount - i ] ) & VT_BYREF ) && ( ii < iRefs ) ) { refArray[ ii ].variant = &pParams->rgvarg[ iCount - i ]; hb_oleVariantToItemEx( refArray[ ii ].item, refArray[ ii ].variant, uiClass ); hb_vmPushItemRef( refArray[ ii++ ].item ); } else hb_oleVariantToItemEx( hb_stackAllocItem(), &pParams->rgvarg[ iCount - i ], uiClass ); } if( pObject && ! HB_IS_HASH( pObject ) ) hb_vmSend( ( HB_USHORT ) iParams ); else hb_vmProc( ( HB_USHORT ) iParams ); if( pVarResult ) hb_oleItemToVariantRef( pVarResult, hb_stackReturnItem(), NULL, pObjFunc ); for( i = 0; i < iRefs; i++ ) hb_oleVariantUpdate( refArray[ i ].variant, refArray[ i ].item, pObjFunc ); for( i = 0; i < iRefs; i++ ) hb_stackPop(); hb_vmRequestRestore(); return HB_TRUE; } return HB_FALSE; } /* IDispatch parameters, return value handling */ static void GetParams( DISPPARAMS * dispparam, HB_UINT uiOffset, HB_BOOL fUseRef, UINT uiNamedArgs, PHB_ITEM * pNamedArgs, DISPID * pDispIds ) { VARIANTARG * pArgs = NULL; UINT uiArgCount; uiArgCount = ( UINT ) hb_pcount(); if( uiOffset > uiArgCount ) uiArgCount = 0; else uiArgCount -= uiOffset; if( uiArgCount > 0 || uiNamedArgs > 0 ) { VARIANTARG * pRefs; UINT uiArg, uiRefs; uiRefs = 0; if( fUseRef ) { for( uiArg = 1; uiArg <= uiArgCount; uiArg++ ) { if( HB_ISBYREF( uiOffset + uiArg ) ) uiRefs++; } } pArgs = ( VARIANTARG * ) hb_xgrab( sizeof( VARIANTARG ) * ( uiArgCount + uiRefs + uiNamedArgs ) ); pRefs = &pArgs[ uiArgCount + uiNamedArgs ]; for( uiArg = 0; uiArg < uiNamedArgs; uiArg++ ) { VARIANT * pVariant = &pArgs[ uiArg ]; VariantInit( pVariant ); hb_oleItemToVariantRef( pVariant, pNamedArgs[ uiArg ], NULL, NULL ); } for( uiArg = 0; uiArg < uiArgCount; uiArg++ ) { VARIANT * pVariant = &pArgs[ uiArg + uiNamedArgs ]; int iParam = ( int ) ( uiOffset + uiArgCount - uiArg ); VariantInit( pVariant ); if( fUseRef && HB_ISBYREF( iParam ) ) { VariantInit( pRefs ); hb_oleItemToVariantRef( pRefs, hb_param( iParam, HB_IT_ANY ), pVariant, NULL ); ++pRefs; } else hb_oleItemToVariantRef( pVariant, hb_param( iParam, HB_IT_ANY ), NULL, NULL ); } } dispparam->rgvarg = pArgs; dispparam->cArgs = uiArgCount + uiNamedArgs; dispparam->rgdispidNamedArgs = pDispIds; dispparam->cNamedArgs = uiNamedArgs; } #define HB_OLE_MAX_NAMEDARGS 32 static HRESULT GetNamedParams( IDispatch * pDisp, OLECHAR * szMethodName, PHB_ITEM pHash, UINT * puiNamedArgs, PHB_ITEM * pArgs, DISPID * pDispIds ) { OLECHAR * pNames[ HB_OLE_MAX_NAMEDARGS + 1 ]; void * phStrings[ HB_OLE_MAX_NAMEDARGS ]; HB_SIZE nLen = hb_hashLen( pHash ), nPos; int iArgs = 0, iArg; HRESULT lOleError; pNames[ 0 ] = szMethodName; for( nPos = 1; nPos <= nLen; ++nPos ) { PHB_ITEM pKey = hb_hashGetKeyAt( pHash, nPos ); if( HB_IS_STRING( pKey ) ) { pNames[ iArgs + 1 ] = ( HB_WCHAR * ) HB_UNCONST( hb_itemGetStrU16( pKey, HB_CDP_ENDIAN_NATIVE, &phStrings[ iArgs ], NULL ) ); if( pNames[ iArgs + 1 ] != NULL ) { pArgs[ iArgs ] = hb_hashGetValueAt( pHash, nPos ); if( ++iArgs == HB_OLE_MAX_NAMEDARGS ) break; } } } *puiNamedArgs = ( UINT ) iArgs; lOleError = HB_VTBL( pDisp )->GetIDsOfNames( HB_THIS_( pDisp ) HB_ID_REF( IID_NULL ), pNames, iArgs + 1, LOCALE_USER_DEFAULT, pDispIds ); for( iArg = 0; iArg < iArgs; ++iArg ) hb_strfree( phStrings[ iArg ] ); return lOleError; } static void PutParams( DISPPARAMS * dispparam, HB_UINT uiOffset, HB_USHORT uiClass ) { VARIANTARG * pRefs = &dispparam->rgvarg[ dispparam->cArgs ]; PHB_ITEM pItem = NULL; UINT uiArg; if( dispparam->cNamedArgs > 0 ) ++uiOffset; for( uiArg = dispparam->cNamedArgs; uiArg < dispparam->cArgs; uiArg++ ) { HB_USHORT uiParam = ( HB_USHORT ) ( uiOffset + dispparam->cArgs - uiArg ); if( HB_ISBYREF( uiParam ) ) { if( ! pItem ) pItem = hb_itemNew( NULL ); hb_oleVariantToItemEx( pItem, &dispparam->rgvarg[ uiArg ], uiClass ); hb_itemParamStoreForward( uiParam, pItem ); VariantClear( pRefs ); pRefs++; } } if( pItem ) hb_itemRelease( pItem ); } static void FreeParams( DISPPARAMS * dispparam ) { if( dispparam->cArgs > 0 ) { UINT ui; for( ui = 0; ui < dispparam->cArgs; ui++ ) VariantClear( &dispparam->rgvarg[ ui ] ); hb_xfree( dispparam->rgvarg ); } } /* PRG level functions and methods */ HB_FUNC( __OLEISDISP ) { hb_retl( hb_oleItemGet( hb_param( 1, HB_IT_ANY ) ) != NULL ); } HB_FUNC( WIN_OLECLASSEXISTS ) /* ( cOleName | cCLSID ) */ { HB_BOOL fExists = HB_FALSE; const char * cOleName = hb_parc( 1 ); if( cOleName ) { CLSID ClassID; wchar_t * cCLSID = AnsiToWide( cOleName ); if( cOleName[ 0 ] == '{' ) fExists = ( CLSIDFromString( ( LPOLESTR ) cCLSID, &ClassID ) == NOERROR ); else fExists = ( CLSIDFromProgID( ( LPCOLESTR ) cCLSID, &ClassID ) == S_OK ); hb_xfree( cCLSID ); } hb_retl( fExists ); } HB_FUNC( __OLECREATEOBJECT ) /* ( cOleName | cCLSID [, cIID ] ) */ { GUID ClassID, iid = IID_IDispatch; IDispatch * pDisp = NULL; const char * cOleName = hb_parc( 1 ); const char * cID = hb_parc( 2 ); HRESULT lOleError; hb_oleInit(); if( cOleName ) { wchar_t * cCLSID = AnsiToWide( cOleName ); if( cOleName[ 0 ] == '{' ) lOleError = CLSIDFromString( ( LPOLESTR ) cCLSID, &ClassID ); else lOleError = CLSIDFromProgID( ( LPCOLESTR ) cCLSID, &ClassID ); hb_xfree( cCLSID ); if( cID ) { if( cID[ 0 ] == '{' ) { cCLSID = AnsiToWide( cID ); lOleError = CLSIDFromString( ( LPOLESTR ) cCLSID, &iid ); hb_xfree( cCLSID ); } else if( hb_parclen( 2 ) == ( HB_SIZE ) sizeof( iid ) ) { memcpy( ( LPVOID ) &iid, cID, sizeof( iid ) ); } } if( lOleError == S_OK ) lOleError = CoCreateInstance( HB_ID_REF( ClassID ), NULL, CLSCTX_SERVER, HB_ID_REF( iid ), ( void ** ) ( void * ) &pDisp ); } else lOleError = CO_E_CLASSSTRING; hb_oleSetError( lOleError ); if( lOleError == S_OK ) hb_oleItemPut( hb_stackReturnItem(), pDisp ); else hb_ret(); } HB_FUNC( __OLEGETACTIVEOBJECT ) /* ( cOleName | cCLSID [, cIID ] ) */ { #if defined( HB_OS_WIN_CE ) hb_oleSetError( E_NOTIMPL ); #else BSTR wCLSID; IID ClassID, iid = IID_IDispatch; IDispatch * pDisp = NULL; IUnknown * pUnk = NULL; const char * cOleName = hb_parc( 1 ); const char * cID = hb_parc( 2 ); HRESULT lOleError; hb_oleInit(); if( cOleName ) { wCLSID = ( BSTR ) AnsiToWide( ( LPSTR ) cOleName ); if( cOleName[ 0 ] == '{' ) lOleError = CLSIDFromString( wCLSID, ( LPCLSID ) &ClassID ); else lOleError = CLSIDFromProgID( wCLSID, ( LPCLSID ) &ClassID ); hb_xfree( wCLSID ); if( cID ) { if( cID[ 0 ] == '{' ) { wCLSID = ( BSTR ) AnsiToWide( ( LPSTR ) cID ); lOleError = CLSIDFromString( wCLSID, &iid ); hb_xfree( wCLSID ); } else if( hb_parclen( 2 ) == ( HB_SIZE ) sizeof( iid ) ) { memcpy( ( LPVOID ) &iid, cID, sizeof( iid ) ); } } if( lOleError == S_OK ) { lOleError = GetActiveObject( HB_ID_REF( ClassID ), NULL, &pUnk ); if( lOleError == S_OK ) { lOleError = HB_VTBL( pUnk )->QueryInterface( HB_THIS_( pUnk ) HB_ID_REF( iid ), ( void ** ) ( void * ) &pDisp ); HB_VTBL( pUnk )->Release( HB_THIS( pUnk ) ); } } } else lOleError = CO_E_CLASSSTRING; hb_oleSetError( lOleError ); if( lOleError == S_OK ) hb_oleItemPut( hb_stackReturnItem(), pDisp ); else hb_ret(); #endif } HB_FUNC( __OLEENUMCREATE ) /* ( __hObj ) */ { IDispatch * pDisp; IEnumVARIANT * pEnum; VARIANTARG variant; DISPPARAMS dispparam; EXCEPINFO excep; UINT uiArgErr; HRESULT lOleError; pDisp = hb_oleParam( 1 ); if( ! pDisp ) return; if( hb_parl( 2 ) ) { hb_oleSetError( S_OK ); hb_errRT_OLE( EG_UNSUPPORTED, 1003, 0, NULL, HB_ERR_FUNCNAME, NULL ); return; } memset( &excep, 0, sizeof( excep ) ); memset( &dispparam, 0, sizeof( dispparam ) ); /* empty parameters */ VariantInit( &variant ); lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) DISPID_NEWENUM, HB_ID_REF( IID_NULL ), LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparam, &variant, &excep, &uiArgErr ); if( lOleError == S_OK ) { if( V_VT( &variant ) == VT_UNKNOWN ) lOleError = HB_VTBL( V_UNKNOWN( &variant ) )->QueryInterface( HB_THIS_( HB_WIN_U3( &variant, punkVal ) ) HB_ID_REF( IID_IEnumVARIANT ), ( void ** ) ( void * ) &pEnum ); else if( V_VT( &variant ) == VT_DISPATCH ) lOleError = HB_VTBL( HB_WIN_U3( &variant, pdispVal ) )->QueryInterface( HB_THIS_( HB_WIN_U3( &variant, pdispVal ) ) HB_ID_REF( IID_IEnumVARIANT ), ( void ** ) ( void * ) &pEnum ); else { VariantClear( &variant ); hb_oleSetError( lOleError ); hb_errRT_OLE( EG_ARG, 1004, ( HB_ERRCODE ) lOleError, NULL, HB_ERR_FUNCNAME, NULL ); return; } VariantClear( &variant ); if( lOleError == S_OK ) { IEnumVARIANT ** ppEnum; hb_oleSetError( S_OK ); ppEnum = ( IEnumVARIANT ** ) hb_gcAllocate( sizeof( IEnumVARIANT * ), &s_gcOleenumFuncs ); *ppEnum = pEnum; hb_retptrGC( ppEnum ); return; } } hb_oleSetError( lOleError ); hb_errRT_OLE( EG_ARG, 1005, ( HB_ERRCODE ) lOleError, NULL, HB_ERR_FUNCNAME, NULL ); } HB_FUNC( __OLEENUMNEXT ) { IEnumVARIANT * pEnum = hb_oleenumParam( 1 ); HB_BOOL fResult = HB_FALSE; if( pEnum ) { VARIANTARG variant; hb_oleInit(); VariantInit( &variant ); if( HB_VTBL( pEnum )->Next( HB_THIS_( pEnum ) 1, &variant, NULL ) == S_OK ) { hb_oleVariantToItemEx( hb_stackReturnItem(), &variant, ( HB_USHORT ) hb_parni( 3 ) ); VariantClear( &variant ); fResult = HB_TRUE; } } hb_storl( fResult, 2 ); } HB_FUNC( WIN_OLEERROR ) { hb_retnint( hb_oleGetError() ); } #ifndef DISP_E_BUFFERTOOSMALL #define DISP_E_BUFFERTOOSMALL 0x80020013L #endif HB_FUNC( WIN_OLEERRORTEXT ) { HRESULT lOleError = HB_ISNUM( 1 ) ? hb_parnl( 1 ) : hb_oleGetError(); switch( lOleError ) { case S_OK: hb_retc_null(); break; case CO_E_CLASSSTRING: hb_retc_const( "CO_E_CLASSSTRING" ); break; case OLE_E_WRONGCOMPOBJ: hb_retc_const( "OLE_E_WRONGCOMPOBJ" ); break; case REGDB_E_CLASSNOTREG: hb_retc_const( "REGDB_E_CLASSNOTREG" ); break; case REGDB_E_WRITEREGDB: hb_retc_const( "REGDB_E_WRITEREGDB" ); break; case E_PENDING: hb_retc_const( "E_PENDING" ); break; case E_NOTIMPL: hb_retc_const( "E_NOTIMPL" ); break; case E_NOINTERFACE: hb_retc_const( "E_NOINTERFACE" ); break; case E_POINTER: hb_retc_const( "E_POINTER" ); break; case E_ABORT: hb_retc_const( "E_ABORT" ); break; case E_FAIL: hb_retc_const( "E_FAIL" ); break; case E_UNEXPECTED: hb_retc_const( "E_UNEXPECTED" ); break; case E_ACCESSDENIED: hb_retc_const( "E_ACCESSDENIED" ); break; case E_HANDLE: hb_retc_const( "E_HANDLE" ); break; case E_OUTOFMEMORY: hb_retc_const( "E_OUTOFMEMORY" ); break; case E_INVALIDARG: hb_retc_const( "E_INVALIDARG" ); break; case DISP_E_UNKNOWNINTERFACE: hb_retc_const( "DISP_E_UNKNOWNINTERFACE" ); break; case DISP_E_MEMBERNOTFOUND: hb_retc_const( "DISP_E_MEMBERNOTFOUND" ); break; case DISP_E_PARAMNOTFOUND: hb_retc_const( "DISP_E_PARAMNOTFOUND" ); break; case DISP_E_TYPEMISMATCH: hb_retc_const( "DISP_E_TYPEMISMATCH" ); break; case DISP_E_UNKNOWNNAME: hb_retc_const( "DISP_E_UNKNOWNNAME" ); break; case DISP_E_NONAMEDARGS: hb_retc_const( "DISP_E_NONAMEDARGS" ); break; case DISP_E_BADVARTYPE: hb_retc_const( "DISP_E_BADVARTYPE" ); break; case DISP_E_EXCEPTION: hb_retc_const( "DISP_E_EXCEPTION" ); break; case DISP_E_OVERFLOW: hb_retc_const( "DISP_E_OVERFLOW" ); break; case DISP_E_BADINDEX: hb_retc_const( "DISP_E_BADINDEX" ); break; case DISP_E_UNKNOWNLCID: hb_retc_const( "DISP_E_UNKNOWNLCID" ); break; case DISP_E_ARRAYISLOCKED: hb_retc_const( "DISP_E_ARRAYISLOCKED" ); break; case DISP_E_BADPARAMCOUNT: hb_retc_const( "DISP_E_BADPARAMCOUNT" ); break; case DISP_E_PARAMNOTOPTIONAL: hb_retc_const( "DISP_E_PARAMNOTOPTIONAL" ); break; case DISP_E_BADCALLEE: hb_retc_const( "DISP_E_BADCALLEE" ); break; case DISP_E_NOTACOLLECTION: hb_retc_const( "DISP_E_NOTACOLLECTION" ); break; case DISP_E_DIVBYZERO: hb_retc_const( "DISP_E_DIVBYZERO" ); break; case DISP_E_BUFFERTOOSMALL: hb_retc_const( "DISP_E_BUFFERTOOSMALL" ); break; default: { char buf[ 16 ]; hb_snprintf( buf, 16, "0x%08x", ( UINT ) ( HB_PTRUINT ) lOleError ); hb_retc( buf ); } } } /* VBScript and Harbour syntax and IDispatch:Invoke() usage differences VBScript syntax dispid DISPATCH_* flags argcnt | Harbour syntax :Invoke parameters ================================================================+======================================= obj DISPID_VALUE METHOD+PROPERTYGET 0 | Same :Invoke is not used obj() DISPID_VALUE METHOD 0 | Not supported obj(param) DISPID_VALUE METHOD+PROPERTYGET 1 | obj[param] Same obj.name name METHOD+PROPERTYGET 0 | Same, =obj.name() Same obj.name() name METHOD 0 | Same, =obj.name flags=METHOD+PROPERTYGET obj.name(param) name METHOD+PROPERTYGET 1 | Same Same | obj = value obj reassigned, :Invoke is not used | Same obj() = value DISPID_VALUE PROPERTYPUT 1 | Not supported obj(param) = value DISPID_VALUE PROPERTYPUT 2 | obj[param] = value obj.name = value name PROPERTYPUT 1 | Same Same obj.name() = value name PROPERTYPUT 1 | Not supported, use obj.name = value obj.name(param) = value name PROPERTYPUT 2 | Not supported, workaround obj._name(param, value) */ HB_FUNC( WIN_OLEAUTO___ONERROR ) { IDispatch * pDisp; const char * szMethod; wchar_t szMethodWide[ HB_SYMBOL_NAME_LEN + 1 ]; OLECHAR * pMemberArray; DISPID dispid; DISPPARAMS dispparam; VARIANTARG variant; EXCEPINFO excep; UINT uiArgErr; HRESULT lOleError; HB_USHORT uiClass; int iPCount; hb_oleInit(); uiClass = hb_objGetClass( hb_stackSelfItem() ); if( uiClass == 0 ) return; /* Get object handle */ hb_vmPushDynSym( s_pDyns_hObjAccess ); hb_vmPush( hb_stackSelfItem() ); hb_vmSend( 0 ); pDisp = hb_oleParam( -1 ); if( ! pDisp ) return; dispid = ( DISPID ) 0; /* to pacify MSVC false warning */ iPCount = hb_pcount(); szMethod = hb_itemGetSymbol( hb_stackBaseItem() )->szName; AnsiToWideBuffer( szMethod, szMethodWide, ( int ) HB_SIZEOFARRAY( szMethodWide ) ); /* Try property put */ if( szMethod[ 0 ] == '_' && iPCount >= 1 ) { pMemberArray = &szMethodWide[ 1 ]; lOleError = HB_VTBL( pDisp )->GetIDsOfNames( HB_THIS_( pDisp ) HB_ID_REF( IID_NULL ), &pMemberArray, 1, LOCALE_USER_DEFAULT, &dispid ); if( lOleError == S_OK ) { DISPID lPropPut = DISPID_PROPERTYPUT; WORD wFlags; memset( &excep, 0, sizeof( excep ) ); GetParams( &dispparam, 0, HB_FALSE, 0, NULL, NULL ); dispparam.rgdispidNamedArgs = &lPropPut; dispparam.cNamedArgs = 1; wFlags = V_VT( &dispparam.rgvarg[ 0 ] ) == VT_DISPATCH ? DISPATCH_PROPERTYPUTREF : DISPATCH_PROPERTYPUT; lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) dispid, HB_ID_REF( IID_NULL ), LOCALE_USER_DEFAULT, wFlags, &dispparam, NULL, &excep, &uiArgErr ); if( lOleError == DISP_E_MEMBERNOTFOUND && wFlags == DISPATCH_PROPERTYPUTREF ) lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) dispid, HB_ID_REF( IID_NULL ), LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparam, NULL, &excep, &uiArgErr ); FreeParams( &dispparam ); /* assign method should return assigned value */ hb_itemReturn( hb_param( iPCount, HB_IT_ANY ) ); hb_oleSetError( lOleError ); if( lOleError != S_OK ) { char * szDescription = NULL; char * szSource = NULL; if( lOleError == DISP_E_EXCEPTION ) hb_oleExcepDescription( &excep, &szDescription, &szSource ); hb_errRT_OLE( EG_ARG, 1006, ( HB_ERRCODE ) lOleError, szDescription, HB_ERR_FUNCNAME, szSource ); if( szSource ) hb_xfree( szSource ); if( szDescription ) hb_xfree( szDescription ); } return; } } /* Try property get and invoke */ if( iPCount >= 1 && HB_ISHASH( 1 ) ) { /* named parameters are passed in hash array */ PHB_ITEM pArgs[ HB_OLE_MAX_NAMEDARGS ]; DISPID pDispIds[ HB_OLE_MAX_NAMEDARGS + 1 ]; UINT uiNamedArgs; lOleError = GetNamedParams( pDisp, szMethodWide, hb_param( 1, HB_IT_HASH ), &uiNamedArgs, pArgs, pDispIds ); if( lOleError == S_OK ) { dispid = pDispIds[ 0 ]; GetParams( &dispparam, 1, HB_TRUE, uiNamedArgs, pArgs, &pDispIds[ 1 ] ); } } else { pMemberArray = szMethodWide; lOleError = HB_VTBL( pDisp )->GetIDsOfNames( HB_THIS_( pDisp ) HB_ID_REF( IID_NULL ), &pMemberArray, 1, LOCALE_USER_DEFAULT, &dispid ); if( lOleError == S_OK ) GetParams( &dispparam, 0, HB_TRUE, 0, NULL, NULL ); } if( lOleError == S_OK ) { memset( &excep, 0, sizeof( excep ) ); VariantInit( &variant ); lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) dispid, HB_ID_REF( IID_NULL ), LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET | DISPATCH_METHOD, &dispparam, &variant, &excep, &uiArgErr ); PutParams( &dispparam, 0, uiClass ); FreeParams( &dispparam ); hb_oleVariantToItemEx( hb_stackReturnItem(), &variant, uiClass ); VariantClear( &variant ); hb_oleSetError( lOleError ); if( lOleError != S_OK ) { char * szDescription = NULL; char * szSource = NULL; if( lOleError == DISP_E_EXCEPTION ) hb_oleExcepDescription( &excep, &szDescription, &szSource ); hb_errRT_OLE( EG_ARG, 1007, ( HB_ERRCODE ) lOleError, szDescription, HB_ERR_FUNCNAME, szSource ); if( szSource ) hb_xfree( szSource ); if( szDescription ) hb_xfree( szDescription ); } return; } hb_oleSetError( lOleError ); /* TODO: add description containing TypeName of the object */ if( szMethod[ 0 ] == '_' ) hb_errRT_OLE( EG_NOVARMETHOD, 1008, ( HB_ERRCODE ) lOleError, NULL, szMethod + 1, NULL ); else hb_errRT_OLE( EG_NOMETHOD, 1009, ( HB_ERRCODE ) lOleError, NULL, szMethod, NULL ); } HB_FUNC( WIN_OLEAUTO___OPINDEX ) { IDispatch * pDisp; DISPPARAMS dispparam; VARIANTARG variant; EXCEPINFO excep; UINT uiArgErr; HRESULT lOleError; HB_BOOL fAssign; HB_USHORT uiClass; hb_oleInit(); uiClass = hb_objGetClass( hb_stackSelfItem() ); if( uiClass == 0 ) return; /* Get object handle */ hb_vmPushDynSym( s_pDyns_hObjAccess ); hb_vmPush( hb_stackSelfItem() ); hb_vmSend( 0 ); pDisp = hb_oleParam( -1 ); if( ! pDisp ) return; fAssign = hb_pcount() > 1; if( fAssign ) { /* Assign */ DISPID lPropPut = DISPID_PROPERTYPUT; memset( &excep, 0, sizeof( excep ) ); GetParams( &dispparam, 0, HB_FALSE, 0, NULL, NULL ); dispparam.rgdispidNamedArgs = &lPropPut; dispparam.cNamedArgs = 1; lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) DISPID_VALUE, HB_ID_REF( IID_NULL ), LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparam, NULL, &excep, &uiArgErr ); FreeParams( &dispparam ); /* assign method should return assigned value */ hb_itemReturn( hb_param( hb_pcount(), HB_IT_ANY ) ); } else { /* Access */ memset( &excep, 0, sizeof( excep ) ); VariantInit( &variant ); GetParams( &dispparam, 0, HB_TRUE, 0, NULL, NULL ); lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) DISPID_VALUE, HB_ID_REF( IID_NULL ), LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET | DISPATCH_METHOD, &dispparam, &variant, &excep, &uiArgErr ); PutParams( &dispparam, 0, uiClass ); FreeParams( &dispparam ); hb_oleVariantToItemEx( hb_stackReturnItem(), &variant, uiClass ); VariantClear( &variant ); } hb_oleSetError( lOleError ); if( lOleError != S_OK ) { /* Try to detect if object is a collection */ char * szDescription = NULL; char * szSource = NULL; HRESULT lOleErrorEnum; if( lOleError == DISP_E_EXCEPTION ) hb_oleExcepDescription( &excep, &szDescription, &szSource ); memset( &excep, 0, sizeof( excep ) ); memset( &dispparam, 0, sizeof( dispparam ) ); VariantInit( &variant ); lOleErrorEnum = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) DISPID_NEWENUM, HB_ID_REF( IID_NULL ), LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparam, &variant, &excep, &uiArgErr ); VariantClear( &variant ); hb_errRT_OLE( lOleErrorEnum == S_OK ? EG_BOUND : EG_ARG, 1016, ( HB_ERRCODE ) lOleError, lOleErrorEnum == S_OK ? hb_langDGetErrorDesc( fAssign ? EG_ARRASSIGN : EG_ARRACCESS ) : szDescription, NULL, szSource ); if( szDescription ) hb_xfree( szDescription ); if( szSource ) hb_xfree( szSource ); } } HB_FUNC( __OLEGETNAMEID ) { IDispatch * pDisp; pDisp = hb_oleParam( 1 ); if( pDisp ) { OLECHAR * pwszMethod; HRESULT lOleError; void * hMethod; DISPID dispid; pwszMethod = ( HB_WCHAR * ) hb_parstr_u16( 2, HB_CDP_ENDIAN_NATIVE, &hMethod, NULL ); lOleError = HB_VTBL( pDisp )->GetIDsOfNames( HB_THIS_( pDisp ) HB_ID_REF( IID_NULL ), &pwszMethod, 1, LOCALE_USER_DEFAULT, &dispid ); hb_strfree( hMethod ); if( lOleError == S_OK ) hb_retnint( dispid ); } } static void hb_oleInvokeCall( WORD wFlags ) { HB_USHORT uiOffset = 0; PHB_ITEM pObject; IDispatch * pDisp; pObject = hb_stackSelfItem(); if( HB_IS_NIL( pObject ) ) pObject = hb_param( ++uiOffset, HB_IT_ANY ); pDisp = pObject ? hb_oleItemGetDispatch( pObject ) : NULL; if( pDisp ) { DISPID dispid; DISPPARAMS dispparam; VARIANTARG variant; EXCEPINFO excep; UINT uiArgErr; HRESULT lOleError; HB_USHORT uiClass; OLECHAR * pwszMethod; void * hMethod; uiClass = hb_objGetClass( pObject ); ++uiOffset; pwszMethod = ( HB_WCHAR * ) hb_parstr_u16( uiOffset, HB_CDP_ENDIAN_NATIVE, &hMethod, NULL ); if( pwszMethod ) { lOleError = HB_VTBL( pDisp )->GetIDsOfNames( HB_THIS_( pDisp ) HB_ID_REF( IID_NULL ), &pwszMethod, 1, LOCALE_USER_DEFAULT, &dispid ); hb_strfree( hMethod ); } else { dispid = ( DISPID ) hb_parnint( uiOffset ); lOleError = S_OK; } if( lOleError == S_OK ) { DISPID lPropPut = wFlags; HB_BOOL fPut = wFlags == DISPATCH_PROPERTYPUT; memset( &excep, 0, sizeof( excep ) ); VariantInit( &variant ); GetParams( &dispparam, uiOffset, ! fPut, 0, NULL, NULL ); if( fPut ) { dispparam.rgdispidNamedArgs = &lPropPut; dispparam.cNamedArgs = 1; } lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) dispid, HB_ID_REF( IID_NULL ), LOCALE_USER_DEFAULT, wFlags, &dispparam, &variant, &excep, &uiArgErr ); if( ! fPut ) PutParams( &dispparam, uiOffset, uiClass ); FreeParams( &dispparam ); hb_oleVariantToItemEx( hb_stackReturnItem(), &variant, uiClass ); VariantClear( &variant ); hb_oleSetError( lOleError ); if( lOleError != S_OK ) { char * szExcepDescription = NULL; char * szExcepSource = NULL; if( lOleError == DISP_E_EXCEPTION ) hb_oleExcepDescription( &excep, &szExcepDescription, &szExcepSource ); hb_errRT_OLE( EG_ARG, 1007, ( HB_ERRCODE ) lOleError, szExcepDescription, HB_ERR_FUNCNAME, szExcepSource ); if( szExcepDescription ) hb_xfree( szExcepDescription ); if( szExcepSource ) hb_xfree( szExcepSource ); } return; } hb_errRT_OLE( EG_NOMETHOD, 1009, ( HB_ERRCODE ) lOleError, NULL, hb_parc( uiOffset ), NULL ); } else hb_errRT_OLE( EG_ARG, 1001, 0, NULL, HB_ERR_FUNCNAME, NULL ); } HB_FUNC( __OLEINVOKEMETHOD ) { hb_oleInvokeCall( DISPATCH_METHOD ); } HB_FUNC( __OLEINVOKEGET ) { hb_oleInvokeCall( DISPATCH_PROPERTYGET ); } HB_FUNC( __OLEINVOKEPUT ) { hb_oleInvokeCall( DISPATCH_PROPERTYPUT ); } /* __oleVariantGetValue( ) --> */ HB_FUNC( __OLEVARIANTGETVALUE ) { VARIANT * pVariant = hb_oleVariantParam( 1 ); if( pVariant ) hb_oleVariantToItemEx( hb_stackReturnItem(), pVariant, 0 ); } /* __oleVariantGetType( ) --> */ HB_FUNC( __OLEVARIANTGETTYPE ) { VARIANT * pVariant = hb_oleVariantParam( 1 ); if( pVariant ) hb_retni( V_VT( pVariant ) ); } /* __oleVariantNew( , [], [] ) --> */ HB_FUNC( __OLEVARIANTNEW ) { int iType = hb_parni( 1 ); PHB_ITEM pInit = hb_param( 2, HB_IT_ANY ); IDispatch * pDisp; VARIANT variant; V_VT( &variant ) = VT_ILLEGAL; if( pInit && HB_IS_ARRAY( pInit ) && iType == ( iType & VT_TYPEMASK ) ) iType |= VT_ARRAY; 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 ), &HB_WIN_U1( &variant, decVal ) /*&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_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; case VT_VARIANT: VariantInit( &variant ); if( pInit != NULL ) hb_oleItemToVariant( &variant, pInit ); break; default: if( iType & VT_ARRAY ) { iType &= ~VT_ARRAY; if( iType == ( iType & VT_TYPEMASK ) ) { long plBuf[ 16 ], * plSize; int iPCount = hb_pcount() - 2, iDims; if( iPCount < 0 ) iPCount = 0; iDims = iPCount; plSize = iDims < ( int ) HB_SIZEOFARRAY( plBuf ) ? plBuf : ( long * ) hb_xgrab( sizeof( long ) * iDims ); while( iPCount > 0 && HB_ISNIL( iPCount + 2 ) ) --iPCount; while( iPCount > 0 ) { --iPCount; plSize[ iPCount ] = hb_parnl( iPCount + 3 ); if( plSize[ iPCount ] <= 0 ) break; } if( iPCount <= 0 ) { V_ARRAY( &variant ) = hb_oleSafeArrayFromItem( pInit, ( VARTYPE ) iType, iDims, plSize ); if( V_ARRAY( &variant ) ) V_VT( &variant ) = ( VARTYPE ) ( iType | VT_ARRAY ); } if( plSize != plBuf ) hb_xfree( plBuf ); break; } } 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 ); } /* __oleVariantNullDate( [] ) --> */ HB_FUNC( __OLEVARIANTNULLDATE ) { hb_retl( hb_oleGetNullDateFlag() ); if( HB_ISLOG( 1 ) ) hb_oleSetNullDateFlag( hb_parl( 1 ) ); } /* __oleVariantNil2Null( [] ) --> */ HB_FUNC( __OLEVARIANTNIL2NULL ) { hb_retl( hb_oleGetNil2NullFlag() ); if( HB_ISLOG( 1 ) ) hb_oleSetNil2NullFlag( hb_parl( 1 ) ); } HB_CALL_ON_STARTUP_BEGIN( _hb_olecore_init_ ) hb_vmAtInit( hb_olecore_init, NULL ); HB_CALL_ON_STARTUP_END( _hb_olecore_init_ ) #if defined( HB_PRAGMA_STARTUP ) #pragma startup _hb_olecore_init_ #elif defined( HB_DATASEG_STARTUP ) #define HB_DATASEG_BODY HB_DATASEG_FUNC( _hb_olecore_init_ ) #include "hbiniseg.h" #endif