LoadLibraryExA 函式 (libloaderapi.h)
將指定的模組載入呼叫行程的位址空間。 指定的模組可能會導致其他模組載入。
語法
HMODULE LoadLibraryExA(
[in] LPCSTR lpLibFileName,
HANDLE hFile,
[in] DWORD dwFlags
);
參數
[in] lpLibFileName
字串,指定要載入之模組的檔名。 此名稱與儲存在連結庫模組本身的名稱無關,如 module-definition (.def) 檔案中的 LIBRARY 關鍵詞所指定。
模組可以是連結庫模組(.dll 檔案)或可執行模組(.exe 檔案)。 如果指定的模組是可執行的模組,則不會載入靜態匯入;相反地,模組會載入,就像已指定 DONT_RESOLVE_DLL_REFERENCES 一樣。 如需詳細資訊,請參閱 dwFlags 參數。
如果字串指定沒有路徑且省略擴展名的模組名稱,函式會將默認連結庫擴展名 「.DLL」 附加至模組名稱。 若要防止函式將 「.DLL」 附加至模組名稱,請在模組名稱字串中包含尾端點字元 (.. )。
如果字串指定完整路徑,函式只會搜尋該模組的路徑。 指定路徑時,請務必使用反斜杠 (\),而不是正斜線 (/)。 如需路徑的詳細資訊,請參閱 命名檔案、路徑和命名空間。
如果字串指定沒有路徑的模組名稱,且多個載入的模組具有相同基底名稱和延伸模組,則函式會傳回第一次載入的模組句柄。
如果字串指定了沒有路徑的模組名稱,而且尚未載入相同名稱的模組,或者如果字串指定具有相對路徑的模組名稱,則函式會搜尋指定的模組。 如果載入指定的模組會導致系統載入其他相關聯的模組,則函式也會搜尋模組(也就是說,如果模組具有相依性)。 搜尋的目錄及其搜尋順序取決於指定的路徑和 dwFlags 參數。 如需詳細資訊,請參閱。
如果函式找不到模組或其其中一個相依性,則函式會失敗。
hFile
此參數保留供日後使用。 它必須是 NULL
[in] dwFlags
載入模組時要採取的動作。 如果未指定旗標,則此函式的行為與 LoadLibrary 函式的行為相同。 此參數可以是下列其中一個值。
價值 | 意義 |
---|---|
|
如果使用這個值,而且可執行模組是 DLL,則系統不會呼叫 DllMain 進程和線程初始化和終止。 此外,系統不會載入所指定模組所參考的其他可執行模組。
注意 請勿使用此值;它僅供回溯相容性使用。 如果您打算只存取 DLL 中的數據或資源,請使用 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE 或 LOAD_LIBRARY_AS_IMAGE_RESOURCE 或兩者。 否則,請使用 LoadLibrary 函式,將連結庫載入為 DLL 或可執行模組。
|
|
如果使用此值,系統不會檢查 Windows Server 2008 R2 和 Windows 7:安裝KB2532445的系統上,呼叫端必須以 “LocalSystem” 或 “TrustedInstaller” 執行;否則系統會忽略此旗標。 如需詳細資訊,請參閱 https://support.microsoft.com/kb/2532445的說明及支持知識庫中的「您可以在執行 Windows 7 或 Windows Server 2008 R2 的電腦上使用 Office 宏來規避 AppLocker 規則」。 Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP:AppLocker 是在 Windows 7 和 Windows Server 2008 R2 中引進的。 |
|
如果使用這個值,系統會將檔案對應至呼叫進程的虛擬位址空間,就好像是數據文件一樣。 不會執行或準備執行對應的檔案。 因此,您無法呼叫 GetModuleFileName、GetModuleHandle 或 GetProcAddress 這個 DLL 的函式。 使用此值會導致寫入唯讀記憶體,以引發存取違規。 當您只想載入 DLL 以從其中擷取訊息或資源時,請使用此旗標。
這個值可以與 LOAD_LIBRARY_AS_IMAGE_RESOURCE搭配使用。 如需詳細資訊,請參閱。 |
|
類似於 LOAD_LIBRARY_AS_DATAFILE,不同之處在於 DLL 檔案是以呼叫程式的獨佔寫入許可權開啟。 其他進程無法在使用時開啟 DLL 檔案進行寫入存取。 不過,DLL 仍然可以由其他進程開啟。
這個值可以與 LOAD_LIBRARY_AS_IMAGE_RESOURCE搭配使用。 如需詳細資訊,請參閱。 Windows Server 2003 和 Windows XP:在 Windows Vista 之前不支援此值。 |
|
如果使用這個值,系統會將檔案對應至進程的虛擬位址空間作為圖像檔。
不過,載入器不會載入靜態匯入或執行其他一般初始化步驟。 當您只想載入 DLL 以從其中擷取訊息或資源時,請使用此旗標。
除非應用程式相依於具有映像記憶體內部配置的檔案,否則此值應該與 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE 或 LOAD_LIBRARY_AS_DATAFILE搭配使用。 如需詳細資訊,請參閱一節。 Windows Server 2003 和 Windows XP:在 Windows Vista 之前不支援此值。 |
|
如果使用這個值,則會搜尋應用程式的安裝目錄來尋找 DLL 及其相依性。 標準搜尋路徑中的目錄不會搜尋。 這個值無法與 LOAD_WITH_ALTERED_SEARCH_PATH結合。
Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008:此值需要安裝 KB2533623。 Windows Server 2003 和 Windows XP:不支援此值。 |
|
這個值是 LOAD_LIBRARY_SEARCH_APPLICATION_DIR、LOAD_LIBRARY_SEARCH_SYSTEM32和 LOAD_LIBRARY_SEARCH_USER_DIRS的組合。 標準搜尋路徑中的目錄不會搜尋。 這個值無法與 LOAD_WITH_ALTERED_SEARCH_PATH結合。
這個值代表應用程式在其 DLL 搜尋路徑中應包含的建議目錄數目上限。 Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008:此值需要安裝 KB2533623。 Windows Server 2003 和 Windows XP:不支援此值。 |
|
如果使用這個值,則包含 DLL 的目錄會暫時新增至搜尋 DLL 相依性的目錄清單開頭。 標準搜尋路徑中的目錄不會搜尋。
lpFileName 參數必須指定完整路徑。 這個值無法與 LOAD_WITH_ALTERED_SEARCH_PATH結合。 例如,如果 Lib2.dll 只是 C:\Dir1 中的 C:\Dir1\Lib1.dll, loading Lib1.dll with this value causes the system to search for Lib2.dll 相依性。 若要在 C:\Dir1 中搜尋 Lib2.dll,以及 DLL 搜尋路徑中的所有目錄,請將此值與 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS結合。 Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008:此值需要安裝 KB2533623。 Windows Server 2003 和 Windows XP:不支援此值。 |
|
如果使用這個值,%windows%\system32 搜尋 DLL 及其相依性。
標準搜尋路徑中的目錄不會搜尋。 這個值無法與 LOAD_WITH_ALTERED_SEARCH_PATH結合。
Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008:此值需要安裝 KB2533623。 Windows Server 2003 和 Windows XP:不支援此值。 |
|
如果使用這個值,則會搜尋使用 AddDllDirectory 或 SetDllDirectory 函式來新增的目錄,以尋找 DLL 及其相依性。 如果已新增多個目錄,則未指定搜尋目錄的順序。 標準搜尋路徑中的目錄不會搜尋。 這個值無法與 LOAD_WITH_ALTERED_SEARCH_PATH結合。
Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008:此值需要安裝 KB2533623。 Windows Server 2003 和 Windows XP:不支援此值。 |
|
如果使用這個值,且 lpFileName 指定絕對路徑,系統會使用一節中討論的替代檔案搜尋策略,來尋找指定模組導致載入的相關可執行檔模組。 如果使用這個值,lpFileName 指定相對路徑,則行為是未定義的。
如果未使用此值,或如果 lpFileName 未指定路徑,則系統會使用一節中討論的標準搜尋策略來尋找指定模組導致載入的相關可執行檔模組。 此值無法與任何 LOAD_LIBRARY_SEARCH 旗標結合。 |
|
指定在載入時必須檢查二進位映像的數字簽名。
此值需要 Windows 8.1、Windows 10 或更新版本。 |
|
如果使用這個值,則只有在 [安全載入] 清單中的目錄下,才允許載入 DLL 以從目前目錄執行。 |
傳回值
如果函式成功,傳回值就是載入模組的句柄。
如果函式失敗,則傳回值 NULL。 若要取得擴充的錯誤資訊,請呼叫 GetLastError。
言論
LoadLibraryEx 函式與 LoadLibrary 函式非常類似。 差異包含一組選擇性行為,LoadLibraryEx 提供:
- LoadLibraryEx 可以載入 DLL 模組,而不呼叫 DLL DllMain 函式。
- LoadLibraryEx 可以針對永遠不會執行模塊的情況優化的方式載入模組,就像是數據文件一樣載入模組。
- LoadLibraryEx 可以使用兩個搜尋策略之一來尋找模組及其相關聯的模組,也可以搜尋進程特定的目錄集。
呼叫進程可以使用 loadLibraryEx 傳回的句柄 來識別呼叫 GetProcAddress、FindResource和 LoadResource 函式中的模組。
若要在 DLL 載入期間啟用或停用載入器所顯示的錯誤訊息,請使用 setErrorMode 函式
從 DllMain呼叫 LoadLibraryEx 並不安全。 如需詳細資訊,請參閱 DllMain中的一節。
Visual C++:Visual C++ 編譯程式支援一種語法,可讓您宣告線程局部變數:_declspec(thread)。 如果您在 DLL 中使用這個語法,您將無法在 Windows Vista 之前的 Windows 版本上明確使用 LoadLibraryEx 載入 DLL。 如果明確載入 DLL,您必須使用線程本機記憶體函式,而不是 _declspec(thread)。 如需範例,請參閱動態連結庫中 使用線程本機記憶體。
載入 DLL 作為資料檔或映像資源
LOAD_LIBRARY_AS_DATAFILE、LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE和 LOAD_LIBRARY_AS_IMAGE_RESOURCE 值會影響每個進程參考計數和指定模組的載入。 如果為 dwFlags 參數指定任何這些值,載入器會檢查進程是否已將模組載入為可執行 DLL。 如果是,這表示模組已經對應至呼叫進程的虛擬位址空間。 在此情況下,LoadLibraryEx 會傳回 DLL 的句柄,並遞增 DLL 參考計數。 如果 DLL 模組尚未載入為 DLL,系統會將模組對應為數據或影像檔,而非可執行檔 DLL。 在此情況下,LoadLibraryEx 會傳回載入的數據或圖像檔句柄,但不會遞增模組的參考計數,而且不會讓 CreateToolhelp32Snapshot 或 EnumProcessModules等函式顯示模組。如果呼叫 LoadLibraryEx 兩次,針對具有 LOAD_LIBRARY_AS_DATAFILE、LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE或 LOAD_LIBRARY_AS_IMAGE_RESOURCE的相同檔案,則會為檔案建立兩個不同的對應。
使用 LOAD_LIBRARY_AS_IMAGE_RESOURCE 值時,模組會使用可攜式可執行檔 (PE) 區段對齊展開來載入為影像。 相對虛擬位址 (RVA) 不需要對應至磁碟位址,因此可以從模組更快速地擷取資源。 指定 LOAD_LIBRARY_AS_IMAGE_RESOURCE 可防止載入模組時修改模組的其他進程。
除非應用程式相依於特定的影像對應特性,否則 LOAD_LIBRARY_AS_IMAGE_RESOURCE 值應該與 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE 或 LOAD_LIBRARY_AS_DATAFILE搭配使用。 這可讓載入器選擇是否要將模組載入為映像資源或數據檔,選取哪一個選項可讓系統更有效率地共用頁面。 FindResource 等資源函式可以使用任一對應。
若要判斷模組的載入方式,請使用下列其中一個宏來測試 loadLibraryEx 傳回的句柄。
#define LDR_IS_DATAFILE(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)1)
#define LDR_IS_IMAGEMAPPING(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)2)
#define LDR_IS_RESOURCE(handle) (LDR_IS_IMAGEMAPPING(handle) || LDR_IS_DATAFILE(handle))
下表描述這些宏。
宏觀 | 描述 |
---|---|
LDR_IS_DATAFILE(句柄) | 如果此宏傳回 TRUE |
LDR_IS_IMAGEMAPPING(句柄) | 如果此宏傳回 TRUE |
LDR_IS_RESOURCE(句柄) | 如果這個宏傳回 true ,則模組會載入為數據檔或圖像檔。 |
使用 FreeLibrary 函式釋放載入的模組,不論載入模組是否導致其參考計數遞增。 如果模組載入為數據或圖像檔案,則會終結對應,但參考計數不會遞減。 否則,DLL 參考計數會遞減。 因此,
搜尋 DLL 和相依性
搜尋路徑是搜尋 DLL 的目錄集合。 LoadLibraryEx 函式可以使用標準搜尋路徑或已改變的搜尋路徑來搜尋 DLL,也可以使用以 setDefaultDllDirectories 和 AddDllDirectory 函式所建立的程式特定搜尋路徑。 如需目錄清單及其搜尋順序,請參閱 Dynamic-Link 連結庫搜尋順序。LoadLibraryEx 函式會在下列情況下使用標準搜尋路徑:
- 檔名未指定路徑,且基底檔名不符合載入模組的基底檔名,而且不會使用任何 LOAD_LIBRARY_SEARCH 旗標。
- 指定路徑,但未使用 LOAD_WITH_ALTERED_SEARCH_PATH。
- 應用程式尚未使用 setDefaultDllDirectories 指定行程的預設 DLL 搜尋路徑,。
如果 lpFileName 指定相對路徑,則會將整個相對路徑附加至 DLL 搜尋路徑中的每個令牌。 若要從相對路徑載入模組而不搜尋任何其他路徑,請使用 GetFullPathName 來取得非關係路徑,並使用非關聯路徑呼叫 LoadLibraryEx。 如果模組載入為數據檔,且相對路徑開頭為 「.」 或 「..」,則會將相對路徑視為絕對路徑。
如果 lpFileName 指定絕對路徑,且 dwFlags 設定為 LOAD_WITH_ALTERED_SEARCH_PATH,LoadLibraryEx 會使用改變的搜尋路徑。 設定 LOAD_WITH_ALTERED_SEARCH_PATH 旗標時,行為是未定義,lpFileName 指定相對路徑。
SetDllDirectory 函式可用來修改搜尋路徑。 此解決方案比使用 setCurrentDirectory 或硬式編碼 DLL 的完整路徑更好。 不過,請注意,使用 SetDllDirectory 有效地停用安全 DLL 搜尋模式,而指定的目錄位於搜尋路徑中,而且不是安全線程。 可能的話,最好使用 AddDllDirectory 來修改默認進程搜尋路徑。 如需詳細資訊,請參閱 Dynamic-Link 連結庫搜尋順序。
應用程式可以使用 LOAD_LIBRARY_SEARCH_* 旗標,指定要搜尋單一 LoadLibraryEx 呼叫的目錄。 如果指定了多個 LOAD_LIBRARY_SEARCH 旗標,則會依下列順序搜尋目錄:
- 包含 DLL 的目錄(LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)。 此目錄只會搜尋要載入之 DLL 的相依性。
- 應用程式目錄 (LOAD_LIBRARY_SEARCH_APPLICATION_DIR)。
- 使用 addDllDirectory 函式
AddDllDirectory 函式 ( LOAD_LIBRARY_SEARCH_USER_DIRS ) 或SetDllDirectory 函式,明確新增至應用程式搜尋路徑的路徑。 如果已新增多個路徑,則未指定搜尋路徑的順序。 - System32 目錄 (LOAD_LIBRARY_SEARCH_SYSTEM32)。
Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008:LOAD_LIBRARY_SEARCH_ 旗標可在已安裝 KB2533623 的系統上使用。 若要判斷旗標是否可用,請使用 GetProcAddress 來取得 AddDllDirectory、RemoveDllDirectory或 SetDefaultDllDirectories 函式的位址。 如果 GetProcAddress 成功,LOAD_LIBRARY_SEARCH_ 旗標可以搭配 LoadLibraryEx使用。
如果應用程式已使用 SetDefaultDllDirectories 函式來建立進程的 DLL 搜尋路徑,且未使用任何 LOAD_LIBRARY_SEARCH_* 旗標,則 LoadLibraryEx 函式會使用進程 DLL 搜尋路徑,而不是標準搜尋路徑。
如果指定路徑,而且有與應用程式相關聯的重新導向檔案,LoadLibraryEx 函式會在應用程式目錄中搜尋模組。 如果模組存在於應用程式目錄中,LoadLibraryEx 會忽略路徑規格,並從應用程式目錄載入模組。 如果模組不存在於應用程式目錄中,函式會從指定的目錄載入模組。 如需詳細資訊,請參閱 動態連結庫重新導向。
如果您呼叫 LoadLibraryEx,且元件名稱沒有路徑規格,而且元件會列在系統相容指令清單中,則呼叫會自動重新導向至並存元件。
安全性備註
LOAD_LIBRARY_AS_DATAFILE 不會防止其他進程在載入模組時修改模組。 由於這可能會讓應用程式不那麼安全,因此除非您特別需要使用 LOAD_LIBRARY_AS_DATAFILE,否則在載入模組時應該使用 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE,而不是 LOAD_LIBRARY_AS_DATAFILE。 指定 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE 可防止載入模組時修改模組的其他進程。 請勿在相同的呼叫中指定 LOAD_LIBRARY_AS_DATAFILE 和 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE。請勿使用 SearchPath 函式來擷取後續 LoadLibraryEx 呼叫之 DLL 的路徑。 SearchPath 函式會使用與 loadLibraryEx 不同的搜尋順序,除非透過使用 BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE呼叫 SetSearchPathMode 明確啟用,否則不會使用安全進程搜尋模式。 因此,SearchPath 可能會先搜尋使用者目前的工作目錄來尋找指定的 DLL。 如果攻擊者已將惡意版本的 DLL 複製到目前的工作目錄中,則 SearchPath 所擷取的路徑 會指向惡意 DLL,LoadLibraryEx 將會載入。
請勿根據搜尋 DLL 的 LoadLibraryEx 呼叫來假設操作系統版本。 如果應用程式在 DLL 合法不存在的環境中執行,但 DLL 的惡意版本位於搜尋路徑中,可能會載入 DLL 的惡意版本。 請改用 取得系統版本中所述的建議技術。
如需 DLL 安全性問題的一般討論,請參閱 Dynamic-Link 連結庫安全性。
例子
下列程式代碼範例示範呼叫 LoadLibraryExA。
//Load the FMAPI DLL
hLib = ::LoadLibraryEx(L"fmapi.dll", NULL, NULL);
if ( !hLib )
{
wprintf(L"Could not load fmapi.dll, Error #%d.\n", GetLastError());
return;
}
如需其他範例,請參閱 查閱錯誤碼號碼的文字。
注意
libloaderapi.h 標頭會將 LoadLibraryEx 定義為別名,根據 UNICODE 預處理器常數的定義,自動選取此函式的 ANSI 或 Unicode 版本。 混合使用編碼中性別名與非編碼中性的程序代碼,可能會導致編譯或運行時間錯誤不符。 如需詳細資訊,請參閱函式原型的
要求
要求 | 價值 |
---|---|
最低支援的用戶端 | Windows XP [僅限傳統型應用程式] |
支援的最低伺服器 | Windows Server 2003 [僅限傳統型應用程式] |
目標平臺 | 窗戶 |
標頭 | libloaderapi.h (包括 Windows.h) |
連結庫 | Kernel32.lib |
DLL | Kernel32.dll |