0% found this document useful (0 votes)
7 views

Windows Win32 Dlls

Uploaded by

wanghoa6868
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Windows Win32 Dlls

Uploaded by

wanghoa6868
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 135

Tell us about your PDF experience.

Dynamic-Link Libraries (Dynamic-Link


Libraries)
Article • 05/31/2022

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.

The Windows application programming interface (API) is implemented as a set of DLLs,


so any process that uses the Windows API uses dynamic linking.

About Dynamic-Link Libraries


Using Dynamic-Link Libraries
Dynamic-Link Library Reference

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

Get help at Microsoft Q&A


About Dynamic-Link Libraries
Article • 01/07/2021

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.

Types of Dynamic Linking


There are two methods for calling a function in a DLL:

In load-time dynamic linking, a module makes explicit calls to exported DLL


functions as if they were local functions. This requires you to link the module with
the import library for the DLL that contains the functions. An import library
supplies the system with the information needed to load the DLL and locate the
exported DLL functions when the application is loaded.
In run-time dynamic linking, a module uses the LoadLibrary or LoadLibraryEx
function to load the DLL at run time. After the DLL is loaded, the module calls the
GetProcAddress function to get the addresses of the exported DLL functions. The
module calls the exported DLL functions using the function pointers returned by
GetProcAddress. This eliminates the need for an import library.

DLLs and Memory Management


Every process that loads the DLL maps it into its virtual address space. After the process
loads the DLL into its virtual address, it can call the exported DLL functions.

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.

For more information about DLLs, see the following topics:

Advantages of Dynamic Linking


Dynamic-Link Library Creation
Dynamic-Link Library Entry-Point Function
Load-Time Dynamic Linking
Run-Time Dynamic Linking
Dynamic-Link Library Search Order
Dynamic-Link Library Data
Dynamic-Link Library Redirection
Dynamic-Link Library Updates
Dynamic-Link Library Security
AppInit DLLs and Secure Boot

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Advantages of Dynamic Linking
Article • 01/07/2021

Dynamic linking has the following advantages over static linking:

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.

A potential disadvantage to using DLLs is that the application is not self-contained; it


depends on the existence of a separate DLL module. The system terminates processes
using load-time dynamic linking if they require a DLL that is not found at process
startup and gives an error message to the user. The system does not terminate a
process using run-time dynamic linking in this situation, but functions exported by the
missing DLL are not available to the program.

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Dynamic-link library creation
Article • 01/26/2024

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.

Creating source files


The source files for a DLL contain exported functions and data, internal functions and
data, and an optional entry-point function for the DLL. You may use any development
tools that support the creation of Windows-based DLLs.

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.

Creating an import library


An import library ( .lib ) file contains information that the linker needs in order to
resolve external references to exported DLL functions, so that the system can locate the
specified DLL and exported DLL functions at run-time. You can create an import library
for your DLL when you build your DLL.
For more info, see Building an import library and export file.

Using an import library


For example, to call the CreateWindow function, you must link your code with the
import library User32.lib . The reason is that CreateWindow resides in a system DLL
named User32.dll , and User32.lib is the import library used to resolve the calls in your
code to exported functions in User32.dll . The linker creates a table that contains the
address of each function call. Calls to functions in a DLL will be fixed up when the DLL is
loaded. While the system is initializing the process, it loads User32.dll because the
process depends on exported functions in that DLL, and it updates the entries in the
function address table. All calls to CreateWindow invoke the function exported from
User32.dll .

For more info, see Link an executable to 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.

Calling the Entry-Point Function


The system calls the entry-point function whenever any one of the following events
occurs:

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.

Entry-Point Function Definition


The DLL entry-point function must be declared with the standard-call calling convention.
If the DLL entry point is not declared correctly, the DLL is not loaded, and the system
displays a message indicating that the DLL entry point must be declared with WINAPI.

In the body of the function, you may handle any combination of the following scenarios
in which the DLL entry point has been called:

A process loads the DLL (DLL_PROCESS_ATTACH).


The current process creates a new thread (DLL_THREAD_ATTACH).
A thread exits normally (DLL_THREAD_DETACH).
A process unloads the DLL (DLL_PROCESS_DETACH).

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

BOOL WINAPI DllMain(


HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;

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.
}

Entry-Point Function Return Value


When a DLL entry-point function is called because a process is loading, the function
returns TRUE to indicate success. For processes using load-time linking, a return value of
FALSE causes the process initialization to fail and the process terminates. For processes
using run-time linking, a return value of FALSE causes the LoadLibrary or LoadLibraryEx
function to return NULL, indicating failure. (The system immediately calls your entry-
point function with DLL_PROCESS_DETACH and unloads the DLL.) The return value of
the entry-point function is disregarded when the function is called for any other reason.
Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Load-Time Dynamic Linking
Article • 01/07/2021

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

Get help at Microsoft Q&A


Run-Time Dynamic Linking
Article • 01/07/2021

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 GetModuleHandle function returns a handle used in GetProcAddress, FreeLibrary,


or FreeLibraryAndExitThread. The GetModuleHandle function succeeds only if the DLL
module is already mapped into the address space of the process by load-time linking or
by a previous call to LoadLibrary or LoadLibraryEx. Unlike LoadLibrary or
LoadLibraryEx, GetModuleHandle does not increment the module reference count. The
GetModuleFileName function retrieves the full path of the module associated with a
handle returned by GetModuleHandle, LoadLibrary, or LoadLibraryEx.

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

Get help at Microsoft Q&A


Dynamic-link library search order
Article • 02/09/2023

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

For definitions of packaged and unpackaged apps, see Advantages and


disadvantages of packaging your app.

Factors that affect searching


Here are some special search factors that are discussed in this topic—you can consider
them to be part of the DLL search order. Later sections in this topic list these factors in
the appropriate search order for certain app types, together with other search locations.
This section is just to introduce the concepts, and to give them names that we'll use to
refer to them later in the topic.

DLL redirection. For details, see Dynamic-link library redirection.


API sets. For details, see Windows API sets.
Side-by-side (SxS) manifest redirection—desktop apps only (not UWP apps). You
can redirect by using an application manifest (also known as a side-by-side
application manifest, or a fusion manifest). For details, see Manifests.
Loaded-module list. The system can check to see whether a DLL with the same
module name is already loaded into memory (no matter which folder it was loaded
from).
Known DLLs. If the DLL is on the list of known DLLs for the version of Windows on
which the application is running, then the system uses its copy of the known DLL
(and the known DLL's dependent DLLs, if any). For a list of known DLLs on the
current system, see the registry key
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs .

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.

Search order for packaged apps


When a packaged app loads a packaged module (specifically, a library module—a .dll
file) by calling the LoadPackagedLibrary function, the DLL must be in the package
dependency graph of the process. For more information, see LoadPackagedLibrary.
When a packaged app loads a module by other means, and doesn't specify a full path,
the system searches for the DLL and its dependencies at load time as described in this
section.

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.

Standard search order for packaged apps


The system searches in this order:

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).

Alternate search order for packaged apps


If a module changes the standard search order by calling the LoadLibraryEx function
with LOAD_WITH_ALTERED_SEARCH_PATH, then the search order is the same as the
standard search order except that in step 7 the system searches the folder that the
specified module was loaded from (the top-loading module's folder) instead of the
executable's folder.
Search order for unpackaged apps
When an unpackaged app loads a module and doesn't specify a full path, the system
searches for the DLL at load time as described in this section.

) 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.

Standard search order for unpackaged apps


The standard DLL search order used by the system depends on whether or not safe DLL
search mode is enabled.

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

Manager\SafeDllSearchMode registry value, and set it to 0. Calling the SetDllDirectory


function effectively disables safe DLL search mode (while the specified folder is in the
search path), and changes the search order as described in this topic.

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).

Alternate search order for unpackaged apps


To change the standard search order used by the system, you can call the LoadLibraryEx
function with LOAD_WITH_ALTERED_SEARCH_PATH. You can also change the standard
search order by calling the SetDllDirectory function.

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.

That's the only way in which they differ.

If safe DLL search mode is enabled, then the alternate search order is as follows:

Steps 1-6 are the same as the standard search order.


7. The folder specified by lpFileName.
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 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).

The SetDllDirectory function supports an alternate search order if the lpPathName


parameter specifies a path. The alternate search order is as follows:

Steps 1-6 are the same as the standard search order.

7. The folder from which the application loaded.


8. The folder specified by the lpPathName parameter of SetDllDirectory.
9. The system folder.
10. The 16-bit system folder.
11. The Windows folder.
12. The directories listed in the PATH environment variable.

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.

Search order using LOAD_LIBRARY_SEARCH flags


You can specify a search order by using one or more LOAD_LIBRARY_SEARCH flags with
the LoadLibraryEx function. You can also use LOAD_LIBRARY_SEARCH flags with the
SetDefaultDllDirectories function to establish a DLL search order for a process. You can
specify additional directories for the process DLL search order by using the
AddDllDirectory or SetDllDirectory functions.

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:

1. LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR. The folder that contains the DLL is


searched. This folder is searched only for dependencies of the DLL to be loaded.
2. LOAD_LIBRARY_SEARCH_APPLICATION_DIR. The application folder is searched.
3. LOAD_LIBRARY_SEARCH_USER_DIRS. Paths explicitly added with the
AddDllDirectory function or the SetDllDirectory function are searched. If you add
more than one path, then the order in which the paths are searched is unspecified.
4. LOAD_LIBRARY_SEARCH_SYSTEM32. The System folder is searched.

If you call LoadLibraryEx with no LOAD_LIBRARY_SEARCH flags, or you establish a DLL


search order for the process, then the system searches for DLLs using either the
standard search order or the alternate search 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

Get help at Microsoft Q&A


Dynamic-Link Library Data
Article • 01/07/2021

A Dynamic-Link Library (DLL) can contain global data or local data.

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.

Dynamic Memory Allocation


When a DLL allocates memory using any of the memory allocation functions
(GlobalAlloc, LocalAlloc, HeapAlloc, and VirtualAlloc), the memory is allocated in the
virtual address space of the calling process and is accessible only to the threads of that
process.

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.

Thread Local Storage


The thread local storage (TLS) functions enable a DLL to allocate an index for storing
and retrieving a different value for each thread of a multithreaded process. For example,
a spreadsheet application can create a new instance of the same thread each time the
user opens a new spreadsheet. A DLL providing the functions for various spreadsheet
operations can use TLS to save information about the current state of each spreadsheet
(row, column, and so on). For a general discussion of thread local storage, see Thread
Local Storage. For an example that uses the DllMain function to set up thread local
storage, see Using Thread Local Storage 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

Get help at Microsoft Q&A


Dynamic-link library redirection
Article • 10/13/2023

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.

DLL versioning problems


If your application depends on a specific version of a shared DLL, and another
application is installed with a newer or older version of that DLL, then that can cause
compatibility problems and instability; it can cause your app to start to fail.

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.

You can use redirection to solve these problems.

Loading and testing private binaries


The rules that the DLL loader follows ensure that system DLLs are loaded from the
Windows system locations—for example, the system folder ( %SystemRoot%\system32 ).
Those rules avoid planting attacks: where an adversary puts code that they wrote in a
location that they can write to, and then convince some process to load and execute it.
But the loader's rules also make it more difficult to work on OS components, because to
run them requires updating the system; and that's a very impactful change.

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:

DLL redirection. Continue to read this topic for more details.


Side-by-side components. Described in the topic Isolated applications and side-
by-side assemblies.

 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.

Optional: configure the registry


To enable DLL redirection machine-wide, you must create a new registry value. Under
the key HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution
Options , create a new DWORD value with the name DevOverrideEnable. Set the value to

1, and restart your computer. Or use the command below (and restart your computer).

Console

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File


Execution Options" /v DevOverrideEnable /t REG_DWORD /d 1

With that registry value set, DotLocal DLL redirection is respected even if the app has an
application manifest.

Create a redirection file or folder


To use DLL redirection, you'll create a redirection file or a redirection folder (depending
on the kind of app you have), as we'll see in later sections in this topic.
How to redirect DLLs for packaged apps
A packaged app requires a special folder structure for DLL redirection. The following
path is where the loader will look when redirection is enabled:

<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&gt;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 "&lt;A.dll&gt;" copy /y "&lt;A.dll&gt;"
$(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
if EXIST "&lt;B.dll&gt;" copy /y "&lt;B.dll&gt;"
$(IntDir)\microsoft.system.package.metadata\application.local 2&gt;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>

Let's walk through some of what that configuration does.

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

<!-- [[Using_.local_(DotLocal)_with_modern_apps]] This makes the extra


DLL deployed via Start 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

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

if EXIST "<path-to-local-dll>" copy /y "<path-to-local-dll>"


$(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
if EXIST "<path-to-local-dll>" copy /y "<path-to-local-dll>"
$(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
</Command>
</PreBuildEvent>

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.

1. Determine the package's installation folder. You can do that in PowerShell by


issuing the command Get-AppxPackage , and looking for the InstallLocation that's
returned.

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.

Verify that everything worked


To confirm that the correct DLL is being loaded at runtime, you can use Visual Studio
with the debugger attached.

1. Open the Modules window (Debug > Windows > Modules).


2. Find the DLL, and make sure that the Path indicates the redirected copy, and not
the system-deployed version.
3. Confirm that only one copy of a given DLL is loaded.

How to redirect DLLs for unpackaged apps


The redirection file must be named <your_app_name>.local . So if your app's name is
Editor.exe , then name your redirection file Editor.exe.local . You must install the

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:

C:\Program Files\Common Files\System\mydll.dll

And if both C:\myapp\myapp.exe.local and C:\myapp\mydll.dll exist, then LoadLibrary


loads C:\myapp\mydll.dll . Otherwise, LoadLibrary loads C:\Program Files\Common
Files\System\mydll.dll .

Alternatively, if a folder named C:\myapp\myapp.exe.local exists, and it contains


mydll.dll , then LoadLibrary loads C:\myapp\myapp.exe.local\mydll.dll .

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

Get help at Microsoft Q&A


Dynamic-Link Library Security
Article • 01/07/2021

When an application dynamically loads a dynamic-link library without specifying a fully


qualified path name, Windows attempts to locate the DLL by searching a well-defined
set of directories in a particular order, as described in Dynamic-Link Library Search
Order. If an attacker gains control of one of the directories on the DLL search path, it can
place a malicious copy of the DLL in that directory. This is sometimes called a DLL
preloading attack or a binary planting attack. If the system does not find a legitimate
copy of the DLL before it searches the compromised directory, it loads the malicious
DLL. If the application is running with administrator privileges, the attacker may succeed
in local privilege elevation.

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:

1. The directory from which the application loaded.


2. The system directory.
3. The 16-bit system directory.
4. The Windows directory.
5. The current directory.
6. The directories that are listed in the PATH environment variable.

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.

Use the LOAD_LIBRARY_SEARCH flags with the LoadLibraryEx function, or use


these flags with the SetDefaultDllDirectories function to establish a DLL search
order for a process and then use the AddDllDirectory or SetDllDirectory functions
to modify the list. For more information, see Dynamic-Link Library Search Order.
Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008:
These flags and functions are available on systems with KB2533623 installed.

On systems with KB2533623 installed, use the LOAD_LIBRARY_SEARCH flags with


the LoadLibraryEx function, or use these flags with the SetDefaultDllDirectories
function to establish a DLL search order for a process and then use the
AddDllDirectory or SetDllDirectory functions to modify the list. For more
information, see Dynamic-Link Library Search Order.

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.

To use Process Monitor to examine DLL load operations in your application

1. Start Process Monitor.


2. In Process Monitor, include the following filters:

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

3. Exclude the following filters:

Process Name is procmon.exe


Process Name is Procmon64.exe
Process Name is System
Operation begins with IRP_MJ_
Operation begins with FASTIO_
Result is SUCCESS
Path ends with pagefile.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

Get help at Microsoft Q&A


AppInit DLLs and Secure Boot
Article • 09/29/2022

Starting in Windows 8, the AppInit_DLLs infrastructure is disabled when secure boot is


enabled.

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.

AppInit_DLLs and secure boot


Windows 8 adopted UEFI and secure boot to improve the overall system integrity and to
provide strong protection against sophisticated threats. When secure boot is enabled,
the AppInit_DLLs mechanism is disabled as part of a no-compromise approach to
protect customers against malware and threats.

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 .

AppInit_DLLs certification requirement for


Windows 8 desktop apps
One of the certification requirements for Windows 8 desktop apps is that the app must
not load arbitrary DLLs to intercept Win32 API calls using the AppInit_DLLs mechanism.
For more detailed information about the certification requirements, refer to section 1.1
of Certification requirements for Windows 8 desktop apps.

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.

To download a whitepaper with info about AppInit_DLLs on Windows 7 and Windows


Server 2008 R2, visit the Windows Hardware Dev Center Archive, and search for AppInit
DLLs in Windows 7 and Windows Server 2008 R2.

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Dynamic-Link Library Best Practices
Article • 05/12/2023

**Updated: **

May 17, 2006

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.

Improper synchronization within DllMain can cause an application to deadlock or access


data or code in an uninitialized DLL. Calling certain functions from within DllMain causes
such problems.
General Best Practices
DllMain is called while the loader-lock is held. Therefore, significant restrictions are
imposed on the functions that can be called within DllMain. As such, DllMain is
designed to perform minimal initialization tasks, by using a small subset of the
Microsoft® Windows® API. You cannot call any function in DllMain that directly or
indirectly tries to acquire the loader lock. Otherwise, you will introduce the possibility
that your application deadlocks or crashes. An error in a DllMain implementation can
jeopardize the entire process and all of its threads.

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:

Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a


deadlock or a crash.
Call GetStringTypeA, GetStringTypeEx, or GetStringTypeW (either directly or
indirectly). This can cause a deadlock or a crash.
Synchronize with other threads. This can cause a deadlock.
Acquire a synchronization object that is owned by code that is waiting to acquire
the loader lock. This can cause a deadlock.
Initialize COM threads by using CoInitializeEx. Under certain conditions, this
function can call LoadLibraryEx.
Call the registry functions.
Call CreateProcess. Creating a process can load another DLL.
Call ExitThread. Exiting a thread during DLL detach can cause the loader lock to be
acquired again, causing a deadlock or a crash.
Call CreateThread. Creating a thread can work if you do not synchronize with other
threads, but it is risky.
Call ShGetFolterPathW. Calling shell/known folder APIs can result in thread
synchronization, and can therefore cause deadlocks.
Create a named pipe or other named object (Windows 2000 only). In Windows
2000, named objects are provided by the Terminal Services DLL. If this DLL is not
initialized, calls to the DLL can cause the process to crash.
Use the memory management function from the dynamic C Run-Time (CRT). If the
CRT DLL is not initialized, calls to these functions can cause the process to crash.
Call functions in User32.dll or Gdi32.dll. Some functions load another DLL, which
may not be initialized.
Use managed code.

The following tasks are safe to perform within DllMain:

Initialize static data structures and members at compile time.


Create and initialize synchronization objects.
Allocate memory and initialize dynamic data structures (avoiding the functions
listed above.)
Set up thread local storage (TLS).
Open, read from, and write to files.
Call functions in Kernel32.dll (except the functions that are listed above).
Set global pointers to NULL, putting off the initialization of dynamic members. In
Microsoft Windows Vista™, you can use the one-time initialization functions to
ensure that a block of code is executed only once in a multithreaded environment.

Deadlocks Caused by Lock Order Inversion


When you are implementing code that uses multiple synchronization objects such as
locks, it is vital to respect lock order. When it is necessary to acquire more than one lock
at a time, you must define an explicit precedence that is called a lock hierarchy or lock
order. For example, if lock A is acquired before lock B somewhere in the code, and lock
B is acquired before lock C elsewhere in the code, then the lock order is A, B, C and this
order should be followed throughout the code. Lock order inversion occurs when the
locking order is not followed—for example, if lock B is acquired before lock A. Lock
order inversion can cause deadlocks that are difficult to debug. To avoid such problems,
all threads must acquire locks in the same order.

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.

Best Practices for Synchronization


Consider a DLL that creates worker threads as part of its initialization. Upon DLL cleanup,
it is necessary to synchronize with all the worker threads to ensure that the data
structures are in a consistent state and then terminate the worker threads. Today, there
is no straightforward way to completely solve the problem of cleanly synchronizing and
shutting down DLLs in a multithreaded environment. This section describes the current
best practices for thread synchronizing during DLL shutdown.

Thread Synchronization in DllMain during Process Exit

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.

Thread Synchronization in DllMain for DLL_THREAD_DETACH during DLL Unload


When the DLL is unloaded, the address space is not thrown away. Therefore, the
DLL is expected to perform a clean shutdown. This includes thread synchronization,
open handles, persistent state, and allocated resources.
Thread synchronization is tricky because waiting on threads to exit in DllMain can
cause a deadlock. For example, DLL A holds the loader lock. It signals thread T to
exit and waits for the thread to exit. Thread T exits and the loader tries to acquire
the loader lock to call into DLL A’s DllMain with DLL_THREAD_DETACH. This causes
a deadlock. To minimize the risk of a deadlock:
DLL A gets a DLL_THREAD_DETACH message in its DllMain and sets an event for
thread T, signaling it to exit.
Thread T finishes its current task, brings itself to a consistent state, signals DLL
A, and waits infinitely. Note that the consistency-checking routines should
follow the same restrictions as DllMain to avoid deadlocking.
DLL A terminates T, knowing that it is in a consistent state.

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:

Use Application Verifier to catch the most common errors in DllMain.


If using a private lock inside DllMain, define a locking hierarchy and use it
consistently. The loader lock must be at the bottom of this hierarchy.
Verify that no calls depend on another DLL that may not have been fully loaded
yet.
Perform simple initializations statically at compile time, rather than in DllMain.
Defer any calls in DllMain that can wait until later.
Defer initialization tasks that can wait until later. Certain error conditions must be
detected early so that the application can handle errors gracefully. However, there
are tradeoffs between this early detection and the loss of robustness that can
result from it. Deferring initialization is often best.
Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Using Dynamic-Link Libraries
Article • 01/07/2021

The following examples demonstrate how to create and use a DLL.

Creating a simple dynamic-link library


Using load-time dynamic linking
Using run-time dynamic linking
Using shared memory in a dynamic-link library
Using thread local storage in a dynamic-link library

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Creating a Simple Dynamic-Link Library
Article • 06/16/2022

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++

// The myPuts function writes a null-terminated string to


// the standard output device.

// The export mechanism used here is the __declspec(export)


// method supported by Microsoft Visual Studio, but any
// other export method supported by your development
// environment may be substituted.

#include <windows.h>

#define EOF (-1)

#ifdef __cplusplus // If used by C++ code,


extern "C" { // we need to export the C interface
#endif

__declspec(dllexport) int __cdecl myPuts(LPCWSTR lpszMsg)


{
DWORD cchWritten;
HANDLE hConout;
BOOL fRet;

// Get a handle to the console output device.

hConout = CreateFileW(L"CONOUT$",
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

if (INVALID_HANDLE_VALUE == hConout)
return EOF;

// Write a null-terminated string to the console output device.

while (*lpszMsg != L'\0')


{
fRet = WriteConsole(hConout, lpszMsg, 1, &cchWritten, NULL);
if( (FALSE == fRet) || (1 != cchWritten) )
return EOF;
lpszMsg++;
}
return 1;
}

#ifdef __cplusplus
}
#endif

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Using Load-Time Dynamic Linking
Article • 09/01/2022

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>

extern "C" int __cdecl myPuts(LPCWSTR); // a function from a DLL

int main(VOID)
{
int Ret = 1;

Ret = myPuts(L"Message sent to the DLL function\n");


return Ret;
}

Related topics
Load-Time Dynamic Linking

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Using Run-Time Dynamic Linking
Article • 06/16/2022

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.

This example illustrates an important difference between run-time and load-time


dynamic linking. If the DLL is not available, the application using load-time dynamic
linking must simply terminate. The run-time dynamic linking example, however, can
respond to the error.

C++

// A simple program that uses LoadLibrary and


// GetProcAddress to access myPuts from Myputs.dll.

#include <windows.h>
#include <stdio.h>

typedef int (__cdecl *MYPROC)(LPCWSTR);

int main( void )


{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

// Get a handle to the DLL module.

hinstLib = LoadLibrary(TEXT("MyPuts.dll"));

// If the handle is valid, try to get the function address.

if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "myPuts");

// If the function address is valid, call the function.

if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (L"Message sent to the DLL function\n");
}
// Free the DLL module.

fFreeResult = FreeLibrary(hinstLib);
}

// If unable to call the DLL function, use an alternative.


if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");

return 0;

Related topics
Run-Time Dynamic Linking

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Using Shared Memory in a Dynamic-
Link Library
Article • 01/07/2021

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.

DLL that Implements the Shared Memory


The example uses file mapping to map a block of named shared memory into the virtual
address space of each process that loads the DLL. To do this, the entry-point function
must:

1. Call the CreateFileMapping function to get a handle to a file-mapping object. The


first process that loads the DLL creates the file-mapping object. Subsequent
processes open a handle to the existing object. For more information, see Creating
a File-Mapping Object.
2. Call the MapViewOfFile function to map a view into the virtual address space. This
enables the process to access the shared memory. For more information, see
Creating a File View.

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++

// The DLL code

#include <windows.h>
#include <memory.h>

#define SHMEMSIZE 4096

static LPVOID lpvMem = NULL; // pointer to shared memory


static HANDLE hMapObject = NULL; // handle to file mapping

// The DLL entry-point function sets up shared memory using a


// named file-mapping object.

BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle


DWORD fdwReason, // reason called
LPVOID lpvReserved) // reserved
{
BOOL fInit, fIgnore;

switch (fdwReason)
{
// DLL load due to process initialization or LoadLibrary

case DLL_PROCESS_ATTACH:

// Create a named file mapping object

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;

// The first process to attach initializes memory

fInit = (GetLastError() != ERROR_ALREADY_EXISTS);

// Get a pointer to the file-mapped shared memory

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;

// Initialize memory if this is the first process

if (fInit)
memset(lpvMem, '\0', SHMEMSIZE);

break;

// The attached process creates a new thread

case DLL_THREAD_ATTACH:
break;

// The thread of the attached process terminates

case DLL_THREAD_DETACH:
break;

// DLL unload due to process termination or FreeLibrary


case DLL_PROCESS_DETACH:

// Unmap shared memory from the process's address space

fIgnore = UnmapViewOfFile(lpvMem);

// Close the process's handle to the file-mapping object

fIgnore = CloseHandle(hMapObject);

break;

default:
break;
}

return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}

// The export mechanism used here is the __declspec(export)


// method supported by Microsoft Visual Studio, but any
// other export method supported by your development
// environment may be substituted.

#ifdef __cplusplus // If used by C++ code,


extern "C" { // we need to export the C interface
#endif

// SetSharedMem sets the contents of the shared memory

__declspec(dllexport) VOID __cdecl SetSharedMem(LPWSTR lpszBuf)


{
LPWSTR lpszTmp;
DWORD dwCount=1;

// Get the address of the shared memory block

lpszTmp = (LPWSTR) lpvMem;

// Copy the null-terminated string into shared memory

while (*lpszBuf && dwCount<SHMEMSIZE)


{
*lpszTmp++ = *lpszBuf++;
dwCount++;
}
*lpszTmp = '\0';
}

// GetSharedMem gets the contents of the shared memory

__declspec(dllexport) VOID __cdecl GetSharedMem(LPWSTR lpszBuf, DWORD


cchSize)
{
LPWSTR lpszTmp;

// Get the address of the shared memory block

lpszTmp = (LPWSTR) lpvMem;

// Copy from shared memory into the caller's buffer

while (*lpszTmp && --cchSize)


*lpszBuf++ = *lpszTmp++;
*lpszBuf = '\0';
}
#ifdef __cplusplus
}
#endif

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.

Processes that Use the Shared Memory


The following processes use the shared memory provided by the DLL defined above.
The first process calls SetSharedMem to write a string while the second process calls
GetSharedMem to retrieve this string.

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>

extern "C" VOID __cdecl SetSharedMem(LPWSTR lpszBuf);

HANDLE CreateChildProcess(LPTSTR szCmdline)


{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bFuncRetn = FALSE;

// Set up members of the PROCESS_INFORMATION structure.

ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );

// Set up members of the STARTUPINFO structure.

ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );


siStartInfo.cb = sizeof(STARTUPINFO);

// Create the child process.

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;
}
}

int _tmain(int argc, TCHAR *argv[])


{
HANDLE hProcess;

if (argc == 1)
{
printf("Please specify an input file");
ExitProcess(0);
}

// Call the DLL function


printf("\nProcess is writing to shared memory...\n\n");
SetSharedMem(L"This is a test string");

// Start the child process that will read the memory


hProcess = CreateChildProcess(argv[1]);
// Ensure this process is around until the child process terminates
if (INVALID_HANDLE_VALUE != hProcess)
{
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess);
}
return 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>

extern "C" VOID __cdecl GetSharedMem(LPWSTR lpszBuf, DWORD cchSize);

int _tmain( void )


{
WCHAR cBuf[MAX_PATH];

GetSharedMem(cBuf, MAX_PATH);

printf("Child process read from shared memory: %S\n", cBuf);

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:

1. Uses the TlsAlloc function to allocate a TLS index.


2. Allocates a block of memory to be used exclusively by the initial thread of the
process.
3. Uses the TLS index in a call to the TlsSetValue function to store the address of the
memory block in the TLS slot associated with the index.

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.

When a thread terminates, the entry-point function is called with the


DLL_THREAD_DETACH value and the memory for that thread is freed. When a process
terminates, the entry-point function is called with the DLL_PROCESS_DETACH value and
the memory referenced by the pointer in the TLS index is freed.

C++

// The DLL code

#include <windows.h>

static DWORD dwTlsIndex; // address of shared memory

// DllMain() is the entry-point function for this DLL.

BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle


DWORD fdwReason, // reason called
LPVOID lpvReserved) // reserved
{
LPVOID lpvData;
BOOL fIgnore;

switch (fdwReason)
{
// The DLL is loading due to process
// initialization or a call to LoadLibrary.

case DLL_PROCESS_ATTACH:

// Allocate a TLS index.

if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)


return FALSE;

// No break: Initialize the index for first thread.

// The attached process creates a new thread.

case DLL_THREAD_ATTACH:

// Initialize the TLS index for this thread.

lpvData = (LPVOID) LocalAlloc(LPTR, 256);


if (lpvData != NULL)
fIgnore = TlsSetValue(dwTlsIndex, lpvData);

break;

// The thread of the attached process terminates.

case DLL_THREAD_DETACH:
// Release the allocated memory for this thread.

lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
LocalFree((HLOCAL) lpvData);

break;

// DLL unload due to process termination or FreeLibrary.

case DLL_PROCESS_DETACH:

// Release the allocated memory for this thread.

lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
LocalFree((HLOCAL) lpvData);

// Release the TLS index.

TlsFree(dwTlsIndex);
break;

default:
break;
}

return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}

// The export mechanism used here is the __declspec(export)


// method supported by Microsoft Visual Studio, but any
// other export method supported by your development
// environment may be substituted.

#ifdef __cplusplus // If used by C++ code,


extern "C" { // we need to export the C interface
#endif

__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 = (DWORD *) lpvData; // Cast to my data type.


// In this example, it is only a pointer to a DWORD
// but it can be a structure pointer to contain more complicated data.

(*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;

pData = (DWORD *) lpvData;


(*pdw) = (*pData);
return TRUE;
}
#ifdef __cplusplus
}
#endif

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);

extern "C" BOOL WINAPI StoreData(DWORD dw);


extern "C" BOOL WINAPI GetData(DWORD *pdw);

DWORD WINAPI ThreadFunc(VOID)


{
int i;

if(!StoreData(GetCurrentThreadId()))
ErrorExit("StoreData error");

for(i=0; i<THREADCOUNT; i++)


{
DWORD dwOut;
if(!GetData(&dwOut))
ErrorExit("GetData error");
if( dwOut != GetCurrentThreadId())
printf("thread %d: data is incorrect (%d)\n", GetCurrentThreadId(),
dwOut);
else printf("thread %d: data is correct\n", GetCurrentThreadId());
Sleep(0);
}
return 0;
}

int main(VOID)
{
DWORD IDThread;
HANDLE hThread[THREADCOUNT];
int i;
HMODULE hm;

// Load the DLL

hm = LoadLibrary(DLL_NAME);
if(!hm)
{
ErrorExit("DLL failed to load");
}

// Create multiple threads.

for (i = 0; i < THREADCOUNT; i++)


{
hThread[i] = CreateThread(NULL, // default security attributes
0, // use default stack size
(LPTHREAD_START_ROUTINE) ThreadFunc, // thread function
NULL, // no thread function argument
0, // use default creation flags
&IDThread); // returns thread identifier

// Check the return value for success.


if (hThread[i] == NULL)
ErrorExit("CreateThread error\n");
}

WaitForMultipleObjects(THREADCOUNT, hThread, TRUE, INFINITE);

FreeLibrary(hm);

return 0;
}

VOID ErrorExit (LPSTR lpszMessage)


{
fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0);
}

Related topics
Dynamic-Link Library Data

Using Thread Local Storage

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Dynamic-Link Library Reference
Article • 01/07/2021

The following elements are used in dynamic linking.

Dynamic-Link Library Functions

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


Dynamic-Link Library Functions
Article • 01/07/2021

The following functions are used in dynamic linking.

Function Description

AddDllDirectory Adds a directory to the process DLL search path.

DisableThreadLibraryCalls Disables thread attach and thread detach notifications for the
specified DLL.

DllMain An optional entry point into a 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.

GetDllDirectory Retrieves the application-specific portion of the search path used to


locate DLLs for the application.

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.

GetModuleHandle Retrieves a module handle for the specified module.

GetModuleHandleEx Retrieves a module handle for the specified module.

GetProcAddress Retrieves the address of an exported function or variable from the


specified DLL.

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

SetDefaultDllDirectories Specifies a default set of directories to search when the calling


process loads a DLL.

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

Get help at Microsoft Q&A


AddDllDirectory function
(libloaderapi.h)
Article10/13/2021

Adds a directory to the process DLL search path.

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.

To remove a directory added with AddDllDirectory, use the RemoveDllDirectory


function.

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

Minimum Windows 8 [desktop apps only],KB2533623 on Windows 7, Windows


supported Server 2008 R2, Windows Vista, and Windows Server 2008
client

Minimum Windows Server 2012 [desktop apps only]


supported
server

Target Platform Windows

Header libloaderapi.h (include Windows.h)

DLL Kernel32.dll

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


DisableThreadLibraryCalls function
(libloaderapi.h)
Article02/06/2024

Disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the


specified dynamic-link library (DLL). This can reduce the size of the working set for some
applications.

Syntax
C++

BOOL DisableThreadLibraryCalls(
[in] HMODULE hLibModule
);

Parameters
[in] hLibModule

A handle to the DLL module for which the DLL_THREAD_ATTACH and


DLL_THREAD_DETACH notifications are to be disabled. The LoadLibrary, LoadLibraryEx,
or GetModuleHandle function returns this handle. Note that you cannot call
GetModuleHandle with NULL because this returns the base address of the executable
image, not the DLL image.

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 client Windows XP [desktop apps | UWP apps]

Minimum supported server Windows Server 2003 [desktop apps | UWP apps]

Target Platform Windows

Header libloaderapi.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
Dynamic-Link Library Entry-Point Function

Dynamic-Link Library Functions

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++

BOOL WINAPI DllMain(


HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;

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
}

// Perform any necessary cleanup.


break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}

This is an example from the Dynamic-Link Library Entry-Point Function.


2 Warning

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++

BOOL WINAPI DllMain(


_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved
);

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]

If fdwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-


NULL for static loads.

If fdwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if FreeLibrary has been


called or the DLL load failed and non-NULL if the process is terminating.

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.

If the DLL's entry-point function returns FALSE following a DLL_PROCESS_ATTACH


notification, it receives a DLL_PROCESS_DETACH notification and the DLL is unloaded
immediately. However, if the DLL_PROCESS_ATTACH code throws an exception, the
entry-point function will not receive the DLL_PROCESS_DETACH notification.

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.

When handling DLL_PROCESS_DETACH, a DLL should free resources such as heap


memory only if the DLL is being unloaded dynamically (the lpvReserved parameter is
NULL). If the process is terminating (the lpvReserved parameter is non-NULL), all threads
in the process except the current thread either have exited already or have been
explicitly terminated by a call to the ExitProcess function, which might leave some
process resources such as heaps in an inconsistent state. In this case, it is not safe for
the DLL to clean up the resources. Instead, the DLL should allow the operating system to
reclaim the memory.

If you terminate a process by calling TerminateProcess or TerminateJobObject, the DLLs


of that process do not receive DLL_PROCESS_DETACH notifications. If you terminate a
thread by calling TerminateThread, the DLLs of that thread do not receive
DLL_THREAD_DETACH notifications.

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

Minimum supported client Windows XP [desktop apps only]

Minimum supported server Windows Server 2003 [desktop apps only]

Header Process.h

See also
Dynamic-Link Library Entry-Point Function

Dynamic-Link Library Functions

FreeLibrary

GetModuleFileName

LoadLibrary

TlsAlloc

TlsFree

DisableThreadLibraryCalls

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


FreeLibrary function (libloaderapi.h)
Article10/13/2021

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

A handle to the loaded library module. The LoadLibrary, LoadLibraryEx,


GetModuleHandle, or GetModuleHandleEx function returns this handle.

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

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

Requirements

Minimum supported client Windows XP [desktop apps | UWP apps]

Minimum supported server Windows Server 2003 [desktop apps | UWP apps]

Target Platform Windows

Header libloaderapi.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll
See also
DllMain

Dynamic-Link Library Functions

FreeLibraryAndExitThread

GetModuleHandle

GetModuleHandleEx

LoadLibrary

Run-Time Dynamic Linking

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


FreeLibraryAndExitThread function
(libloaderapi.h)
Article10/13/2021

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

The exit code for the calling thread.

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 client Windows XP [desktop apps | UWP apps]

Minimum supported server Windows Server 2003 [desktop apps | UWP apps]

Target Platform Windows

Header libloaderapi.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
DisableThreadLibraryCalls

Dynamic-Link Library Functions

ExitThread

FreeLibrary

Run-Time Dynamic Linking

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


GetDllDirectoryA function (winbase.h)
Article02/09/2023

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

The size of the output buffer, in characters.

[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]

Minimum supported server Windows Server 2003 [desktop apps only]

Target Platform Windows

Header winbase.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
Dynamic-Link Library Search Order

SetDllDirectory

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


DLLGetDocumentation function
Article • 11/07/2022

Retrieves a localized string for a given help context value.

Syntax
C++

STDAPI DLLGetDocumentation
(
ITypeLib * ptlib,
ITypeInfo * ptinfo,
LCID lcid,
DWORD dwCtx,
BSTR * pbstrHelpString
);

Parameters
ptlib

The TypeLib associated with help context.

ptinfo

The TypeInfo associated with help context.

lcid

Windows Language Code Identifier.

dwCtx

Cookie value representing the help context id being looked for.

pbstrHelpString

Localized help string associated with the context id passed in.

Return value
This function doesn't return a value.

Remarks
For more info, see To specify localized help strings on GitHub.

Requirements

Target Platform Windows

Header N/A

Library N/A

DLL Unknown

See also
To specify localized help strings on GitHub

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


GetModuleFileNameA function
(libloaderapi.h)
Article02/09/2023

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

The size of the lpFilename buffer, in TCHARs.

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

The libloaderapi.h header defines GetModuleFileName 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 XP [desktop apps | UWP apps]

Minimum supported server Windows Server 2003 [desktop apps | UWP apps]

Target Platform Windows

Header libloaderapi.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
Dynamic-Link Library Functions

GetModuleFileNameEx

GetModuleHandle

LoadLibrary

LoadLibraryEx

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


GetModuleHandleA function
(libloaderapi.h)
Article02/09/2023

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.

The GetModuleHandle function returns a handle to a mapped module without


incrementing its reference count. However, if this handle is passed to the FreeLibrary
function, the reference count of the mapped module will be decremented. Therefore, do
not pass a handle returned by GetModuleHandle to the FreeLibrary function. Doing so
can cause a DLL module to be unmapped prematurely.

This function must be used carefully in a multithreaded application. There is no


guarantee that the module handle remains valid between the time this function returns
the handle and the time it is used. For example, suppose that a thread retrieves a
module handle, but before it uses the handle, a second thread frees the module. If the
system loads another module, it could reuse the module handle that was recently freed.
Therefore, the first thread would have a handle to a different module than the one
intended.

Examples
For an example, see Using Brushes.

7 Note

The libloaderapi.h header defines GetModuleHandle 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 XP [desktop apps only]

Minimum supported server Windows Server 2003 [desktop apps only]

Target Platform Windows

Header libloaderapi.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
Dynamic-Link Library Functions

FreeLibrary

GetModuleFileName

GetModuleHandleEx

LoadLibrary

LoadLibraryEx

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


GetModuleHandleExA function
(libloaderapi.h)
Article02/09/2023

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.

This option cannot be used with


GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT.
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
(0x00000002)

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.

This option cannot be used with GET_MODULE_HANDLE_EX_FLAG_PIN.

[in, optional] lpModuleName

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.

If dwFlags contains GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, the


GetModuleHandleEx function returns a handle to a mapped module without
incrementing its reference count. However, if this handle is passed to the FreeLibrary
function, the reference count of the mapped module will be decremented. Therefore, do
not pass a handle returned by GetModuleHandleEx with
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT to the FreeLibrary function.
Doing so can cause a DLL module to be unmapped prematurely.

If dwFlags contains GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, this


function must be used carefully in a multithreaded application. There is no guarantee
that the module handle remains valid between the time this function returns the handle
and the time it is used. For example, a thread retrieves a module handle, but before it
uses the handle, a second thread frees the module. If the system loads another module,
it could reuse the module handle that was recently freed. Therefore, first thread would
have a handle to a module different than the one intended.

To compile an application that uses this function, define _WIN32_WINNT as 0x0501 or


later. For more information, see Using the Windows Headers.

7 Note

The libloaderapi.h header defines GetModuleHandleEx 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 is 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 XP [desktop apps only]

Minimum supported server Windows Server 2003 [desktop apps only]

Target Platform Windows

Header libloaderapi.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
Dynamic-Link Library Functions

FreeLibrary

GetModuleFileName

LoadLibrary

LoadLibraryEx

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


GetProcAddress function
(libloaderapi.h)
Article02/06/2024

Retrieves the address of an exported function (also known as a procedure) or variable


from the specified dynamic-link library (DLL).

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++

typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);

// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.

PGNSI pGNSI;
SYSTEM_INFO si;

ZeroMemory(&si, sizeof(SYSTEM_INFO));

pGNSI = (PGNSI) GetProcAddress(


GetModuleHandle(TEXT("kernel32.dll")),
"GetNativeSystemInfo");
if(NULL != pGNSI)
{
pGNSI(&si);
}
else
{
GetSystemInfo(&si);
}
For the complete example that contains this code fragment, see Getting the System
Version.

Examples

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

Requirements
ノ Expand table

Minimum supported client Windows XP [desktop apps | UWP apps]

Minimum supported server Windows Server 2003 [desktop apps | UWP apps]

Target Platform Windows

Header libloaderapi.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
Dynamic-Link Library Functions

FreeLibrary

GetModuleHandle

LoadLibrary

LoadLibraryEx

LoadPackagedLibrary

Run-Time Dynamic Linking

Vertdll APIs available in VBS enclaves

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.

For additional load options, use the LoadLibraryEx function.

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

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

7 Note

The libloaderapi.h header defines LoadLibrary 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 XP [desktop apps only]

Minimum supported server Windows Server 2003 [desktop apps only]

Target Platform Windows

Header libloaderapi.h (include Windows.h)

Library Kernel32.lib
DLL Kernel32.dll

See also
DllMain

Dynamic-Link Library Functions

FindResource

FreeLibrary

GetProcAddress

GetSystemDirectory

GetWindowsDirectory

LoadLibraryEx

LoadResource

Run-Time Dynamic Linking

SetDllDirectory

SetErrorMode

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


LoadLibraryExA 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 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

This parameter is reserved for future use. It must be NULL.

[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

DONT_RESOLVE_DLL_REFERENCES If this value is used, and the executable module is


0x00000001 a DLL, the system does not call DllMain for process
and thread initialization and termination. Also, the
system does not load additional executable
modules that are referenced by the specified
module.

Note Do not use this value; it is


provided only for backward
compatibility. If you are planning to
access only data or resources in the
DLL, use
LOAD_LIBRARY_AS_DATAFILE_EXCLUSI
VE or
LOAD_LIBRARY_AS_IMAGE_RESOURCE
or both. Otherwise, load the library as a
DLL or executable module using the
LoadLibrary function.

LOAD_IGNORE_CODE_AUTHZ_LEVEL If this value is used, the system does not check


0x00000010 AppLocker rules or apply Software Restriction
Policies for the DLL. This action applies only to the
DLL being loaded and not to its dependencies.
This value is recommended for use in setup
programs that must run extracted DLLs during
installation.

Windows Server 2008 R2 and Windows 7: On


systems with KB2532445 installed, the caller must
be running as "LocalSystem" or "TrustedInstaller";
otherwise the system ignores this flag. For more
information, see "You can circumvent AppLocker
rules by using an Office macro on a computer that
is running Windows 7 or Windows Server 2008 R2"
in the Help and Support Knowledge Base at
https://support.microsoft.com/kb/2532445 .

Windows Server 2008, Windows Vista, Windows


Server 2003 and Windows XP: AppLocker was
introduced in Windows 7 and Windows
Server 2008 R2.

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.

This value can be used with


LOAD_LIBRARY_AS_IMAGE_RESOURCE. For more
information, see Remarks.

LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE Similar to LOAD_LIBRARY_AS_DATAFILE, except


0x00000040 that the DLL file is opened with exclusive write
access for the calling process. Other processes
cannot open the DLL file for write access while it is
in use. However, the DLL can still be opened by
other processes.

This value can be used with


LOAD_LIBRARY_AS_IMAGE_RESOURCE. For more
information, see Remarks.

Windows Server 2003 and Windows XP: This


value is not supported until Windows Vista.

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.

Windows Server 2003 and Windows XP: This


value is not supported until Windows Vista.

LOAD_LIBRARY_SEARCH_APPLICATION_DIR If this value is used, the application's installation


0x00000200 directory is searched for the DLL and its
dependencies. Directories in the standard search
path are not searched. This value cannot be
combined with
LOAD_WITH_ALTERED_SEARCH_PATH.

Windows 7, Windows Server 2008 R2,


Windows Vista and Windows Server 2008: This
value requires KB2533623 to be installed.

Windows Server 2003 and Windows XP: This


value is not supported.

LOAD_LIBRARY_SEARCH_DEFAULT_DIRS This value is a combination of


0x00001000 LOAD_LIBRARY_SEARCH_APPLICATION_DIR,
LOAD_LIBRARY_SEARCH_SYSTEM32, and
LOAD_LIBRARY_SEARCH_USER_DIRS. Directories
in the standard search path are not searched. This
value cannot be combined with
LOAD_WITH_ALTERED_SEARCH_PATH.

This value represents the recommended maximum


number of directories an application should
include in its DLL search path.

Windows 7, Windows Server 2008 R2,


Windows Vista and Windows Server 2008: This
value requires KB2533623 to be installed.

Windows Server 2003 and Windows XP: This


value is not supported.

LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR If this value is used, the directory that contains the


0x00000100 DLL is temporarily added to the beginning of the
list of directories that are searched for the DLL's
dependencies. Directories in the standard search
path are not searched.
The lpFileName parameter must specify a fully
qualified path. This value cannot be combined
with LOAD_WITH_ALTERED_SEARCH_PATH.

For example, if Lib2.dll is a dependency of


C:\Dir1\Lib1.dll, loading Lib1.dll with this value
causes the system to search for Lib2.dll only in
C:\Dir1. To search for Lib2.dll in C:\Dir1 and all of
the directories in the DLL search path, combine
this value with
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS.

Windows 7, Windows Server 2008 R2,


Windows Vista and Windows Server 2008: This
value requires KB2533623 to be installed.

Windows Server 2003 and Windows XP: This


value is not supported.

LOAD_LIBRARY_SEARCH_SYSTEM32 If this value is used, %windows%\system32 is


0x00000800 searched for the DLL and its dependencies.
Directories in the standard search path are not
searched. This value cannot be combined with
LOAD_WITH_ALTERED_SEARCH_PATH.

Windows 7, Windows Server 2008 R2,


Windows Vista and Windows Server 2008: This
value requires KB2533623 to be installed.

Windows Server 2003 and Windows XP: This


value is not supported.

LOAD_LIBRARY_SEARCH_USER_DIRS If this value is used, directories added using the


0x00000400 AddDllDirectory or the SetDllDirectory function are
searched for the DLL and its dependencies. If more
than one directory has been added, the order in
which the directories are searched is unspecified.
Directories in the standard search path are not
searched. This value cannot be combined with
LOAD_WITH_ALTERED_SEARCH_PATH.

Windows 7, Windows Server 2008 R2,


Windows Vista and Windows Server 2008: This
value requires KB2533623 to be installed.

Windows Server 2003 and Windows XP: This


value is not supported.

LOAD_WITH_ALTERED_SEARCH_PATH If this value is used and lpFileName specifies an


0x00000008 absolute path, the system uses the alternate file
search strategy discussed in the Remarks section
to find associated executable modules that the
specified module causes to be loaded. If this value
is used and lpFileName specifies a relative path,
the behavior is undefined.

If this value is not used, or if lpFileName does not


specify a path, the system uses the standard
search strategy discussed in the Remarks section
to find associated executable modules that the
specified module causes to be loaded.

This value cannot be combined with any


LOAD_LIBRARY_SEARCH flag.

LOAD_LIBRARY_REQUIRE_SIGNED_TARGET Specifies that the digital signature of the binary


0x00000080 image must be checked at load time.
This value requires Windows 8.1, Windows 10 or
later.

LOAD_LIBRARY_SAFE_CURRENT_DIRS If this value is used, loading a DLL for execution


0x00002000 from the current directory is only allowed if it is
under a directory in the Safe load list.

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.

Loading a DLL as a Data File or Image Resource


The LOAD_LIBRARY_AS_DATAFILE, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE, and
LOAD_LIBRARY_AS_IMAGE_RESOURCE values affect the per-process reference count
and the loading of the specified module. If any of these values is specified for the
dwFlags parameter, the loader checks whether the module was already loaded by the
process as an executable DLL. If so, this means that the module is already mapped into
the virtual address space of the calling process. In this case, LoadLibraryEx returns a
handle to the DLL and increments the DLL reference count. If the DLL module was not
already loaded as a DLL, the system maps the module as a data or image file and not as
an executable DLL. In this case, LoadLibraryEx returns a handle to the loaded data or
image file but does not increment the reference count for the module and does not
make the module visible to functions such as CreateToolhelp32Snapshot or
EnumProcessModules.

If LoadLibraryEx is called twice for the same file with LOAD_LIBRARY_AS_DATAFILE,


LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE, or LOAD_LIBRARY_AS_IMAGE_RESOURCE,
two separate mappings are created for the file.

When the LOAD_LIBRARY_AS_IMAGE_RESOURCE value is used, the module is loaded as


an image using portable executable (PE) section alignment expansion. Relative virtual
addresses (RVA) do not have to be mapped to disk addresses, so resources can be more
quickly retrieved from the module. Specifying LOAD_LIBRARY_AS_IMAGE_RESOURCE
prevents other processes from modifying the module while it is loaded.

Unless an application depends on specific image mapping characteristics, the


LOAD_LIBRARY_AS_IMAGE_RESOURCE value should be used with either
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE or LOAD_LIBRARY_AS_DATAFILE. This allows
the loader to choose whether to load the module as an image resource or a data file,
selecting whichever option enables the system to share pages more effectively.
Resource functions such as FindResource can use either mapping.

To determine how a module was loaded, use one of the following macros to test the
handle returned by LoadLibraryEx.

C++

#define LDR_IS_DATAFILE(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)1)


#define LDR_IS_IMAGEMAPPING(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)2)
#define LDR_IS_RESOURCE(handle) (LDR_IS_IMAGEMAPPING(handle) ||
LDR_IS_DATAFILE(handle))

The following table describes these macros.

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_IMAGEMAPPING(handle) If this macro returns TRUE, the module was loaded as an


image file (LOAD_LIBRARY_AS_IMAGE_RESOURCE).

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.

Searching for DLLs and Dependencies


The search path is the set of directories that are searched for a DLL. The LoadLibraryEx
function can search for a DLL using a standard search path or an altered search path, or
it can use a process-specific search path established with the SetDefaultDllDirectories
and AddDllDirectory functions. For a list of directories and the order in which they are
searched, see Dynamic-Link Library Search Order.
The LoadLibraryEx function uses the standard search path in the following cases:

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.

If lpFileName specifies an absolute path and dwFlags is set to


LOAD_WITH_ALTERED_SEARCH_PATH, LoadLibraryEx uses the altered search path. The
behavior is undefined when LOAD_WITH_ALTERED_SEARCH_PATH flag is set, and
lpFileName specifies a relative 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:

The directory that contains the DLL (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR).


This directory is searched only for dependencies of the DLL to be loaded.
The application directory (LOAD_LIBRARY_SEARCH_APPLICATION_DIR).
Paths explicitly added to the application search path with the AddDllDirectory
function (LOAD_LIBRARY_SEARCH_USER_DIRS) or the SetDllDirectory function. If
more than one path has been added, the order in which the paths are searched is
unspecified.
The System32 directory (LOAD_LIBRARY_SEARCH_SYSTEM32).

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 the application has used the SetDefaultDllDirectories function to establish a DLL


search path for the process and none of the LOAD_LIBRARY_SEARCH_* flags are used,
the LoadLibraryEx function uses the process DLL search path instead of the standard
search path.

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++

//Load the FMAPI DLL


hLib = ::LoadLibraryEx(L"fmapi.dll", NULL, NULL);
if ( !hLib )
{
wprintf(L"Could not load fmapi.dll, Error #%d.\n", GetLastError());
return;
}

For an additional example, see Looking Up Text for Error Code Numbers.

7 Note

The libloaderapi.h header defines LoadLibraryEx 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 XP [desktop apps only]

Minimum supported server Windows Server 2003 [desktop apps only]

Target Platform Windows

Header libloaderapi.h (include Windows.h)


Library Kernel32.lib

DLL Kernel32.dll

See also
DllMain

Dynamic-Link Library Functions

Dynamic-Link Library Search Order

Dynamic-Link Library Security

FindResource

FreeLibrary

GetProcAddress

GetSystemDirectory

GetWindowsDirectory

LoadLibrary

LoadResource

OpenFile

Run-Time Dynamic Linking

SearchPath

SetDllDirectory

SetErrorMode

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


LoadModule function (winbase.h)
Article10/13/2021

Loads and executes an application or creates a new instance of an existing application.

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:

1. The directory from which the application loaded.


2. The current directory.
3. The system directory. Use the GetSystemDirectory function to get the path of this
directory.
4. The 16-bit system directory. There is no function that obtains the path of this
directory, but it is searched. The name of this directory is System.
5. The Windows directory. Use the GetWindowsDirectory function to get the path of
this directory.
6. The directories that are listed in the PATH environment variable.

[in] lpParameterBlock

A pointer to an application-defined LOADPARMS32 structure that defines the new


application's parameter block.
Set all unused members to NULL, except for lpCmdLine, which must point to a null-
terminated string if it is not used. For more information, see Remarks.

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.

Return code/value Description

0 The system is out of memory or resources.

ERROR_BAD_FORMAT The .exe file is invalid.


11L

ERROR_FILE_NOT_FOUND The specified file was not found.


2L

ERROR_PATH_NOT_FOUND The specified path was not found.


3L

Remarks
The LOADPARMS32 structure has the following form:

syntax

typedef struct tagLOADPARMS32 {


LPSTR lpEnvAddress; // address of environment strings
LPSTR lpCmdLine; // address of command line
LPSTR lpCmdShow; // how to show new program
DWORD dwReserved; // must be zero
} LOADPARMS32;

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.

dwReserved This parameter is reserved; it must be zero.

Applications should use the CreateProcess function instead of LoadModule. The


LoadModule function calls CreateProcess by forming the parameters as follows.

CreateProcess parameter Argument used

lpszApplicationName lpModuleName

lpszCommandLine lpParameterBlock.lpCmdLine

lpProcessAttributes NULL

lpThreadAttributes NULL

bInheritHandles FALSE

dwCreationFlags 0

lpEnvironment lpParameterBlock.lpEnvAddress

lpCurrentDirectory NULL

lpStartupInfo The structure is initialized to zero. The cb member is set to the


size of the structure. The wShowWindow member is set to the
value of the second word of lpParameterBlock.lpCmdShow.

lpProcessInformation.hProcess The handle is immediately closed.

lpProcessInformation.hThread The handle is immediately closed.

Requirements

Minimum supported client Windows XP [desktop apps only]

Minimum supported server Windows Server 2003 [desktop apps only]


Target Platform Windows

Header winbase.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
CreateProcess

Dynamic-Link Library Functions

GetSystemDirectory

GetWindowsDirectory

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


LoadPackagedLibrary function
(winbase.h)
Article03/11/2023

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

This parameter is reserved. It must be 0.

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.

LoadPackagedLibrary returns a handle to the specified module and increments its


reference count. If the module is already loaded, the function returns a handle to the
loaded module. The calling process can use the handle returned by
LoadPackagedLibrary to identify the module in calls to the GetProcAddress function.
Use the FreeLibrary function to free a loaded module and decrement its reference count.

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

On Windows Phone, LoadPackagedLibrary must be called from PhoneAppModelHost.dll .


Using Kernel32.dll is not supported.

Requirements

Minimum supported client Windows 8 [desktop apps | UWP apps]

Minimum supported server Windows Server 2012 [desktop apps | UWP apps]

Target Platform Windows

Header winbase.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
Dynamic-Link Library Search Order

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


QueryOptionalDelayLoadedAPI function
(libloaderapi2.h)
Article10/09/2023

Determines whether the specified function in a delay-loaded DLL is available on the


system.

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

The name of the function to query. This parameter is case-sensitive.

Reserved

This parameter is reserved and must be zero (0).


Return value
TRUE if the specified function is available on the system. If the specified function is not
available on the system, this function returns FALSE. To get extended error information,
call GetLastError.

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.

Applications that target multiple versions of Windows or multiple Windows device


families also rely on delay-loaded DLLs to make visible extra features when they are
available.

A desktop application can use delayed loading as an alternative to runtime dynamic


linking that uses LoadLibrary or LoadLibraryEx to load a DLL and GetProcAddress to get
a pointer to a function. A Windows Store app cannot use LoadLibrary or LoadLibraryEx,
so to get the benefits to runtime dynamic linking, a Windows Store app must use the
delayed loading mechanism.

To check whether a function in a delay-loaded DLL is available on the system, the


application calls QueryOptionalDelayLoadedAPI with the specified function. If
QueryOptionalDelayLoadedAPI succeeds, the application can safely call the specified
function.

Examples

The following example shows how to use QueryOptionalDelayLoadedAPI to determine


whether the MkParseDisplayName function is available on the system.

C++

#include <windows.h>
#include <libloaderapi2.h>

// For this example, you need to pass


// /delayload: ext-ms-win-com-ole32-l1-1-1.dll to link.exe.
EXTERN_C IMAGE_DOS_HEADER __ImageBase;

BOOL
AreMonikersSupported ()
{

BOOL isApiAvailable;

// Check if MkParseDisplayName is available on the system. It is only


// available on desktop computers, and not on mobile devices or Xbox.

isApiAvailable =
QueryOptionalDelayLoadedAPI(static_cast<HMODULE>(&__ImageBase),
"ext-ms-win-com-ole32-l1-1-1.dll",
"MkParseDisplayName",
0);

return isApiAvailable;
}

Requirements

Minimum supported client Windows 10 [desktop apps | UWP apps]

Minimum supported server Windows Server 2016 [desktop apps | UWP apps]

Target Platform Windows

Header libloaderapi2.h

Library WindowsApp.lib

DLL Api-ms-win-core-libraryloader-l1-1-1.dll

See also
LoadPackagedLibrary

Run-Time Dynamic Linking

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

Minimum Windows Server 2012 [desktop apps only]


supported
server

Target Platform Windows

Header libloaderapi.h (include Windows.h)

DLL Kernel32.dll

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A


SetDefaultDllDirectories function
(libloaderapi.h)
Article10/13/2021

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

LOAD_LIBRARY_SEARCH_APPLICATION_DIR If this value is used, the application's installation


0x00000200 directory is searched.

LOAD_LIBRARY_SEARCH_DEFAULT_DIRS This value is a combination of


0x00001000 LOAD_LIBRARY_SEARCH_APPLICATION_DIR,
LOAD_LIBRARY_SEARCH_SYSTEM32, and
LOAD_LIBRARY_SEARCH_USER_DIRS.

This value represents the recommended maximum


number of directories an application should
include in its DLL search path.

LOAD_LIBRARY_SEARCH_SYSTEM32 If this value is used, %windows%\system32 is


0x00000800 searched.

LOAD_LIBRARY_SEARCH_USER_DIRS If this value is used, any path explicitly added


0x00000400 using the AddDllDirectory or SetDllDirectory
function is searched. If more than one directory
has been added, the order in which those
directories are searched is unspecified.

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:

The directory that contains the DLL (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR).


This directory is searched only for dependencies of the DLL being loaded.
The application directory (LOAD_LIBRARY_SEARCH_APPLICATION_DIR).
Paths explicitly added to the application search path with the AddDllDirectory
function (LOAD_LIBRARY_SEARCH_USER_DIRS) or the SetDllDirectory function. If
more than one path has been added, the order in which the paths are searched is
unspecified.
The System directory (LOAD_LIBRARY_SEARCH_SYSTEM32).

If SetDefaultDllDirectories does not specify LOAD_LIBRARY_SEARCH_USER_DIRS,


directories specified with the AddDllDirectory function are used only for LoadLibraryEx
function calls that specify LOAD_LIBRARY_SEARCH_USER_DIRS.

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

Minimum Windows 8 [desktop apps only],KB2533623 on Windows 7, Windows


supported Server 2008 R2, Windows Vista, and Windows Server 2008
client

Minimum Windows Server 2012 [desktop apps only]


supported
server

Target Platform Windows

Header libloaderapi.h (include Windows.h)

DLL Kernel32.dll

See also
AddDllDirectory

Dynamic-Link Library Search Order

Dynamic-Link Library Security

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:

1. The directory from which the application loaded.


2. The directory specified by the lpPathName parameter.
3. The system directory. Use the GetSystemDirectory function to get the path of this
directory. The name of this directory is System32.
4. The 16-bit system directory. There is no function that obtains the path of this
directory, but it is searched. The name of this directory is System.
5. The Windows directory. Use the GetWindowsDirectory function to get the path of
this directory.
6. The directories that are listed in the PATH environment variable.

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.

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 SetDllDirectory 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]

Minimum supported server Windows Server 2003 [desktop apps only]

Target Platform Windows


Header winbase.h (include Windows.h)

Library Kernel32.lib

DLL Kernel32.dll

See also
AddDllDirectory

Dynamic-Link Library Search Order

GetDllDirectory

GetSystemDirectory

GetWindowsDirectory

LoadLibrary

LoadLibraryEx

Feedback
Was this page helpful? ツ Yes ト No

Get help at Microsoft Q&A

You might also like