How DLL Name Resolution Works on Windows: A Practical Look at Search Order, Known DLLs, API Sets, and SxS

· · Windows, DLL, Loader, Security, Windows Development

When you work with native DLLs on Windows, confusion like this comes up all the time:

  • You write LoadLibrary("foo.dll") — where does Windows actually look?
  • You drop a DLL right next to the EXE, and yet a different DLL gets loaded
  • Does System32 win, or does the application folder win?
  • At what point do manifests, API sets, and Known DLLs come into play?
  • Even when you load a DLL by full path, are its dependencies pinned the same way?

This article organizes Windows DLL name resolution from a practical, day-to-day angle.

1. The bottom line first

  • Windows DLL name resolution does not start with a filesystem search. DLL redirection, API sets, SxS manifests, the loaded-module list, and Known DLLs all sit in front of the search order.
  • For a typical desktop app, the application folder is high up in the order, but the special rules above are evaluated before it.
  • Loading a DLL by full path does not automatically pin that DLL’s dependencies to the same full path.
  • Known DLLs is a mechanism by which the OS binds certain well-known DLLs to the system copy. It is not something an application can override by dropping a DLL in its own folder.
  • API sets (api-ms-win-...) are not physical DLL names — they are virtual aliases that hide the real implementation DLL.
  • For safety, combine full paths, SetDefaultDllDirectories, and the search flags on LoadLibraryEx to explicitly narrow the search scope.

2. Pre-filesystem rules

The DLL load search order has the following pre-filesystem rules ahead of any directory probing:

  1. DLL redirection
  2. API sets
  3. SxS manifest redirection
  4. The loaded-module list (is a DLL with the same name already in memory?)
  5. Known DLLs

Only after these does the loader move on to the application folder, System32, the Windows folder, PATH, and so on.

3. Standard search order for an unpackaged app

For a regular desktop app (with safe DLL search mode enabled), the search order is:

  1. DLL redirection
  2. API sets
  3. SxS manifest redirection
  4. The loaded-module list
  5. Known DLLs
  6. The directory the application was loaded from
  7. System32
  8. The 16-bit system folder
  9. The Windows folder
  10. The current folder
  11. PATH

Key points:

  • The current folder sits fairly far down by default. Safe DLL search mode makes it harder to push it forward.
  • That does not mean it is safe just because it is at the bottom. As long as a directory an attacker can control is anywhere in the search list, there is still room for a DLL planting attack.

4. Packaged apps and unpackaged apps are different

Packaged apps (MSIX and similar) define a different search order. Missing this distinction is a common source of confusion: a DLL that the loader finds during your unpackaged dev runs may be unfindable inside the production package.

In articles and design reviews, the safest first move is to ask “are we talking about a packaged app or an unpackaged app?” before anything else.

5. Known DLLs and the loaded-module list

The loaded-module list: the system checks whether a DLL with the same module name is already loaded into the process. If you miss the fact that “a same-named DLL from a different folder was loaded into this process first,” you will misread your repro conditions.

Known DLLs: a list of DLLs that Windows treats as well known for that version. You can inspect it under HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs. This is not a list a normal application can override by dropping a same-named DLL into its own folder.

6. API sets are contracts, not physical DLL names

Names like api-ms-win-core-... are not the actual DLL filenames on disk. They are virtual aliases that hide the real implementation DLL. The API set scheme keeps things consistent even when the implementing DLL differs across Windows versions or device categories.

7. The role of manifests and SxS

DLL redirection and SxS manifests are not just minor tweaks to the search order — they exist to avoid DLL versioning conflicts. In practice you should keep these scenarios mentally separate:

  • Just placing a private DLL in the app folder
  • Using DLL redirection such as .local
  • Using side-by-side binding via a manifest

8. Things to watch in the main APIs

SetDllDirectory

This does more than change the search order — it effectively disables safe DLL search mode as a side effect. Reaching for it casually can backfire from a security standpoint.

AddDllDirectory

Directories you add are used together with LOAD_LIBRARY_SEARCH_USER_DIRS. When you add several, the search order between them is unspecified.

SetDefaultDllDirectories

This API removes hijack-prone directories from the default DLL search path and limits the search scope. It applies process-wide, and once you set it, you cannot revert to the original default search path.

LoadLibraryEx

With flags like LOAD_WITH_ALTERED_SEARCH_PATH and LOAD_LIBRARY_SEARCH_*, you can control search behavior — for example, including the folder of the loading DLL when resolving its dependencies.

9. A full path does not pin the dependencies

This matters a lot in practice and is easy to miss. Even when you load the first DLL by full path, its dependencies are still resolved by module name alone.

In other words, explicitly loading C:\MyApp\plugins\foo.dll does not guarantee that bar.dll, which foo.dll depends on, will also be picked up from that same folder.

10. Avoiding DLL hijacking

  • Cut down on bare-name loads like LoadLibrary("foo.dll")
  • Use full paths where you can
  • Tighten the process default search path with SetDefaultDllDirectories
  • Add only the directories you have explicitly approved using AddDllDirectory
  • Make the search scope explicit with LOAD_LIBRARY_SEARCH_SYSTEM32, LOAD_LIBRARY_SEARCH_APPLICATION_DIR, and LOAD_LIBRARY_SEARCH_USER_DIRS
  • Avoid relying on the current folder or a careless PATH

A process running with administrator privileges combined with a vague search path is especially dangerous. A malicious DLL loaded under those conditions runs with that process’s privileges.

11. A practical checklist

  1. Is the app packaged or unpackaged?
  2. Which DLLs come in via static linking, and which are loaded dynamically?
  3. Is the load done by full path, or by module name alone?
  4. Are you using SetDllDirectory?
  5. Is the design suitable for SetDefaultDllDirectories and LOAD_LIBRARY_SEARCH_*?
  6. Are you using AddDllDirectory multiple times while implicitly relying on an order that is not guaranteed?
  7. Are dependencies managed via manifests, SxS, private DLLs, or redirection — which one?
  8. Are there security-weak assumptions about the current folder or PATH?
  9. Could a dependent DLL be resolved from a different location in another environment?

Summary

DLL name resolution on Windows is not just “the order in which folders are searched.” In reality, DLL redirection, API sets, SxS manifests, the loaded-module list, Known DLLs, and the search space modified by various API calls all stack on top of each other.

What matters most in practice:

  • Do not memorize the search order as a single flat table
  • Separate packaged from unpackaged
  • Understand that even with a full path, dependent DLLs are handled separately
  • Do not reach for SetDllDirectory casually
  • When you want to err on the safe side, use SetDefaultDllDirectories together with the LoadLibraryEx search flags

References

  1. Microsoft Learn: Dynamic-link library search order
  2. Microsoft Learn: Dynamic-Link Library Security
  3. Microsoft Learn: Windows API sets
  4. Microsoft Learn: SetDefaultDllDirectories function
  5. Microsoft Learn: AddDllDirectory function
  6. Microsoft Learn: LoadLibraryEx function
  7. Microsoft Learn: Dynamic-link library redirection
  8. Microsoft Learn: Manifests
  9. Microsoft Learn: About Side-by-Side Assemblies

Related Articles

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

Related Topics

These topic pages place the article in a broader service and decision context.

Where This Topic Connects

This article connects naturally to the following service pages.

Back to the Blog