Hi Paul,
I can't help, since I haven't a Windows PC, but I noticed that you
initialize your $entry variable like this:

my PROCESSENTRY32 $entry .= new(:dwSize(nativesizeof(PROCESSENTRY32)));

I don't think the argument to the "new" call is necessary. Try this:

my PROCESSENTRY32 $entry .= new;
say nativesizeof($entry);  # output: 556

Raku already knows the native size of the CStruct class.
Other than that I can't say anything useful.

On Sun, Jan 3, 2021 at 8:38 AM Paul Procacci <pproca...@gmail.com> 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-process32first
>
> 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
>
>
> On Sun, Jan 3, 2021 at 2:12 AM ToddAndMargo via perl6-users <
> perl6-us...@perl.org> wrote:
>
>> On 1/2/21 8:13 PM, Paul Procacci wrote:
>> > What I'm trying to attempt to do now is display the contents of that
>> > CArray (raku member a).  In my mind, this is an "array of utf16LE byte
>> > sequences terminated by 0".
>>
>> Hi Paul,
>>
>> If I understand your problem, you are having trouble
>> extracting something usable from Windows return UTF16
>> string.
>>
>> I have a series of modules I wrote to read and write
>> to the Windows registry.  The strings I got back were
>> all "UTF16 little ending C Strings".
>>
>> This means that every character is a TWO byte word
>> (16 bits) with the first byte containing the low
>> value byte.  And they terminate with both bytes
>> being a numerical zero.  It is a little weird to get
>> use to.
>>
>> There was some interesting conversation in these
>> parts a bit ago as to if a C string could ever
>> not be terminated with a nul.  They are always
>> terminated with a nul.
>>
>> The following is from one of the modules I wrote to
>> support this.  I used brute force, rather than
>> rely on UTF conversion utilities as I found them
>> unreliable.
>>
>> If you un-comment
>>     # print $CStr[ $i ] ~ "," ~ $CStr[ $i + 1 ] ~ ",  ";
>> you can watch the sub do its thing.
>>
>> I have a sub to go the other way too, if you want it.
>>
>> HTH,
>> -T
>>
>>
>>
>> use NativeCall;
>>
>> sub c-to-raku-str( BYTES $CStr ) returns Str  is export( :c-to-raku-str )
>> {
>>     # Note: C Strings are always terminated with a nul.  This sub will
>> malfunction without it.
>>     # Note: presumes a UTF16 little endian C String and converts to UTF8
>>
>>     my Str    $SubName   = &?ROUTINE.name;
>>     my Str    $RakuStr   = "";
>>     my Str    $Msg       = "";
>>     my uint32 $CStrElems = $CStr.elems;
>>     # say $CStrElems;
>>
>>     loop (my $i = 0; $i < $CStrElems - 2 ; $i += 2) {
>>        if  $CStr[ $i ] == 0  &&  $CStr[ $i + 1 ] == 0  { last; }
>>
>>        if $i == $CStrElems - 4  {
>>           $Msg = "$SubName ERROR:" ~ " C Strings are required to be
>> terminated with a nul\n\n" ~
>>                  "                     Returning an empty string\n" ~
>>                  "                     Cowardly existing\n";
>>           exit;
>>        }
>>
>>        # print $CStr[ $i ] ~ "," ~ $CStr[ $i + 1 ] ~ ",  ";
>>        $RakuStr ~= chr( $CStr[ $i ] );
>>     }
>>     # say "";
>>
>>     # say "$RakuStr";
>>     return $RakuStr;
>> }
>>
>>
>>
>
> --
> __________________
>
> :(){ :|:& };:
>


-- 
Fernando Santagata

Reply via email to