diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 7a25185be5..a99d3baeb7 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,41 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-02-12 12:20 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) + * contrib/hbwin/hbwin.ch + + Added HB_WIN_DLL_CALLCONV_* macros. (so far only privately defined inside .c code) + + Added HB_WIN_DLL_CTYPE_* macros. (so far only privately defined inside .c code) + + Reworked HB_WIN_DLL_CTYPE_* macro values. INCOMPATIBLE. Since they weren't + previously documented, this should not be a breakage, pls report it if this is + a problem. + ! Fixed .ch syntax to also work in .c files. + + * contrib/hbwin/hbwin.h + * contrib/hbwin/legacycd.c + * contrib/hbwin/win_dll.c + * contrib/hbwin/tests/testdll.prg + * Using hbwin.ch for callconv and C type constants. + + Added public low-level interface: hbwin_dllCall(). + This has provision for exact parameter type specification. + * Changed Harbour level functions to use new public + interface hbwin_dllCall(). + + Moved CALLDLL(), CALLDLLBOOL(), CALLDLLTYPED() to legacy source. + * HB_DLLEXEC structure made private to XPP compatibility + section. + + Added new WIN_DLLCALL() API. This can replace all old CALL*() + function and give more flexibility. Its first parameter is an + optional array, which can specify calling convention (it was + fixed in old implementation), return type and UNICODE swicth, + plus it has provision to specify parameter types, too. + + Changed test app to use new WIN_DLLCALL() API. + * hb_getprocaddress() made public (but not exported) and + renamed to hbwin_getprocaddress(). + + * config/wce/mingwarm.mk + * config/win/mingw.mk + - Deleted hack to always add frame buffer for hbwin. + It's not necessary anymore. + 2010-02-12 10:28 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) * contrib/hbwin/win_dll.c + Reimplemented win32 .dll calls using pure C code. diff --git a/harbour/config/wce/mingwarm.mk b/harbour/config/wce/mingwarm.mk index cda29aa212..e73d50b786 100644 --- a/harbour/config/wce/mingwarm.mk +++ b/harbour/config/wce/mingwarm.mk @@ -26,10 +26,7 @@ ifneq ($(HB_BUILD_OPTIM),no) # Use -O2 instead of -O3 here. CFLAGS += -O2 ifneq ($(HB_BUILD_DEBUG),yes) - # NOTE: Hack to always include frame pointer to make win_dll.c / hb_DynaCall() work. - ifneq ($(LIBNAME),hbwin) - CFLAGS += -fomit-frame-pointer - endif + CFLAGS += -fomit-frame-pointer endif endif diff --git a/harbour/config/win/mingw.mk b/harbour/config/win/mingw.mk index 2f035dfe32..c62d145e0c 100644 --- a/harbour/config/win/mingw.mk +++ b/harbour/config/win/mingw.mk @@ -34,10 +34,7 @@ endif ifneq ($(HB_BUILD_OPTIM),no) CFLAGS += -O3 ifneq ($(HB_BUILD_DEBUG),yes) - # NOTE: Hack to always include frame pointer to make win_dll.c / hb_DynaCall() work. - ifneq ($(LIBNAME),hbwin) - CFLAGS += -fomit-frame-pointer - endif + CFLAGS += -fomit-frame-pointer endif ifeq ($(HB_COMPILER),mingw) CFLAGS += -march=i586 -mtune=pentiumpro diff --git a/harbour/contrib/hbwin/hbwin.ch b/harbour/contrib/hbwin/hbwin.ch index 4a39a25ccb..7dafc3be7d 100644 --- a/harbour/contrib/hbwin/hbwin.ch +++ b/harbour/contrib/hbwin/hbwin.ch @@ -56,6 +56,39 @@ #ifndef HBWIN_CH_ #define HBWIN_CH_ +/* WIN_DLLCALL() C calling convention */ +#define HB_WIN_DLL_CALLCONV_CDECL 1 +#define HB_WIN_DLL_CALLCONV_STDCALL 2 + +/* WIN_DLLCALL() C types */ +#define HB_WIN_DLL_CTYPE_DEFAULT 0x0000 +#define HB_WIN_DLL_CTYPE_CHAR 0x0001 +#define HB_WIN_DLL_CTYPE_CHAR_UNSIGNED 0x0011 +#define HB_WIN_DLL_CTYPE_CHAR_PTR 0x0101 +#define HB_WIN_DLL_CTYPE_CHAR_UNSIGNED_PTR 0x0111 +#define HB_WIN_DLL_CTYPE_SHORT 0x0002 +#define HB_WIN_DLL_CTYPE_SHORT_UNSIGNED 0x0012 +#define HB_WIN_DLL_CTYPE_SHORT_PTR 0x0102 +#define HB_WIN_DLL_CTYPE_SHORT_UNSIGNED_PTR 0x0112 +#define HB_WIN_DLL_CTYPE_INT 0x0003 +#define HB_WIN_DLL_CTYPE_INT_UNSIGNED 0x0013 +#define HB_WIN_DLL_CTYPE_INT_PTR 0x0103 +#define HB_WIN_DLL_CTYPE_INT_UNSIGNED_PTR 0x0113 +#define HB_WIN_DLL_CTYPE_LONG 0x0004 +#define HB_WIN_DLL_CTYPE_LONG_UNSIGNED 0x0014 +#define HB_WIN_DLL_CTYPE_LONG_PTR 0x0104 +#define HB_WIN_DLL_CTYPE_LONG_UNSIGNED_PTR 0x0114 +#define HB_WIN_DLL_CTYPE_FLOAT 0x0005 +#define HB_WIN_DLL_CTYPE_FLOAT_PTR 0x0105 +#define HB_WIN_DLL_CTYPE_DOUBLE 0x0006 +#define HB_WIN_DLL_CTYPE_DOUBLE_PTR 0x0106 +#define HB_WIN_DLL_CTYPE_BOOL 0x0008 +#define HB_WIN_DLL_CTYPE_BOOL_PTR 0x0108 +#define HB_WIN_DLL_CTYPE_VOID 0x0009 +#define HB_WIN_DLL_CTYPE_VOID_PTR 0x0109 +#define HB_WIN_DLL_CTYPE_STRUCTURE 0x000A +#define HB_WIN_DLL_CTYPE_STRUCTURE_PTR 0x010A + /* WIN_MAPISENDMAIL() address types */ #define WIN_MAPI_TO 1 #define WIN_MAPI_CC 2 @@ -459,7 +492,8 @@ /* Deprecated constants and macros */ /* ------------------------------- */ -#if defined( HB_LEGACY_LEVEL3 ) .AND. ! defined( HB_WIN_NO_LEGACY ) +#if defined( HB_LEGACY_LEVEL3 ) +#if ! defined( HB_WIN_NO_LEGACY ) #define HKEY_CLASSES_ROOT WIN_HKEY_CLASSES_ROOT #define HKEY_CURRENT_USER WIN_HKEY_CURRENT_USER @@ -617,6 +651,7 @@ #define EASTEUROPE_CHARSET WIN_EASTEUROPE_CHARSET #define OEM_CHARSET WIN_OEM_CHARSET +#endif #endif #endif /* HBWIN_CH_ */ diff --git a/harbour/contrib/hbwin/hbwin.h b/harbour/contrib/hbwin/hbwin.h index e10c909966..373d4801b4 100644 --- a/harbour/contrib/hbwin/hbwin.h +++ b/harbour/contrib/hbwin/hbwin.h @@ -93,6 +93,9 @@ HB_EXTERN_BEGIN extern HB_EXPORT int hbwin_bitmapType( const void * pImgBuf, HB_SIZE size ); +extern HB_EXPORT void hbwin_dllCall( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC lpFunction, int iParams, int iFirst, int * iParTypes ); + +extern FARPROC hbwin_getprocaddress( HMODULE hDLL, int iParam, HB_BOOL * pbUNICODE ); HB_EXTERN_END diff --git a/harbour/contrib/hbwin/legacycd.c b/harbour/contrib/hbwin/legacycd.c index c375a68086..aa4dc253c7 100644 --- a/harbour/contrib/hbwin/legacycd.c +++ b/harbour/contrib/hbwin/legacycd.c @@ -78,4 +78,26 @@ HB_FUNC( SETLASTERROR ) SetLastError( hb_parnl( 1 ) ); } +#ifndef HB_WIN_NO_LEGACY +#define HB_WIN_NO_LEGACY +#endif +#undef HB_LEGACY_LEVEL3 + +#include "hbwin.ch" + +HB_FUNC( CALLDLL ) +{ + hbwin_dllCall( HB_WIN_DLL_CALLCONV_STDCALL, HB_WIN_DLL_CTYPE_DEFAULT, HB_FALSE, ( FARPROC ) hb_parptr( 1 ), hb_pcount(), 2, NULL ); +} + +HB_FUNC( CALLDLLBOOL ) +{ + hbwin_dllCall( HB_WIN_DLL_CALLCONV_STDCALL, HB_WIN_DLL_CTYPE_BOOL , HB_FALSE, ( FARPROC ) hb_parptr( 1 ), hb_pcount(), 2, NULL ); +} + +HB_FUNC( CALLDLLTYPED ) +{ + hbwin_dllCall( HB_WIN_DLL_CALLCONV_STDCALL, hb_parni( 2 ) , HB_FALSE, ( FARPROC ) hb_parptr( 1 ), hb_pcount(), 3, NULL ); +} + #endif diff --git a/harbour/contrib/hbwin/tests/testdll.prg b/harbour/contrib/hbwin/tests/testdll.prg index 6a7128de62..91fc4e3f13 100644 --- a/harbour/contrib/hbwin/tests/testdll.prg +++ b/harbour/contrib/hbwin/tests/testdll.prg @@ -13,6 +13,8 @@ * */ +#include "hbwin.ch" + #define MB_OK 0x00000000 #define MB_OKCANCEL 0x00000001 #define MB_ABORTRETRYIGNORE 0x00000002 @@ -96,12 +98,12 @@ PROCEDURE Main() hDLL := DllLoad( "shell32.dll" ) ? "ValType( hDLL ): ", ValType( hDLL ) cData := Space( MAX_PATH ) - ? "CALLDLLBOOL: ", CallDllBool( GetProcAddress( hDLL, "SHGetSpecialFolderPath" ), 0, @cData, CSIDL_APPDATA, 0 ) + ? "WIN_DLLCALL (BOOL retval): ", win_dllCall( { NIL, HB_WIN_DLL_CTYPE_BOOL }, GetProcAddress( hDLL, "SHGetSpecialFolderPath" ), 0, @cData, CSIDL_APPDATA, 0 ) ? "@cData: ", cData - ? "CALLDLL: ", CallDll( GetProcAddress( hDLL, "SHGetFolderPath" ), 0, CSIDL_ADMINTOOLS, 0, 0, cData ) // WRONG + ? "WIN_DLLCALL: ", win_dllCall( GetProcAddress( hDLL, "SHGetFolderPath" ), 0, CSIDL_ADMINTOOLS, 0, 0, cData ) // WRONG ? "cData:", cData cData := Space( MAX_PATH ) - ? "CALDLL: ", CallDll( GetProcAddress( hDLL, "SHGetFolderPath" ), 0, CSIDL_ADMINTOOLS, 0, 0, @cData ) + ? "WIN_DLLCALL: ", win_dllCall( GetProcAddress( hDLL, "SHGetFolderPath" ), 0, CSIDL_ADMINTOOLS, 0, 0, @cData ) ? "@cData: ", cData DllUnload( hDLL ) diff --git a/harbour/contrib/hbwin/win_dll.c b/harbour/contrib/hbwin/win_dll.c index 6d656f1bbb..dfed4ba0a3 100644 --- a/harbour/contrib/hbwin/win_dll.c +++ b/harbour/contrib/hbwin/win_dll.c @@ -57,54 +57,19 @@ #include "hbapiitm.h" #include "hbvm.h" -/* C calling conventions */ -#define _CALLCONV_CDECL 1 -#define _CALLCONV_STDCALL 2 +#ifndef HB_WIN_NO_LEGACY +#define HB_WIN_NO_LEGACY +#endif +#undef HB_LEGACY_LEVEL3 +#include "hbwin.ch" /* C raw return types */ -#define _RETTYPERAW_INT32 1 -#define _RETTYPERAW_INT64 2 -#define _RETTYPERAW_DOUBLE 3 -#define _RETTYPERAW_FLOAT 4 +#define _RETTYPERAW_INT32 1 +#define _RETTYPERAW_INT64 2 +#define _RETTYPERAW_DOUBLE 3 +#define _RETTYPERAW_FLOAT 4 -/* C parameter types */ -#define _RETTYPE_VOID 9 -#define _RETTYPE_CHAR 1 -#define _RETTYPE_UNSIGNED_CHAR -1 -#define _RETTYPE_CHAR_PTR 10 -#define _RETTYPE_UNSIGNED_CHAR_PTR -10 -#define _RETTYPE_SHORT 2 -#define _RETTYPE_UNSIGNED_SHORT -2 -#define _RETTYPE_SHORT_PTR 20 -#define _RETTYPE_UNSIGNED_SHORT_PTR -20 -#define _RETTYPE_INT 3 -#define _RETTYPE_UNSIGNED_INT -3 -#define _RETTYPE_INT_PTR 30 -#define _RETTYPE_UNSIGNED_INT_PTR -30 -#define _RETTYPE_LONG 4 -#define _RETTYPE_UNSIGNED_LONG -4 -#define _RETTYPE_LONG_PTR 40 -#define _RETTYPE_UNSIGNED_LONG_PTR -40 -#define _RETTYPE_FLOAT 5 -#define _RETTYPE_FLOAT_PTR 50 -#define _RETTYPE_DOUBLE 6 -#define _RETTYPE_DOUBLE_PTR 60 -#define _RETTYPE_VOID_PTR 7 -#define _RETTYPE_BOOL 8 -#define _RETTYPE_STRUCTURE 1000 -#define _RETTYPE_STRUCTURE_PTR 10000 - -typedef struct -{ - HMODULE hDLL; /* Handle */ - HB_BOOL bFreeDLL; /* Free library handle on destroy? */ - int iCallConv; - int iRetType; - HB_BOOL bUNICODE; - FARPROC lpFunction; /* Function Address */ -} HB_DLLEXEC, * PHB_DLLEXEC; - -#define _DLLEXEC_MAXPARAM 15 +#define _DLLEXEC_MAXPARAM 15 #if defined( HB_ARCH_64BIT ) @@ -515,17 +480,11 @@ typedef float ( _cdecl * WIN32_CFLP30 )( HB_U32, HB_U32, HB_U32, HB_U32, HB_U #endif -static void hb_DllExec( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC lpFunction, PHB_DLLEXEC xec, int iParams, int iFirst ) +void hbwin_dllCall( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC lpFunction, int iParams, int iFirst, int * iParTypes ) { int tmp; - if( xec ) - { - iCallConv = xec->iCallConv; - iRetType = xec->iRetType; - bUNICODE = xec->bUNICODE; - lpFunction = xec->lpFunction; - } + HB_SYMBOL_UNUSED( iParTypes ); if( ! lpFunction ) return; @@ -534,6 +493,8 @@ static void hb_DllExec( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC l { HB_WINCALL wcall; + HB_SYMBOL_UNUSED( iCallConv ); + wcall.bUNICODE = bUNICODE; wcall.iFirst = iFirst - 1; @@ -541,7 +502,7 @@ static void hb_DllExec( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC l if( iParams <= _DLLEXEC_MAXPARAM ) { - HB_U64 nRetVal; + HB_U64 nRetVal = 0; if( iParams ) { @@ -576,53 +537,53 @@ static void hb_DllExec( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC l switch( iRetType ) { - case _RETTYPE_VOID: + case HB_WIN_DLL_CTYPE_VOID: hb_ret(); break; - case _RETTYPE_BOOL: + case HB_WIN_DLL_CTYPE_BOOL: hb_retl( nRetVal != 0 ); break; - case _RETTYPE_CHAR: - case _RETTYPE_UNSIGNED_CHAR: - case _RETTYPE_SHORT: - case _RETTYPE_UNSIGNED_SHORT: - case _RETTYPE_INT: + case HB_WIN_DLL_CTYPE_CHAR: + case HB_WIN_DLL_CTYPE_CHAR_UNSIGNED: + case HB_WIN_DLL_CTYPE_SHORT: + case HB_WIN_DLL_CTYPE_SHORT_UNSIGNED: + case HB_WIN_DLL_CTYPE_INT: hb_retni( ( int ) nRetVal ); break; - case _RETTYPE_LONG: + case HB_WIN_DLL_CTYPE_LONG: hb_retnl( ( long ) nRetVal ); break; - case _RETTYPE_UNSIGNED_INT: - case _RETTYPE_UNSIGNED_LONG: + case HB_WIN_DLL_CTYPE_INT_UNSIGNED: + case HB_WIN_DLL_CTYPE_LONG_UNSIGNED: hb_retnint( nRetVal ); break; - case _RETTYPE_CHAR_PTR: - case _RETTYPE_UNSIGNED_CHAR_PTR: + case HB_WIN_DLL_CTYPE_CHAR_PTR: + case HB_WIN_DLL_CTYPE_CHAR_UNSIGNED_PTR: if( bUNICODE ) hb_retstr_u16( HB_CDP_ENDIAN_NATIVE, ( const HB_WCHAR * ) nRetVal ); else hb_retstr( hb_setGetOSCP(), ( const char * ) nRetVal ); break; - case _RETTYPE_INT_PTR: - case _RETTYPE_UNSIGNED_SHORT_PTR: - case _RETTYPE_UNSIGNED_INT_PTR: - case _RETTYPE_STRUCTURE_PTR: - case _RETTYPE_LONG_PTR: - case _RETTYPE_UNSIGNED_LONG_PTR: - case _RETTYPE_VOID_PTR: - case _RETTYPE_FLOAT_PTR: - case _RETTYPE_DOUBLE_PTR: + case HB_WIN_DLL_CTYPE_INT_PTR: + case HB_WIN_DLL_CTYPE_SHORT_UNSIGNED_PTR: + case HB_WIN_DLL_CTYPE_INT_UNSIGNED_PTR: + case HB_WIN_DLL_CTYPE_STRUCTURE_PTR: + case HB_WIN_DLL_CTYPE_LONG_PTR: + case HB_WIN_DLL_CTYPE_LONG_UNSIGNED_PTR: + case HB_WIN_DLL_CTYPE_VOID_PTR: + case HB_WIN_DLL_CTYPE_FLOAT_PTR: + case HB_WIN_DLL_CTYPE_DOUBLE_PTR: hb_retptr( ( void * ) nRetVal ); break; - case _RETTYPE_FLOAT: - case _RETTYPE_DOUBLE: + case HB_WIN_DLL_CTYPE_FLOAT: + case HB_WIN_DLL_CTYPE_DOUBLE: hb_retnd( HB_GET_LE_DOUBLE( ( HB_BYTE * ) &nRetVal ) ); break; @@ -694,9 +655,9 @@ static void hb_DllExec( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC l ret.t.n64 = 0; - if( iRetType == _RETTYPE_DOUBLE ) + if( iRetType == HB_WIN_DLL_CTYPE_DOUBLE ) iRetTypeRaw = _RETTYPERAW_DOUBLE; - if( iRetType == _RETTYPE_FLOAT ) + if( iRetType == HB_WIN_DLL_CTYPE_FLOAT ) iRetTypeRaw = _RETTYPERAW_FLOAT; else iRetTypeRaw = _RETTYPERAW_INT32; @@ -725,7 +686,7 @@ static void hb_DllExec( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC l rawpar[ iParamsRaw++ ] = r2; } - if( iCallConv == _CALLCONV_CDECL ) + if( iCallConv == HB_WIN_DLL_CALLCONV_CDECL ) { switch( iRetTypeRaw ) { @@ -1030,59 +991,59 @@ static void hb_DllExec( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC l { /* TODO: Add 64-bit integer support */ - case _RETTYPE_VOID: + case HB_WIN_DLL_CTYPE_VOID: hb_ret(); break; - case _RETTYPE_BOOL: + case HB_WIN_DLL_CTYPE_BOOL: hb_retl( ret.t.n32 != 0 ); break; - case _RETTYPE_CHAR: - case _RETTYPE_UNSIGNED_CHAR: + case HB_WIN_DLL_CTYPE_CHAR: + case HB_WIN_DLL_CTYPE_CHAR_UNSIGNED: hb_retni( ( int ) ( ret.t.n32 & 0xFF ) ); break; - case _RETTYPE_SHORT: - case _RETTYPE_UNSIGNED_SHORT: - case _RETTYPE_INT: + case HB_WIN_DLL_CTYPE_SHORT: + case HB_WIN_DLL_CTYPE_SHORT_UNSIGNED: + case HB_WIN_DLL_CTYPE_INT: hb_retni( ( int ) ret.t.n32 ); break; - case _RETTYPE_LONG: + case HB_WIN_DLL_CTYPE_LONG: hb_retnl( ( long ) ret.t.n32 ); break; - case _RETTYPE_UNSIGNED_INT: - case _RETTYPE_UNSIGNED_LONG: + case HB_WIN_DLL_CTYPE_INT_UNSIGNED: + case HB_WIN_DLL_CTYPE_LONG_UNSIGNED: hb_retnint( ret.t.n32 ); break; - case _RETTYPE_CHAR_PTR: - case _RETTYPE_UNSIGNED_CHAR_PTR: + case HB_WIN_DLL_CTYPE_CHAR_PTR: + case HB_WIN_DLL_CTYPE_CHAR_UNSIGNED_PTR: if( wcall.bUNICODE ) hb_retstr_u16( HB_CDP_ENDIAN_NATIVE, ( const HB_WCHAR * ) ret.t.n32 ); else hb_retstr( hb_setGetOSCP(), ( const char * ) ret.t.n32 ); break; - case _RETTYPE_INT_PTR: - case _RETTYPE_UNSIGNED_SHORT_PTR: - case _RETTYPE_UNSIGNED_INT_PTR: - case _RETTYPE_STRUCTURE_PTR: - case _RETTYPE_LONG_PTR: - case _RETTYPE_UNSIGNED_LONG_PTR: - case _RETTYPE_VOID_PTR: - case _RETTYPE_FLOAT_PTR: - case _RETTYPE_DOUBLE_PTR: + case HB_WIN_DLL_CTYPE_INT_PTR: + case HB_WIN_DLL_CTYPE_SHORT_UNSIGNED_PTR: + case HB_WIN_DLL_CTYPE_INT_UNSIGNED_PTR: + case HB_WIN_DLL_CTYPE_STRUCTURE_PTR: + case HB_WIN_DLL_CTYPE_LONG_PTR: + case HB_WIN_DLL_CTYPE_LONG_UNSIGNED_PTR: + case HB_WIN_DLL_CTYPE_VOID_PTR: + case HB_WIN_DLL_CTYPE_FLOAT_PTR: + case HB_WIN_DLL_CTYPE_DOUBLE_PTR: hb_retptr( ( void * ) ret.t.n32 ); break; - case _RETTYPE_FLOAT: + case HB_WIN_DLL_CTYPE_FLOAT: hb_retnd( ret.t.nFL ); break; - case _RETTYPE_DOUBLE: + case HB_WIN_DLL_CTYPE_DOUBLE: hb_retnd( ret.t.nDB ); break; @@ -1143,24 +1104,7 @@ static void hb_DllExec( int iCallConv, int iRetType, HB_BOOL bUNICODE, FARPROC l /* ------------------------------------------------------------------ */ -static HB_GARBAGE_FUNC( _DLLUnload ) -{ - PHB_DLLEXEC xec = ( PHB_DLLEXEC ) Cargo; - - if( xec->hDLL && xec->bFreeDLL ) - { - FreeLibrary( xec->hDLL ); - xec->hDLL = NULL; - } -} - -static const HB_GC_FUNCS s_gcDllFuncs = -{ - _DLLUnload, - hb_gcDummyMark -}; - -static FARPROC hb_getprocaddress( HMODULE hDLL, int iParam, HB_BOOL * pbUNICODE ) +FARPROC hbwin_getprocaddress( HMODULE hDLL, int iParam, HB_BOOL * pbUNICODE ) { #if defined( HB_OS_WIN_CE ) void * hStr; @@ -1241,7 +1185,7 @@ HB_FUNC( GETPROCADDRESS ) else hDLL = ( HMODULE ) hb_parptr( 1 ); - hb_retptr( hDLL ? ( void * ) hb_getprocaddress( hDLL, 2, NULL ) : NULL ); + hb_retptr( hDLL ? ( void * ) hbwin_getprocaddress( hDLL, 2, NULL ) : NULL ); } #ifdef HB_COMPAT_XPP @@ -1249,6 +1193,33 @@ HB_FUNC( GETPROCADDRESS ) /* NOTE: I'm not totally familiar with how Xbase++ works. This functionality was derived from the context in which the functions are used. [pt] */ +typedef struct +{ + HMODULE hDLL; /* Handle */ + HB_BOOL bFreeDLL; /* Free library handle on destroy? */ + int iCallConv; + int iRetType; + HB_BOOL bUNICODE; + FARPROC lpFunction; /* Function Address */ +} HB_DLLEXEC, * PHB_DLLEXEC; + +static HB_GARBAGE_FUNC( _DLLUnload ) +{ + PHB_DLLEXEC xec = ( PHB_DLLEXEC ) Cargo; + + if( xec->hDLL && xec->bFreeDLL ) + { + FreeLibrary( xec->hDLL ); + xec->hDLL = NULL; + } +} + +static const HB_GC_FUNCS s_gcDllFuncs = +{ + _DLLUnload, + hb_gcDummyMark +}; + HB_FUNC( DLLLOAD ) { HB_FUNC_EXEC( LOADLIBRARY ); @@ -1261,33 +1232,36 @@ HB_FUNC( DLLUNLOAD ) HB_FUNC( DLLCALL ) { - HB_DLLEXEC xec; - - memset( &xec, 0, sizeof( xec ) ); + HMODULE hDLL; if( HB_ISPOINTER( 1 ) ) - xec.hDLL = ( HMODULE ) hb_parptr( 1 ); + hDLL = ( HMODULE ) hb_parptr( 1 ); else if( HB_ISNUM( 1 ) ) - xec.hDLL = ( HMODULE ) ( HB_PTRDIFF ) hb_parnint( 1 ); + hDLL = ( HMODULE ) ( HB_PTRDIFF ) hb_parnint( 1 ); else if( HB_ISCHAR( 1 ) ) { void * hFileName; - xec.hDLL = LoadLibrary( HB_PARSTR( 1, &hFileName, NULL ) ); + hDLL = LoadLibrary( HB_PARSTR( 1, &hFileName, NULL ) ); hb_strfree( hFileName ); } + else + hDLL = NULL; - if( xec.hDLL && ( HB_PTRDIFF ) xec.hDLL >= 32 ) + if( hDLL && ( HB_PTRDIFF ) hDLL >= 32 ) { HB_BOOL bUNICODE; + FARPROC lpFunction = hbwin_getprocaddress( hDLL, 3, &bUNICODE ); - xec.lpFunction = hb_getprocaddress( ( HMODULE ) xec.hDLL, 3, &bUNICODE ); - xec.iCallConv = HB_ISNUM( 2 ) ? hb_parni( 2 ) : _CALLCONV_STDCALL; - xec.bUNICODE = bUNICODE; - - hb_DllExec( 0, 0, HB_FALSE, NULL, &xec, hb_pcount(), 4 ); + hbwin_dllCall( HB_ISNUM( 2 ) ? hb_parni( 2 ) : HB_WIN_DLL_CALLCONV_STDCALL, + HB_WIN_DLL_CTYPE_DEFAULT, + bUNICODE, + lpFunction, + hb_pcount(), + 4, + NULL ); if( HB_ISCHAR( 1 ) ) - FreeLibrary( xec.hDLL ); + FreeLibrary( hDLL ); } } @@ -1316,10 +1290,10 @@ HB_FUNC( DLLPREPARECALL ) if( xec->hDLL ) { HB_BOOL bUNICODE; - xec->lpFunction = hb_getprocaddress( xec->hDLL, 3, &bUNICODE ); + xec->lpFunction = hbwin_getprocaddress( xec->hDLL, 3, &bUNICODE ); if( xec->lpFunction ) { - xec->iCallConv = HB_ISNUM( 2 ) ? hb_parni( 2 ) : _CALLCONV_STDCALL; + xec->iCallConv = HB_ISNUM( 2 ) ? hb_parni( 2 ) : HB_WIN_DLL_CALLCONV_STDCALL; xec->bUNICODE = bUNICODE; hb_retptrGC( xec ); @@ -1340,26 +1314,45 @@ HB_FUNC( DLLEXECUTECALL ) PHB_DLLEXEC xec = ( PHB_DLLEXEC ) hb_parptrGC( &s_gcDllFuncs, 1 ); if( xec && xec->hDLL && xec->lpFunction ) - hb_DllExec( 0, 0, HB_FALSE, NULL, xec, hb_pcount(), 2 ); + { + hbwin_dllCall( xec->iCallConv, + xec->iRetType, + xec->bUNICODE, + xec->lpFunction, + hb_pcount(), + 2, + NULL ); + } } #endif /* HB_COMPAT_XPP */ /* ------------------------------------------------------------------ */ -/* Call a DLL function from Harbour, the first parameter is a pointer returned from - GetProcAddress() above. Note that it is hardcoded to use PASCAL calling convention. */ -HB_FUNC( CALLDLL ) +HB_FUNC( WIN_DLLCALL ) { - hb_DllExec( _CALLCONV_STDCALL, 0 , HB_FALSE, ( FARPROC ) hb_parptr( 1 ), NULL, hb_pcount(), 2 ); -} + PHB_ITEM pParam = hb_param( 1, HB_IT_ARRAY ); + int iFirst = 1; -HB_FUNC( CALLDLLBOOL ) -{ - hb_DllExec( _CALLCONV_STDCALL, _RETTYPE_BOOL, HB_FALSE, ( FARPROC ) hb_parptr( 1 ), NULL, hb_pcount(), 2 ); -} + int iCallConv = HB_WIN_DLL_CALLCONV_STDCALL; + int iRetType = HB_WIN_DLL_CTYPE_DEFAULT; + HB_BOOL bUNICODE = HB_FALSE; -HB_FUNC( CALLDLLTYPED ) -{ - hb_DllExec( _CALLCONV_STDCALL, hb_parni( 2 ), HB_FALSE, ( FARPROC ) hb_parptr( 1 ), NULL, hb_pcount(), 3 ); + if( pParam ) + { + HB_SIZE nLen = hb_arrayLen( pParam ); + + ++iFirst; + + if( nLen >= 1 && HB_IS_NUMERIC( hb_arrayGetItemPtr( pParam, 1 ) ) ) + iCallConv = hb_arrayGetNI( pParam, 1 ); + if( nLen >= 2 && HB_IS_NUMERIC( hb_arrayGetItemPtr( pParam, 2 ) ) ) + iRetType = hb_arrayGetNI( pParam, 2 ); + if( nLen >= 3 && HB_IS_LOGICAL( hb_arrayGetItemPtr( pParam, 3 ) ) ) + bUNICODE = hb_arrayGetL( pParam, 3 ); + + /* TODO: Allow to specify parameter types, too */ + } + + hbwin_dllCall( iCallConv, iRetType, bUNICODE, ( FARPROC ) hb_parptr( iFirst ), hb_pcount(), iFirst + 1, NULL ); }