From 4077cbb993ab8230b1ddd172be04b1cfae29da36 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Fri, 21 Aug 2009 11:35:11 +0000 Subject: [PATCH] 2009-08-21 13:34 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/bin/hb-func.sh ! do not strip system libraries in windows shared linking - unused ones are not attached to harbour*.dll * harbour/contrib/hbwin/hbwinole.h * harbour/contrib/hbwin/olecore.c + added support to pass strings with embedded chr(0) characters + added new public C function: IDispatch* hb_oleItemGet( PHB_ITEM pItem ); it extracts IDispatch* pointer from Harbour OLE pointer item. + added new public C function: void hb_oleVariantUpdate( VARIANT* pVariant, PHB_ITEM pItem ); it updates pVariant structure using values from given pointer item (used to update parameter passed by reference to activex event handler) % optimized some code * harbour/contrib/hbwin/hbwinole.h * harbour/contrib/hbwin/axcore.c + added new public C function: BOOL hb_oleAxInit( void ); + added new public C function: PHB_ITEM hb_oleAxControlNew( PHB_ITEM pItem, HWND hWnd ); It's C function with the same functionality as __AXGETCONTROL() ! allocate ISink structure using hb_xgrab() not hb_gcAlloc() ! initialize ISink reference counter to 0 ! fixed Release() method to free all allocated resources when reference counter reach 0 * return new Active-X control as Harbour OLE item pointer. Warning !!! hb_parptr() and hb_itemGetPtr() do not return valid pointer for controls created by hb_oleAxControlNew()/__AXGETCONTROL() Use hb_oleItemGet() and hb_oleParam() to extract pointer to IDispatch Please update existing code which used __AXGETCONTROL() pointers at C level. - removed not longer used hb_sink_destructor ! removed WIN_AXRELEASEOBJECT() - this function breaks reference counters used by OLE object which needs strict updating to avoid memory leaks (not freed OLE object) or GPF traps (accessing freed object) + extended Invoke() method to update OLE parameters passed by reference. + accept as event handler hash arrays indexed by event numbers and values with codeblocks or function pointers. Similar functionality exists in HWGUI when it's compiled with __USEHASHEVENTS macro and it's much better then passing two arrays. % optimized some code Please test above Active-X modifications. I'm not MS-Windows user so they have to be verified by real MS-Windows developers. They should fix problems with memory leaks (OLE objects where never freed) or GPF traps in C code which tired to strictly manage reference counters. To C programmers: if you increase reference counter to activex control (AddRef()) then you have to release it (Release()) or activex control will never be freed even after clearing all .prg references. It's released only when last reference owner calls Release() method so now valid code can keep references to IDispatch at C level without any problem but it also means that this code can exploit problems in existing wrong code. --- harbour/ChangeLog | 58 +++++++++ harbour/bin/hb-func.sh | 4 +- harbour/contrib/hbwin/axcore.c | 213 +++++++++++++++++++----------- harbour/contrib/hbwin/hbwinole.h | 8 +- harbour/contrib/hbwin/olecore.c | 214 +++++++++++++++++++++++++------ 5 files changed, 375 insertions(+), 122 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index d4d7d8ca0a..b62041bbcf 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,64 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-08-21 13:34 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/bin/hb-func.sh + ! do not strip system libraries in windows shared linking - unused + ones are not attached to harbour*.dll + + * harbour/contrib/hbwin/hbwinole.h + * harbour/contrib/hbwin/olecore.c + + added support to pass strings with embedded chr(0) characters + + added new public C function: + IDispatch* hb_oleItemGet( PHB_ITEM pItem ); + it extracts IDispatch* pointer from Harbour OLE pointer item. + + added new public C function: + void hb_oleVariantUpdate( VARIANT* pVariant, PHB_ITEM pItem ); + it updates pVariant structure using values from given pointer item + (used to update parameter passed by reference to activex event handler) + % optimized some code + + * harbour/contrib/hbwin/hbwinole.h + * harbour/contrib/hbwin/axcore.c + + added new public C function: + BOOL hb_oleAxInit( void ); + + added new public C function: + PHB_ITEM hb_oleAxControlNew( PHB_ITEM pItem, HWND hWnd ); + It's C function with the same functionality as __AXGETCONTROL() + ! allocate ISink structure using hb_xgrab() not hb_gcAlloc() + ! initialize ISink reference counter to 0 + ! fixed Release() method to free all allocated resources when + reference counter reach 0 + * return new Active-X control as Harbour OLE item pointer. + Warning !!! hb_parptr() and hb_itemGetPtr() do not return valid + pointer for controls created by hb_oleAxControlNew()/__AXGETCONTROL() + Use hb_oleItemGet() and hb_oleParam() to extract pointer to IDispatch + Please update existing code which used __AXGETCONTROL() pointers + at C level. + - removed not longer used hb_sink_destructor + ! removed WIN_AXRELEASEOBJECT() - this function breaks reference counters + used by OLE object which needs strict updating to avoid memory leaks + (not freed OLE object) or GPF traps (accessing freed object) + + extended Invoke() method to update OLE parameters passed by reference. + + accept as event handler hash arrays indexed by event numbers and + values with codeblocks or function pointers. Similar functionality + exists in HWGUI when it's compiled with __USEHASHEVENTS macro and + it's much better then passing two arrays. + % optimized some code + + Please test above Active-X modifications. I'm not MS-Windows user so + they have to be verified by real MS-Windows developers. + They should fix problems with memory leaks (OLE objects where never + freed) or GPF traps in C code which tired to strictly manage reference + counters. + To C programmers: if you increase reference counter to activex control + (AddRef()) then you have to release it (Release()) or activex control + will never be freed even after clearing all .prg references. It's + released only when last reference owner calls Release() method so now + valid code can keep references to IDispatch at C level without any + problem but it also means that this code can exploit problems in + existing wrong code. + 2009-08-21 12:48 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * config/win/mingw.mk * config/win/msvc.mk diff --git a/harbour/bin/hb-func.sh b/harbour/bin/hb-func.sh index d51fa5a943..5a6e991aa8 100755 --- a/harbour/bin/hb-func.sh +++ b/harbour/bin/hb-func.sh @@ -519,7 +519,9 @@ fi [ -n "\${HB_GPM_LIB}" ] && SYSTEM_LIBS="-l\${HB_GPM_LIB} \${SYSTEM_LIBS}" -if [ "\${HB_STATIC}" = "no" ]; then +if [ "\${HB_STATIC}" = "no" ] && \ + [ "\${HB_ARCHITECTURE}" != "win" ] && \ + [ "\${HB_ARCHITECTURE}" != "wce" ]; then SYSTEM_LIBS="" fi diff --git a/harbour/contrib/hbwin/axcore.c b/harbour/contrib/hbwin/axcore.c index 6cecfea527..8555c59c20 100644 --- a/harbour/contrib/hbwin/axcore.c +++ b/harbour/contrib/hbwin/axcore.c @@ -67,7 +67,7 @@ static HMODULE s_hLib = NULL; static PHB_AX_GETCTRL s_pAtlAxGetControl = NULL; -static void hb_ax_exit( void* cargo ) +static void hb_oleAxExit( void* cargo ) { HB_SYMBOL_UNUSED( cargo ); @@ -81,8 +81,7 @@ static void hb_ax_exit( void* cargo ) } } - -static int hb_ax_init( void ) +BOOL hb_oleAxInit( void ) { if( s_hLib == NULL ) { @@ -100,7 +99,7 @@ static int hb_ax_init( void ) if( pAtlAxWinInit ) ( *pAtlAxWinInit )(); - hb_vmAtQuit( hb_ax_exit, NULL ); + hb_vmAtQuit( hb_oleAxExit, NULL ); } return 1; } @@ -108,47 +107,72 @@ static int hb_ax_init( void ) HB_FUNC( WIN_AXINIT ) { - hb_retl( hb_ax_init() ); + hb_retl( hb_oleAxInit() ); +} + + +PHB_ITEM hb_oleAxControlNew( PHB_ITEM pItem, HWND hWnd ) +{ + PHB_ITEM pSubst = NULL; + IUnknown* pUnk = NULL; + IDispatch* pDisp = NULL; + HRESULT lOleError; + + if( pItem ) + hb_itemClear( pItem ); + + if( ! hb_oleAxInit() || ! s_pAtlAxGetControl ) + { + hb_oleSetError( S_OK ); + pSubst = hb_errRT_BASE_Subst( EG_UNSUPPORTED, 3012, "ActiveX not initialized", HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + } + else + { + lOleError = ( *s_pAtlAxGetControl )( hWnd, &pUnk ); + + if( lOleError == S_OK ) + { + lOleError = HB_VTBL( pUnk )->QueryInterface( HB_THIS_( pUnk ) HB_ID_REF( IID_IDispatch ), ( void** ) ( void * ) &pDisp ); + HB_VTBL( pUnk )->Release( HB_THIS( pUnk ) ); + } + + hb_oleSetError( lOleError ); + + if( lOleError == S_OK ) + pItem = hb_oleItemPut( pItem, pDisp ); + else + pSubst = hb_errRT_BASE_Subst( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + } + + if( pSubst ) + { + if( pItem ) + { + hb_itemMove( pItem, pSubst ); + hb_itemRelease( pSubst ); + } + else + pItem = pSubst; + } + + return pItem; } HB_FUNC( __AXGETCONTROL ) /* ( hWnd ) --> pDisp */ { - IUnknown* pUnk = NULL; - IDispatch* pDisp = NULL; - HRESULT lOleError; + HWND hWnd = ( HWND ) hb_parptr( 1 ); - if( ! s_pAtlAxGetControl ) - { - hb_oleSetError( S_OK ); + if( ! hWnd ) hb_errRT_BASE_SubstR( EG_UNSUPPORTED, 3012, "ActiveX not initialized", HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } - - lOleError = ( *s_pAtlAxGetControl )( ( HWND ) hb_parptr( 1 ), &pUnk ); - - if( lOleError == S_OK ) - { - lOleError = HB_VTBL( pUnk )->QueryInterface( HB_THIS_( pUnk ) HB_ID_REF( IID_IDispatch ), ( void** ) ( void * ) &pDisp ); - HB_VTBL( pUnk )->Release( HB_THIS( pUnk ) ); - } - - hb_oleSetError( lOleError ); - - if( lOleError == S_OK ) - hb_itemReturnRelease( hb_oleItemPut( NULL, pDisp ) ); else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_oleAxControlNew( hb_stackReturnItem(), hWnd ); } -HB_FUNC( WIN_AXRELEASEOBJECT ) -{ - IDispatch * pDisp = hb_oleParam( 1 ); - HB_VTBL( pDisp )->Release( HB_THIS( pDisp ) ); -} /* ======================== Event handler support ======================== */ + #if !defined( HB_OLE_C_API ) typedef struct { @@ -172,26 +196,6 @@ typedef struct { } ISink; -static HB_GARBAGE_FUNC( hb_sink_destructor ) -{ - ISink * pSink = ( ISink * ) Cargo; - - if( pSink->pItemHandler ) - { - hb_itemRelease( pSink->pItemHandler ); - pSink->pItemHandler = NULL; - } - if( pSink->pConnectionPoint ) - { - HB_VTBL( pSink->pConnectionPoint )->Unadvise( HB_THIS_( pSink->pConnectionPoint ) pSink->dwCookie ); - HB_VTBL( pSink->pConnectionPoint )->Release( HB_THIS( pSink->pConnectionPoint ) ); - pSink->pConnectionPoint = NULL; - pSink->dwCookie = 0; - } - HB_VTBL( ( IDispatch* ) pSink )->Release( HB_THIS( ( IDispatch* ) pSink ) ); -} - - static HRESULT STDMETHODCALLTYPE QueryInterface( IDispatch* lpThis, REFIID riid, void** ppRet ) { if( IsEqualIID( riid, HB_ID_REF( IID_IUnknown ) ) || IsEqualIID( riid, HB_ID_REF( IID_IDispatch ) ) ) @@ -213,12 +217,26 @@ static ULONG STDMETHODCALLTYPE AddRef( IDispatch* lpThis ) static ULONG STDMETHODCALLTYPE Release( IDispatch* lpThis ) { - if( --( ( ISink* ) lpThis )->count == 0 ) + ISink* pSink = ( ISink* ) lpThis; + + if( --pSink->count == 0 ) { - hb_xfree( lpThis ); + if( pSink->pItemHandler ) + { + hb_itemRelease( pSink->pItemHandler ); + pSink->pItemHandler = NULL; + } + if( pSink->pConnectionPoint ) + { + HB_VTBL( pSink->pConnectionPoint )->Unadvise( HB_THIS_( pSink->pConnectionPoint ) pSink->dwCookie ); + HB_VTBL( pSink->pConnectionPoint )->Release( HB_THIS( pSink->pConnectionPoint ) ); + pSink->pConnectionPoint = NULL; + pSink->dwCookie = 0; + } + hb_xfree( pSink ); /* TODO: GlobalAlloc/Free GMEM_FIXED ??? */ return 0; } - return ( ( ISink* ) lpThis )->count; + return pSink->count; } @@ -251,17 +269,22 @@ static HRESULT STDMETHODCALLTYPE GetIDsOfNames( IDispatch* lpThis, REFIID riid, return E_NOTIMPL; } +typedef struct +{ + PHB_ITEM item; + VARIANT* variant; +} +HB_OLE_PARAM_REF; static HRESULT STDMETHODCALLTYPE Invoke( IDispatch* lpThis, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr ) { - PHB_ITEM pItem; - int i, iCount; + int i, iCount, ii, iRefs; + PHB_ITEM pAction; HB_SYMBOL_UNUSED( lcid ); HB_SYMBOL_UNUSED( wFlags ); - HB_SYMBOL_UNUSED( pVarResult ); HB_SYMBOL_UNUSED( pExcepInfo ); HB_SYMBOL_UNUSED( puArgErr ); @@ -271,26 +294,58 @@ static HRESULT STDMETHODCALLTYPE Invoke( IDispatch* lpThis, DISPID dispid, REFII if( ! ( ( ISink* ) lpThis)->pItemHandler ) return S_OK; - hb_vmPushState(); - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( ( ( ISink* ) lpThis )->pItemHandler ); - hb_vmPushLong( dispid ); + pAction = ( ( ISink* ) lpThis )->pItemHandler; - iCount = pParams->cArgs; - for( i = 1; i <= iCount; i++ ) + if( HB_IS_HASH( pAction ) ) { - pItem = hb_itemNew( NULL ); - hb_oleVariantToItem( pItem, &( pParams->rgvarg[ iCount - i ] ) ); - hb_vmPush( pItem ); - hb_itemRelease( pItem ); + PHB_ITEM pKey = hb_itemPutNL( NULL, ( LONG ) dispid ); + pAction = hb_hashGetItemPtr( pAction, pKey, 0 ); + hb_itemRelease( pKey ); } - hb_vmDo( ( USHORT ) iCount + 1 ); + if( pAction && hb_vmRequestReenter() ) + { + HB_OLE_PARAM_REF refArray[ 32 ]; - if( pVarResult ) - hb_oleItemToVariant( pVarResult, hb_stackReturnItem() ); + iCount = pParams->cArgs; + + for( i = iRefs = 0; i < iCount && iRefs < 32; i++ ) + { + if( pParams->rgvarg[ i ].n1.n2.vt & VT_BYREF ) + refArray[ iRefs++ ].item = hb_stackAllocItem(); + } + + hb_vmPushEvalSym(); + hb_vmPush( pAction ); + hb_vmPushLong( ( LONG ) dispid ); + + for( i = 1, ii = 0; i <= iCount; i++ ) + { + if( pParams->rgvarg[ iCount - i ].n1.n2.vt & VT_BYREF ) + { + refArray[ ii ].variant = &pParams->rgvarg[ iCount - i ]; + hb_oleVariantToItem( refArray[ ii ].item, refArray[ ii ].variant ); + hb_vmPushItemRef( refArray[ ii++ ].item ); + } + else + hb_oleVariantToItem( hb_stackAllocItem(), + &pParams->rgvarg[ iCount - i ] ); + } + + hb_vmSend( ( USHORT ) iCount + 1 ); + + if( pVarResult ) + hb_oleItemToVariant( pVarResult, hb_stackReturnItem() ); + + for( i = 0; i < iRefs; i++ ) + hb_oleVariantUpdate( refArray[ i ].variant, refArray[ i ].item ); + + for( i = 0; i < iRefs; i++ ) + hb_stackPop(); + + hb_vmRequestRestore(); + } - hb_vmPopState(); return S_OK; } @@ -312,7 +367,7 @@ HB_FUNC( __AXREGISTERHANDLER ) /* ( pDisp, bHandler ) --> pSink */ if( pDisp ) { - PHB_ITEM pItemBlock = hb_param( 2, HB_IT_BLOCK | HB_IT_SYMBOL ); + PHB_ITEM pItemBlock = hb_param( 2, HB_IT_BLOCK | HB_IT_SYMBOL | HB_IT_HASH ); if( pItemBlock ) { @@ -327,16 +382,18 @@ HB_FUNC( __AXREGISTERHANDLER ) /* ( pDisp, bHandler ) --> pSink */ if( lOleError == S_OK ) { DWORD dwCookie = 0; - ISink * pSink = ( ISink* ) hb_gcAlloc( sizeof( ISink ), hb_sink_destructor ); /* TODO: GlobalAlloc GMEM_FIXED ??? */ - pSink->lpVtbl = ( IDispatchVtbl * ) &ISink_Vtbl; - pSink->count = 2; /* 1 for pCP->Advice() param and 1 for Harbour collectible pointer [Mindaugas] */ - pSink->pItemHandler = hb_itemNew( pItemBlock ); + ISink * pSink; + pSink = ( ISink* ) hb_xgrab( sizeof( ISink ) ); /* TODO: GlobalAlloc/Free GMEM_FIXED ??? */ + + pSink->lpVtbl = ( IDispatchVtbl * ) &ISink_Vtbl; + pSink->count = 1; /* 1 for Harbour collectible pointer [Mindaugas] */ + pSink->pItemHandler = hb_itemNew( pItemBlock ); lOleError = HB_VTBL( pCP )->Advise( HB_THIS_( pCP ) ( IUnknown* ) pSink, &dwCookie ); pSink->pConnectionPoint = pCP; pSink->dwCookie = dwCookie; - hb_retptrGC( pSink ); + hb_oleItemPut( hb_stackReturnItem(), ( IDispatch* ) pDisp ); } HB_VTBL( pCPC )->Release( HB_THIS( pCPC ) ); } diff --git a/harbour/contrib/hbwin/hbwinole.h b/harbour/contrib/hbwin/hbwinole.h index 2ee9690f46..2c864c62ff 100644 --- a/harbour/contrib/hbwin/hbwinole.h +++ b/harbour/contrib/hbwin/hbwinole.h @@ -103,9 +103,15 @@ HB_EXTERN_BEGIN HB_EXPORT void hb_oleInit( void ); HB_EXPORT HRESULT hb_oleGetError( void ); HB_EXPORT void hb_oleSetError( HRESULT lOleError ); -HB_EXPORT void hb_oleItemToVariant( VARIANT* pVariant, PHB_ITEM pItem ); HB_EXPORT void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ); +HB_EXPORT void hb_oleItemToVariant( VARIANT* pVariant, PHB_ITEM pItem ); +HB_EXPORT void hb_oleVariantUpdate( VARIANT* pVariant, PHB_ITEM pItem ); HB_EXPORT IDispatch* hb_oleParam( int iParam ); +HB_EXPORT IDispatch* hb_oleItemGet( PHB_ITEM pItem ); HB_EXPORT PHB_ITEM hb_oleItemPut( PHB_ITEM pItem, IDispatch* pDisp ); +/* activex control */ +HB_EXPORT BOOL hb_oleAxInit( void ); +HB_EXPORT PHB_ITEM hb_oleAxControlNew( PHB_ITEM pItem, HWND hWnd ); + HB_EXTERN_END diff --git a/harbour/contrib/hbwin/olecore.c b/harbour/contrib/hbwin/olecore.c index 956a66f530..0457f81f47 100644 --- a/harbour/contrib/hbwin/olecore.c +++ b/harbour/contrib/hbwin/olecore.c @@ -152,6 +152,23 @@ IDispatch* hb_oleParam( int iParam ) } +IDispatch* hb_oleItemGet( PHB_ITEM pItem ) +{ + return ( IDispatch* ) hb_itemGetPtrGC( pItem, hb_ole_destructor ); +} + + +PHB_ITEM hb_oleItemPut( PHB_ITEM pItem, IDispatch* pDisp ) +{ + IDispatch** ppDisp; + + ppDisp = ( IDispatch** ) hb_gcAlloc( sizeof( IDispatch* ), hb_ole_destructor ); + *ppDisp = pDisp; + + return hb_itemPutPtrGC( pItem, ppDisp ); +} + + static IEnumVARIANT* hb_oleenumParam( int iParam ) { IEnumVARIANT** ppEnum = ( IEnumVARIANT** ) hb_parptrGC( hb_oleenum_destructor, iParam ); @@ -178,15 +195,33 @@ static wchar_t* AnsiToWide( const char* szString ) } -static char* WideToAnsi( const wchar_t* szWide ) -{ - int iLen; - char* szString; - iLen = WideCharToMultiByte( CP_ACP, 0, szWide, -1, NULL, 0, NULL, NULL ); + +static BSTR hb_oleItemToString( PHB_ITEM pItem ) +{ + const char* szString; + BSTR strVal; + int iLen, iStrLen; + + szString = hb_itemGetCPtr( pItem ); + iLen = ( int ) hb_itemGetCLen( pItem ); + iStrLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szString, iLen, NULL, 0 ); + strVal = SysAllocStringLen( NULL, iStrLen ); + MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szString, iLen, strVal, iStrLen + 1 ); + return strVal; +} + + +static void hb_oleStringToItem( BSTR strVal, PHB_ITEM pItem ) +{ + char* szString; + int iLen, iStrLen; + + iStrLen = ( int ) SysStringLen( strVal ); + iLen = WideCharToMultiByte( CP_ACP, 0, strVal, iStrLen, NULL, 0, NULL, NULL ); szString = ( char* ) hb_xgrab( ( iLen + 1 ) * sizeof( char ) ); - WideCharToMultiByte( CP_ACP, 0, szWide, -1, szString, iLen, NULL, NULL ); - return szString; + WideCharToMultiByte( CP_ACP, 0, strVal, iStrLen, szString, iLen + 1, NULL, NULL ); + hb_itemPutCLPtr( pItem, szString, iLen ); } @@ -201,18 +236,15 @@ static void hb_oleItemToVariantRef( VARIANT* pVariant, PHB_ITEM pItem, { case HB_IT_STRING: case HB_IT_MEMO: - { - wchar_t* szString = AnsiToWide( hb_itemGetCPtr( pItem ) ); pVariant->n1.n2.vt = VT_BSTR; - pVariant->n1.n2.n3.bstrVal = SysAllocString( szString ); - hb_xfree( szString ); + pVariant->n1.n2.n3.bstrVal = hb_oleItemToString( pItem ); if( pVarRef ) { pVarRef->n1.n2.vt = VT_BSTR | VT_BYREF; pVarRef->n1.n2.n3.pbstrVal = &pVariant->n1.n2.n3.bstrVal; } break; - } + case HB_IT_LOGICAL: pVariant->n1.n2.vt = VT_BOOL; pVariant->n1.n2.n3.boolVal = hb_itemGetL( pItem ) ? VARIANT_TRUE : VARIANT_FALSE; @@ -383,22 +415,13 @@ static void hb_oleItemToVariantRef( VARIANT* pVariant, PHB_ITEM pItem, #endif } + void hb_oleItemToVariant( VARIANT* pVariant, PHB_ITEM pItem ) { hb_oleItemToVariantRef( pVariant, pItem, NULL ); } -PHB_ITEM hb_oleItemPut( PHB_ITEM pItem, IDispatch* pDisp ) -{ - IDispatch** ppDisp; - - ppDisp = ( IDispatch** ) hb_gcAlloc( sizeof( IDispatch* ), hb_ole_destructor ); - *ppDisp = pDisp; - - return hb_itemPutPtrGC( pItem, ppDisp ); -} - void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ) { if( pVariant->n1.n2.vt == ( VT_VARIANT | VT_BYREF ) ) @@ -451,18 +474,12 @@ void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ) } case VT_BSTR: - { - char* szString = WideToAnsi( pVariant->n1.n2.n3.bstrVal ); - hb_itemPutCPtr( pItem, szString ); + hb_oleStringToItem( pVariant->n1.n2.n3.bstrVal, pItem ); break; - } case VT_BSTR | VT_BYREF: - { - char* szString = WideToAnsi( *pVariant->n1.n2.n3.pbstrVal ); - hb_itemPutCPtr( pItem, szString ); + hb_oleStringToItem( *pVariant->n1.n2.n3.pbstrVal, pItem ); break; - } case VT_BOOL: hb_itemPutL( pItem, pVariant->n1.n2.n3.boolVal ? TRUE : FALSE ); @@ -473,19 +490,19 @@ void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ) break; case VT_I1: - hb_itemPutNI( pItem, ( int ) pVariant->n1.n2.n3.cVal ); + hb_itemPutNI( pItem, ( signed char ) pVariant->n1.n2.n3.cVal ); break; case VT_I1 | VT_BYREF: - hb_itemPutNI( pItem, ( int ) *pVariant->n1.n2.n3.pcVal ); + hb_itemPutNI( pItem, ( signed char ) *pVariant->n1.n2.n3.pcVal ); break; case VT_I2: - hb_itemPutNI( pItem, ( int ) pVariant->n1.n2.n3.iVal ); + hb_itemPutNI( pItem, ( short ) pVariant->n1.n2.n3.iVal ); break; case VT_I2 | VT_BYREF: - hb_itemPutNI( pItem, ( int ) *pVariant->n1.n2.n3.piVal ); + hb_itemPutNI( pItem, ( short ) *pVariant->n1.n2.n3.piVal ); break; case VT_I4: @@ -519,27 +536,27 @@ void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ) break; case VT_UI1: - hb_itemPutNI( pItem, ( int ) pVariant->n1.n2.n3.bVal ); + hb_itemPutNI( pItem, ( unsigned char ) pVariant->n1.n2.n3.bVal ); break; case VT_UI1 | VT_BYREF: - hb_itemPutNI( pItem, ( int ) *pVariant->n1.n2.n3.pbVal ); + hb_itemPutNI( pItem, ( unsigned char ) *pVariant->n1.n2.n3.pbVal ); break; case VT_UI2: - hb_itemPutNI( pItem, ( int ) pVariant->n1.n2.n3.uiVal ); + hb_itemPutNI( pItem, ( unsigned short ) pVariant->n1.n2.n3.uiVal ); break; case VT_UI2 | VT_BYREF: - hb_itemPutNI( pItem, ( int ) *pVariant->n1.n2.n3.puiVal ); + hb_itemPutNI( pItem, ( unsigned short ) *pVariant->n1.n2.n3.puiVal ); break; case VT_UI4: - hb_itemPutNInt( pItem, ( HB_LONG ) pVariant->n1.n2.n3.ulVal ); + hb_itemPutNInt( pItem, pVariant->n1.n2.n3.ulVal ); break; case VT_UI4 | VT_BYREF: - hb_itemPutNInt( pItem, ( HB_LONG ) *pVariant->n1.n2.n3.pulVal ); + hb_itemPutNInt( pItem, *pVariant->n1.n2.n3.pulVal ); break; case VT_UI8: @@ -575,11 +592,11 @@ void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ) break; case VT_UINT: - hb_itemPutNInt( pItem, ( HB_LONG ) pVariant->n1.n2.n3.uintVal ); + hb_itemPutNInt( pItem, pVariant->n1.n2.n3.uintVal ); break; case VT_UINT | VT_BYREF: - hb_itemPutNInt( pItem, ( HB_LONG ) *pVariant->n1.n2.n3.puintVal ); + hb_itemPutNInt( pItem, *pVariant->n1.n2.n3.puintVal ); break; case VT_R4: @@ -682,6 +699,119 @@ void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ) } +void hb_oleVariantUpdate( VARIANT* pVariant, PHB_ITEM pItem ) +{ + switch( pVariant->n1.n2.vt ) + { + case VT_DISPATCH | VT_BYREF: + { + IDispatch* pDisp = hb_oleItemGet( pItem ); + + if( pDisp ) + { + IDispatch* pdispVal = *pVariant->n1.n2.n3.ppdispVal; + HB_VTBL( pDisp )->AddRef( HB_THIS( pDisp ) ); + *pVariant->n1.n2.n3.ppdispVal = pDisp; + if( pdispVal ) + HB_VTBL( pdispVal )->Release( HB_THIS( pdispVal ) ); + } + break; + } + + case VT_BSTR | VT_BYREF: + SysFreeString( *pVariant->n1.n2.n3.pbstrVal ); + *pVariant->n1.n2.n3.pbstrVal = hb_oleItemToString( pItem ); + break; + + case VT_BOOL | VT_BYREF: + *pVariant->n1.n2.n3.pboolVal = hb_itemGetL( pItem ); + break; + + case VT_I1 | VT_BYREF: + *pVariant->n1.n2.n3.pcVal = ( signed char ) hb_itemGetNI( pItem ); + break; + + case VT_I2 | VT_BYREF: + *pVariant->n1.n2.n3.piVal = ( short ) hb_itemGetNI( pItem ); + break; + + case VT_I4 | VT_BYREF: + *pVariant->n1.n2.n3.plVal = hb_itemGetNL( pItem ); + break; + + case VT_I8 | VT_BYREF: +#if HB_LONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) + *pVariant->n1.n2.n3.plVal = ( long ) hb_itemGetNInt( pItem ); +#elif defined( HB_OLE_NO_LLREF ) + /* workaround for wrong OLE variant structure definition */ + * ( LONGLONG * ) pVariant->n1.n2.n3.pdblVal = ( LONGLONG ) hb_itemGetNInt( pItem ); +#else + *pVariant->n1.n2.n3.pllVal = ( LONGLONG ) hb_itemGetNInt( pItem ); +#endif + break; + + case VT_UI1 | VT_BYREF: + *pVariant->n1.n2.n3.pbVal = ( unsigned char ) hb_itemGetNI( pItem ); + break; + + case VT_UI2 | VT_BYREF: + *pVariant->n1.n2.n3.puiVal = ( unsigned short ) hb_itemGetNI( pItem ); + break; + + case VT_UI4 | VT_BYREF: + *pVariant->n1.n2.n3.pulVal = ( unsigned long ) hb_itemGetNL( pItem ); + break; + + case VT_UI8 | VT_BYREF: +#if HB_LONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF ) + *pVariant->n1.n2.n3.pulVal = ( unsigned long ) hb_itemGetNInt( pItem ); +#elif defined( HB_OLE_NO_LLREF ) + /* workaround for wrong OLE variant structure definition */ + * ( ULONGLONG * ) pVariant->n1.n2.n3.pdblVal = ( ULONGLONG ) hb_itemGetNInt( pItem ); +#else + *pVariant->n1.n2.n3.pullVal = ( ULONGLONG ) hb_itemGetNInt( pItem ); +#endif + break; + + case VT_INT | VT_BYREF: + *pVariant->n1.n2.n3.pintVal = hb_itemGetNI( pItem ); + break; + + case VT_UINT | VT_BYREF: + *pVariant->n1.n2.n3.puintVal = ( unsigned int ) hb_itemGetNI( pItem ); + break; + + case VT_R4 | VT_BYREF: + *pVariant->n1.n2.n3.pfltVal = ( float ) hb_itemGetND( pItem ); + break; + + case VT_R8 | VT_BYREF: + *pVariant->n1.n2.n3.pdblVal = hb_itemGetND( pItem ); + break; + + case VT_CY | VT_BYREF: + VarCyFromR8( hb_itemGetND( pItem ), pVariant->n1.n2.n3.pcyVal ); + break; + + case VT_DECIMAL | VT_BYREF: + VarDecFromR8( hb_itemGetND( pItem ), pVariant->n1.n2.n3.pdecVal ); + break; + + case VT_DATE | VT_BYREF: + *pVariant->n1.n2.n3.pdblVal = hb_itemGetTD( pItem ) - HB_OLE_DATE_BASE; + break; + + case VT_BYREF | VT_VARIANT: + hb_oleItemToVariantRef( pVariant->n1.n2.n3.pvarVal, pItem, NULL ); + break; + + case VT_VARIANT | VT_ARRAY | VT_BYREF: + /* TODO: */ + break; + } +} + + /* IDispatch parameters, return value handling */ static void GetParams( DISPPARAMS * dispparam )