Solved

Query if a file is compiled as 32 or 64 bit

Posted on 2013-06-15
4
476 Views
Last Modified: 2013-06-19
Hi Experts.

Here I got a example on how to query header in file path, but its of type TStream.
So I ask you experts is there any way to detect if a file is compiled as 32 or 64 bit file?
And the routine must be able to take FileName path as parameter and return boolean if its a 64 bit file, and false if its a 32 bit file.

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;
0
Comment
Question by:DelphiEmil
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 

Author Comment

by:DelphiEmil
ID: 39251600
Any Delphi expert here?
0
 
LVL 22

Accepted Solution

by:
Ferruccio Accalai earned 500 total points
ID: 39252682
You can use your function this way

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;

procedure TForm1.Button1Click(Sender: TObject);
var
  Stream: TStream;
  OpenDialog: TOpenDialog;
  i: Integer;
begin
  OpenDialog := TOpenDialog.Create(nil);
  with OpenDialog do
    try
      Filter := 'Executable files|*.exe';
      if execute then
      begin
        Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
        try
          if Isx64(Stream) then
            i := 64
          else
            i := 32;
          showmessage(Format('%s was compiled as %d bit', [OpenDialog.FileName, i]));
        finally
          Stream.Free;
        end;
      end;
    finally
      OpenDialog.Free;
    end;
end;

Open in new window

0
 
LVL 32

Expert Comment

by:Ephraim Wangoya
ID: 39258550
You could simply write a second overloaded function

function Isx64(const Strm: TStream): Boolean; overload;
function Isx64(const AFileName: string): Boolean; overload;

implementation

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;

function Isx64(const AFileName: string): Boolean; overload;
var
  Stream: TFileStream;
begin
  if not FileExists(AFileName) then
    raise Exception.Create('Invalid file');
  Stream := TFileStream.Create(AFileName, fmOpenRead);
  try
    Result := Isx64(Stream);
  finally
    Stream.Free;
  end;
end;

Open in new window

0
 

Author Closing Comment

by:DelphiEmil
ID: 39258949
Yes it works very good.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question