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.
This commit is contained in:
Przemyslaw Czerpak
2009-08-21 11:35:11 +00:00
parent 4cd1edfa66
commit 4077cbb993
5 changed files with 375 additions and 122 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 ) );
}

View File

@@ -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

View File

@@ -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 )