How Windows DLL Name Resolution Works - Search Order and SxS
· Go Komura · Windows, DLL, Loader, Security, Windows Development
Whenever native DLLs on Windows come up, confusion like the following arises with remarkable frequency.
- When you write
LoadLibrary("foo.dll"), where does it actually look? - You put the DLL in the same folder as the executable, so why is a different DLL being loaded?
- Does
System32take precedence, or does the application folder? - At which stage do manifests, API sets, and Known DLLs take effect?
- What changes when you use
SetDllDirectoryorAddDllDirectory? - What makes DLL planting attacks and DLL hijacking likely to happen?
Memorizing the search order as a one-liner is not enough for real work. In reality, the Windows loader evaluates several special rules before it ever starts walking the file system in order.
In this article, we organize DLL name resolution on Windows for practical use, covering the differences between unpackaged and packaged apps, Known DLLs, the loaded-module list, API sets, side-by-side manifests, and the effects of the LoadLibraryEx family of APIs.
The content is based on public information on Microsoft Learn as of March 2026.123456789
1. The Conclusion First
Here are the practical conclusions up front.
- Windows DLL name resolution is not “file system search first.” Elements like DLL redirection, API sets, SxS manifests, the loaded-module list, and Known DLLs come before the search order proper.1
- In the standard configuration for an unpackaged app with safe DLL search mode enabled, the application folder ranks high, but the special rules above are evaluated before it.1
- Even if you load a DLL by full path, its dependent DLLs are not automatically pinned to the same full path. Dependent DLLs are searched by module name only, so they can be resolved from somewhere else.1
Known DLLsis a mechanism by which the OS binds certain well-known DLLs to the system-side copies; it is not something a normal app-side deployment overrides.1- An API set is not “the actual DLL name itself” but a virtual alias that hides the implementation DLL. If you see a name like
api-ms-win-...and reason about it the way you would about a normal DLL search, you will likely misunderstand.3 SetDllDirectorydoes more than change the search order — it has the behavior of effectively disabling safe DLL search mode, so using it casually can backfire from a security standpoint.1- In practice, the safe approach is to combine full-path loading,
SetDefaultDllDirectories,AddDllDirectory, and theLOAD_LIBRARY_SEARCH_*flags ofLoadLibraryExto narrow the search scope explicitly.4562
In short, the practical view is that Windows DLL name resolution is determined not just by “which folder comes in what order,” but by “which pre-stage rules resolve the name first” and “how the APIs have altered the search space.”
2. DLL Name Resolution Has Pre-Stage Rules Before “Folder Search”
According to the DLL search order documentation on Microsoft Learn, when a DLL is loaded, the following elements are treated as part of the search order first.1
- DLL redirection
- API sets
- SxS manifest redirection
- The loaded-module list
- Known DLLs
Only after that does the loader proceed to the file system search across the app folder, System32, the Windows folder, PATH, and so on.1
If you miss this, it can feel “wrong” that something gets decided before the application folder — but as a description of the Windows loader, that is in fact the main path.
flowchart TD
A["DLL name needs resolution"] --> B["DLL redirection"]
B --> C["API set"]
C --> D["SxS manifest redirection"]
D --> E["loaded-module list"]
E --> F["Known DLLs"]
F --> G["Search order on the file system"]
G --> H["The DLL actually loaded is determined"]
3. The Standard Search Order for Unpackaged Apps
For an ordinary desktop app loading a DLL without a full path, Microsoft Learn describes the standard search order for unpackaged apps. In the default state with safe DLL search mode enabled, the flow is essentially this.1
- DLL redirection
- API sets
- SxS manifest redirection
- The loaded-module list
- Known DLLs
- On Windows 11 21H2 and later, the package dependency graph
- The folder the application was loaded from
System32- The 16-bit system folder
- The Windows folder
- The current folder
PATH
Three points matter most in practice.
- The current folder is quite far down by default. Safe DLL search mode makes it hard to move the current folder forward.1
- However, being far down does not mean safe. As long as a directory the attacker can control remains in the search scope, room for DLL preloading remains.2
- On Windows 11 21H2 and later, the package dependency graph appears in the unpackaged app search description as well. This is an easy delta to miss if you only remember the older description.1
4. Packaged Apps and Unpackaged Apps Are Not the Same
Microsoft Learn defines a separate search order for packaged apps. In packaged apps, the package dependency graph takes effect at an earlier stage, and the search model itself is somewhat different.1
Miss this difference, and after moving to MSIX or adopting the Windows App SDK you get confusion like this:
- A DLL found when running unpackaged during development is not found in the production package
- Dependencies via the package manifest mix with old-style
PATHdependence and the reproduction conditions change - Explaining “the Windows DLL search order is such-and-such” with a single table, dropping the behavioral differences of packaged apps
In articles and design reviews, it is safest to first separate “is this about a packaged app or an unpackaged app?”1
5. What Known DLLs and the Loaded-Module List Are Doing
The parts of DLL resolution most likely to defy intuition are the loaded-module list and Known DLLs.
5.1 The loaded-module list
Microsoft Learn explains that the system can check whether a DLL with the same module name is already loaded in memory.1
In other words, before the file system search, there is a check of
- whether that DLL name is already loaded, and
- consequently, whether there is any need to go searching at all.
So if, during an investigation, you drop the fact that “in this process, a same-named DLL from another folder was already loaded first,” you will misread the reproduction conditions.
5.2 Known DLLs
Known DLLs is the list of DLLs Windows considers well known for that version, and it can be inspected at HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\KnownDLLs. For a DLL on the list, the system uses its copy of that known DLL.1
What matters here is that Known DLLs is not the kind of thing a regular app can “win” by placing a same-named DLL in its application folder.
Understanding it as a simple first-come race against System32 misreads the behavior.
6. An API Set Is a Contract Name, Not an “Actual DLL Name”
When you see a name like api-ms-win-core-..., it is tempting to wonder “where do I find that DLL file?” But Microsoft Learn explains that an API set is a virtual alias for a physical DLL — a mechanism that separates the contract from the implementation.3
In other words, reasoning like
- API set name = the physical DLL file name as is
- API set resolution = the same file search as a normal DLL
is inaccurate.
With the API set model in mind, it becomes easier to explain that
- things stay consistent even when the implementing DLL name differs across Windows versions and device types, and
- the caller does not need to know, in fixed terms, “which host DLL implements this.”3
7. Manifests and Side-by-Side (SxS) Are an Alternative Answer to the DLL Versioning Problem
DLL redirection and SxS manifests are described not as minor search-order tricks but as mechanisms for avoiding DLL versioning conflicts.789
Microsoft Learn’s framing is:
- A manifest is XML describing a side-by-side assembly or an isolated application
- A side-by-side assembly is the unit of naming, binding, versioning, and deployment
- The loader decides which version to bind to based on the dependencies recorded in the manifest
So in practice you need to think about these three separately:
- Simply placing a private DLL in the app folder
- Using DLL redirection such as
.local - Using side-by-side binding via manifests
All of them are similar in that they “affect DLL resolution,” but their design intent is not the same.
8. What Changes with LoadLibraryEx, SetDllDirectory, and AddDllDirectory
8.1 SetDllDirectory
SetDllDirectory changes the search order, but Microsoft Learn explicitly states that it effectively disables safe DLL search mode.1
That is, even if you only intended to “add one app-specific folder,” the search space changes as a result, including how the current folder is treated.
Furthermore, calling SetDllDirectory in a parent process can affect the standard search order in child processes as well.1
For this reason, rather than using SetDllDirectory carelessly as a habit, it is safer in practice to lean on
SetDefaultDllDirectoriesAddDllDirectory- the
LOAD_LIBRARY_SEARCH_*flags ofLoadLibraryEx
8.2 AddDllDirectory
Paths added with AddDllDirectory are used in combination with LOAD_LIBRARY_SEARCH_USER_DIRS.
On Microsoft Learn, the search order among multiple added directories is unspecified.15
So a design that
- adds multiple directories, and
- strictly expects a particular search order among them
is best avoided.
8.3 SetDefaultDllDirectories
SetDefaultDllDirectories is described as an API for removing the more vulnerability-prone directories from the standard DLL search path and restricting the search scope.4
Three properties are particularly worth knowing.
- It takes effect per process
- Once called, it persists for the lifetime of the process
- A standard search path once set cannot simply be restored to the original default
From a security standpoint, this API lends itself to a design of “shifting to a safer search space right after startup.”4
8.4 LoadLibraryEx
LoadLibraryEx lets you change the search behavior with LOAD_WITH_ALTERED_SEARCH_PATH and the LOAD_LIBRARY_SEARCH_* flags.61
Practically, it is an API well suited to requirements like
- including the folder of the DLL being loaded in the search scope, dependencies included, or
- restricting the search to the application folder,
System32, and explicitly added user directories only.
9. A Full Path Does Not Pin the Dependent DLLs
This is the point on this topic that matters a great deal in practice yet is easily overlooked. Microsoft Learn explains that even when the first DLL is loaded by full path, its dependent DLLs are searched by module name only.14
That is, just because
- you explicitly loaded
C:\\MyApp\\plugins\\foo.dll
it does not follow that
bar.dll, whichfoo.dlldepends on, will always be taken from the same folder.
With this misconception in place, you get the rather nasty failure mode of
- it works in the development environment,
- a different
bar.dllgets resolved at the customer site, and - dependent-DLL conflicts become environment-dependent to reproduce.
10. Avoiding DLL Preloading / Hijacking
Microsoft Learn’s DLL security documentation explains that the combination of dynamic loading without a full path and attacker-controllable directories in the search scope leads to DLL preloading attacks and binary planting attacks.2
In practice, it helps to converge on this baseline.
- Reduce bare-name loads like
LoadLibrary("foo.dll") - Use full-path loading where needed
- Narrow the process-default search path with
SetDefaultDllDirectories - Add only explicitly approved directories with
AddDllDirectory - Make the search scope explicit with flags like
LOAD_LIBRARY_SEARCH_SYSTEM32,LOAD_LIBRARY_SEARCH_APPLICATION_DIR, andLOAD_LIBRARY_SEARCH_USER_DIRS - Avoid the current folder and careless reliance on
PATH
A situation where a process running with administrator privileges has an ambiguous search path is especially dangerous. Microsoft Learn also notes that when a malicious DLL gets loaded, it executes with the privileges of that process.2
11. A Practical Decision Checklist
When reviewing DLL loading design on Windows, checking at least the following reduces incidents.
- Is the app a packaged app or an unpackaged app?
- Which DLLs come from static linking, and which are dynamically loaded?
- Full-path loading, or module name only?
- Is
SetDllDirectoryin use anywhere? - Is the configuration such that
SetDefaultDllDirectoriesandLOAD_LIBRARY_SEARCH_*can be used? - Are multiple
AddDllDirectorycalls in use with an implicit expectation of ordering? - Are dependencies managed via manifests / SxS / private DLLs / redirection — and which one?
- Are there weak security assumptions around the current folder or
PATH? - Could dependent DLLs be resolved from a different location in a different environment?
Checking these nine points separately lets you eliminate problems like “DLL not found,” “the wrong DLL was loaded,” “it only fails to start in production,” and “blocked at the vulnerability review” at a much earlier stage.
12. Summary
DLL name resolution on Windows is not merely a “folder search order.” In reality, it is determined by the overlap of DLL redirection, API sets, SxS manifests, the loaded-module list, Known DLLs, and the search space as modified by API calls.134
What matters most in practice comes down to these five things.
- Do not memorize the search order as a single table
- Separate packaged from unpackaged
- Understand that even with full-path loading, dependent DLLs can be treated differently
- Do not use
SetDllDirectorycasually - To err on the safe side, use
SetDefaultDllDirectoriesand the search flags ofLoadLibraryEx
DLL name resolution is a place where startup failures, environment differences, and security problems all tend to surface at once. That is exactly why it is worth understanding not just “in what order Windows searches,” but “what Windows treats as the premises of name resolution in the first place.”
Related articles
- A Minimum Security Checklist for Windows Applications
- How Far Can a Windows App Really Be a Single Binary?
- When Do You Actually Need Administrator Privileges on Windows?
- What Is Reg-Free COM?
References
- Microsoft Learn: Dynamic-link library search order
- Microsoft Learn: Dynamic-Link Library Security
- Microsoft Learn: Windows API sets
- Microsoft Learn: SetDefaultDllDirectories function
- Microsoft Learn: AddDllDirectory function
- Microsoft Learn: LoadLibraryEx function
- Microsoft Learn: Dynamic-link library redirection
- Microsoft Learn: Manifests
- Microsoft Learn: About Side-by-Side Assemblies
-
Microsoft Learn, Dynamic-link library search order, accessed March 24, 2026 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15 ↩16 ↩17 ↩18 ↩19 ↩20 ↩21
-
Microsoft Learn, Dynamic-Link Library Security, accessed March 24, 2026 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Windows API sets, accessed March 24, 2026 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, SetDefaultDllDirectories function, accessed March 24, 2026 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Microsoft Learn, AddDllDirectory function, accessed March 24, 2026 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, LoadLibraryEx function, accessed March 24, 2026 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Dynamic-link library redirection, accessed March 24, 2026 ↩ ↩2
-
Microsoft Learn, About Side-by-Side Assemblies, accessed March 24, 2026 ↩ ↩2 ↩3
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
Why Windows Became What It Is Today: The Evolution of Windows Through a Developer's Eyes
A look at the changes from Windows 95 to Windows 11 — not as a visual timeline, but from a Windows application developer's perspective: c...
Why Windows Shows "Windows protected your PC"
A practical look at why SmartScreen warnings appear when distributing Windows apps, covering code signing, EV/OV certificates, Azure Arti...
When Do You Actually Need Administrator Privileges on Windows? - UAC, Protected Areas, and How to Tell by Design
A practical look at when administrator privileges are required on Windows, from the perspectives of UAC, protected areas, services, drive...
What to Do Before Disposing of a Windows PC — A Practical Checklist for Data Erasure, Account Unlinking, and Backups
What to do before disposing of, transferring, selling, or returning a leased Windows PC — covering backups, data erasure, BitLocker, Micr...
Windows App Outsourcing and Contract Development: What to Sort Out Before You Ask
Before commissioning Windows app outsourcing or contract development, here is how to sort out existing software modification, device inte...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Where This Topic Connects
This article connects naturally to the following service pages.
Windows App Development
DLL placement and loading directly affect whether a Windows app starts, how it is distributed, and how reproducible failures are, so this is well worth addressing in the context of Windows application development.
Technical Consulting & Design Review
DLL name resolution sits at the intersection of bug investigation, porting, vulnerability avoidance, and distribution design, making it an easy topic to work through as a design review or technical consultation.
Author Profile
Profile page for the article author.
Go Komura
Representative of KomuraSoft LLC
Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.
Public links