【Windows】获取函数地址所对应的DLL或EXE地址

下面这个函数可以让你知道一个函数来自那里DLL或者是不是当前可执行文件内部实现的函数,参考代码如下:

uses psapi;

function GetCodeFileName(Addr: Pointer): QStringW;
var
  AModules: array of THandle;
  I, ACount: Cardinal;
  APriorModule: THandle;
  procedure QuickSort(L, R: Integer);
  var
    I, J: Integer;
    P, T: THandle;
  begin
    repeat
      I := L;
      J := R;
      P := AModules[(L + R) shr 1];
      repeat
        while AModules[I] < P do
          Inc(I);
        while AModules[J] > P do
          Dec(J);
        if I <= J then
        begin
          if I <> J then
          begin
            T := AModules[I];
            AModules[I] := AModules[J];
            AModules[J] := T;
          end;
          Inc(I);
          Dec(J);
        end;
      until I > J;
      if L < J then
        QuickSort(L, J);
      L := I;
    until I >= R;
  end;
  function GetModuleFileName(AModule: THandle): QStringW;
  begin
    SetLength(Result, MAX_PATH);
    SetLength(Result, GetModuleFileNameW(AModule, PWideChar(Result), MAX_PATH));
  end;

begin
  Result := '';
  EnumProcessModules(GetCurrentProcess, nil, 0, ACount);
  SetLength(AModules, ACount);
  APriorModule := 0;
  if EnumProcessModules(GetCurrentProcess, @AModules[0], ACount, ACount) then
  begin
    QuickSort(0, ACount - 1);
    for I := 0 to ACount - 1 do
    begin
      if AModules[I] <> 0 then
      begin
        if (THandle(Addr) >= APriorModule) and (THandle(Addr) < AModules[I])
        then
        begin
          Result := GetModuleFileName(APriorModule);
          Break;
        end;
        APriorModule := AModules[I];
      end;
    end;
    if Length(Result) = 0 then
    begin
      SetLength(Result, MAX_PATH);
      SetLength(Result, GetModuleFileNameW(APriorModule, PWideChar(Result),
        MAX_PATH));
    end;
  end;
end;

这个函数的用法比较简单,比如我们要看一下 IDBService 这个服务实例是由那个 DLL 创建的:

var
  AService: IDBService;
begin
  if Supports(PluginsManager, IDBService, AService) then
  begin
    ShowMessage('服务 ' + IntToHex(IntPtr(AService), 8) + ' 来自文件: '#13#10 +
      GetCodeFileName(PPointer(AService)^));
  end;

 

执行效果如下:
codefilename

 

分享到: