0

我有下面的代码,我的问题与foo()功能有关。

问题是,当foo()在每次执行之间有间隔的无限循环中执行时,会加载我的应用程序中已经存在的相同 dll ( FileName ) 的副本。

例如:gdi32.dll

那么,如何在我的应用程序中防止同一个 dll 的多个实例?

谢谢你。

这是foo()功能:

const
  myDll = 'c:\windows\system32\gdi32.dll';

    procedure foo(const FileName: string);
    var
      Image: THSPeImage;
    begin
     Image := THSPeImage.Create(FileName);
    try
     // Do something
     finally
       Image.Free;
      end;
    end;

/////// Usage /////////

While True do begin
  foo(myDll);
  Sleep(5000);
end;

使用单位:

PeImage.pas

unit PeImage;

interface
uses
 Windows, Classes, HSFileMapper;

type
 TSectionList = class(TList)
 private
   function GetItems(I: Integer): PImageSectionHeader;
 public
   property Items[I: Integer]: PImageSectionHeader read GetItems; default;
 end;

 THSPEImage = class
 private
   FMapper: THSFileMapper;
   FSections: TSectionList;
   function GetRVAData(AVirtualAddress: ULONG): Pointer;
 public
   constructor Create (const AFileName: string);
   destructor Destroy; override;
   property RVAData[VirtualAddress: ULONG]: Pointer read GetRVAData;
 end;

implementation

type
 PIMAGE_NT_HEADERS = PImageNtHeaders;
 PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
 PIMAGE_DATA_DIRECTORY = ^IMAGE_DATA_DIRECTORY;

{ THSPEImage }

constructor THSPEImage.Create(const AFileName: string);
var
 PSection: PImageSectionHeader;
 I: Integer;
 Header: PIMAGE_NT_HEADERS;
begin
 FMapper := THSFileMapper.Create (AFileName);
 FSections := TSectionList.Create;
 Header := PIMAGE_NT_HEADERS(FMapper.Map +
   PIMAGE_DOS_HEADER(FMapper.Map)^._lfanew);
 PSection := PImageSectionHeader(DWORD(@(Header^.OptionalHeader)) +
   Header^.FileHeader.SizeOfOptionalHeader);
 for I:=1 to Header^.FileHeader.NumberOfSections do begin
   FSections.Add (PSection);
   Inc(PSection);
 end;
end;

destructor THSPEImage.Destroy;
begin
 FSections.Free;
 inherited;
end;

function THSPEImage.GetRVAData(AVirtualAddress: ULONG): Pointer;
var
 I: Integer;
begin
 Result := nil;
 for I:=0 to Pred(FSections.Count) do
   with FSections[I]^ do
     if (VirtualAddress <= AVirtualAddress) and
        ((VirtualAddress + Misc.VirtualSize) > AVirtualAddress) then begin
       Result := FMapper.Map + PointerToRawData +
         (AVirtualAddress - VirtualAddress);
     end;
end;

{ TSectionList }

function TSectionList.GetItems(I: Integer): PImageSectionHeader;
begin
 Result := PImageSectionHeader (inherited Items[I]);
end;

end.

HSFileMapper.pas

unit HsFileMapper;

interface
uses
 Windows;

type
 THSFileMapper = class
 private
   FFileHandle: THandle;
   FFileSize: DWORD;
   FMap: PChar;
   FFileName: string;
   function GetEndMap: PChar;
 public
   constructor Create (const AFileName: string);
   destructor  Destroy; override;
   property Map: PChar read FMap;
   property EndMap: PChar read GetEndMap;
   property FileSize: DWORD read FFileSize;
   property FileName: string read FFileName;
 end;

implementation
uses
 SysUtils;

{ THSFileMapper }

constructor THSFileMapper.Create(const AFileName: string);
var
 SizeHighPart: DWORD;
 FileMapping: THandle;
begin
 FFileName := AFileName;
 FFileHandle := CreateFile (PChar(AFileName), GENERIC_READ,
   FILE_SHARE_READ or FILE_SHARE_WRITE,
   nil, OPEN_EXISTING, 0, 0);
 if FFileHandle = INVALID_HANDLE_VALUE then
   RaiseLastWin32Error;
 FFileSize := GetFileSize(FFileHandle, @SizeHighPart);
 FileMapping := CreateFileMapping (FFileHandle, nil, PAGE_READONLY, 0, 0, nil );
 if FileMapping = 0 then
   RaiseLastWin32Error;
 FMap := MapViewOfFile (FileMapping, FILE_MAP_READ, 0, 0, 0 );
 CloseHandle (FileMapping);
 if not Assigned(FMap) then
   RaiseLastWin32Error;
end;

destructor THSFileMapper.Destroy;
begin
 if Assigned(FMap) then
   UnmapViewOfFile (FMap);
 if FFileHandle <> INVALID_HANDLE_VALUE then
   CloseHandle (FFileHandle);
 inherited;
end;

function THSFileMapper.GetEndMap: PChar;
begin
 Result := FMap + FFileSize;
end;

end.
4

0 回答 0