2016-12-03 46 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的調用。當我必須進行大量的動態加載時,我使用了一系列相當複雜的包裝宏,主要是因爲它簡化了我必須編寫的代碼量並減少了出錯的機率。但在這樣的簡單場景中並不需要它。 –