Files
harbour-core/harbour/examples/hboleold/win_ole.c
Viktor Szakats e094b59e07 2009-06-14 00:45 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* examples/hbdoc/hbdfrdln.c
  * examples/hbgf/hbgfos2/os2pm.c
  * examples/hbgf/hbgfwin/winapi.c
  * examples/hbmake/hbmakec.c
  * examples/hboleold/win_ole.c
  * examples/hbwhat/whtbmp.c
  * examples/hbwhat/whtcdlg.c
  * examples/hbwhat/whtclpb.c
  * examples/hbwhat/whtcomm.c
  * examples/hbwhat/whtdate.c
  * examples/hbwhat/whtdc.c
  * examples/hbwhat/whtdir.c
  * examples/hbwhat/whtdlg.c
  * examples/hbwhat/whtdraw.c
  * examples/hbwhat/whtfont.c
  * examples/hbwhat/whticon.c
  * examples/hbwhat/whtilst.c
  * examples/hbwhat/whtinet.c
  * examples/hbwhat/whtini.c
  * examples/hbwhat/whtkbrd.c
  * examples/hbwhat/whtmenu.c
  * examples/hbwhat/whtmeta.c
  * examples/hbwhat/whtmisc.c
  * examples/hbwhat/whtmous.c
  * examples/hbwhat/whtmsg.c
  * examples/hbwhat/whtprn.c
  * examples/hbwhat/whtrect.c
  * examples/hbwhat/whtrgn.c
  * examples/hbwhat/whtscrlb.c
  * examples/hbwhat/whtseria.c
  * examples/hbwhat/whtshell.c
  * examples/hbwhat/whtsock.c
  * examples/hbwhat/whtsys.c
  * examples/hbwhat/whttab.c
  * examples/hbwhat/whttbar.c
  * examples/hbwhat/whttext.c
  * examples/hbwhat/whtwnd.c
  * examples/hbwhat/wincorec.c
  * examples/uhttpd/socket.c
    * IS*() -> HB_IS*() macro rename.
      (pass 2)
2009-06-13 22:47:30 +00:00

1993 lines
60 KiB
C

/*
* $Id$
*/
/*
* Copyright 2002 Jose F. Gimenez (JFG) - <jfgimenez@wanadoo.es>
* Ron Pinkas - <ron@ronpinkas.com>
*
* www - http://www.xharbour.org
*
* 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 software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the xHarbour Project gives permission for
* additional uses of the text contained in its release of xHarbour.
*
* The exception is that, if you link the xHarbour 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 xHarbour 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 xHarbour
* Project under the name xHarbour. If you copy code from other
* xHarbour Project or Free Software Foundation releases into a copy of
* xHarbour, 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 xHarbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#define HB_OS_WIN_USED
#ifndef CINTERFACE
#define CINTERFACE 1
#endif
#define NONAMELESSUNION
#include <string.h>
#include "hbvmint.h" /* TOFIX: clean the code to not access any internal HVM structures */
#include "hbapi.h"
#include "hbstack.h"
#include "hbapierr.h"
#include "hbapiitm.h"
#include "hbapicls.h"
#include "hbvm.h"
#include "hbdate.h"
#include "hboo.ch"
#if ! defined( HB_OS_WIN_CE )
#include <windows.h>
#include <ole2.h>
#include <oleauto.h>
#include <olectl.h>
#ifndef __MINGW32__
/* Missing in Mingw V 2. */
/* #include <oledb.h> */
#endif
#include <shlobj.h>
#ifdef __MINGW32__
/* Missing in oleauto.h */
WINOLEAUTAPI VarR8FromDec(DECIMAL *pdecIn, DOUBLE *pdblOut);
#endif
#if ( defined(__DMC__) || defined(__MINGW32__) || ( defined(__WATCOMC__) && !defined(__FORCE_LONG_LONG__) ) )
#define HB_LONG_LONG_OFF
#endif
#if defined( __cplusplus ) && ( defined( __BORLANDC__ ) || defined( _MSC_VER ) || ( defined(__WATCOMC__) && ( __WATCOMC__ >= 1280 ) ) )
# define HB_ID_REF( type, id ) id
#else
# define HB_ID_REF( type, id ) ( ( type ) &id )
#endif
static void RetValue( void );
static HRESULT s_nOleError;
static PHB_ITEM s_pOleAuto = NULL;
static PHB_DYNS s_pSym_TOleAuto = NULL;
static PHB_DYNS s_pSym_hObj = NULL;
static PHB_DYNS s_pSym_New = NULL;
static PHB_DYNS s_pSym_cClassName = NULL;
static PHB_DYNS s_pSym_VTWrapper = NULL;
static PHB_DYNS s_pSym_VTArrayWrapper = NULL;
static PHB_DYNS s_pSym_vt = NULL;
static PHB_DYNS s_pSym_Value = NULL;
static DISPPARAMS s_EmptyDispParams;
static VARIANTARG s_RetVal;
static VARIANTARG s_OleVal;
static BOOL s_bInit = FALSE;
/* ----------------------------------------------------------------------- */
#define EG_OLEEXCEPTION 1001
#define HB_STRING_ALLOC( p, l ) hb_itemReSizeString( p, l )
static void hb_itemPushForward( PHB_ITEM pItem )
{
hb_itemMove( hb_stackAllocItem(), pItem );
}
static void hb_vmRequestReset( void )
{
hb_stackSetActionRequest( 0 ); /* TOFIX */
}
/* ----------------------------------------------------------------------- */
static EXCEPINFO s_excep;
static DISPID s_lPropPut = DISPID_PROPERTYPUT;
static UINT s_uArgErr;
HRESULT hb_oleVariantToItem( PHB_ITEM pItem, VARIANT *pVariant );
static PHB_ITEM SafeArrayToArray( SAFEARRAY * parray, UINT iDim, long * rgIndices, VARTYPE vt );
/* ----------------------------------------------------------------------- */
BSTR hb_oleAnsiToSysString( const char * cString )
{
int nConvertedLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, cString, -1, NULL, 0 );
if( nConvertedLen )
{
BSTR bstrString = SysAllocStringLen( NULL, nConvertedLen - 1 );
if( MultiByteToWideChar( CP_ACP, 0, cString, -1, bstrString, nConvertedLen ) )
return bstrString;
else
SysFreeString( bstrString );
}
return NULL;
}
/* ----------------------------------------------------------------------- */
LPWSTR hb_oleAnsiToWide( LPSTR cString )
{
int nConvertedLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, cString, -1, NULL, 0 );
if( nConvertedLen )
{
LPWSTR wString = ( LPWSTR ) hb_xgrab( nConvertedLen * 2 + 1 );
if( MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, cString, -1, wString, nConvertedLen ) )
return wString;
else
hb_xfree( wString );
}
return NULL;
}
/* This code is executed only once when HVM clears static variables
* inside hb_vmQuit() - so it's executed after all EXIT functions
* and allow to use OLE in object destructors
*/
static HB_GARBAGE_FUNC( hb_oleRelease )
{
HB_SYMBOL_UNUSED( Cargo );
if( s_bInit )
{
OleUninitialize();
s_bInit = FALSE;
if( s_pOleAuto )
{
hb_itemRelease( s_pOleAuto );
s_pOleAuto = NULL;
}
}
}
/* ----------------------------------------------------------------------- */
HB_FUNC( __HB_OLE_INIT )
{
if( s_pSym_TOleAuto == NULL )
{
s_pSym_TOleAuto = hb_dynsymFind( "TOLEAUTO" );
s_pSym_New = hb_dynsymFind( "NEW" );
s_pSym_hObj = hb_dynsymFind( "HOBJ" );
s_pSym_cClassName = hb_dynsymFind( "CCLASSNAME" );
s_pSym_VTWrapper = hb_dynsymFind( "VTWRAPPER" );
s_pSym_VTArrayWrapper = hb_dynsymFind( "VTARRAYWRAPPER" );
s_pSym_vt = hb_dynsymGetCase( "VT" );
s_pSym_Value = hb_dynsymFind( "VALUE" );
s_EmptyDispParams.rgvarg = NULL;
s_EmptyDispParams.cArgs = 0;
s_EmptyDispParams.rgdispidNamedArgs = 0;
s_EmptyDispParams.cNamedArgs = 0;
if( ! s_bInit )
{
OleInitialize( NULL );
hb_retptrGC( hb_gcAlloc( 1, hb_oleRelease ) );
s_bInit = TRUE;
}
VariantInit( &s_RetVal );
VariantInit( &s_OleVal );
}
}
/* ----------------------------------------------------------------------- */
HB_FUNC( ANSITOWIDE ) /* ( cAnsiStr ) -> cWideStr */
{
char *cString = hb_parc( 1 );
if( cString )
{
BSTR wString = hb_oleAnsiToWide( cString );
if( wString )
hb_retclen_buffer( ( char * ) wString, SysStringLen( wString ) );
}
}
/* ----------------------------------------------------------------------- */
LPSTR hb_oleWideToAnsi( BSTR wString )
{
int nConvertedLen = WideCharToMultiByte( CP_ACP, 0, wString, -1, NULL, 0, NULL, NULL );
if( nConvertedLen )
{
char * cString = ( char * ) hb_xgrab( nConvertedLen + 1 );
if( WideCharToMultiByte( CP_ACP, 0, wString, -1, cString, nConvertedLen + 1, NULL, NULL ) )
return cString;
else
hb_xfree( cString );
}
#if 0
wprintf( L"\nWide: '%s'\n", wString );
printf( "\nAnsi: '%s'\n", cString );
#endif
return NULL;
}
/* ----------------------------------------------------------------------- */
HB_FUNC( WIDETOANSI ) /* ( cWideStr, nLen ) -> cAnsiStr */
{
BSTR wString = ( BSTR ) hb_parc( 1 );
if( wString )
{
char *cString = hb_oleWideToAnsi( wString );
if( cString )
hb_retclen_buffer( cString, strlen( cString ) );
}
}
/* ----------------------------------------------------------------------- */
void hb_oleItemToVariant( VARIANT *pVariant, PHB_ITEM pItem )
{
BOOL bByRef;
VARIANT mVariant;
VARTYPE vt;
SAFEARRAYBOUND rgsabound;
void *pSource;/* = NULL;*/
unsigned long i;
char *sString;
if( HB_IS_BYREF( pItem ) )
{
pItem = hb_itemUnRef( pItem );
bByRef = TRUE;
}
else
bByRef = FALSE;
VariantClear( pVariant );
switch( hb_itemType( pItem ) )
{
case HB_IT_NIL:
/*pVariant->n1.n2.vt = VT_EMPTY;*/
break;
case HB_IT_STRING:
case HB_IT_MEMO:
{
ULONG ulLen = hb_itemGetCLen( pItem );
sString = hb_itemGetCPtr( pItem );
/* Check for hidden signature of SafeArrayToArray(). */
if( ( int ) ( pItem->item.asString.allocated - ulLen ) >= 5 && /* TOFIX */
sString[ ulLen ] == 0x7A && sString[ ulLen + 1 ] == 0x7B && sString[ ulLen + 2 ] == 0x7C && sString[ ulLen + 3 ] == 0x7D )
{
vt = ( VARTYPE ) sString[ ulLen + 4 ];
goto ItemToVariant_StringArray;
}
if( bByRef )
{
hb_itemPutCLConst( pItem, ( char * ) hb_oleAnsiToSysString( sString ), ulLen * 2 + 1 );
pVariant->n1.n2.vt = VT_BYREF | VT_BSTR;
pVariant->n1.n2.n3.pbstrVal = ( BSTR * ) &( pItem->item.asString.value ); /* TOFIX */
/*wprintf( L"*** BYREF >%s<\n", *pVariant->n1.n2.n3.bstrVal );*/
}
else
{
pVariant->n1.n2.vt = VT_BSTR;
pVariant->n1.n2.n3.bstrVal = hb_oleAnsiToSysString( sString );
/*wprintf( L"*** >%s<\n", pVariant->n1.n2.n3.bstrVal );*/
}
break;
}
case HB_IT_LOGICAL:
if( bByRef )
{
pVariant->n1.n2.vt = VT_BYREF | VT_BOOL;
pVariant->n1.n2.n3.pboolVal = ( short * ) &( pItem->item.asLogical.value ) ; /* TOFIX */
*pVariant->n1.n2.n3.pboolVal = hb_itemGetL( pItem ) ? VARIANT_TRUE : VARIANT_FALSE;
/*pItem->type = HB_IT_LONG;*/
}
else
{
pVariant->n1.n2.vt = VT_BOOL;
pVariant->n1.n2.n3.boolVal = hb_itemGetL( pItem ) ? VARIANT_TRUE : VARIANT_FALSE;
}
break;
case HB_IT_INTEGER:
#if HB_INT_MAX == INT16_MAX
if( bByRef )
{
pVariant->n1.n2.vt = VT_BYREF | VT_I2;
pVariant->n1.n2.n3.piVal = &( pItem->item.asInteger.value ) ; /* TOFIX */
}
else
{
pVariant->n1.n2.vt = VT_I2;
pVariant->n1.n2.n3.iVal = hb_itemGetNI( pItem );
}
break;
#else
if( bByRef )
{
pVariant->n1.n2.vt = VT_BYREF | VT_I4;
pVariant->n1.n2.n3.plVal = ( long * ) &( pItem->item.asInteger.value ) ; /* TOFIX */
}
else
{
pVariant->n1.n2.vt = VT_I4;
pVariant->n1.n2.n3.lVal = hb_itemGetNL( pItem );
}
break;
#endif
case HB_IT_LONG:
#if HB_LONG_MAX == INT32_MAX || defined( HB_LONG_LONG_OFF )
if( bByRef )
{
pVariant->n1.n2.vt = VT_BYREF | VT_I4;
pVariant->n1.n2.n3.plVal = ( long * ) &( pItem->item.asLong.value ) ; /* TOFIX */
}
else
{
pVariant->n1.n2.vt = VT_I4;
pVariant->n1.n2.n3.lVal = hb_itemGetNL( pItem );
}
#else
if( bByRef )
{
pVariant->n1.n2.vt = VT_BYREF | VT_I8;
pVariant->n1.n2.n3.pllVal = &( pItem->item.asLong.value ) ; /* TOFIX */
}
else
{
pVariant->n1.n2.vt = VT_I8;
pVariant->n1.n2.n3.llVal = hb_itemGetNLL( pItem );
}
#endif
break;
case HB_IT_DOUBLE:
if( bByRef )
{
pVariant->n1.n2.vt = VT_BYREF | VT_R8;
pVariant->n1.n2.n3.pdblVal = &( pItem->item.asDouble.value ) ; /* TOFIX */
pItem->type = HB_IT_DOUBLE;
}
else
{
pVariant->n1.n2.vt = VT_R8;
pVariant->n1.n2.n3.dblVal = hb_itemGetND( pItem );
}
break;
case HB_IT_DATE:
{
long lDate = hb_itemGetDL( pItem );
if( lDate == 0 )
pVariant->n1.n2.vt = VT_NULL;
else if( bByRef )
{
hb_itemPutND( pItem, (double) ( lDate - 2415019 ) );
pVariant->n1.n2.vt = VT_BYREF | VT_DATE;
pVariant->n1.n2.n3.pdblVal = &( pItem->item.asDouble.value );
}
else
{
pVariant->n1.n2.vt = VT_DATE;
pVariant->n1.n2.n3.dblVal = (double) ( lDate - 2415019 );
}
}
break;
case HB_IT_TIMESTAMP:
{
double dDateTime = hb_itemGetTD( pItem );
if( dDateTime == 0 )
pVariant->n1.n2.vt = VT_NULL;
else if( bByRef )
{
hb_itemPutND( pItem, ( dDateTime - (double) 2415019 ) );
pVariant->n1.n2.vt = VT_BYREF | VT_DATE;
pVariant->n1.n2.n3.pdblVal = &( pItem->item.asDouble.value );
}
else
{
pVariant->n1.n2.vt = VT_DATE;
pVariant->n1.n2.n3.dblVal = ( dDateTime - (double) 2415019 );
}
}
break;
case HB_IT_POINTER:
pVariant->n1.n2.vt = VT_PTR;
pVariant->n1.n2.n3.byref = hb_itemGetPtr( pItem );
break;
case HB_IT_ARRAY:
{
if( HB_IS_OBJECT( pItem ) )
{
if( hb_clsIsParent( hb_objGetClass( pItem ), "TOLEAUTO" ) )
{
IDispatch *pDisp;/* = NULL;*/
hb_vmPushDynSym( s_pSym_hObj );
hb_vmPush( pItem );
hb_vmSend( 0 );
pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( -1 );
pDisp->lpVtbl->AddRef( pDisp );
/*HB_TRACE(HB_TR_INFO, ("Dispatch: in: %s(%i)%ld\n", pDisp, __FILE__, __LINE__));*/
if( bByRef )
{
pVariant->n1.n2.vt = ( VT_DISPATCH | VT_BYREF );
/* Hack!!! Using high 4 bytes of the union (llVal) */
*( ( IDispatch ** ) ( &pVariant->n1.n2.n3.lVal ) + 1 ) = pDisp;
pVariant->n1.n2.n3.ppdispVal = ( IDispatch ** ) ( &pVariant->n1.n2.n3.lVal ) + 1;
}
else
{
pVariant->n1.n2.vt = VT_DISPATCH;
pVariant->n1.n2.n3.pdispVal = pDisp;
}
}
/* MUST be before "VTWRAPPER" */
else if( hb_clsIsParent( hb_objGetClass( pItem ), "VTARRAYWRAPPER" ) )
{
/* vt := oVTArray:vt */
hb_vmPushDynSym( s_pSym_vt );
hb_vmPush( pItem );
hb_vmSend( 0 );
vt = ( VARTYPE ) hb_parnl( -1 );
/* aArray := oVTArray:Value */
hb_vmPushDynSym( s_pSym_Value );
hb_vmPush( pItem );
hb_vmSend( 0 );
/* Intentionally not using hb_itemCopy() or hb_itemForwardValue() */
pItem = hb_stackReturnItem();
if( ( vt == VT_I1 || vt == VT_UI1 ) && HB_IS_STRING( pItem ) )
{
SAFEARRAY *parray;
sString = hb_itemGetCPtr( pItem );
ItemToVariant_StringArray:
rgsabound.cElements = hb_itemGetCLen( pItem );
rgsabound.lLbound = 0;
parray = SafeArrayCreate( vt, 1, &rgsabound );
if( bByRef )
{
pVariant->n1.n2.vt = ( VT_ARRAY | VT_BYREF | vt );
/* Hack!!! Using high 4 bytes of the union (llVal) */
*( ( SAFEARRAY ** ) ( &pVariant->n1.n2.n3.lVal ) + 1 ) = parray;
pVariant->n1.n2.n3.pparray = ( SAFEARRAY ** ) ( &pVariant->n1.n2.n3.lVal ) + 1;
}
else
{
pVariant->n1.n2.vt = ( VT_ARRAY | vt );
pVariant->n1.n2.n3.parray = parray;
}
for( i = 0; i < rgsabound.cElements; i++ )
SafeArrayPutElement( parray, ( LONG * ) &i, &( sString[ i ] ) );
break;
}
VariantInit( &mVariant );
pSource = &mVariant.n1.n2.n3.cVal;
goto ItemToVariant_ProcessArray;
}
else if( hb_clsIsParent( hb_objGetClass( pItem ), "VTWRAPPER" ) )
{
/* vt := oVT:vt */
hb_vmPushDynSym( s_pSym_vt );
hb_vmPush( pItem );
hb_vmSend( 0 );
pVariant->n1.n2.vt = ( VARTYPE ) hb_parnl( -1 );
/* value := oVT:value */
hb_vmPushDynSym( s_pSym_Value );
hb_vmPush( pItem );
hb_vmSend( 0 );
switch( pVariant->n1.n2.vt )
{
case VT_UNKNOWN:
pVariant->n1.n2.n3.punkVal = ( IUnknown * ) hb_parptr( -1 );
break;
case ( VT_UNKNOWN | VT_BYREF ):
/* Hack!!! Using high 4 bytes of the union (llVal) */
*( ( IUnknown ** ) ( &pVariant->n1.n2.n3.lVal ) + 1 ) = ( IUnknown * ) hb_parptr( -1 );
pVariant->n1.n2.n3.ppunkVal = ( IUnknown ** ) ( &pVariant->n1.n2.n3.lVal ) + 1;
break;
default:
HB_TRACE(HB_TR_INFO, ("Unexpected VT type %p in: %s(%i)!\n", ( void * ) ( HB_PTRUINT ) pVariant->n1.n2.vt, __FILE__, __LINE__));
}
break;
}
else
{
HB_TRACE(HB_TR_INFO, ("Class: '%s' not suported!\n", hb_objGetClsName( pItem )));
}
}
else
{
unsigned long i;
SAFEARRAY *parray;
vt = VT_VARIANT;
VariantInit( &mVariant );
pSource = &mVariant;
ItemToVariant_ProcessArray:
rgsabound.cElements = hb_arrayLen( pItem );
rgsabound.lLbound = 0;
/*HB_TRACE(HB_TR_INFO, ("ItemToVariant() Array len: %i type: %i ByRef: %i in: %s(%i) \n", rgsabound.cElements, vt, bByRef, __FILE__, __LINE__));*/
parray = SafeArrayCreate( vt, 1, &rgsabound );
if( bByRef )
{
pVariant->n1.n2.vt = ( VT_ARRAY | VT_BYREF | vt );
/* Hack!!! Using high 4 bytes of the union (llVal) */
*( ( SAFEARRAY ** ) ( &pVariant->n1.n2.n3.lVal ) + 1 ) = parray;
pVariant->n1.n2.n3.pparray = ( SAFEARRAY ** ) ( &pVariant->n1.n2.n3.lVal ) + 1;
}
else
{
pVariant->n1.n2.vt = ( VT_ARRAY | vt );
pVariant->n1.n2.n3.parray = parray;
}
for( i = 0; i < rgsabound.cElements; i++ )
{
hb_oleItemToVariant( &mVariant, hb_arrayGetItemPtr( pItem, i + 1 ) );
SafeArrayPutElement( parray, ( LONG * ) &i, pSource );
VariantClear( &mVariant );
}
}
}
break;
default:
{
/*HB_TRACE(HB_TR_INFO, ("Unexpected type %p in: %s(%i)!\n", hb_itemType( pItem ), __FILE__, __LINE__));*/
}
}
}
/* ----------------------------------------------------------------------- */
static PHB_ITEM * GetParams( DISPPARAMS *pDispParams, int nOffset )
{
VARIANTARG * pArgs = NULL;
int n, nArgs, nArg;
/*BOOL bByRef;*/
PHB_ITEM *aPrgParams = NULL;
nArgs = hb_pcount() - nOffset;
if( nArgs > 0 )
{
pArgs = ( VARIANTARG * ) hb_xgrab( sizeof( VARIANTARG ) * nArgs );
aPrgParams = ( PHB_ITEM * ) hb_xgrab( sizeof( PHB_ITEM ) * nArgs );
/*printf( "Args: %i\n", nArgs );*/
for( n = 0; n < nArgs; n++ )
{
/* Parameters are processed in reversed order. */
nArg = nArgs - n;
VariantInit( &( pArgs[ n ] ) );
aPrgParams[ n ] = hb_stackItemFromBase( nArg + nOffset );
/*HB_TRACE(HB_TR_INFO, ("N: %i Arg: %i Type: %i %i ByRef: %i\n", n, nArg, hb_itemType( pParam ), hb_itemType( aPrgParams[ n ] ), bByRef));*/
hb_oleItemToVariant( &( pArgs[ n ] ), aPrgParams[ n ] );
}
}
pDispParams->rgvarg = pArgs;
pDispParams->cArgs = nArgs;
pDispParams->rgdispidNamedArgs = 0;
pDispParams->cNamedArgs = 0;
return aPrgParams;
}
/* ----------------------------------------------------------------------- */
static void FreeParams( DISPPARAMS *pDispParams, PHB_ITEM *aPrgParams )
{
if( pDispParams->cArgs > 0 )
{
IDispatch *pDisp = NULL;
int n; /*, nParam;*/
char *sString;
VARIANT *pVariant;
PHB_ITEM pItem;
BOOL bByRef;
for( n = 0; n < ( int ) pDispParams->cArgs; n++ )
{
pVariant = &( pDispParams->rgvarg[ n ] );
pItem = aPrgParams[ n ];
if( HB_IS_BYREF( pItem ) )
{
bByRef = TRUE;
pItem = hb_itemUnRef( pItem );
}
else
bByRef = FALSE;
/*nParam = pDispParams->cArgs - n;*/
/*HB_TRACE(HB_TR_INFO, ("*** N: %i, Param: %i Type: %i\n", n, nParam, pVariant->n1.n2.vt));*/
if( bByRef )
{
switch( pVariant->n1.n2.vt )
{
case VT_BYREF | VT_BSTR:
SysFreeString( *pVariant->n1.n2.n3.pbstrVal );
sString = hb_oleWideToAnsi( *( pVariant->n1.n2.n3.pbstrVal ) );
hb_itemPutCPtr2( pItem, sString );
break;
case VT_BSTR:
sString = hb_oleWideToAnsi( pVariant->n1.n2.n3.bstrVal );
hb_itemPutCPtr2( pItem, sString );
break;
case VT_BYREF | VT_BOOL:
/*( pItem )->type = HB_IT_LOGICAL;*/
hb_itemPutL( pItem, *pVariant->n1.n2.n3.pboolVal == VARIANT_FALSE ? FALSE : TRUE );
break;
case VT_BOOL:
hb_itemPutL( pItem, pVariant->n1.n2.n3.boolVal == VARIANT_FALSE ? FALSE : TRUE );
break;
case ( VT_BYREF | VT_DISPATCH ):
if( *pVariant->n1.n2.n3.ppdispVal == NULL )
{
hb_itemClear( pItem );
break;
}
else
{
pDisp = *pVariant->n1.n2.n3.ppdispVal;
}
/* Intentionally fall through. */
case VT_DISPATCH:
if( pVariant->n1.n2.vt == VT_DISPATCH )
{
if( pVariant->n1.n2.n3.pdispVal == NULL )
{
hb_itemClear( pItem );
break;
}
else
pDisp = pVariant->n1.n2.n3.pdispVal;
}
if( s_pOleAuto == NULL )
s_pOleAuto = hb_itemNew( NULL );
else
hb_itemClear( s_pOleAuto );
if( s_pSym_TOleAuto )
{
hb_vmPushDynSym( s_pSym_TOleAuto );
hb_vmPushNil();
hb_vmDo( 0 );
hb_itemForwardValue( s_pOleAuto, hb_stackReturnItem() );
}
if( s_pSym_New && hb_itemType( s_pOleAuto ) )
{
/* Implemented in :New() */
/*pDisp->lpVtbl->AddRef( pDisp );*/
/*TOleAuto():New( nDispatch )*/
hb_vmPushDynSym( s_pSym_New );
hb_itemPushForward( s_pOleAuto );
hb_vmPushNumInt( ( HB_PTRUINT ) pDisp );
hb_vmSend( 1 );
hb_itemForwardValue( pItem, hb_stackReturnItem() );
}
break;
case VT_BYREF | VT_I2:
hb_itemPutNI( pItem, ( int ) *pVariant->n1.n2.n3.piVal );
break;
case VT_I2:
hb_itemPutNI( pItem, ( int ) pVariant->n1.n2.n3.iVal );
break;
case VT_BYREF | VT_I4:
hb_itemPutNL( pItem, ( LONG ) *pVariant->n1.n2.n3.plVal );
break;
case VT_I4:
hb_itemPutNL( pItem, ( LONG ) pVariant->n1.n2.n3.lVal );
break;
#ifndef HB_LONG_LONG_OFF
case VT_BYREF | VT_I8:
hb_itemPutNLL( pItem, ( LONGLONG ) *pVariant->n1.n2.n3.pllVal );
break;
#endif
#ifndef HB_LONG_LONG_OFF
case VT_I8:
hb_itemPutNLL( pItem, ( LONGLONG ) pVariant->n1.n2.n3.llVal );
break;
#endif
case VT_BYREF | VT_R8:
hb_itemPutND( pItem, *pVariant->n1.n2.n3.pdblVal );
break;
case VT_R8:
hb_itemPutND( pItem, pVariant->n1.n2.n3.dblVal );
break;
case VT_BYREF | VT_DATE:
hb_itemPutTD( pItem, *pVariant->n1.n2.n3.pdblVal + ( double ) 2415019 );
break;
case VT_DATE:
hb_itemPutTD( pItem, pVariant->n1.n2.n3.dblVal + ( double ) 2415019 );
break;
case VT_BYREF | VT_EMPTY:
case VT_EMPTY:
hb_itemClear( pItem );
break;
case VT_BYREF | VT_VARIANT:
hb_oleItemToVariant( pVariant->n1.n2.n3.pvarVal, pItem );
break;
default:
if( ( VARTYPE ) ( pVariant->n1.n2.vt & ( VT_BYREF | VT_ARRAY ) ) == ( VARTYPE ) ( VT_BYREF | VT_ARRAY ) )
{
VARTYPE vt;
PHB_ITEM pArray;
UINT iDims = SafeArrayGetDim( *pVariant->n1.n2.n3.pparray );
long * rgIndices = ( long * ) hb_xgrab( sizeof( long ) * iDims );
vt = pVariant->n1.n2.vt;
vt &= ~VT_ARRAY;
vt &= ~VT_BYREF;
pArray = SafeArrayToArray( *pVariant->n1.n2.n3.pparray, iDims, rgIndices, vt );
hb_xfree( ( void * ) rgIndices );
hb_itemForwardValue( pItem, pArray );
hb_itemRelease( pArray );
}
else
{
HB_TRACE(HB_TR_INFO, ("Unexpected type %p in: %s(%i)!\n", ( void * ) ( HB_PTRUINT ) pVariant->n1.n2.vt, __FILE__, __LINE__));
}
}
}
else
{
if( pVariant->n1.n2.vt & VT_BYREF )
{
HB_TRACE(HB_TR_INFO, ("Unexpected type %p in: %s(%i)!\n", ( void * ) ( HB_PTRUINT ) pVariant->n1.n2.vt, __FILE__, __LINE__));
}
}
VariantClear( &(pDispParams->rgvarg[ n ] ) );
}
hb_xfree( ( LPVOID ) pDispParams->rgvarg );
hb_xfree( ( LPVOID ) aPrgParams );
}
}
/* ----------------------------------------------------------------------- */
static PHB_ITEM SafeArrayToArray( SAFEARRAY * parray, UINT iDim, long * rgIndices, VARTYPE vt )
{
long iFrom, iTo, iLen, i;
PHB_ITEM pArray = hb_itemNew( NULL );
if( parray == NULL )
{
hb_arrayNew( pArray, 0 );
return pArray;
}
SafeArrayGetLBound( parray, iDim, &iFrom );
SafeArrayGetUBound( parray, iDim, &iTo );
iLen = iTo - iFrom + 1;
if( iDim > 1 )
{
PHB_ITEM pSubArray;
hb_arrayNew( pArray, iLen );
for( i = iFrom; i <= iTo; i++ )
{
rgIndices[ iDim - 1 ] = i;
/*printf( " Sub: %i\n", i );*/
pSubArray = SafeArrayToArray( parray, iDim - 1, rgIndices, vt );
hb_arraySetForward( pArray, i - iFrom + 1, pSubArray );
hb_itemRelease( pSubArray );
}
}
else
{
VARIANT mElem;
void * pTarget;
char * sArray = NULL;
VariantInit( &mElem );
if( vt == VT_VARIANT )
{
hb_arrayNew( pArray, iLen );
pTarget = &mElem;
}
else
{
if( vt == VT_I1 || vt == VT_UI1 )
{
/* Ugly hack, but needed to allocate our signature as hidden bytes! */
hb_itemPutC( pArray, NULL );
HB_STRING_ALLOC( pArray, ( ULONG )( iLen + 5 ) );
pArray->item.asString.length = iLen; /* TOFIX */
sArray = hb_itemGetCPtr( pArray );
sArray[ iLen ] = 0x7A;
sArray[ iLen + 1 ] = 0x7B;
sArray[ iLen + 2 ] = 0x7C;
sArray[ iLen + 3 ] = 0x7D;
sArray[ iLen + 4 ] = ( char ) vt;
pTarget = NULL;
}
else
{
hb_arrayNew( pArray, iLen );
pTarget = &mElem.n1.n2.n3.cVal;
}
}
for( i = iFrom; i <= iTo; i++ )
{
rgIndices[ iDim - 1 ] = i;
if( vt != VT_VARIANT )
{
/* Get cleared on VariantClear() - don't place out of loop! */
mElem.n1.n2.vt = vt;
if( vt == VT_I1 || vt == VT_UI1 )
{
SafeArrayGetElement( parray, rgIndices, &( sArray[ i - iFrom ] ) );
continue;
}
}
if( SUCCEEDED( SafeArrayGetElement( parray, rgIndices, pTarget ) ) )
{
/*HB_TRACE(HB_TR_INFO, ("Type: %p in: %s(%i)\n", mElem.n1.n2.vt, __FILE__, __LINE__));*/
hb_oleVariantToItem( hb_arrayGetItemPtr( pArray, i - iFrom + 1 ), &mElem );
VariantClear( &mElem );
}
}
}
/*HB_TRACE(HB_TR_INFO, ("Return len: %i\n", hb_arrayLen( pArray )));*/
/* Wrap our array with VTArrayWrapper() class ( aArray := VTArrayWrapper( vt, aArray) ) */
if( HB_IS_ARRAY( pArray ) && vt != VT_VARIANT )
{
PHB_ITEM pVT = hb_itemPutNL( hb_itemNew( NULL ), ( LONG ) vt );
hb_vmPushDynSym( s_pSym_VTArrayWrapper );
hb_vmPushNil();
hb_itemPushForward( pVT );
hb_itemPushForward( pArray );
hb_vmDo( 2 );
hb_itemForwardValue( pArray, hb_stackReturnItem() );
hb_itemRelease( pVT );
}
return pArray;
}
/* ----------------------------------------------------------------------- */
HRESULT hb_oleVariantToItem( PHB_ITEM pItem, VARIANT *pVariant )
{
PHB_ITEM pOleAuto;
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL;
SAFEARRAY *parray;/* = NULL;*/
hb_itemClear( pItem );
/* Don't "optimize" (VT_ARRAY | VT_VARIANT) must not match! */
while( pVariant->n1.n2.vt == ( VT_BYREF | VT_VARIANT ) || pVariant->n1.n2.vt == VT_VARIANT || pVariant->n1.n2.vt == VT_BYREF )
pVariant = pVariant->n1.n2.n3.pvarVal;
switch( pVariant->n1.n2.vt )
{
case VT_BSTR | VT_BYREF:
case VT_BSTR:
{
char *sString;
if( pVariant->n1.n2.vt & VT_BYREF )
sString = hb_oleWideToAnsi( *pVariant->n1.n2.n3.pbstrVal );
else
sString = hb_oleWideToAnsi( pVariant->n1.n2.n3.bstrVal );
if( sString )
hb_itemPutCPtr2( pItem, sString );
else
hb_itemPutC( pItem, NULL );
break;
}
case VT_BOOL | VT_BYREF:
hb_itemPutL( pItem, *pVariant->n1.n2.n3.pboolVal == VARIANT_FALSE ? FALSE : TRUE );
break;
case VT_BOOL:
hb_itemPutL( pItem, pVariant->n1.n2.n3.boolVal == VARIANT_FALSE ? FALSE : TRUE );
break;
case ( VT_UNKNOWN | VT_BYREF ):
pUnk = *pVariant->n1.n2.n3.ppunkVal;
/* Intentionally fall through */
case VT_UNKNOWN:
if( pVariant->n1.n2.vt == VT_UNKNOWN )
pUnk = pVariant->n1.n2.n3.punkVal;
if( pUnk )
{
IDispatch ** pDispPtr = &pDisp;
pUnk->lpVtbl->QueryInterface( pUnk, HB_ID_REF( REFIID, IID_IDispatch ), ( void ** ) pDispPtr );
}
/* Intentionally fall through */
case ( VT_DISPATCH | VT_BYREF ):
if( pVariant->n1.n2.vt == ( VT_DISPATCH | VT_BYREF ) )
pDisp = *pVariant->n1.n2.n3.ppdispVal;
/* Intentionally fall through */
case VT_DISPATCH:
if( pVariant->n1.n2.vt == VT_DISPATCH )
pDisp = pVariant->n1.n2.n3.pdispVal;
if( pDisp == NULL )
{
if( pUnk )
{
PHB_ITEM pVT = hb_itemPutNL( hb_itemNew( NULL ), ( LONG ) pVariant->n1.n2.vt );
PHB_ITEM pUnknown = hb_itemPutPtr( hb_itemNew( NULL ), ( void * ) pUnk );
hb_vmPushDynSym( s_pSym_VTWrapper );
hb_vmPushNil();
hb_itemPushForward( pVT );
hb_itemPushForward( pUnknown );
hb_vmDo( 2 );
if( pItem != hb_stackReturnItem() )
hb_itemForwardValue( pItem, hb_stackReturnItem() );
hb_itemRelease( pVT );
hb_itemRelease( pUnknown );
}
break;
}
pOleAuto = hb_itemNew( NULL );
hb_vmPushDynSym( s_pSym_TOleAuto );
hb_vmPushNil();
hb_vmDo( 0 );
/* Safety! */
hb_vmRequestReset();
hb_itemForwardValue( pOleAuto, hb_stackReturnItem() );
if( hb_itemType( pOleAuto ) )
{
/*TOleAuto():New( nDispatch )*/
hb_vmPushDynSym( s_pSym_New );
hb_itemPushForward( pOleAuto );
hb_vmPushNumInt( ( HB_PTRUINT ) pDisp );
hb_vmSend( 1 );
/* If retrieved from IUnknown than doubly added! */
if( pVariant->n1.n2.vt == VT_UNKNOWN || pVariant->n1.n2.vt == ( VT_UNKNOWN | VT_BYREF ) )
pDisp->lpVtbl->Release( pDisp );
hb_itemRelease( pOleAuto );
/* Safety! */
hb_vmRequestReset();
if( pItem != hb_stackReturnItem() )
hb_itemForwardValue( pItem, hb_stackReturnItem() );
}
break;
case VT_I1 | VT_BYREF: /* Byte */
case VT_UI1 | VT_BYREF:
hb_itemPutNI( pItem, ( short ) *pVariant->n1.n2.n3.pbVal );
break;
case VT_I1: /* Byte */
case VT_UI1:
hb_itemPutNI( pItem, ( short ) pVariant->n1.n2.n3.bVal );
break;
case VT_I2 | VT_BYREF: /* Short (2 bytes) */
case VT_UI2 | VT_BYREF:
hb_itemPutNI( pItem, ( short ) *pVariant->n1.n2.n3.piVal );
break;
case VT_I2: /* Short (2 bytes) */
case VT_UI2:
hb_itemPutNI( pItem, ( short ) pVariant->n1.n2.n3.iVal );
break;
case VT_I4 | VT_BYREF: /* Long (4 bytes) */
case VT_UI4 | VT_BYREF:
case VT_INT | VT_BYREF:
case VT_UINT | VT_BYREF:
hb_itemPutNL( pItem, ( LONG ) *pVariant->n1.n2.n3.plVal );
break;
case VT_I4: /* Long (4 bytes) */
case VT_UI4:
case VT_INT:
case VT_UINT:
hb_itemPutNL( pItem, ( LONG ) pVariant->n1.n2.n3.lVal );
break;
case VT_R4 | VT_BYREF: /* Single */
hb_itemPutND( pItem, *pVariant->n1.n2.n3.pfltVal );
break;
case VT_R4: /* Single */
hb_itemPutND( pItem, pVariant->n1.n2.n3.fltVal );
break;
case VT_R8 | VT_BYREF: /* Double */
hb_itemPutND( pItem, *pVariant->n1.n2.n3.pdblVal );
break;
case VT_R8: /* Double */
hb_itemPutND( pItem, pVariant->n1.n2.n3.dblVal );
break;
case VT_CY | VT_BYREF: /* Currency */
case VT_CY: /* Currency */
{
double tmp = 0;
if( pVariant->n1.n2.vt & VT_BYREF )
VarR8FromCy( *pVariant->n1.n2.n3.pcyVal, &tmp );
else
VarR8FromCy( pVariant->n1.n2.n3.cyVal, &tmp );
hb_itemPutND( pItem, tmp );
break;
}
case VT_DECIMAL | VT_BYREF: /* Decimal */
case VT_DECIMAL: /* Decimal */
{
double tmp = 0;
if( pVariant->n1.n2.vt & VT_BYREF )
VarR8FromDec( pVariant->n1.n2.n3.pdecVal, &tmp );
else
VarR8FromDec( &pVariant->n1.decVal, &tmp );
hb_itemPutND( pItem, tmp );
break;
}
case VT_DATE | VT_BYREF:
hb_itemPutTD( pItem, *pVariant->n1.n2.n3.pdblVal + ( double ) 2415019 );
break;
case VT_DATE:
hb_itemPutTD( pItem, pVariant->n1.n2.n3.dblVal + ( double ) 2415019 );
break;
case VT_EMPTY | VT_BYREF:
case VT_NULL | VT_BYREF:
case VT_EMPTY:
case VT_NULL:
break;
/*
case VT_VARIANT:
hb_oleVariantToItem( pItem, pVariant->n1.n2.n3.pvarVal );
break;
*/
case VT_PTR:
hb_itemPutPtr( pItem, pVariant->n1.n2.n3.byref );
break;
default:
if( pVariant->n1.n2.vt & VT_ARRAY )
{
UINT iDims;
long * rgIndices;
PHB_ITEM pArray;
VARTYPE vt;
if( pVariant->n1.n2.vt & VT_BYREF )
parray = *pVariant->n1.n2.n3.pparray;
else
parray = pVariant->n1.n2.n3.parray;
if( parray )
{
iDims = SafeArrayGetDim( parray );
rgIndices = ( long * ) hb_xgrab( sizeof( long ) * iDims );
vt = pVariant->n1.n2.vt;
vt &= ~VT_ARRAY;
vt &= ~VT_BYREF;
/*HB_TRACE(HB_TR_INFO, ("Type: %p in: %s(%i)\n", vt, __FILE__, __LINE__));*/
pArray = SafeArrayToArray( parray, iDims, rgIndices, vt );
hb_xfree( ( void * ) rgIndices );
hb_itemForwardValue( pItem, pArray );
hb_itemRelease( pArray );
}
else
hb_arrayNew( pItem, 0 );
}
else
{
HB_TRACE(HB_TR_INFO, ("Unexpected type %p in: %s(%i)!\n", ( void * ) ( HB_PTRUINT ) pVariant->n1.n2.vt, __FILE__, __LINE__));
return E_FAIL;
}
}
/*VariantClear( pVariant );*/
return S_OK;
}
/* ----------------------------------------------------------------------- */
static void RetValue( void )
{
hb_oleVariantToItem( hb_stackReturnItem(), &s_RetVal );
VariantClear( &s_RetVal );
return;
}
HB_FUNC( __OLEENUMNEXT )
{
IEnumVARIANT *pEnumVariant = ( IEnumVARIANT * ) hb_parptr( 1 );
ULONG *pcElementFetched = NULL;
if( pEnumVariant->lpVtbl->Next( pEnumVariant, 1, &s_RetVal, pcElementFetched ) == S_OK )
{
hb_oleVariantToItem( hb_stackReturnItem(), &s_RetVal );
VariantClear( &s_RetVal );
hb_storl( TRUE, 2 );
}
else
hb_storl( FALSE, 2 );
}
HB_FUNC( __OLEENUMSTOP )
{
IEnumVARIANT *pEnumVariant = ( IEnumVARIANT * ) hb_parptr( 1 );
pEnumVariant->lpVtbl->Release( pEnumVariant );
}
/* ----------------------------------------------------------------------- */
HB_FUNC( OLEEXCEPTIONSOURCE )
{
if( ( LONG ) s_nOleError == DISP_E_EXCEPTION )
hb_retc_buffer( hb_oleWideToAnsi( s_excep.bstrSource ) );
}
/* ----------------------------------------------------------------------- */
HB_FUNC( OLEEXCEPTIONDESCRIPTION )
{
if( ( LONG ) s_nOleError == DISP_E_EXCEPTION )
hb_retc_buffer( hb_oleWideToAnsi( s_excep.bstrDescription ) );
}
/* ----------------------------------------------------------------------- */
HB_FUNC( OLEERROR )
{
hb_retnl( ( long ) s_nOleError );
}
/* ----------------------------------------------------------------------- */
static char * Ole2TxtError( void )
{
switch( ( LONG ) s_nOleError )
{
case S_OK: return "S_OK";
case CO_E_CLASSSTRING: return "CO_E_CLASSSTRING";
case OLE_E_WRONGCOMPOBJ: return "OLE_E_WRONGCOMPOBJ";
case REGDB_E_CLASSNOTREG: return "REGDB_E_CLASSNOTREG";
case REGDB_E_WRITEREGDB: return "REGDB_E_WRITEREGDB";
case E_FAIL: return "E_FAIL";
case E_OUTOFMEMORY: return "E_OUTOFMEMORY";
case E_NOTIMPL: return "E_NOTIMPL";
case E_INVALIDARG: return "E_INVALIDARG";
case E_UNEXPECTED: return "E_UNEXPECTED";
case DISP_E_UNKNOWNNAME: return "DISP_E_UNKNOWNNAME";
case DISP_E_UNKNOWNLCID: return "DISP_E_UNKNOWNLCID";
case DISP_E_BADPARAMCOUNT: return "DISP_E_BADPARAMCOUNT";
case DISP_E_BADVARTYPE: return "DISP_E_BADVARTYPE";
case DISP_E_EXCEPTION: return "DISP_E_EXCEPTION";
case DISP_E_MEMBERNOTFOUND: return "DISP_E_MEMBERNOTFOUND";
case DISP_E_NONAMEDARGS: return "DISP_E_NONAMEDARGS";
case DISP_E_OVERFLOW: return "DISP_E_OVERFLOW";
case DISP_E_PARAMNOTFOUND: return "DISP_E_PARAMNOTFOUND";
case DISP_E_TYPEMISMATCH: return "DISP_E_TYPEMISMATCH";
case DISP_E_UNKNOWNINTERFACE: return "DISP_E_UNKNOWNINTERFACE";
case DISP_E_PARAMNOTOPTIONAL: return "DISP_E_PARAMNOTOPTIONAL";
case CO_E_SERVER_EXEC_FAILURE: return "CO_E_SERVER_EXEC_FAILURE";
case MK_E_UNAVAILABLE: return "MK_E_UNAVAILABLE";
}
HB_TRACE(HB_TR_INFO, ("TOleAuto Error %p\n", ( void * ) ( HB_PTRUINT ) s_nOleError));
return "Unknown error";
}
/* ----------------------------------------------------------------------- */
HB_FUNC( OLE2TXTERROR )
{
hb_retc( Ole2TxtError() );
}
/* ----------------------------------------------------------------------- */
HB_FUNC( MESSAGEBOX )
{
LPTSTR lpStr1 = HB_TCHAR_CONVTO( hb_parcx( 2 ) );
LPTSTR lpStr2 = HB_TCHAR_CONVTO( hb_parcx( 3 ) );
HWND hWnd = HB_ISNUM( 1 ) ? ( HWND ) ( HB_PTRUINT ) hb_parnint( 1 ) :
( HWND ) hb_parptr( 1 );
hb_retni( MessageBox( hWnd, lpStr1, lpStr2, hb_parni( 4 ) ) );
HB_TCHAR_FREE( lpStr1 );
HB_TCHAR_FREE( lpStr2 );
}
/* ----------------------------------------------------------------------- */
HB_FUNC( CREATEOLEOBJECT ) /* ( cOleName | cCLSID [, cIID ] [, cLicense ] ) */
{
BSTR bstrClassID;
IID ClassID, iid;
LPIID riid = ( LPIID ) &IID_IDispatch;
void *pDisp = NULL; /* IDispatch */
/* void *
* used intentionally to inform compiler that there is no
* strict-aliasing
*/
bstrClassID = hb_oleAnsiToSysString( hb_parcx( 1 ) );
if( hb_parcx( 1 )[ 0 ] == '{' )
s_nOleError = CLSIDFromString( bstrClassID, ( LPCLSID ) &ClassID );
else
s_nOleError = CLSIDFromProgID( bstrClassID, ( LPCLSID ) &ClassID );
SysFreeString( bstrClassID );
/*HB_TRACE(HB_TR_INFO, ("Result: %p\n", s_nOleError));*/
if( HB_ISCHAR( 2 ) )
{
if( hb_parcx( 2 )[ 0 ] == '{' )
{
bstrClassID = hb_oleAnsiToSysString( hb_parcx( 2 ) );
s_nOleError = CLSIDFromString( bstrClassID, &iid );
SysFreeString( bstrClassID );
}
else
memcpy( ( LPVOID ) &iid, hb_parcx( 2 ), sizeof( iid ) );
riid = &iid;
}
if( SUCCEEDED( s_nOleError ) )
{
if( HB_ISCHAR( 3 ) )
{
LPVOID * pCFPtr = NULL;
s_nOleError = CoGetClassObject( HB_ID_REF( REFCLSID, ClassID ), CLSCTX_SERVER, NULL, HB_ID_REF( REFIID, IID_IClassFactory2 ), pCFPtr );
if( SUCCEEDED( s_nOleError ) )
{
IClassFactory2 * pCF = ( IClassFactory2 * ) pCFPtr;
BSTR bstrLic = hb_oleAnsiToSysString( hb_parc( 3 ) );
s_nOleError = pCF->lpVtbl->CreateInstanceLic( pCF, NULL, NULL, (REFIID) riid, bstrLic, &pDisp );
SysFreeString( bstrLic );
pCF->lpVtbl->Release( pCF );
}
}
else
{
/*HB_TRACE(HB_TR_INFO, ("Class: %i\n", ClassID));*/
s_nOleError = CoCreateInstance( HB_ID_REF( REFCLSID, ClassID ), NULL, CLSCTX_SERVER, (REFIID) riid, &pDisp );
/*HB_TRACE(HB_TR_INFO, ("Result: %p\n", s_nOleError));*/
}
}
hb_retnint( ( HB_PTRUINT ) pDisp );
}
/* ----------------------------------------------------------------------- */
HB_FUNC( GETOLEOBJECT ) /* ( cOleName | cCLSID [, cIID ] ) */
{
BSTR bstrClassID;
IID ClassID, iid;
LPIID riid = ( LPIID ) &IID_IDispatch;
IUnknown *pUnk = NULL;
void *pDisp = NULL; /* IDispatch */
/* void *
* used intentionally to inform compiler that there is no
* strict-aliasing
*/
bstrClassID = hb_oleAnsiToSysString( hb_parcx( 1 ) );
if( hb_parcx( 1 )[ 0 ] == '{' )
s_nOleError = CLSIDFromString( bstrClassID, ( LPCLSID ) &ClassID );
else
s_nOleError = CLSIDFromProgID( bstrClassID, ( LPCLSID ) &ClassID );
/*s_nOleError = ProgIDFromCLSID( &ClassID, &pOleStr );*/
/*wprintf( L"Result %i ProgID: '%s'\n", s_nOleError, pOleStr );*/
SysFreeString( bstrClassID );
if( hb_pcount() == 2 )
{
if( hb_parcx( 2 )[ 0 ] == '{' )
{
bstrClassID = hb_oleAnsiToSysString( hb_parcx( 2 ) );
s_nOleError = CLSIDFromString( bstrClassID, &iid );
SysFreeString( bstrClassID );
}
else
memcpy( ( LPVOID ) &iid, hb_parcx( 2 ), sizeof( iid ) );
riid = &iid;
}
if( SUCCEEDED( s_nOleError ) )
{
s_nOleError = GetActiveObject( HB_ID_REF( REFCLSID, ClassID ), NULL, &pUnk );
if( SUCCEEDED( s_nOleError ) )
{
s_nOleError = pUnk->lpVtbl->QueryInterface( pUnk, (REFIID) riid, &pDisp );
pUnk->lpVtbl->Release( pUnk );
if( SUCCEEDED( s_nOleError ) )
hb_retnint( ( HB_PTRUINT ) pDisp );
}
}
}
/* ----------------------------------------------------------------------- */
HB_FUNC( OLEADDREF ) /* ( hOleObject, szMethodName, uParams... ) */
{
IDispatch * pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( 1 );
/*HB_TRACE(HB_TR_INFO, ("OleAddRef( %p )\n", pDisp));*/
s_nOleError = pDisp->lpVtbl->AddRef( pDisp );
hb_retnl( s_nOleError );
}
/* ----------------------------------------------------------------------- */
HB_FUNC( OLERELEASEOBJECT ) /* ( hOleObject, szMethodName, uParams... ) */
{
IDispatch * pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( 1 );
/*HB_TRACE(HB_TR_INFO, ("OleReleaseObject( %p )\n", pDisp));*/
s_nOleError = pDisp->lpVtbl->Release( pDisp );
hb_retnl( s_nOleError );
}
/* ----------------------------------------------------------------------- */
static HRESULT OleSetProperty( IDispatch *pDisp, DISPID DispID, DISPPARAMS *pDispParams )
{
pDispParams->rgdispidNamedArgs = &s_lPropPut;
pDispParams->cNamedArgs = 1;
/* 1 Based!!! */
if( ( HB_ISBYREF( 1 ) ) || HB_ISARRAY( 1 ) )
{
memset( ( LPBYTE ) &s_excep, 0, sizeof( s_excep ) );
s_nOleError = pDisp->lpVtbl->Invoke( pDisp,
DispID,
HB_ID_REF( REFIID, IID_NULL ),
LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUTREF,
pDispParams,
NULL, /* No return value */
&s_excep,
&s_uArgErr );
if( SUCCEEDED( s_nOleError ) )
return s_nOleError;
}
memset( ( LPBYTE ) &s_excep, 0, sizeof( s_excep ) );
s_nOleError = pDisp->lpVtbl->Invoke( pDisp,
DispID,
HB_ID_REF( REFIID, IID_NULL ),
LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUT,
pDispParams,
NULL, /* No return value */
&s_excep,
&s_uArgErr );
pDispParams->rgdispidNamedArgs = NULL;
pDispParams->cNamedArgs = 0;
return s_nOleError;
}
/* ----------------------------------------------------------------------- */
static HRESULT OleInvoke( IDispatch *pDisp, DISPID DispID, DISPPARAMS *pDispParams )
{
memset( ( LPBYTE ) &s_excep, 0, sizeof( s_excep ) );
s_nOleError = pDisp->lpVtbl->Invoke( pDisp,
DispID,
HB_ID_REF( REFIID, IID_NULL ),
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
pDispParams,
&s_RetVal,
&s_excep,
&s_uArgErr );
return s_nOleError;
}
/* ----------------------------------------------------------------------- */
static HRESULT OleGetProperty( IDispatch *pDisp, DISPID DispID, DISPPARAMS *pDispParams )
{
memset( ( LPBYTE ) &s_excep, 0, sizeof( s_excep ) );
s_nOleError = pDisp->lpVtbl->Invoke( pDisp,
DispID,
HB_ID_REF( REFIID, IID_NULL ),
LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET,
pDispParams,
&s_RetVal,
&s_excep,
&s_uArgErr );
/*HB_TRACE(HB_TR_INFO, ("OleGetValue: %p\n", s_nOleError));*/
return s_nOleError;
}
/* ----------------------------------------------------------------------- */
static HRESULT OleGetValue( IDispatch *pDisp )
{
VariantClear( &s_RetVal );
/* Try to apply the requested message to the DEFAULT Property of the object if any. */
if( SUCCEEDED( OleGetProperty( pDisp, DISPID_VALUE, &s_EmptyDispParams ) ) && ( s_RetVal.n1.n2.vt == VT_DISPATCH || s_RetVal.n1.n2.vt == ( VT_DISPATCH | VT_BYREF ) ) )
{
VariantCopy( &s_OleVal, &s_RetVal );
VariantClear( &s_RetVal );
return s_nOleError;
}
return E_FAIL;
}
/* ----------------------------------------------------------------------- */
static void OleThrowError( void )
{
PHB_ITEM pReturn;
char *sDescription;
BOOL fFree = FALSE;
hb_vmPushDynSym( s_pSym_cClassName );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
if( s_nOleError == DISP_E_EXCEPTION )
{
sDescription = hb_oleWideToAnsi( s_excep.bstrDescription );
fFree = TRUE;
}
else
sDescription = Ole2TxtError();
/*HB_TRACE(HB_TR_INFO, ("Desc: '%s'\n", sDescription));*/
pReturn = hb_errRT_SubstParams( hb_parcx( -1 ), EG_OLEEXCEPTION, (ULONG) s_nOleError, sDescription, hb_itemGetSymbol( hb_stackBaseItem() )->szName );
if( fFree )
{
hb_xfree( ( void * ) sDescription );
}
if( pReturn )
hb_itemReturnRelease( pReturn );
}
/* ----------------------------------------------------------------------- */
HB_FUNC( TOLEAUTO_OLEVALUE )
{
if( hb_pcount() == 0 )
{
IDispatch *pDisp;
hb_vmPushDynSym( s_pSym_hObj );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( -1 );
VariantClear( &s_RetVal );
OleGetProperty( pDisp, DISPID_VALUE, &s_EmptyDispParams );
/*HB_TRACE(HB_TR_INFO, ("GetDefault: %p\n", s_nOleError));*/
if( SUCCEEDED( s_nOleError ) )
RetValue();
else
OleThrowError();
}
}
/* ----------------------------------------------------------------------- */
HB_FUNC( TOLEAUTO__OLEVALUE )
{
if( hb_pcount() >= 1 )
{
IDispatch *pDisp;
DISPPARAMS DispParams;
PHB_ITEM *aPrgParams;
hb_vmPushDynSym( s_pSym_hObj );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( -1 );
VariantClear( &s_RetVal );
aPrgParams = GetParams( &DispParams, 0 );
OleSetProperty( pDisp, DISPID_VALUE, &DispParams );
/*HB_TRACE(HB_TR_INFO, ("SetDefault: %p\n", s_nOleError));*/
FreeParams( &DispParams, aPrgParams );
if( SUCCEEDED( s_nOleError ) )
hb_itemReturn( hb_stackItemFromBase( 1 ) );
else
OleThrowError();
}
}
/* ----------------------------------------------------------------------- */
HB_FUNC( TOLEAUTO_OLENEWENUMERATOR ) /* ( hOleObject, szMethodName, uParams... ) */
{
IDispatch *pDisp;
hb_vmPushDynSym( s_pSym_hObj );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( -1 );
VariantClear( &s_RetVal );
if( SUCCEEDED( OleGetProperty( pDisp, DISPID_NEWENUM, &s_EmptyDispParams ) ) ||
SUCCEEDED( OleInvoke( pDisp, DISPID_NEWENUM, &s_EmptyDispParams ) ) )
{
LPVOID pEnumVariant = NULL; /* IEnumVARIANT */
if( s_RetVal.n1.n2.vt == ( VT_UNKNOWN | VT_BYREF ) )
s_nOleError = (*s_RetVal.n1.n2.n3.ppunkVal)->lpVtbl->QueryInterface( *s_RetVal.n1.n2.n3.ppunkVal, HB_ID_REF( REFIID, IID_IEnumVARIANT ), &pEnumVariant );
else if( s_RetVal.n1.n2.vt == VT_UNKNOWN )
s_nOleError = s_RetVal.n1.n2.n3.punkVal->lpVtbl->QueryInterface( s_RetVal.n1.n2.n3.punkVal, HB_ID_REF( REFIID, IID_IEnumVARIANT ), &pEnumVariant );
else if( s_RetVal.n1.n2.vt == ( VT_DISPATCH | VT_BYREF ) )
s_nOleError = (*s_RetVal.n1.n2.n3.ppdispVal)->lpVtbl->QueryInterface( *s_RetVal.n1.n2.n3.ppdispVal, HB_ID_REF( REFIID, IID_IEnumVARIANT ), &pEnumVariant );
else if( s_RetVal.n1.n2.vt == VT_DISPATCH )
s_nOleError = s_RetVal.n1.n2.n3.pdispVal->lpVtbl->QueryInterface( s_RetVal.n1.n2.n3.pdispVal, HB_ID_REF( REFIID, IID_IEnumVARIANT ), &pEnumVariant );
else
s_nOleError = E_FAIL;
VariantClear( &s_RetVal );
if( SUCCEEDED( s_nOleError ) )
hb_retptr( pEnumVariant );
}
else
OleThrowError();
}
/* ----------------------------------------------------------------------- */
static HRESULT OleGetID( IDispatch *pDisp, const char *szName, DISPID *pDispID, BOOL *pbSetFirst )
{
BSTR bstrMessage;
if( pbSetFirst )
*pbSetFirst = FALSE;
/*
if( strcmp( szName, "OLEVALUE" ) == 0 || strcmp( szName, "_OLEVALUE" ) == 0 )
{
DispID = DISPID_VALUE;
s_nOleError = S_OK;
}
else*/ if( szName[0] == '_' && szName[1] && hb_pcount() >= 1 )
{
bstrMessage = hb_oleAnsiToSysString( szName + 1 );
s_nOleError = pDisp->lpVtbl->GetIDsOfNames( pDisp, HB_ID_REF( REFIID, IID_NULL ), ( wchar_t ** ) &bstrMessage, 1, LOCALE_SYSTEM_DEFAULT, pDispID );
SysFreeString( bstrMessage );
/*HB_TRACE(HB_TR_INFO, ("1. ID of: '%s' -> %i Result: %p\n", hb_itemGetSymbol( hb_stackBaseItem() )->szName + 1, DispID, s_nOleError));*/
if( SUCCEEDED( s_nOleError ) )
{
if( pbSetFirst )
*pbSetFirst = TRUE;
}
}
else
s_nOleError = E_PENDING;
if( FAILED( s_nOleError ) )
{
/* Try again without removing the assign prefix (_). */
bstrMessage = hb_oleAnsiToSysString( szName );
s_nOleError = pDisp->lpVtbl->GetIDsOfNames( pDisp, HB_ID_REF( REFIID, IID_NULL ), ( wchar_t ** ) &bstrMessage, 1, 0, pDispID );
SysFreeString( bstrMessage );
/*HB_TRACE(HB_TR_INFO, ("2. ID of: '%s' -> %i Result: %p\n", szName, *pDispID, s_nOleError));*/
}
return s_nOleError;
}
/* ----------------------------------------------------------------------- */
HB_FUNC( TOLEAUTO_INVOKE )
{
IDispatch *pDisp;
char *szName = hb_parc(1);
DISPID DispID;
DISPPARAMS DispParams;
hb_vmPushDynSym( s_pSym_hObj );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( -1 );
if( szName && SUCCEEDED( OleGetID( pDisp, szName, &DispID, NULL ) ) )
{
PHB_ITEM *aPrgParams = GetParams( &DispParams, 1 );
if( SUCCEEDED( OleInvoke( pDisp, DispID, &DispParams ) ) )
RetValue();
FreeParams( &DispParams, aPrgParams );
}
}
/* ----------------------------------------------------------------------- */
HB_FUNC( TOLEAUTO_SET )
{
IDispatch *pDisp;
char *szName = hb_parc( 1 );
DISPID DispID;
DISPPARAMS DispParams;
hb_vmPushDynSym( s_pSym_hObj );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( -1 );
if( szName && SUCCEEDED( OleGetID( pDisp, szName, &DispID, NULL ) ) )
{
PHB_ITEM *aPrgParams = GetParams( &DispParams, 1 );
if( SUCCEEDED( OleSetProperty( pDisp, DispID, &DispParams ) ) )
RetValue();
FreeParams( &DispParams, aPrgParams );
}
}
/* ----------------------------------------------------------------------- */
HB_FUNC( TOLEAUTO_GET )
{
IDispatch *pDisp;
char *szName = hb_parc(1);
DISPID DispID;
DISPPARAMS DispParams;
hb_vmPushDynSym( s_pSym_hObj );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( -1 );
if( szName && SUCCEEDED( OleGetID( pDisp, szName, &DispID, NULL ) ) )
{
PHB_ITEM *aPrgParams = GetParams( &DispParams, 1 );
if( SUCCEEDED( OleGetProperty( pDisp, DispID, &DispParams ) ) )
RetValue();
FreeParams( &DispParams, aPrgParams );
}
}
/* ----------------------------------------------------------------------- */
HB_FUNC( TOLEAUTO_ONERROR )
{
IDispatch *pDisp;
DISPID DispID;
DISPPARAMS DispParams;
BOOL bSetFirst = FALSE, bTryDefault = TRUE;
PHB_ITEM *aPrgParams = GetParams( &DispParams, 0 );
/*HB_TRACE(HB_TR_INFO, ("Class: '%s' Message: '%s', Params: %i Arg1: %i\n", hb_objGetClsName( hb_stackSelfItem() ), hb_itemGetSymbol( hb_stackBaseItem() )->szName, hb_pcount(), hb_parinfo(1)));*/
hb_vmPushDynSym( s_pSym_hObj );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
pDisp = ( IDispatch * ) ( HB_PTRUINT ) hb_parnint( -1 );
OleGetID:
if( SUCCEEDED( OleGetID( pDisp, hb_itemGetSymbol( hb_stackBaseItem() )->szName, &DispID, &bSetFirst ) ) )
{
VariantClear( &s_RetVal );
if( bSetFirst )
{
if( SUCCEEDED( OleSetProperty( pDisp, DispID, &DispParams ) ) )
hb_itemReturn( hb_stackItemFromBase( 1 ) );
/*HB_TRACE(HB_TR_INFO, ("FIRST OleSetProperty %i\n", s_nOleError));*/
}
else
s_nOleError = E_PENDING;
if( FAILED( s_nOleError ) )
{
if( SUCCEEDED( OleInvoke( pDisp, DispID, &DispParams ) ) )
RetValue();
/*HB_TRACE(HB_TR_INFO, ("OleInvoke %i\n", s_nOleError));*/
}
if( FAILED( s_nOleError ) )
{
if( SUCCEEDED( OleGetProperty( pDisp, DispID, &DispParams ) ) )
RetValue();
/*HB_TRACE(HB_TR_INFO, ("OleGetProperty(%i) %i\n", DispParams.cArgs, s_nOleError));*/
}
if( FAILED( s_nOleError ) && bSetFirst == FALSE && hb_pcount() >= 1 )
{
if( SUCCEEDED( OleSetProperty( pDisp, DispID, &DispParams ) ) )
hb_itemReturn( hb_stackItemFromBase( 1 ) );
/*HB_TRACE(HB_TR_INFO, ("OleSetProperty %i\n", s_nOleError));*/
}
}
if( SUCCEEDED( s_nOleError ) )
{
/*HB_TRACE(HB_TR_INFO, ("Invoke Succeeded!\n"));*/
if( HB_IS_OBJECT( hb_stackReturnItem() ) && hb_clsIsParent( hb_objGetClass( hb_stackReturnItem() ), "TOLEAUTO" ) )
{
PHB_ITEM pReturn = hb_itemNew( NULL );
PHB_ITEM pOleClassName = hb_itemNew( NULL );
char *sOleClassName;
int iClassNameLen, iMsgNameLen;
hb_itemForwardValue( pReturn, hb_stackReturnItem() );
hb_vmPushDynSym( s_pSym_cClassName );
hb_vmPush( hb_stackSelfItem() );
hb_vmSend( 0 );
iClassNameLen = hb_parclen( -1 );
iMsgNameLen = strlen( hb_itemGetSymbol( hb_stackBaseItem() )->szName );
sOleClassName = ( char * ) hb_xgrab( iClassNameLen + 1 + iMsgNameLen + 1 );
hb_strncpy( sOleClassName, hb_parc( - 1 ), iClassNameLen );
sOleClassName[ iClassNameLen ] = ':';
hb_strncpy( sOleClassName + iClassNameLen + 1, hb_itemGetSymbol( hb_stackBaseItem() )->szName, iMsgNameLen );
/*HB_TRACE(HB_TR_INFO, ("Class: '%s'\n", sOleClassName));*/
hb_itemPutCLPtr( pOleClassName, sOleClassName, iClassNameLen + 1 + iMsgNameLen );
hb_vmPushDynSym( s_pSym_cClassName );
hb_vmPush( pReturn );
hb_itemPushForward( pOleClassName );
hb_vmSend( 1 );
hb_itemReturnForward( pReturn );
hb_itemRelease( pReturn );
hb_itemRelease( pOleClassName );
}
}
else
{
/* Try to apply the requested message to the DEFAULT Method of the object if any. */
if( bTryDefault )
{
if( SUCCEEDED( ( /* s_nOleError = */ OleGetValue( pDisp ) ) ) )
{
bTryDefault = FALSE;
/*HB_TRACE(HB_TR_INFO, ("Try using DISPID_VALUE\n"));*/
pDisp = s_OleVal.n1.n2.n3.pdispVal;
goto OleGetID;
}
}
/*HB_TRACE(HB_TR_INFO, ("Invoke Failed!\n"));*/
OleThrowError();
}
FreeParams( &DispParams, aPrgParams );
/* We are responsible to release the Default Interface which we retrieved */
if( bTryDefault == FALSE && pDisp )
pDisp->lpVtbl->Release( pDisp );
}
#endif