带有函数指针的 TypeDef:函数不存在
TypeDef with Function Pointer: Function does not Exist
问题是 运行 旧机器上的代码不存在请求的函数。要检查它,请使用 LoadLibrary
和 GetProcAddress
,如 here 所示,但 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" ))
{...
此处代码崩溃:
The procedure entry point Wow64RevertWow64FsRedirection could not be located in the dynamic link library Kernel32.dll
使用非 WINAPI typedef 实现我们自己的自定义 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
,所以我也不需要释放模块句柄。
我将生成的句柄连同包含要检索其地址的 function/procedure 名称的字符串一起传递给 GetProcAddress
函数。此函数尝试检索该函数的地址,如果存在则 returns 它;否则,它将失败并且 returns NULL.
我检查它是否返回了一个有效的指针,如果是,我通过该指针动态调用该函数。否则,它返回 NULL,意味着该函数不可用,但在那种情况下,我们甚至不需要担心它,所以代码就变成了空操作。
至于有趣的演员表,请参阅 my answer here,其中解释了这个技巧。
问题是 运行 旧机器上的代码不存在请求的函数。要检查它,请使用 LoadLibrary
和 GetProcAddress
,如 here 所示,但 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" ))
{...
此处代码崩溃:
The procedure entry point Wow64RevertWow64FsRedirection could not be located in the dynamic link library Kernel32.dll
使用非 WINAPI typedef 实现我们自己的自定义 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
,所以我也不需要释放模块句柄。
我将生成的句柄连同包含要检索其地址的 function/procedure 名称的字符串一起传递给 GetProcAddress
函数。此函数尝试检索该函数的地址,如果存在则 returns 它;否则,它将失败并且 returns NULL.
我检查它是否返回了一个有效的指针,如果是,我通过该指针动态调用该函数。否则,它返回 NULL,意味着该函数不可用,但在那种情况下,我们甚至不需要担心它,所以代码就变成了空操作。
至于有趣的演员表,请参阅 my answer here,其中解释了这个技巧。