Hi Fernando,

I appreciate your response.
The windows api requires that the dwSize member of the structure gets set
to the size of the structure.
This is the reason why the object is being constructed as I've provided.

~Paul

On Sun, Jan 3, 2021 at 4:58 AM Fernando Santagata <nando.santag...@gmail.com>
wrote:

> 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