2016-12-03 72 views
0

问题是在不存在请求的功能的旧机器上运行代码。为了检查它,使用LoadLibraryGetProcAddress,如here所示,但GetProcAddress要求在使用之前在TypeDef中的功能的地址。
例如,以这两个上例如,Windows XP SP2 32位:带功能指针的TypeDef:功能不存在

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")) 
{... 

代码崩溃这里:

程序输入点Wow64RevertWow64FsRedirection不能设在动态链接库的Kernel32。 dll的

这是很容易实现自己的自定义Wow64RevertWow64FsRedirection与非WINAPI类型定义,但他们怎么能与基类型时设定的功能所取代离子存在于kernel32.dll中?

+0

*但GetProcAddress需要函数的地址* - 这是不正确的。 [GetProcAddress](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx)只需要模块句柄和一个字符串。 – PaulMcKenzie

+0

@保罗:帮帮我吧。看着你的[答](http://forums.codeguru.com/showthread.php?247936-Problem-using-GetProcAddress)的方式:这是否仍然适用? –

+0

'GetProcAddress'返回一个指向函数的指针。调用该函数不需要函数指针(除了字符串名称的指针)。 – PaulMcKenzie

回答

1

我在理解你的问题时遇到了一些麻烦。在32位操作系统上显然不存在Wow64RevertWow64FsRedirection函数,因此它在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,所以我也不需要释放模块句柄。

我将生成的句柄传递给GetProcAddress函数,以及一个包含要检索地址的函数/过程的名称的字符串。该函数尝试检索该函数的地址,如果存在则返回该函数;否则,它失败并返回NULL。

我检查,看它是否返回一个有效的指针,如果是这样,我通过该指针动态调用该函数。否则,它会返回NULL,这意味着该功能不可用,但在这种情况下,我们甚至都不需要担心,这样的代码只是成为一个无操作。

至于有趣的铸造,请参阅my answer here,这解释了这个技巧。

+0

OUCH!谷歌搜索几个小时刚刚遇到[this](http://stackoverflow.com/questions/25413612/wow64disablewow64fsredirection-on-32-bit-windows-xp)。但是,谢谢,问题是代码在执行任何WOW64语句之前崩溃了。所以我们假设这与'LPFN_ISWOW64PROCESS'是最初在全球宣布的唯一事情有关。 –

+0

看起来像在[Codeproject](https://www.codeproject.com/Articles/1087/Loading-DLLs-made-easy?)的方法是没用的,不是? –

+0

它确实看起来过于设计了我。在你无法保证你想加载的模块已经加载的情况下,它可能会更有用。这意味着你不能使用'GetModuleHandle',而必须调用'LoadLibrary'。这意味着对FreeLibrary的调用。当我必须进行大量的动态加载时,我使用了一系列相当复杂的包装宏,主要是因为它简化了我必须编写的代码量并减少了出错的几率。但在这样的简单场景中并不需要它。 –