EnumWindows behaves strangely in 64-bit Delphi

I am working in Delphi XE3 on a Windows 8 64-bit machine, building 32-bit and 64-bit applications.

I am using EnumWindows to find out the Windows handle of the main window of a process with its process ID. The code uses the LPARAM parameter in the callback procedure to pass a pointer to the entry.

The code I am using is fine for 32 bit build.

Unable to compile and run 64-bit assembly. The problem occurs because the LPARAM value is passed in the Wnd parameter. The parameter value is always set to $ FFFF ... in other words, I don't get the HWND value at all ... so it's not like through the parameters, just swapping.

type
  PEnumInfo = ^TEnumInfo;
  TEnumInfo = record
    ProcessID : DWORD;
    HWND      : THandle;
  end;

function EnumWindowsProc(Wnd: HWND;  Param : LPARAM): Bool; stdcall;
    var
      PID : DWORD;
      PEI : PEnumInfo;
    begin
// in 32-bit Param matches the address of the param that is passed
// in 64-bit Param is set to $FFFF - however Wnd = the expected address
      ShowMessage('PEI = '+IntToStr(Param));

      PEI := PEnumInfo(Param);
      GetWindowThreadProcessID(Wnd, @PID);

// the code fails at this next line in 64-bit build because PEI = $FFFF rather than the actual pointer passed
      Result := (PID <> PEI^.ProcessID) or
              (not IsWindowVisible(WND)) or
              (not IsWindowEnabled(WND));

      if not Result then PEI^.HWND := WND; //break on return FALSE
    end;


    function FindMainWindow(PID: DWORD): DWORD;
    var
      EI : TEnumInfo;
    begin
      EI.ProcessID := PID;
      EI.HWND := 0;
      ShowMessage('PEI = '+IntToStr(LPARAM(@EI)));
      EnumWindows(@EnumWindowsProc, LPARAM(@EI));
      Result := EI.HWND;
    end;

      

Is Win64 calling convention different? Or am I making some other fundamental mistake?

Any help or ideas are greatly appreciated.

+3


source to share


1 answer


The code in your question works great. Your ad is EnumWindowsProc

correct. The parameters and return value are of the correct type. The calling rule is correct, although it really doesn't matter on x64 Windows which only has one calling convention.

If you build a simple application using the code from your question, you will find that it behaves correctly and lists windows correctly.

The problem is your actual code is different from the code you provided. I am assuming that in your actual code EnumWindowsProc

is a nested function: Why can't I get the address for a nested local function in 64 bit Delphi? But that's just Guess. I don't know what your real code looks like. I know the code in the question is working correctly.



Another comment is that you are mistakenly declaring a member as a HWND

type THandle

. This will not affect the correctness of your program, but it is semantically incorrect. I would say something like this:

type
  TEnumInfo = record
    PID: DWORD;
    Wnd: HWND;
  end;

      

+6


source







All Articles