带有功能指针的Typedef:函数不存在

TypeDef with Function Pointer: Function does not Exist

本文关键字:函数 不存在 Typedef 功能 指针      更新时间:2023-10-16

问题是在不存在请求功能的旧计算机上运行代码。要检查它,请使用此处所示的LoadLibraryGetProcAddress,但是GetProcAddress在使用之前需要TypeDef中的函数地址。
例如,将这两个在例如XP SP2 32位上进行:

typedef BOOL (__stdcall *LPFN_Wow64RevertWow64FsRedirection) (PVOID OldValue);
typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
...
...
LPFN_Wow64RevertWow64FsRedirection wowRevert = NULL;
LPFN_Wow64DisableWow64FsRedirection wowDisable = NULL;
HINSTANCE hLib;
if(GetProcAddresses( &hLib, "kernel32.dll", 2, &wowRevert,_ 
"Wow64RevertWow64FsRedirection", &wowDisable, Wow64DisableWow64FsRedirection" ))
{...

代码在此处崩溃:

过程输入点WOW64REVERTWOW64FSREDIRECTIONT无法位于Dynamic Link库中kernel32.dll

使用非Winapi typedefs实现我们自己的自定义Wow64RevertWow64FsRedirection,但是当函数存在于kernel32.dll中时,如何将其替换为基本类型?

我遇到了一些麻烦,了解您的问题。Wow64RevertWow64FsRedirection功能显然在32位操作系统上不存在,因此在32位Windows XP上不存在。因此,尝试通过GetProcAddress检索该功能的指针将失败。您会发现找不到此入口点的明智错误。如果找不到入口点,则该函数不存在,您不应尝试调用它。

您声称可以实现自己的自定义Wow64RevertWow64FsRedirection功能,但是我不知道为什么要这样做。如果操作系统支持WOW64文件系统重定向,则将提供Wow64RevertWow64FsRedirection功能。如果没有,则不会提供该功能,但是您不需要这样的功能,因为没有WOW64文件系统重定向的内容。您无需启用,禁用或恢复它。

看来,您使这比需要的要复杂得多。您甚至不需要首先验证该过程是一个64位过程。您可以尝试将入口点定位到Wow64RevertWow64FsRedirection(或根据需要的Wow64DisableWow64FsRedirection),如果存在,则将其调用,或者如果失败不存在,则忽略了。

这很简单:

BOOL RevertWOW64RedirectionIfNecessary(PVOID pOldValue)
{
    typedef BOOL (WINAPI * fnWow64RevertWow64FsRedirection)(PVOID);
    fnWow64RevertWow64FsRedirection pfn =
        reinterpret_cast<fnWow64RevertWow64FsRedirection>(
           reinterpret_cast<void*>(
           GetProcAddress(GetModuleHandle(L"kernel32"),
                          "Wow64RevertWow64FsRedirection")));
    if (pfn)
    {
        // The function exists, so call it through the pointer we obtained.
        return pfn(pOldValue);
    }
    else
    {
        // The function does not exist, so we can't call it.
        // But we don't ever need to call it in such cases,
        // so do nothing and feign success.
        return TRUE;
    }
}

请注意,我正在调用GetModuleHandle功能以检索模块kernel32.dll的手柄(隐含.dll扩展名)。我可以在此处使用GetModuleHandle而不是LoadModule,因为我知道kernel32.dll保证可以始终加载到任何应用程序的过程中。而且由于我使用了GetModuleHandle,所以我也不需要释放模块句柄。

i将结果句柄传递给GetProcAddress函数,以及包含要检索地址的函数/过程的名称的字符串。此功能试图检索该函数的地址,并在其存在时将其返回;否则,它失败并返回null。

我检查一下它是否返回有效的指针,如果是这样,我通过该指针动态调用该功能。否则,它返回了null,这意味着该函数不可用,但是在这种情况下,我们甚至不需要担心它,因此代码只是一个no-op。

至于有趣的演员,请参阅我的答案,其中解释了这个技巧。