Link to home
Start Free TrialLog in
Avatar of jon_rs
jon_rs

asked on

Using EnumWindows in 64-bit Delphi application

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

I am using EnumWindows to find out the Windows Handle of a process given its Process ID.  The code uses the LPARAM parameter in the call back routine to pass a pointer to a record.

The code I am using has worked fine for a 32-bit build.

It is failing when I compile and run the 64-bit build. The problem occurs because the pointer is not passed correctly, and so the de-reference causes an access violation.

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 65535
      ShowMessage('PEI = '+IntToStr(Param));

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

// the code fails at this next line in 64-bit build because PEI = 65535 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;

Open in new window


Any clues as to why the the call back routine has a different value passed to the Param parameter under 64-bit?

Thanks

Jon
Avatar of Sinisa Vuk
Sinisa Vuk
Flag of Croatia image

try to change lparam with Pointer:
function EnumWindowsProc(Wnd: HWND;  Param : Pointer): Bool; stdcall;
...

Open in new window

and
...
EnumWindows(@EnumWindowsProc, Pointer(@EI));

Open in new window

... alternatively ... go to this EE question and scroll down (find function FindExeProcess2) where I wrote function using wmi to find process ... similar ... using wmi you can find what you want.
Avatar of jon_rs
jon_rs

ASKER

Thanks for the response.

Changing Param to be a pointer makes no difference - the value the function receives when compiled for Win64 is still $FFFF

Your alternative WMI code snippet FindExeProcess2 returns the Process ID, not the Handle to the Main Window - which (in this instance) is what I actually want.  I want to be able to post Windows messages to the main window of Process N .. so need to know the Windows Handle of that process's Main Window.

And (while I am interested in a work-around if necessary) this doesn't answer my original question as to why the EnumWindowsProc is being passed $FFFF (65535) instead of correct address of the structure I am passing.
It works under Win32 compilation ... but not Win64.  I can't believe I am the only person in the world who uses this function, so I must be doing something wrong, and I'd like to understand what that is ...

Thanks

Jon
Avatar of jon_rs

ASKER

Some further information:

It transpires that the value I am expecting to be passed in the Param parameter, is in fact being passed in the Wnd parameter.

The Wnd value is NOT however swapped and sent in the Param parameter .. this is always set to $FFFF

It's almost as though the parameters being passed to the callback routine have slipped along one position ...
I run your code on windows 7/64 bit + XE3 ... and code works ok for both 32 bit and 64 bit app. Strange.
Maybe you can upload here small project .... Maybe I can see more ... (in project settings....)
Avatar of jon_rs

ASKER

Thanks for the offer :-)

I've built a standalone Test project with the core functionality embedded.


You should be able to recreate both a 32-bit and 64-bit version of the Test App from this.
However, I have also included MY compiled versions of the 32 and 64 bit EXEs which produce the following results on my machine...

User generated image
User generated image
One more bit of info which I didn't mention before ... I am running Windows 8.1 on a MAC within Parallels 9 ... wonder if this might explain what is going on ... be interesting to see if my compiled EXEs work OK on your machine ...

Jon
Yes, this is my intention. Post project here - so I can rebuild it.
Avatar of jon_rs

ASKER

Sorry ... attached link first time .. but looks like it didn't attach properly ...
Here it is again

Test.zip
ASKER CERTIFIED SOLUTION
Avatar of Sinisa Vuk
Sinisa Vuk
Flag of Croatia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jon_rs

ASKER

Thanks for your help.  It's great to nail the actual cause rather just find a work around :-)