You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调整Delphi应用的系统DLL搜索方式,避免加载伪系统DLL?

Fixing Delphi App Loading Rogue System DLLs from Application Directory

Great question! This is a classic Windows DLL loading pitfall—by default, Windows checks the app's current directory first before system folders, which lets rogue copies of system DLLs hijack the load and throw errors like the 0xc0000020 status you're seeing. Here are several practical, reliable ways to resolve this:

1. Adjust DLL Search Order via Initialization Code

The simplest and most effective fix for modern Windows versions is to modify the DLL search path early in your app's lifecycle. Use Windows API functions to prioritize system directories over your app's folder:

uses
  Windows;

initialization
  // Target Windows Vista and later (most systems today)
  if Win32MajorVersion >= 6 then
    // Restrict DLL searches to the System32 folder for system DLLs
    SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32)
  else
    // For Windows XP and older, remove current directory from search path
    SetDllDirectory('');

How it works:

  • SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32) tells Windows to only look in the System32 directory for system DLLs, skipping the app's current folder entirely.
  • For older systems, SetDllDirectory('') clears the current directory from the DLL search order, forcing Windows to use the standard system path.

2. Use an Application Manifest to Redirect System DLLs

You can add a manifest file to your Delphi project that explicitly instructs Windows to load specified system DLLs from the system directory, overriding the default search order.

  1. Create a file named app.manifest with this content:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <!-- Optional: Include common controls manifest if needed -->
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
    </dependentAssembly>
  </dependency>
  <!-- List system DLLs you want to protect; add more as needed -->
  <file name="version.dll" />
  <file name="kernel32.dll" />
  <file name="user32.dll" />
</assembly>
  1. Link it to your Delphi project:
    • Go to Project > Options > Application > Manifest
    • Select "Custom manifest" and browse to your app.manifest file

This tells Windows to load the listed DLLs directly from the system location, ignoring any copies in your app's directory.

For core system functions you rely on, you can statically link them instead of using dynamic loading. In Delphi, you can use the {$LINK} directive to link against import libraries directly. This is more work, but it eliminates the risk of DLL hijacking for those specific functions.

For example, to statically link a function from kernel32.dll:

{$LINK 'kernel32.lib'}
function GetSystemDirectory(lpBuffer: LPTSTR; uSize: UINT): UINT; stdcall;

Note: This method only works for individual functions, not entire DLLs, so it's best for critical, frequently used functions.

4. Hook LoadLibrary to Validate DLL Sources (High Security)

If you need maximum control, you can hook the LoadLibrary/LoadLibraryEx functions in your app to validate that system DLLs are loaded from the system directory. This requires using a detour library like Microsoft Detours to intercept the calls.

Here's a simplified example:

uses
  Windows;

type
  TLoadLibraryW = function(lpLibFileName: PWideChar): HMODULE; stdcall;

var
  OriginalLoadLibraryW: TLoadLibraryW;

function HookedLoadLibraryW(lpLibFileName: PWideChar): HMODULE; stdcall;
var
  SystemDir: array[0..MAX_PATH] of WideChar;
  FullSystemPath: array[0..MAX_PATH] of WideChar;
begin
  // Check if we're loading a system DLL (customize this list as needed)
  if SameText(lpLibFileName, 'version.dll') then
  begin
    GetSystemDirectoryW(SystemDir, MAX_PATH);
    wsprintfW(FullSystemPath, '%s\%s', [SystemDir, lpLibFileName]);
    Result := OriginalLoadLibraryW(FullSystemPath);
  end
  else
    // For non-system DLLs, use the original load logic
    Result := OriginalLoadLibraryW(lpLibFileName);
end;

initialization
  // Get pointer to original LoadLibraryW
  OriginalLoadLibraryW := GetProcAddress(GetModuleHandleW('kernel32.dll'), 'LoadLibraryW');
  // Install detour (requires Microsoft Detours library)
  // DetourAttach(PVOID(@OriginalLoadLibraryW), PVOID(@HookedLoadLibraryW));
finalization
  // Remove detour when app exits
  // DetourDetach(PVOID(@OriginalLoadLibraryW), PVOID(@HookedLoadLibraryW));

Important Considerations:

  • The SetDefaultDllDirectories method is the most recommended for modern apps—it's lightweight, OS-native, and covers all system DLLs without needing to list them individually.
  • Always test your app on all target Windows versions to ensure compatibility, especially if you support older systems like Windows XP.
  • Avoid breaking legitimate DLLs your app needs to load from its own directory—these methods target system DLLs, but double-check your app's dependencies to ensure you don't block required files.

内容的提问来源于stack exchange,提问作者Anto Raja Prakash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:44:56