![]() |
[C] Winapi Call Dynamically and easily
This Small Function Let You call winapi dynamically, without having to define function definition, or writing nonsense wrappers.
Code:
void* DynCall(void *ptr, ...)Code:
DWORD dwResult = DynCall("ntdll.dll","NtUnmapViewOfSection",I think it will be useful to someone. |
Using this with a wrong number of arguments OR screwing up stack (e.g. using wrong calling convention) ... good luck debugging this!
|
when you dont know, number of arguments or calling convention of the function, you should not call that function,
its not for a commercial application (approx no maintainance), its for different scenarios. |
I think the parameter number of arguments is better than 0xb33f. Ex. void* DynCall(void *ptr, int nargs, ...).
More, need checking for 32/64-bit and calling convention (32-bit can be __stdcall, __cdecl, ... 64-bit can be C-D-8-9 ordered registers, ...). |
yes number of arguments would be better, it will help in debugging,
(you can modify the function, i have just given a way to call winapi pure dynamically, which i wa not able to find anywhere) also the function was written for 32bit, no 64bit support but as you posted i got a requirement to port it in 64 bit (coincidence!!) |
It's likely not a good idea.
Any of imported functions must be correctly declared individulally, and thus must be called normally. In addition - without of using __asm directive. In addition2 - repeated calls will be performed much faster. In addition3 - [less or more] universal solution for x32/x64. ..It's likely not a good idea but it works.. --Add-- Add 1st argument of function as enum {C_CALL,STD_CALL} and produce separate __asm code for this conventions ? --Add2-- Quote:
Quote:
|
this code resolves problem when you don't want imports to be created in an executables, you can use getprocaddress and loadlibrary obviously, but using them and declaring each function prototype is very frustrating.
|
@0xalloc: I don't understand what problem this solves in the first place? In which cases do you call an API while at the same time not knowing its function signature? I mean, you cannot even correctly call any API without knowing its signature, i.e., how many bytes to push/pop off the stack?
|
Quote:
|
Quote:
|
Quote:
|
Quote:
It produces even simpler, smaller and clean code. |
Quote:
|
Quote:
:) |
Quote:
|
Quote:
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. |
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. |
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... |
1 Attachment(s)
Quote:
I'm written once more usage example of DynCall(). [minor fixed] See attached archive. Also it is here - Pass: exetools |
Taking what I said previously into account, a much safer variant could look like this:
Code:
template < typename RetType, typename... ArgTypes >Code:
int main() {produces this output: Code:
GetTickCount1: 16462234The 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:
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. |
sorry for taking criticism in a wrong way, thank you, for your valuable opinions, they are appreciated.
appologies |
absolutely no worries :)
|
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.
|
that would be nice.
|
1 Attachment(s)
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:
PHP Code:
PHP Code:
|
just for the fun of it, a c++14 version :)
PHP Code:
PHP Code:
|
What is C++14 specific about this code?
One drawback is that it's not thread safe. |
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 |
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" ;) |
Quote:
|
Quote:
anyways, this should fix it: Code:
static thread_local lib_map libMap;Quote:
|
Well, if the code yields UB, that needs to be fixed since it violates the C++ standard. This code violates assumptions made by the compiler when reasoning about/optimizing your program - I shouldn't have to get your program to crash. Above reasoning should already convince you that this code needs to be fixed.
Also, I would move the caching outside of the function, or simply use a mutex - these are much faster than people usually assume, and always safe. |
i ve never stated that this is thread safe assuming that it is is wrong.
this snippet is thought as c++ type safe replacement for original post. i agree its not production code where youd better use some loader/lib/functor classes but thats not the purpose of these few lines and neither is original post. its rather for quick testing and only requiring copy&paste a few lines of code. fwiw this aint thread safe either: PHP Code:
|
It could be changed to GetModuleHandleEx - but there's probably no point in not calling LoadLibrary directly?
|
if you simply replace it w/ GetModuleHandleEx or LoadLibrary you ll increase lib ref count every call.
|
Which is what you want, unless performance is your top priority (likely isn't). You simply have to make sure to invoke FreeLibrary accordingly. That's why I subsequently proposed to make the actual call through a functor which would invoke FreeLibrary in the destructor.
|
youre mixing stuff up. that GetModuleHandle/LoadLibrary is from original post and thats C, functor in C w/ destructor?
my c++14 version keeps lib ref count constant, thats the sole purpose of the map (what you call 'cache') also you want to keep lib loaded as dlls might have some init/deinit functions or keep some state between calls. so if you want to fix version from original post use GetModuleHandleEx and call FreeLibrary later only if GetModuleHandleEx returned a valid handle. for my c++ version just use thread_local on map like i ve already said before. this will also fix if a dll uses DLL_THREAD_ATTACH which a mutex does not. |
I was referring to the ref count problem: that can be trivially solved by having correct pairing of Load/FreeLibrary (and doing what i proposed earlier with a functor would do the right thing). I do not see how that is solved with the c++14 approach you posted? How are LoadLibrary / FreeLibrary calls matched without leaking library handles?
edit: ah got it, it's the shared pointer that points a custom deleter to FreeLibrary. ok. However, for all practical purposes this just keeps libraries loaded until the thread exits - which may or may not be what you want - you have no control over it. edit2: to clarify, the functor approach was suggested because it inherently avoids unnecessary API lookups, e.g., if you invoke an API in a loop, you'll do the same lookup over and over again because you have coupled lookup with invocation of the API. The functor approach however decouples lookup from invoking, is thread-safe by definition and doesn't need any synchronization mechanisms. |
w/ thread_local its a per thread map and lib is loaded/freed per thread, if that thread exits is see no problem there. OS lib ref count is the same as it was before thread was entered.
well again, this was just a c++ type safe replacement for original post, nothing more nothing less. if you want to do an uber lib loader youre free to do so :) if you want to optimize lookup you could as well just add an optional opaque pointer and store some infos there. e.g.: PHP Code:
|
Quote:
|
| All times are GMT +8. The time now is 11:25. |
Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2026, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX