Windows Win32 Dlls
Windows Win32 Dlls
A dynamic-link library (DLL) is a module that contains functions and data that can be
used by another module (application or DLL).
A DLL can define two kinds of functions: exported and internal. The exported functions
are intended to be called by other modules, as well as from within the DLL where they
are defined. Internal functions are typically intended to be called only from within the
DLL where they are defined. Although a DLL can export data, its data is generally used
only by its functions. However, there is nothing to prevent another module from reading
or writing that address.
DLLs provide a way to modularize applications so that their functionality can be updated
and reused more easily. DLLs also help reduce memory overhead when several
applications use the same functionality at the same time, because although each
application receives its own copy of the DLL data, the applications share the DLL code.
7 Note
If you are a user experiencing difficulty with a DLL on your computer, you should
contact customer support for the software vendor that publishes the DLL. If you
feel you are in need of support for a Microsoft product (including Windows), please
go to our technical support site at support.microsoft.com .
Related topics
DLLs (Visual C++)
Feedback
Was this page helpful? ツ Yes ト No
Dynamic linking allows a module to include only the information needed to locate an
exported DLL function at load time or run time. Dynamic linking differs from the more
familiar static linking, in which the linker copies a library function's code into each
module that calls it.
The system maintains a per-process reference count for each DLL. When a thread loads
the DLL, the reference count is incremented by one. When the process terminates, or
when the reference count becomes zero (run-time dynamic linking only), the DLL is
unloaded from the virtual address space of the process.
Like any other function, an exported DLL function runs in the context of the thread that
calls it. Therefore, the following conditions apply:
The threads of the process that called the DLL can use handles opened by a DLL
function. Similarly, handles opened by any thread of the calling process can be
used in the DLL function.
The DLL uses the stack of the calling thread and the virtual address space of the
calling process.
The DLL allocates memory from the virtual address space of the calling process.
Feedback
Was this page helpful? ツ Yes ト No
Multiple processes that load the same DLL at the same base address share a single
copy of the DLL in physical memory. Doing this saves system memory and reduces
swapping.
When the functions in a DLL change, the applications that use them do not need
to be recompiled or relinked as long as the function arguments, calling
conventions, and return values do not change. In contrast, statically linked object
code requires that the application be relinked when the functions change.
A DLL can provide after-market support. For example, a display driver DLL can be
modified to support a display that was not available when the application was
initially shipped.
Programs written in different programming languages can call the same DLL
function as long as the programs follow the same calling convention that the
function uses. The calling convention (such as C, Pascal, or standard call) controls
the order in which the calling function must push the arguments onto the stack,
whether the function or the calling function is responsible for cleaning up the
stack, and whether any arguments are passed in registers. For more information,
see the documentation included with your compiler.
Feedback
Was this page helpful? ツ Yes ト No
To create a Dynamic-link library (DLL), you must create one or more source code files,
and possibly a linker file for exporting the functions. If you plan to allow applications
that use your DLL to use load-time dynamic linking, then you must also create an import
library.
If your DLL may be used by a multithreaded application, then you should make your DLL
"thread-safe". To avoid data corruption, you must synchronize access to all of the DLL's
global data. You must also ensure that you link only with libraries that are thread-safe as
well. For example, Microsoft Visual C++ contains multiple versions of the C Run-time
Library, one that is not thread-safe and two that are.
Exporting functions
How you specify which functions in a DLL should be exported depends on the tools that
you are using for development. Some compilers allow you to export a function directly
in the source code by using a modifier in the function declaration. Other times, you
must specify exports in a file that you pass to the linker.
For example, using Visual C++, there are two possible ways to export DLL functions:
with the __declspec(dllexport) modifier or with a module-definition ( .def ) file. If you
use the __declspec(dllexport) modifier, then it's not necessary to use a .def file. For
more info, see Exporting from a DLL.
Related topics
Creating a Simple Dynamic-link Library
DLLs (Visual C++)
Feedback
Was this page helpful? Yes No
Dynamic-Link Library Entry-Point
Function
Article • 01/07/2021
A DLL can optionally specify an entry-point function. If present, the system calls the
entry-point function whenever a process or thread loads or unloads the DLL. It can be
used to perform simple initialization and cleanup tasks. For example, it can set up thread
local storage when a new thread is created, and clean it up when the thread is
terminated.
If you are linking your DLL with the C run-time library, it may provide an entry-point
function for you, and allow you to provide a separate initialization function. Check the
documentation for your run-time library for more information.
If you are providing your own entry-point, see the DllMain function. The name DllMain
is a placeholder for a user-defined function. You must specify the actual name you use
when you build your DLL. For more information, see the documentation included with
your development tools.
A process loads the DLL. For processes using load-time dynamic linking, the DLL is
loaded during process initialization. For processes using run-time linking, the DLL
is loaded before LoadLibrary or LoadLibraryEx returns.
A process unloads the DLL. The DLL is unloaded when the process terminates or
calls the FreeLibrary function and the reference count becomes zero. If the process
terminates as a result of the TerminateProcess or TerminateThread function, the
system does not call the DLL entry-point function.
A new thread is created in a process that has loaded the DLL. You can use the
DisableThreadLibraryCalls function to disable notification when threads are
created.
A thread of a process that has loaded the DLL terminates normally, not using
TerminateThread or TerminateProcess. When a process unloads the DLL, the
entry-point function is called only once for the entire process, rather than once for
each existing thread of the process. You can use DisableThreadLibraryCalls to
disable notification when threads are terminated.
Only one thread at a time can call the entry-point function.
The system calls the entry-point function in the context of the process or thread that
caused the function to be called. This allows a DLL to use its entry-point function for
allocating memory in the virtual address space of the calling process or to open handles
accessible to the process. The entry-point function can also allocate memory that is
private to a new thread by using thread local storage (TLS). For more information about
thread local storage, see Thread Local Storage.
In the body of the function, you may handle any combination of the following scenarios
in which the DLL entry point has been called:
The entry-point function should perform only simple initialization tasks. It must not call
the LoadLibrary or LoadLibraryEx function (or a function that calls these functions),
because this may create dependency loops in the DLL load order. This can result in a
DLL being used before the system has executed its initialization code. Similarly, the
entry-point function must not call the FreeLibrary function (or a function that calls
FreeLibrary) during process termination, because this can result in a DLL being used
after the system has executed its termination code.
Because Kernel32.dll is guaranteed to be loaded in the process address space when the
entry-point function is called, calling functions in Kernel32.dll does not result in the DLL
being used before its initialization code has been executed. Therefore, the entry-point
function can create synchronization objects such as critical sections and mutexes, and
use TLS, because these functions are located in Kernel32.dll. It is not safe to call the
registry functions, for example, because they are located in Advapi32.dll.
Calling other functions may result in problems that are difficult to diagnose. For
example, calling User, Shell, and COM functions can cause access violation errors,
because some functions in their DLLs call LoadLibrary to load other system
components. Conversely, calling those functions during termination can cause access
violation errors because the corresponding component may already have been
unloaded or uninitialized.
The following example demonstrates how to structure the DLL entry-point function.
syntax
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
When the system starts a program that uses load-time dynamic linking, it uses the
information the linker placed in the file to locate the names of the DLLs that are used by
the process. The system then searches for the DLLs. For more information, see Dynamic-
Link Library Search Order.
If the system cannot locate a required DLL, it terminates the process and displays a
dialog box that reports the error to the user. Otherwise, the system maps the DLL into
the virtual address space of the process and increments the DLL reference count.
The system calls the entry-point function. The function receives a code indicating that
the process is loading the DLL. If the entry-point function does not return TRUE, the
system terminates the process and reports the error. For more information about the
entry-point function, see Dynamic-Link Library Entry-Point Function.
Finally, the system modifies the function address table with the starting addresses for
the imported DLL functions.
The DLL is mapped into the virtual address space of the process during its initialization
and is loaded into physical memory only when needed.
Related topics
Using Load-Time Dynamic Linking
Feedback
Was this page helpful? ツ Yes ト No
When the application calls the LoadLibrary or LoadLibraryEx functions, the system
attempts to locate the DLL (for details, see Dynamic-Link Library Search Order). If the
search succeeds, the system maps the DLL module into the virtual address space of the
process and increments the reference count. If the call to LoadLibrary or LoadLibraryEx
specifies a DLL whose code is already mapped into the virtual address space of the
calling process, the function simply returns a handle to the DLL and increments the DLL
reference count. Note that two DLLs that have the same base file name and extension
but are found in different directories are not considered to be the same DLL.
The system calls the entry-point function in the context of the thread that called
LoadLibrary or LoadLibraryEx. The entry-point function is not called if the DLL was
already loaded by the process through a call to LoadLibrary or LoadLibraryEx with no
corresponding call to the FreeLibrary function.
If the system cannot find the DLL or if the entry-point function returns FALSE,
LoadLibrary or LoadLibraryEx returns NULL. If LoadLibrary or LoadLibraryEx succeeds,
it returns a handle to the DLL module. The process can use this handle to identify the
DLL in a call to the GetProcAddress, FreeLibrary, or FreeLibraryAndExitThread function.
The process can use GetProcAddress to get the address of an exported function in the
DLL using a DLL module handle returned by LoadLibrary or LoadLibraryEx,
GetModuleHandle.
When the DLL module is no longer needed, the process can call FreeLibrary or
FreeLibraryAndExitThread. These functions decrement the module reference count and
unmap the DLL code from the virtual address space of the process if the reference count
is zero.
Run-time dynamic linking enables the process to continue running even if a DLL is not
available. The process can then use an alternate method to accomplish its objective. For
example, if a process is unable to locate one DLL, it can try to use another, or it can
notify the user of an error. If the user can provide the full path of the missing DLL, the
process can use this information to load the DLL even though it is not in the normal
search path. This situation contrasts with load-time linking, in which the system simply
terminates the process if it cannot find the DLL.
Run-time dynamic linking can cause problems if the DLL uses the DllMain function to
perform initialization for each thread of a process, because the entry-point is not called
for threads that existed before LoadLibrary or LoadLibraryEx is called. For an example
showing how to deal with this problem, see Using Thread Local Storage in a Dynamic-
Link Library.
Related topics
Using Run-time Dynamic Linking
Feedback
Was this page helpful? ツ Yes ト No
It's common for multiple versions of the same dynamic-link library (DLL) to exist in
different file system locations within an operating system (OS). You can control the
specific location from which any given DLL is loaded by specifying a full path. But if you
don't use that method, then the system searches for the DLL at load time as described in
this topic. The DLL loader is the part of the operating system (OS) that loads DLLs and/or
resolves references to DLLs.
Tip
If a DLL has dependencies, then the system searches for the dependent DLLs as if they
were loaded by using only their module names. That's true even if the first DLL was
loaded by specifying a full path.
When the system searches for a module or its dependencies, it always uses the search
order for packaged apps; even if a dependency is not packaged app code.
1. DLL redirection.
2. API sets.
3. Desktop apps only (not UWP apps). SxS manifest redirection.
4. Loaded-module list.
5. Known DLLs.
6. The package dependency graph of the process. This is the application's package
plus any dependencies specified as <PackageDependency> in the <Dependencies>
section of the application's package manifest. Dependencies are searched in the
order they appear in the manifest.
7. The folder the calling process was loaded from (the executable's folder).
8. The system folder ( %SystemRoot%\system32 ).
If a DLL has dependencies, then the system searches for the dependent DLLs as if they
were loaded with just their module names (even if the first DLL was loaded by specifying
a full path).
) Important
If an attacker gains control of one of the directories that's searched, then it can
place a malicious copy of the DLL in that folder. For ways to help prevent such
attacks, see Dynamic-link library security.
Safe DLL search mode (which is enabled by default) moves the user's current folder later
in the search order. To disable safe DLL search mode, create the
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session
If safe DLL search mode is enabled, then the search order is as follows:
1. DLL Redirection.
2. API sets.
3. SxS manifest redirection.
4. Loaded-module list.
5. Known DLLs.
6. Windows 11, version 21H2 (10.0; Build 22000), and later. The package dependency
graph of the process. This is the application's package plus any dependencies
specified as <PackageDependency> in the <Dependencies> section of the
application's package manifest. Dependencies are searched in the order they
appear in the manifest.
7. The folder from which the application loaded.
8. The system folder. Use the GetSystemDirectory function to retrieve the path of
this folder.
9. The 16-bit system folder. There's no function that obtains the path of this folder,
but it is searched.
10. The Windows folder. Use the GetWindowsDirectory function to get the path of
this folder.
11. The current folder.
12. The directories that are listed in the PATH environment variable. This doesn't
include the per-application path specified by the App Paths registry key. The App
Paths key isn't used when computing the DLL search path.
If safe DLL search mode is disabled, then the search order is the same except that the
current folder moves from position 11 to position 8 in the sequence (immediately after
step 7. The folder from which the application loaded).
7 Note
The standard search order of the process will also be affected by calling the
SetDllDirectory function in the parent process before the start of the current
process.
If you specify an alternate search strategy, then its behavior continues until all
associated executable modules have been located. After the system starts processing
DLL initialization routines, the system reverts to the standard search strategy.
The LoadLibraryEx function supports an alternate search order if the call specifies
LOAD_WITH_ALTERED_SEARCH_PATH, and the lpFileName parameter specifies an
absolute path.
The standard search strategy begins (after the initial steps) in the calling
application's folder.
The alternate search strategy specified by LoadLibraryEx with
LOAD_WITH_ALTERED_SEARCH_PATH begins (after the initial steps) in the folder
of the executable module that LoadLibraryEx is loading.
If safe DLL search mode is enabled, then the alternate search order is as follows:
If safe DLL search mode is disabled, then the alternate search order is the same except
that the current folder moves from position 11 to position 8 in the sequence
(immediately after step 7. The folder specified by lpFileName).
If the lpPathName parameter is an empty string, then the call removes the current folder
from the search order.
SetDllDirectory effectively disables safe DLL search mode while the specified folder is in
the search path. To restore safe DLL search mode based on the SafeDllSearchMode
registry value, and restore the current folder to the search order, call SetDllDirectory
with lpPathName as NULL.
The directories that are searched depend on the flags specified with
SetDefaultDllDirectories or LoadLibraryEx. If you use more than one flag, then the
corresponding directories are searched in this order:
Related topics
Application registration
Dynamic-link library redirection
Dynamic-link library security
Side-by-side components
AddDllDirectory
LoadLibrary
LoadLibraryEx
LoadPackagedLibrary
SetDefaultDllDirectories
SetDllDirectory
Feedback
Was this page helpful? ツ Yes ト No
Variable Scope
Variables that are declared as global in a DLL source code file are treated as global
variables by the compiler and linker, but each process that loads a given DLL gets its
own copy of that DLL's global variables. The scope of static variables is limited to the
block in which the static variables are declared. As a result, each process has its own
instance of the DLL global and static variables by default.
7 Note
Your development tools may allow you to override the default behavior. For
example, the Visual C++ compiler supports #pragma section and the linker
supports the /SECTION option. For more information, see the documentation
included with your development tools.
A DLL can use file mapping to allocate memory that can be shared among processes.
For a general discussion of how to use file mapping to create named shared memory,
see File Mapping. For an example that uses the DllMain function to set up shared
memory using file mapping, see Using Shared Memory in a Dynamic-Link Library.
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 or
LoadLibraryEx 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).
Feedback
Was this page helpful? ツ Yes ト No
The DLL loader is the part of the operating system (OS) that resolves references to DLLs,
loads them, and links them. Dynamic-link library (DLL) redirection is one of the
techniques by which you can influence the behavior of the DLL loader, and control which
one of several candidate DLLs it actually loads.
Other names for this feature include .local, Dot Local, DotLocal, and Dot Local Debugging.
The DLL loader looks in the folder that the calling process was loaded from (the
executable's folder) before it looks in other file system locations. So one workaround is
to install the DLL that your app needs in your executable's folder. That effectively makes
the DLL private.
But that doesn't solve the problem for COM. Two incompatible versions of a COM server
can be installed and registered (even in different file system locations), but there's only
one place to register the COM server. So only the latest registered COM server will be
activated.
But you can use redirection to load private copies of DLLs (for purposes such as testing,
or measuring the performance impact of a code change).
If you want to contribute to the source code in the public WindowsAppSDK GitHub
repository, then you'll want to test your changes. And, again, that's a scenario for which
you can use redirection to load your private copies of DLLs instead of the versions that
ship with the Windows App SDK.
Your options
In fact, there are two ways to ensure that your app uses the version of the DLL that you
want it to:
Tip
If you're a developer or an administrator, then you should use DLL redirection for
existing applications. That's because it doesn't require any changes to the app
itself. But if you're creating a new app, or updating an existing app, and you want
to isolate your app from potential problems, then create a side-by-side component.
1, and restart your computer. Or use the command below (and restart your computer).
Console
With that registry value set, DotLocal DLL redirection is respected even if the app has an
application manifest.
<Drive>:\<path_to_package>\microsoft.system.package.metadata\application.local\
If you're able to edit your .vcxproj file, then a convenient way to cause that special
folder to be created and deployed with your package is to add some extra steps to the
build in your .vcxproj :
XML
<ItemDefinitionGroup>
<PreBuildEvent>
<Command>
del $(FinalAppxManifestName) 2>nul
<!-- [[Using_.local_(DotLocal)_with_a_packaged_app]] This makes
the extra DLL deployed via F5 get loaded instead of the system one. -->
if NOT EXIST
$(IntDir)\microsoft.system.package.metadata\application.local MKDIR
$(IntDir)\microsoft.system.package.metadata\application.local
if EXIST "<A.dll>" copy /y "<A.dll>"
$(IntDir)\microsoft.system.package.metadata\application.local 2>nul
if EXIST "<B.dll>" copy /y "<B.dll>"
$(IntDir)\microsoft.system.package.metadata\application.local 2>nul
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<!-- Include any locally built system experience -->
<Media
Include="$(IntDir)\microsoft.system.package.metadata\application.local\**">
<Link>microsoft.system.package.metadata\application.local</Link>
</Media>
</ItemGroup>
1. Set up a PreBuildEvent for your Visual Studio Start Without Debugging (or Start
Debugging) experience.
XML
<ItemDefinitionGroup>
<PreBuildEvent>
2. Ensure that you have the correct folder structure in your intermediate directory.
XML
3. Copy any DLLs that you've built locally (and wish to use in preference to the
system-deployed DLLs) into the application.local directory. You can pick up DLLs
from just about anywhere (we recommended that you use the available macros for
your .vcxproj ). Just be sure that those DLLs build before this project does;
otherwise they'll be missing. Two template copy commands are shown here; use as
many as you need, and edit the <path-to-local-dll> placeholders.
XML
4. Lastly, indicate that you want to include the special directory and its contents in
the deployed package.
XML
<ItemGroup>
<!-- Include any locally built system experience -->
<Media
Include="$(IntDir)\microsoft.system.package.metadata\application.local\
**">
<Link>microsoft.system.package.metadata\application.local</Link>
</Media>
</ItemGroup>
The approach described here (using an intermediate directory) keeps your source code
control enlistment clean, and reduces the possibility of accidentally committing a
compiled binary.
Next, all you need to do is to (re)deploy your project. In order to get a clean, full
(re)deployment, you might also have to uninstall/clean out the existing deployment on
your target device.
Copying the binaries manually
If you're not able to use your .vcxproj in the way shown above, then you can achieve
the same ends by hand on your target device with a couple of simple steps.
2. Use that InstallLocation to change the ACLs to allow yourself to create folders/copy
files. Edit the <InstallLocation> placeholders in this script, and run the script:
Console
cd <InstallLocation>\Microsoft.system.package.metadata
takeown /F . /A
icacls . /grant Administrators:F
md
<InstallLocation>\Microsoft.system.package.metadata\application.local
3. Lastly, manually copy any DLLs that you've built locally (and wish to use in
preference to the system-deployed DLLs) into the application.local directory,
and [re]start the app.
redirection file in the executable's folder. You must also install the DLLs in the
executable's folder.
The contents of a redirection file are ignored; its presence alone causes the DLL loader to
check the executable's folder first whenever it loads a DLL. To mitigate the COM
problem, that redirection applies both to full path and partial name loading. So
redirection happens in the COM case and also regardless of the path specified to
LoadLibrary or LoadLibraryEx. If the DLL isn't found in the executable's folder, then
loading follows its usual search order. For example, if the app C:\myapp\myapp.exe calls
LoadLibrary using the following path:
If you're using DLL redirection, and the app doesn't have access to all drives and
directories in the search order, then LoadLibrary stops searching as soon as access is
denied. If you're not using DLL redirection, then LoadLibrary skips directories that it
can't access, and then it continues searching.
It's good practice to install app DLLs in the same folder that contains the app; even if
you're not using DLL redirection. That ensures that installing the app doesn't overwrite
other copies of the DLL (thereby causing other apps to fail). Also, if you follow this good
practice, then other apps don't overwrite your copy of the DLL (and don't cause your
app to fail).
Feedback
Was this page helpful? Yes No
Dynamic-Link Library Updates
Article • 01/07/2021
It is sometimes necessary to replace a DLL with a newer version. Before replacing a DLL,
perform a version check to ensure that you are replacing an older version with a newer
version. It is possible to replace a DLL that is in use. The method you use to replace DLLs
that are in use depends on the operating system you are using. On Windows XP and
later, applications should use Isolated Applications and Side-by-side Assemblies.
It is not necessary to restart the computer if you perform the following steps:
1. Use the MoveFileEx function to rename the DLL being replaced. Do not specify
MOVEFILE_COPY_ALLOWED, and make sure the renamed file is on the same
volume that contains the original file. You could also simply rename the file in the
same directory by giving it a different extension.
2. Copy the new DLL to the directory that contains the renamed DLL. All applications
will now use the new DLL.
3. Use MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT to delete the renamed DLL.
Before you make this replacement, applications will use the original DLL until it is
unloaded. After you make the replacement, applications will use the new DLL. When you
write a DLL, you must be careful to ensure that it is prepared for this situation, especially
if the DLL maintains global state information or communicates with other services. If the
DLL is not prepared for a change in global state information or communication
protocols, updating the DLL will require you to restart the computer to ensure that all
applications are using the same version of the DLL.
Feedback
Was this page helpful? ツ Yes ト No
For example, suppose an application is designed to load a DLL from the user's current
directory and fail gracefully if the DLL is not found. The application calls LoadLibrary
with just the name of the DLL, which causes the system to search for the DLL. Assuming
safe DLL search mode is enabled and the application is not using an alternate search
order, the system searches directories in the following order:
Continuing the example, an attacker with knowledge of the application gains control of
the current directory and places a malicious copy of the DLL in that directory. When the
application issues the LoadLibrary call, the system searches for the DLL, finds the
malicious copy of the DLL in the current directory, and loads it. The malicious copy of
the DLL then runs within the application and gains the privileges of the user.
Developers can help safeguard their applications against DLL preloading attacks by
following these guidelines:
Wherever possible, specify a fully qualified path when using the LoadLibrary,
LoadLibraryEx, CreateProcess, or ShellExecute functions.
Consider using DLL redirection or a manifest to ensure that your application uses
the correct DLL.
When using the standard search order, make sure that safe DLL search mode is
enabled. This places the user's current directory later in the search order,
increasing the chances that Windows will find a legitimate copy of the DLL before a
malicious copy. Safe DLL search mode is enabled by default starting with
Windows XP with Service Pack 2 (SP2) and is controlled by the
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session
Manager\SafeDllSearchMode registry value. For more information, see Dynamic-
Link Library Search Order.
Consider removing the current directory from the standard search path by calling
SetDllDirectory with an empty string (""). This should be done once early in
process initialization, not before and after calls to LoadLibrary. Be aware that
SetDllDirectory affects the entire process and that multiple threads calling
SetDllDirectory with different values can cause undefined behavior. If your
application loads third-party DLLs, test carefully to identify any incompatibilities.
Do not use the SearchPath function to retrieve a path to a DLL for a subsequent
LoadLibrary call unless safe process search mode is enabled. When safe process
search mode is not enabled, the SearchPath function uses a different search order
than LoadLibrary and is likely to first search the user's current directory for the
specified DLL. To enable safe process search mode for the SearchPath function, use
the SetSearchPathMode function with
BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE. This moves the current
directory to the end of the SearchPath search list for the life of the process. Note
that the current directory is not removed from the search path, so if the system
does not find a legitimate copy of the DLL before it reaches the current directory,
the application is still vulnerable. As with SetDllDirectory, calling
SetSearchPathMode should be done early in process initialization and it affects
the entire process. If your application loads third-party DLLs, test carefully to
identify any incompatibilities.
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 copy of the
DLL is in the search path, the malicious copy of the DLL may be loaded. Instead,
use the recommended techniques described in Getting the System Version.
The Process Monitor tool can be used to help identify DLL load operations that might be
vulnerable. The Process Monitor tool can be downloaded from
https://technet.microsoft.com/sysinternals/bb896645.aspx .
The following procedure describes how to use Process Monitor to examine DLL load
operations in your application.
Operation is CreateFile
Operation is LoadImage
Path contains .cpl
Path contains .dll
Path contains .drv
Path contains .exe
Path contains .ocx
Path contains .scr
Path contains .sys
4. Attempt to start your application with the current directory set to a specific
directory. For example, double-click a file with an extension whose file handler is
assigned to your application.
5. Check Process Monitor output for paths that look suspicious, such as a call to the
current directory to load a DLL. This kind of call might indicate a vulnerability in
your application.
Feedback
Was this page helpful? ツ Yes ト No
About AppInit_DLLs
The AppInit_DLLs infrastructure provides an easy way to hook system APIs by allowing
custom DLLs to be loaded into the address space of every interactive application.
Applications and malicious software both use AppInit DLLs for the same basic reason,
which is to hook APIs; after the custom DLL is loaded, it can hook a well-known system
API and implement alternate functionality. Only a small set of modern legitimate
applications use this mechanism to load DLLs, while a large set of malware use this
mechanism to compromise systems. Even legitimate AppInit_DLLs can unintentionally
cause system deadlocks and performance problems, therefore usage of AppInit_DLLs is
not recommended.
Please note that secure boot is a UEFI protocol and not a Windows 8 feature. More info
on UEFI and the secure boot protocol specification can be found at
https://www.uefi.org .
Summary
The AppInit_DLLs mechanism is not a recommended approach for legitimate
applications because it can lead to system deadlocks and performance problems.
The AppInit_DLLs mechanism is disabled by default when secure boot is enabled.
Using AppInit_DLLs in a Windows 8 desktop app is a Windows desktop app
certification failure.
Feedback
Was this page helpful? ツ Yes ト No
**Updated: **
Important APIs
DllMain
LoadLibraryEx
CreateProcess
Creating DLLs presents a number of challenges for developers. DLLs do not have
system-enforced versioning. When multiple versions of a DLL exist on a system, the ease
of being overwritten coupled with the lack of a versioning schema creates dependency
and API conflicts. Complexity in the development environment, the loader
implementation, and the DLL dependencies has created fragility in load order and
application behavior. Lastly, many applications rely on DLLs and have complex sets of
dependencies that must be honored for the applications to function properly. This
document provides guidelines for DLL developers to help in building more robust,
portable, and extensible DLLs.
The ideal DllMain would be just an empty stub. However, given the complexity of many
applications, this is generally too restrictive. A good rule of thumb for DllMain is to
postpone as much initialization as possible. Lazy initialization increases robustness of
the application because this initialization is not performed while the loader lock is held.
Also, lazy initialization enables you to safely use much more of the Windows API.
Some initialization tasks cannot be postponed. For example, a DLL that depends on a
configuration file should fail to load if the file is malformed or contains garbage. For this
type of initialization, the DLL should attempt the action and fail quickly rather than
waste resources by completing other work.
You should never perform the following tasks from within DllMain:
It is important to note that the loader calls DllMain with the loader lock already
acquired, so the loader lock should have the highest precedence in the locking
hierarchy. Also note that code only has to acquire the locks it requires for proper
synchronization; it does not have to acquire every single lock that is defined in the
hierarchy. For example, if a section of code requires only locks A and C for proper
synchronization, then the code should acquire lock A before it acquires lock C; it is not
necessary for the code to also acquire lock B. Furthermore, DLL code cannot explicitly
acquire the loader lock. If the code must call an API such as GetModuleFileName that
can indirectly acquire the loader lock and the code must also acquire a private lock, then
the code should call GetModuleFileName before it acquires lock P, thus ensuring that
load order is respected.
Figure 2 is an example that illustrates lock order inversion. Consider a DLL whose main
thread contains DllMain. The library loader acquires the loader lock L and then calls into
DllMain. The main thread creates synchronization objects A, B, and G to serialize access
to its data structures and then tries to acquire lock G. A worker thread that has already
successfully acquired lock G then calls a function such as GetModuleHandle that
attempts to acquire the loader lock L. Thus, the worker thread is blocked on L and the
main thread is blocked on G, resulting in a deadlock.
To prevent deadlocks that are caused by lock order inversion, all threads should attempt
to acquire synchronization objects in the defined load order at all times.
By the time DllMain is called at process exit, all the process’s threads have been
forcibly cleaned up and there is a chance that the address space is inconsistent.
Synchronization is not required in this case. In other words, the ideal
DLL_PROCESS_DETACH handler is empty.
Windows Vista ensures that core data structures (environment variables, current
directory, process heap, and so on) are in a consistent state. However, other data
structures can be corrupted, so cleaning memory is not safe.
Persistent state that needs to be saved must be flushed to permanent storage.
If a DLL is unloaded after all its threads have been created, but before they begin
executing, the threads may crash. If the DLL created threads in its DllMain as part of its
initialization, some threads may not have finished initialization and their
DLL_THREAD_ATTACH message is still waiting to be delivered to the DLL. In this
situation, if the DLL is unloaded, it will begin terminating threads. However, some
threads may be blocked behind the loader lock. Their DLL_THREAD_ATTACH messages
are processed after the DLL has been unmapped, causing the process to crash.
Recommendations
The following are recommended guidelines:
Feedback
Was this page helpful? ツ Yes ト No
The following example is the source code needed to create a simple DLL, Myputs.dll. It
defines a simple string-printing function called myPuts. The Myputs DLL does not define
an entry-point function, because it is linked with the C run-time library and has no
initialization or cleanup functions of its own to perform.
To build the DLL, follow the directions in the documentation included with your
development tools.
For an example that uses myPuts, see Using Load-Time Dynamic Linking or Using Run-
Time Dynamic Linking.
C++
#include <windows.h>
hConout = CreateFileW(L"CONOUT$",
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hConout)
return EOF;
#ifdef __cplusplus
}
#endif
Feedback
Was this page helpful? ツ Yes ト No
After you have created a DLL, you can use the functions it defines in an application. The
following is a simple console application that uses the myPuts function exported from
Myputs.dll (see Creating a Simple Dynamic-Link Library).
Because this example calls the DLL function explicitly, the module for the application
must be linked with the import library Myputs.lib. For more information about building
DLLs, see the documentation included with your development tools.
C++
#include <windows.h>
int main(VOID)
{
int Ret = 1;
Related topics
Load-Time Dynamic Linking
Feedback
Was this page helpful? ツ Yes ト No
You can use the same DLL in both load-time and run-time dynamic linking. The
following example uses the LoadLibrary function to get a handle to the Myputs DLL (see
Creating a Simple Dynamic-Link Library). If LoadLibrary succeeds, the program uses the
returned handle in the GetProcAddress function to get the address of the DLL's myPuts
function. After calling the DLL function, the program calls the FreeLibrary function to
unload the DLL.
Because the program uses run-time dynamic linking, it is not necessary to link the
module with an import library for the DLL.
C++
#include <windows.h>
#include <stdio.h>
hinstLib = LoadLibrary(TEXT("MyPuts.dll"));
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "myPuts");
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (L"Message sent to the DLL function\n");
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
return 0;
Related topics
Run-Time Dynamic Linking
Feedback
Was this page helpful? ツ Yes ト No
The following example demonstrates how the DLL entry-point function can use a file-
mapping object to set up memory that can be shared by processes that load the DLL.
The shared DLL memory persists only as long as the DLL is loaded. Applications can use
the SetSharedMem and GetSharedMem functions to access the shared memory.
Note that while you can specify default security attributes by passing in a NULL value for
the lpAttributes parameter of CreateFileMapping, you may choose to use a
SECURITY_ATTRIBUTES structure to provide additional security.
C++
#include <windows.h>
#include <memory.h>
switch (fdwReason)
{
// DLL load due to process initialization or LoadLibrary
case DLL_PROCESS_ATTACH:
hMapObject = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security attributes
PAGE_READWRITE, // read/write access
0, // size: high 32-bits
SHMEMSIZE, // size: low 32-bits
TEXT("dllmemfilemap")); // name of map object
if (hMapObject == NULL)
return FALSE;
lpvMem = MapViewOfFile(
hMapObject, // object to map view of
FILE_MAP_WRITE, // read/write access
0, // high offset: map from
0, // low offset: beginning
0); // default: map entire file
if (lpvMem == NULL)
return FALSE;
if (fInit)
memset(lpvMem, '\0', SHMEMSIZE);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
fIgnore = UnmapViewOfFile(lpvMem);
fIgnore = CloseHandle(hMapObject);
break;
default:
break;
}
return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}
Shared memory can be mapped to a different address in each process. For this reason,
each process has its own instance of lpvMem, which is declared as a global variable so
that it is available to all DLL functions. The example assumes that the DLL global data is
not shared, so each process that loads the DLL has its own instance of lpvMem.
Note that the shared memory is released when the last handle to the file-mapping
object is closed. To create persistent shared memory, you would need to ensure that
some process always has an open handle to the file-mapping object.
This process uses the SetSharedMem function implemented by the DLL to write the
string "This is a test string" to the shared memory. It also starts a child process that will
read the string from the shared memory.
C++
// Parent process
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
bFuncRetn = CreateProcess(NULL,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (bFuncRetn == 0)
{
printf("CreateProcess failed (%)\n", GetLastError());
return INVALID_HANDLE_VALUE;
}
else
{
CloseHandle(piProcInfo.hThread);
return piProcInfo.hProcess;
}
}
if (argc == 1)
{
printf("Please specify an input file");
ExitProcess(0);
}
This process uses the GetSharedMem function implemented by the DLL to read a string
from the shared memory. It is started by the parent process above.
C++
// Child process
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
GetSharedMem(cBuf, MAX_PATH);
return 0;
}
Related topics
Dynamic-Link Library Data
Feedback
Was this page helpful? ツ Yes ト No
Get help at Microsoft Q&A
Using Thread Local Storage in a
Dynamic-Link Library
Article • 01/07/2021
This section shows the use of a DLL entry-point function to set up a thread local storage
(TLS) index to provide private storage for each thread of a multithreaded process.
The TLS index is stored in a global variable, making it available to all of the DLL
functions. This example assumes that the DLL's global data is not shared, because the
TLS index is not necessarily the same for each process that loads the DLL.
The entry-point function uses the TlsAlloc function to allocate a TLS index whenever a
process loads the DLL. Each thread can then use this index to store a pointer to its own
block of memory.
When the entry-point function is called with the DLL_PROCESS_ATTACH value, the code
performs the following actions:
Each time the process creates a new thread, the entry-point function is called with the
DLL_THREAD_ATTACH value. The entry-point function then allocates a block of memory
for the new thread and stores a pointer to it by using the TLS index.
When a function requires access to the data associated with a TLS index, specify the
index in a call to the TlsGetValue function. This retrieves the contents of the TLS slot for
the calling thread, which in this case is a pointer to the memory block for the data.
When a process uses load-time linking with this DLL, the entry-point function is
sufficient to manage the thread local storage. Problems can occur with a process that
uses run-time linking because the entry-point function is not called for threads that exist
before the LoadLibrary function is called, so TLS memory is not allocated for these
threads. This example solves this problem by checking the value returned by the
TlsGetValue function and allocating memory if the value indicates that the TLS slot for
this thread is not set.
When each thread no longer needs to use a TLS index, it must free the memory whose
pointer is stored in the TLS slot. When all threads have finished using a TLS index, use
the TlsFree function to release the index.
C++
#include <windows.h>
switch (fdwReason)
{
// The DLL is loading due to process
// initialization or a call to LoadLibrary.
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
// Release the allocated memory for this thread.
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
LocalFree((HLOCAL) lpvData);
break;
case DLL_PROCESS_DETACH:
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
LocalFree((HLOCAL) lpvData);
TlsFree(dwTlsIndex);
break;
default:
break;
}
return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}
__declspec(dllexport)
BOOL WINAPI StoreData(DWORD dw)
{
LPVOID lpvData;
DWORD * pData; // The stored memory pointer
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData == NULL)
{
lpvData = (LPVOID) LocalAlloc(LPTR, 256);
if (lpvData == NULL)
return FALSE;
if (!TlsSetValue(dwTlsIndex, lpvData))
return FALSE;
}
(*pData) = dw;
return TRUE;
}
__declspec(dllexport)
BOOL WINAPI GetData(DWORD *pdw)
{
LPVOID lpvData;
DWORD * pData; // The stored memory pointer
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData == NULL)
return FALSE;
The following code demonstrates the use of the DLL functions defined in the previous
example.
C++
#include <windows.h>
#include <stdio.h>
#define THREADCOUNT 4
#define DLL_NAME TEXT("testdll")
VOID ErrorExit(LPSTR);
if(!StoreData(GetCurrentThreadId()))
ErrorExit("StoreData error");
int main(VOID)
{
DWORD IDThread;
HANDLE hThread[THREADCOUNT];
int i;
HMODULE hm;
hm = LoadLibrary(DLL_NAME);
if(!hm)
{
ErrorExit("DLL failed to load");
}
FreeLibrary(hm);
return 0;
}
Related topics
Dynamic-Link Library Data
Feedback
Was this page helpful? ツ Yes ト No
Feedback
Was this page helpful? ツ Yes ト No
Function Description
DisableThreadLibraryCalls Disables thread attach and thread detach notifications for the
specified DLL.
FreeLibrary Decrements the reference count of the loaded DLL. When the
reference count reaches zero, the module is unmapped from the
address space of the calling process.
FreeLibraryAndExitThread Decrements the reference count of a loaded DLL by one, and then
calls ExitThread to terminate the calling thread.
GetModuleFileName Retrieves the fully qualified path for the file containing the specified
module.
GetModuleFileNameEx Retrieves the fully qualified path for the file containing the specified
module.
LoadLibrary Maps the specified executable module into the address space of the
calling process.
LoadLibraryEx Maps the specified executable module into the address space of the
calling process.
LoadPackagedLibrary Maps the specified packaged module and its dependencies into the
address space of the calling process. Only Windows Store apps can
call this function.
RemoveDllDirectory Removes a directory that was added to the process DLL search path
by using AddDllDirectory.
Function Description
SetDllDirectory Modifies the search path used to locate DLLs for the application.
Obsolete Functions
These functions are provided only for compatibility with 16-bit versions of Windows.
LoadModule
Feedback
Was this page helpful? ツ Yes ト No
Syntax
C++
DLL_DIRECTORY_COOKIE AddDllDirectory(
[in] PCWSTR NewDirectory
);
Parameters
[in] NewDirectory
An absolute path to the directory to add to the search path. For example, to add the
directory Dir2 to the process DLL search path, specify \Dir2. For more information about
paths, see Naming Files, Paths, and Namespaces.
Return value
If the function succeeds, the return value is an opaque pointer that can be passed to
RemoveDllDirectory to remove the DLL from the process DLL search path.
If the function fails, the return value is zero. To get extended error information, call
GetLastError.
Remarks
The AddDllDirectory function can be used to add any absolute path to the set of
directories that are searched for a DLL. If SetDefaultDllDirectories is first called with
LOAD_LIBRARY_SEARCH_USER_DIRS, directories specified with AddDllDirectory are
added to the process DLL search path. Otherwise, directories specified with the
AddDllDirectory function are used only for LoadLibraryEx function calls that specify
LOAD_LIBRARY_SEARCH_USER_DIRS.
If AddDllDirectory is used to add more than one directory to the process DLL search
path, the order in which those directories are searched is unspecified.
Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: To
use this function in an application, call GetProcAddress to retrieve the function's address
from Kernel32.dll. KB2533623 must be installed on the target platform.
Requirements
DLL Kernel32.dll
Feedback
Was this page helpful? ツ Yes ト No
Syntax
C++
BOOL DisableThreadLibraryCalls(
[in] HMODULE hLibModule
);
Parameters
[in] hLibModule
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. The DisableThreadLibraryCalls function fails
if the DLL specified by hModule has active static thread local storage, or if hModule is an
invalid module handle. To get extended error information, call GetLastError.
Remarks
The DisableThreadLibraryCalls function lets a DLL disable the DLL_THREAD_ATTACH
and DLL_THREAD_DETACH notification calls. This can be a useful optimization for
multithreaded applications that have many DLLs, frequently create and delete threads,
and whose DLLs do not need these thread-level notifications of
attachment/detachment. A remote procedure call (RPC) server application is an example
of such an application. In these sorts of applications, DLL initialization routines often
remain in memory to service DLL_THREAD_ATTACH and DLL_THREAD_DETACH
notifications. By disabling the notifications, the DLL initialization code is not paged in
because a thread is created or deleted, thus reducing the size of the application's
working code set. To implement the optimization, modify a DLL's DLL_PROCESS_ATTACH
code to call DisableThreadLibraryCalls.
Do not call this function from a DLL that is linked to the static C run-time library (CRT).
The static CRT requires DLL_THREAD_ATTACH and DLL_THREAD_DETATCH notifications
to function properly.
This function does not perform any optimizations if static Thread Local Storage (TLS) is
enabled. Static TLS is enabled when using thread_local variables, __declspec( thread )
variables, or function-local static.
Requirements
ノ Expand table
Minimum supported server Windows Server 2003 [desktop apps | UWP apps]
Library Kernel32.lib
DLL Kernel32.dll
See also
Dynamic-Link Library Entry-Point Function
FreeLibraryAndExitThread
Vertdll APIs available in VBS enclaves
Feedback
Was this page helpful? Yes No
DllMain entry point
Article • 09/02/2022
An optional entry point into a dynamic-link library (DLL). When the system starts or
terminates a process or thread, it calls the entry-point function for each loaded DLL
using the first thread of the process. The system also calls the entry-point function for a
DLL when it is loaded or unloaded using the LoadLibrary and FreeLibrary functions.
Example
C++
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
if (lpvReserved != nullptr)
{
break; // do not do cleanup if process termination scenario
}
There are significant limits on what you can safely do in a DLL entry point. See
General Best Practices for specific Windows APIs that are unsafe to call in DllMain.
If you need anything but the simplest initialization then do that in an initialization
function for the DLL. You can require applications to call the initialization function
after DllMain has run and before they call any other functions in the DLL.
Syntax
C++
Parameters
hinstDLL [in]
A handle to the DLL module. The value is the base address of the DLL. The HINSTANCE
of a DLL is the same as the HMODULE of the DLL, so hinstDLL can be used in calls to
functions that require a module handle.
fdwReason [in]
The reason code that indicates why the DLL entry-point function is being called. This
parameter can be one of the following values.
Value Meaning
DLL_PROCESS_ATTACH The DLL is being loaded into the virtual address space of the current
1 process as a result of the process starting up or as a result of a call to
LoadLibrary. DLLs can use this opportunity to initialize any instance
data or to use the TlsAlloc function to allocate a thread local storage
(TLS) index.
The lpvReserved parameter indicates whether the DLL is being loaded
statically or dynamically.
Value Meaning
DLL_PROCESS_DETACH The DLL is being unloaded from the virtual address space of the calling
0 process because it was loaded unsuccessfully or the reference count
has reached zero (the processes has either terminated or called
FreeLibrary one time for each time it called LoadLibrary).
The lpvReserved parameter indicates whether the DLL is being unloaded
as a result of a FreeLibrary call, a failure to load, or process termination.
The DLL can use this opportunity to call the TlsFree function to free any
TLS indices allocated by using TlsAlloc and to free any thread local
data.
Note that the thread that receives the DLL_PROCESS_DETACH
notification is not necessarily the same thread that received the
DLL_PROCESS_ATTACH notification.
DLL_THREAD_ATTACH The current process is creating a new thread. When this occurs, the
2 system calls the entry-point function of all DLLs currently attached to
the process. The call is made in the context of the new thread. DLLs can
use this opportunity to initialize a TLS slot for the thread. A thread
calling the DLL entry-point function with DLL_PROCESS_ATTACH does
not call the DLL entry-point function with DLL_THREAD_ATTACH.
Note that a DLL's entry-point function is called with this value only by
threads created after the DLL is loaded by the process. When a DLL is
loaded using LoadLibrary, existing threads do not call the entry-point
function of the newly loaded DLL.
DLL_THREAD_DETACH A thread is exiting cleanly. If the DLL has stored a pointer to allocated
3 memory in a TLS slot, it should use this opportunity to free the
memory. The system calls the entry-point function of all currently
loaded DLLs with this value. The call is made in the context of the
exiting thread.
lpvReserved [in]
Return value
When the system calls the DllMain function with the DLL_PROCESS_ATTACH value, the
function returns TRUE if it succeeds or FALSE if initialization fails. If the return value is
FALSE when DllMain is called because the process uses the LoadLibrary function,
LoadLibrary returns NULL. (The system immediately calls your entry-point function with
DLL_PROCESS_DETACH and unloads the DLL.) If the return value is FALSE when DllMain
is called during process initialization, the process terminates with an error. To get
extended error information, call GetLastError.
When the system calls the DllMain function with any value other than
DLL_PROCESS_ATTACH, the return value is ignored.
Remarks
DllMain is a placeholder for the library-defined function name. You must specify the
actual name you use when you build your DLL. For more information, see the
documentation included with your development tools.
During initial process startup or after a call to LoadLibrary, the system scans the list of
loaded DLLs for the process. For each DLL that has not already been called with the
DLL_PROCESS_ATTACH value, the system calls the DLL's entry-point function. This call is
made in the context of the thread that caused the process address space to change,
such as the primary thread of the process or the thread that called LoadLibrary. Access
to the entry point is serialized by the system on a process-wide basis. Threads in DllMain
hold the loader lock so no additional DLLs can be dynamically loaded or initialized.
There are cases in which the entry-point function is called for a terminating thread even
if the entry-point function was never called with DLL_THREAD_ATTACH for the thread:
The thread was the initial thread in the process, so the system called the entry-
point function with the DLL_PROCESS_ATTACH value.
The thread was already running when a call to the LoadLibrary function was made,
so the system never called the entry-point function for it.
When a DLL is unloaded from a process as a result of an unsuccessful load of the DLL,
termination of the process, or a call to FreeLibrary, the system does not call the DLL's
entry-point function with the DLL_THREAD_DETACH value for the individual threads of
the process. The DLL is only sent a DLL_PROCESS_DETACH notification. DLLs can take
this opportunity to clean up all resources for all threads known to the DLL.
The entry-point function should perform only simple initialization or termination tasks. It
must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these
functions), because this may create dependency loops in the DLL load order. This can
result in a DLL being used before the system has executed its initialization code.
Similarly, the entry-point function must not call the FreeLibrary function (or a function
that calls FreeLibrary) during process termination, because this can result in a DLL being
used after the system has executed its termination code.
Because Kernel32.dll is guaranteed to be loaded in the process address space when the
entry-point function is called, calling functions in Kernel32.dll does not result in the DLL
being used before its initialization code has been executed. Therefore, the entry-point
function can call functions in Kernel32.dll that do not load other DLLs. For example,
DllMain can create synchronization objects such as critical sections and mutexes, and
use TLS. Unfortunately, there is not a comprehensive list of safe functions in Kernel32.dll.
Calling functions that require DLLs other than Kernel32.dll may result in problems that
are difficult to diagnose. For example, calling User, Shell, and COM functions can cause
access violation errors, because some functions load other system components.
Conversely, calling functions such as these during termination can cause access violation
errors because the corresponding component may already have been unloaded or
uninitialized.
Because DLL notifications are serialized, entry-point functions should not attempt to
communicate with other threads or processes. Deadlocks may occur as a result.
For information on best practices when writing a DLL, see Dynamic-link library best
practices.
If your DLL is linked with the C run-time library (CRT), the entry point provided by the
CRT calls the constructors and destructors for global and static C++ objects. Therefore,
these restrictions for DllMain also apply to constructors and destructors and any code
that is called from them.
Consider calling DisableThreadLibraryCalls when receiving DLL_PROCESS_ATTACH,
unless your DLL is linked with static C run-time library (CRT).
Requirements
Requirement Value
Header Process.h
See also
Dynamic-Link Library Entry-Point Function
FreeLibrary
GetModuleFileName
LoadLibrary
TlsAlloc
TlsFree
DisableThreadLibraryCalls
Feedback
Was this page helpful? ツ Yes ト No
Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its
reference count. When the reference count reaches zero, the module is unloaded from
the address space of the calling process and the handle is no longer valid.
Syntax
C++
BOOL FreeLibrary(
[in] HMODULE hLibModule
);
Parameters
[in] hLibModule
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call the
GetLastError function.
Remarks
The system maintains a per-process reference count for each loaded module. A module
that was loaded at process initialization due to load-time dynamic linking has a
reference count of one. The reference count for a module is incremented each time the
module is loaded by a call to LoadLibrary. The reference count is also incremented by a
call to LoadLibraryEx unless the module is being loaded for the first time and is being
loaded as a data or image file.
The reference count is decremented each time the FreeLibrary or
FreeLibraryAndExitThread function is called for the module. When a module's reference
count reaches zero or the process terminates, the system unloads the module from the
address space of the process. Before unloading a library module, the system enables the
module to detach from the process by calling the module's DllMain function, if it has
one, with the DLL_PROCESS_DETACH value. Doing so gives the library module an
opportunity to clean up resources allocated on behalf of the current process. After the
entry-point function returns, the library module is removed from the address space of
the current process.
It is not safe to call FreeLibrary from DllMain. For more information, see the Remarks
section in DllMain.
Calling FreeLibrary does not affect other processes that are using the same module.
Use caution when calling FreeLibrary with a handle returned by GetModuleHandle. The
GetModuleHandle function does not increment a module's reference count, so passing
this handle to FreeLibrary can cause a module to be unloaded prematurely.
A thread that must unload the DLL in which it is executing and then terminate itself
should call FreeLibraryAndExitThread instead of calling FreeLibrary and ExitThread
separately. Otherwise, a race condition can occur. For details, see the Remarks section of
FreeLibraryAndExitThread.
Examples
Requirements
Minimum supported server Windows Server 2003 [desktop apps | UWP apps]
Library Kernel32.lib
DLL Kernel32.dll
See also
DllMain
FreeLibraryAndExitThread
GetModuleHandle
GetModuleHandleEx
LoadLibrary
Feedback
Was this page helpful? ツ Yes ト No
Decrements the reference count of a loaded dynamic-link library (DLL) by one, then calls
ExitThread to terminate the calling thread. The function does not return.
Syntax
C++
void FreeLibraryAndExitThread(
[in] HMODULE hLibModule,
[in] DWORD dwExitCode
);
Parameters
[in] hLibModule
A handle to the DLL module whose reference count the function decrements. The
LoadLibrary or GetModuleHandleEx function returns this handle.
Do not call this function with a handle returned by either the GetModuleHandleEx
function (with the GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT flag) or
the GetModuleHandle function, as they do not maintain a reference count for the
module.
[in] dwExitCode
Return value
None
Remarks
The FreeLibraryAndExitThread function allows threads that are executing within a DLL
to safely free the DLL in which they are executing and terminate themselves. If they were
to call FreeLibrary and ExitThread separately, a race condition would exist. The library
could be unloaded before ExitThread is called.
Requirements
Minimum supported server Windows Server 2003 [desktop apps | UWP apps]
Library Kernel32.lib
DLL Kernel32.dll
See also
DisableThreadLibraryCalls
ExitThread
FreeLibrary
Feedback
Was this page helpful? ツ Yes ト No
Retrieves the application-specific portion of the search path used to locate DLLs for the
application.
Syntax
C++
DWORD GetDllDirectoryA(
[in] DWORD nBufferLength,
[out] LPSTR lpBuffer
);
Parameters
[in] nBufferLength
[out] lpBuffer
A pointer to a buffer that receives the application-specific portion of the search path.
Return value
If the function succeeds, the return value is the length of the string copied to lpBuffer, in
characters, not including the terminating null character. If the return value is greater
than nBufferLength, it specifies the size of the buffer required for the path.
If the function fails, the return value is zero. To get extended error information, call
GetLastError.
Remarks
To compile an application that uses this function, define _WIN32_WINNT as 0x0502 or
later. For more information, see Using the Windows Headers.
7 Note
The winbase.h header defines GetDllDirectory as an alias which automatically
selects the ANSI or Unicode version of this function based on the definition of the
UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with
code that not encoding-neutral can lead to mismatches that result in compilation
or runtime errors. For more information, see Conventions for Function Prototypes.
Requirements
Minimum supported client Windows Vista, Windows XP with SP1 [desktop apps only]
Library Kernel32.lib
DLL Kernel32.dll
See also
Dynamic-Link Library Search Order
SetDllDirectory
Feedback
Was this page helpful? ツ Yes ト No
Syntax
C++
STDAPI DLLGetDocumentation
(
ITypeLib * ptlib,
ITypeInfo * ptinfo,
LCID lcid,
DWORD dwCtx,
BSTR * pbstrHelpString
);
Parameters
ptlib
ptinfo
lcid
dwCtx
pbstrHelpString
Return value
This function doesn't return a value.
Remarks
For more info, see To specify localized help strings on GitHub.
Requirements
Header N/A
Library N/A
DLL Unknown
See also
To specify localized help strings on GitHub
Feedback
Was this page helpful? ツ Yes ト No
Retrieves the fully qualified path for the file that contains the specified module. The
module must have been loaded by the current process.
To locate the file for a module that was loaded by another process, use the
GetModuleFileNameEx function.
Syntax
C++
DWORD GetModuleFileNameA(
[in, optional] HMODULE hModule,
[out] LPSTR lpFilename,
[in] DWORD nSize
);
Parameters
[in, optional] hModule
A handle to the loaded module whose path is being requested. If this parameter is
NULL, GetModuleFileName retrieves the path of the executable file of the current
process.
The GetModuleFileName function does not retrieve the path for modules that were
loaded using the LOAD_LIBRARY_AS_DATAFILE flag. For more information, see
LoadLibraryEx.
[out] lpFilename
A pointer to a buffer that receives the fully qualified path of the module. If the length of
the path is less than the size that the nSize parameter specifies, the function succeeds
and the path is returned as a null-terminated string.
If the length of the path exceeds the size that the nSize parameter specifies, the function
succeeds and the string is truncated to nSize characters including the terminating null
character.
Windows XP: The string is truncated to nSize characters and is not null-terminated.
The string returned will use the same format that was specified when the module was
loaded. Therefore, the path can be a long or short file name, and can use the prefix \\?
\ . For more information, see Naming a File.
[in] nSize
Return value
If the function succeeds, the return value is the length of the string that is copied to the
buffer, in characters, not including the terminating null character. If the buffer is too
small to hold the module name, the string is truncated to nSize characters including the
terminating null character, the function returns nSize, and the function sets the last error
to ERROR_INSUFFICIENT_BUFFER.
Windows XP: If the buffer is too small to hold the module name, the function returns
nSize. The last error code remains ERROR_SUCCESS. If nSize is zero, the return value is
zero and the last error code is ERROR_SUCCESS.
If the function fails, the return value is 0 (zero). To get extended error information, call
GetLastError.
Remarks
If a DLL is loaded in two processes, its file name in one process may differ in case from
its file name in the other process.
The global variable _pgmptr is automatically initialized to the full path of the executable
file, and can be used to retrieve the full path name of an executable file.
Examples
For an example, see Installing a Service.
7 Note
Requirements
Minimum supported server Windows Server 2003 [desktop apps | UWP apps]
Library Kernel32.lib
DLL Kernel32.dll
See also
Dynamic-Link Library Functions
GetModuleFileNameEx
GetModuleHandle
LoadLibrary
LoadLibraryEx
Feedback
Was this page helpful? ツ Yes ト No
Retrieves a module handle for the specified module. The module must have been
loaded by the calling process.
To avoid the race conditions described in the Remarks section, use the
GetModuleHandleEx function.
Syntax
C++
HMODULE GetModuleHandleA(
[in, optional] LPCSTR lpModuleName
);
Parameters
[in, optional] lpModuleName
The name of the loaded module (either a .dll or .exe file). If the file name extension is
omitted, the default library extension .dll is appended. The file name string can include a
trailing point character (.) to indicate that the module name has no extension. The string
does not have to specify a path. When specifying a path, be sure to use backslashes (\),
not forward slashes (/). The name is compared (case independently) to the names of
modules currently mapped into the address space of the calling process.
If this parameter is NULL, GetModuleHandle returns a handle to the file used to create
the calling process (.exe file).
The GetModuleHandle function does not retrieve handles for modules that were loaded
using the LOAD_LIBRARY_AS_DATAFILE flag. For more information, see LoadLibraryEx.
Return value
If the function succeeds, the return value is a handle to the specified module.
If the function fails, the return value is NULL. To get extended error information, call
GetLastError.
Remarks
The returned handle is not global or inheritable. It cannot be duplicated or used by
another process.
If lpModuleName does not include a path and there is more than one loaded module
with the same base name and extension, you cannot predict which module handle will
be returned. To work around this problem, you could specify a path, use side-by-side
assemblies, or use GetModuleHandleEx to specify a memory location rather than a DLL
name.
Examples
For an example, see Using Brushes.
7 Note
Library Kernel32.lib
DLL Kernel32.dll
See also
Dynamic-Link Library Functions
FreeLibrary
GetModuleFileName
GetModuleHandleEx
LoadLibrary
LoadLibraryEx
Feedback
Was this page helpful? ツ Yes ト No
Retrieves a module handle for the specified module and increments the module's
reference count unless GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT is
specified. The module must have been loaded by the calling process.
Syntax
C++
BOOL GetModuleHandleExA(
[in] DWORD dwFlags,
[in, optional] LPCSTR lpModuleName,
[out] HMODULE *phModule
);
Parameters
[in] dwFlags
This parameter can be zero or one or more of the following values. If the module's
reference count is incremented, the caller must use the FreeLibrary function to
decrement the reference count when the module handle is no longer needed.
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS (0x00000004)
The lpModuleName parameter is an address in the module.
GET_MODULE_HANDLE_EX_FLAG_PIN (0x00000001)
The module stays loaded until the process is terminated, no matter how many times
FreeLibrary is called.
The reference count for the module is not incremented. This option is equivalent to the
behavior of GetModuleHandle. Do not pass the retrieved module handle to the
FreeLibrary function; doing so can cause the DLL to be unmapped prematurely. For
more information, see Remarks.
The name of the loaded module (either a .dll or .exe file), or an address in the module (if
dwFlags is GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS).
For a module name, if the file name extension is omitted, the default library extension
.dll is appended. The file name string can include a trailing point character (.) to indicate
that the module name has no extension. The string does not have to specify a path.
When specifying a path, be sure to use backslashes (\), not forward slashes (/). The name
is compared (case independently) to the names of modules currently mapped into the
address space of the calling process.
If this parameter is NULL, the function returns a handle to the file used to create the
calling process (.exe file).
[out] phModule
A handle to the specified module. If the function fails, this parameter is NULL.
The GetModuleHandleEx function does not retrieve handles for modules that were
loaded using the LOAD_LIBRARY_AS_DATAFILE flag. For more information, see
LoadLibraryEx.
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, see
GetLastError.
Remarks
The handle returned is not global or inheritable. It cannot be duplicated or used by
another process.
If lpModuleName does not include a path and there is more than one loaded module
with the same base name and extension, you cannot predict which module handle will
be returned. To work around this problem, you could specify a path, use side-by-side
assemblies, or specify a memory location rather than a DLL name in the lpModuleName
parameter.
7 Note
Requirements
Minimum supported client Windows XP [desktop apps only]
Library Kernel32.lib
DLL Kernel32.dll
See also
Dynamic-Link Library Functions
FreeLibrary
GetModuleFileName
LoadLibrary
LoadLibraryEx
Feedback
Was this page helpful? ツ Yes ト No
Syntax
C++
FARPROC GetProcAddress(
[in] HMODULE hModule,
[in] LPCSTR lpProcName
);
Parameters
[in] hModule
A handle to the DLL module that contains the function or variable. The LoadLibrary,
LoadLibraryEx, LoadPackagedLibrary, or GetModuleHandle function returns this handle.
The GetProcAddress function does not retrieve addresses from modules that were
loaded using the LOAD_LIBRARY_AS_DATAFILE flag. For more information, see
LoadLibraryEx.
[in] lpProcName
The function or variable name, or the function's ordinal value. If this parameter is an
ordinal value, it must be in the low-order word; the high-order word must be zero.
Return value
If the function succeeds, the return value is the address of the exported function or
variable.
If the function fails, the return value is NULL. To get extended error information, call
GetLastError.
Remarks
The spelling and case of a function name pointed to by lpProcName must be identical to
that in the EXPORTS statement of the source DLL's module-definition (.def) file. The
exported names of functions may differ from the names you use when calling these
functions in your code. This difference is hidden by macros used in the SDK header files.
For more information, see Conventions for Function Prototypes.
The lpProcName parameter can identify the DLL function by specifying an ordinal value
associated with the function in the EXPORTS statement. GetProcAddress verifies that
the specified ordinal is in the range 1 through the highest ordinal value exported in the
.def file. The function then uses the ordinal as an index to read the function's address
from a function table.
If the .def file does not number the functions consecutively from 1 to N (where N is the
number of exported functions), an error can occur where GetProcAddress returns an
invalid, non-NULL address, even though there is no function with the specified ordinal.
If the function might not exist in the DLL module—for example, if the function is
available only on Windows Vista but the application might be running on Windows XP—
specify the function by name rather than by ordinal value and design your application to
handle the case when the function is not available, as shown in the following code
fragment.
C++
PGNSI pGNSI;
SYSTEM_INFO si;
ZeroMemory(&si, sizeof(SYSTEM_INFO));
Examples
Requirements
ノ Expand table
Minimum supported server Windows Server 2003 [desktop apps | UWP apps]
Library Kernel32.lib
DLL Kernel32.dll
See also
Dynamic-Link Library Functions
FreeLibrary
GetModuleHandle
LoadLibrary
LoadLibraryEx
LoadPackagedLibrary
Feedback
Was this page helpful? Yes No
LoadLibraryA function (libloaderapi.h)
Article02/09/2023
Loads the specified module into the address space of the calling process. The specified
module may cause other modules to be loaded.
Syntax
C++
HMODULE LoadLibraryA(
[in] LPCSTR lpLibFileName
);
Parameters
[in] lpLibFileName
The name of the module. This can be either a library module (a .dll file) or an executable
module (an .exe file). If the specified module is an executable module, static imports are
not loaded; instead, the module is loaded as if by LoadLibraryEx with the
DONT_RESOLVE_DLL_REFERENCES flag.
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
7 Note
Requirements
Library Kernel32.lib
DLL Kernel32.dll
See also
DllMain
FindResource
FreeLibrary
GetProcAddress
GetSystemDirectory
GetWindowsDirectory
LoadLibraryEx
LoadResource
SetDllDirectory
SetErrorMode
Feedback
Was this page helpful? ツ Yes ト No
Loads the specified module into the address space of the calling process. The specified
module may cause other modules to be loaded.
Syntax
C++
HMODULE LoadLibraryExA(
[in] LPCSTR lpLibFileName,
HANDLE hFile,
[in] DWORD dwFlags
);
Parameters
[in] lpLibFileName
A string that specifies the file name of the module to load. This name is not related to
the name stored in a library module itself, as specified by the LIBRARY keyword in the
module-definition (.def) file.
The module can be a library module (a .dll file) or an executable module (an .exe file). If
the specified module is an executable module, static imports are not loaded; instead, the
module is loaded as if DONT_RESOLVE_DLL_REFERENCES was specified. See the
dwFlags parameter for more information.
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.
If the string specifies a fully qualified path, the function searches only that path for the
module. When specifying a path, be sure to use backslashes (\), not forward slashes (/).
For more information about paths, see Naming Files, Paths, and Namespaces.
If the string specifies a module name without a path and more than one loaded module
has the same base name and extension, the function returns a handle to the module
that was loaded first.
If the string specifies a module name without a path and a module of the same name is
not already loaded, or if the string specifies a module name with a relative path, the
function searches for the specified module. The function also searches for modules if
loading the specified module causes the system to load other associated modules (that
is, if the module has dependencies). The directories that are searched and the order in
which they are searched depend on the specified path and the dwFlags parameter. For
more information, see Remarks.
If the function cannot find the module or one of its dependencies, the function fails.
hFile
[in] dwFlags
The action to be taken when loading the module. If no flags are specified, the behavior
of this function is identical to that of the LoadLibrary function. This parameter can be
one of the following values.
Value Meaning
LOAD_LIBRARY_AS_DATAFILE If this value is used, the system maps the file into
0x00000002 the calling process's virtual address space as if it
were a data file. Nothing is done to execute or
prepare to execute the mapped file. Therefore, you
cannot call functions like GetModuleFileName,
GetModuleHandle or GetProcAddress with this
DLL. Using this value causes writes to read-only
memory to raise an access violation. Use this flag
when you want to load a DLL only to extract
messages or resources from it.
LOAD_LIBRARY_AS_IMAGE_RESOURCE If this value is used, the system maps the file into
0x00000020 the process's virtual address space as an image
file. However, the loader does not load the static
imports or perform the other usual initialization
steps. Use this flag when you want to load a DLL
only to extract messages or resources from it.
Unless the application depends on the file having
the in-memory layout of an image, this value
should be used with either
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE or
LOAD_LIBRARY_AS_DATAFILE. For more
information, see the Remarks section.
Return value
If the function succeeds, the return value is a handle to the loaded module.
If the function fails, the return value is NULL. To get extended error information, call
GetLastError.
Remarks
The LoadLibraryEx function is very similar to the LoadLibrary function. The differences
consist of a set of optional behaviors that LoadLibraryEx provides:
LoadLibraryEx can load a DLL module without calling the DllMain function of the
DLL.
LoadLibraryEx can load a module in a way that is optimized for the case where the
module will never be executed, loading the module as if it were a data file.
LoadLibraryEx can find modules and their associated modules by using either of
two search strategies or it can search a process-specific set of directories.
You select these optional behaviors by setting the dwFlags parameter; if dwFlags is zero,
LoadLibraryEx behaves identically to LoadLibrary.
The calling process can use the handle returned by LoadLibraryEx to identify the
module in calls to the GetProcAddress, FindResource, and LoadResource functions.
To enable or disable error messages displayed by the loader during DLL loads, use the
SetErrorMode function.
It is not safe to call LoadLibraryEx from DllMain. For more information, see the Remarks
section in DllMain.
Visual C++: 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 LoadLibraryEx 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.
To determine how a module was loaded, use one of the following macros to test the
handle returned by LoadLibraryEx.
C++
Macro Description
LDR_IS_DATAFILE(handle) If this macro returns TRUE, the module was loaded as a data
file (LOAD_LIBRARY_AS_DATAFILE or
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE).
LDR_IS_RESOURCE(handle) If this macro returns TRUE, the module was loaded as either a
data file or an image file.
Use the FreeLibrary function to free a loaded module, whether or not loading the
module caused its reference count to be incremented. If the module was loaded as a
data or image file, the mapping is destroyed but the reference count is not
decremented. Otherwise, the DLL reference count is decremented. Therefore, it is safe to
call FreeLibrary with any handle returned by LoadLibraryEx.
The file name is specified without a path and the base file name does not match
the base file name of a loaded module, and none of the LOAD_LIBRARY_SEARCH
flags are used.
A path is specified but LOAD_WITH_ALTERED_SEARCH_PATH is not used.
The application has not specified a default DLL search path for the process using
SetDefaultDllDirectories.
If lpFileName specifies a relative path, the entire relative path is appended to every
token in the DLL search path. To load a module from a relative path without searching
any other path, use GetFullPathName to get a nonrelative path and call LoadLibraryEx
with the nonrelative path. If the module is being loaded as a datafile and the relative
path starts with "." or "..", the relative path is treated as an absolute path.
The SetDllDirectory function can be used to modify the search path. This solution is
better than using SetCurrentDirectory or hard-coding the full path to the DLL. However,
be aware that using SetDllDirectory effectively disables safe DLL search mode while the
specified directory is in the search path and it is not thread safe. If possible, it is best to
use AddDllDirectory to modify a default process search path. For more information, see
Dynamic-Link Library Search Order.
An application can specify the directories to search for a single LoadLibraryEx call by
using the LOAD_LIBRARY_SEARCH_* flags. If more than one LOAD_LIBRARY_SEARCH
flag is specified, the directories are searched in the following order:
Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: The
LOAD_LIBRARY_SEARCH_ flags are available on systems that have KB2533623
installed. To determine whether the flags are available, use GetProcAddress to get the
address of the AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories function.
If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_ flags can be used with
LoadLibraryEx.
If a path is specified and there is a redirection file associated with the application, the
LoadLibraryEx function searches for the module in the application directory. If the
module exists in the application directory, LoadLibraryEx ignores the path specification
and loads the module from the application directory. If the module does not exist in the
application directory, the function loads the module from the specified directory. For
more information, see Dynamic Link Library Redirection.
If you call LoadLibraryEx 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.
Security Remarks
LOAD_LIBRARY_AS_DATAFILE does not prevent other processes from modifying the
module while it is loaded. Because this can make your application less secure, you
should use LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE instead of
LOAD_LIBRARY_AS_DATAFILE when loading a module as a data file, unless you
specifically need to use LOAD_LIBRARY_AS_DATAFILE. Specifying
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE prevents other processes from modifying the
module while it is loaded. Do not specify LOAD_LIBRARY_AS_DATAFILE and
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE in the same call.
Do not use the SearchPath function to retrieve a path to a DLL for a subsequent
LoadLibraryEx call. The SearchPath function uses a different search order than
LoadLibraryEx 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 LoadLibraryEx will then
load.
Do not make assumptions about the operating system version based on a
LoadLibraryEx 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.
For a general discussion of DLL security issues, see Dynamic-Link Library Security.
Examples
The following code example demonstrates a call to LoadLibraryExA.
C++
For an additional example, see Looking Up Text for Error Code Numbers.
7 Note
Requirements
DLL Kernel32.dll
See also
DllMain
FindResource
FreeLibrary
GetProcAddress
GetSystemDirectory
GetWindowsDirectory
LoadLibrary
LoadResource
OpenFile
SearchPath
SetDllDirectory
SetErrorMode
Feedback
Was this page helpful? ツ Yes ト No
Note This function is provided only for compatibility with 16-bit versions of
Windows. Applications should use the CreateProcess function.
Syntax
C++
DWORD LoadModule(
[in] LPCSTR lpModuleName,
[in] LPVOID lpParameterBlock
);
Parameters
[in] lpModuleName
The file name of the application to be run. When specifying a path, be sure to use
backslashes (\), not forward slashes (/). If the lpModuleName parameter does not contain
a directory path, the system searches for the executable file in this order:
[in] lpParameterBlock
Return value
If the function succeeds, the return value is greater than 31.
If the function fails, the return value is an error value, which may be one of the following
values.
Remarks
The LOADPARMS32 structure has the following form:
syntax
Member Meaning
lpEnvAddress Pointer to an array of null-terminated strings that supply the environment strings
for the new process. The array has a value of NULL as its last entry. A value of
NULL for this parameter causes the new process to start with the same
environment as the calling process.
lpCmdLine Pointer to a Pascal-style string that contains a correctly formed command line.
The first byte of the string contains the number of bytes in the string. The
remainder of the string contains the command line arguments, excluding the
name of the child process. If there are no command line arguments, this
parameter must point to a zero length string; it cannot be NULL.
lpCmdShow Pointer to a structure containing two WORD values. The first value must always
be set to two. The second value specifies how the application window is to be
shown and is used to supply the wShowWindow member of the STARTUPINFO
structure to the CreateProcess function. See the description of the nCmdShow
parameter of the ShowWindow function for a list of acceptable values.
lpszApplicationName lpModuleName
lpszCommandLine lpParameterBlock.lpCmdLine
lpProcessAttributes NULL
lpThreadAttributes NULL
bInheritHandles FALSE
dwCreationFlags 0
lpEnvironment lpParameterBlock.lpEnvAddress
lpCurrentDirectory NULL
Requirements
Library Kernel32.lib
DLL Kernel32.dll
See also
CreateProcess
GetSystemDirectory
GetWindowsDirectory
Feedback
Was this page helpful? ツ Yes ト No
Loads the specified packaged module and its dependencies into the address space of
the calling process.
Syntax
C++
HMODULE LoadPackagedLibrary(
[in] LPCWSTR lpwLibFileName,
DWORD Reserved
);
Parameters
[in] lpwLibFileName
The file name of the packaged module to load. The module can be a library module (a
.dll file) or an executable module (an .exe file).
If this parameter 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.
If this parameter specifies a path, the function searches that path for the module. The
path cannot be an absolute path or a relative path that contains ".." in the path. When
specifying a path, be sure to use backslashes (\), not forward slashes (/). For more
information about paths, see Naming Files, Paths, and Namespaces.
If the specified module is already loaded in the process, the function returns a handle to
the loaded module. The module must have been originally loaded from the package
dependency graph of the process.
If loading the specified module causes the system to load other associated modules, the
function first searches loaded modules, then it searches the package dependency graph
of the process. For more information, see Remarks.
Reserved
Return value
If the function succeeds, the return value is a handle to the loaded module.
If the function fails, the return value is NULL. To get extended error information, call
GetLastError.
Remarks
The LoadPackagedLibrary function is a simplified version of LoadLibraryEx. Packaged
apps can use LoadPackagedLibrary to load packaged modules. Unpackaged
applications cannot use LoadPackagedLibrary; if a unpackaged application calls this
function it fails with APPMODEL_ERROR_NO_PACKAGE.
If the function must search for the specified module or its dependencies, it searches only
the package dependency graph of the process. This is the application's package plus
any dependencies specified as <PackageDependency> in the <Dependencies> section of
the application's package manifest. Dependencies are searched in the order they appear
in the manifest. The package dependency graph is specified in the <Dependencies>
section of the application's package manifest. Dependencies are searched in the order
they appear in the manifest. The search proceeds as follows:
1. The function first searches modules that are already loaded. If the specified
module was originally loaded from the package dependency graph of the process,
the function returns a handle to the loaded module. If the specified module was
not loaded from the package dependency graph of the process, the function
returns NULL.
2. If the module is not already loaded, the function searches the package
dependency graph of the process.
3. If the function cannot find the specified module or one of its dependencies, the
function fails.
It is not safe to call LoadPackagedLibrary from DllMain. For more information, see the
Remarks section in DllMain.
7 Note
Requirements
Minimum supported server Windows Server 2012 [desktop apps | UWP apps]
Library Kernel32.lib
DLL Kernel32.dll
See also
Dynamic-Link Library Search Order
Feedback
Was this page helpful? ツ Yes ト No
Syntax
C++
BOOL QueryOptionalDelayLoadedAPI(
[in] HMODULE hParentModule,
[in] LPCSTR lpDllName,
[in] LPCSTR lpProcName,
DWORD Reserved
);
Parameters
[in] hParentModule
A handle to the calling module. Desktop applications can use the GetModuleHandle or
GetModuleHandleEx function to get this handle. Windows Store apps should set this
parameter to static_cast<HMODULE>(&__ImageBase) .
[in] lpDllName
The file name of the delay-loaded DLL that exports the specified function. This
parameter is case-insensitive.
Windows Store apps should specify API sets, rather than monolithic DLLs. For example,
api-ms-win-core-memory-l1-1-1.dll, rather than kernel32.dll.
[in] lpProcName
Reserved
Remarks
A delay-loaded DLL is statically linked but not actually loaded into memory until the
running application references a symbol exported by that DLL. Applications often delay
load DLLs that contain functions the application might call only rarely or not at all,
because the DLL is only loaded when it is needed instead of being loaded at application
startup like other statically linked DLLs. This helps improve application performance,
especially during initialization. A delay-load DLL is specified at link time with the
/DELAYLOAD (Delay Load Import) linker option.
Examples
C++
#include <windows.h>
#include <libloaderapi2.h>
BOOL
AreMonikersSupported ()
{
BOOL isApiAvailable;
isApiAvailable =
QueryOptionalDelayLoadedAPI(static_cast<HMODULE>(&__ImageBase),
"ext-ms-win-com-ole32-l1-1-1.dll",
"MkParseDisplayName",
0);
return isApiAvailable;
}
Requirements
Minimum supported server Windows Server 2016 [desktop apps | UWP apps]
Header libloaderapi2.h
Library WindowsApp.lib
DLL Api-ms-win-core-libraryloader-l1-1-1.dll
See also
LoadPackagedLibrary
Feedback
Was this page helpful? Yes No
RemoveDllDirectory function
(libloaderapi.h)
Article10/13/2021
Removes a directory that was added to the process DLL search path by using
AddDllDirectory.
Syntax
C++
BOOL RemoveDllDirectory(
[in] DLL_DIRECTORY_COOKIE Cookie
);
Parameters
[in] Cookie
The cookie returned by AddDllDirectory when the directory was added to the search
path.
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call
GetLastError.
Remarks
After RemoveDllDirectory returns, the cookie is no longer valid and should not be used.
Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: To
call this function in an application, use the GetProcAddress function to retrieve its
address from Kernel32.dll. KB2533623 must be installed on the target platform.
Requirements
Minimum Windows 8 [desktop apps only],KB2533623 on Windows 7, Windows
supported Server 2008 R2, Windows Vista, and Windows Server 2008
client
DLL Kernel32.dll
Feedback
Was this page helpful? ツ Yes ト No
Specifies a default set of directories to search when the calling process loads a DLL. This
search path is used when LoadLibraryEx is called with no LOAD_LIBRARY_SEARCH flags.
Syntax
C++
BOOL SetDefaultDllDirectories(
[in] DWORD DirectoryFlags
);
Parameters
[in] DirectoryFlags
The directories to search. This parameter can be any combination of the following
values.
Value Meaning
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call
GetLastError.
Remarks
The DLL search path is the set of directories that are searched for a DLL when a full path
is not specified in a LoadLibrary or LoadLibraryEx function call, or when a full path to the
DLL is specified but the system must search for dependent DLLs. For more information
about the standard DLL search path, see Dynamic-Link Library Search Order.
The standard DLL search path contains directories that can be vulnerable to a DLL pre-
loading attack. An application can use the SetDefaultDllDirectories function to specify a
default DLL search path for the process that eliminates the most vulnerable directories
and limits the other directories that are searched. The process DLL search path applies
only to the calling process and persists for the life of the process.
If the DirectoryFlags parameter specifies more than one flag, the directories are searched
in the following order:
It is not possible to revert to the standard DLL search path or remove any directory
specified with SetDefaultDllDirectories from the search path. However, the process DLL
search path can be overridden by calling LoadLibraryEx with one or more
LOAD_LIBRARY_SEARCH flags, and directories added with AddDllDirectory can be
removed by calling RemoveDllDirectory.
Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: To
call this function in an application, use the GetProcAddress function to retrieve its
address from Kernel32.dll. KB2533623 must be installed on the target platform.
Requirements
DLL Kernel32.dll
See also
AddDllDirectory
LoadLibrary
LoadLibraryEx
RemoveDllDirectory
Feedback
Was this page helpful? ツ Yes ト No
Get help at Microsoft Q&A
SetDllDirectoryA function (winbase.h)
Article02/09/2023
Adds a directory to the search path used to locate DLLs for the application.
Syntax
C++
BOOL SetDllDirectoryA(
[in, optional] LPCSTR lpPathName
);
Parameters
[in, optional] lpPathName
The directory to be added to the search path. If this parameter is an empty string (""),
the call removes the current directory from the default DLL search order. If this
parameter is NULL, the function restores the default search order.
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call
GetLastError.
Remarks
The SetDllDirectory function affects all subsequent calls to the LoadLibrary and
LoadLibraryEx functions. It also effectively disables safe DLL search mode while the
specified directory is in the search path.
7 Note
For Win32 processes that are not running a packaged or protected process, calling
this function will also affect the DLL search order of the children processes started
from the process that has called the function.
After calling SetDllDirectory, the standard DLL search path is:
Each time the SetDllDirectory function is called, it replaces the directory specified in the
previous SetDllDirectory call. To specify more than one directory, use the
AddDllDirectory function and call LoadLibraryEx with
LOAD_LIBRARY_SEARCH_USER_DIRS.
To revert to the standard search path used by LoadLibrary and LoadLibraryEx, call
SetDllDirectory with NULL. This also restores safe DLL search mode based on the
SafeDllSearchMode registry value.
7 Note
Requirements
Minimum supported client Windows Vista, Windows XP with SP1 [desktop apps only]
Library Kernel32.lib
DLL Kernel32.dll
See also
AddDllDirectory
GetDllDirectory
GetSystemDirectory
GetWindowsDirectory
LoadLibrary
LoadLibraryEx
Feedback
Was this page helpful? ツ Yes ト No