如何在我的应用程序中阻止同一模块的多个实例?

时间:2017-03-12 00:08:11

标签: delphi file-mapping

我的代码如下,我的问题与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.

0 个答案:

没有答案