Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception when loading native dlls from the application path when using AssemblyDirectory and System32 as the DllImportSearchPath #111825

Open
ThomasGoulet73 opened this issue Jan 25, 2025 · 3 comments · May be fixed by #111990
Labels
area-Interop-coreclr in-pr There is an active PR which will close this issue when it is merged
Milestone

Comments

@ThomasGoulet73
Copy link
Contributor

ThomasGoulet73 commented Jan 25, 2025

Description

There seems to be an issue when loading a native dll in the application path that depends on a native dll also in the application path when using DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32 as the search path. When both of those scenario occurs, it'll throw an exception that the dll could not be loaded. This issue is not reproducible when using only DllImportSearchPath.AssemblyDirectory or if a native dll does not have a dependency on another native dll in the application path. This also doesn't seem to affect native dlls shipped in a runtime pack because the .Net host seems to include a custom search path for the runtime packs.

This is a bug I found while investigating a problem when running WPF unit tests, see dotnet/wpf#10304 (comment) for more info. I'm not sure if it's the expected behavior, a bug or if I simply misunderstood the bug in WPF.

/cc @dipeshmsft

Reproduction Steps

  1. Clone https://github.com/ThomasGoulet73/DllSearchPathRepro
  2. Build TestLibrary1.
  3. Build TestLibrary2.
  4. Run ConsoleApp. It should exit without issue.
  5. Open Program.cs in ConsoleApp.
  6. Comment the line in Main with Test1WithoutSystem32
  7. Uncomment the line in Main with Test1WithSystem32
  8. Run ConsoleApp. It should exit with an exception that TestLibrary1.dll could not be loaded.

Expected behavior

Methods Test1WithoutSystem32 and Test1WithSystem32 should both succeed.

Actual behavior

Methods Test1WithoutSystem32 succeeds and Test1WithSystem32 fails.

Regression?

I tested using .Net 6 through .Net 9 and they all have the same behavior.

Known Workarounds

Change the DllImportSearchPath.

Configuration

.Net 9.0
Windows 11 x64
Don't know if it is specific to my configuration.

Other information

No response

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Jan 25, 2025
Copy link
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

@AaronRobinsonMSFT
Copy link
Member

@elinor-fung can you take a look?

@agocke agocke added this to the 10.0.0 milestone Jan 28, 2025
@agocke agocke removed the untriaged New issue has not been triaged by the area owner label Jan 28, 2025
@elinor-fung
Copy link
Member

elinor-fung commented Jan 28, 2025

We end up loading with LOAD_WITH_ALTERED_SEARCH_PATH | LOAD_LIBRARY_SEARCH_SYSTEM32. The LoadLibrary documentation indicates that LOAD_WITH_ALTERED_SEARCH_PATH cannot be combined with any LOAD_LIBRARY_SEARCH flag.

hmod = LoadFromPInvokeAssemblyDirectory(callingAssembly, currLibNameVariation, loadWithAlteredPathFlags | dllImportSearchPathFlags, pErrorTracker);

I'm not sure why it only fails in the case where it needs to load a dependency of the library, but we should probably remove any LOAD_LIBRARY_SEARCH flags when explicitly passing LOAD_WITH_ALTERED_SEARCH_PATH (like we do for the assembly directory case above).

I think that is also true for the case where the DllImport specifies an absolute path:

if (!libNameIsRelativePath)
{
DWORD flags = loadWithAlteredPathFlags;
if ((dllImportSearchPathFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) != 0)
{
// LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR is the only flag affecting absolute path. Don't OR the flags
// unconditionally as all absolute path P/Invokes could then lose LOAD_WITH_ALTERED_SEARCH_PATH.
flags |= dllImportSearchPathFlags;
}

@dotnet-policy-service dotnet-policy-service bot added the in-pr There is an active PR which will close this issue when it is merged label Jan 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Interop-coreclr in-pr There is an active PR which will close this issue when it is merged
Projects
Status: No status
4 participants