Todd!

Of what use are these module printouts?

For someone who complains immediately if you are disrespected by having your grammar corrected, you are remarkably disrespectful to everyone else.

The work you have done getting these modules to work on Windows is great. Given the dominance of Windows in computing, your modules will almost certainly be useful to someone.

But you send them to an email list. Only those who regularly read the list will see them. Someone coming later will not.

Where do regular Raku programmers (not just 'developers') put modules? Into the ecosystem, so that everyone! can search for a module they need, and can then simply install it with zef.

Second, your plain text versions of modules have no tests, there is no dependency list, there is no one to go to if the module does not work, eg. because Microsoft changed something at random, as they do.

If you expect someone else to do that work, think again. Most people on this list probably have more projects in their TODO list than you do, and it seems to me that the majority of them have moved away from an OS that you yourself have described pejoratively.

There are many reasons for creating the modules as described in the documentation and placing them in the ecosystem.

If you don't like doing this, that's OK, but it's a shame that the results of your time and energy can't be used by others.

Flooding this email list with plain text programs is just blatantly saying "I don't care about your conventions, I'll do this my way". And that is disrespectful of the community.

Todd, you ask many many questions on this list, questions about things that provide value to you and for which you say you get paid for. You receive free help in a patient and friendly manner, even when you are contemptuous of the people who help you. The very least you could do is to abide by the norms that this community has set up.

If you have modules you want to share, share them in a way that people can use. If you find issues, then raise them in the places where issues are handled. If you have a personal rule about doing some things differently, fine, but please be respectful of others in the community and the 'rules' they abide by.

Have a prosperous New Year, and may your programming bring you joy.

Richard

On 01/01/2020 07:12, ToddAndMargo via perl6-users wrote:

Hi All,

My latest three modules.  two more in the works that use these:

WinReg.pm6
WinMessageBox
NativeConstants.pm6

WinReg.pm6 about killed me!

-T


<WinReg.pm6>
# unit module WinReg;
# WinReg.pm6

#`{

   Utilities to operate on the Windows registry

   perl6 -I. -c WinReg.pm6

   Test one liner:
      perl6 -I. -e "use WinMount :GetLUA; say GetLUA();"
      perl6 -I. -e "use NativeConstants; use WinReg :WinReadRegKey; say WinReadRegKey( HKEY_LOCAL_MACHINE, Q[SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system], Q[EnableLUA], REG_DWORD, True ).base(16);"       perl6 -I. -e "use NativeConstants; use WinReg :WinReadRegKey; say WinReadRegKey( HKEY_LOCAL_MACHINE, Q[SOFTWARE\Microsoft\Windows NT\CurrentVersion], Q[ProductName], REG_SZ,True );"

   References:

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

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

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

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

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

}

use NativeCall;
use NativeConstants;
use WinMessageBox :WinMsg;


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


sub OpenKey( WinRegHives $Hive, Str $SubKey, $Debug ) {

#`{
    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
    );
}

   my Str $SubName = &?ROUTINE.name;

   my int32 $Handle;
   my int32 $RtnCode = 0;

   my $lpSubKey      = to-c-str( $SubKey );

   my int32 $ulOptions  = 0;
   my int32 $lpData     = 0;
   my int32 $lpcbData   = 1024;  # In:  the maximum amount of bytes allowed in the return variable
                                 # Out: the value of the key
   my int32 $lpReserved = 0;


   if $Debug { say "$SubName"; }
   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 );

   if not $RtnCode == 0  || $Debug == True  {
      my $ErrStr ="ERROR: $SubName\n   Handle $Handle\n   RtnCode $RtnCode\n" ~
          "Unable to open $Hive" ~ Q[\] ~ $SubKey ~ "\n";
      say $ErrStr;
      WinMsg( "Open Error", $ErrStr );
   }

   return $Handle;
}



sub CloseKey( int32 $Handle, $Debug ) {

#`{
    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
    );
}

   my Str $SubName = &?ROUTINE.name;

   my int32 $RtnCode = 0;

   if $Debug { say "$SubName"; }
   sub RegCloseKey( DWORD ) is native("Kernel32.dll") returns DWORD { * };

   $RtnCode = RegCloseKey( $Handle );

   if not $RtnCode == 0  || $Debug == True {
      say "ERROR: $SubName\n   Handle $Handle\n   RtnCode $RtnCode\n";
   }

}



sub WinReadRegKey( WinRegHives $Hive, Str $SubKey, Str $KeyName, ValueNames $ValueName, Bool $Debug = False ) is export( :WinReadRegKey ) {

#`{

    Return "Any" value of $Hive\$SubKey\$KeyName

    For Example:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
          "EnableLUA"=dword:00000000
    $Hive    = HKEY_LOCAL_MACHINE\SOFTWARE
    $SubKey  = Microsoft\Windows\CurrentVersion\Policies   # no leading or trailing slashes
    $KeyName = EnableLUA


    References:
       Raku's NativeCall
       https://docs.perl6.org/language/nativecall

       Win32 return codes:

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

    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 handle from OpenKey
       LPCWSTR lpValueName,   # key name (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
    );


}

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

   my int32 $Handle;
   my       $RtnCode;
   my Any   $KeyValue;

   my $lpSubKey    = to-c-str( $SubKey );  # SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
   my $lpValueName = to-c-str( $KeyName ); # EnableLUA

   my int32 $ulOptions  = 0;
#   my int32 $lpData; #     = 1024;
   my BYTES $lpData = CArray[BYTE].new( 0 xx 1024 );

   my int32 $lpcbData   = 1024;   # max size of returned data


   $Handle = OpenKey( HKEY_LOCAL_MACHINE, $SubKey, $Debug );

   if $Debug  { say "$SubName"; }
   sub RegQueryValueExW( DWORD, WCHARS, DWORD, DWORD, CArray[BYTE] is rw, DWORD is rw ) is native( "Kernel32.dll" ) is symbol( "RegQueryValueExW" ) returns DWORD { * };    $RtnCode = RegQueryValueExW( $Handle, $lpValueName, 0, 0, $lpData, $lpcbData );

   if $Debug  { say "$SubName: data received, byte count $lpcbData"; }

   if not $RtnCode == 0  {
      say "ERROR: $SubName\n   Handle $Handle\n   RtnCode $RtnCode, 0x$RtnCode.base(16)  " ~        "\(2 KeyNotFound; 6 handle; 87 Invalid Parameter; 234 More data\)\n" ~
      "   lpcbData data length $lpcbData\n";
   }

   CloseKey( $Handle, $Debug );

   if $RtnCode == 0  {

      if $ValueName eq REG_SZ                        ||
         $ValueName eq REG_EXPAND_SZ                 ||
         $ValueName eq REG_LINK                      ||
         $ValueName eq REG_LINK                      ||
         $ValueName eq REG_MULTI_SZ                  ||
         $ValueName eq REG_RESOURCE_LIST             ||
         $ValueName eq REG_FULL_RESOURCE_DESCRIPTOR  ||
         $ValueName eq REG_RESOURCE_REQUIREMENTS_LIST   {
            loop (my $Index=0; $Index < $lpcbData - 2 ; $Index += 2) {
               $KeyValue ~= chr( $lpData[ $Index ] );
            }

         } else {
            # say "lpData = $lpData";
            loop (my $Index = 0; $Index < $lpcbData; $Index += 1 ) {
               my BYTE  $x = $lpData[ $Index ]; # say $x.base(16);
               my int32 $y = $x +| 0x0000;      # say $y.base(16);
               $KeyValue += ( $y +< ( $Index * 8 ) );
               # say "KeyValue = $KeyValue $KeyValue.base(16)\n";;
         }
      }

   } else {
      $KeyValue = "ERROR";
      my $ErrStr ="ERROR: $SubName\n   Handle $Handle\n   RtnCode $RtnCode\n" ~           "Unable to open $Hive" ~ Q[\] ~ $SubKey ~ Q[\] ~ $KeyName ~ Q[::] ~ $ValueName ~ "\n";
      say $ErrStr;
      WinMsg( "Open Error", $ErrStr );

   }

   return $KeyValue;
}
</WinReg.pm6>




<WinMessageBox>
# unit module WinMessageBox;
# MessageBox.pm6

#`{

    This Module provides access to Windows "user32" MessageBox function and     give a WinMsg to substitute for Windows Professional's msg.exe program, without
    the networking.

    This module is not able to retrieve information from the user other than the buttons

       Test one liners:
        perl6 -e "use lib '.'; use WinMessageBox :MessageBox; say MessageBox( 'Some Title', 'Something Cleaver', MB_ICONINFORMATION, MB_OK );"         perl6 -e "use lib '.'; use WinMessageBox :MessageBox; say MessageBox( 'Some Title', 'Something Cleaver', MB_ICONQUESTION, MB_YESNOCANCEL );         perl6 -e "use lib '.'; use WinMessageBox :MessageBox; say MessageBox( 'Some Title', 'Something Cleaver', MB_ICONERROR, MB_CANCELTRYCONTINUE );"

        perl6 -e "use lib '.'; use WinMessageBox :WinMsg;     say WinMsg(     'Some Title', 'Something Cleaver' );"


      References:

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox

https://stackoverflow.com/questions/59105696/how-can-i-create-pop-up-windows-for-perl6-in-windows
         https://docs.perl6.org/language/nativecall
}

use NativeCall;
use NativeConstants;


enum Icons (
   MB_ICONEXCLAMATION   => 0x00000030,
   MB_ICONWARNING       => 0x00000030,
   MB_ICONINFORMATION   => 0x00000040,
   MB_ICONASTERISK      => 0x00000040,
   MB_ICONQUESTION      => 0x00000020,
   MB_ICONSTOP          => 0x00000010,
   MB_ICONERROR         => 0x00000010,
   MB_ICONHAND          => 0x00000010
);

enum Buttons (
   MB_ABORTRETRYIGNORE  => 0x00000002,
   MB_CANCELTRYCONTINUE => 0x00000006,
   MB_HELP              => 0x00004000,
   MB_OK                => 0x00000000,
   MB_OKCANCEL          => 0x00000001,
   MB_RETRYCANCEL       => 0x00000005,
   MB_YESNO             => 0x00000004,
   MB_YESNOCANCEL       => 0x00000003
);

enum MessageBoxReturn (
   ABORT     =>  3,
   CANCEL   =>  2,
   CONTINUE => 11,
   IGNORE   =>  5,
   NO       =>  7,
   OK       =>  1,
   RETRY    =>  4,
   TRYAGAIN => 10,
   YES      =>  6
);


sub MessageBoxW(
   HANDLE,
   LPWCTSTR,
   LPWCTSTR,
   UINT
)
   is native("user32")
   is symbol("MessageBoxW")
   returns INT
{ * };


sub MessageBox(
   Str $Title,
   Str $Message,
   Icons $Icon = Icons::MB_ICONINFORMATION,
   Buttons $Button = Buttons::MB_OK
)
   returns MessageBoxReturn is export( :MessageBox )
{

#`{
    Pop up a message box to the user.
    Windows only.
    Return what button was pressed

    See top for test one liners
}

   my Str $SubName = &?ROUTINE.name;
   my Str $OS      = $*KERNEL.name;

   if not $OS eq "win32" {
      say "Sorry, $SubName only work in Windows.";
      exit;
   }

   my $lpText    = CArray[uint16].new( $Message.encode.list ); $lpText[$lpText.elems]       = 0;    my $lpCaption = CArray[uint16].new( $Title.encode.list ); $lpCaption[$lpCaption.elems] = 0;
   my $uType     = $Icon +| $Button;   # bitwise OR them together

   return MessageBoxReturn( MessageBoxW( my $Handle, $lpText, $lpCaption, $uType ));
}


sub WinMsg( Str $TitleStr, Str $MessageStr ) is export( :WinMsg ) {

#`{
    Simple "Ok" pop up with no return value.  Thjis as a subsitute for Windows `msg.exe` program
    that only runs in the Professinal version and without the netowrking.

    See top for test one liners
}

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

   return  MessageBox( $TitleStr, $MessageStr, MB_ICONINFORMATION, MB_OK );
}
</WinMessageBox>



<NativeConstants.pm6>
# unit module NativeConstants;
# NativeConstants.pm6

#`{

    Constants used across Windows libraries that use Native Call

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

https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-key-security-and-access-rights

https://docs.microsoft.com/en-us/windows/win32/intl/language-identifiers

https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
https://stackoverflow.com/questions/321413/lpcstr-lpctstr-and-lptstr

https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types

https://docs.microsoft.com/en-us/windows/win32/sysinfo/structure-of-the-registry

    perl6 -I. -c NativeConstants.pm6

    Test one liner:
       perl6 -I. -e "use NativeConstants; say FORMAT_MESSAGE_ALLOCATE_BUFFER.base(16);"

}


use NativeCall;

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

constant INT      = int32;
constant UINT     = uint32;
constant HANDLE   = Pointer[void];
constant LPWCTSTR = CArray[WCHAR];

constant FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
constant FORMAT_MESSAGE_FROM_SYSTEM     = 0x00001000;
constant FORMAT_MESSAGE_IGNORE_INSERTS  = 0x00000200;

constant KEY_QUERY_VALUE   = 1;
constant ERROR_SUCCESS     = 0; # Win-Api  0 = success

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


enum WinRegHives (
   HKEY_CLASSES_ROOT     => 0x80000000;
   HKEY_CURRENT_USER     => 0x80000001;
   HKEY_LOCAL_MACHINE    => 0x80000002;
   HKEY_USERS            => 0x80000003;
   HKEY_PERFORMANCE_DATA => 0x80000004;
   HKEY_CURRENT_CONFIG   => 0x80000005;
   HKEY_DYN_DATA         => 0x80000006;
);

enum ValueNames (
   REG_NONE                       => 0;   # No value type
   REG_SZ                         => 1;   # Unicode nul terminated string
   REG_EXPAND_SZ                  => 2;   # Unicode nul terminated string = (with environment variable references)
   REG_BINARY                     => 3;   # Free form binary
   REG_DWORD                      => 4;   # 32-bit number
   REG_DWORD_LITTLE_ENDIAN        => 4;   # 32-bit number = (same as REG_DWORD)
   REG_DWORD_BIG_ENDIAN           => 5;   # 32-bit number
   REG_LINK                       => 6;   # Symbolic Link = (unicode)
   REG_MULTI_SZ                   => 7;   # Multiple Unicode strings
   REG_RESOURCE_LIST              => 8;   # Resource list in the resource map    REG_FULL_RESOURCE_DESCRIPTOR   => 9;   # Resource list in the hardware description
   REG_RESOURCE_REQUIREMENTS_LIST => 10;
   REG_QWORD                      => 11;  # 64-bit number
   REG_QWORD_LITTLE_ENDIAN        => 11;  # same as REG_QWORD
);
</NativeConstants.pm6>

Reply via email to