From 8a2c2d71bd2b9529a9537a85adfb696560c13719 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Fri, 12 Feb 2010 11:27:02 +0000 Subject: [PATCH] 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. --- harbour/ChangeLog | 35 +++ harbour/config/wce/mingwarm.mk | 5 +- harbour/config/win/mingw.mk | 5 +- harbour/contrib/hbwin/hbwin.ch | 37 ++- harbour/contrib/hbwin/hbwin.h | 3 + harbour/contrib/hbwin/legacycd.c | 22 ++ harbour/contrib/hbwin/tests/testdll.prg | 8 +- harbour/contrib/hbwin/win_dll.c | 293 ++++++++++++------------ 8 files changed, 246 insertions(+), 162 deletions(-) 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 ); }