getmodulehandleex函数详解

发布时间:2023-05-20

一、函数概述

GetModuleHandleEx函数是Windows操作系统提供的一个函数,用于获取指定模块的句柄。该函数被广泛应用于Windows编程中,是操作系统提供的一个非常强大的函数。

二、函数原型和参数

BOOL GetModuleHandleEx(
 DWORD   dwFlags,
 LPCTSTR lpModuleName,
 HMODULE *phModule
);

GetModuleHandleEx函数的参数如下:

  • dwFlags:一个DWORD类型的标志,标志着以何种方式获取模块句柄。这里可选的常量标志有:GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESSGET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNTGET_MODULE_HANDLE_EX_FLAG_PIN
  • lpModuleName:一个指向字符串的指针,用于指定模块的名字。
  • phModule:一个HMODULE类型的指针,函数返回时用于接收获取到的模块句柄。

三、获取当前进程的模块句柄

使用GetModuleHandleEx函数可以获取当前进程中指定模块的句柄。例如,下面的代码用于获取当前进程中kernel32.dll模块的句柄:

DWORD dwRet = 0;
HMODULE hKernel32 = NULL;
// 获取kernel32模块句柄
dwRet = GetModuleHandleEx(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
    (LPCTSTR)&GetModuleHandleEx,
    &hKernel32);

通过这段代码,我们可以获得当前进程中kernel32模块的句柄。

四、获取其他进程的模块句柄

GetModuleHandleEx函数同样可以用于获取其他进程中指定模块的句柄。为了安全起见,我们需要先打开指定进程的句柄,然后在该进程中调用GetModuleHandleEx函数来获取指定模块的句柄。下面的代码演示了如何获取其他进程中kernel32.dll模块的句柄:

// 首先打开指定进程的句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (NULL == hProcess)
{
    return FALSE;
}
// 在指定进程中获取kernel32模块句柄
dwRet = GetModuleHandleEx(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
    (LPCTSTR)&GetModuleHandleEx,
    &hKernel32);
// 关闭指定进程的句柄
CloseHandle(hProcess);

通过这段代码,我们可以获得指定进程中kernel32模块的句柄。

五、给其他进程增加引用计数

在获取其他进程中指定模块的句柄时,如果我们需要在其他进程中进行操作,首先需要给该句柄增加引用计数。例如,下面的代码演示了如何获取其他进程中的kernel32.dll模块,然后调用其中的函数:

// 首先打开指定进程的句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (NULL == hProcess)
{
    return FALSE;
}
// 在指定进程中获取kernel32模块句柄
dwRet = GetModuleHandleEx(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
    (LPCTSTR)&GetModuleHandleEx,
    &hKernel32);
// 增加引用计数
Module32First(hSnapshot, &me32);
while (Module32Next(hSnapshot, &me32))
{
    if (me32.hModule == hKernel32)
    {
        m_info.th32ModuleID = me32.th32ModuleID; // 模块ID
        m_info.hModule = me32.hModule;           // 模块句柄
        m_info.modBaseAddr = me32.modBaseAddr;   // 模块基址
        m_info.modBaseSize = me32.modBaseSize;   // 模块大小
        HANDLE hModule = OpenProcess(PROCESS_ALL_ACCESS, FALSE, me32.th32ProcessID);
        if (hModule)
        {
            DWORD dwResult = 0;
            // 如果引用计数增加成功,则返回该模块的句柄,否则返回NULL。
            if (TRUE == Module32First(hSnapshot, &me32))
            {
                dwRet = Module32First(hModule, &me32);
                if (dwRet == TRUE)
                {
                    while (TRUE == Module32Next(hModule, &me32))
                    {
                        if (me32.hModule == hKernel32)
                        {
                            HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, me32.th32ProcessID);
                            LoadLibraryA(m_info.szExePath);
                            CloseHandle(hProc);
                            break;
                        }
                    }
                }
            }
            CloseHandle(hModule);
        }
        break;
    }
}
// 关闭指定进程的句柄
CloseHandle(hProcess);

在调用GetModuleHandleEx函数获取模块句柄之后,我们通过Module32FirstModule32Next函数遍历进程模块,找到指定模块。然后我们调用OpenProcess打开该模块所在进程的句柄,并调用LoadLibraryA函数增加该模块的引用计数。增加成功之后,我们就可以在其他进程中安全地访问该模块了。

总结

GetModuleHandleEx函数是Windows操作系统提供的一个非常实用的函数,可以用于获取指定模块的句柄,并且还支持在其他进程中获取句柄并增加引用计数。通过本文的介绍,我们相信大家已经了解了GetModuleHandleEx函数的基本用法,并能够在实际Windows编程中使用它来解决问题。