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;
> }
>
>
>

-- 
__________________

:(){ :|:& };:

Reply via email to