type
PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;
PIMAGE_EXPORT_DIRECTORY = ^IMAGE_EXPORT_DIRECTORY;
function ImageNtHeader(Base: Pointer): PIMAGE_NT_HEADERS;
stdcall;
external '
dbghelp.dll';
function ImageRvaToVa(NtHeaders: Pointer; Base: Pointer; Rva: ULONG;
LastRvaSection: Pointer): Pointer;
stdcall;
external '
dbghelp.dll';
procedure ImageExportedFunctionNames(
const ImageName:
string; NamesList: TStrings);
var
i: Integer;
FileHandle: THandle;
ImageHandle: THandle;
ImagePointer: Pointer;
Header: PIMAGE_NT_HEADERS;
ExportTable: PIMAGE_EXPORT_DIRECTORY;
NamesPointer: Pointer;
Names: PAnsiChar;
NamesDataLeft: Integer;
begin
//NOTE: our policy in this procedure is to exit upon any failure and return an empty list
NamesList.Clear;
FileHandle := CreateFile(PWideChar(ImageName),GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if FileHandle=INVALID_HANDLE_VALUE
then
exit;
try
ImageHandle := CreateFileMapping(FileHandle,
nil, PAGE_READONLY, 0, 0,
nil);
if ImageHandle = 0
then
exit;
try
ImagePointer := MapViewOfFile(ImageHandle, FILE_MAP_READ, 0, 0, 0);
if not Assigned(ImagePointer)
then
exit;
try
Header := ImageNtHeader(ImagePointer);
if not Assigned(Header)
then
exit;
if Header.Signature<>$00004550
then // "PE\0\0" as a DWORD.
exit;
ExportTable := ImageRvaToVa(Header, ImagePointer, Header.OptionalHeader.DataDirectory[0].VirtualAddress,
nil);
if not Assigned(ExportTable)
then
exit;
NamesPointer := ImageRvaToVa(Header, ImagePointer, Cardinal(ExportTable.AddressOfNames),
nil);
if not Assigned(NamesPointer)
then
exit;
Names := ImageRvaToVa(Header, ImagePointer, Cardinal(NamesPointer^),
nil);
if not Assigned(Names)
then
exit;
NamesDataLeft := Header.OptionalHeader.DataDirectory[0].Size;
for i := 0
to ExportTable.NumberOfNames-1
do begin
NamesList.Add(
string(Names));
// Locate the next name
while (Names^<>chr(0))
and (NamesDataLeft>0)
do begin
inc(Names);
dec(NamesDataLeft);
end;
inc(Names);
end;
finally
UnmapViewOfFile(ImagePointer);
// Ignore error as there is not much we could do.
end;
finally
CloseHandle(ImageHandle);
end;
finally
CloseHandle(FileHandle);
end;
end;