一个进程内有:
模块A(a.dll),有一个函数f();
模块B(b.dll);
模块C(c.dll);
还有自己X(x.exe);大家知道GetModuleHandle(NULL)可以返回创建进程的模块,这个例子里就是X。
但是当模块B或C调用模块A的f()函数时,f()函数体里如何得调用者模块的HMODULE?

解决方案 »

  1.   

    补充:f()是不知道B或C模块的名字(b.dll/c.dll)的,否则就可以用GetModuleHandle("b.dll")来获取了
      

  2.   

    按我理解你的意思作一下回答模块B/C调用f()函数,f()函数根本就不知道模块B/C的HMODULE,也不需要知道。只要模块B/C知道模块A的HMODULE就行了,也就是说模块A没必要知道模块B/C的HMODULE。除非你在你的DLL里面的DLLMAIN函数里面获取HINSTANCE也就是你所说的调用者的HMODULE了,只要
    (HMODULE)Hinstance进行转换就行了
      

  3.   

    _AFX_THREAD_STATE *pafxState = AfxGetThreadState(); CWinApp *pPreApp = pafxState->m_pModuleState->m_pCurrentWinApp;其中pPreApp 就是前一个运行的程序的theapp,不过这个方法只是在mfc dll试验过
      

  4.   

    只有在进程载入dll时,或dll已被载入后进程里又创建了一个新线程的时候,以及线程退出、进程退出时才调用DllMain()而DllMain()的这个hInstance只是dll自己被载入后的HMODULE,跟本不是其他模块的HMODULE。所以 maijian(asmvc) 回答不正确,同样  holyeagle(一杯清茶)  答不对题。
      

  5.   

    我想如果有了theapp,得到相应的模块的句柄应该不是问题啊。CWinApp::m_hInstance就是app的模块的句柄。
      

  6.   

    在B/C调用a中函数的时候,能不能把自己的句柄作为参数传过去?
      

  7.   

    re: 我想如果有了theapp,得到相应的模块的句柄应该不是问题啊。CWinApp::m_hInstance就是app的模块的句柄。不是问题?那到底怎么获得啊?又不知道b/c模块名。不能传参数,因为b/c模块是别人写好的dll。
      

  8.   

    为什么不考虑把module handle作为参数传给f()呢
      

  9.   

    theapp.m_hInstance就是实例句柄吧。
      

  10.   

    如果是DEBUG版本,可以用StackWalk取得,Release版本有点难。
      

  11.   

    to:  msdn_user(蓝天) 
        其实f()模块是注入别人的进程里的,所以你要别人进程里的其他模块传module handle给f()是不可能的。to:  holyeagle(一杯清茶) 
        theApp.m_hInstance是进程实例句柄没错,也是进程exe文件模块句柄也没错,
    但我不是要这个, 你怎么还不知道问题呢!to:  DentistryDoctor(牙科医生)
         回答对口了,但是看来不简单,有没有简单点的?
      

  12.   

    不是exe的,是上一级调用者的。比如在一级dll中可以得到的就是exe,二级就是上一级调用dll的句柄
      

  13.   

    可以分析内存实例的PE结构,得到静态联编的各dll模块的HMODULE。但动态装载的,就没法了。不过还可以在进程地址空间内搜索“MZ”PE标志,再进一步得分析是否是一个PE模块。进程地址空间内,可以先分析内存块的属性,只分析只读和可执行的代码块。总之,在知道了各模块的起始地址后,要得到F()函数是由哪个模块调用的,我想还是只有分析堆栈中的调用地址了,知道调用地址,就可以知道它此次调用属于哪个模块了。
      

  14.   

    可能MS有特别的,或是未公开的(我反正不知道)函数,直接从系统数据结构中查到各个模块。但要得到调用模块,还是只有查堆栈,除非在EXE中有输出的调试信息内有。
      

  15.   

    调用地址是调用者call时候被push进去的返回地址吗?
    如何获得?如果能准确获得的话就一切ok了,
    因为以下函数能根据地址得到地址所在的模块:HMODULE ModuleFromAddress(LPVOID lpv)
    {
    MEMORY_BASIC_INFORMATION mbi;
    memset(&mbi, 0, sizeof(mbi));
    return VirtualQuery(lpv, &mbi, sizeof(mbi)) ? (HMODULE)mbi.AllocationBase : NULL;
    }
      

  16.   

    是啊,不过要知道函数的调用约定才行,压栈会不一样。跟踪一下代码就行了,计算参数的地址,根据ESP和EBP就可以得到的
      

  17.   

    用ModuleFromAddress可能直接得到HMOULE,很有意思,不用玫举模块了。
    f是你自已写的,你当然知道调用方式和参数
    插汇编,直接使用esp,加上参数,加上你的局部变量就可以得到调用函数地址了
      

  18.   

    void __stdcall f(int a)
    {
        struct {
           int m1;
           char *m2;
        } v;    //这种情况下如何计算返回地址?
        //麻烦给个sample code吧,asm我已经不熟了啊
    }
      

  19.   

    DLL2EXP void DLL_ShowMsg(DWORD *pParentWnd, BYTE dwSize)
    {
    LPDWORD pdwPtr = NULL;

    // Get parent address
    _asm
    {
    mov EAX, dword ptr [ebp+4]
    mov dword ptr [ebp-4], EAX
    }

    HMODULE hParent = ModuleFromAddress((LPVOID)pdwPtr);

    MessageBox(NULL,"Test", NULL, MB_OK);
    }
    注意LPDWORD pdwPtr = NULL;前不要加参数,不然pdwPtr得不到地址.
      

  20.   

    这个用很简单的方法就能实现,虽然不知道是b,还是c调用了f(),但是你可以在f()的入参里面指明是b模块还是c模块对它进行了调用。为什么一定要搞的这么复杂呢?