develooper Front page | perl.perl6.users | Postings from January 2020

Re: stolen uint's

Thread Previous | Thread Next
From:
ToddAndMargo via perl6-users
Date:
January 29, 2020 18:34
Subject:
Re: stolen uint's
Message ID:
2bf928b3-ac6f-b4ee-33ef-180c7818b633@zoho.com
On 2020-01-29 00:43, Tobias Boege wrote:
> On Tue, 28 Jan 2020, ToddAndMargo via perl6-users wrote:
>> This all came up when I tried to match
>>
>>        RegSetValueExW(
>>            _In_ HKEY hKey,
>>            _In_opt_ LPCWSTR lpValueName,
>>            _Reserved_ DWORD Reserved,
>>            _In_ DWORD dwType,
>>            _In_reads_bytes_opt_(cbData) CONST BYTE * lpData,
>>            _In_ DWORD cbData
>>
>> where CbData can either be a UTF little endian C string,
>> terminated by a nul or a four byte little endian
>> unsigned integer (no two's complement allowed) depending
>> on the value of lpValueName (REG_SZ, REG_DWORD, etc.)
>>
>> I wound up doing this:
>>
>> subset StrOrDword where Str | UInt;
>> sub WinRegSetValue( WinRegHives $Hive, Str $SubKey, Str $KeyName, ValueNames
>> $ValueType, StrOrDword $ValueData, Bool $Debug = False )
>>                      returns DWORD is export( :WinRegSetValue ) {
> 
> Are you really 100% sure that you interpreted this API correctly? I see how
> a DWORD cbData can be a four-byte unsigned integer: it gives the length of
> lpData in bytes, as documented [1].
> 
> But then a DWORD is 4 bytes long. Reusing these 4 bytes for an alternative
> interface where you may pass a UTF-whatever string that is at most 4 bytes
> encoded, including the NUL terminator... seems too insane. And there is no
> mention of that in the documentation page [1]. I do not think that cbData
> is ever used for anything but to indicate the length of the buffer lpData.
> It is lpData which can have a multitude of types (and serialization formats),
> the intended one to be taken from the dwType argument (not lpValueName).
> 
> My advice is still the same I gave in my very first reply to this thread:
> make your function a multi and write a candidate for each dwType. You have
> to write different code for serializing an integer vs. a string to pass as
> lpData anyway and the compiler can detect native types in multi dispatch
> for you:
> 
>    # REG_DWORD
>    multi WinRegSetValue(…, uint32 $data) {
>        use experimental :pack;
>        RegSetValueExW(…, REG_DWORD, pack("L", $data), 4)
>    }
> 
>    # REG_SZ
>    multi WinRegSetValue(…, Str $data) {
>        my $blob = "$data\0".encode
>        RegSetValueExW(…, REG_SZ, $blob, $blob.bytes)
>    }
> 
>    # REG_BINARY
>    multi WinRegSetValue(…, blob8 $data) {
>        RegSetValueExW(…, REG_BINARY, $data, $data.bytes)
>    }
> 
> Regards,
> Tobias
> 
> [1] https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexw
> 



Hi Tobias,

I don't have to get so complicated.  Code looks sweet
though.  I will probably write it down for use
on other things. Thank you!

Oh yes.  I can pass it strings and DWORD with ease.

I check the value of lpValueName and then proceed.

lpData is basically an array of bytes.  I set the
bytes up based on lpValueName.  And you have to
tell cbData how many bytes are legitimate
in lpData.

It they pass me a string for REG_DWORD or a UInt for
a REG_SZ, I wag the finger wagged at them big time.
For example:

    if $ValueData.^name  ne "Int"  || $ValueData < 0  {   # UInt gets 
"boxed" to an Int
       $ErrStr = "ERROR: $SubName\n\n" ~
                 "   ValueData must be an Unsigned Integer when used 
with $ValueType\n\n" ~
                 "   Cowardly exiting\n\n";
       say $ErrStr;
       WinMsg( "ValueData Error", $ErrStr );
       exit;
    }

Hmmmmm... I forgot the "Bummer Dude!"

Would you like to see the actual code?  I am not
posting it here as it is several hundred lines long
and then I'd get the finger wagged at me.  Every
thing is spread across several modules.

-T

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About