windows 如何将参数传递给 DLL 初始化(例如,通过 LoadLibrary 加载时)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5678357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:39:20  来源:igfitidea点击:

How to pass arguments to DLL initialization (ex. when loaded via LoadLibrary)?

cwindowswinapidll

提问by soze

How could one pass arguments to the initialization function of a DLL loaded via LoadLibrary? Is it possible at all? Without resorting to some kind of exported function or shared memory, that is.

如何将参数传递给通过 LoadLibrary 加载的 DLL 的初始化函数?有可能吗?无需求助于某种导出函数或共享内存,即。

回答by Didier Trosset

There is no direct way.

没有直接的方法。

The easiest may be through environment variables. They can be set easily before calling LoadLibraywith setenv, and then the DLL (in the same process) can retrieve them with getenv.

最简单的方法可能是通过环境变量。他们可以很容易地调用之前设置LoadLibraysetenv,然后DLL(在同一过程中)可以检索它们getenv

回答by RectangleEquals

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 VirtualLockbefore loading the DLL.

  虽然我不太确定这是否属于“共享内存” (因为您也可以使用此方法将数据发送到加载在单独进程中的 DLL,以及)...您可以使用VirtualAllocEx,在特定地址分配一些内存,传入一个包含 DLL 需要使用的所有数据的结构WriteProcessMemory,然后VirtualLock在加载 DLL 之前将其锁定。

Then in the DLL's entry point function, I would use VirtualUnlock, grab that data using ReadProcessMemory, then VirtualFreeto clean up resources.

然后在 DLL 的入口点函数中,我会使用VirtualUnlock,使用获取该数据ReadProcessMemory,然后VirtualFree清理资源。

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...
// 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 );
}
" }; // ... 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

 

 

// 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();
//...

回答by Giuseppe Guerrini

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:

另一种可能的解决方案:创建第二个仅公开“setparam”和“getparam”方法的 DLL,然后在应用程序 (setparam) 和 dll 的 DllMain (getparam) 中使用它。在它们的基本形式中,这些方法是用静态变量实现的,但您可以使用更复杂的技术。这种解决方案虽然稍微困难一些,但有一些优点:

  • 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.

  • 它不使用任何“全局”约定(通用 DLL 的名称除外!)

  • 它不会消耗可能有限的资源(例如环境变量)

  • 这是一般的:您可以在任何地方使用相同的 DLL。

  • 它可以根据您的需要变得强大和复杂:例如,如果需要,您可以使其成为线程安全的。这只是一个实施问题。

Here's a minimal example:

这是一个最小的例子:

##代码##

回答by RobotHumans

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.

它是“坏的”和“丑陋的”,但是您可以在调用之前使用内嵌 ASM 将参数推送到堆栈中,然后以几乎相同的方式将它们弹出。一个非常hack-ish的解决方案,但它可以工作。我注意到它只是因为它是可能的,而不是因为它是一种做事的好方法。