From Raku/Perl6, how to read this registry key?

5

Windows

With Raku/Perl6, how do I use NativeCall to read the value of

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ "EnableLUA"]

with RegQueryValueExW?

https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw

Many thanks,

-T

edit 12-27-2019 #1: removing bad code and inserting new code

This is how far I have gotten.

Test run string: K:\Windows\NtUtil>perl6 -I. -e "use WinMount :GetLUA; say GetLUA();" RegOpenKeyExW RegOpenKeyExW RtnCode 0

RegQueryValueExW
1
2
RegQueryValueExW   RtnCode 87  (87 = ERROR_INVALID_PARAMETER)
lpData pointer 0
lpcbData data length 0

RegCloseKey
RegCloseKey   RtnCode 0

True

WinMount.pm6

# unit module WinMount;
# WinMount.pm6#`{

   Utilities to mount and dismound drive partitions
   Note: LUA must be unset (0x00000000) for mount to function prpoperly 

   raku -I. -c WinMount.pm6

}

use NativeCall;
use WinPopUps :WinMsg;


# Reference to types and values: http://dsource.org/projects/tango/ticket/820

constant BYTE    := uint8;
constant WCHAR   := uint16;   
constant DWORD   := int32;    
constant REGSAM  := int32;
constant WCHARS  := CArray[WCHAR];
constant BYTES   := CArray[BYTE];

constant HKEY_CURRENT_USER  = 0x80000001;
constant HKEY_LOCAL_MACHINE = 0x80000002;
constant KEY_QUERY_VALUE   = 1;
constant ERROR_SUCCESS     = 0; # Yeah, I know. The Win-Api uses 0 for success and other values to indicate errors
constant REG_SZ = 1;

constant KEY_READ      = 0x20019;
constant KEY_SET_VALUE = 0x0002;
constant REG_DWORD     = 0x00000004;



sub to-c-str( Str $str ) returns CArray[WCHAR]  is export( :to-c-str ) {
   my @str := CArray[WCHAR].new;
   for ( $str.comb ).kv -> $i, $char { @str[$i] = $char.ord; }
   @str[ $str.chars ] = 0;
   @str;
}


sub wstr( Str $str ) returns WCHARS  is export( :wstr ) {
    CArray[WCHAR].new( $str.comb.map: *.ord )
}


sub GetLUA() is export( :GetLUA ) {

#`{

Returns the LUA value in the registry to True (0x00000001) or False (0x00000000)

          [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
          "EnableLUA"=dword:00000000

    https://docs.perl6.org/language/nativecall

    Win32 return codes:
    https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-

}

   my Str $SubName = &?ROUTINE.name;
   my Str $OS      = $*KERNEL.name;
   if not $OS eq "win32" { say "Sorry, $SubName only work in Windows."; exit; }

   my Bool  $LUA = True;
   my       $RtnCode;

   my Str   $SubKey = Q[SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\];
   my Str   $Key = Q[EnableLUA];

   my       $lpSubKey    = wstr( $SubKey );
   my       $lpValueName = wstr( $Key );
   # my $lpSubKey    = CArray[uint8].new($Key.encode.list);
   # my $lpValueName = CArray[uint8].new($SubKey.encode.list);


   my int32 $Handle;
   my int32 $ulOptions = 0;
   my int32 $lpData;
   my int32 $lpcbData;
   my int32 $lpReserved = 1;


#`{
    Open the key:
    https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexw
    https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-key-security-and-access-rights
    C++
    LSTATUS RegOpenKeyExW(
       HKEY    hKey,          # Hive name (HKEY_LOCAL_MACHINE)
       LPCWSTR lpSubKey,      # path to the key(/SOFTWARE/Microsoft/Windows/CurrentVersion/Policies/System/EnableLUA)
       DWORD   ulOptions,     # 0
       REGSAM  samDesired,    # KEY_READ (0x20019), KEY_SET_VALUE (0x0002)
       PHKEY   phkResult      # A pointer to a variable that receives a handle to the opened key
    );
}    
   say "RegOpenKeyExW";
   sub RegOpenKeyExW( DWORD, WCHARS, DWORD, DWORD, DWORD is rw) is native("Kernel32.dll") returns DWORD { * };
   $RtnCode = RegOpenKeyExW( HKEY_LOCAL_MACHINE, $lpSubKey, $ulOptions, KEY_READ, $Handle );
   say "RegOpenKeyExW   RtnCode $RtnCode\n";



#`{
    Read the key:
    use RegQueryValueExW if you know key and value name
    https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw
    C++
    LSTATUS RegQueryValueExW(
       HKEY    hKey,          # Hive name (HKEY_LOCAL_MACHINE)
       LPCWSTR lpValueName,   # path to the key(\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA)
       LPDWORD lpReserved,    # give it "int32" without the quotes to give it a NULL
       LPDWORD lpType,        # Registry Value Type (REG_DWORD which is 32 bit)
       LPBYTE  lpData,        # Pointer to the return value
       LPDWORD lpcbData       # number of bytes in the return value
    );
}    
   say "RegQueryValueExW";
   sub RegQueryValueExW( DWORD, WCHARS, DWORD, DWORD, DWORD is rw, DWORD is rw ) is native("Kernel32.dll") returns DWORD { * };
say "1";   
   $RtnCode = RegQueryValueExW( $Handle, $lpValueName, $lpReserved, REG_DWORD, $lpData, $lpcbData );
say "2";   
   say "RegQueryValueExW   RtnCode $RtnCode  (87 = ERROR_INVALID_PARAMETER)\nlpData pointer $lpData\nlpcbData data length $lpcbData\n";



#`{
    Close the key 
    https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
    C++
    LSTATUS RegCloseKey(
       HKEY hKey    # handle to the open key to be closed.  See RegOpenKeyExW phkResult
    );
}   
   say "RegCloseKey";
   sub RegCloseKey( DWORD ) is native("Kernel32.dll") returns DWORD { * };
   $RtnCode = RegCloseKey( $Handle );
   say "RegCloseKey   RtnCode $RtnCode\n";


   return $LUA;
}
winapi
raku
asked on Stack Overflow Dec 25, 2019 by Todd • edited Jan 6, 2020 by Elizabeth Mattijsen

1 Answer

3

Here's what I have so far. I am able to successfully retrieve the handle for the registry key, but when I try to read the key it throws "Native call expected argument that references a native integer, but got P6int". And I don't know why yet. But I figured I post this already, maybe someone else can shed some light.

use NativeCall;

constant BYTE    := uint8;
constant WCHAR   := uint16;   
constant DWORD   := int32;    
constant REGSAM  := int32;
constant WCHARS  := CArray[WCHAR];
constant BYTES   := CArray[BYTE];

constant HKEY_CURRENT_USER  = 0x80000001;
constant HKEY_LOCAL_MACHINE = 0x80000002;
constant KEY_QUERY_VALUE   = 1;
constant ERROR_SUCCESS     = 0; # Yeah, I know. The Win-Api uses 0 for success and other values to indicate errors
constant REG_SZ = 1;

sub RegOpenKeyExW( DWORD, WCHARS, DWORD, REGSAM, DWORD is rw) is native("Kernel32.dll") returns DWORD { * };

#DWORD RegOpenKeyExW(
#  HKEY    hKey,
#  LPCWSTR lpSubKey,
#  DWORD   ulOptions,
#  REGSAM  samDesired,
#  PHKEY   phkResult
#);

sub RegQueryValueExW( DWORD, WCHARS, DWORD is rw, DWORD is rw, BYTE is rw, DWORD is rw) is native("Kernel32.dll") returns DWORD { * };

#DWORD RegQueryValueExW(
#  HKEY    hKey,
#  LPCWSTR lpValueName,
#  LPDWORD lpReserved,
#  LPDWORD lpType,
#  LPBYTE  lpData,
#  LPDWORD lpcbData
#);


my $key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System';

my DWORD $hkey;
my $length = 1024;

if RegOpenKeyExW(HKEY_LOCAL_MACHINE, wstr($key), 0, KEY_QUERY_VALUE, $hkey) == ERROR_SUCCESS
{
    say "Got handle: $hkey";

    my BYTES $buffer = CArray[BYTE].new( 0 xx 1024 );

    # throws "Native call expected argument that references a native integer, but got P6int"
    if RegQueryValueExW( $hkey, WCHARS, DWORD, REG_SZ, $buffer, $length ) == ERROR_SUCCESS
    {
        say "Got data of length $length";
        say gather for 0 .. $length { take $buffer[$_] };
    }
}


sub wstr( Str $str ) returns WCHARS {
    CArray[WCHAR].new( $str.comb.map: *.ord )
}
answered on Stack Overflow Dec 26, 2019 by Holli • edited Dec 26, 2019 by Holli

User contributions licensed under CC BY-SA 3.0