diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 3ff59c2f80..54d41e8966 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,18 @@ The license applies to all entries newer than 2009-04-28. */ +2011-08-09 14:26 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/src/vm/classes.c + ! added missing initialization of onError and destructor flags. + The problem could be exploited when class inherits from more + then one parent classes and onError handler[s] or destructor[s] + were neither defined in the class nor in the first ancestor. + + * harbour/contrib/hbwin/olecore.c + + added helper PRG functions: + __oleInvokeMethod(), __oleInvokePut(), __oleInvokeGet(), + __oleGetNameId() + 2011-08-08 15:55 UTC+0200 Tamas TEVESZ (ice extreme.hu) * contrib/hbct/ctwin.c ! use correct format string for int diff --git a/harbour/contrib/hbwin/olecore.c b/harbour/contrib/hbwin/olecore.c index c206937bb6..fa2cf4f3fd 100644 --- a/harbour/contrib/hbwin/olecore.c +++ b/harbour/contrib/hbwin/olecore.c @@ -1216,12 +1216,16 @@ HB_BOOL hb_oleDispInvoke( PHB_SYMB pSym, PHB_ITEM pObject, PHB_ITEM pParam, /* IDispatch parameters, return value handling */ -static void GetParams( DISPPARAMS * dispparam, HB_BOOL fUseRef ) +static void GetParams( DISPPARAMS * dispparam, HB_USHORT uiOffset, HB_BOOL fUseRef ) { VARIANTARG *pArgs = NULL, *pRefs; UINT uiArgCount, uiArg, uiRefs; uiArgCount = ( UINT ) hb_pcount(); + if( uiOffset > uiArgCount ) + uiArgCount = 0; + else + uiArgCount -= uiOffset; if( uiArgCount > 0 ) { @@ -1230,7 +1234,7 @@ static void GetParams( DISPPARAMS * dispparam, HB_BOOL fUseRef ) { for( uiArg = 1; uiArg <= uiArgCount; uiArg++ ) { - if( HB_ISBYREF( uiArg ) ) + if( HB_ISBYREF( uiOffset + uiArg ) ) uiRefs++; } } @@ -1241,15 +1245,15 @@ static void GetParams( DISPPARAMS * dispparam, HB_BOOL fUseRef ) for( uiArg = 0; uiArg < uiArgCount; uiArg++ ) { VariantInit( &pArgs[ uiArg ] ); - if( fUseRef && HB_ISBYREF( uiArgCount - uiArg ) ) + if( fUseRef && HB_ISBYREF( uiOffset + uiArgCount - uiArg ) ) { VariantInit( pRefs ); - hb_oleItemToVariantRef( pRefs, hb_param( uiArgCount - uiArg, HB_IT_ANY ), + hb_oleItemToVariantRef( pRefs, hb_param( uiOffset + uiArgCount - uiArg, HB_IT_ANY ), &pArgs[ uiArg ], NULL ); ++pRefs; } else - hb_oleItemToVariantRef( &pArgs[ uiArg ], hb_param( uiArgCount - uiArg, HB_IT_ANY ), NULL, NULL ); + hb_oleItemToVariantRef( &pArgs[ uiArg ], hb_param( uiOffset + uiArgCount - uiArg, HB_IT_ANY ), NULL, NULL ); } } @@ -1259,7 +1263,7 @@ static void GetParams( DISPPARAMS * dispparam, HB_BOOL fUseRef ) dispparam->cNamedArgs = 0; } -static void PutParams( DISPPARAMS * dispparam, HB_USHORT uiClass ) +static void PutParams( DISPPARAMS * dispparam, HB_USHORT uiOffset, HB_USHORT uiClass ) { VARIANTARG* pRefs = &dispparam->rgvarg[ dispparam->cArgs ]; PHB_ITEM pItem = NULL; @@ -1267,12 +1271,12 @@ static void PutParams( DISPPARAMS * dispparam, HB_USHORT uiClass ) for( uiArg = 0; uiArg < dispparam->cArgs; uiArg++ ) { - if( HB_ISBYREF( dispparam->cArgs - uiArg ) ) + if( HB_ISBYREF( uiOffset + dispparam->cArgs - uiArg ) ) { if( !pItem ) pItem = hb_itemNew( NULL ); hb_oleVariantToItemEx( pItem, &dispparam->rgvarg[ uiArg ], uiClass ); - hb_itemParamStoreForward( ( HB_USHORT ) ( dispparam->cArgs - uiArg ), pItem ); + hb_itemParamStoreForward( ( HB_USHORT ) ( uiOffset + dispparam->cArgs - uiArg ), pItem ); VariantClear( pRefs ); pRefs++; } @@ -1413,7 +1417,7 @@ HB_FUNC( __OLEGETACTIVEOBJECT ) /* ( cOleName | cCLSID [, cIID ] ) */ HB_FUNC( __OLEENUMCREATE ) /* ( __hObj ) */ { - IDispatch * pDisp = hb_oleParam( 1 ); + IDispatch * pDisp; IEnumVARIANT * pEnum; VARIANTARG variant; DISPPARAMS dispparam; @@ -1421,7 +1425,9 @@ HB_FUNC( __OLEENUMCREATE ) /* ( __hObj ) */ UINT uiArgErr; HRESULT lOleError; - hb_oleInit(); + pDisp = hb_oleParam( 1 ); + if( !pDisp ) + return; if( hb_parl( 2 ) ) { @@ -1613,7 +1619,7 @@ HB_FUNC( WIN_OLEAUTO___ONERROR ) DISPID lPropPut = DISPID_PROPERTYPUT; memset( &excep, 0, sizeof( excep ) ); - GetParams( &dispparam, HB_FALSE ); + GetParams( &dispparam, 0, HB_FALSE ); dispparam.rgdispidNamedArgs = &lPropPut; dispparam.cNamedArgs = 1; @@ -1643,14 +1649,14 @@ HB_FUNC( WIN_OLEAUTO___ONERROR ) { memset( &excep, 0, sizeof( excep ) ); VariantInit( &variant ); - GetParams( &dispparam, HB_TRUE ); + GetParams( &dispparam, 0, HB_TRUE ); 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, uiClass ); + PutParams( &dispparam, 0, uiClass ); FreeParams( &dispparam ); hb_oleVariantToItemEx( hb_stackReturnItem(), &variant, uiClass ); @@ -1704,7 +1710,7 @@ HB_FUNC( WIN_OLEAUTO___OPINDEX ) DISPID lPropPut = DISPID_PROPERTYPUT; memset( &excep, 0, sizeof( excep ) ); - GetParams( &dispparam, HB_FALSE ); + GetParams( &dispparam, 0, HB_FALSE ); dispparam.rgdispidNamedArgs = &lPropPut; dispparam.cNamedArgs = 1; @@ -1722,14 +1728,14 @@ HB_FUNC( WIN_OLEAUTO___OPINDEX ) /* Access */ memset( &excep, 0, sizeof( excep ) ); VariantInit( &variant ); - GetParams( &dispparam, HB_TRUE ); + GetParams( &dispparam, 0, HB_TRUE ); 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, uiClass ); + PutParams( &dispparam, 0, uiClass ); FreeParams( &dispparam ); hb_oleVariantToItemEx( hb_stackReturnItem(), &variant, uiClass ); @@ -1757,6 +1763,117 @@ HB_FUNC( WIN_OLEAUTO___OPINDEX ) } +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( 1, 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 = DISPID_PROPERTYPUT; + HB_BOOL fPut = wFlags == DISPATCH_PROPERTYPUT; + + if( wFlags == DISPATCH_PROPERTYGET ) + uiOffset = hb_pcount(); + memset( &excep, 0, sizeof( excep ) ); + VariantInit( &variant ); + GetParams( &dispparam, uiOffset, !fPut ); + 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 ) + hb_errRT_OLE( EG_ARG, 1007, ( HB_ERRCODE ) lOleError, NULL, HB_ERR_FUNCNAME ); + return; + } + } + else + hb_errRT_OLE( EG_ARG, 1001, 0, NULL, HB_ERR_FUNCNAME ); +} + +HB_FUNC( __OLEINVOKEMETHOD ) +{ + hb_oleInvokeCall( DISPATCH_METHOD ); +} + +HB_FUNC( __OLEINVOKEGET ) +{ + hb_oleInvokeCall( DISPATCH_PROPERTYGET ); +} + +HB_FUNC( __OLEINVOKEPUT ) +{ + hb_oleInvokeCall( DISPATCH_PROPERTYPUT ); +} + + HB_CALL_ON_STARTUP_BEGIN( _hb_olecore_init_ ) hb_vmAtInit( hb_olecore_init, NULL ); HB_CALL_ON_STARTUP_END( _hb_olecore_init_ ) diff --git a/harbour/src/vm/classes.c b/harbour/src/vm/classes.c index a872ab00dc..f9213fb2ce 100644 --- a/harbour/src/vm/classes.c +++ b/harbour/src/vm/classes.c @@ -372,6 +372,8 @@ static HB_USHORT s_uiNumericClass = 0; static HB_USHORT s_uiSymbolClass = 0; static HB_USHORT s_uiPointerClass = 0; +static HB_USHORT s_uiObjectClass = 0; + /* ================================================ */ /* @@ -1069,12 +1071,14 @@ void hb_clsDoInit( void ) { "HBARRAY", "HBBLOCK", "HBCHARACTER", "HBDATE", "HBTIMESTAMP", "HBHASH", "HBLOGICAL", "HBNIL", "HBNUMERIC", - "HBSYMBOL", "HBPOINTER" }; + "HBSYMBOL", "HBPOINTER", + "HBOBJECT" }; static HB_USHORT * s_puiHandles[] = { &s_uiArrayClass, &s_uiBlockClass, &s_uiCharacterClass, &s_uiDateClass, &s_uiTimeStampClass, &s_uiHashClass, &s_uiLogicalClass, &s_uiNilClass, &s_uiNumericClass, - &s_uiSymbolClass, &s_uiPointerClass }; + &s_uiSymbolClass, &s_uiPointerClass, + &s_uiObjectClass }; HB_STACK_TLS_PRELOAD int i; @@ -3305,10 +3309,16 @@ static HB_USHORT hb_clsNew( const char * szClassName, HB_USHORT uiDatas, return 0; /* Ok, this bucket is empty */ - if( pMethod->pMessage == NULL ) + if( pMethod->pMessage == NULL || + ( hb_clsCanClearMethod( pMethod, HB_FALSE ) && + ( pMethod->pFuncSym == &s___msgVirtual || + ( s_uiObjectClass != 0 && + pMethod->uiSprClass == s_uiObjectClass ) ) ) ) { - /* Now, we can increment the msg count */ - pNewCls->uiMethods++; + if( pMethod->pMessage == NULL ) + /* Now, we can increment the msg count */ + pNewCls->uiMethods++; + memcpy( pMethod, pSprCls->pMethods + n, sizeof( METHOD ) ); if( ! hb_clsUpdateHiddenMessages( pMethod, pMethod, pNewCls ) ) { @@ -3353,6 +3363,10 @@ static HB_USHORT hb_clsNew( const char * szClassName, HB_USHORT uiDatas, } } } + if( pSprCls->fHasOnError ) + pNewCls->fHasOnError = HB_TRUE; + if( pSprCls->fHasDestructor ) + pNewCls->fHasDestructor = HB_TRUE; pNewCls->nOpFlags |= pSprCls->nOpFlags; if( pSprCls->uiMutexOffset ) pNewCls->uiMutexOffset = 1; @@ -3655,7 +3669,8 @@ HB_FUNC( __CLSMODMSG ) PHB_ITEM pBlock = hb_param( 3, HB_IT_BLOCK ); if( pBlock ) { - if( pFuncSym == &s___msgEvalInline ) + if( pFuncSym == &s___msgEvalInline && + pMethod->uiSprClass == uiClass ) { hb_arraySet( s_pClasses[ pMethod->uiSprClass ]->pInlines, pMethod->uiData, pBlock );