Todd,

Nothing you stated addresses my initial question nor subsequent findings.
My question is simply how to retrieve the value that gets stored in the
CArray; nothing more.
My subsequent findings included the following as I believe I'm running into
it: https://github.com/rakudo/rakudo/issues/3633


Irrelevant musings:
--
A windows handle is a pointer.
A handle is an abstraction to a memory location that can be used in
subsequent api calls.
Declaring it as any incarnation of an int is a mistake and will not
function properly across all machines.

--
The windows api requires the PROCESSENTRY32 structure member dwSize to be
set to size of the structure.
There's nothing wrong with my instantiation.
Passing this structure to Process32First and Process32Next in the manner I
have done so works.

Furthermore you can't pass a naked $entry to like so:
Process32First($handle, $entry)
It has to be a pointer;  had you tried what you suggested, raku would have
thrown errors and for good reason.

--
My suggestion is to try it yourself.  Utilize the windows api in a manner
in which you'd expect it to run
properly and see what happens.  Retrieve the value in szExeFile.  If you'd
get it to work properly, show me
what version of raku you are using and supply it as it could be a bug in
the version I'm running.

~Paul

On Sun, Jan 3, 2021 at 5:37 AM ToddAndMargo via perl6-users <
perl6-us...@perl.org> wrote:

> On 1/2/21 11:38 PM, Paul Procacci wrote:
> > I don't have a C string that's terminated by null.
> > I have a CArray[int16] of length 260 that's passed to and filled in by
> > the windows api.
> >
> >
> https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
> > <
> https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
> >
> >
> https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32first
> > <
> https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32first
> >
> >
> https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32next
> > <
> https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32next
> >
> >
> > Take the following for example which I quickly whipped up that is
> > supposed to iterate over the processes running on the given windows
> machine:
> >
> > -------------------------------------------------------------
> >
> > use NativeCall;
> >
> > constant \MAX_PATH = 260;
> > constant \TH32CS_SNAPPROCESS = 0x00000002;
> >
> > class PROCESSENTRY32 is repr('CStruct') {
> >      has int32 $.dwSize;
> >      has int32 $.cntUsage;
> >      has int32 $.th32ProcessID;
> >      has int32 $.th32DefaultHeapID;
> >      has int32 $.th32ModuleID;
> >      has int32 $.cntThreads;
> >      has int32 $.th32ParentProcessID;
> >      has int32 $.pcPriClassBase;
> >      has int32 $.dwFlags is rw;
> >      HAS uint16 @.szExeFile[MAX_PATH] is CArray;
> > };
> >
> > sub CreateToolhelp32Snapshot(int32,int32 -->Pointer)is
> native('Kernel32') { * };
> > sub Process32First(Pointer,Pointer -->Bool)is native('Kernel32') { * };
> > sub Process32Next(Pointer,Pointer -->Bool)is native('Kernel32') { * };
> >
> > my $ptr = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
> > die 'Failed to retreive process list.' if $ptr == Bool::False;
> > my PROCESSENTRY32 $entry .= new(:dwSize(nativesizeof(PROCESSENTRY32)));
> > die 'Unable to iterate over process list' if Process32First($ptr,
> nativecast(Pointer, $entry))== Bool::False;
> >
> > repeat {
> >      say $entry.szExeFile[0].ord;
> >      say $entry.szExeFile[1].ord;
> > }while Process32Next($ptr, nativecast(Pointer, $entry));
> >
> > ------------------------------------------
> >
> > The output of the above is:
> > 48
> > 48
> >
> > This is clearly wrong.  This is either a) my misunderstanding of these
> api calls b) raku bug or c) a usage error on my part.
> >
> > ~Paul
>
> Hi Paul,
>
> Please bottom post.  It removes a lot of confusion.
>
> ~~~~~~~~~~~~~~~~~~~~~~
> CreateToolhelp32Snapshot:
>
>     C++
>
>     HANDLE CreateToolhelp32Snapshot(
>       DWORD dwFlags,
>       DWORD th32ProcessID
>     );
>
>
> The return is a "handle", not a pointer.
>
> You declare it as such:
>
>      sub CreateToolhelp32Snapshot(int32, int32 --> Pointer) is
> native('Kernel32') { * };
>
>      my $ptr = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
>
>
> I am not sure you are declaring that correctly.
>
> I would declare it:
>     sub CreateToolhelp32Snapshot(int32, int32 --> int32) is
> native('Kernel32') { * };
>
>     my $handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
>
>
> ~~~~~~~~~~~~~~~~~~~~~~
>
> Process32First:
>
>     C++
>
>     BOOL Process32First(
>       HANDLE           hSnapshot,
>       LPPROCESSENTRY32 lppe
>     );
>
> Returns a True or False for success/failure.
>
> You give it the "handle" you got from
> CreateToolhelp32Snapshot
>
> lppe is actually a C Pointer point to a c++
> structure called PROCESSENTRY32
>
>     C++
>
>     typedef struct tagPROCESSENTRY32 {
>       DWORD     dwSize;
>       DWORD     cntUsage;
>       DWORD     th32ProcessID;
>       ULONG_PTR th32DefaultHeapID;
>       DWORD     th32ModuleID;
>       DWORD     cntThreads;
>       DWORD     th32ParentProcessID;
>       LONG      pcPriClassBase;
>       DWORD     dwFlags;
>      CHAR      szExeFile[MAX_PATH];
>     } PROCESSENTRY32;
>
> You are duplicating this structure with
>
>     constant \MAX_PATH = 260;
>     constant \TH32CS_SNAPPROCESS = 0x00000002;
>
>     class PROCESSENTRY32 is repr('CStruct') {
>         has int32 $.dwSize;
>         has int32 $.cntUsage;
>         has int32 $.th32ProcessID;
>         has int32 $.th32DefaultHeapID;
>         has int32 $.th32ModuleID;
>         has int32 $.cntThreads;
>         has int32 $.th32ParentProcessID;
>         has int32 $.pcPriClassBase;
>         has int32 $.dwFlags is rw;
>         HAS uint16 @.szExeFile[MAX_PATH] is CArray;
>     };
>
> And calling it with:
>
>     my PROCESSENTRY32 $entry .= new(:dwSize(nativesizeof(PROCESSENTRY32)));
>
>     Process32First($ptr, nativecast(Pointer, $entry));
>
> I would tend to do it this way:
>
>     my $entry = PROCESSENTRY32,new();
>     sub  Process32First( int32, PROCESSENTRY32 is rw --> Bool );
>     my Bool $PassFail = Process32First( $handle, $entry)
>
>
> lppe, on the other hard is a pointer.  Adding "is rw" will
> read the structure it points to into your object.
>
>
> ~~~~~~~~~~~~~~~~~~~~~~
>
> Process32Next:
>
>     C++
>
>     BOOL Process32Next(
>       HANDLE           hSnapshot,
>       LPPROCESSENTRY32 lppe
>     );
>
>     sub  Process32Next( int32, PROCESSENTRY32 is rw --> Bool );
>
>      while Process32Next( handle, $entry )  {
>         say $entry.szExeFile[0].ord;
>         say $entry.szExeFile[1].ord;
>      }
>
> ~~~~~~~~~~~~~~~~~~~~~~
>
> By the way, the uint16 size is going to be a "little ending".
>
>      0xF5D3 comes out [0]=0xD3 and [1] 0xF4
>
> Native call will not convert it for you if you addess it as
> a CArray.
>
> I have a conversion for that too.
>
>
> HTH,
> -T
>
>
>

-- 
__________________

:(){ :|:& };:

Reply via email to