* * *

Author Topic: [64bit] Yet another problem, with TlHelp32  (Read 15945 times)

Hiam87

  • New member
  • *
  • Posts: 7
[64bit] Yet another problem, with TlHelp32
« on: July 11, 2009, 07:20:34 pm »
I'm really trying to get into using x64, but whatever i do, it does not seem to work.

What im trying todo this time is:

Code: [Select]
function GetProcessID(ProcessName : string ) : DWORD ;
var
  Handle:tHandle;
  Process:tProcessEntry32A;
  GotProcess:Boolean;
begin
  Handle:=CreateToolHelp32SnapShot(TH32CS_SNAPALL,0);
  Showmessage(IntToHex(Handle,8));
  Process.dwSize:=SizeOf(Process);
  Showmessage(IntToHex(Process.dwSize,8));
  GotProcess := Process32First(Handle,Process);
  if GotProcess and (Process.szExeFile<>ProcessName) then
      repeat
      Showmessage(Process.szExeFile);
        GotProcess := Process32Next(Handle,Process);
      until (not GotProcess) or (Process.szExeFile=ProcessName);
  if GotProcess then Result := Process.th32ProcessID
    else Result := 0;
        CloseHandle(Handle);
end;

And i've exported the TlHelp32 class from Delphi to Lazarus.
I also tried to directly import the dll functions without any luck.

Is the problem that itself that its being compiled under x64 or is it something else? Since the code works under 32bit.
As it is now, it does not seem to enumrate though the processes at all.

Kind regards Hiam.

Marc

  • Administrator
  • Hero Member
  • *
  • Posts: 2484
Re: [64bit] Yet another problem, with TlHelp32
« Reply #1 on: July 12, 2009, 09:54:05 pm »
First, for efficiency, it looks better to me to use TH32CS_SNAPPROCESS instead of TH32CS_SNAPALL (since you only need a process list)

What worries me is the 32 in all function and structure names, but I don't see exceptions for 64bit in the MSDN. (maybe snapall limits it)

So what doesn't work ? Did you step through the code ? Do you get a valid handle ? Does Process32First return something ? Does it loop, and what values are returned ?
//--
{$I stdsig.inc}
//-I still can't read someones mind
//-Bugs reported here will be forgotten. Use the bug tracker

Hiam87

  • New member
  • *
  • Posts: 7
Re: [64bit] Yet another problem, with TlHelp32
« Reply #2 on: July 12, 2009, 11:34:21 pm »
Code: [Select]
 Handle:=CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS,0);
  Showmessage(IntToHex(Handle,8));
  Process.dwSize:=SizeOf(Process);
  Showmessage(IntToHex(Process.dwSize,8));
  GotProcess := Process32First(Handle,Process);   <- Fails here.
return is false. Last error code is ERROR_BAD_LENGTH.

Quote
The CreateToolhelp32Snapshot function can fail with an error code of ERROR_BAD_LENGTH for a variety of reasons. For example, this error can occur if the loader data table in the target process is corrupted or not initialized, or if an internal synchronization error has occurred between the calling process and the target process. Ensure that the target process was not started suspended, and try calling the function again.

Not really sure why, but maybe the struct for the tProcessEntry32A maybe diffrent.
*EDIT* That does not seem to be the case. That error normally raises when you forget to tet the dwSize, but i've done that.

*EDIT* again, found the error. Embarcadero's TLHelp32 declares
th32DefaultHeapID: DWORD;
where as it should be: th32DefaultHeapID: ULONG_PTR;

the fpc interprets it then not to be a pointer but a number. Which case, when declaring your TProcessEntry32, make sure it's a ULONG_PTR

Kind regards Hiam.
« Last Edit: July 13, 2009, 02:36:14 pm by Hiam87 »

Marc

  • Administrator
  • Hero Member
  • *
  • Posts: 2484
Re: [64bit] Yet another problem, with TlHelp32
« Reply #3 on: July 13, 2009, 01:10:07 am »
Not really sure why, but maybe the struct for the tProcessEntry32A maybe diffrent.
*EDIT* That does not seem to be the case. That error normally raises when you forget to tet the dwSize, but i've done that.
Do you mean that you get the error too if you don't set the size ?
Then It could be the definition of the record which is wrong.

Quote
*EDIT* again, found the error. Embarcadero's TLHelp32 declares
th32DefaultHeapID: DWORD;
where as it should be: th32DefaultHeapID: ULONG_PTR;
for 32bit thats ok. for 64 bit I think not.

Quote
the fpc interprets it then not to be a pounter but a number. Which case, when declaring your TProcessEntry32, make sure it's a ULONG_PTR
?????
What do you mean here. How is it defined in fpc ?

//--
{$I stdsig.inc}
//-I still can't read someones mind
//-Bugs reported here will be forgotten. Use the bug tracker

Hiam87

  • New member
  • *
  • Posts: 7
Re: [64bit] Yet another problem, with TlHelp32
« Reply #4 on: July 13, 2009, 02:39:10 pm »
Sorry i guess i explained that kind of weird. Anyhow, what i ment is that with a dword, the length won't match (32bit) with what the heap needs.
It needs a 64bits under x64 kind of obvious, or am i wrong?

Paul Ishenin

  • Administrator
  • Sr. Member
  • *
  • Posts: 274
Re: [64bit] Yet another problem, with TlHelp32
« Reply #5 on: July 13, 2009, 03:09:35 pm »
No, not wrong. Use PtrUInt type for ULONG_PTR field.

Hiam87

  • New member
  • *
  • Posts: 7
Re: [64bit] Yet another problem, with TlHelp32
« Reply #6 on: July 13, 2009, 03:50:55 pm »
ULONG_PTR works, is there any diffrence?

Hiam87

  • New member
  • *
  • Posts: 7
Re: [64bit] Yet another problem, with TlHelp32
« Reply #7 on: July 13, 2009, 07:41:19 pm »
Are none of the API's adapted for x64? Seems like that's the case.
I don't want to come keep running here with questions, but this far i've almost always ran into problems with the Windows API's under x64.
I du understand FPC's main purpose is not to concentrate on x64, but it's abit annoying trying to lure out the problem each time i want to use a new API =/

Vincent Snijders

  • Administrator
  • Hero Member
  • *
  • Posts: 2660
    • My Lazarus wiki user page
Re: [64bit] Yet another problem, with TlHelp32
« Reply #8 on: July 13, 2009, 09:18:41 pm »
Somebody has to be the first to fix these obscure apis for win64.

Marc

  • Administrator
  • Hero Member
  • *
  • Posts: 2484
Re: [64bit] Yet another problem, with TlHelp32
« Reply #9 on: July 14, 2009, 10:26:59 am »
ULONG_PTR works, is there any diffrence?
Beweeen PtrUInt and ULONG_PTR ? No they are the same. We (fpc) made this type to have an unsigned value with the size of a pointer.
//--
{$I stdsig.inc}
//-I still can't read someones mind
//-Bugs reported here will be forgotten. Use the bug tracker

delphian

  • New member
  • *
  • Posts: 39
Re: [64bit] Yet another problem, with TlHelp32
« Reply #10 on: April 28, 2010, 02:21:04 pm »
The Cause for this bug is the dwFlags of TProcessEntry32 in jwaTLHelp32 - its defined as a DWORD , it should be a ULONG_PTR.  the Process32First and Process32Next Functions are expecting 304 bytes not 300.

mantis Bug id - 16361


skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1821
Re: [64bit] Yet another problem, with TlHelp32
« Reply #11 on: April 28, 2010, 07:11:54 pm »
delphian, I've my own test, please see comments at : http://bugs.freepascal.org/view.php?id=16361

could you also run the test on win32?

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 5644
Re: [64bit] Yet another problem, with TlHelp32
« Reply #12 on: April 29, 2010, 07:55:08 am »
The Cause for this bug is the dwFlags of TProcessEntry32 in jwaTLHelp32 - its defined as a DWORD , it should be a ULONG_PTR.  the Process32First and Process32Next Functions are expecting 304 bytes not 300.

mantis Bug id - 16361

typedef struct tagPROCESSENTRY32
{
    DWORD   dwSize;
    DWORD   cntUsage;
    DWORD   th32ProcessID;          // this process
    ULONG_PTR th32DefaultHeapID;
    DWORD   th32ModuleID;           // associated exe
    DWORD   cntThreads;
    DWORD   th32ParentProcessID;    // this process's parent process
    LONG    pcPriClassBase;         // Base priority of process's threads
    DWORD   dwFlags;
    CHAR    szExeFile[MAX_PATH];    // Path
} PROCESSENTRY32;

So it is mostly likely a packing issue. But jwa* units are externally maintained, I'll see if I can contact upstream.

Eugene Loza

  • Sr. Member
  • ****
  • Posts: 450
    • My "almost daily" development blog
Re: [64bit] Yet another problem, with TlHelp32
« Reply #13 on: July 25, 2016, 11:20:31 am »
Well... time for necro-posting :)
Last week I was struggling with TlHelp32 (replaced by JwaTlHelp32, jwawinbase, jwawinnt) to reanimate an ancient Delphi project written not by me (CHRUnLoad was an utility/hack to fake import characters to Wizardry 8 game). I've ran into exact problem described in this topic.
sizeof(PROCESSENTRY32) gave me 296 bytes and #24 error (ERROR_BAD_LENGTH)
I've made a stupid fix to increase PROCESSENTRY32 size by adding tmp1,tmp2,tmp3,tmp4,tmp5:DWORD; to it (i.e.additional 20 bytes)
Actually I've just added the "tmp" variables until I got sizeof(PROCESSENTRY32)=316 which gave error #18 (ERROR_NO_MORE_FILES) which looks ok
Eventually the program works as expected and provides all necessary data.

The complete PROCESSENTRY32 in my case is:
Code: Pascal  [Select]
  1. type PROCESSENTRY32 = record
  2.     dwSize: DWORD;
  3.     cntUsage: DWORD;
  4.     th32ProcessID: DWORD;          // this process
  5.     th32DefaultHeapID: ULONG_PTR;
  6.     th32ModuleID: DWORD;           // associated exe
  7.     cntThreads: DWORD;
  8.     th32ParentProcessID: DWORD;    // this process's parent process
  9.     pcPriClassBase: LONG;          // Base priority of process's threads
  10.     dwFlags: DWORD;
  11.     szExeFile: array [0..MAX_PATH-1] of Char;    // Path
  12.  
  13.     tmp1,tmp2,tmp3,tmp4,tmp5:DWORD;      //WHAT THE HELL IS THAT????? 20 bytes missing????
  14.   end;
 
instead of the same record in "JwaTlHelp32.pas,v 1.11 2007/09/05 11:58:52 dezipaitor" found in Lazarus 1.6 / FPC 3.0.0

Code: Pascal  [Select]
  1. type  tagPROCESSENTRY32 = record
  2.     dwSize: DWORD;
  3.     cntUsage: DWORD;
  4.     th32ProcessID: DWORD;          // this process
  5.     th32DefaultHeapID: ULONG_PTR;
  6.     th32ModuleID: DWORD;           // associated exe
  7.     cntThreads: DWORD;
  8.     th32ParentProcessID: DWORD;    // this process's parent process
  9.     pcPriClassBase: LONG;          // Base priority of process's threads
  10.     dwFlags: DWORD;
  11.     szExeFile: array [0..MAX_PATH - 1] of Char;    // Path
  12.   end;
 
Moreover I had to copy-paste all the relevant structures and procedures into my code, because for some reason JwaTlHelp32 ignored any changes I've made and always gave up sizeof(tagPROCESSENTRY32)=296 no matter what I've changed. But I might have been doing something wrong, e.g. I don't remember if I added any sort of additional variables to the record. P.S. Increasing the length of "szExeFile: array [0..MAX_PATH-1] of Char;" array works only once? E.g. I get 296->300 bytes size if I write "array [0..MAX_PATH-0] of Char" but if I write "array [0..MAX_PATH+3] of Char" the size of the whole record still remains 300 bytes.

The function giving the error #24 is

Code: Pascal  [Select]
  1. interface
  2. function Process32First(hSnapshot: HANDLE; var lppe: PROCESSENTRY32): BOOL; stdcall;//always ANSI!
  3. ...
  4. implementation
  5. function Process32First; external 'kernel32.dll' name 'Process32First'; //ANSI

Relevant to Win7x64
Seems like Kernel32.dll version is 6.1.7601.17514 (818kb) modified 21.11.2010 5:24

I'm using {$MODE Delphi} as it was a project imported from Delphi source.

P.S. The problem looks solved for my task by that stupid hack I've made, so it's rather a note than any request for help. Moreover, I don't really think anyone would use anything like that now except for reviving ancient software. So there is absolutely nothing urgent in the problem. But having JwaTlHelp32 running smoothly is a good idea.

(UPD) Looks like dwSize = sizeof(PROCESSENTRY32); must be set before sending lppe to kernel32.
« Last Edit: July 25, 2016, 11:35:17 am by Eugene Loza »
My Free and Open Source games in Lazarus/FreePascal/CastleGameEngine:
https://decoherence.itch.io/
(and some ancient games in Turbo Pascal too)
Sources are here: https://github.com/eugeneloza?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 4439
Re: [64bit] Yet another problem, with TlHelp32
« Reply #14 on: July 25, 2016, 01:05:05 pm »
If you use records for Windows API calls always declare packed records..... Simple as that. The windows API has no knowledge about the internal alignment of the FPC record. So use packed.
If there is no packed in the sources, then that is a bug.
"Logically, no number of positive outcomes at the level of experimental testing can confirm a scientific theory, but a single counterexample is logically decisive."

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus