How to pass arguments to DLL initialization (ex. when loaded via LoadLibrary)?
How could one pass arguments to the initialization function of a DLL loaded via LoadLib开发者_JAVA技巧rary? Is it possible at all? Without resorting to some kind of exported function or shared memory, that is.
There is no direct way.
The easiest may be through environment variables. They can be set easily before calling LoadLibray
with setenv
, and then the DLL (in the same process) can retrieve them with getenv
.
Another possible solution: create a second DLL that only exposes a "setparam" and a "getparam" method, than use it in both the application (setparam) and the dll's DllMain (getparam). In their basic form, the methods are implemented with static variables, but you can use more sophisticated technologies. This solution, although slightly more difficult, has some advantages:
it doesn't use any "global" convention (except the name of the common DLL!)
it doesn't consume possibly limited resources (e.g. environment variables)
it's general: you can use the same DLL wherever you want.
it may be made as powerful and complicated as you need: e.g. you can make it thread-safe if required. It's only a matter of implementation.
Here's a minimal example:
// The "helper" DLL //
static int param;
void setparam(int v) { param = v; }
int getparam(void) { return param; }
// The application //
setparam(12345);
LoadLibrary("TheDLL.dll");
// The DLL to which you want to pass parameters //
BOOL WINAPI DllMain(HINSTANCE h,DWORD re,LPVOID res)
{
int param;
switch (re)
{
case DLL_PROCESS_ATTACH:
param = getparam();
//...
An alternative means
While I'm not quite sure if this falls under "shared memory" (since you can also use this method to send data to DLLs loaded in separate processes, as well)... You could allocate some memory at a specific address using VirtualAllocEx
, pass in a struct containing all the data the DLL will need using WriteProcessMemory
, then lock it with VirtualLock
before loading the DLL.
Then in the DLL's entry point function, I would use VirtualUnlock
, grab that data using ReadProcessMemory
, then VirtualFree
to clean up resources.
Although a bit choppy, this is especially useful if you have more than just a simple string to pass on.
Note that you must have read/write access in the target process for this to work.
Example (pseudo-code)
// YourApp.cpp
struct DataToSend {
int myInt;
char myStr[320];
};
DataToSend m_data = { 1337, "This is a test string...\0" };
// ...
PVOID remoteData = VirtualAllocEx( hTargetProcess, NULL, sizeof(m_data), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( hTargetProcess, remoteData, &m_data, sizeof(m_data), NULL );
VirtualLock( remoteData, sizeof(m_data) );
// Save the address (DWORD) of remoteData to the registry, to a local file, or using setenv as suggested in other answers here
// YourDll.cpp
BOOL APIENTRY DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
DataToSend m_data = {0};
PVOID localData = /* address used in YourApp */ NULL;
//...
VirtualUnlock( localData, sizeof(m_data) );
ReadProcessMemory( hProcess, localData, &m_data, sizeof(m_data), NULL );
VirtualFree( localData, 0, MEM_RELEASE );
}
It is "bad" and "ugly" but you can push arguments on to the stack with in-line ASM before you make your call and pop them back off in much the same way. A very hack-ish solution, but it can work. I only note it because it's POSSIBLE, not because it's a good way to do things.
精彩评论