Using either Delphi 2007+ or Lazarus(Win64) I'm looking for a way to determine if a dll is compiled as x64 or x86?
views:
344answers:
2
+9
A:
You should read and parse PE header.
Like this:
function Isx64(const Strm: TStream): Boolean;
const
IMAGE_FILE_MACHINE_I386 = $014c; // Intel x86
IMAGE_FILE_MACHINE_IA64 = $0200; // Intel Itanium Processor Family (IPF)
IMAGE_FILE_MACHINE_AMD64 = $8664; // x64 (AMD64 or EM64T)
// You'll unlikely encounter the things below:
IMAGE_FILE_MACHINE_R3000_BE = $160; // MIPS big-endian
IMAGE_FILE_MACHINE_R3000 = $162; // MIPS little-endian, 0x160 big-endian
IMAGE_FILE_MACHINE_R4000 = $166; // MIPS little-endian
IMAGE_FILE_MACHINE_R10000 = $168; // MIPS little-endian
IMAGE_FILE_MACHINE_ALPHA = $184; // Alpha_AXP }
IMAGE_FILE_MACHINE_POWERPC = $1F0; // IBM PowerPC Little-Endian
var
Header: TImageDosHeader;
ImageNtHeaders: TImageNtHeaders;
begin
Strm.ReadBuffer(Header, SizeOf(Header));
if (Header.e_magic <> IMAGE_DOS_SIGNATURE) or
(Header._lfanew = 0) then
raise Exception.Create('Invalid executable');
Strm.Position := Header._lfanew;
Strm.ReadBuffer(ImageNtHeaders, SizeOf(ImageNtHeaders));
if ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE then
raise Exception.Create('Invalid executable');
Result := ImageNtHeaders.FileHeader.Machine <> IMAGE_FILE_MACHINE_I386;
end;
Alexander
2010-05-01 07:24:25
Thanks for the response.Unfortunately this would required JCL to work. I have not added JCL to my Delphi 2007 but may if it looks like the only expedient solution.
TheSteven
2010-05-04 06:55:48
What? This code doesn't use any JCL classes nor routines.
Alexander
2010-05-04 08:40:23
Your updated version works just fine in Delphi 2007 and Delphi 2010.An elegant solution - thank you.
TheSteven
2010-05-04 15:26:24
Note that these constants are in unit Windows on FPC. (at least in 2.4.0+ don't know about older ones)
Marco van de Voort
2010-05-21 14:05:28
+2
A:
You could use JclPeImage from the JCL. The following app shows how to do it.
program Isx64ImageTest;
{$APPTYPE CONSOLE}
uses
SysUtils, JclWin32, JclPEImage;
var
PEImage: TJclPeImage;
begin
PEImage := TJclPeImage.Create;
try
//usage is "Isx64ImageTest filename"
PEImage.FileName := ParamStr(1);
//print the machine value as string
WriteLn(Format('Machine value of image %s is %s',
[PEImage.FileName, PEImage.HeaderValues[JclPeHeader_Machine]]));
//check for a special machine value
case PEImage.LoadedImage.FileHeader^.FileHeader.Machine of
IMAGE_FILE_MACHINE_I386: begin end;
IMAGE_FILE_MACHINE_AMD64: begin end;
else
begin
end;
end;
finally
PEImage.Free;
end;
end.
Uwe Schuster
2010-05-01 15:37:32
If you're using JCL - there is more simpler approach - by using PeMapImgTarget function or PEImage.Target property (in your example). No need to analyze headers by yourself.
Alexander
2010-05-01 20:48:58
Not using JCL yet, may eventually do so.I've been trying to mirror my Delphi2007 and Delphi2010 components because I've been planning on migrating to Delphi2010. Is JCL available for Delphi2010?
TheSteven
2010-05-04 07:02:53