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