EXETOOLS FORUM  

Go Back   EXETOOLS FORUM > General > Source Code

Notices

Reply
 
Thread Tools Display Modes
  #16  
Old 04-06-2018, 07:08
dosprog dosprog is offline
Friend
 
Join Date: Feb 2018
Posts: 61
Rept. Given: 0
Rept. Rcvd 7 Times in 6 Posts
Thanks Given: 23
Thanks Rcvd at 71 Times in 34 Posts
dosprog Reputation: 7
Quote:
Originally Posted by 0xall0c View Post
see the function prototype you defined, when there are lot functions to call, that's an extra headache.
It's programming..

In MASM32 we can invoke function using prototype or call function without prototype.
I tend to use the invoke.
It is convenient, however it is necessary to get used to.



Last edited by dosprog; 04-06-2018 at 07:17.
Reply With Quote
  #17  
Old 04-06-2018, 15:44
0xall0c 0xall0c is offline
Friend
 
Join Date: Mar 2018
Posts: 23
Rept. Given: 0
Rept. Rcvd 2 Times in 2 Posts
Thanks Given: 21
Thanks Rcvd at 16 Times in 9 Posts
0xall0c Reputation: 2
its just one more way to call api's, i am just saying use it if you want to else dont. i never said it is the best way to call an api, it is just another way. as i said previously it is subjective you like your own way of programming same way everyone like thiers.

IT IS JUST ONE ANOTHER WAY OF DOING IT.
Reply With Quote
The Following 2 Users Say Thank You to 0xall0c For This Useful Post:
dosprog (04-06-2018), niculaita (04-06-2018)
  #18  
Old 04-06-2018, 16:50
mcp mcp is offline
Friend
 
Join Date: Dec 2011
Posts: 72
Rept. Given: 4
Rept. Rcvd 12 Times in 11 Posts
Thanks Given: 6
Thanks Rcvd at 19 Times in 11 Posts
mcp Reputation: 12
Sure, it's another way of doing it (i never questioned that), and I argued rationally why it doesn't give significant benefits, what it's downsides are, and thus why it isn't worth the trouble.
If you don't want your advice to be discussed and have the pros & cons be weighted against each other, then why even post it? This forum obviously should foster technical discussions, which is exactly what i did.

Note that not everyone has the ability to discriminate good from bad solutions, so it's valuable to have these kinds of discussions in order to avoid spreading non-ideal solutions.

Also, no need for screaming...
Reply With Quote
The Following 3 Users Say Thank You to mcp For This Useful Post:
0xall0c (04-06-2018), dosprog (04-06-2018), zeffy (04-11-2018)
  #19  
Old 04-06-2018, 17:45
dosprog dosprog is offline
Friend
 
Join Date: Feb 2018
Posts: 61
Rept. Given: 0
Rept. Rcvd 7 Times in 6 Posts
Thanks Given: 23
Thanks Rcvd at 71 Times in 34 Posts
dosprog Reputation: 7
Quote:
Originally Posted by 0xall0c View Post
IT IS JUST ONE ANOTHER WAY OF DOING IT.
) Ok.
I'm written once more usage example of DynCall(). [minor fixed]

See attached archive.

Also it is here - Pass: exetools


Attached Files
File Type: rar DYNCALL.RAR (12.5 KB, 2 views)

Last edited by dosprog; 04-06-2018 at 17:51.
Reply With Quote
The Following 2 Users Say Thank You to dosprog For This Useful Post:
0xall0c (04-06-2018), tonyweb (05-09-2018)
  #20  
Old 04-06-2018, 17:51
mcp mcp is offline
Friend
 
Join Date: Dec 2011
Posts: 72
Rept. Given: 4
Rept. Rcvd 12 Times in 11 Posts
Thanks Given: 6
Thanks Rcvd at 19 Times in 11 Posts
mcp Reputation: 12
Taking what I said previously into account, a much safer variant could look like this:

Code:
template < typename RetType, typename... ArgTypes >
RetType DynCall(const char* dll_name, const char* api_name, ArgTypes...args) {
  typedef RetType(__stdcall* F)(ArgTypes...);
  HMODULE module = LoadLibrary(dll_name);
  assert(module != INVALID_MODULE_HANDLE && "Failed to load library");
  F fptr = (F)GetProcAddress(module, api_name);
  assert(fptr && "Unable to resolve API");
  return fptr(args...);
}
Usage would look like this:

Code:
int main() {
  std::cout << "GetTickCount1: "
            << DynCal< DWORD >("kernel32.dll", "GetTickCount") << "\n";
  DynCall< VOID, DWORD >("kernel32.dll", "Sleep", 1000);
  std::cout << "GetTickCount2: "
            << DynCall< DWORD >("kernel32.dll", "GetTickCount") << "\n"
}

produces this output:
Code:
GetTickCount1: 16462234
GetTickCount2: 16463250
Press any key to continue . . .
The first template argument specifies the return type of the API, after that you pass the argument types. Note that the function assumes stdcall!

The advantage here is that the compiler does all the type checking for you, so this cannot fail unless you mess up the function prototype itself - but that problem cannot be fixed anyhow unless we're using a correct import library which would defeat the whole purpose of this exercise.

Things to improve:
  • Throw an exception if loading library or resolving the function fails. Alternatively, wrap the result into std:ptional so callers are aware they need to check for error.
  • Add string type as template param so code is agnostic of whether compiled with unicode or MBCS.
  • Invoke FreeLibrary after API was invoked; possibly add an overload that takes an already loaded library handle without freeing it (i.e. do not transfer ownership).

Edit: the template argument do not display correctly due to forum system :/ I fixed it by adding a blank to the template arguments, now it displays correctly.

Last edited by mcp; 04-06-2018 at 18:37.
Reply With Quote
The Following 4 Users Say Thank You to mcp For This Useful Post:
0xall0c (04-06-2018), dosprog (04-06-2018), SLV (05-07-2018), tonyweb (05-09-2018)
  #21  
Old 04-06-2018, 18:05
0xall0c 0xall0c is offline
Friend
 
Join Date: Mar 2018
Posts: 23
Rept. Given: 0
Rept. Rcvd 2 Times in 2 Posts
Thanks Given: 21
Thanks Rcvd at 16 Times in 9 Posts
0xall0c Reputation: 2
sorry for taking criticism in a wrong way, thank you, for your valuable opinions, they are appreciated.

appologies
Reply With Quote
  #22  
Old 04-06-2018, 18:36
mcp mcp is offline
Friend
 
Join Date: Dec 2011
Posts: 72
Rept. Given: 4
Rept. Rcvd 12 Times in 11 Posts
Thanks Given: 6
Thanks Rcvd at 19 Times in 11 Posts
mcp Reputation: 12
absolutely no worries
Reply With Quote
  #23  
Old 04-06-2018, 18:50
mcp mcp is offline
Friend
 
Join Date: Dec 2011
Posts: 72
Rept. Given: 4
Rept. Rcvd 12 Times in 11 Posts
Thanks Given: 6
Thanks Rcvd at 19 Times in 11 Posts
mcp Reputation: 12
Another idea worth exploring could be to return a functor from DynCall (instead of invoking the API directly). The functor would basically just capture the function pointer in the c'tor, and provide an overloaded operator(), so the user could call the same API as often as they like (it would also make the code more readable). The functor could then invoke FreeLibrary in the d'tor to free the OS resources.
Reply With Quote
  #24  
Old 04-06-2018, 19:45
0xall0c 0xall0c is offline
Friend
 
Join Date: Mar 2018
Posts: 23
Rept. Given: 0
Rept. Rcvd 2 Times in 2 Posts
Thanks Given: 21
Thanks Rcvd at 16 Times in 9 Posts
0xall0c Reputation: 2
that would be nice.
Reply With Quote
  #25  
Old 04-09-2018, 08:30
bugficks bugficks is offline
Friend
 
Join Date: Apr 2018
Posts: 8
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 2
Thanks Rcvd at 6 Times in 2 Posts
bugficks Reputation: 0
i have to deal a lot w/ dyn sym libs/calls for my stuff @samygo and came up w/ some self-including .h file.
its basically for *nix but i ve hacked some windows support though not all features are available there

- should compile as C and C++
- type safe
- easy to use (imho)
- supports logging

here some example usage:
PHP Code:
// msvc doesn't support weak linking
#define DYNSYM_LOG __dynsym_log

#define DYNSYM_CALL_DECL WINAPI
#define DYNSYM_H "u32.h"
#include "dynsym.h"

#define DYNSYM_CALL_DECL WINAPI
#define DYNSYM_H "k32.h"
#include "dynsym.h"

void main()
{
    if(
user32_init() > 0)
    {
        
user32.MessageBoxA(0"test""test"0);
        
user32_deinit();
    }
    
    if(
k32_init() > 0)
    {
        
k32.Sleep(0);
        
k32_deinit();
    }

u32.h:
PHP Code:
#ifdef DYNSYM_BEGIN

DYNSYM_BEGIN("user32"user32)
DYNSYM_DEF(intMessageBoxAHWND hWndLPCSTR lpTextLPCSTR lpCaptionUINT uType)
DYNSYM_END(user32)

#endif // #ifdef DYNSYM_BEGIN 
dynsym.h macro hell
PHP Code:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// bugficks@samygo
// (c) 2016 - 2018
//
// License: GPLv3
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//lib_blub.h:
// DYNSYM_BEGIN("lib_blub.so.0", lib_blub)
// supports patterns (glob w/ braces) and colon-separated list of libs
// //DYNSYM_BEGIN("{/usr/lib/{lib_blub.so,lib_bla.so*}}", lib_blub)
// //DYNSYM_BEGIN("lib_blub.so*:lib_bla.so*", lib_blub)
// //DYNSYM_BEGIN("lib_blub.so:lib_blub.so.0:lib_blub.so.1", lib_blub)
// // required symbols
// DYNSYM_DEF(int, func_bla, int)
// DYNSYM_DEF_EX(int, short_bla, func_loooooooong_bla, int)
// //optional symbols
// DYNSYM_OPT(int, func_blub, int)
// DYNSYM_OPT_EX(int, short_blub, func_loooooooong_blub, int)
// DYNSYM_END(lib_blub)
//
// // add additional data to lib_blub structure
//#ifndef DYNSYM_DATA
//#define DYNSYM_DATA \
//    int bla; \
//    void *blub;
//#endif
//
//code:
// #define DYNSYM_H    "lib_blub.h"
// optionally supply a colon-separated list of directories as library search path
// #define DYNSYM_LIB_PATH "/usr/lib:/some/lib/dir"
// #include <samygo/dynsym.h>
//
// lib_blub_init();
// lib_blub.func_bla(0);
// if(lib_blub.func_blub)
//    lib_blub.func_blub(0);
// lib_blub_deinit();

// < 0 : error
// else: num resolved symbols
// int xxx_init();
// int xxx_init_ex(void *lib);
//
// void xxx_deinit();

#ifndef __DYNSYM_DONE_H__

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef DYNSYM_H
#error DYNSYM_H is not defined.
#endif

#ifdef DYNSYM_BEGIN
#undef DYNSYM_BEGIN
#endif

#ifdef DYNSYM_END
#undef DYNSYM_END
#endif

#ifdef DYNSYM_DEF
#undef DYNSYM_DEF
#endif

#ifdef DYNSYM_DEF_EX
#undef DYNSYM_DEF_EX
#endif

#ifdef DYNSYM_VAR
#undef DYNSYM_VAR
#endif

#ifdef DYNSYM_VAR_EX
#undef DYNSYM_VAR_EX
#endif

#ifdef DYNSYM_OPT
#undef DYNSYM_OPT
#endif

#ifdef DYNSYM_OPT_EX
#undef DYNSYM_OPT_EX
#endif

#ifdef DYNSYM_VAR_OPT
#undef DYNSYM_VAR_OPT
#endif

#ifdef DYNSYM_VAR_OPT_EX
#undef DYNSYM_VAR_OPT_EX
#endif

#ifdef DYNSYM_INIT
#undef DYNSYM_INIT
#endif

#ifdef DYNSYM_DEINIT
#undef DYNSYM_DEINIT
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if __DYNSYM_INC_LEVEL == 1
#undef __DYNSYM_INC_LEVEL
#define __DYNSYM_INC_LEVEL 2
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef DYNSYM_DATA
#define DYNSYM_DATA void *_dummy_;
#endif

#define DYNSYM_BEGIN(DLL, STRUCT) \
    
typedef union \
    { \
        
struct \
        { \
            const 
uint32_t nSyms;

#define DYNSYM_END(STRUCT) \
            
DYNSYM_DATA \
        }; \
        
dynsym_tab_t symtab; \
    } 
STRUCT##_t; \
    
DYNSYM_STRUCT_DATA(STRUCT);

#define DYNSYM_DEF(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_DEF_EX(RET, FUNC, NAME, ...) \
    
struct FUNC##_t FUNC; const char *name_##FUNC; };

#define DYNSYM_VAR(TYPE, NAME) \
    
DYNSYM_VAR_EX(TYPENAMENAME)

#define DYNSYM_VAR_EX(TYPE, VNAME, SNAME) \
    
struct TYPE *VNAME; const char *name_##VNAME; };

#define DYNSYM_OPT(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_OPT_EX(RET, FUNC, NAME, ...) \
    
DYNSYM_DEF_EX(RETFUNCNAME__VA_ARGS__)

#define DYNSYM_VAR_OPT(TYPE, NAME) \
    
DYNSYM_VAR_EX(TYPENAMENAME)

#define DYNSYM_VAR_OPT_EX(TYPE, VNAME, SNAME) \
    
DYNSYM_VAR_EX(TYPEVNAMESNAME)

#define DYNSYM_STRUCT_DATA(STRUCT) \
    
typedef struct \
    { \
        
DYNSYM_DATA \
    } 
STRUCT##_data_t;


#include DYNSYM_H

#undef DYNSYM_DATA
#undef DYNSYM_STRUCT_DATA

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#elif __DYNSYM_INC_LEVEL == 2
#undef __DYNSYM_INC_LEVEL
#define __DYNSYM_INC_LEVEL 3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define DYNSYM_BEGIN(DLL, STRUCT) \
    
static STRUCT##_t STRUCT = \
    
{ {\
        (((
sizeof(STRUCT##_t) - sizeof(STRUCT##_data_t)) - sizeof(STRUCT.symtab)) / sizeof(dynsym_sym_t)),

#define DYNSYM_END(STRUCT) \
    
} }; \
    
DYNSYM_INIT(DLLSTRUCT) \
    
DYNSYM_DEINIT(DLLSTRUCT)

#define DYNSYM_DEF(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_DEF_EX(RET, FUNC, NAME, ...) \
    
0#NAME },

#define DYNSYM_VAR(TYPE, NAME) \
    
DYNSYM_VAR_EX(TYPENAMENAME)

#define DYNSYM_VAR_EX(TYPE, VNAME, SNAME) \
    
0#SNAME },

#define DYNSYM_OPT(RET, NAME, ...) \
    
DYNSYM_OPT_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_OPT_EX(RET, FUNC, NAME, ...) \
    
{ (FUNC##_t)eDYNSYM_OPTIONAL, #NAME },

#define DYNSYM_VAR_OPT(TYPE, NAME) \
    
DYNSYM_VAR_OPT_EX(TYPENAMENAME)

#define DYNSYM_VAR_OPT_EX(TYPE, VNAME, SNAME) \
    
{ (TYPE*)eDYNSYM_OPTIONAL#SNAME },


#ifndef DYNSYM_LIB_PATH
#define DYNSYM_LIB_PATH "/lib:/usr/lib"
#endif

#define DYNSYM_INIT(DLL, STRUCT) \
    
static int STRUCT##_init_ex(void *lib) \
    
{ \
        return 
dynsym_init_ex(lib, &STRUCT##_lib, &STRUCT.symtab); \
    
} \
    \
    static 
int STRUCT##_init() \
    
{ \
        return 
dynsym_init(&STRUCT##_lib, &STRUCT.symtab, DYNSYM_LIB_PATH); \
    
}

#define DYNSYM_DEINIT(DLL, STRUCT) \
    
static void STRUCT##_deinit() \
    
{ \
        
dynsym_tab_deinit(&STRUCT##_lib, &STRUCT.symtab); \
        
STRUCT##_lib.lib = 0; \
    
}


#include DYNSYM_H

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#elif __DYNSYM_INC_LEVEL == 3
#define __DYNSYM_DONE_H__

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#else
#define __DYNSYM_INC_LEVEL 1
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __DYNSYM_H__
#define __DYNSYM_H__

#include <stdint.h>
#include <errno.h>

#ifdef _WIN32

#include <windows.h>
#include <tchar.h>
#define  __attribute__(...)
#define PATH_MAX MAX_PATH

enum {
    
RTLD_LAZY 0x0001
};
inline voiddlopen(const char *nint)
{
    return (
void*)LoadLibraryA(n);
}
inline int dlclose(void *h)
{
    return 
FreeLibrary((HMODULE)h) ? : -1;
}
inline voiddlsym(void *h, const char *n)
{
    return (
void*)GetProcAddress((HMODULE)hn);
}

#define LIBRARY_PATH        "PATH"
#define TOKEN_PATH_SPLIT    ";"
#define strtok_r(A, B, C) strtok(A, B)

#else

#include <dlfcn.h>
#include <link.h>
#include <glob.h>

#define LIBRARY_PATH        "LD_LIBRARY_PATH"
#define TOKEN_PATH_SPLIT    ":"

#endif

typedef struct
{
    const 
char *name;//[PATH_MAX];
    
void *lib;
dynsym_lib_t;

typedef struct
{
    
void *fn;
    const 
char *name;
dynsym_sym_t;

typedef struct
{
    
uint32_t nSyms;
    
dynsym_sym_t syms[];
dynsym_tab_t;

typedef enum
{
    
eDYNSYM_DEFAULT       0,
    
eDYNSYM_OPTIONAL      = (<< 0),
    
eDYNSYM_MASK          3,
dynsym_flags_t;

typedef enum
{
    
eDYNSYM_LOG_NONE,
    
eDYNSYM_LOG_ERROR,
    
eDYNSYM_LOG_WARN,
    
eDYNSYM_LOG_INFO,
    
eDYNSYM_LOG_DBG
dynsym_log_level_t;


void dynsym_log(
        
int l, const char *fmt, ...) __attribute__ ((weak));

#ifndef DYNSYM_LOG
#define DYNSYM_LOG(L, ...) \
    
{ \
        if(
dynsym_log) \
            
dynsym_log(L__VA_ARGS__); \
        else \
            
__dynsym_log(L__VA_ARGS__); \
    }
#endif

static void __dynsym_log(
        
int l, const char *fmt, ...)
{
    
va_list ap;
    
va_start(apfmt);
    switch(
l)
    {
        case 
eDYNSYM_LOG_ERROR:
            
printf("[E]");
            break;
        case 
eDYNSYM_LOG_WARN:
            
printf("[W]");
            break;
        case 
eDYNSYM_LOG_INFO:
            
printf("[I]");
            break;
        case 
eDYNSYM_LOG_DBG:
            
printf("[D]");
            break;
        default:
            break;
    }
    
printf("[DYNSYM] ");
    
vprintf(fmtap);
    
va_end(ap);
    
fflush(stdout);
}

static 
inline const char *dynsym_libname(
        const 
dynsym_lib_t *lib)
{
    const 
char *lib_name "(nil)";
    if(!
lib)
        return 
lib_name;
    if(!
lib->name)
        return 
lib_name;
    if(!
lib->name[0])
        return 
lib_name;
    return 
lib->name;
}

static 
int dynsym_tab_init(
        
dynsym_lib_t *libdynsym_tab_t *symtab)
{
    
int n 0;
    const 
char *lib_name dynsym_libname(lib);
    
dynsym_sym_t *syms symtab->syms;
    for(
uint32_t i 0symtab->nSymsi++)
    {
        
uintptr_t flags = (uintptr_t)syms[i].fn;
        
int opt flags eDYNSYM_OPTIONAL;
        
void *fn dlsym(lib->libsyms[i].name);
        if(!
fn)
        {
            
int l opt eDYNSYM_LOG_WARN eDYNSYM_LOG_ERROR;
            
DYNSYM_LOG(l,"dlsym lib: '%s' '%s' failed.\n"lib_namesyms[i].name);
            if(!
opt)
                return -
1;
        }
        else
        {
            
DYNSYM_LOG(eDYNSYM_LOG_INFO,"dlsym lib: '%s' '%s' %p.\n"lib_namesyms[i].namefn);
            
n++;
        }

        
syms[i].fn fn;
    }
    return 
n;
}

static 
void dynsym_tab_deinit(
        
dynsym_lib_t *libdynsym_tab_t *symtab)
{
    
void *_lib lib->lib;
    if(
_lib)
    {
        
lib->lib 0;
        
dynsym_sym_t *syms symtab->syms;
        for(
uint32_t i 0symtab->nSymsi++)
            
syms[i].fn 0;

        
dlclose(_lib);
    }
    const 
char *name lib->name;
    if(
name)
    {
        
lib->name 0;
        
free((void*)name);
    }
}

static 
int dynsym_init_ex(
        
void *libdynsym_lib_t *dynsymlibdynsym_tab_t *symtab)
{
    if(!
lib)
        return -
1;
    if(
dynsymlib->lib)
        return -
1;

    
dynsymlib->lib lib;

#ifndef _WIN32
    
struct link_map *lm 0;
    
dlinfo(libRTLD_DI_LINKMAP, &lm);
    if(
lm && lm->l_name && lm->l_name[0])
        
dynsymlib->name strdup(lm->l_name);
    else if(!
dynsymlib->name || !dynsymlib->name[0])
        
dynsymlib->name realpath(program_invocation_name0);
#else
    
{
        
char tmp[MAX_PATH];
        
memset(tmp0sizeof(tmp));
        if(
GetModuleFileNameA((HMODULE)libtmpARRAYSIZE(tmp)))
            
dynsymlib->name _strdup(tmp);
    }
#endif

    
DYNSYM_LOG(eDYNSYM_LOG_DBG,"lib: '%s' %p.\n"dynsym_libname(dynsymlib), dynsymlib->lib);

    
int n dynsym_tab_init(dynsymlibsymtab);
    return 
n;
}

typedef int (*sgo_log_t)(
        
int l, const char *tag, const char *comp, const char *fmt, ...);

static 
void *dynsym_dlopen(
        const 
char *name_patterndynsym_lib_t *dynsymlib, const char *const _LIB_PATHsgo_log_t logger)
{
    if(!
name_pattern)
    {
        
void *lib dlopen(0RTLD_LAZY);
        return 
lib;
    }

    
char *strtok_name 0;
    
char name_wrk[PATH_MAX];
    
memset(name_wrk0sizeof(name_wrk));
    
strncpy(name_wrkname_patternsizeof(name_wrk));
    const 
char *name strtok_r(name_wrkTOKEN_PATH_SPLIT, &strtok_name);
    while(
name)
    {
        
// no pattern, just use dlopen
        
if(!strpbrk(name"?*[]{}"))
        {
            
void *lib dlopen(nameRTLD_LAZY);
            if(
lib)
                return 
lib;
        }
#ifdef HAVE_GLOB
        // pattern, we need absolute path for dlopen, fill lib search dirs
        
char LIB_PATH[PATH_MAX] = { };
        if(!
strchr(name'/'))
        {
            const 
char *const LD_LIBRARY_PATH getenv(LIBRARY_PATH);

            if(
LD_LIBRARY_PATH && LD_LIBRARY_PATH[0])
                
snprintf(LIB_PATHsizeof(LIB_PATH) - 1"%s:"LD_LIBRARY_PATH);
            
strncat(LIB_PATH_LIB_PATHsizeof(LIB_PATH) - 1);

            
DYNSYM_LOG(eDYNSYM_LOG_DBG"LIB_PATH: '%s'\n"LIB_PATH);
        }

        
char *strtok_dir 0;
        const 
char *libdir strtok_r(LIB_PATHTOKEN_PATH_SPLIT, &strtok_dir);
        
void *lib 0;
        do
        {
            
char libpath[PATH_MAX];
            
memset(libpath0sizeof(libpath));
            if(
libdir)
                
snprintf(libpathsizeof(libpath) - 1"%s/%s"libdirname);
            else
                
strncpy(libpathnamesizeof(libpath) - 1);

            
glob_t blob;
            
int r glob(libpathGLOB_BRACE0, &blob);
            if(
r)
            {
                
DYNSYM_LOG(eDYNSYM_LOG_DBG"glob('%s') failed. [%s]\n"libpathstrerror(ENOENT));
            }
            else
            {
                for(
size_t i 0blob.gl_pathci++)
                {
                    const 
char *name blob.gl_pathv[i];
                    
lib dlopen(nameRTLD_LAZY);
                    if(
lib)
                        break;
                }
            }

            
globfree(&blob);

            if(
lib)
                return 
lib;

            
libdir strtok_r(0TOKEN_PATH_SPLIT, &strtok_dir);
        }
        while(
libdir);
#endif

        
name strtok_r(0TOKEN_PATH_SPLIT, &strtok_name);
    }

    return 
0;
}

static 
int dynsym_init(
        
dynsym_lib_t *dynsymlibdynsym_tab_t *symtab, const char *const LIB_PATH)
{
    
void *lib dynsym_dlopen(dynsymlib->namedynsymlibLIB_PATH0);
    if(!
lib)
    {
        
DYNSYM_LOG(eDYNSYM_LOG_ERROR,"dlopen lib: '%s' failed.\n"dynsym_libname(dynsymlib));
    }

    return 
dynsym_init_ex(libdynsymlibsymtab);
}

#endif // #ifndef __DYNSYM_H__


#ifndef DYNSYM_CALL_DECL
#define DYNSYM_CALL_DECL
#endif

#define DYNSYM_DEF(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_DEF_EX(RET, FUNC, NAME, ...) \
    
typedef RET (DYNSYM_CALL_DECL FUNC##_t)(__VA_ARGS__);

#define DYNSYM_VAR(T, NAME) \
    
DYNSYM_VAR_EX(TVNAMESNAME)

#define DYNSYM_VAR_EX(T, VNAME, SNAME)

#define DYNSYM_OPT(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_OPT_EX(RET, FUNC, NAME, ...) \
    
DYNSYM_DEF_EX(RETFUNCNAME__VA_ARGS__)

#define DYNSYM_VAR_OPT(T, NAME) \
    
DYNSYM_VAR_OPT_EX(TNAMENAME)

#define DYNSYM_VAR_OPT_EX(T, VNAME, SNAME)

#define DYNSYM_BEGIN(DLL, STRUCT) \
    
static dynsym_lib_t STRUCT##_lib = { DLL, 0 };

#define DYNSYM_END(STRUCT)

#include DYNSYM_H

#undef DYNSYM_CALL_DECL

#endif

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#if __DYNSYM_INC_LEVEL < 4
#include "dynsym.h"
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#else // #ifndef __DYNSYM_DONE_H__

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#undef __DYNSYM_DONE_H__

#ifdef DYNSYM_LIB_PATH
#undef DYNSYM_LIB_PATH
#endif

#undef DYNSYM_H
#undef __DYNSYM_INC_LEVEL

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif  // #ifndef __DYNSYM_DONE_H__

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
Attached Files
File Type: zip dynsym.zip (4.1 KB, 1 views)
Reply With Quote
The Following 4 Users Say Thank You to bugficks For This Useful Post:
0xall0c (04-10-2018), emo (04-12-2018), niculaita (04-14-2018), tonyweb (05-09-2018)
  #26  
Old 04-14-2018, 08:39
bugficks bugficks is offline
Friend
 
Join Date: Apr 2018
Posts: 8
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 2
Thanks Rcvd at 6 Times in 2 Posts
bugficks Reputation: 0
just for the fun of it, a c++14 version

PHP Code:
#include <string>
#include <memory>
#include <map>
#include <system_error>

template <typename Ftypename... ArgTypes>
auto DynCallT(LPCTSTR libNameLPCSTR funcNameArgTypes... args)
{
    
using tstring std::basic_string<TCHARstd::char_traits<TCHAR>, std::allocator<TCHAR>>;
    
using lib_ptr std::shared_ptr<std::remove_pointer_t<const HMODULE>>;
    
using lib_map std::map<const tstringlib_ptr>;

    static 
lib_map libMap;

    
HMODULE h nullptr;
    const 
auto &libMap.find(libName);
    if(
!= libMap.end())
        
l->second.get();
    else if((
= ::LoadLibrary(libName)) != nullptr)
        
libMap[libName] = lib_ptr(h, ::FreeLibrary);
    else
        throw 
std::system_error(std::make_error_code(std::errc::invalid_argument));

    
F f reinterpret_cast<F>(::GetProcAddress(hfuncName));
    if(!
f)
        throw 
std::system_error(std::make_error_code(std::errc::function_not_supported));

    return 
f(args...);

usage:
PHP Code:
    // using 'decltype' when you have a prototype 
    
auto r DynCallT<decltype(&MessageBoxA)>(_T("user32"), "MessageBoxA"nullptr"123""321"0);

    
// or using func decl as template arg
    
auto tc1 DynCallT<DWORD(WINAPI*)()>(_T("kernel32"), "GetTickCount");

    
// using "i dont give a shit" decl :)
    
auto tc2 DynCallT<void*(WINAPI*)(...)>(_T("kernel32"), "GetTickCount"1"asd");

    
void WINAPI blub(DWORD);
    
DynCallT<decltype(&blub)>(_T("kernel32"), "Sleep"0); 
Reply With Quote
The Following 2 Users Say Thank You to bugficks For This Useful Post:
niculaita (04-14-2018), tonyweb (05-09-2018)
  #27  
Old 04-14-2018, 18:04
mcp mcp is offline
Friend
 
Join Date: Dec 2011
Posts: 72
Rept. Given: 4
Rept. Rcvd 12 Times in 11 Posts
Thanks Given: 6
Thanks Rcvd at 19 Times in 11 Posts
mcp Reputation: 12
What is C++14 specific about this code?
One drawback is that it's not thread safe.
Reply With Quote
  #28  
Old 04-14-2018, 18:38
bugficks bugficks is offline
Friend
 
Join Date: Apr 2018
Posts: 8
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 2
Thanks Rcvd at 6 Times in 2 Posts
bugficks Reputation: 0
auto as return type is c++14 specific.

well thread safety wasn't my goal but it should be virtually thread safe. i mean the worst thing that can happen is that you replace a already loaded lib which isn't much of a problem
Reply With Quote
  #29  
Old 04-14-2018, 23:40
mcp mcp is offline
Friend
 
Join Date: Dec 2011
Posts: 72
Rept. Given: 4
Rept. Rcvd 12 Times in 11 Posts
Thanks Given: 6
Thanks Rcvd at 19 Times in 11 Posts
mcp Reputation: 12
Ah right, didn't spot auto return type deduction.

Data races yield undefined behavior, so the worst thing that could happen is that this code produces hard to find bugs/crashes. There is no such thing as "virtually thread safe"
Reply With Quote
  #30  
Old 04-15-2018, 11:35
dosprog dosprog is offline
Friend
 
Join Date: Feb 2018
Posts: 61
Rept. Given: 0
Rept. Rcvd 7 Times in 6 Posts
Thanks Given: 23
Thanks Rcvd at 71 Times in 34 Posts
dosprog Reputation: 7
Quote:
Originally Posted by bugficks View Post
auto as return type is c++14 specific.
There is such a thing as the portability of the source code.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On


Similar Threads
Thread Thread Starter Forum Replies Last Post
[C++, WinAPI] Enigma HWID patcher with hardware breakpoints mr.exodia Source Code 1 07-31-2014 11:50
WinAPI: No WM_COMMAND Message? aldente General Discussion 2 07-05-2006 07:17


All times are GMT +8. The time now is 08:13.


ICP05004977
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX