c ++:将.dll加载到新进程

时间:2014-06-27 06:31:53

标签: c++ dll process

我们有一个基于插件的应用程序。每个插件都导出到动态库。由于某些原因,我们必须将每个插件作为一个新进程运行(每个插件都需要单独的可执行文件)。因此,我们要将.dll导出到一个新流程。

每个插件都包含构造函数,析构函数和一些函数。 如果没有导出,它就会以这种方式运行得很好(简化代码):

HINSTANCE lib = LoadLibrary(boost_path_to_dll);
// load the plugin class interface from the library using its factory functions
typedef fooClass *(*CreatePluginFuncDef)();
// pointer to constructor inside of plugin
CreatePluginFuncDef createPtr = (CreatePluginFuncDef)GetProcAddress(lib, "Create");
// pointer to destructor inside of plugin
typedef void(*DestroyPluginFuncDef)(fooClass*);
DestroyPluginFuncDef destroyPtr = (DestroyPluginFuncDef)GetProcAddress(lib, "Destroy");

// create new object
a = boost::shared_prt<fooClass>(pluginCreateFactoryPtr(), DestroyPluginFuncDef);

a->callSomeFunctionFromPlugin();

现在应该将插件导出到新进程。在网上,我发现了Wanderley Caloni Jr。的这个例子:

    /**
* Run CreateProcess with specified parameters and get handle that allows
* to allocate memory and to run threads for this process.
*/
CreateAndGetProcessGodHandle(
    LPCTSTR lpApplicationName,
    LPTSTR lpCommandLine
    )
{
    HANDLE hRet = NULL;
    STARTUPINFO si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    TCHAR tzApplicationName[MAX_PATH] = _T("");
    BOOL bRes;

    // If string are empty, invalidate pointer and use the lpCommandLine.
    if (lpApplicationName && !*lpApplicationName)
        lpApplicationName = NULL;
    else
        ExpandEnvironmentStrings(lpApplicationName,
        tzApplicationName,
        sizeof(tzApplicationName));

    bRes =
        CreateProcess(*tzApplicationName ? tzApplicationName : lpApplicationName,
        lpCommandLine,
        NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL,
        &si, &pi);

    if (bRes != FALSE)
    {
        hRet = OpenProcess(PROCESS_CREATE_THREAD |
            PROCESS_QUERY_INFORMATION |
            PROCESS_VM_OPERATION |
            PROCESS_VM_WRITE |
            PROCESS_VM_READ,
            TRUE,
            pi.dwProcessId);

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

    return hRet;
}

   /**
* Load DLL in another process.
*/
RemoteLoadLibrary(
    HANDLE hProcess,
    LPCTSTR lpFileName
    )
{
    LPCSTR tzLoadLibrary =
#ifdef UNICODE
        "LoadLibraryW"
#else
        "LoadLibraryA"
#endif
        ;

    HMODULE hRet = NULL;
    TCHAR tzFileName[MAX_PATH] = { 0 };
    LPVOID lpCodeMem;
    SIZE_T stCodeMem;

    // Make a safe copy of the module path to be opened.
    StringCbCopy(tzFileName, sizeof(tzFileName), lpFileName);

    // Allocate memory in the another process.
    stCodeMem = (_tcslen(tzFileName) + 1) * sizeof(TCHAR);
    lpCodeMem = VirtualAllocEx(hProcess,
        NULL,
        stCodeMem,
        MEM_COMMIT,
        PAGE_EXECUTE_READWRITE);

    if (lpCodeMem != NULL)
    {
        // Write tzFileName in the allocated memory in the another process.
        if (WriteProcessMemory(hProcess,
            lpCodeMem,
            tzFileName,
            stCodeMem,
            &stCodeMem))
        {
            HANDLE hThr;
            DWORD dwThrId;
            FARPROC fpLoadLibrary;

            fpLoadLibrary =
                GetProcAddress(GetModuleHandle(_T("Kernel32")), tzLoadLibrary);

            // Create remote thread that loads the tzFileName module.
            hThr =
                CreateRemoteThread(hProcess,
                NULL,
                0,
                (LPTHREAD_START_ROUTINE)fpLoadLibrary,
                (LPVOID)lpCodeMem,
                0,
                &dwThrId);

            if (hThr != NULL)
            {
                // Get address where the module was loaded.
                WaitForSingleObject(hThr, INFINITE);
                GetExitCodeThread(hThr, (LPDWORD)&hRet);
                CloseHandle(hThr);
            }
        }

        VirtualFreeEx(hProcess, lpCodeMem, 0, MEM_RELEASE);
    }

    return hRet;
}

并在代码中使用它(再次简化):

//typedef HINSTANCE HMODULE;  /* HMODULEs can be used in place of HINSTANCEs */    

int iRet = 0;
TCHAR tzProgPath[MAX_PATH] = _T("%ComSpec%");
TCHAR tzProgArgs[MAX_PATH] = _T("");
TCHAR tzDllPath[MAX_PATH] = _T("paht_to_my_dll");
int opt;

/** Load DLL in another process. */
HANDLE hProc;

// Start process and get handle with powers.
// Starts cmd ( do you know, how to start it hidded ?! )
hProc = CreateAndGetProcessGodHandle(tzProgPath, tzProgArgs);

// edit:
// old post: seems to work properly ( not sure about it )
// new post: hDll has value 0x59a80000{unused=???}, but should know about loaded
// plugin ( so, the problem is inside of  RemoteLoadLibrary() )
HMODULE hDll = RemoteLoadLibrary(hProc, tzDllPath);

// edit:
// old post: and from here the part, which is not working ( crash by this call )
// new post: no crash, but the createPrt has value = 0 

// load the plugin class interface from the library using its factory functions
typedef fooClass *(*CreatePluginFuncDef)();
// pointer to constructor inside of plugin
CreatePluginFuncDef createPtr = (CreatePluginFuncDef)GetProcAddress(hDll, "Create");

// pointer to destructor inside of plugin
typedef void(*DestroyPluginFuncDef)(fooClass*);
DestroyPluginFuncDef destroyPtr = (DestroyPluginFuncDef)GetProcAddress(hDll, "Destroy");
...
你能看出我的错误吗? (也许不可能以这种方式调用dll函数?!)

您是否知道将dll导出到新流程的更好解决方案?

谢谢!

干杯 亚历克斯。

0 个答案:

没有答案