LoadLibraryExW 函式 (libloaderapi.h)
將指定的模組載入呼叫進程的位址空間。 指定的模組可能會導致載入其他模組。
語法
HMODULE LoadLibraryExW(
[in] LPCWSTR 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 或可執行模組。
|
|
如果使用此值,系統不會檢查 AppLocker 規則或套用 DLL 的軟體限制原則 。 此動作只適用于要載入的 DLL,而不適用於其相依性。 建議在安裝程式中使用此值,這些安裝程式必須在安裝期間執行擷取的 DLL。
Windows Server 2008 R2 和 Windows 7: 在已安裝 KB2532445 的系統上,呼叫端必須以 「LocalSystem」 或 「TrustedInstaller」 執行;否則,系統會忽略此旗標。 For more information, see "You can circumvent AppLocker rules by using an Office macro on a computer that is running Windows 7 or Windows Server 2008 R2" in the Help and Support Knowledge Base at https://support.microsoft.com/kb/2532445. Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP: AppLocker 是在 Windows 7 和 Windows Server 2008 R2 中引進。 |
|
如果使用這個值,系統會將檔案對應至呼叫進程的虛擬位址空間,就像是資料檔案一樣。 不會執行任何動作,或準備執行對應的檔案。 因此,您無法使用此 DLL 呼叫 GetModuleFileName、 GetModuleHandle 或 GetProcAddress 等函式。 使用此值會導致寫入唯讀記憶體,以引發存取違規。 當您只想載入 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\Lib1.dll 的相依性,使用此值載入 Lib1.dll 會導致系統只在 C:\Dir1 中搜尋 Lib2.dll。 若要在 C:\Dir1 中搜尋 Lib2.dll,以及 DLL 搜尋路徑中的所有目錄,請將此值與 LOAD_LIBRARY_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 (執行緒) 。 如果您在 DLL 中使用這個語法,您將無法在 Windows Vista 之前的 Windows 版本上明確地使用 LoadLibraryEx 載入 DLL。 如果您的 DLL 會明確載入,您必須使用執行緒本機儲存體函式,而不是 _declspec (執行緒) 。 如需範例,請參閱 在動態連結程式庫中使用執行緒本機儲存體。
載入 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等函式看到模組。如果針對具有LOAD_LIBRARY_AS_DATAFILE、LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE或LOAD_LIBRARY_AS_IMAGE_RESOURCE的相同檔案呼叫LoadLibraryEx兩次,則會為檔案建立兩個不同的對應。
使用 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,模組會載入為資料檔案 (LOAD_LIBRARY_AS_DATAFILE 或 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) 。 |
LDR_IS_IMAGEMAPPING (控制碼) | 如果這個宏傳回 TRUE,模組會載入為影像檔 (LOAD_LIBRARY_AS_IMAGE_RESOURCE) 。 |
LDR_IS_RESOURCE (控制碼) | 如果這個宏傳回 TRUE,模組會載入為資料檔案或影像檔。 |
使用 FreeLibrary 函式釋放載入的模組,不論載入模組是否導致其參考計數遞增。 如果模組已載入為數據或影像檔案,則會終結對應,但參考計數不會遞減。 否則,DLL 參考計數會遞減。 因此,使用LoadLibraryEx所傳回的任何控制碼呼叫FreeLibrary是安全的。
搜尋 DLL 和相依性
搜尋路徑是搜尋 DLL 的目錄集合。 LoadLibraryEx函式可以使用標準搜尋路徑或改變的搜尋路徑來搜尋 DLL,也可以使用以SetDefaultDllDirectories和AddDllDirectory函式建立的進程特定搜尋路徑。 如需目錄的清單及其搜尋順序,請參閱 動態連結程式庫搜尋順序。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 來修改預設進程搜尋路徑。 如需詳細資訊,請參閱 動態連結程式庫搜尋順序。
應用程式可以使用LOAD_LIBRARY_SEARCH_*旗標來指定要搜尋單一LoadLibraryEx呼叫的目錄。 如果指定多個 LOAD_LIBRARY_SEARCH 旗標,則會依下列順序搜尋目錄:
- 包含 DLL (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) 的目錄。 此目錄只會搜尋要載入之 DLL 的相依性。
- 應用程式目錄 (LOAD_LIBRARY_SEARCH_APPLICATION_DIR) 。
- 使用 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不同的搜尋順序,但除非透過呼叫SetSearchPathMode與BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE明確啟用此搜尋模式,否則不會使用安全進程搜尋模式。 因此, SearchPath 可能先搜尋使用者目前的工作目錄以尋找指定的 DLL。 如果攻擊者已將惡意版本的 DLL 複製到目前的工作目錄中, SearchPath 所擷取的路徑會指向 載入 LoadLibraryEx 的惡意 DLL。
請勿根據搜尋 DLL 的 LoadLibraryEx 呼叫來假設作業系統版本。 如果應用程式在 DLL 合法不存在但 DLL 惡意版本位於搜尋路徑的環境中執行,可能會載入 DLL 的惡意版本。 請改用 取得系統版本中所述的建議技術。
如需 DLL 安全性問題的一般討論,請參閱 動態連結程式庫安全性。
範例
如需範例,請參閱 查閱錯誤碼號碼的文字。
注意
libloaderapi.h 標頭會將 LoadLibraryEx 定義為別名,根據 UNICODE 預處理器常數的定義,自動選取此函式的 ANSI 或 Unicode 版本。 混合使用編碼中性別名與非編碼中性的程式碼,可能會導致編譯或執行時間錯誤不符。 如需詳細資訊,請參閱 函式原型的慣例。
需求
最低支援的用戶端 | Windows XP [僅限傳統型應用程式] |
最低支援的伺服器 | Windows Server 2003 [僅限桌面應用程式] |
目標平台 | Windows |
標頭 | libloaderapi.h (包含 Windows.h) |
程式庫 | Kernel32.lib |
DLL | Kernel32.dll |
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應