LoadLibrary function

Expand
49 out of 110 rated this helpful - Rate this topic

LoadLibrary function

Applies to: desktop apps only

Loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded.

For additional load options, use the LoadLibraryEx function.

Syntax

HMODULE WINAPI LoadLibrary(
  __in  LPCTSTR lpFileName
);

Parameters

lpFileName [in]

The name of the module. This can be either a library module (a .dll file) or an executable module (an .exe file). The name specified is the file name of the module and is not related to the name stored in the library module itself, as specified by the LIBRARY keyword in the module-definition (.def) file.

If the string specifies a full path, the function searches only that path for the module.

If the string specifies a relative path or a module name without a path, the function uses a standard search strategy to find the module; for more information, see the Remarks.

If the function cannot find the module, the function fails. When specifying a path, be sure to use backslashes (\), not forward slashes (/). For more information about paths, see Naming a File or Directory.

If the string specifies a module name without a path and the file name extension is omitted, the function appends the default library extension .dll to the module name. To prevent the function from appending .dll to the module name, include a trailing point character (.) in the module name string.

Return value

If the function succeeds, the return value is a handle to the module.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Remarks

To enable or disable error messages displayed by the loader during DLL loads, use the SetErrorMode function.

LoadLibrary can be used to load a library module into the address space of the process and return a handle that can be used in GetProcAddress to get the address of a DLL function. LoadLibrary can also be used to load other executable modules. For example, the function can specify an .exe file to get a handle that can be used in FindResource or LoadResource. However, do not use LoadLibrary to run an .exe file. Instead, use the CreateProcess function.

If the specified module is a DLL that is not already loaded for the calling process, the system calls the DLL's DllMain function with the DLL_PROCESS_ATTACH value. If DllMain returns TRUE, LoadLibrary returns a handle to the module. If DllMain returns FALSE, the system unloads the DLL from the process address space and LoadLibrary returns NULL. It is not safe to call LoadLibrary from DllMain. For more information, see the Remarks section in DllMain.

Module handles are not global or inheritable. A call to LoadLibrary by one process does not produce a handle that another process can use — for example, in calling GetProcAddress. The other process must make its own call to LoadLibrary for the module before calling GetProcAddress.

If lpFileName does not include a path and there is more than one loaded module with the same base name and extension, the function returns a handle to the module that was loaded first.

If no file name extension is specified in the lpFileName parameter, the default library extension .dll is appended. However, the file name string can include a trailing point character (.) to indicate that the module name has no extension. When no path is specified, the function searches for loaded modules whose base name matches the base name of the module to be loaded. If the name matches, the load succeeds. Otherwise, the function searches for the file.

The first directory searched is the directory containing the image file used to create the calling process (for more information, see the CreateProcess function). Doing this allows private dynamic-link library (DLL) files associated with a process to be found without adding the process's installed directory to the PATH environment variable. If a relative path is specified, the entire relative path is appended to every token in the DLL search path list. To load a module from a relative path without searching any other path, use GetFullPathName to get a nonrelative path and call LoadLibrary with the nonrelative path. For more information on the DLL search order, see Dynamic-Link Library Search Order.

The search path can be altered using the SetDllDirectory function. This solution is recommended instead of using SetCurrentDirectory or hard-coding the full path to the DLL.

If a path is specified and there is a redirection file for the application, the function searches for the module in the application's directory. If the module exists in the application's directory, LoadLibrary ignores the specified path and loads the module from the application's directory. If the module does not exist in the application's directory, LoadLibrary loads the module from the specified directory. For more information, see Dynamic Link Library Redirection.

If you call LoadLibrary with the name of an assembly without a path specification and the assembly is listed in the system compatible manifest, the call is automatically redirected to the side-by-side assembly.

The system maintains a per-process reference count on all loaded modules. Calling LoadLibrary increments the reference count. Calling the FreeLibrary or FreeLibraryAndExitThread function decrements the reference count. The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count).

Windows Server 2003 and Windows XP:  The Visual C++ compiler supports a syntax that enables you to declare thread-local variables: _declspec(thread). If you use this syntax in a DLL, you will not be able to load the DLL explicitly using LoadLibrary on versions of Windows prior to Windows Vista. If your DLL will be loaded explicitly, you must use the thread local storage functions instead of _declspec(thread). For an example, see Using Thread Local Storage in a Dynamic Link Library.

Security Remarks

Do not use the SearchPath function to retrieve a path to a DLL for a subsequent LoadLibrary call. The SearchPath function uses a different search order than LoadLibrary and it does not use safe process search mode unless this is explicitly enabled by calling SetSearchPathMode with BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE. Therefore, SearchPath is likely to first search the user’s current working directory for the specified DLL. If an attacker has copied a malicious version of a DLL into the current working directory, the path retrieved by SearchPath will point to the malicious DLL, which LoadLibrary will then load.

Do not make assumptions about the operating system version based on a LoadLibrary call that searches for a DLL. If the application is running in an environment where the DLL is legitimately not present but a malicious version of the DLL is in the search path, the malicious version of the DLL may be loaded. Instead, use the recommended techniques described in Getting the System Version.

Examples

For an example, see Using Run-Time Dynamic Linking.

Requirements

Minimum supported client

Windows XP

Minimum supported server

Windows Server 2003

Header

Winbase.h (include Windows.h)

Library

Kernel32.lib

DLL

Kernel32.dll

Unicode and ANSI names

LoadLibraryW (Unicode) and LoadLibraryA (ANSI)

See also

DllMain
Dynamic-Link Library Functions
FindResource
FreeLibrary
GetProcAddress
GetSystemDirectory
GetWindowsDirectory
LoadLibraryEx
LoadResource
Run-Time Dynamic Linking
SetDllDirectory
SetErrorMode

 

 

Send comments about this topic to Microsoft

Build date: 5/5/2012

Did you find this helpful?
(1500 characters remaining)
Community Additions ADD
C++ Class

A sample C++ class for dynamically loading and operating dll files can be found here:
Header:
http://www.asyncop.com/MTnPDirEnum.aspx?treeviewPath=%5bo%5d+Open-Source%5cWinModules%5cInfrastructure%5cSystemAPI.h
Source:
http://www.asyncop.com/MTnPDirEnum.aspx?treeviewPath=%5bo%5d+Open-Source%5cWinModules%5cInfrastructure%5cSystemAPI.cpp
This includes loading the library, calling functions and reading resources

An example call would be:

HINSTANCE hinstLib;

.

.

.

hinstLib = LoadLibrary(TEXT("C:\\ FolderName\\YOUR_DLL.dll")); // NOTE: The use of double back-slashes.

8/25/2011
BadImageFormat Error due to Windows 64 Bit bug
Hello

I want to describe a bug in the Windows 7 - 64 Bit operating system that results in:

"An attempt was made to load a program with an incorrect format. (Exception 0x8007000B)
System.BadImageFormatException
when using PInvoke in a C# application via
[DllImport("MyDll.dll", EntryPoint="xyz", SetLastError=true)

or that results in Error 193 (ERROR_BAD_EXE_FORMAT) when using LoadLibrary().

If you get this error it normally means that a 64 Bit application tries to load a 32 Bit Dll.
This is what you find everywhere when googling.
But not always - as in my case:


I observed this on Windows 7 - 64 Bit with a C# application compiled on VS2005 as "AnyCpu".

And now comes the interesting part:
This error occurred when loading a 64 Bit MFC Dll (also compiled on VS2005) into this process!

That's incredible, isn't it ?
A BadImageFormat exception !IS! even possible when loading a 64 Bit Dll into a 64 Bit process due to a bug in Windows 7 - 64 Bit!

I wasted 2 entire days of my life investigating this stuff and here comes the result for all those, who have the same problem:

_________________________________________________________________

FIRST:
------
How can you be SURE if the process you are running is a 64 Bit process ?
1.)
You see in Taskmanager a *32 behind all 32 Bit processes and nothing behind all 64 Bit processes.
2.)
But I recommend to install Process Explorer from www.SysInternals.com
ATTENTION: The strange thing is that Process Explorer shows Exe's compiled as "AnyCpu" as if they were 32 Bit!
That means that the EXE is marked as 32 Bit. (I suppose they have the 32 Bit PE header but internally run as 64 Bit)
But you see that all DLLs that this process has loaded like Kernel32.dll are 64 Bit DLLs and this is the clear sign that this process is running as 64 Bit.
So don't care about what the Exe says in Process Explorer!
In the lower pane of Process Explorer you can see all the loaded DLLs with their path and if they are 32 Bit or 64 Bit.

I recommend before you start to analyze your process: First study the differences in Process Explorer between:
C:\Windows\System32\Calc.exe  and
C:\Windows\SysWow64\Calc.exe

SECOND:
-------
How can you be !SURE! that the Dll you want to load is really a 64 Bit Dll ?
Install DepdendencyWalker from www.SysInternals.com and it will tell you immediately if a Dll is compiled as 64 Bit or not.
___________________________________________________________________

Back to the problem:

In my case I compiled the Exe and the DLL both on my own and so I knew that
the EXE is "AnyCpu",
the DLL is "x64".

So why did I get the BadImageFormat Excpetion then?

I used another tool: Process Monitor also from www.SysInternals.com to study what the app is doing when starting up.
Immediately after LoadLibary() or PInvoke I saw that Windows was opening a ComCtl32.dll in a folder named
C:\Windows\winsxs\x86_microsoft-windows-comctl32-........

And after that the exception was thrown.
That's the real hammer!

How is it possible that a 64 Bit Process even looks into any folder named X86_... ???
The 64 Bit Dlls are in folders named
C:\Windows\winsxs\amd64_......

Now I found the cause of the BadImageFormat exception:
Not MY Dll had the bad image format!
My Dll depends on ComCtl32.dll and Windwos has so few intelligency that it searches for a depency in the folder of a 32 Bit Dll!
That's really a big fat Windows bug!
It should be obvious that all depencies of a 64 Bit Dll MUST be searched in one of the Amd64 folders, but NOT in the X86 folders.

But that's only one of the bugs!

The next bug is the wrong error message.
The error leads into the wrong direction and made me waste 2 entire days.
The error made me think that my Dll has the wrong Exe format.
But it was a Dll that Windows searched in the wrong folder that obviously had the wrong Exe format!

Now how did I solve the problem:
My Dll needed a Manifest file.

VS2005 automatically embeds a Manifest.
But it is completely useless:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
</assembly>

It simply says nothing.

I found this very good article about manifests:
http://msdn.microsoft.com/en-us/library/bb773175(VS.85).aspx
After reading it and after following the links in this article you will know that there are 3 ways to add a manifest:
1.) As a separate file (usefull if you don't have the sourcecode of the Dll)
2.) As embedded manifest file (RT_MANIFEST)
3.) Via a #pragma comment linker which is the easiest and fastset way on VS2005 or higher.

I did the latter and now it works !
Finally!


I hope that Mircosoft fixes this heavy bug:
A 64 Bit application must never ever search Dlls in SideBySide folders (SxS) starting with X86.... not even if a manifest is missing or wrong or incomplete!
Simply NEVER!
A 64 Bit application must only search in the SxS folders starting with Amd64...


The other topic is the error handling of Microsoft products that always has been a mess.
Error messages are misleading or even suppressed.
The correct error in this case would be:
"Missing manifest for MyDll.dll"


Elmü



6/2/2011
vb.net syntax
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function LoadLibrary(<[In], MarshalAs(UnmanagedType.LPTStr)> ByVal lpFileName As String) As IntPtr
End Function
C# syntax
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
internal static extern IntPtr LoadLibrary([In, MarshalAs(UnmanagedType.LPStr)] string lpFileName);


Usage of [In, MarshalAs(UnmanageType.LPStr)] causes LoadLibrary call to fail in my case.  Removing it works.  Comment below seems to confirm.
5/12/2010
Visual Basic 9 and C# Declarations
  Public Declare Auto Function LoadLibrary Lib "kernel32" (ByVal lpLibFileName As String) As IntPtr




[DllImport("kernel32", CharSet=CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpLibFileName);
How to know which modules (DLL etc.) are loaded by a program in Windows?

From the command line run the following command syntax:

    tasklist /m /fi "IMAGENAME eq [filename.exe]"



Ofcourse, replace the [filename.exe] above with the EXE file name that you are working with.

Example: With Notepad.exe


Command:

    tasklist /m /fi "IMAGENAME eq notepad.exe"

Sample Output:


    Image Name                   PID Modules
========================= ====== =============================================
NOTEPAD.EXE 3340 ntdll.dll, kernel32.dll, comdlg32.dll,
ADVAPI32.dll, RPCRT4.dll, Secur32.dll,
COMCTL32.dll, msvcrt.dll, GDI32.dll,
USER32.dll, SHLWAPI.dll, SHELL32.dll,
WINSPOOL.DRV, ShimEng.dll, AcGenral.DLL,
WINMM.dll, ole32.dll, OLEAUT32.dll,
MSACM32.dll, VERSION.dll, USERENV.dll,
UxTheme.dll, IMM32.DLL, LPK.DLL, USP10.dll,
MSCTF.dll, msctfime.ime, autoaway.dll



Note: To open the command prompt, go to Start > Run. Then type CMD and hit <Enter>.

9/23/2008
Relative paths
The information about the path passed into LoadLibrary is slightly fuzzy about relative paths. I know that I can pass in an absolute path to the call, but are partial paths supported as well? For instance, is passing in "somedir\something.dll" going to be supported? By testing, I can see that it does work -- but I don't want to rely on undocumented behavior.
4/8/2008
Reloading dlls

If the dll is already loaded - LoadLibrary will just increase the reference count to that library when returning the new handle (or maybe it will just return the same handle as the previous time, but I doubt it).

In a case like: code in exe1.dll loads dll1.dll, then dll1.dll loads dll2.dll, then dll2.dll loads dll1.dll - dll2.dll gets access to the assembly from which it was loaded itself, which may be complex and cause some issues, but is also pretty useful.

2/22/2007