How can I tell if I'm running on x64?
Asked Answered
W

7

9

I just got a bug report for an issue that only occurs when the program is running "on a 64-bit machine." Now, Delphi doesn't produce 64-bit code, so theoretically that shouldn't matter, but apparently it does in this case. I think I have a workaround, but it will break things on 32-bit Windows, so I need some way to tell:

  1. If I'm running on a x64 or an x86 processor and
  2. If I'm running under a 64-bit version of Windows under Win32 emulation or native Win32 on a 32-bit OS.

Does anyone know how I can get those answers from within my app?

Wallford answered 17/9, 2009 at 0:39 Comment(0)
W
21

Mason, you can use IsWow64Process (WOW64 is the x86 emulator that allows 32-bit Windows-based applications to run seamlessly on 64-bit Windows)

Uses Windows;

type
  WinIsWow64 = function( Handle: THandle; var Iret: BOOL ): Windows.BOOL; stdcall;


function IAmIn64Bits: Boolean;
var
  HandleTo64BitsProcess: WinIsWow64;
  Iret                 : Windows.BOOL;
begin
  Result := False;
  HandleTo64BitsProcess := GetProcAddress(GetModuleHandle('kernel32.dll'), 'IsWow64Process');
  if Assigned(HandleTo64BitsProcess) then
  begin
    if not HandleTo64BitsProcess(GetCurrentProcess, Iret) then
    Raise Exception.Create('Invalid handle');
    Result := Iret;
  end;
end;

Bye.

Weixel answered 17/9, 2009 at 0:53 Comment(2)
Is this allowed by windows' UAC when running app has medium or low permissions?Selfregulating
I answer to my own comment: Yes! because kernel32.dll is part of every Delphi processSelfregulating
D
8

I see the your question 2 (are you running on Win64?) is already answered. Just keep in mind that for your code to be future-proof, you need to consider that in a (hypothetical) 64-bit Delphi app running on Win64, IsWow64Process would also return FALSE.

As regards your first question - are you on a 64-bit CPU -, you can check the hardware for the respective CPUID feature flag, like in the code below.


function Is64BitProcessor: boolean;
begin
  Result:=false;
  if CpuidAvailable = true then Result := Has64BitFeatureFlag;
end;

which uses the following two low-level functions:


function CPUIDavailable:boolean;
asm // if EFLAGS bit 21 can be modified then CPUID is available
    pushfd              //Save Flags
          pushfd        //Copy flags to EAX
          pop eax
          mov ecx,eax   //Make another copy in ECX
          btc eax,21    //Complement bit 21
          push eax      //Copy EAX to flags
          popfd
          pushfd        //Copy flags back to EAX
          pop eax
          cmp eax,ecx   //Compare "old" flags value with potentially modified "new" value
          setne al      //Set return value
    popfd               //Restore flags
end;

function Has64BitFeatureFlag: boolean; asm //IF CPUID.80000001h.EDX[bit29]=1 THEN it's a 64bit processor. //But we first need to check whether there's a function 80000001h. push ebx //Save EBX as CPUID will modify EBX push esi //Save ESI as we'll use ESI internally

xor eax,eax             //Setting EAX = input param for CPUID to 0
cpuid                   //Call CPUID.0
                        //Returns -> EAX = max "standard" EAX input value
mov esi, eax            //Saving MaxStdInput Value

mov eax,80000000h       //Setting EAX = input param for CPUID to $80000000
cpuid                   //Call CPUID.80000000h
                        //Returns -> EAX = max "extended" EAX input value
                        //If 80000000h call is unsupported (no 64-bit processor),
                        //cpuid should return the same as in call 0
cmp eax, esi
je @No64BitProcessor    //IF EAX{MaxExtInput} = ESI{MaxStdInput} THEN goto No64BitProcessor;

cmp eax, 80000001h
jb @No64BitProcessor    //IF EAX{MaxExtInput} < $80000001 THEN goto No64BitProcessor;

mov eax,80000001h       //Call $80000001 is supported, setting EAX:=$80000001
cpuid                   //Call CPUID.80000001h
                        //Checking "AMD long mode"/"Intel EM64T" feature bit (i.e., 64bit processor)
bt edx, 29              //by checking CPUID.80000001h.EDX[bit29]
setc al                 //IF Bit29=1 then AL{Result}:=1{true; it's a 64-bit processor}
jmp @Exit               //Exit {Note that Delphi may actually recode this as POP ESI; POP EBX; RET}

@No64BitProcessor: xor eax, eax //Result{AL/EAX}:=0{false; it's a 32-bit processor}; @Exit: pop esi //Restore ESI pop ebx //Restore EBX end;

EDIT1: A note on CPUIDavailable: This is of course assuming a >= 32-bit x86 processor (80386 or later), but Delphi Win32 code won't run on earlier machines anyway. The CPUID instruction was introduced with late 80486 processors.

Dryer answered 17/9, 2009 at 6:48 Comment(0)
A
3

You can check for the existence of and then call IsWow64Process. The linked MSDN page shows the required code.

Antimacassar answered 17/9, 2009 at 0:52 Comment(0)
P
2

The MSDN page says:

For compatibility with operating systems that do not support this function, call GetProcAddress to detect whether IsWow64Process is implemented in Kernel32.dll. If GetProcAddress succeeds, it is safe to call this function. Otherwise, WOW64 is not present. Note that this technique is not a reliable way to detect whether the operating system is a 64-bit version of Windows because the Kernel32.dll in current versions of 32-bit Windows also contains this function.

Which means: this is a new function and you have to be careful statically linking to it.

Propane answered 2/11, 2012 at 15:41 Comment(0)
N
0

Since Delphi can now compile Win64, I'd like to share my solution:

function WindowsBits: integer;

  function IsWow64: Boolean;
  {$IFDEF WIN64}
  begin
    // Native 64 Bit App means OS and CPU is 64 Bit, too.
    result := false;
  {$ELSE}
  type
    TIsWow64Process = function( // Type of IsWow64Process API fn
      Handle: Windows.THandle; var Res: Windows.BOOL
    ): Windows.BOOL; stdcall;
  var
    IsWow64Result: Windows.BOOL;      // Result from IsWow64Process
    IsWow64Process: TIsWow64Process;  // IsWow64Process fn reference
  begin
    // Try to load required function from kernel32
    IsWow64Process := Windows.GetProcAddress(
      Windows.GetModuleHandle('kernel32'), 'IsWow64Process'
    );
    if Assigned(IsWow64Process) then
    begin
      // Function is implemented: call it
      if not IsWow64Process(
        Windows.GetCurrentProcess, IsWow64Result
      ) then
        raise SysUtils.Exception.Create('IsWow64: bad process handle');
      // Return result of function
      Result := IsWow64Result;
    end
    else
      // Function not implemented: can't be running on Wow64
      Result := False;
  {$ENDIF}
  end;

begin
  {$IFDEF WIN64}
  result := 64;
  {$ELSE}
  if IsWow64 then
    result := 64
  else
    result := 32;
  {$ENDIF}
end;
Norse answered 30/1, 2023 at 0:9 Comment(0)
D
-1

At the beginning of the first function you need to add

if SizeOf(Pointer)=8 then
  Exit(True); // Current app is 64 bit
Dongdonga answered 17/2, 2020 at 9:13 Comment(1)
The question is about how to tell if the windows OS is 64-bit, not if the application is 64-bit.Goodall
I
-2

if sizeof(IntPtr) == 8 you're a 64-bit application on 64-bit Windows (edit: applies only to Delphi Prism)

else if IsWow64Process succeeds and returns true, you're a 32-bit application on 64-bit Windows

else you're on 32-bit Windows

Interrex answered 17/9, 2009 at 1:41 Comment(5)
First part isn't applicable, since Delphi doesn't compile 64-bit applications.Wallford
Doesn't Delphi Prism build .Net applications to IL? :-)Interrex
Yes, but Delphi and Delphi Prism are two different languages. When someone just says "Delphi", they usually mean the native version.Wallford
If we go to 128bit in the future you will detect it as x86 since it's not 8 bytes.Northwest
@Northwest you are technically correct, my answer will fail because it doesn't know how to deal with >64-bit OS. Then again, it'll fail in general to detect whether it's 128-bit app, or a 64-bit WOW app in 128-bit OS, or a 32-bit WOW app in 64-bit WOW emulator on 128-bit OS anyway. And I think you would be hard pressed to update my answer right now for detection of any app running on 128-bit OS, for the simple reason there's no correct way to detect something that does not exist yet.Interrex

© 2022 - 2024 — McMap. All rights reserved.