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 > > > -- __________________ :(){ :|:& };: