【问题标题】:GetModuleFileNameExA won't work like it should when I try to link the function on runtime from psapi.dll (windows)当我尝试在运行时从 psapi.dll (windows) 链接函数时,GetModuleFileNameExA 将无法正常工作
【发布时间】:2020-12-24 22:31:56
【问题描述】:

我正在尝试在 Windows 上运行时从 dll 加载函数。我试着做一个程序来打印它自己的模块,基于这个:https://docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-modules-for-a-process

我需要两个函数来做我想做的事:EnumProcessModules 和 GetModuleFileNameExA。我设法在运行时从 psapi.dll 获取它们,但是 GetModuleFileNameExA 并不能正常工作,我不知道为什么

这是我写的功能脚本:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <psapi.h>

typedef DWORD (__cdecl *EnumModules)(HANDLE hprocess, HMODULE *moduleHandles, DWORD cb, LPDWORD lpcNeeded);
typedef DWORD (__cdecl *GetModuleName)(HANDLE hprocess, HMODULE hmodule, LPSTR name, DWORD size);

void ErrorMessage(const char *message){
    fprintf(stderr, message);
    exit(EXIT_FAILURE);
}

int PrintModules( HANDLE pHandle )
{
    HMODULE hMods[1024];
    DWORD cbNeeded;
    unsigned int i;

    if (NULL == pHandle)
        return EXIT_FAILURE;

    // Loads the lib
    HMODULE psapiLib = LoadLibrary("C:\\Windows\\SysWOW64\\psapi.dll");
    if(! psapiLib) ErrorMessage("Error loading psapi.dll\n");

    // Get the functions we need from the lib
    EnumModules getModules = (EnumModules)GetProcAddress(psapiLib, "EnumProcessModules");
    GetModuleName getModuleName = (GetModuleName)GetProcAddress(psapiLib, "GetModuleFileNameExA");
    if(!getModules) ErrorMessage("Error finding EnumProcessModules from psapi.dll\n");
    if(!getModuleName) ErrorMessage("Error finding GetModuleFileNameExA from psapi.dll\n");


   // Get a list of all the modules in this process.

    if( getModules(pHandle, hMods, sizeof(hMods), &cbNeeded))
    {
        for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
        {
            LPSTR szModName;
            szModName = malloc(1024 * sizeof(LPSTR));

            // Get the full path to the module's file.

            // change GetModuleFileNameExA with getModuleName to see the error
            if ( GetModuleFileNameExA( pHandle, hMods[i], szModName, 1024 * sizeof(char))){
                // Print the module name and handle value.
                printf(("\t%s (0x%08X)\n"), szModName, hMods[i] );
                
            }

            free(szModName);
        }
    }

    return 0;
}

int main( void )
{
    HANDLE myHandle = GetCurrentProcess();
    PrintModules(myHandle);
    CloseHandle(myHandle);

    return 0;
}

如果我改变这部分

if ( GetModuleFileNameExA( pHandle, hMods[i], szModName, 1024 * sizeof(char))){
                // Print the module name and handle value.
                printf(("\t%s (0x%08X)\n"), szModName, hMods[i] );
                
            }

到这里

if ( getModuleName( pHandle, hMods[i], szModName, 1024 * sizeof(char))){
                // Print the module name and handle value.
                printf(("\t%s (0x%08X)\n"), szModName, hMods[i] );
                
            }

所以它会使用我的函数,而不需要在加载时链接 psapi.dll,它只是不起作用。它要么出现段错误,要么不打印任何东西。我尝试修改我呈现缓冲区的方式,尝试使用 Widechar 或 Tchar 但似乎没有任何效果。

这是我使用功能脚本的输出: working script ouput

这是我的函数的输出: non functional script output

有趣的是,其中一个函数 getModules(指向 EnumProcessModules)工作得非常好!我就是不明白发生了什么。

【问题讨论】:

    标签: c++ winapi dll linker runtime


    【解决方案1】:

    你应该改变这行代码

    typedef DWORD (__cdecl *EnumModules)(HANDLE hprocess, HMODULE *moduleHandles, DWORD cb, LPDWORD lpcNeeded);
    

    到这个。

    typedef DWORD(__stdcall* EnumModules)(HANDLE hprocess, HMODULE* moduleHandles, DWORD cb, LPDWORD lpcNeeded);
    

    更多信息可以参考this

    【讨论】:

    • 也与GetModuleName typedef 相同。几乎所有 Win32 API 函数都使用 __stdcall,唯一的例外是像 wsprintf 这样需要 __cdecl 的函数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多