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 函式 的行為相同。 此參數可以是下列其中一個值。

意義
DONT_RESOLVE_DLL_REFERENCES
0x00000001
如果使用這個值,而且可執行檔模組是 DLL,則系統不會呼叫 DllMain 進行進程和線程初始化和終止。 此外,系統不會載入指定模組所參考的其他可執行模組。
注意 請勿使用此值;它僅供回溯相容性使用。 如果您打算只存取 DLL 中的數據或資源,請使用 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVELOAD_LIBRARY_AS_IMAGE_RESOURCE 或兩者。 否則,請使用 LoadLibrary 函式,將連結庫載入為 DLL 或可執行模組。
 
LOAD_IGNORE_CODE_AUTHZ_LEVEL
0x00000010
如果使用此值,系統不會檢查 AppLocker 規則或套用 DLL 的軟體限制原則 。 此動作只適用於載入的 DLL,而不是其相依性。 建議在安裝程式中使用此值,這些安裝程式必須在安裝期間執行解壓縮的 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 中引進。

LOAD_LIBRARY_AS_DATAFILE
0x00000002
如果使用這個值,系統會將檔案對應至呼叫進程的虛擬位址空間,就像是數據文件一樣。 不會執行任何動作,或準備執行對應的檔案。 因此,您無法使用此 DLL 呼叫 GetModuleFileNameGetModuleHandleGetProcAddress 等函式。 使用此值會導致寫入唯讀記憶體,以引發存取違規。 當您只想載入 DLL 以從中擷取訊息或資源時,請使用此旗標。

此值可與 LOAD_LIBRARY_AS_IMAGE_RESOURCE搭配使用。 如需詳細資訊,請參閱<備註>。

LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE
0x00000040
LOAD_LIBRARY_AS_DATAFILE類似,不同之處在於 DLL 檔案是以呼叫程式的獨佔寫入存取權開啟。 其他進程在使用時,無法開啟 DLL 檔案以進行寫入存取。 不過,DLL 仍然可以由其他進程開啟。

此值可與 LOAD_LIBRARY_AS_IMAGE_RESOURCE搭配使用。 如需詳細資訊,請參閱<備註>。

Windows Server 2003 和 Windows XP: 在 Windows Vista 之前,不支援此值。

LOAD_LIBRARY_AS_IMAGE_RESOURCE
0x00000020
如果使用這個值,系統會將檔案對應至進程的虛擬位址空間作為圖像檔案。 不過,載入器不會載入靜態匯入,或執行其他一般初始化步驟。 當您只想載入 DLL 以從中擷取訊息或資源時,請使用此旗標。

除非應用程式相依於具有影像記憶體內部配置的檔案,否則此值應該與 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVELOAD_LIBRARY_AS_DATAFILE搭配使用。 如需詳細資訊,請參閱<備註>一節。

Windows Server 2003 和 Windows XP: 在 Windows Vista 之前,不支援此值。

LOAD_LIBRARY_SEARCH_APPLICATION_DIR
0x00000200
如果使用此值,則會搜尋應用程式的安裝目錄,以尋找 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_DEFAULT_DIRS
0x00001000
這個值是 LOAD_LIBRARY_SEARCH_APPLICATION_DIRLOAD_LIBRARY_SEARCH_SYSTEM32LOAD_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: 不支援此值。

LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
0x00000100
如果使用這個值,則包含 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_SEARCH_DEFAULT_DIRS合併。

Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008: 此值需要安裝 KB2533623

Windows Server 2003 和 Windows XP: 不支援此值。

LOAD_LIBRARY_SEARCH_SYSTEM32
0x00000800
如果使用這個值,則會搜尋 %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: 不支援這個值。

LOAD_LIBRARY_SEARCH_USER_DIRS
0x00000400
如果使用此值,則會搜尋使用 AddDllDirectorySetDllDirectory 函式新增的目錄,以尋找 DLL 及其相依性。 如果已新增多個目錄,則未指定搜尋目錄的順序。 不會搜尋標準搜尋路徑中的目錄。 這個值無法與 LOAD_WITH_ALTERED_SEARCH_PATH結合。

Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008: 此值需要安裝 KB2533623

Windows Server 2003 和 Windows XP: 不支援這個值。

LOAD_WITH_ALTERED_SEARCH_PATH
0x00000008
如果使用這個值, 且 lpFileName 指定絕對路徑,則系統會使用一節中討論的替代檔案搜尋策略,尋找指定模組導致載入的相關可執行文件模組。 如果使用這個值,且 lpFileName 指定相對路徑,則行為為未定義。

如果未使用此值,或 lpFileName 未指定路徑,則系統會使用一節中討論的標準搜尋策略來尋找指定模組導致載入的相關可執行檔模組。

這個值不能與任何 LOAD_LIBRARY_SEARCH 旗標結合。

LOAD_LIBRARY_REQUIRE_SIGNED_TARGET
0x00000080
指定在載入時必須檢查二進位影像的數字簽名。

此值需要 Windows 8.1、Windows 10 或更新版本。

LOAD_LIBRARY_SAFE_CURRENT_DIRS
0x00002000
如果使用這個值,則只有在 [安全載入] 清單中的目錄下,才允許載入 DLL 以從目前目錄執行。

傳回值

如果函式成功,則傳回值是載入模組的句柄。

如果函式失敗,傳回值為 NULL。 若要取得擴充的錯誤資訊,請呼叫 GetLastError

備註

LoadLibraryEx 函式與 LoadLibrary 函式非常類似。 差異是由 LoadLibraryEx 提供的一組選擇性行為所組成:

  • LoadLibraryEx 可以載入 DLL 模組,而不需呼叫 DLL 的 DllMain 函式。
  • LoadLibraryEx 可以針對永遠不會執行模塊的情況優化的方式來載入模組,載入模組就像是數據文件一樣。
  • LoadLibraryEx 可以使用兩個搜尋策略之一來尋找模組及其相關聯的模組,也可以搜尋一組程式特定的目錄。
您可以藉由設定 dwFlags 參數來選取這些選擇性行為;如果 dwFlags 為零, LoadLibraryEx 的行為會與 LoadLibrary 相同。

呼叫進程可以使用 LoadLibraryEx 傳回的句柄來識別呼叫 GetProcAddressFindResource 和 LoadResource 函式中的模組。

若要在 DLL 載入期間啟用或停用載入器所顯示的錯誤訊息,請使用 SetErrorMode 函式。

DllMain 呼叫 LoadLibraryEx 並不安全。 如需詳細資訊,請參閱 DllMain 中的一節。

Visual C++: Visual C++ 編譯程式支援可讓您宣告線程局部變數的語法: _declspec (线程) 。 如果您在 DLL 中使用這個語法,您將無法在 Windows Vista 之前的 Windows 版本上明確地使用 LoadLibraryEx 載入 DLL。 如果您的 DLL 會明確載入,您必須使用線程本機記憶體函式,而不是 _declspec (线程) 。 如需範例,請參閱 在動態連結庫中使用線程本機記憶體

載入 DLL 作為資料檔或影像資源

LOAD_LIBRARY_AS_DATAFILELOAD_LIBRARY_AS_DATAFILE_EXCLUSIVELOAD_LIBRARY_AS_IMAGE_RESOURCE值會影響每個進程參考計數和指定模組的載入。 如果為 dwFlags 參數指定了其中任何值,載入器會檢查進程是否已將模組載入為可執行 DLL。 如果是,這表示模組已經對應到呼叫進程的虛擬位址空間。 在此情況下, LoadLibraryEx 會傳回 DLL 的句柄,並遞增 DLL 參考計數。 如果 DLL 模組尚未載入為 DLL,則系統會將模組對應為數據或影像檔,而不是可執行檔 DLL。 在此情況下, LoadLibraryEx 會傳回載入的數據或圖像檔句柄,但不會遞增模組的參考計數,而且不會讓 CreateToolhelp32SnapshotEnumProcessModules 等函式看到模組。

如果針對具有LOAD_LIBRARY_AS_DATAFILELOAD_LIBRARY_AS_DATAFILE_EXCLUSIVELOAD_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_EXCLUSIVELOAD_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_DATAFILELOAD_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,也可以使用以 SetDefaultDllDirectoriesAddDllDirectory 函式建立的進程特定搜尋路徑。 如需目錄的清單及其搜尋順序,請參閱 動態連結庫搜尋順序

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、RemoveDllDirectorySetDefaultDllDirectories 函式的位址。 如果 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_DATAFILELOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE

請勿使用 SearchPath 函式來擷取 DLL 的路徑,以供後續 的 LoadLibraryEx 呼叫使用。 SearchPath 函式會使用與 LoadLibraryEx 不同的搜尋順序,而且它不會使用安全進程搜尋模式,除非藉由使用 BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE 呼叫 SetSearchPathMode 來明確啟用此功能。 因此, SearchPath 可能會先搜尋使用者目前的工作目錄,以尋找指定的 DLL。 如果攻擊者已將惡意版本的 DLL 複製到目前的工作目錄中, SearchPath 所擷取的路徑會指向 LoadLibraryEx 接著會載入的惡意 DLL。

請勿根據搜尋 DLL 的 LoadLibraryEx 呼叫來假設操作系統版本。 如果應用程式是在 DLL 合法不存在的環境中執行,但 DLL 的惡意版本位於搜尋路徑中,可能會載入 DLL 的惡意版本。 請改用 取得系統版本中所述的建議技術。

如需 DLL 安全性問題的一般討論,請參閱 動態連結庫安全性

範例

下列程式代碼範例示範 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 [僅限傳統型應用程式]
目標平台 Windows
標頭 libloaderapi.h (包含 Windows.h)
程式庫 Kernel32.lib
DLL Kernel32.dll

另請參閱

DllMain

動態連結庫函式

動態連結庫搜尋順序

動態連結庫安全性

FindResource

FreeLibrary

GetProcAddress

GetSystemDirectory

GetWindowsDirectory

LoadLibrary

LoadResource

OpenFile

運行時間動態連結

SearchPath

SetDllDirectory

SetErrorMode