diff options
author | Reinhard Kotucha <reinhard.kotucha@web.de> | 2007-12-29 21:29:01 +0000 |
---|---|---|
committer | Reinhard Kotucha <reinhard.kotucha@web.de> | 2007-12-29 21:29:01 +0000 |
commit | 632de1b57f1b3669f2823985dcc444ecab1116ce (patch) | |
tree | 8b12407a43ea614a776f2f6672beb137e0c87302 /Master/tlpkg/lib | |
parent | d73a51fb1c4819c2a3710a77875a3c7aaea5e5fd (diff) |
Perl5_lib-TL_inst: new Modules from Siep
git-svn-id: svn://tug.org/texlive/trunk@5992 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/lib')
15 files changed, 9365 insertions, 0 deletions
diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/AutoLoader.pm b/Master/tlpkg/lib/Perl5_lib-TL_inst/AutoLoader.pm new file mode 100644 index 00000000000..4352d8b1fbe --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/AutoLoader.pm @@ -0,0 +1,343 @@ +package AutoLoader; + +use strict; +use 5.006_001; + +our($VERSION, $AUTOLOAD); + +my $is_dosish; +my $is_epoc; +my $is_vms; +my $is_macos; + +BEGIN { + $is_dosish = $^O eq 'dos' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'NetWare'; + $is_epoc = $^O eq 'epoc'; + $is_vms = $^O eq 'VMS'; + $is_macos = $^O eq 'MacOS'; + $VERSION = '5.60'; +} + +AUTOLOAD { + my $sub = $AUTOLOAD; + my $filename; + # Braces used to preserve $1 et al. + { + # Try to find the autoloaded file from the package-qualified + # name of the sub. e.g., if the sub needed is + # Getopt::Long::GetOptions(), then $INC{Getopt/Long.pm} is + # something like '/usr/lib/perl5/Getopt/Long.pm', and the + # autoload file is '/usr/lib/perl5/auto/Getopt/Long/GetOptions.al'. + # + # However, if @INC is a relative path, this might not work. If, + # for example, @INC = ('lib'), then $INC{Getopt/Long.pm} is + # 'lib/Getopt/Long.pm', and we want to require + # 'auto/Getopt/Long/GetOptions.al' (without the leading 'lib'). + # In this case, we simple prepend the 'auto/' and let the + # C<require> take care of the searching for us. + + my ($pkg,$func) = ($sub =~ /(.*)::([^:]+)$/); + $pkg =~ s#::#/#g; + if (defined($filename = $INC{"$pkg.pm"})) { + if ($is_macos) { + $pkg =~ tr#/#:#; + $filename =~ s#^(.*)$pkg\.pm\z#$1auto:$pkg:$func.al#s; + } else { + $filename =~ s#^(.*)$pkg\.pm\z#$1auto/$pkg/$func.al#s; + } + + # if the file exists, then make sure that it is a + # a fully anchored path (i.e either '/usr/lib/auto/foo/bar.al', + # or './lib/auto/foo/bar.al'. This avoids C<require> searching + # (and failing) to find the 'lib/auto/foo/bar.al' because it + # looked for 'lib/lib/auto/foo/bar.al', given @INC = ('lib'). + + if (-r $filename) { + unless ($filename =~ m|^/|s) { + if ($is_dosish) { + unless ($filename =~ m{^([a-z]:)?[\\/]}is) { + if ($^O ne 'NetWare') { + $filename = "./$filename"; + } else { + $filename = "$filename"; + } + } + } + elsif ($is_epoc) { + unless ($filename =~ m{^([a-z?]:)?[\\/]}is) { + $filename = "./$filename"; + } + } + elsif ($is_vms) { + # XXX todo by VMSmiths + $filename = "./$filename"; + } + elsif (!$is_macos) { + $filename = "./$filename"; + } + } + } + else { + $filename = undef; + } + } + unless (defined $filename) { + # let C<require> do the searching + $filename = "auto/$sub.al"; + $filename =~ s#::#/#g; + } + } + my $save = $@; + local $!; # Do not munge the value. + eval { local $SIG{__DIE__}; require $filename }; + if ($@) { + if (substr($sub,-9) eq '::DESTROY') { + no strict 'refs'; + *$sub = sub {}; + $@ = undef; + } elsif ($@ =~ /^Can't locate/) { + # The load might just have failed because the filename was too + # long for some old SVR3 systems which treat long names as errors. + # If we can successfully truncate a long name then it's worth a go. + # There is a slight risk that we could pick up the wrong file here + # but autosplit should have warned about that when splitting. + if ($filename =~ s/(\w{12,})\.al$/substr($1,0,11).".al"/e){ + eval { local $SIG{__DIE__}; require $filename }; + } + } + if ($@){ + $@ =~ s/ at .*\n//; + my $error = $@; + require Carp; + Carp::croak($error); + } + } + $@ = $save; + goto &$sub; +} + +sub import { + my $pkg = shift; + my $callpkg = caller; + + # + # Export symbols, but not by accident of inheritance. + # + + if ($pkg eq 'AutoLoader') { + no strict 'refs'; + *{ $callpkg . '::AUTOLOAD' } = \&AUTOLOAD + if @_ and $_[0] =~ /^&?AUTOLOAD$/; + } + + # + # Try to find the autosplit index file. Eg., if the call package + # is POSIX, then $INC{POSIX.pm} is something like + # '/usr/local/lib/perl5/POSIX.pm', and the autosplit index file is in + # '/usr/local/lib/perl5/auto/POSIX/autosplit.ix', so we require that. + # + # However, if @INC is a relative path, this might not work. If, + # for example, @INC = ('lib'), then + # $INC{POSIX.pm} is 'lib/POSIX.pm', and we want to require + # 'auto/POSIX/autosplit.ix' (without the leading 'lib'). + # + + (my $calldir = $callpkg) =~ s#::#/#g; + my $path = $INC{$calldir . '.pm'}; + if (defined($path)) { + # Try absolute path name. + if ($is_macos) { + (my $malldir = $calldir) =~ tr#/#:#; + $path =~ s#^(.*)$malldir\.pm\z#$1auto:$malldir:autosplit.ix#s; + } else { + $path =~ s#^(.*)$calldir\.pm\z#$1auto/$calldir/autosplit.ix#; + } + + eval { require $path; }; + # If that failed, try relative path with normal @INC searching. + if ($@) { + $path ="auto/$calldir/autosplit.ix"; + eval { require $path; }; + } + if ($@) { + my $error = $@; + require Carp; + Carp::carp($error); + } + } +} + +sub unimport { + my $callpkg = caller; + + no strict 'refs'; + my $symname = $callpkg . '::AUTOLOAD'; + undef *{ $symname } if \&{ $symname } == \&AUTOLOAD; + *{ $symname } = \&{ $symname }; +} + +1; + +__END__ + +=head1 NAME + +AutoLoader - load subroutines only on demand + +=head1 SYNOPSIS + + package Foo; + use AutoLoader 'AUTOLOAD'; # import the default AUTOLOAD subroutine + + package Bar; + use AutoLoader; # don't import AUTOLOAD, define our own + sub AUTOLOAD { + ... + $AutoLoader::AUTOLOAD = "..."; + goto &AutoLoader::AUTOLOAD; + } + +=head1 DESCRIPTION + +The B<AutoLoader> module works with the B<AutoSplit> module and the +C<__END__> token to defer the loading of some subroutines until they are +used rather than loading them all at once. + +To use B<AutoLoader>, the author of a module has to place the +definitions of subroutines to be autoloaded after an C<__END__> token. +(See L<perldata>.) The B<AutoSplit> module can then be run manually to +extract the definitions into individual files F<auto/funcname.al>. + +B<AutoLoader> implements an AUTOLOAD subroutine. When an undefined +subroutine in is called in a client module of B<AutoLoader>, +B<AutoLoader>'s AUTOLOAD subroutine attempts to locate the subroutine in a +file with a name related to the location of the file from which the +client module was read. As an example, if F<POSIX.pm> is located in +F</usr/local/lib/perl5/POSIX.pm>, B<AutoLoader> will look for perl +subroutines B<POSIX> in F</usr/local/lib/perl5/auto/POSIX/*.al>, where +the C<.al> file has the same name as the subroutine, sans package. If +such a file exists, AUTOLOAD will read and evaluate it, +thus (presumably) defining the needed subroutine. AUTOLOAD will then +C<goto> the newly defined subroutine. + +Once this process completes for a given function, it is defined, so +future calls to the subroutine will bypass the AUTOLOAD mechanism. + +=head2 Subroutine Stubs + +In order for object method lookup and/or prototype checking to operate +correctly even when methods have not yet been defined it is necessary to +"forward declare" each subroutine (as in C<sub NAME;>). See +L<perlsub/"SYNOPSIS">. Such forward declaration creates "subroutine +stubs", which are place holders with no code. + +The AutoSplit and B<AutoLoader> modules automate the creation of forward +declarations. The AutoSplit module creates an 'index' file containing +forward declarations of all the AutoSplit subroutines. When the +AutoLoader module is 'use'd it loads these declarations into its callers +package. + +Because of this mechanism it is important that B<AutoLoader> is always +C<use>d and not C<require>d. + +=head2 Using B<AutoLoader>'s AUTOLOAD Subroutine + +In order to use B<AutoLoader>'s AUTOLOAD subroutine you I<must> +explicitly import it: + + use AutoLoader 'AUTOLOAD'; + +=head2 Overriding B<AutoLoader>'s AUTOLOAD Subroutine + +Some modules, mainly extensions, provide their own AUTOLOAD subroutines. +They typically need to check for some special cases (such as constants) +and then fallback to B<AutoLoader>'s AUTOLOAD for the rest. + +Such modules should I<not> import B<AutoLoader>'s AUTOLOAD subroutine. +Instead, they should define their own AUTOLOAD subroutines along these +lines: + + use AutoLoader; + use Carp; + + sub AUTOLOAD { + my $sub = $AUTOLOAD; + (my $constname = $sub) =~ s/.*:://; + my $val = constant($constname, @_ ? $_[0] : 0); + if ($! != 0) { + if ($! =~ /Invalid/ || $!{EINVAL}) { + $AutoLoader::AUTOLOAD = $sub; + goto &AutoLoader::AUTOLOAD; + } + else { + croak "Your vendor has not defined constant $constname"; + } + } + *$sub = sub { $val }; # same as: eval "sub $sub { $val }"; + goto &$sub; + } + +If any module's own AUTOLOAD subroutine has no need to fallback to the +AutoLoader's AUTOLOAD subroutine (because it doesn't have any AutoSplit +subroutines), then that module should not use B<AutoLoader> at all. + +=head2 Package Lexicals + +Package lexicals declared with C<my> in the main block of a package +using B<AutoLoader> will not be visible to auto-loaded subroutines, due to +the fact that the given scope ends at the C<__END__> marker. A module +using such variables as package globals will not work properly under the +B<AutoLoader>. + +The C<vars> pragma (see L<perlmod/"vars">) may be used in such +situations as an alternative to explicitly qualifying all globals with +the package namespace. Variables pre-declared with this pragma will be +visible to any autoloaded routines (but will not be invisible outside +the package, unfortunately). + +=head2 Not Using AutoLoader + +You can stop using AutoLoader by simply + + no AutoLoader; + +=head2 B<AutoLoader> vs. B<SelfLoader> + +The B<AutoLoader> is similar in purpose to B<SelfLoader>: both delay the +loading of subroutines. + +B<SelfLoader> uses the C<__DATA__> marker rather than C<__END__>. +While this avoids the use of a hierarchy of disk files and the +associated open/close for each routine loaded, B<SelfLoader> suffers a +startup speed disadvantage in the one-time parsing of the lines after +C<__DATA__>, after which routines are cached. B<SelfLoader> can also +handle multiple packages in a file. + +B<AutoLoader> only reads code as it is requested, and in many cases +should be faster, but requires a mechanism like B<AutoSplit> be used to +create the individual files. L<ExtUtils::MakeMaker> will invoke +B<AutoSplit> automatically if B<AutoLoader> is used in a module source +file. + +=head1 CAVEATS + +AutoLoaders prior to Perl 5.002 had a slightly different interface. Any +old modules which use B<AutoLoader> should be changed to the new calling +style. Typically this just means changing a require to a use, adding +the explicit C<'AUTOLOAD'> import if needed, and removing B<AutoLoader> +from C<@ISA>. + +On systems with restrictions on file name length, the file corresponding +to a subroutine may have a shorter name that the routine itself. This +can lead to conflicting file names. The I<AutoSplit> package warns of +these potential conflicts when used to split a module. + +AutoLoader may fail to find the autosplit files (or even find the wrong +ones) in cases where C<@INC> contains relative paths, B<and> the program +does C<chdir>. + +=head1 SEE ALSO + +L<SelfLoader> - an autoloader that doesn't use external files. + +=cut diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/Config.pm b/Master/tlpkg/lib/Perl5_lib-TL_inst/Config.pm new file mode 100644 index 00000000000..7e5ad77b30a --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/Config.pm @@ -0,0 +1,95 @@ +# This file was created by configpm when Perl was built. Any changes +# made to this file will be lost the next time perl is built. + +package Config; +use strict; +# use warnings; Pulls in Carp +# use vars pulls in Carp +@Config::EXPORT = qw(%Config); +@Config::EXPORT_OK = qw(myconfig config_sh config_vars config_re); + +# Need to stub all the functions to make code such as print Config::config_sh +# keep working + +sub myconfig; +sub config_sh; +sub config_vars; +sub config_re; + +my %Export_Cache = map {($_ => 1)} (@Config::EXPORT, @Config::EXPORT_OK); + +our %Config; + +# Define our own import method to avoid pulling in the full Exporter: +sub import { + my $pkg = shift; + @_ = @Config::EXPORT unless @_; + + my @funcs = grep $_ ne '%Config', @_; + my $export_Config = @funcs < @_ ? 1 : 0; + + no strict 'refs'; + my $callpkg = caller(0); + foreach my $func (@funcs) { + die sprintf qq{"%s" is not exported by the %s module\n}, + $func, __PACKAGE__ unless $Export_Cache{$func}; + *{$callpkg.'::'.$func} = \&{$func}; + } + + *{"$callpkg\::Config"} = \%Config if $export_Config; + return; +} + +die "Perl lib version (v5.8.8) doesn't match executable version ($])" + unless $^V; + +$^V eq v5.8.8 + or die "Perl lib version (v5.8.8) doesn't match executable version (" . + sprintf("v%vd",$^V) . ")"; + + +sub FETCH { + my($self, $key) = @_; + + # check for cached value (which may be undef so we use exists not defined) + return $self->{$key} if exists $self->{$key}; + + return $self->fetch_string($key); +} +sub TIEHASH { + bless $_[1], $_[0]; +} + +sub DESTROY { } + +sub AUTOLOAD { + require 'Config_heavy.pl'; + goto \&launcher unless $Config::AUTOLOAD =~ /launcher$/; + die "&Config::AUTOLOAD failed on $Config::AUTOLOAD"; +} + +# tie returns the object, so the value returned to require will be true. +tie %Config, 'Config', { + archlibexp => 'x:\\perl\\lib', + archname => 'MSWin32-x86-multi-thread', + cc => 'gcc', + d_readlink => undef, + d_symlink => undef, + dlsrc => 'dl_win32.xs', + dont_use_nlink => undef, + exe_ext => '.exe', + inc_version_list => '', + intsize => '4', + ldlibpthname => '', + libpth => 'x:\\msys\\mingw\\lib', + osname => 'MSWin32', + osvers => '5.1', + path_sep => ';', + privlibexp => 'x:\\perl\\lib', + scriptdir => 'x:\\perl\\bin', + sitearchexp => 'x:\\perl\\site\\lib', + sitelibexp => 'x:\\perl\\site\\lib', + useithreads => 'define', + usevendorprefix => undef, + version => '5.8.8', +}; diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/DynaLoader.pm b/Master/tlpkg/lib/Perl5_lib-TL_inst/DynaLoader.pm new file mode 100644 index 00000000000..178e9b2616c --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/DynaLoader.pm @@ -0,0 +1,833 @@ + +# Generated from DynaLoader.pm.PL + +package DynaLoader; + +# And Gandalf said: 'Many folk like to know beforehand what is to +# be set on the table; but those who have laboured to prepare the +# feast like to keep their secret; for wonder makes the words of +# praise louder.' + +# (Quote from Tolkien suggested by Anno Siegel.) +# +# See pod text at end of file for documentation. +# See also ext/DynaLoader/README in source tree for other information. +# +# Tim.Bunce@ig.co.uk, August 1994 + +use vars qw($VERSION *AUTOLOAD); + +$VERSION = '1.05'; # avoid typo warning + +require AutoLoader; +*AUTOLOAD = \&AutoLoader::AUTOLOAD; + +use Config; + +# The following require can't be removed during maintenance +# releases, sadly, because of the risk of buggy code that does +# require Carp; Carp::croak "..."; without brackets dying +# if Carp hasn't been loaded in earlier compile time. :-( +# We'll let those bugs get found on the development track. +require Carp if $] < 5.00450; + +# enable debug/trace messages from DynaLoader perl code +$dl_debug = $ENV{PERL_DL_DEBUG} || 0 unless defined $dl_debug; + +# +# Flags to alter dl_load_file behaviour. Assigned bits: +# 0x01 make symbols available for linking later dl_load_file's. +# (only known to work on Solaris 2 using dlopen(RTLD_GLOBAL)) +# (ignored under VMS; effect is built-in to image linking) +# +# This is called as a class method $module->dl_load_flags. The +# definition here will be inherited and result on "default" loading +# behaviour unless a sub-class of DynaLoader defines its own version. +# + +sub dl_load_flags { 0x00 } + +# ($dl_dlext, $dlsrc) +# = @Config::Config{'dlext', 'dlsrc'}; + ($dl_dlext, $dlsrc) = ('dll','dl_win32.xs') +; +# Some systems need special handling to expand file specifications +# (VMS support by Charles Bailey <bailey@HMIVAX.HUMGEN.UPENN.EDU>) +# See dl_expandspec() for more details. Should be harmless but +# inefficient to define on systems that don't need it. +$Is_VMS = $^O eq 'VMS'; +$do_expand = $Is_VMS; +$Is_MacOS = $^O eq 'MacOS'; + +my $Mac_FS; +$Mac_FS = eval { require Mac::FileSpec::Unixish } if $Is_MacOS; + +@dl_require_symbols = (); # names of symbols we need +@dl_resolve_using = (); # names of files to link with +@dl_library_path = (); # path to look for files + +#XSLoader.pm may have added elements before we were required +#@dl_shared_objects = (); # shared objects for symbols we have +#@dl_librefs = (); # things we have loaded +#@dl_modules = (); # Modules we have loaded + +# This is a fix to support DLD's unfortunate desire to relink -lc +@dl_resolve_using = dl_findfile('-lc') if $dlsrc eq "dl_dld.xs"; + +# Initialise @dl_library_path with the 'standard' library path +# for this platform as determined by Configure. + +push(@dl_library_path, split(' ', $Config::Config{libpth})); + + +my $ldlibpthname = $Config::Config{ldlibpthname}; +my $ldlibpthname_defined = defined $Config::Config{ldlibpthname}; +my $pthsep = $Config::Config{path_sep}; + +# Add to @dl_library_path any extra directories we can gather from environment +# during runtime. + +if ($ldlibpthname_defined && + exists $ENV{$ldlibpthname}) { + push(@dl_library_path, split(/$pthsep/, $ENV{$ldlibpthname})); +} + +# E.g. HP-UX supports both its native SHLIB_PATH *and* LD_LIBRARY_PATH. + +if ($ldlibpthname_defined && + $ldlibpthname ne 'LD_LIBRARY_PATH' && + exists $ENV{LD_LIBRARY_PATH}) { + push(@dl_library_path, split(/$pthsep/, $ENV{LD_LIBRARY_PATH})); +} + + +# No prizes for guessing why we don't say 'bootstrap DynaLoader;' here. +# NOTE: All dl_*.xs (including dl_none.xs) define a dl_error() XSUB +boot_DynaLoader('DynaLoader') if defined(&boot_DynaLoader) && + !defined(&dl_error); + +if ($dl_debug) { + print STDERR "DynaLoader.pm loaded (@INC, @dl_library_path)\n"; + print STDERR "DynaLoader not linked into this perl\n" + unless defined(&boot_DynaLoader); +} + +1; # End of main code + + +sub croak { require Carp; Carp::croak(@_) } + +sub bootstrap_inherit { + my $module = $_[0]; + local *isa = *{"$module\::ISA"}; + local @isa = (@isa, 'DynaLoader'); + # Cannot goto due to delocalization. Will report errors on a wrong line? + bootstrap(@_); +} + +# The bootstrap function cannot be autoloaded (without complications) +# so we define it here: + +sub bootstrap { + # use local vars to enable $module.bs script to edit values + local(@args) = @_; + local($module) = $args[0]; + local(@dirs, $file); + + unless ($module) { + require Carp; + Carp::confess("Usage: DynaLoader::bootstrap(module)"); + } + + # A common error on platforms which don't support dynamic loading. + # Since it's fatal and potentially confusing we give a detailed message. + croak("Can't load module $module, dynamic loading not available in this perl.\n". + " (You may need to build a new perl executable which either supports\n". + " dynamic loading or has the $module module statically linked into it.)\n") + unless defined(&dl_load_file); + + my @modparts = split(/::/,$module); + my $modfname = $modparts[-1]; + + # Some systems have restrictions on files names for DLL's etc. + # mod2fname returns appropriate file base name (typically truncated) + # It may also edit @modparts if required. + $modfname = &mod2fname(\@modparts) if defined &mod2fname; + + # Truncate the module name to 8.3 format for NetWare + if (($^O eq 'NetWare') && (length($modfname) > 8)) { + $modfname = substr($modfname, 0, 8); + } + + my $modpname = join(($Is_MacOS ? ':' : '/'),@modparts); + + print STDERR "DynaLoader::bootstrap for $module ", + ($Is_MacOS + ? "(:auto:$modpname:$modfname.$dl_dlext)\n" : + "(auto/$modpname/$modfname.$dl_dlext)\n") + if $dl_debug; + + foreach (@INC) { + chop($_ = VMS::Filespec::unixpath($_)) if $Is_VMS; + my $dir; + if ($Is_MacOS) { + my $path = $_; + if ($Mac_FS && ! -d $path) { + $path = Mac::FileSpec::Unixish::nativize($path); + } + $path .= ":" unless /:$/; + $dir = "${path}auto:$modpname"; + } else { + $dir = "$_/auto/$modpname"; + } + + next unless -d $dir; # skip over uninteresting directories + + # check for common cases to avoid autoload of dl_findfile + my $try = $Is_MacOS ? "$dir:$modfname.$dl_dlext" : "$dir/$modfname.$dl_dlext"; + last if $file = ($do_expand) ? dl_expandspec($try) : ((-f $try) && $try); + + # no luck here, save dir for possible later dl_findfile search + push @dirs, $dir; + } + # last resort, let dl_findfile have a go in all known locations + $file = dl_findfile(map("-L$_",@dirs,@INC), $modfname) unless $file; + + croak("Can't locate loadable object for module $module in \@INC (\@INC contains: @INC)") + unless $file; # wording similar to error from 'require' + + $file = uc($file) if $Is_VMS && $Config::Config{d_vms_case_sensitive_symbols}; + my $bootname = "boot_$module"; + $bootname =~ s/\W/_/g; + @dl_require_symbols = ($bootname); + + # Execute optional '.bootstrap' perl script for this module. + # The .bs file can be used to configure @dl_resolve_using etc to + # match the needs of the individual module on this architecture. + my $bs = $file; + $bs =~ s/(\.\w+)?(;\d*)?$/\.bs/; # look for .bs 'beside' the library + if (-s $bs) { # only read file if it's not empty + print STDERR "BS: $bs ($^O, $dlsrc)\n" if $dl_debug; + eval { do $bs; }; + warn "$bs: $@\n" if $@; + } + + my $boot_symbol_ref; + + if ($^O eq 'darwin') { + if ($boot_symbol_ref = dl_find_symbol(0, $bootname)) { + goto boot; #extension library has already been loaded, e.g. darwin + } + } + + # Many dynamic extension loading problems will appear to come from + # this section of code: XYZ failed at line 123 of DynaLoader.pm. + # Often these errors are actually occurring in the initialisation + # C code of the extension XS file. Perl reports the error as being + # in this perl code simply because this was the last perl code + # it executed. + + my $libref = dl_load_file($file, $module->dl_load_flags) or + croak("Can't load '$file' for module $module: ".dl_error()); + + push(@dl_librefs,$libref); # record loaded object + + my @unresolved = dl_undef_symbols(); + if (@unresolved) { + require Carp; + Carp::carp("Undefined symbols present after loading $file: @unresolved\n"); + } + + $boot_symbol_ref = dl_find_symbol($libref, $bootname) or + croak("Can't find '$bootname' symbol in $file\n"); + + push(@dl_modules, $module); # record loaded module + + boot: + my $xs = dl_install_xsub("${module}::bootstrap", $boot_symbol_ref, $file); + + # See comment block above + + push(@dl_shared_objects, $file); # record files loaded + + &$xs(@args); +} + + +#sub _check_file { # private utility to handle dl_expandspec vs -f tests +# my($file) = @_; +# return $file if (!$do_expand && -f $file); # the common case +# return $file if ( $do_expand && ($file=dl_expandspec($file))); +# return undef; +#} + + +# Let autosplit and the autoloader deal with these functions: +__END__ + + +sub dl_findfile { + # Read ext/DynaLoader/DynaLoader.doc for detailed information. + # This function does not automatically consider the architecture + # or the perl library auto directories. + my (@args) = @_; + my (@dirs, $dir); # which directories to search + my (@found); # full paths to real files we have found + my $dl_ext= 'dll'; # $Config::Config{'dlext'} suffix for perl extensions + my $dl_so = 'dll'; # $Config::Config{'so'} suffix for shared libraries + + print STDERR "dl_findfile(@args)\n" if $dl_debug; + + # accumulate directories but process files as they appear + arg: foreach(@args) { + # Special fast case: full filepath requires no search + if ($Is_VMS && m%[:>/\]]% && -f $_) { + push(@found,dl_expandspec(VMS::Filespec::vmsify($_))); + last arg unless wantarray; + next; + } + elsif ($Is_MacOS) { + if (m/:/ && -f $_) { + push(@found,$_); + last arg unless wantarray; + } + } + elsif (m:/: && -f $_ && !$do_expand) { + push(@found,$_); + last arg unless wantarray; + next; + } + + # Deal with directories first: + # Using a -L prefix is the preferred option (faster and more robust) + if (m:^-L:) { s/^-L//; push(@dirs, $_); next; } + + if ($Is_MacOS) { + # Otherwise we try to try to spot directories by a heuristic + # (this is a more complicated issue than it first appears) + if (m/:/ && -d $_) { push(@dirs, $_); next; } + # Only files should get this far... + my(@names, $name); # what filenames to look for + s/^-l//; + push(@names, $_); + foreach $dir (@dirs, @dl_library_path) { + next unless -d $dir; + $dir =~ s/^([^:]+)$/:$1/; + $dir =~ s/:$//; + foreach $name (@names) { + my($file) = "$dir:$name"; + print STDERR " checking in $dir for $name\n" if $dl_debug; + if (-f $file) { + push(@found, $file); + next arg; # no need to look any further + } + } + } + next; + } + + # Otherwise we try to try to spot directories by a heuristic + # (this is a more complicated issue than it first appears) + if (m:/: && -d $_) { push(@dirs, $_); next; } + + # VMS: we may be using native VMS directory syntax instead of + # Unix emulation, so check this as well + if ($Is_VMS && /[:>\]]/ && -d $_) { push(@dirs, $_); next; } + + # Only files should get this far... + my(@names, $name); # what filenames to look for + if (m:-l: ) { # convert -lname to appropriate library name + s/-l//; + push(@names,"lib$_.$dl_so"); + push(@names,"lib$_.a"); + } else { # Umm, a bare name. Try various alternatives: + # these should be ordered with the most likely first + push(@names,"$_.$dl_ext") unless m/\.$dl_ext$/o; + push(@names,"$_.$dl_so") unless m/\.$dl_so$/o; + push(@names,"lib$_.$dl_so") unless m:/:; + push(@names,"$_.a") if !m/\.a$/ and $dlsrc eq "dl_dld.xs"; + push(@names, $_); + } + foreach $dir (@dirs, @dl_library_path) { + next unless -d $dir; + chop($dir = VMS::Filespec::unixpath($dir)) if $Is_VMS; + foreach $name (@names) { + my($file) = "$dir/$name"; + print STDERR " checking in $dir for $name\n" if $dl_debug; + $file = ($do_expand) ? dl_expandspec($file) : (-f $file && $file); + #$file = _check_file($file); + if ($file) { + push(@found, $file); + next arg; # no need to look any further + } + } + } + } + if ($dl_debug) { + foreach(@dirs) { + print STDERR " dl_findfile ignored non-existent directory: $_\n" unless -d $_; + } + print STDERR "dl_findfile found: @found\n"; + } + return $found[0] unless wantarray; + @found; +} + + +sub dl_expandspec { + my($spec) = @_; + # Optional function invoked if DynaLoader.pm sets $do_expand. + # Most systems do not require or use this function. + # Some systems may implement it in the dl_*.xs file in which case + # this autoload version will not be called but is harmless. + + # This function is designed to deal with systems which treat some + # 'filenames' in a special way. For example VMS 'Logical Names' + # (something like unix environment variables - but different). + # This function should recognise such names and expand them into + # full file paths. + # Must return undef if $spec is invalid or file does not exist. + + my $file = $spec; # default output to input + + if ($Is_VMS) { # dl_expandspec should be defined in dl_vms.xs + require Carp; + Carp::croak("dl_expandspec: should be defined in XS file!\n"); + } else { + return undef unless -f $file; + } + print STDERR "dl_expandspec($spec) => $file\n" if $dl_debug; + $file; +} + +sub dl_find_symbol_anywhere +{ + my $sym = shift; + my $libref; + foreach $libref (@dl_librefs) { + my $symref = dl_find_symbol($libref,$sym); + return $symref if $symref; + } + return undef; +} + +=head1 NAME + +DynaLoader - Dynamically load C libraries into Perl code + +=head1 SYNOPSIS + + package YourPackage; + require DynaLoader; + @ISA = qw(... DynaLoader ...); + bootstrap YourPackage; + + # optional method for 'global' loading + sub dl_load_flags { 0x01 } + + +=head1 DESCRIPTION + +This document defines a standard generic interface to the dynamic +linking mechanisms available on many platforms. Its primary purpose is +to implement automatic dynamic loading of Perl modules. + +This document serves as both a specification for anyone wishing to +implement the DynaLoader for a new platform and as a guide for +anyone wishing to use the DynaLoader directly in an application. + +The DynaLoader is designed to be a very simple high-level +interface that is sufficiently general to cover the requirements +of SunOS, HP-UX, NeXT, Linux, VMS and other platforms. + +It is also hoped that the interface will cover the needs of OS/2, NT +etc and also allow pseudo-dynamic linking (using C<ld -A> at runtime). + +It must be stressed that the DynaLoader, by itself, is practically +useless for accessing non-Perl libraries because it provides almost no +Perl-to-C 'glue'. There is, for example, no mechanism for calling a C +library function or supplying arguments. A C::DynaLib module +is available from CPAN sites which performs that function for some +common system types. And since the year 2000, there's also Inline::C, +a module that allows you to write Perl subroutines in C. Also available +from your local CPAN site. + +DynaLoader Interface Summary + + @dl_library_path + @dl_resolve_using + @dl_require_symbols + $dl_debug + @dl_librefs + @dl_modules + @dl_shared_objects + Implemented in: + bootstrap($modulename) Perl + @filepaths = dl_findfile(@names) Perl + $flags = $modulename->dl_load_flags Perl + $symref = dl_find_symbol_anywhere($symbol) Perl + + $libref = dl_load_file($filename, $flags) C + $status = dl_unload_file($libref) C + $symref = dl_find_symbol($libref, $symbol) C + @symbols = dl_undef_symbols() C + dl_install_xsub($name, $symref [, $filename]) C + $message = dl_error C + +=over 4 + +=item @dl_library_path + +The standard/default list of directories in which dl_findfile() will +search for libraries etc. Directories are searched in order: +$dl_library_path[0], [1], ... etc + +@dl_library_path is initialised to hold the list of 'normal' directories +(F</usr/lib>, etc) determined by B<Configure> (C<$Config{'libpth'}>). This should +ensure portability across a wide range of platforms. + +@dl_library_path should also be initialised with any other directories +that can be determined from the environment at runtime (such as +LD_LIBRARY_PATH for SunOS). + +After initialisation @dl_library_path can be manipulated by an +application using push and unshift before calling dl_findfile(). +Unshift can be used to add directories to the front of the search order +either to save search time or to override libraries with the same name +in the 'normal' directories. + +The load function that dl_load_file() calls may require an absolute +pathname. The dl_findfile() function and @dl_library_path can be +used to search for and return the absolute pathname for the +library/object that you wish to load. + +=item @dl_resolve_using + +A list of additional libraries or other shared objects which can be +used to resolve any undefined symbols that might be generated by a +later call to load_file(). + +This is only required on some platforms which do not handle dependent +libraries automatically. For example the Socket Perl extension +library (F<auto/Socket/Socket.so>) contains references to many socket +functions which need to be resolved when it's loaded. Most platforms +will automatically know where to find the 'dependent' library (e.g., +F</usr/lib/libsocket.so>). A few platforms need to be told the +location of the dependent library explicitly. Use @dl_resolve_using +for this. + +Example usage: + + @dl_resolve_using = dl_findfile('-lsocket'); + +=item @dl_require_symbols + +A list of one or more symbol names that are in the library/object file +to be dynamically loaded. This is only required on some platforms. + +=item @dl_librefs + +An array of the handles returned by successful calls to dl_load_file(), +made by bootstrap, in the order in which they were loaded. +Can be used with dl_find_symbol() to look for a symbol in any of +the loaded files. + +=item @dl_modules + +An array of module (package) names that have been bootstrap'ed. + +=item @dl_shared_objects + +An array of file names for the shared objects that were loaded. + +=item dl_error() + +Syntax: + + $message = dl_error(); + +Error message text from the last failed DynaLoader function. Note +that, similar to errno in unix, a successful function call does not +reset this message. + +Implementations should detect the error as soon as it occurs in any of +the other functions and save the corresponding message for later +retrieval. This will avoid problems on some platforms (such as SunOS) +where the error message is very temporary (e.g., dlerror()). + +=item $dl_debug + +Internal debugging messages are enabled when $dl_debug is set true. +Currently setting $dl_debug only affects the Perl side of the +DynaLoader. These messages should help an application developer to +resolve any DynaLoader usage problems. + +$dl_debug is set to C<$ENV{'PERL_DL_DEBUG'}> if defined. + +For the DynaLoader developer/porter there is a similar debugging +variable added to the C code (see dlutils.c) and enabled if Perl was +built with the B<-DDEBUGGING> flag. This can also be set via the +PERL_DL_DEBUG environment variable. Set to 1 for minimal information or +higher for more. + +=item dl_findfile() + +Syntax: + + @filepaths = dl_findfile(@names) + +Determine the full paths (including file suffix) of one or more +loadable files given their generic names and optionally one or more +directories. Searches directories in @dl_library_path by default and +returns an empty list if no files were found. + +Names can be specified in a variety of platform independent forms. Any +names in the form B<-lname> are converted into F<libname.*>, where F<.*> is +an appropriate suffix for the platform. + +If a name does not already have a suitable prefix and/or suffix then +the corresponding file will be searched for by trying combinations of +prefix and suffix appropriate to the platform: "$name.o", "lib$name.*" +and "$name". + +If any directories are included in @names they are searched before +@dl_library_path. Directories may be specified as B<-Ldir>. Any other +names are treated as filenames to be searched for. + +Using arguments of the form C<-Ldir> and C<-lname> is recommended. + +Example: + + @dl_resolve_using = dl_findfile(qw(-L/usr/5lib -lposix)); + + +=item dl_expandspec() + +Syntax: + + $filepath = dl_expandspec($spec) + +Some unusual systems, such as VMS, require special filename handling in +order to deal with symbolic names for files (i.e., VMS's Logical Names). + +To support these systems a dl_expandspec() function can be implemented +either in the F<dl_*.xs> file or code can be added to the autoloadable +dl_expandspec() function in F<DynaLoader.pm>. See F<DynaLoader.pm> for +more information. + +=item dl_load_file() + +Syntax: + + $libref = dl_load_file($filename, $flags) + +Dynamically load $filename, which must be the path to a shared object +or library. An opaque 'library reference' is returned as a handle for +the loaded object. Returns undef on error. + +The $flags argument to alters dl_load_file behaviour. +Assigned bits: + + 0x01 make symbols available for linking later dl_load_file's. + (only known to work on Solaris 2 using dlopen(RTLD_GLOBAL)) + (ignored under VMS; this is a normal part of image linking) + +(On systems that provide a handle for the loaded object such as SunOS +and HPUX, $libref will be that handle. On other systems $libref will +typically be $filename or a pointer to a buffer containing $filename. +The application should not examine or alter $libref in any way.) + +This is the function that does the real work. It should use the +current values of @dl_require_symbols and @dl_resolve_using if required. + + SunOS: dlopen($filename) + HP-UX: shl_load($filename) + Linux: dld_create_reference(@dl_require_symbols); dld_link($filename) + NeXT: rld_load($filename, @dl_resolve_using) + VMS: lib$find_image_symbol($filename,$dl_require_symbols[0]) + +(The dlopen() function is also used by Solaris and some versions of +Linux, and is a common choice when providing a "wrapper" on other +mechanisms as is done in the OS/2 port.) + +=item dl_unload_file() + +Syntax: + + $status = dl_unload_file($libref) + +Dynamically unload $libref, which must be an opaque 'library reference' as +returned from dl_load_file. Returns one on success and zero on failure. + +This function is optional and may not necessarily be provided on all platforms. +If it is defined, it is called automatically when the interpreter exits for +every shared object or library loaded by DynaLoader::bootstrap. All such +library references are stored in @dl_librefs by DynaLoader::Bootstrap as it +loads the libraries. The files are unloaded in last-in, first-out order. + +This unloading is usually necessary when embedding a shared-object perl (e.g. +one configured with -Duseshrplib) within a larger application, and the perl +interpreter is created and destroyed several times within the lifetime of the +application. In this case it is possible that the system dynamic linker will +unload and then subsequently reload the shared libperl without relocating any +references to it from any files DynaLoaded by the previous incarnation of the +interpreter. As a result, any shared objects opened by DynaLoader may point to +a now invalid 'ghost' of the libperl shared object, causing apparently random +memory corruption and crashes. This behaviour is most commonly seen when using +Apache and mod_perl built with the APXS mechanism. + + SunOS: dlclose($libref) + HP-UX: ??? + Linux: ??? + NeXT: ??? + VMS: ??? + +(The dlclose() function is also used by Solaris and some versions of +Linux, and is a common choice when providing a "wrapper" on other +mechanisms as is done in the OS/2 port.) + +=item dl_load_flags() + +Syntax: + + $flags = dl_load_flags $modulename; + +Designed to be a method call, and to be overridden by a derived class +(i.e. a class which has DynaLoader in its @ISA). The definition in +DynaLoader itself returns 0, which produces standard behavior from +dl_load_file(). + +=item dl_find_symbol() + +Syntax: + + $symref = dl_find_symbol($libref, $symbol) + +Return the address of the symbol $symbol or C<undef> if not found. If the +target system has separate functions to search for symbols of different +types then dl_find_symbol() should search for function symbols first and +then other types. + +The exact manner in which the address is returned in $symref is not +currently defined. The only initial requirement is that $symref can +be passed to, and understood by, dl_install_xsub(). + + SunOS: dlsym($libref, $symbol) + HP-UX: shl_findsym($libref, $symbol) + Linux: dld_get_func($symbol) and/or dld_get_symbol($symbol) + NeXT: rld_lookup("_$symbol") + VMS: lib$find_image_symbol($libref,$symbol) + + +=item dl_find_symbol_anywhere() + +Syntax: + + $symref = dl_find_symbol_anywhere($symbol) + +Applies dl_find_symbol() to the members of @dl_librefs and returns +the first match found. + +=item dl_undef_symbols() + +Example + + @symbols = dl_undef_symbols() + +Return a list of symbol names which remain undefined after load_file(). +Returns C<()> if not known. Don't worry if your platform does not provide +a mechanism for this. Most do not need it and hence do not provide it, +they just return an empty list. + + +=item dl_install_xsub() + +Syntax: + + dl_install_xsub($perl_name, $symref [, $filename]) + +Create a new Perl external subroutine named $perl_name using $symref as +a pointer to the function which implements the routine. This is simply +a direct call to newXSUB(). Returns a reference to the installed +function. + +The $filename parameter is used by Perl to identify the source file for +the function if required by die(), caller() or the debugger. If +$filename is not defined then "DynaLoader" will be used. + + +=item bootstrap() + +Syntax: + +bootstrap($module) + +This is the normal entry point for automatic dynamic loading in Perl. + +It performs the following actions: + +=over 8 + +=item * + +locates an auto/$module directory by searching @INC + +=item * + +uses dl_findfile() to determine the filename to load + +=item * + +sets @dl_require_symbols to C<("boot_$module")> + +=item * + +executes an F<auto/$module/$module.bs> file if it exists +(typically used to add to @dl_resolve_using any files which +are required to load the module on the current platform) + +=item * + +calls dl_load_flags() to determine how to load the file. + +=item * + +calls dl_load_file() to load the file + +=item * + +calls dl_undef_symbols() and warns if any symbols are undefined + +=item * + +calls dl_find_symbol() for "boot_$module" + +=item * + +calls dl_install_xsub() to install it as "${module}::bootstrap" + +=item * + +calls &{"${module}::bootstrap"} to bootstrap the module (actually +it uses the function reference returned by dl_install_xsub for speed) + +=back + +=back + + +=head1 AUTHOR + +Tim Bunce, 11 August 1994. + +This interface is based on the work and comments of (in no particular +order): Larry Wall, Robert Sanders, Dean Roehrich, Jeff Okamoto, Anno +Siegel, Thomas Neumann, Paul Marquess, Charles Bailey, myself and others. + +Larry Wall designed the elegant inherited bootstrap mechanism and +implemented the first Perl 5 dynamic loader using it. + +Solaris global loading added by Nick Ing-Simmons with design/coding +assistance from Tim Bunce, January 1996. + +=cut diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/Tie/Hash.pm b/Master/tlpkg/lib/Perl5_lib-TL_inst/Tie/Hash.pm new file mode 100644 index 00000000000..a838915482b --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/Tie/Hash.pm @@ -0,0 +1,257 @@ +package Tie::Hash; + +our $VERSION = '1.02'; + +=head1 NAME + +Tie::Hash, Tie::StdHash, Tie::ExtraHash - base class definitions for tied hashes + +=head1 SYNOPSIS + + package NewHash; + require Tie::Hash; + + @ISA = (Tie::Hash); + + sub DELETE { ... } # Provides needed method + sub CLEAR { ... } # Overrides inherited method + + + package NewStdHash; + require Tie::Hash; + + @ISA = (Tie::StdHash); + + # All methods provided by default, define only those needing overrides + # Accessors access the storage in %{$_[0]}; + # TIEHASH should return a reference to the actual storage + sub DELETE { ... } + + package NewExtraHash; + require Tie::Hash; + + @ISA = (Tie::ExtraHash); + + # All methods provided by default, define only those needing overrides + # Accessors access the storage in %{$_[0][0]}; + # TIEHASH should return an array reference with the first element being + # the reference to the actual storage + sub DELETE { + $_[0][1]->('del', $_[0][0], $_[1]); # Call the report writer + delete $_[0][0]->{$_[1]}; # $_[0]->SUPER::DELETE($_[1]) + } + + + package main; + + tie %new_hash, 'NewHash'; + tie %new_std_hash, 'NewStdHash'; + tie %new_extra_hash, 'NewExtraHash', + sub {warn "Doing \U$_[1]\E of $_[2].\n"}; + +=head1 DESCRIPTION + +This module provides some skeletal methods for hash-tying classes. See +L<perltie> for a list of the functions required in order to tie a hash +to a package. The basic B<Tie::Hash> package provides a C<new> method, as well +as methods C<TIEHASH>, C<EXISTS> and C<CLEAR>. The B<Tie::StdHash> and +B<Tie::ExtraHash> packages +provide most methods for hashes described in L<perltie> (the exceptions +are C<UNTIE> and C<DESTROY>). They cause tied hashes to behave exactly like standard hashes, +and allow for selective overwriting of methods. B<Tie::Hash> grandfathers the +C<new> method: it is used if C<TIEHASH> is not defined +in the case a class forgets to include a C<TIEHASH> method. + +For developers wishing to write their own tied hashes, the required methods +are briefly defined below. See the L<perltie> section for more detailed +descriptive, as well as example code: + +=over 4 + +=item TIEHASH classname, LIST + +The method invoked by the command C<tie %hash, classname>. Associates a new +hash instance with the specified class. C<LIST> would represent additional +arguments (along the lines of L<AnyDBM_File> and compatriots) needed to +complete the association. + +=item STORE this, key, value + +Store datum I<value> into I<key> for the tied hash I<this>. + +=item FETCH this, key + +Retrieve the datum in I<key> for the tied hash I<this>. + +=item FIRSTKEY this + +Return the first key in the hash. + +=item NEXTKEY this, lastkey + +Return the next key in the hash. + +=item EXISTS this, key + +Verify that I<key> exists with the tied hash I<this>. + +The B<Tie::Hash> implementation is a stub that simply croaks. + +=item DELETE this, key + +Delete the key I<key> from the tied hash I<this>. + +=item CLEAR this + +Clear all values from the tied hash I<this>. + +=item SCALAR this + +Returns what evaluating the hash in scalar context yields. + +B<Tie::Hash> does not implement this method (but B<Tie::StdHash> +and B<Tie::ExtraHash> do). + +=back + +=head1 Inheriting from B<Tie::StdHash> + +The accessor methods assume that the actual storage for the data in the tied +hash is in the hash referenced by C<tied(%tiedhash)>. Thus overwritten +C<TIEHASH> method should return a hash reference, and the remaining methods +should operate on the hash referenced by the first argument: + + package ReportHash; + our @ISA = 'Tie::StdHash'; + + sub TIEHASH { + my $storage = bless {}, shift; + warn "New ReportHash created, stored in $storage.\n"; + $storage + } + sub STORE { + warn "Storing data with key $_[1] at $_[0].\n"; + $_[0]{$_[1]} = $_[2] + } + + +=head1 Inheriting from B<Tie::ExtraHash> + +The accessor methods assume that the actual storage for the data in the tied +hash is in the hash referenced by C<(tied(%tiedhash))-E<gt>[0]>. Thus overwritten +C<TIEHASH> method should return an array reference with the first +element being a hash reference, and the remaining methods should operate on the +hash C<< %{ $_[0]->[0] } >>: + + package ReportHash; + our @ISA = 'Tie::ExtraHash'; + + sub TIEHASH { + my $class = shift; + my $storage = bless [{}, @_], $class; + warn "New ReportHash created, stored in $storage.\n"; + $storage; + } + sub STORE { + warn "Storing data with key $_[1] at $_[0].\n"; + $_[0][0]{$_[1]} = $_[2] + } + +The default C<TIEHASH> method stores "extra" arguments to tie() starting +from offset 1 in the array referenced by C<tied(%tiedhash)>; this is the +same storage algorithm as in TIEHASH subroutine above. Hence, a typical +package inheriting from B<Tie::ExtraHash> does not need to overwrite this +method. + +=head1 C<SCALAR>, C<UNTIE> and C<DESTROY> + +The methods C<UNTIE> and C<DESTROY> are not defined in B<Tie::Hash>, +B<Tie::StdHash>, or B<Tie::ExtraHash>. Tied hashes do not require +presence of these methods, but if defined, the methods will be called in +proper time, see L<perltie>. + +C<SCALAR> is only defined in B<Tie::StdHash> and B<Tie::ExtraHash>. + +If needed, these methods should be defined by the package inheriting from +B<Tie::Hash>, B<Tie::StdHash>, or B<Tie::ExtraHash>. See L<pertie/"SCALAR"> +to find out what happens when C<SCALAR> does not exist. + +=head1 MORE INFORMATION + +The packages relating to various DBM-related implementations (F<DB_File>, +F<NDBM_File>, etc.) show examples of general tied hashes, as does the +L<Config> module. While these do not utilize B<Tie::Hash>, they serve as +good working examples. + +=cut + +use Carp; +use warnings::register; + +sub new { + my $pkg = shift; + $pkg->TIEHASH(@_); +} + +# Grandfather "new" + +sub TIEHASH { + my $pkg = shift; + if (defined &{"${pkg}::new"}) { + warnings::warnif("WARNING: calling ${pkg}->new since ${pkg}->TIEHASH is missing"); + $pkg->new(@_); + } + else { + croak "$pkg doesn't define a TIEHASH method"; + } +} + +sub EXISTS { + my $pkg = ref $_[0]; + croak "$pkg doesn't define an EXISTS method"; +} + +sub CLEAR { + my $self = shift; + my $key = $self->FIRSTKEY(@_); + my @keys; + + while (defined $key) { + push @keys, $key; + $key = $self->NEXTKEY(@_, $key); + } + foreach $key (@keys) { + $self->DELETE(@_, $key); + } +} + +# The Tie::StdHash package implements standard perl hash behaviour. +# It exists to act as a base class for classes which only wish to +# alter some parts of their behaviour. + +package Tie::StdHash; +# @ISA = qw(Tie::Hash); # would inherit new() only + +sub TIEHASH { bless {}, $_[0] } +sub STORE { $_[0]->{$_[1]} = $_[2] } +sub FETCH { $_[0]->{$_[1]} } +sub FIRSTKEY { my $a = scalar keys %{$_[0]}; each %{$_[0]} } +sub NEXTKEY { each %{$_[0]} } +sub EXISTS { exists $_[0]->{$_[1]} } +sub DELETE { delete $_[0]->{$_[1]} } +sub CLEAR { %{$_[0]} = () } +sub SCALAR { scalar %{$_[0]} } + +package Tie::ExtraHash; + +sub TIEHASH { my $p = shift; bless [{}, @_], $p } +sub STORE { $_[0][0]{$_[1]} = $_[2] } +sub FETCH { $_[0][0]{$_[1]} } +sub FIRSTKEY { my $a = scalar keys %{$_[0][0]}; each %{$_[0][0]} } +sub NEXTKEY { each %{$_[0][0]} } +sub EXISTS { exists $_[0][0]->{$_[1]} } +sub DELETE { delete $_[0][0]->{$_[1]} } +sub CLEAR { %{$_[0][0]} = () } +sub SCALAR { scalar %{$_[0][0]} } + +1; diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32/Registry.pm b/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32/Registry.pm new file mode 100644 index 00000000000..c83fca5a3b1 --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32/Registry.pm @@ -0,0 +1,547 @@ +package Win32::Registry; + +=head1 NAME + +Win32::Registry - accessing the Windows registry [obsolete, use Win32::TieRegistry] + +=head1 SYNOPSIS + + use Win32::Registry; + my $tips; + $::HKEY_LOCAL_MACHINE->Open("SOFTWARE\\Microsoft\\Windows" + ."\\CurrentVersion\\Explorer\\Tips", $tips) + or die "Can't open tips: $^E"; + my ($type, $value); + $tips->QueryValueEx("18", $type, $value) or die "No tip #18: $^E"; + print "Here's a tip: $value\n"; + +=head1 DESCRIPTION + + NOTE: This module provides a very klunky interface to access the + Windows registry, and is not currently being developed actively. It + only exists for backward compatibility with old code that uses it. + For more powerful and flexible ways to access the registry, use + Win32::TieRegistry. + +Win32::Registry provides an object oriented interface to the Windows +Registry. + +The following "root" registry objects are exported to the main:: name +space. Additional keys must be opened by calling the provided methods +on one of these. + + $HKEY_CLASSES_ROOT + $HKEY_CURRENT_USER + $HKEY_LOCAL_MACHINE + $HKEY_USERS + $HKEY_PERFORMANCE_DATA + $HKEY_CURRENT_CONFIG + $HKEY_DYN_DATA + +=cut + +use strict; +require Exporter; +require DynaLoader; +use Win32::WinError; + +require Win32 unless defined &Win32::GetLastError; + +use vars qw($VERSION $AUTOLOAD @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); + +$VERSION = '0.07'; + +@ISA = qw( Exporter DynaLoader ); +@EXPORT = qw( + HKEY_CLASSES_ROOT + HKEY_CURRENT_USER + HKEY_LOCAL_MACHINE + HKEY_PERFORMANCE_DATA + HKEY_CURRENT_CONFIG + HKEY_DYN_DATA + HKEY_USERS + KEY_ALL_ACCESS + KEY_CREATE_LINK + KEY_CREATE_SUB_KEY + KEY_ENUMERATE_SUB_KEYS + KEY_EXECUTE + KEY_NOTIFY + KEY_QUERY_VALUE + KEY_READ + KEY_SET_VALUE + KEY_WRITE + REG_BINARY + REG_CREATED_NEW_KEY + REG_DWORD + REG_DWORD_BIG_ENDIAN + REG_DWORD_LITTLE_ENDIAN + REG_EXPAND_SZ + REG_FULL_RESOURCE_DESCRIPTOR + REG_LEGAL_CHANGE_FILTER + REG_LEGAL_OPTION + REG_LINK + REG_MULTI_SZ + REG_NONE + REG_NOTIFY_CHANGE_ATTRIBUTES + REG_NOTIFY_CHANGE_LAST_SET + REG_NOTIFY_CHANGE_NAME + REG_NOTIFY_CHANGE_SECURITY + REG_OPENED_EXISTING_KEY + REG_OPTION_BACKUP_RESTORE + REG_OPTION_CREATE_LINK + REG_OPTION_NON_VOLATILE + REG_OPTION_RESERVED + REG_OPTION_VOLATILE + REG_REFRESH_HIVE + REG_RESOURCE_LIST + REG_RESOURCE_REQUIREMENTS_LIST + REG_SZ + REG_WHOLE_HIVE_VOLATILE +); + +@EXPORT_OK = qw( + RegCloseKey + RegConnectRegistry + RegCreateKey + RegCreateKeyEx + RegDeleteKey + RegDeleteValue + RegEnumKey + RegEnumValue + RegFlushKey + RegGetKeySecurity + RegLoadKey + RegNotifyChangeKeyValue + RegOpenKey + RegOpenKeyEx + RegQueryInfoKey + RegQueryValue + RegQueryValueEx + RegReplaceKey + RegRestoreKey + RegSaveKey + RegSetKeySecurity + RegSetValue + RegSetValueEx + RegUnLoadKey +); +$EXPORT_TAGS{ALL}= \@EXPORT_OK; + +bootstrap Win32::Registry; + +sub import { + my $pkg = shift; + if ($_[0] && "Win32" eq $_[0]) { + Exporter::export($pkg, "Win32", @EXPORT_OK); + shift; + } + Win32::Registry->export_to_level(1+$Exporter::ExportLevel, $pkg, @_); +} + +####################################################################### +# This AUTOLOAD is used to 'autoload' constants from the constant() +# XS function. If a constant is not found then control is passed +# to the AUTOLOAD in AutoLoader. + +sub AUTOLOAD { + my($constname); + ($constname = $AUTOLOAD) =~ s/.*:://; + #reset $! to zero to reset any current errors. + local $! = 0; + my $val = constant($constname, 0); + if ($! != 0) { + if ($! =~ /Invalid/) { + $AutoLoader::AUTOLOAD = $AUTOLOAD; + goto &AutoLoader::AUTOLOAD; + } + else { + my ($pack,$file,$line) = caller; + die "Unknown constant $constname in Win32::Registry " + . "at $file line $line.\n"; + } + } + eval "sub $AUTOLOAD { $val }"; + goto &$AUTOLOAD; +} + +####################################################################### +# _new is a private constructor, not intended for public use. +# + +sub _new { + my $self; + if ($_[0]) { + $self->{'handle'} = $_[0]; + bless $self; + } + $self; +} + +#define the basic registry objects to be exported. +#these had to be hardwired unfortunately. +# XXX Yuck! + +{ + package main; + use vars qw( + $HKEY_CLASSES_ROOT + $HKEY_CURRENT_USER + $HKEY_LOCAL_MACHINE + $HKEY_USERS + $HKEY_PERFORMANCE_DATA + $HKEY_CURRENT_CONFIG + $HKEY_DYN_DATA + ); +} + +$::HKEY_CLASSES_ROOT = _new(&HKEY_CLASSES_ROOT); +$::HKEY_CURRENT_USER = _new(&HKEY_CURRENT_USER); +$::HKEY_LOCAL_MACHINE = _new(&HKEY_LOCAL_MACHINE); +$::HKEY_USERS = _new(&HKEY_USERS); +$::HKEY_PERFORMANCE_DATA = _new(&HKEY_PERFORMANCE_DATA); +$::HKEY_CURRENT_CONFIG = _new(&HKEY_CURRENT_CONFIG); +$::HKEY_DYN_DATA = _new(&HKEY_DYN_DATA); + +=head2 Methods + +The following methods are supported. Note that subkeys can be +specified as a path name, separated by backslashes (which may +need to be doubled if you put them in double quotes). + +=over 8 + +=item Open + + $reg_obj->Open($sub_key_name, $sub_reg_obj); + +Opens a subkey of a registry object, returning the new registry object +in $sub_reg_obj. + +=cut + +sub Open { + my $self = shift; + die 'usage: $obj->Open($sub_key_name, $sub_reg_obj)' if @_ != 2; + + my ($subkey) = @_; + my ($result,$subhandle); + + $result = RegOpenKey($self->{'handle'},$subkey,$subhandle); + $_[1] = _new($subhandle); + + return 0 unless $_[1]; + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item Close + + $reg_obj->Close(); + +Closes an open registry key. + +=cut + +sub Close { + my $self = shift; + die 'usage: $obj->Close()' if @_ != 0; + + return unless exists $self->{'handle'}; + my $result = RegCloseKey($self->{'handle'}); + if ($result) { + delete $self->{'handle'}; + } + else { + $! = Win32::GetLastError(); + } + return $result; +} + +sub DESTROY { + my $self = shift; + return unless exists $self->{'handle'}; + RegCloseKey($self->{'handle'}); + delete $self->{'handle'}; +} + + +=item Connect + + $reg_obj->Connect($node_name, $new_reg_obj); + +Connects to a remote Registry on the node specified by $node_name, +returning it in $new_reg_obj. Returns false if it fails. + +=cut + +sub Connect { + my $self = shift; + die 'usage: $obj->Connect($node_name, $new_reg_obj)' if @_ != 2; + + my ($node) = @_; + my ($result,$subhandle); + + $result = RegConnectRegistry ($node, $self->{'handle'}, $subhandle); + $_[1] = _new($subhandle); + + return 0 unless $_[1]; + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item Create + + $reg_obj->Create($sub_key_name, $new_reg_obj); + +Opens the subkey specified by $sub_key_name, returning the new registry +object in $new_reg_obj. If the specified subkey doesn't exist, it is +created. + +=cut + +sub Create { + my $self = shift; + die 'usage: $obj->Create($sub_key_name, $new_reg_obj)' if @_ != 2; + + my ($subkey) = @_; + my ($result,$subhandle); + + $result = RegCreateKey($self->{'handle'},$subkey,$subhandle); + $_[1] = _new ($subhandle); + + return 0 unless $_[1]; + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item SetValue + + $reg_obj->SetValue($sub_key_name, $type, $value); + +Sets the default value for a subkey specified by $sub_key_name. + +=cut + +sub SetValue { + my $self = shift; + die 'usage: $obj->SetValue($subkey, $type, $value)' if @_ != 3; + my $result = RegSetValue($self->{'handle'}, @_); + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item SetValueEx + + $reg_obj->SetValueEx($value_name, $reserved, $type, $value); + +Sets the value for the value name identified by $value_name +in the key specified by $reg_obj. + +=cut + +sub SetValueEx { + my $self = shift; + die 'usage: $obj->SetValueEx($value_name, $reserved, $type, $value)' if @_ != 4; + my $result = RegSetValueEx($self->{'handle'}, @_); + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item QueryValue + + $reg_obj->QueryValue($sub_key_name, $value); + +Gets the default value of the subkey specified by $sub_key_name. + +=cut + +sub QueryValue { + my $self = shift; + die 'usage: $obj->QueryValue($sub_key_name, $value)' if @_ != 2; + my $result = RegQueryValue($self->{'handle'}, $_[0], $_[1]); + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item QueryKey + + $reg_obj->QueryKey($classref, $number_of_subkeys, $number_of_values); + +Gets information on a key specified by $reg_obj. + +=cut + +sub QueryKey { + my $garbage; + my $self = shift; + die 'usage: $obj->QueryKey($classref, $number_of_subkeys, $number_of_values)' + if @_ != 3; + + my $result = RegQueryInfoKey($self->{'handle'}, $_[0], + $garbage, $garbage, $_[1], + $garbage, $garbage, $_[2], + $garbage, $garbage, $garbage, $garbage); + + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item QueryValueEx + + $reg_obj->QueryValueEx($value_name, $type, $value); + +Gets the value for the value name identified by $value_name +in the key specified by $reg_obj. + +=cut + +sub QueryValueEx { + my $self = shift; + die 'usage: $obj->QueryValueEx($value_name, $type, $value)' if @_ != 3; + my $result = RegQueryValueEx($self->{'handle'}, $_[0], undef, $_[1], $_[2]); + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item GetKeys + + my @keys; + $reg_obj->GetKeys(\@keys); + +Populates the supplied array reference with the names of all the keys +within the registry object $reg_obj. + +=cut + +sub GetKeys { + my $self = shift; + die 'usage: $obj->GetKeys($arrayref)' if @_ != 1 or ref($_[0]) ne 'ARRAY'; + + my ($result, $i, $keyname); + $keyname = "DummyVal"; + $i = 0; + $result = 1; + + while ( $result ) { + $result = RegEnumKey( $self->{'handle'},$i++, $keyname ); + if ($result) { + push( @{$_[0]}, $keyname ); + } + } + return(1); +} + +=item GetValues + + my %values; + $reg_obj->GetValues(\%values); + +Populates the supplied hash reference with entries of the form + + $value_name => [ $value_name, $type, $data ] + +for each value in the registry object $reg_obj. + +=cut + +sub GetValues { + my $self = shift; + die 'usage: $obj->GetValues($hashref)' if @_ != 1; + + my ($result,$name,$type,$data,$i); + $name = "DummyVal"; + $i = 0; + while ( $result=RegEnumValue( $self->{'handle'}, + $i++, + $name, + undef, + $type, + $data )) + { + $_[0]->{$name} = [ $name, $type, $data ]; + } + return(1); +} + +=item DeleteKey + + $reg_obj->DeleteKey($sub_key_name); + +Deletes a subkey specified by $sub_key_name from the registry. + +=cut + +sub DeleteKey { + my $self = shift; + die 'usage: $obj->DeleteKey($sub_key_name)' if @_ != 1; + my $result = RegDeleteKey($self->{'handle'}, @_); + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item DeleteValue + + $reg_obj->DeleteValue($value_name); + +Deletes a value identified by $value_name from the registry. + +=cut + +sub DeleteValue { + my $self = shift; + die 'usage: $obj->DeleteValue($value_name)' if @_ != 1; + my $result = RegDeleteValue($self->{'handle'}, @_); + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item Save + + $reg_obj->Save($filename); + +Saves the hive specified by $reg_obj to a file. + +=cut + +sub Save { + my $self = shift; + die 'usage: $obj->Save($filename)' if @_ != 1; + my $result = RegSaveKey($self->{'handle'}, @_); + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item Load + + $reg_obj->Load($sub_key_name, $file_name); + +Loads a key specified by $sub_key_name from a file. + +=cut + +sub Load { + my $self = shift; + die 'usage: $obj->Load($sub_key_name, $file_name)' if @_ != 2; + my $result = RegLoadKey($self->{'handle'}, @_); + $! = Win32::GetLastError() unless $result; + return $result; +} + +=item UnLoad + + $reg_obj->Unload($sub_key_name); + +Unloads a registry hive. + +=cut + +sub UnLoad { + my $self = shift; + die 'usage: $obj->UnLoad($sub_key_name)' if @_ != 1; + my $result = RegUnLoadKey($self->{'handle'}, @_); + $! = Win32::GetLastError() unless $result; + return $result; +} + +1; +__END__ diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32/TieRegistry.pm b/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32/TieRegistry.pm new file mode 100644 index 00000000000..0abbbddb6b8 --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32/TieRegistry.pm @@ -0,0 +1,3801 @@ +# Win32/TieRegistry.pm -- Perl module to easily use a Registry +# (on Win32 systems so far). +# by Tye McQueen, tye@metronet.com, see http://www.metronet.com/~tye/. + +# +# Skip to "=head" line for user documentation. +# + + +package Win32::TieRegistry; + + +use strict; +use vars qw( $PACK $VERSION @ISA @EXPORT @EXPORT_OK ); + +$PACK= "Win32::TieRegistry"; # Used in error messages. +$VERSION= '0.26'; + + +use Carp; + +require Tie::Hash; +@ISA= qw(Tie::Hash); + +# Required other modules: +use Win32API::Registry 0.12 qw( :KEY_ :HKEY_ :REG_ ); + +#Optional other modules: +use vars qw( $_NoMoreItems $_FileNotFound $_TooSmall $_MoreData $_SetDualVar ); + +if( eval { require Win32::WinError } ) { + $_NoMoreItems= Win32::WinError::constant("ERROR_NO_MORE_ITEMS",0); + $_FileNotFound= Win32::WinError::constant("ERROR_FILE_NOT_FOUND",0); + $_TooSmall= Win32::WinError::constant("ERROR_INSUFFICIENT_BUFFER",0); + $_MoreData= Win32::WinError::constant("ERROR_MORE_DATA",0); +} else { + $_NoMoreItems= "^No more data"; + $_FileNotFound= "cannot find the file"; + $_TooSmall= " data area passed to "; + $_MoreData= "^more data is avail"; +} +if( $_SetDualVar= eval { require SetDualVar } ) { + import SetDualVar; +} + + +#Implementation details: +# When opened: +# HANDLE long; actual handle value +# MACHINE string; name of remote machine ("" if local) +# PATH list ref; machine-relative full path for this key: +# ["LMachine","System","Disk"] +# ["HKEY_LOCAL_MACHINE","System","Disk"] +# DELIM char; delimiter used to separate subkeys (def="\\") +# OS_DELIM char; always "\\" for Win32 +# ACCESS long; usually KEY_ALL_ACCESS, perhaps KEY_READ, etc. +# ROOTS string; var name for "Lmachine"->HKEY_LOCAL_MACHINE map +# FLAGS int; bits to control certain options +# Often: +# VALUES ref to list of value names (data/type never cached) +# SUBKEYS ref to list of subkey names +# SUBCLASSES ref to list of subkey classes +# SUBTIMES ref to list of subkey write times +# MEMBERS ref to list of subkey_name.DELIM's, DELIM.value_name's +# MEMBHASH hash ref to with MEMBERS as keys and 1's as values +# Once Key "Info" requested: +# Class CntSubKeys CntValues MaxSubKeyLen MaxSubClassLen +# MaxValNameLen MaxValDataLen SecurityLen LastWrite +# If is tied to a hash and iterating over key values: +# PREVIDX int; index of last MEMBERS element return +# If is the key object returned by Load(): +# UNLOADME list ref; information about Load()ed key +# If is a subkey of a "loaded" key other than the one returned by Load(): +# DEPENDON obj ref; object that can't be destroyed before us + + +#Package-local variables: + +# Option flag bits: +use vars qw( $Flag_ArrVal $Flag_TieVal $Flag_DualTyp $Flag_DualBin + $Flag_FastDel $Flag_HexDWord $Flag_Split $Flag_FixNulls ); +$Flag_ArrVal= 0x0001; +$Flag_TieVal= 0x0002; +$Flag_FastDel= 0x0004; +$Flag_HexDWord= 0x0008; +$Flag_Split= 0x0010; +$Flag_DualTyp= 0x0020; +$Flag_DualBin= 0x0040; +$Flag_FixNulls= 0x0080; + + +use vars qw( $RegObj %_Roots %RegHash $Registry ); + +# Short-hand for HKEY_* constants: +%_Roots= ( + "Classes" => HKEY_CLASSES_ROOT, + "CUser" => HKEY_CURRENT_USER, + "LMachine" => HKEY_LOCAL_MACHINE, + "Users" => HKEY_USERS, + "PerfData" => HKEY_PERFORMANCE_DATA, # Too picky to be useful + "CConfig" => HKEY_CURRENT_CONFIG, + "DynData" => HKEY_DYN_DATA, # Too picky to be useful +); + +# Basic master Registry object: +$RegObj= {}; +@$RegObj{qw( HANDLE MACHINE PATH DELIM OS_DELIM ACCESS FLAGS ROOTS )}= ( + "NONE", "", [], "\\", "\\", + KEY_READ|KEY_WRITE, $Flag_HexDWord|$Flag_FixNulls, "${PACK}::_Roots" ); +$RegObj->{FLAGS} |= $Flag_DualTyp|$Flag_DualBin if $_SetDualVar; +bless $RegObj; + +# Fill cache for master Registry object: +@$RegObj{qw( VALUES SUBKEYS SUBCLASSES SUBTIMES )}= ( + [], [ keys(%_Roots) ], [], [] ); +grep( s#$#$RegObj->{DELIM}#, + @{ $RegObj->{MEMBERS}= [ @{$RegObj->{SUBKEYS}} ] } ); +@$RegObj{qw( Class MaxSubKeyLen MaxSubClassLen MaxValNameLen + MaxValDataLen SecurityLen LastWrite CntSubKeys CntValues )}= + ( "", 0, 0, 0, 0, 0, 0, 0, 0 ); + +# Create master Registry tied hash: +$RegObj->Tie( \%RegHash ); + +# Create master Registry combination object and tied hash reference: +$Registry= \%RegHash; +bless $Registry; + + +# Preloaded methods go here. + + +# Map option names to name of subroutine that controls that option: +use vars qw( @_opt_subs %_opt_subs ); +@_opt_subs= qw( Delimiter ArrayValues TieValues SplitMultis DWordsToHex + FastDelete FixSzNulls DualTypes DualBinVals AllowLoad AllowSave ); +@_opt_subs{@_opt_subs}= @_opt_subs; + +sub import +{ + my $pkg= shift(@_); + my $level= $Exporter::ExportLevel; + my $expto= caller($level); + my @export= (); + my @consts= (); + my $registry= $Registry->Clone; + local( $_ ); + while( @_ ) { + $_= shift(@_); + if( /^\$(\w+::)*\w+$/ ) { + push( @export, "ObjVar" ) if /^\$RegObj$/; + push( @export, $_ ); + } elsif( /^\%(\w+::)*\w+$/ ) { + push( @export, $_ ); + } elsif( /^[$%]/ ) { + croak "${PACK}->import: Invalid variable name ($_)"; + } elsif( /^:/ || /^(H?KEY|REG)_/ ) { + push( @consts, $_ ); + } elsif( ! @_ ) { + croak "${PACK}->import: Missing argument after option ($_)"; + } elsif( exists $_opt_subs{$_} ) { + $_= $_opt_subs{$_}; + $registry->$_( shift(@_) ); + } elsif( /^TiedRef$/ ) { + $_= shift(@_); + if( ! ref($_) && /^(\$?)(\w+::)*\w+$/ ) { + $_= '$'.$_ unless '$' eq $1; + } elsif( "SCALAR" ne ref($_) ) { + croak "${PACK}->import: Invalid var after TiedRef ($_)"; + } + push( @export, $_ ); + } elsif( /^TiedHash$/ ) { + $_= shift(@_); + if( ! ref($_) && /^(\%?)(\w+::)*\w+$/ ) { + $_= '%'.$_ unless '%' eq $1; + } elsif( "HASH" ne ref($_) ) { + croak "${PACK}->import: Invalid var after TiedHash ($_)"; + } + push( @export, $_ ); + } elsif( /^ObjectRef$/ ) { + $_= shift(@_); + if( ! ref($_) && /^(\$?)(\w+::)*\w+$/ ) { + push( @export, "ObjVar" ); + $_= '$'.$_ unless '$' eq $1; + } elsif( "SCALAR" eq ref($_) ) { + push( @export, "ObjRef" ); + } else { + croak "${PACK}->import: Invalid var after ObjectRef ($_)"; + } + push( @export, $_ ); + } elsif( /^ExportLevel$/ ) { + $level= shift(@_); + $expto= caller($level); + } elsif( /^ExportTo$/ ) { + undef $level; + $expto= caller($level); + } else { + croak "${PACK}->import: Invalid option ($_)"; + } + } + Win32API::Registry->export( $expto, @consts ) if @consts; + @export= ('$Registry') unless @export; + while( @export ) { + $_= shift( @export ); + if( /^\$((?:\w+::)*)(\w+)$/ ) { + my( $pack, $sym )= ( $1, $2 ); + $pack= $expto unless defined($pack) && "" ne $pack; + no strict 'refs'; + *{"${pack}::$sym"}= \${"${pack}::$sym"}; + ${"${pack}::$sym"}= $registry; + } elsif( /^\%((?:\w+::)*)(\w+)$/ ) { + my( $pack, $sym )= ( $1, $2 ); + $pack= $expto unless defined($pack) && "" ne $pack; + no strict 'refs'; + *{"${pack}::$sym"}= \%{"${pack}::$sym"}; + $registry->Tie( \%{"${pack}::$sym"} ); + } elsif( "SCALAR" eq ref($_) ) { + $$_= $registry; + } elsif( "HASH" eq ref($_) ) { + $registry->Tie( $_ ); + } elsif( /^ObjVar$/ ) { + $_= shift( @_ ); + /^\$((?:\w+::)*)(\w+)$/; + my( $pack, $sym )= ( $1, $2 ); + $pack= $expto unless defined($pack) && "" ne $pack; + no strict 'refs'; + *{"${pack}::$sym"}= \${"${pack}::$sym"}; + ${"${pack}::$sym"}= $registry->ObjectRef; + } elsif( /^ObjRef$/ ) { + ${shift(@_)}= $registry->ObjectRef; + } else { + die "Impossible var to export ($_)"; + } + } +} + + +use vars qw( @_new_Opts %_new_Opts ); +@_new_Opts= qw( ACCESS DELIM MACHINE DEPENDON ); +@_new_Opts{@_new_Opts}= (1) x @_new_Opts; + +sub _new +{ + my $this= shift( @_ ); + $this= tied(%$this) if ref($this) && tied(%$this); + my $class= ref($this) || $this; + my $self= {}; + my( $handle, $rpath, $opts )= @_; + if( @_ < 2 || "ARRAY" ne ref($rpath) || 3 < @_ + || 3 == @_ && "HASH" ne ref($opts) ) { + croak "Usage: ${PACK}->_new( \$handle, \\\@path, {OPT=>VAL,...} );\n", + " options: @_new_Opts\nCalled"; + } + @$self{qw( HANDLE PATH )}= ( $handle, $rpath ); + @$self{qw( MACHINE ACCESS DELIM OS_DELIM ROOTS FLAGS )}= + ( $this->Machine, $this->Access, $this->Delimiter, + $this->OS_Delimiter, $this->_Roots, $this->_Flags ); + if( ref($opts) ) { + my @err= grep( ! $_new_Opts{$_}, keys(%$opts) ); + @err and croak "${PACK}->_new: Invalid options (@err)"; + @$self{ keys(%$opts) }= values(%$opts); + } + bless $self, $class; + return $self; +} + + +sub _split +{ + my $self= shift( @_ ); + $self= tied(%$self) if tied(%$self); + my $path= shift( @_ ); + my $delim= @_ ? shift(@_) : $self->Delimiter; + my $list= [ split( /\Q$delim/, $path ) ]; + return $list; +} + + +sub _rootKey +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $keyPath= shift(@_); + my $delim= @_ ? shift(@_) : $self->Delimiter; + my( $root, $subPath ); + if( "ARRAY" eq ref($keyPath) ) { + $subPath= $keyPath; + } else { + $subPath= $self->_split( $keyPath, $delim ); + } + $root= shift( @$subPath ); + if( $root =~ /^HKEY_/ ) { + my $handle= Win32API::Registry::constant($root,0); + $handle or croak "Invalid HKEY_ constant ($root): $!"; + return( $self->_new( $handle, [$root], {DELIM=>$delim} ), + $subPath ); + } elsif( $root =~ /^([-+]|0x)?\d/ ) { + return( $self->_new( $root, [sprintf("0x%lX",$root)], + {DELIM=>$delim} ), + $subPath ); + } else { + my $roots= $self->Roots; + if( $roots->{$root} ) { + return( $self->_new( $roots->{$root}, [$root], {DELIM=>$delim} ), + $subPath ); + } + croak "No such root key ($root)"; + } +} + + +sub _open +{ + my $this= shift(@_); + $this= tied(%$this) if ref($this) && tied(%$this); + my $subPath= shift(@_); + my $sam= @_ ? shift(@_) : $this->Access; + my $subKey= join( $this->OS_Delimiter, @$subPath ); + my $handle= 0; + $this->RegOpenKeyEx( $subKey, 0, $sam, $handle ) + or return (); + return $this->_new( $handle, [ @{$this->_Path}, @$subPath ], + { ACCESS=>$sam, ( defined($this->{UNLOADME}) ? ("DEPENDON",$this) + : defined($this->{DEPENDON}) ? ("DEPENDON",$this->{DEPENDON}) : () ) + } ); +} + + +sub ObjectRef +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + return $self; +} + + +sub _constant +{ + my( $name, $desc )= @_; + my $value= Win32API::Registry::constant( $name, 0 ); + my $func= (caller(1))[3]; + if( 0 == $value ) { + if( $! =~ /invalid/i ) { + croak "$func: Invalid $desc ($name)"; + } elsif( 0 != $! ) { + croak "$func: \u$desc ($name) not support on this platform"; + } + } + return $value; +} + + +sub _connect +{ + my $this= shift(@_); + $this= tied(%$this) if ref($this) && tied(%$this); + my $subPath= pop(@_); + $subPath= $this->_split( $subPath ) unless ref($subPath); + my $machine= @_ ? shift(@_) : shift(@$subPath); + my $handle= 0; + my( $temp )= $this->_rootKey( [@$subPath] ); + $temp->RegConnectRegistry( $machine, $temp->Handle, $handle ) + or return (); + my $self= $this->_new( $handle, [shift(@$subPath)], {MACHINE=>$machine} ); + return( $self, $subPath ); +} + + +use vars qw( @Connect_Opts %Connect_Opts ); +@Connect_Opts= qw(Access Delimiter); +@Connect_Opts{@Connect_Opts}= (1) x @Connect_Opts; + +sub Connect +{ + my $this= shift(@_); + my $tied= ref($this) && tied(%$this); + $this= tied(%$this) if $tied; + my( $machine, $key, $opts )= @_; + my $delim= ""; + my $sam; + my $subPath; + if( @_ < 2 || 3 < @_ + || 3 == @_ && "HASH" ne ref($opts) ) { + croak "Usage: \$obj= ${PACK}->Connect(", + " \$Machine, \$subKey, { OPT=>VAL,... } );\n", + " options: @Connect_Opts\nCalled"; + } + if( ref($opts) ) { + my @err= grep( ! $Connect_Opts{$_}, keys(%$opts) ); + @err and croak "${PACK}->Connect: Invalid options (@err)"; + } + $delim= "$opts->{Delimiter}" if defined($opts->{Delimiter}); + $delim= $this->Delimiter if "" eq $delim; + $sam= defined($opts->{Access}) ? $opts->{Access} : $this->Access; + $sam= _constant($sam,"key access type") if $sam =~ /^KEY_/; + ( $this, $subPath )= $this->_connect( $machine, $key ); + return () unless defined($this); + my $self= $this->_open( $subPath, $sam ); + return () unless defined($self); + $self->Delimiter( $delim ); + $self= $self->TiedRef if $tied; + return $self; +} + + +my @_newVirtual_keys= qw( MEMBERS VALUES SUBKEYS SUBTIMES SUBCLASSES + Class SecurityLen LastWrite CntValues CntSubKeys + MaxValNameLen MaxValDataLen MaxSubKeyLen MaxSubClassLen ); + +sub _newVirtual +{ + my $self= shift(@_); + my( $rPath, $root, $opts )= @_; + my $new= $self->_new( "NONE", $rPath, $opts ) + or return (); + @{$new}{@_newVirtual_keys}= @{$root->ObjectRef}{@_newVirtual_keys}; + return $new; +} + + +#$key= new Win32::TieRegistry "LMachine/System/Disk"; +#$key= new Win32::TieRegistry "//Server1/LMachine/System/Disk"; +#Win32::TieRegistry->new( HKEY_LOCAL_MACHINE, {DELIM=>"/",ACCESS=>KEY_READ} ); +#Win32::TieRegistry->new( [ HKEY_LOCAL_MACHINE, ".../..." ], {DELIM=>$DELIM} ); +#$key->new( ... ); + +use vars qw( @new_Opts %new_Opts ); +@new_Opts= qw(Access Delimiter); +@new_Opts{@new_Opts}= (1) x @new_Opts; + +sub new +{ + my $this= shift( @_ ); + $this= tied(%$this) if ref($this) && tied(%$this); + if( ! ref($this) ) { + no strict "refs"; + my $self= ${"${this}::Registry"}; + croak "${this}->new failed since ${PACK}::new sees that ", + "\$${this}::Registry is not an object." + if ! ref($self); + $this= $self->Clone; + } + my( $subKey, $opts )= @_; + my $delim= ""; + my $dlen; + my $sam; + my $subPath; + if( @_ < 1 || 2 < @_ + || 2 == @_ && "HASH" ne ref($opts) ) { + croak "Usage: \$obj= ${PACK}->new( \$subKey, { OPT=>VAL,... } );\n", + " options: @new_Opts\nCalled"; + } + if( defined($opts) ) { + my @err= grep( ! $new_Opts{$_}, keys(%$opts) ); + @err and die "${PACK}->new: Invalid options (@err)"; + } + $delim= "$opts->{Delimiter}" if defined($opts->{Delimiter}); + $delim= $this->Delimiter if "" eq $delim; + $dlen= length($delim); + $sam= defined($opts->{Access}) ? $opts->{Access} : $this->Access; + $sam= _constant($sam,"key access type") if $sam =~ /^KEY_/; + if( "ARRAY" eq ref($subKey) ) { + $subPath= $subKey; + if( "NONE" eq $this->Handle && @$subPath ) { + ( $this, $subPath )= $this->_rootKey( $subPath ); + } + } elsif( $delim x 2 eq substr($subKey,0,2*$dlen) ) { + my $path= $this->_split( substr($subKey,2*$dlen), $delim ); + my $mach= shift(@$path); + if( ! @$path ) { + return $this->_newVirtual( $path, $Registry, + {MACHINE=>$mach,DELIM=>$delim,ACCESS=>$sam} ); + } + ( $this, $subPath )= $this->_connect( $mach, $path ); + return () if ! defined($this); + if( 0 == @$subPath ) { + $this->Delimiter( $delim ); + return $this; + } + } elsif( $delim eq substr($subKey,0,$dlen) ) { + ( $this, $subPath )= $this->_rootKey( substr($subKey,$dlen), $delim ); + } elsif( "NONE" eq $this->Handle && "" ne $subKey ) { + my( $mach )= $this->Machine; + if( $mach ) { + ( $this, $subPath )= $this->_connect( $mach, $subKey ); + } else { + ( $this, $subPath )= $this->_rootKey( $subKey, $delim ); + } + } else { + $subPath= $this->_split( $subKey, $delim ); + } + return () unless defined($this); + if( 0 == @$subPath && "NONE" eq $this->Handle ) { + return $this->_newVirtual( $this->_Path, $this, + { DELIM=>$delim, ACCESS=>$sam } ); + } + my $self= $this->_open( $subPath, $sam ); + return () unless defined($self); + $self->Delimiter( $delim ); + return $self; +} + + +sub Open +{ + my $self= shift(@_); + my $tied= ref($self) && tied(%$self); + $self= tied(%$self) if $tied; + $self= $self->new( @_ ); + $self= $self->TiedRef if defined($self) && $tied; + return $self; +} + + +sub Clone +{ + my $self= shift( @_ ); + my $new= $self->Open(""); + return $new; +} + + +{ my @flush; + sub Flush + { + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my( $flush )= shift(@_); + @_ and croak "Usage: \$key->Flush( \$bFlush );"; + return 0 if "NONE" eq $self->Handle; + @flush= qw( VALUES SUBKEYS SUBCLASSES SUBTIMES MEMBERS Class + CntSubKeys CntValues MaxSubKeyLen MaxSubClassLen + MaxValNameLen MaxValDataLen SecurityLen LastWrite PREVIDX ) + unless @flush; + delete( @$self{@flush} ); + if( defined($flush) && $flush ) { + return $self->RegFlushKey(); + } else { + return 1; + } + } +} + + +sub _DualVal +{ + my( $hRef, $num )= @_; + if( $_SetDualVar && $$hRef{$num} ) { + &SetDualVar( $num, "$$hRef{$num}", 0+$num ); + } + return $num; +} + + +use vars qw( @_RegDataTypes %_RegDataTypes ); +@_RegDataTypes= qw( REG_SZ REG_EXPAND_SZ REG_BINARY REG_LINK REG_MULTI_SZ + REG_DWORD_LITTLE_ENDIAN REG_DWORD_BIG_ENDIAN REG_DWORD + REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR + REG_RESOURCE_REQUIREMENTS_LIST REG_NONE ); +# Make sure that REG_DWORD appears _after_ other REG_DWORD_* +# items above and that REG_NONE appears _last_. +foreach( @_RegDataTypes ) { + $_RegDataTypes{Win32API::Registry::constant($_,0)}= $_; +} + +sub GetValue +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + 1 == @_ or croak "Usage: (\$data,\$type)= \$key->GetValue('ValName');"; + my( $valName )= @_; + my( $valType, $valData, $dLen )= (0,"",0); + return () if "NONE" eq $self->Handle; + $self->RegQueryValueEx( $valName, [], $valType, $valData, + $dLen= ( defined($self->{MaxValDataLen}) ? $self->{MaxValDataLen} : 0 ) + ) or return (); + if( REG_DWORD == $valType ) { + my $val= unpack("L",$valData); + $valData= sprintf "0x%08.8lX", $val if $self->DWordsToHex; + &SetDualVar( $valData, $valData, $val ) if $self->DualBinVals + } elsif( REG_BINARY == $valType && length($valData) <= 4 ) { + &SetDualVar( $valData, $valData, hex reverse unpack("h*",$valData) ) + if $self->DualBinVals; + } elsif( ( REG_SZ == $valType || REG_EXPAND_SZ == $valType ) + && $self->FixSzNulls ) { + substr($valData,-1)= "" if "\0" eq substr($valData,-1); + } elsif( REG_MULTI_SZ == $valType && $self->SplitMultis ) { + ## $valData =~ s/\0\0$//; # Why does this often fail?? + substr($valData,-2)= "" if "\0\0" eq substr($valData,-2); + $valData= [ split( /\0/, $valData, -1 ) ] + } + if( ! wantarray ) { + return $valData; + } elsif( ! $self->DualTypes ) { + return( $valData, $valType ); + } else { + return( $valData, _DualVal( \%_RegDataTypes, $valType ) ); + } +} + + +sub _ErrNum +{ + # return $^E; + return Win32::GetLastError(); +} + + +sub _ErrMsg +{ + # return $^E; + return Win32::FormatMessage( Win32::GetLastError() ); +} + +sub _Err +{ + my $err; + # return $^E; + return _ErrMsg if ! $_SetDualVar; + return &SetDualVar( $err, _ErrMsg, _ErrNum ); +} + +sub _NoMoreItems +{ + return + $_NoMoreItems =~ /^\d/ + ? _ErrNum == $_NoMoreItems + : _ErrMsg =~ /$_NoMoreItems/io; +} + + +sub _FileNotFound +{ + return + $_FileNotFound =~ /^\d/ + ? _ErrNum == $_FileNotFound + : _ErrMsg =~ /$_FileNotFound/io; +} + + +sub _TooSmall +{ + return + $_TooSmall =~ /^\d/ + ? _ErrNum == $_TooSmall + : _ErrMsg =~ /$_TooSmall/io; +} + + +sub _MoreData +{ + return + $_MoreData =~ /^\d/ + ? _ErrNum == $_MoreData + : _ErrMsg =~ /$_MoreData/io; +} + + +sub _enumValues +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my( @names )= (); + my $pos= 0; + my $name= ""; + my $nlen= 1+$self->Information("MaxValNameLen"); + while( $self->RegEnumValue($pos++,$name,$nlen,[],[],[],[]) ) { + push( @names, $name ); + } + if( ! _NoMoreItems() ) { + return (); + } + $self->{VALUES}= \@names; + return 1; +} + + +sub ValueNames +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \@names= \$key->ValueNames;"; + $self->_enumValues unless $self->{VALUES}; + return @{$self->{VALUES}}; +} + + +sub _enumSubKeys +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my( @subkeys, @classes, @times )= (); + my $pos= 0; + my( $subkey, $class, $time )= ("","",""); + my( $namSiz, $clsSiz )= $self->Information( + qw( MaxSubKeyLen MaxSubClassLen )); + $namSiz++; $clsSiz++; + while( $self->RegEnumKeyEx( + $pos++, $subkey, $namSiz, [], $class, $clsSiz, $time ) ) { + push( @subkeys, $subkey ); + push( @classes, $class ); + push( @times, $time ); + } + if( ! _NoMoreItems() ) { + return (); + } + $self->{SUBKEYS}= \@subkeys; + $self->{SUBCLASSES}= \@classes; + $self->{SUBTIMES}= \@times; + return 1; +} + + +sub SubKeyNames +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \@names= \$key->SubKeyNames;"; + $self->_enumSubKeys unless $self->{SUBKEYS}; + return @{$self->{SUBKEYS}}; +} + + +sub SubKeyClasses +{ + my $self= shift(@_); + @_ and croak "Usage: \@classes= \$key->SubKeyClasses;"; + $self->_enumSubKeys unless $self->{SUBCLASSES}; + return @{$self->{SUBCLASSES}}; +} + + +sub SubKeyTimes +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \@times= \$key->SubKeyTimes;"; + $self->_enumSubKeys unless $self->{SUBTIMES}; + return @{$self->{SUBTIMES}}; +} + + +sub _MemberNames +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \$arrayRef= \$key->_MemberNames;"; + if( ! $self->{MEMBERS} ) { + $self->_enumValues unless $self->{VALUES}; + $self->_enumSubKeys unless $self->{SUBKEYS}; + my( @members )= ( map( $_.$self->{DELIM}, @{$self->{SUBKEYS}} ), + map( $self->{DELIM}.$_, @{$self->{VALUES}} ) ); + $self->{MEMBERS}= \@members; + } + return $self->{MEMBERS}; +} + + +sub _MembersHash +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \$hashRef= \$key->_MembersHash;"; + if( ! $self->{MEMBHASH} ) { + my $aRef= $self->_MemberNames; + $self->{MEMBHASH}= {}; + @{$self->{MEMBHASH}}{@$aRef}= (1) x @$aRef; + } + return $self->{MEMBHASH}; +} + + +sub MemberNames +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \@members= \$key->MemberNames;"; + return @{$self->_MemberNames}; +} + + +sub Information +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my( $time, $nkeys, $nvals, $xsec, $xkey, $xcls, $xname, $xdata )= + ("",0,0,0,0,0,0,0); + my $clen= 8; + if( ! $self->RegQueryInfoKey( [], [], $nkeys, $xkey, $xcls, + $nvals, $xname, $xdata, $xsec, $time ) ) { + return (); + } + if( defined($self->{Class}) ) { + $clen= length($self->{Class}); + } else { + $self->{Class}= ""; + } + while( ! $self->RegQueryInfoKey( $self->{Class}, $clen, + [],[],[],[],[],[],[],[],[]) + && _MoreData ) { + $clen *= 2; + } + my( %info ); + @info{ qw( LastWrite CntSubKeys CntValues SecurityLen + MaxValDataLen MaxSubKeyLen MaxSubClassLen MaxValNameLen ) + }= ( $time, $nkeys, $nvals, $xsec, + $xdata, $xkey, $xcls, $xname ); + if( @_ ) { + my( %check ); + @check{keys(%info)}= keys(%info); + my( @err )= grep( ! $check{$_}, @_ ); + if( @err ) { + croak "${PACK}::Information- Invalid info requested (@err)"; + } + return @info{@_}; + } else { + return %info; + } +} + + +sub Delimiter +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + $self= $RegObj unless ref($self); + my( $oldDelim )= $self->{DELIM}; + if( 1 == @_ && "" ne "$_[0]" ) { + delete $self->{MEMBERS}; + delete $self->{MEMBHASH}; + $self->{DELIM}= "$_[0]"; + } elsif( 0 != @_ ) { + croak "Usage: \$oldDelim= \$key->Delimiter(\$newDelim);"; + } + return $oldDelim; +} + + +sub Handle +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \$handle= \$key->Handle;"; + $self= $RegObj unless ref($self); + return $self->{HANDLE}; +} + + +sub Path +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \$path= \$key->Path;"; + my $delim= $self->{DELIM}; + $self= $RegObj unless ref($self); + if( "" eq $self->{MACHINE} ) { + return( $delim . join( $delim, @{$self->{PATH}} ) . $delim ); + } else { + return( $delim x 2 + . join( $delim, $self->{MACHINE}, @{$self->{PATH}} ) + . $delim ); + } +} + + +sub _Path +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \$arrRef= \$key->_Path;"; + $self= $RegObj unless ref($self); + return $self->{PATH}; +} + + +sub Machine +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \$machine= \$key->Machine;"; + $self= $RegObj unless ref($self); + return $self->{MACHINE}; +} + + +sub Access +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \$access= \$key->Access;"; + $self= $RegObj unless ref($self); + return $self->{ACCESS}; +} + + +sub OS_Delimiter +{ + my $self= shift(@_); + @_ and croak "Usage: \$backslash= \$key->OS_Delimiter;"; + return $self->{OS_DELIM}; +} + + +sub _Roots +{ + my $self= shift(@_); + $self= tied(%$self) if ref($self) && tied(%$self); + @_ and croak "Usage: \$varName= \$key->_Roots;"; + $self= $RegObj unless ref($self); + return $self->{ROOTS}; +} + + +sub Roots +{ + my $self= shift(@_); + $self= tied(%$self) if ref($self) && tied(%$self); + @_ and croak "Usage: \$hashRef= \$key->Roots;"; + $self= $RegObj unless ref($self); + return eval "\\%$self->{ROOTS}"; +} + + +sub TIEHASH +{ + my( $this )= shift(@_); + $this= tied(%$this) if ref($this) && tied(%$this); + my( $key )= @_; + if( 1 == @_ && ref($key) && "$key" =~ /=/ ) { + return $key; # $key is already an object (blessed reference). + } + return $this->new( @_ ); +} + + +sub Tie +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my( $hRef )= @_; + if( 1 != @_ || ! ref($hRef) || "$hRef" !~ /(^|=)HASH\(/ ) { + croak "Usage: \$key->Tie(\\\%hash);"; + } + return tie %$hRef, ref($self), $self; +} + + +sub TiedRef +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $hRef= @_ ? shift(@_) : {}; + return () if ! defined($self); + $self->Tie($hRef); + bless $hRef, ref($self); + return $hRef; +} + + +sub _Flags +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlags= $self->{FLAGS}; + if( 1 == @_ ) { + $self->{FLAGS}= shift(@_); + } elsif( 0 != @_ ) { + croak "Usage: \$oldBits= \$key->_Flags(\$newBits);"; + } + return $oldFlags; +} + + +sub ArrayValues +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlag= $Flag_ArrVal == ( $Flag_ArrVal & $self->{FLAGS} ); + if( 1 == @_ ) { + my $bool= shift(@_); + if( $bool ) { + $self->{FLAGS} |= $Flag_ArrVal; + } else { + $self->{FLAGS} &= ~( $Flag_ArrVal | $Flag_TieVal ); + } + } elsif( 0 != @_ ) { + croak "Usage: \$oldBool= \$key->ArrayValues(\$newBool);"; + } + return $oldFlag; +} + + +sub TieValues +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlag= $Flag_TieVal == ( $Flag_TieVal & $self->{FLAGS} ); + if( 1 == @_ ) { + my $bool= shift(@_); + if( $bool ) { + croak "${PACK}->TieValues cannot be enabled with this version"; + $self->{FLAGS} |= $Flag_TieVal; + } else { + $self->{FLAGS} &= ~$Flag_TieVal; + } + } elsif( 0 != @_ ) { + croak "Usage: \$oldBool= \$key->TieValues(\$newBool);"; + } + return $oldFlag; +} + + +sub FastDelete +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlag= $Flag_FastDel == ( $Flag_FastDel & $self->{FLAGS} ); + if( 1 == @_ ) { + my $bool= shift(@_); + if( $bool ) { + $self->{FLAGS} |= $Flag_FastDel; + } else { + $self->{FLAGS} &= ~$Flag_FastDel; + } + } elsif( 0 != @_ ) { + croak "Usage: \$oldBool= \$key->FastDelete(\$newBool);"; + } + return $oldFlag; +} + + +sub SplitMultis +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlag= $Flag_Split == ( $Flag_Split & $self->{FLAGS} ); + if( 1 == @_ ) { + my $bool= shift(@_); + if( $bool ) { + $self->{FLAGS} |= $Flag_Split; + } else { + $self->{FLAGS} &= ~$Flag_Split; + } + } elsif( 0 != @_ ) { + croak "Usage: \$oldBool= \$key->SplitMultis(\$newBool);"; + } + return $oldFlag; +} + + +sub DWordsToHex +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlag= $Flag_HexDWord == ( $Flag_HexDWord & $self->{FLAGS} ); + if( 1 == @_ ) { + my $bool= shift(@_); + if( $bool ) { + $self->{FLAGS} |= $Flag_HexDWord; + } else { + $self->{FLAGS} &= ~$Flag_HexDWord; + } + } elsif( 0 != @_ ) { + croak "Usage: \$oldBool= \$key->DWordsToHex(\$newBool);"; + } + return $oldFlag; +} + + +sub FixSzNulls +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlag= $Flag_FixNulls == ( $Flag_FixNulls & $self->{FLAGS} ); + if( 1 == @_ ) { + my $bool= shift(@_); + if( $bool ) { + $self->{FLAGS} |= $Flag_FixNulls; + } else { + $self->{FLAGS} &= ~$Flag_FixNulls; + } + } elsif( 0 != @_ ) { + croak "Usage: \$oldBool= \$key->FixSzNulls(\$newBool);"; + } + return $oldFlag; +} + + +sub DualTypes +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlag= $Flag_DualTyp == ( $Flag_DualTyp & $self->{FLAGS} ); + if( 1 == @_ ) { + my $bool= shift(@_); + if( $bool ) { + croak "${PACK}->DualTypes cannot be enabled since ", + "SetDualVar module not installed" + unless $_SetDualVar; + $self->{FLAGS} |= $Flag_DualTyp; + } else { + $self->{FLAGS} &= ~$Flag_DualTyp; + } + } elsif( 0 != @_ ) { + croak "Usage: \$oldBool= \$key->DualTypes(\$newBool);"; + } + return $oldFlag; +} + + +sub DualBinVals +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $oldFlag= $Flag_DualBin == ( $Flag_DualBin & $self->{FLAGS} ); + if( 1 == @_ ) { + my $bool= shift(@_); + if( $bool ) { + croak "${PACK}->DualBinVals cannot be enabled since ", + "SetDualVar module not installed" + unless $_SetDualVar; + $self->{FLAGS} |= $Flag_DualBin; + } else { + $self->{FLAGS} &= ~$Flag_DualBin; + } + } elsif( 0 != @_ ) { + croak "Usage: \$oldBool= \$key->DualBinVals(\$newBool);"; + } + return $oldFlag; +} + + +sub GetOptions +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my( $opt, $meth ); + if( ! @_ || 1 == @_ && "HASH" eq ref($_[0]) ) { + my $href= @_ ? $_[0] : {}; + foreach $opt ( grep !/^Allow/, @_opt_subs ) { + $meth= $_opt_subs{$opt}; + $href->{$opt}= $self->$meth(); + } + return @_ ? $self : $href; + } + my @old; + foreach $opt ( @_ ) { + $meth= $_opt_subs{$opt}; + if( defined $meth ) { + if( $opt eq "AllowLoad" || $opt eq "AllowSave" ) { + croak "${PACK}->GetOptions: Getting current setting of $opt ", + "not supported in this release"; + } + push( @old, $self->$meth() ); + } else { + croak "${PACK}->GetOptions: Invalid option ($opt) ", + "not one of ( ", join(" ",grep !/^Allow/, @_opt_subs), " )"; + } + } + return wantarray ? @old : $old[-1]; +} + + +sub SetOptions +{ + my $self= shift(@_); + # Don't get object if hash ref so "ref" returns original ref. + my( $opt, $meth, @old ); + while( @_ ) { + $opt= shift(@_); + $meth= $_opt_subs{$opt}; + if( ! @_ ) { + croak "${PACK}->SetOptions: Option value missing ", + "after option name ($opt)"; + } elsif( defined $meth ) { + push( @old, $self->$meth( shift(@_) ) ); + } elsif( $opt eq substr("reference",0,length($opt)) ) { + shift(@_) if @_; + push( @old, $self ); + } else { + croak "${PACK}->SetOptions: Invalid option ($opt) ", + "not one of ( @_opt_subs )"; + } + } + return wantarray ? @old : $old[-1]; +} + + +sub _parseTiedEnt +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $ent= shift(@_); + my $delim= shift(@_); + my $dlen= length( $delim ); + my $parent= @_ ? shift(@_) : 0; + my $off; + if( $delim x 2 eq substr($ent,0,2*$dlen) && "NONE" eq $self->Handle ) { + if( 0 <= ( $off= index( $ent, $delim x 2, 2*$dlen ) ) ) { + return( substr( $ent, 0, $off ), substr( $ent, 2*$dlen+$off ) ); + } elsif( $delim eq substr($ent,-$dlen) ) { + return( substr($ent,0,-$dlen) ); + } elsif( 2*$dlen <= ( $off= rindex( $ent, $delim ) ) ) { + return( substr( $ent, 0, $off ), + undef, substr( $ent, $dlen+$off ) ); + } elsif( $parent ) { + return(); + } else { + return( $ent ); + } + } elsif( $delim eq substr($ent,0,$dlen) && "NONE" ne $self->Handle ) { + return( undef, substr($ent,$dlen) ); + } elsif( $self->{MEMBERS} && $self->_MembersHash->{$ent} ) { + return( substr($ent,0,-$dlen) ); + } elsif( 0 <= ( $off= index( $ent, $delim x 2 ) ) ) { + return( substr( $ent, 0, $off ), substr( $ent, 2*$dlen+$off ) ); + } elsif( $delim eq substr($ent,-$dlen) ) { + if( $parent + && 0 <= ( $off= rindex( $ent, $delim, length($ent)-2*$dlen ) ) ) { + return( substr($ent,0,$off), + undef, undef, substr($ent,$dlen+$off,-$dlen) ); + } else { + return( substr($ent,0,-$dlen) ); + } + } elsif( 0 <= ( $off= rindex( $ent, $delim ) ) ) { + return( + substr( $ent, 0, $off ), undef, substr( $ent, $dlen+$off ) ); + } else { + return( undef, undef, $ent ); + } +} + + +sub _FetchValue +{ + my $self= shift( @_ ); + my( $val, $createKey )= @_; + my( $data, $type ); + if( ( $data, $type )= $self->GetValue( $val ) ) { + return $self->ArrayValues ? [ $data, $type ] + : wantarray ? ( $data, $type ) + : $data; + } elsif( $createKey and $data= $self->new($val) ) { + return $data->TiedRef; + } else { + return (); + } +} + + +sub FETCH +{ + my $self= shift(@_); + my $ent= shift(@_); + my $delim= $self->Delimiter; + my( $key, $val, $ambig )= $self->_parseTiedEnt( $ent, $delim, 0 ); + my $sub; + if( defined($key) ) { + if( defined($self->{MEMBHASH}) + && $self->{MEMBHASH}->{$key.$delim} + && 0 <= index($key,$delim) ) { + return () + unless $sub= $self->new( $key, + {"Delimiter"=>$self->OS_Delimiter} ); + $sub->Delimiter($delim); + } else { + return () + unless $sub= $self->new( $key ); + } + } else { + $sub= $self; + } + if( defined($val) ) { + return $sub->_FetchValue( $val ); + } elsif( ! defined($ambig) ) { + return $sub->TiedRef; + } elsif( defined($key) ) { + return $sub->FETCH( $ambig ); + } else { + return $sub->_FetchValue( $ambig, "" ne $ambig ); + } +} + + +sub _FetchOld +{ + my( $self, $key )= @_; + my $old= $self->FETCH($key); + if( $old ) { + my $copy= {}; + %$copy= %$old; + return $copy; + } + # return $^E; + return _Err; +} + + +sub DELETE +{ + my $self= shift(@_); + my $ent= shift(@_); + my $delim= $self->Delimiter; + my( $key, $val, $ambig, $subkey )= $self->_parseTiedEnt( $ent, $delim, 1 ); + my $sub; + my $fast= defined(wantarray) ? $self->FastDelete : 2; + my $old= 1; # Value returned if FastDelete is set. + if( defined($key) + && ( defined($val) || defined($ambig) || defined($subkey) ) ) { + return () + unless $sub= $self->new( $key ); + } else { + $sub= $self; + } + if( defined($val) ) { + $old= $sub->GetValue($val) || _Err unless 2 <= $fast; + $sub->RegDeleteValue( $val ); + } elsif( defined($subkey) ) { + $old= $sub->_FetchOld( $subkey.$delim ) unless $fast; + $sub->RegDeleteKey( $subkey ); + } elsif( defined($ambig) ) { + if( defined($key) ) { + $old= $sub->DELETE($ambig); + } else { + $old= $sub->GetValue($ambig) || _Err unless 2 <= $fast; + if( defined( $old ) ) { + $sub->RegDeleteValue( $ambig ); + } else { + $old= $sub->_FetchOld( $ambig.$delim ) unless $fast; + $sub->RegDeleteKey( $ambig ); + } + } + } elsif( defined($key) ) { + $old= $sub->_FetchOld( $key.$delim ) unless $fast; + $sub->RegDeleteKey( $key ); + } else { + croak "${PACK}->DELETE: Key ($ent) can never be deleted"; + } + return $old; +} + + +sub SetValue +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + my $name= shift(@_); + my $data= shift(@_); + my( $type )= @_; + my $size; + if( ! defined($type) ) { + if( "ARRAY" eq ref($data) ) { + croak "${PACK}->SetValue: Value is array reference but ", + "no data type given" + unless 2 == @$data; + ( $data, $type )= @$data; + } else { + $type= REG_SZ; + } + } + $type= _constant($type,"registry value data type") if $type =~ /^REG_/; + if( REG_MULTI_SZ == $type && "ARRAY" eq ref($data) ) { + $data= join( "\0", @$data ) . "\0\0"; + ## $data= pack( "a*" x (1+@$data), map( $_."\0", @$data, "" ) ); + } elsif( ( REG_SZ == $type || REG_EXPAND_SZ == $type ) + && $self->FixSzNulls ) { + $data .= "\0" unless "\0" eq substr($data,0,-1); + } elsif( REG_DWORD == $type && $data =~ /^0x[0-9a-fA-F]{3,}$/ ) { + $data= pack( "L", hex($data) ); + # We could to $data=pack("L",$data) for REG_DWORD but I see + # no nice way to always destinguish when to do this or not. + } + return $self->RegSetValueEx( $name, 0, $type, $data, length($data) ); +} + + +sub StoreKey +{ + my $this= shift(@_); + $this= tied(%$this) if ref($this) && tied(%$this); + my $subKey= shift(@_); + my $data= shift(@_); + my $ent; + my $self; + if( ! ref($data) || "$data" !~ /(^|=)HASH/ ) { + croak "${PACK}->StoreKey: For ", $this->Path.$subKey, ",\n", + " subkey data must be a HASH reference"; + } + if( defined( $$data{""} ) && "HASH" eq ref($$data{""}) ) { + $self= $this->CreateKey( $subKey, delete $$data{""} ); + } else { + $self= $this->CreateKey( $subKey ); + } + return () if ! defined($self); + foreach $ent ( keys(%$data) ) { + return () + unless $self->STORE( $ent, $$data{$ent} ); + } + return $self; +} + + +# = { "" => {OPT=>VAL}, "val"=>[], "key"=>{} } creates a new key +# = "string" creates a new REG_SZ value +# = [ data, type ] creates a new value +sub STORE +{ + my $self= shift(@_); + my $ent= shift(@_); + my $data= shift(@_); + my $delim= $self->Delimiter; + my( $key, $val, $ambig, $subkey )= $self->_parseTiedEnt( $ent, $delim, 1 ); + my $sub; + if( defined($key) + && ( defined($val) || defined($ambig) || defined($subkey) ) ) { + return () + unless $sub= $self->new( $key ); + } else { + $sub= $self; + } + if( defined($val) ) { + croak "${PACK}->STORE: For ", $sub->Path.$delim.$val, ",\n", + " value data cannot be a HASH reference" + if ref($data) && "$data" =~ /(^|=)HASH/; + $sub->SetValue( $val, $data ); + } elsif( defined($subkey) ) { + croak "${PACK}->STORE: For ", $sub->Path.$subkey.$delim, ",\n", + " subkey data must be a HASH reference" + unless ref($data) && "$data" =~ /(^|=)HASH/; + $sub->StoreKey( $subkey, $data ); + } elsif( defined($ambig) ) { + if( ref($data) && "$data" =~ /(^|=)HASH/ ) { + $sub->StoreKey( $ambig, $data ); + } else { + $sub->SetValue( $ambig, $data ); + } + } elsif( defined($key) ) { + croak "${PACK}->STORE: For ", $sub->Path.$key.$delim, ",\n", + " subkey data must be a HASH reference" + unless ref($data) && "$data" =~ /(^|=)HASH/; + $sub->StoreKey( $key, $data ); + } else { + croak "${PACK}->STORE: Key ($ent) can never be created nor set"; + } +} + + +sub EXISTS +{ + my $self= shift(@_); + my $ent= shift(@_); + return defined( $self->FETCH($ent) ); +} + + +sub FIRSTKEY +{ + my $self= shift(@_); + my $members= $self->_MemberNames; + $self->{PREVIDX}= 0; + return @{$members} ? $members->[0] : undef; +} + + +sub NEXTKEY +{ + my $self= shift(@_); + my $prev= shift(@_); + my $idx= $self->{PREVIDX}; + my $members= $self->_MemberNames; + if( ! defined($idx) || $prev ne $members->[$idx] ) { + $idx= 0; + while( $idx < @$members && $prev ne $members->[$idx] ) { + $idx++; + } + } + $self->{PREVIDX}= ++$idx; + return $members->[$idx]; +} + + +sub DESTROY +{ + my $self= shift(@_); + return if tied(%$self); + my $unload; + local $@; + eval { $unload= $self->{UNLOADME}; 1 } + or return; + my $debug= $ENV{DEBUG_TIE_REGISTRY}; + if( defined($debug) ) { + if( 1 < $debug ) { + my $hand= $self->Handle; + my $dep= $self->{DEPENDON}; + carp "${PACK} destroying ", $self->Path, " (", + "NONE" eq $hand ? $hand : sprintf("0x%lX",$hand), ")", + defined($dep) ? (" [depends on ",$dep->Path,"]") : (); + } else { + warn "${PACK} destroying ", $self->Path, ".\n"; + } + } + $self->RegCloseKey + unless "NONE" eq $self->Handle; + if( defined($unload) ) { + if( defined($debug) && 1 < $debug ) { + my( $obj, $subKey, $file )= @$unload; + warn "Unloading ", $self->Path, + " (from ", $obj->Path, ", $subKey)...\n"; + } + $self->UnLoad + || warn "Couldn't unload ", $self->Path, ": ", _ErrMsg, "\n"; + ## carp "Never unloaded ${PACK}::Load($$unload[2])"; + } + #delete $self->{DEPENDON}; +} + + +use vars qw( @CreateKey_Opts %CreateKey_Opts %_KeyDispNames ); +@CreateKey_Opts= qw( Access Class Options Delimiter + Disposition Security Volatile Backup ); +@CreateKey_Opts{@CreateKey_Opts}= (1) x @CreateKey_Opts; +%_KeyDispNames= ( REG_CREATED_NEW_KEY() => "REG_CREATED_NEW_KEY", + REG_OPENED_EXISTING_KEY() => "REG_OPENED_EXISTING_KEY" ); + +sub CreateKey +{ + my $self= shift(@_); + my $tied= tied(%$self); + $self= tied(%$self) if $tied; + my( $subKey, $opts )= @_; + my( $sam )= $self->Access; + my( $delim )= $self->Delimiter; + my( $class )= ""; + my( $flags )= 0; + my( $secure )= []; + my( $garb )= []; + my( $result )= \$garb; + my( $handle )= 0; + if( @_ < 1 || 2 < @_ + || 2 == @_ && "HASH" ne ref($opts) ) { + croak "Usage: \$new= \$old->CreateKey( \$subKey, {OPT=>VAL,...} );\n", + " options: @CreateKey_Opts\nCalled"; + } + if( defined($opts) ) { + $sam= $opts->{"Access"} if defined($opts->{"Access"}); + $class= $opts->{Class} if defined($opts->{Class}); + $flags= $opts->{Options} if defined($opts->{Options}); + $delim= $opts->{"Delimiter"} if defined($opts->{"Delimiter"}); + $secure= $opts->{Security} if defined($opts->{Security}); + if( defined($opts->{Disposition}) ) { + "SCALAR" eq ref($opts->{Disposition}) + or croak "${PACK}->CreateKey option `Disposition'", + " must provide a scalar reference"; + $result= $opts->{Disposition}; + } + if( 0 == $flags ) { + $flags |= REG_OPTION_VOLATILE + if defined($opts->{Volatile}) && $opts->{Volatile}; + $flags |= REG_OPTION_BACKUP_RESTORE + if defined($opts->{Backup}) && $opts->{Backup}; + } + } + my $subPath= ref($subKey) ? $subKey : $self->_split($subKey,$delim); + $subKey= join( $self->OS_Delimiter, @$subPath ); + $self->RegCreateKeyEx( $subKey, 0, $class, $flags, $sam, + $secure, $handle, $$result ) + or return (); + if( ! ref($$result) && $self->DualTypes ) { + $$result= _DualVal( \%_KeyDispNames, $$result ); + } + my $new= $self->_new( $handle, [ @{$self->_Path}, @{$subPath} ] ); + $new->{ACCESS}= $sam; + $new->{DELIM}= $delim; + $new= $new->TiedRef if $tied; + return $new; +} + + +use vars qw( $Load_Cnt @Load_Opts %Load_Opts ); +$Load_Cnt= 0; +@Load_Opts= qw(NewSubKey); +@Load_Opts{@Load_Opts}= (1) x @Load_Opts; + +sub Load +{ + my $this= shift(@_); + my $tied= ref($this) && tied(%$this); + $this= tied(%$this) if $tied; + my( $file, $subKey, $opts )= @_; + if( 2 == @_ && "HASH" eq ref($subKey) ) { + $opts= $subKey; + undef $subKey; + } + @_ < 1 || 3 < @_ || defined($opts) && "HASH" ne ref($opts) + and croak "Usage: \$key= ", + "${PACK}->Load( \$fileName, [\$newSubKey,] {OPT=>VAL...} );\n", + " options: @Load_Opts @new_Opts\nCalled"; + if( defined($opts) && exists($opts->{NewSubKey}) ) { + $subKey= delete $opts->{NewSubKey}; + } + if( ! defined( $subKey ) ) { + if( "" ne $this->Machine ) { + ( $this )= $this->_connect( [$this->Machine,"LMachine"] ); + } else { + ( $this )= $this->_rootKey( "LMachine" ); # Could also be "Users" + } + $subKey= "PerlTie:$$." . ++$Load_Cnt; + } + $this->RegLoadKey( $subKey, $file ) + or return (); + my $self= $this->new( $subKey, defined($opts) ? $opts : () ); + if( ! defined( $self ) ) { + { my $err= Win32::GetLastError(); + #{ local( $^E ); #} + $this->RegUnLoadKey( $subKey ) or carp + "Can't unload $subKey from ", $this->Path, ": ", _ErrMsg, "\n"; + Win32::SetLastError($err); + } + return (); + } + $self->{UNLOADME}= [ $this, $subKey, $file ]; + $self= $self->TiedRef if $tied; + return $self; +} + + +sub UnLoad +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + @_ and croak "Usage: \$key->UnLoad;"; + my $unload= $self->{UNLOADME}; + "ARRAY" eq ref($unload) + or croak "${PACK}->UnLoad called on a key which was not Load()ed"; + my( $obj, $subKey, $file )= @$unload; + $self->RegCloseKey; + return Win32API::Registry::RegUnLoadKey( $obj->Handle, $subKey ); +} + + +sub AllowSave +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + return $self->AllowPriv( "SeBackupPrivilege", @_ ); +} + + +sub AllowLoad +{ + my $self= shift(@_); + $self= tied(%$self) if tied(%$self); + return $self->AllowPriv( "SeRestorePrivilege", @_ ); +} + + +# RegNotifyChangeKeyValue( hKey, bWatchSubtree, iNotifyFilter, hEvent, bAsync ) + + +sub RegCloseKey { my $self= shift(@_); + Win32API::Registry::RegCloseKey $self->Handle, @_; } +sub RegConnectRegistry { my $self= shift(@_); + Win32API::Registry::RegConnectRegistry @_; } +sub RegCreateKey { my $self= shift(@_); + Win32API::Registry::RegCreateKey $self->Handle, @_; } +sub RegCreateKeyEx { my $self= shift(@_); + Win32API::Registry::RegCreateKeyEx $self->Handle, @_; } +sub RegDeleteKey { my $self= shift(@_); + Win32API::Registry::RegDeleteKey $self->Handle, @_; } +sub RegDeleteValue { my $self= shift(@_); + Win32API::Registry::RegDeleteValue $self->Handle, @_; } +sub RegEnumKey { my $self= shift(@_); + Win32API::Registry::RegEnumKey $self->Handle, @_; } +sub RegEnumKeyEx { my $self= shift(@_); + Win32API::Registry::RegEnumKeyEx $self->Handle, @_; } +sub RegEnumValue { my $self= shift(@_); + Win32API::Registry::RegEnumValue $self->Handle, @_; } +sub RegFlushKey { my $self= shift(@_); + Win32API::Registry::RegFlushKey $self->Handle, @_; } +sub RegGetKeySecurity { my $self= shift(@_); + Win32API::Registry::RegGetKeySecurity $self->Handle, @_; } +sub RegLoadKey { my $self= shift(@_); + Win32API::Registry::RegLoadKey $self->Handle, @_; } +sub RegNotifyChangeKeyValue { my $self= shift(@_); + Win32API::Registry::RegNotifyChangeKeyValue $self->Handle, @_; } +sub RegOpenKey { my $self= shift(@_); + Win32API::Registry::RegOpenKey $self->Handle, @_; } +sub RegOpenKeyEx { my $self= shift(@_); + Win32API::Registry::RegOpenKeyEx $self->Handle, @_; } +sub RegQueryInfoKey { my $self= shift(@_); + Win32API::Registry::RegQueryInfoKey $self->Handle, @_; } +sub RegQueryMultipleValues { my $self= shift(@_); + Win32API::Registry::RegQueryMultipleValues $self->Handle, @_; } +sub RegQueryValue { my $self= shift(@_); + Win32API::Registry::RegQueryValue $self->Handle, @_; } +sub RegQueryValueEx { my $self= shift(@_); + Win32API::Registry::RegQueryValueEx $self->Handle, @_; } +sub RegReplaceKey { my $self= shift(@_); + Win32API::Registry::RegReplaceKey $self->Handle, @_; } +sub RegRestoreKey { my $self= shift(@_); + Win32API::Registry::RegRestoreKey $self->Handle, @_; } +sub RegSaveKey { my $self= shift(@_); + Win32API::Registry::RegSaveKey $self->Handle, @_; } +sub RegSetKeySecurity { my $self= shift(@_); + Win32API::Registry::RegSetKeySecurity $self->Handle, @_; } +sub RegSetValue { my $self= shift(@_); + Win32API::Registry::RegSetValue $self->Handle, @_; } +sub RegSetValueEx { my $self= shift(@_); + Win32API::Registry::RegSetValueEx $self->Handle, @_; } +sub RegUnLoadKey { my $self= shift(@_); + Win32API::Registry::RegUnLoadKey $self->Handle, @_; } +sub AllowPriv { my $self= shift(@_); + Win32API::Registry::AllowPriv @_; } + + +# Autoload methods go after =cut, and are processed by the autosplit program. + +1; +__END__ + +=head1 NAME + +Win32::TieRegistry - Powerful and easy ways to manipulate a registry +[on Win32 for now]. + +=head1 SYNOPSIS + + use Win32::TieRegistry 0.20 ( UseOptionName=>UseOptionValue[,...] ); + + $Registry->SomeMethodCall(arg1,...); + + $subKey= $Registry->{"Key\\SubKey\\"}; + $valueData= $Registry->{"Key\\SubKey\\\\ValueName"}; + $Registry->{"Key\\SubKey\\"}= { "NewSubKey" => {...} }; + $Registry->{"Key\\SubKey\\\\ValueName"}= "NewValueData"; + $Registry->{"\\ValueName"}= [ pack("fmt",$data), REG_DATATYPE ]; + +=head1 EXAMPLES + + use Win32::TieRegistry( Delimiter=>"#", ArrayValues=>0 ); + $pound= $Registry->Delimiter("/"); + $diskKey= $Registry->{"LMachine/System/Disk/"} + or die "Can't read LMachine/System/Disk key: $^E\n"; + $data= $key->{"/Information"} + or die "Can't read LMachine/System/Disk//Information value: $^E\n"; + $remoteKey= $Registry->{"//ServerA/LMachine/System/"} + or die "Can't read //ServerA/LMachine/System/ key: $^E\n"; + $remoteData= $remoteKey->{"Disk//Information"} + or die "Can't read ServerA's System/Disk//Information value: $^E\n"; + foreach $entry ( keys(%$diskKey) ) { + ... + } + foreach $subKey ( $diskKey->SubKeyNames ) { + ... + } + $diskKey->AllowSave( 1 ); + $diskKey->RegSaveKey( "C:/TEMP/DiskReg", [] ); + +=head1 DESCRIPTION + +The I<Win32::TieRegistry> module lets you manipulate the Registry +via objects [as in "object oriented"] or via tied hashes. But +you will probably mostly use a combination reference, that is, a +reference to a tied hash that has also been made an object so that +you can mix both access methods [as shown above]. + +If you did not get this module as part of L<libwin32>, you might +want to get a recent version of L<libwin32> from CPAN which should +include this module and the I<Win32API::Registry> module that it +uses. + +Skip to the L<SUMMARY> section if you just want to dive in and start +using the Registry from Perl. + +Accessing and manipulating the registry is extremely simple using +I<Win32::TieRegistry>. A single, simple expression can return +you almost any bit of information stored in the Registry. +I<Win32::TieRegistry> also gives you full access to the "raw" +underlying API calls so that you can do anything with the Registry +in Perl that you could do in C. But the "simple" interface has +been carefully designed to handle almost all operations itself +without imposing arbitrary limits while providing sensible +defaults so you can list only the parameters you care about. + +But first, an overview of the Registry itself. + +=head2 The Registry + +The Registry is a forest: a collection of several tree structures. +The root of each tree is a key. These root keys are identified by +predefined constants whose names start with "HKEY_". Although all +keys have a few attributes associated with each [a class, a time +stamp, and security information], the most important aspect of keys +is that each can contain subkeys and can contain values. + +Each subkey has a name: a string which cannot be blank and cannot +contain the delimiter character [backslash: C<'\\'>] nor nul +[C<'\0'>]. Each subkey is also a key and so can contain subkeys +and values [and has a class, time stamp, and security information]. + +Each value has a name: a string which E<can> be blank and E<can> +contain the delimiter character [backslash: C<'\\'>] and any +character except for null, C<'\0'>. Each value also has data +associated with it. Each value's data is a contiguous chunk of +bytes, which is exactly what a Perl string value is so Perl +strings will usually be used to represent value data. + +Each value also has a data type which says how to interpret the +value data. The primary data types are: + +=over + +=item REG_SZ + +A null-terminated string. + +=item REG_EXPAND_SZ + +A null-terminated string which contains substrings consisting of a +percent sign [C<'%'>], an environment variable name, then a percent +sign, that should be replaced with the value associate with that +environment variable. The system does I<not> automatically do this +substitution. + +=item REG_BINARY + +Some arbitrary binary value. You can think of these as being +"packed" into a string. + +If your system has the L<SetDualVar> module installed, +the C<DualBinVals()> option wasn't turned off, and you +fetch a C<REG_BINARY> value of 4 bytes or fewer, then +you can use the returned value in a numeric context to +get at the "unpacked" numeric value. See C<GetValue()> +for more information. + +=item REG_MULTI_SZ + +Several null-terminated strings concatenated together with an +extra trailing C<'\0'> at the end of the list. Note that the list +can include empty strings so use the value's length to determine +the end of the list, not the first occurrence of C<'\0\0'>. +It is best to set the C<SplitMultis()> option so I<Win32::TieRegistry> +will split these values into an array of strings for you. + +=item REG_DWORD + +A long [4-byte] integer value. These values are expected either +packed into a 4-character string or as a hex string of E<more than> +4 characters [but I<not> as a numeric value, unfortunately, as there is +no sure way to tell a numeric value from a packed 4-byte string that +just happens to be a string containing a valid numeric value]. + +How such values are returned depends on the C<DualBinVals()> and +C<DWordsToHex()> options. See C<GetValue()> for details. + +=back + +In the underlying Registry calls, most places which take a +subkey name also allow you to pass in a subkey "path" -- a +string of several subkey names separated by the delimiter +character, backslash [C<'\\'>]. For example, doing +C<RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\DISK",...)> is much +like opening the C<"SYSTEM"> subkey of C<HKEY_LOCAL_MACHINE>, +then opening its C<"DISK"> subkey, then closing the C<"SYSTEM"> +subkey. + +All of the I<Win32::TieRegistry> features allow you to use your +own delimiter in place of the system's delimiter, [C<'\\'>]. In +most of our examples we will use a forward slash [C<'/'>] as our +delimiter as it is easier to read and less error prone to use when +writing Perl code since you have to type two backslashes for each +backslash you want in a string. Note that this is true even when +using single quotes -- C<'\\HostName\LMachine\'> is an invalid +string and must be written as C<'\\\\HostName\\LMachine\\'>. + +You can also connect to the registry of other computers on your +network. This will be discussed more later. + +Although the Registry does not have a single root key, the +I<Win32::TieRegistry> module creates a virtual root key for you +which has all of the I<HKEY_*> keys as subkeys. + +=head2 Tied Hashes Documentation + +Before you can use a tied hash, you must create one. One way to +do that is via: + + use Win32::TieRegistry ( TiedHash => '%RegHash' ); + +which exports a C<%RegHash> variable into your package and ties it +to the virtual root key of the Registry. An alternate method is: + + my %RegHash; + use Win32::TieRegistry ( TiedHash => \%RegHash ); + +There are also several ways you can tie a hash variable to any +other key of the Registry, which are discussed later. + +Note that you will most likely use C<$Registry> instead of using +a tied hash. C<$Registry> is a reference to a hash that has +been tied to the virtual root of your computer's Registry [as if, +C<$Registry= \%RegHash>]. So you would use C<$Registry-E<gt>{Key}> +rather than C<$RegHash{Key}> and use C<keys %{$Registry}> rather +than C<keys %RegHash>, for example. + +For each hash which has been tied to a Registry key, the Perl +C<keys> function will return a list containing the name of each +of the key's subkeys with a delimiter character appended to it and +containing the name of each of the key's values with a delimiter +prepended to it. For example: + + keys( %{ $Registry->{"HKEY_CLASSES_ROOT\\batfile\\"} } ) + +might yield the following list value: + + ( "DefaultIcon\\", # The subkey named "DefaultIcon" + "shell\\", # The subkey named "shell" + "shellex\\", # The subkey named "shellex" + "\\", # The default value [named ""] + "\\EditFlags" ) # The value named "EditFlags" + +For the virtual root key, short-hand subkey names are used as +shown below. You can use the short-hand name, the regular +I<HKEY_*> name, or any numeric value to access these keys, but +the short-hand names are all that will be returned by the C<keys> +function. + +=over + +=item "Classes" for HKEY_CLASSES_ROOT + +Contains mappings between file name extensions and the uses +for such files along with configuration information for COM +[MicroSoft's Common Object Model] objects. Usually a link to +the C<"SOFTWARE\\Classes"> subkey of the C<HKEY_LOCAL_MACHINE> +key. + +=item "CUser" for HKEY_CURRENT_USER + +Contains information specific to the currently logged-in user. +Mostly software configuration information. Usually a link to +a subkey of the C<HKEY_USERS> key. + +=item "LMachine" for HKEY_LOCAL_MACHINE + +Contains all manner of information about the computer. + +=item "Users" for HKEY_USERS + +Contains one subkey, C<".DEFAULT">, which gets copied to a new +subkey whenever a new user is added. Also contains a subkey for +each user of the system, though only those for active users +[usually only one] are loaded at any given time. + +=item "PerfData" for HKEY_PERFORMANCE_DATA + +Used to access data about system performance. Access via this key +is "special" and all but the most carefully constructed calls will +fail, usually with C<ERROR_INSUFFICIENT_BUFFER>. For example, you +can't enumerate key names without also enumerating values which +require huge buffers but the exact buffer size required cannot be +determined beforehand because C<RegQueryInfoKey()> E<always> fails +with C<ERROR_INSUFFICIENT_BUFFER> for C<HKEY_PERFORMANCE_DATA> no +matter how it is called. So it is currently not very useful to +tie a hash to this key. You can use it to create an object to use +for making carefully constructed calls to the underlying Reg*() +routines. + +=item "CConfig" for HKEY_CURRENT_CONFIG + +Contains minimal information about the computer's current +configuration that is required very early in the boot process. +For example, setting for the display adapter such as screen +resolution and refresh rate are found in here. + +=item "DynData" for HKEY_DYN_DATA + +Dynamic data. We have found no documentation for this key. + +=back + +A tied hash is much like a regular hash variable in Perl -- you give +it a key string inside braces, [C<{> and C<}>], and it gives you +back a value [or lets you set a value]. For I<Win32::TieRegistry> +hashes, there are two types of values that will be returned. + +=over + +=item SubKeys + +If you give it a string which represents a subkey, then it will +give you back a reference to a hash which has been tied to that +subkey. It can't return the hash itself, so it returns a +reference to it. It also blesses that reference so that it is +also an object so you can use it to call method functions. + +=item Values + +If you give it a string which is a value name, then it will give +you back a string which is the data for that value. Alternately, +you can request that it give you both the data value string and +the data value type [we discuss how to request this later]. In +this case, it would return a reference to an array where the value +data string is element C<[0]> and the value data type is element +C<[1]>. + +=back + +The key string which you use in the tied hash must be interpreted +to determine whether it is a value name or a key name or a path +that combines several of these or even other things. There are +two simple rules that make this interpretation easy and +unambiguous: + + Put a delimiter after each key name. + Put a delimiter in front of each value name. + +Exactly how the key string will be intepreted is governed by the +following cases, in the order listed. These cases are designed +to "do what you mean". Most of the time you won't have to think +about them, especially if you follow the two simple rules above. +After the list of cases we give several examples which should be +clear enough so feel free to skip to them unless you are worried +about the details. + +=over + +=item Remote machines + +If the hash is tied to the virtual root of the registry [or the +virtual root of a remote machine's registry], then we treat hash +key strings which start with the delimiter character specially. + +If the hash key string starts with two delimiters in a row, then +those should be immediately followed by the name of a remote +machine whose registry we wish to connect to. That can be +followed by a delimiter and more subkey names, etc. If the +machine name is not following by anything, then a virtual root +for the remote machine's registry is created, a hash is tied to +it, and a reference to that hash it is returned. + +=item Hash key string starts with the delimiter + +If the hash is tied to a virtual root key, then the leading +delimiter is ignored. It should be followed by a valid Registry +root key name [either a short-hand name like C<"LMachine">, an +I<HKEY_*> value, or a numeric value]. This alternate notation is +allowed in order to be more consistant with the C<Open()> method +function. + +For all other Registry keys, the leading delimiter indicates +that the rest of the string is a value name. The leading +delimiter is stripped and the rest of the string [which can +be empty and can contain more delimiters] is used as a value +name with no further parsing. + +=item Exact match with direct subkey name followed by delimiter + +If you have already called the Perl C<keys> function on the tied +hash [or have already called C<MemberNames> on the object] and the +hash key string exactly matches one of the strings returned, then +no further parsing is done. In other words, if the key string +exactly matches the name of a direct subkey with a delimiter +appended, then a reference to a hash tied to that subkey is +returned [but only if C<keys> or C<MemberNames> has already +been called for that tied hash]. + +This is only important if you have selected a delimiter other than +the system default delimiter and one of the subkey names contains +the delimiter you have chosen. This rule allows you to deal with +subkeys which contain your chosen delimiter in their name as long +as you only traverse subkeys one level at a time and always +enumerate the list of members before doing so. + +The main advantage of this is that Perl code which recursively +traverses a hash will work on hashes tied to Registry keys even if +a non-default delimiter has been selected. + +=item Hash key string contains two delimiters in a row + +If the hash key string contains two [or more] delimiters in a row, +then the string is split between the first pair of delimiters. +The first part is interpreted as a subkey name or a path of subkey +names separated by delimiters and with a trailing delimiter. The +second part is interpreted as a value name with one leading +delimiter [any extra delimiters are considered part of the value +name]. + +=item Hash key string ends with a delimiter + +If the key string ends with a delimiter, then it is treated +as a subkey name or path of subkey names separated by delimiters. + +=item Hash key string contains a delimiter + +If the key string contains a delimiter, then it is split after +the last delimiter. The first part is treated as a subkey name or +path of subkey names separated by delimiters. The second part +is ambiguous and is treated as outlined in the next item. + +=item Hash key string contains no delimiters + +If the hash key string contains no delimiters, then it is ambiguous. + +If you are reading from the hash [fetching], then we first use the +key string as a value name. If there is a value with a matching +name in the Registry key which the hash is tied to, then the value +data string [and possibly the value data type] is returned. +Otherwise, we retry by using the hash key string as a subkey name. +If there is a subkey with a matching name, then we return a +reference to a hash tied to that subkey. Otherwise we return +C<undef>. + +If you are writing to the hash [storing], then we use the key +string as a subkey name only if the value you are storing is a +reference to a hash value. Otherwise we use the key string as +a value name. + +=back + +=head3 Examples + +Here are some examples showing different ways of accessing Registry +information using references to tied hashes: + +=over + +=item Canonical value fetch + + $tip18= $Registry->{"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\" + . 'Windows\\CurrentVersion\\Explorer\\Tips\\\\18'}; + +Should return the text of important tip number 18. Note that two +backslashes, C<"\\">, are required to get a single backslash into +a Perl double-quoted or single-qouted string. Note that C<"\\"> +is appended to each key name [C<"HKEY_LOCAL_MACHINE"> through +C<"Tips">] and C<"\\"> is prepended to the value name, C<"18">. + +=item Changing your delimiter + + $Registry->Delimiter("/"); + $tip18= $Registry->{"HKEY_LOCAL_MACHINE/Software/Microsoft/" + . 'Windows/CurrentVersion/Explorer/Tips//18'}; + +This usually makes things easier to read when working in Perl. +All remaining examples will assume the delimiter has been changed +as above. + +=item Using intermediate keys + + $ms= $Registry->{"LMachine/Software/Microsoft/"}; + $tips= $ms->{"Windows/CurrentVersion/Explorer/Tips/"}; + $tip18= $winlogon->{"/18"}; + +Same as above but opens more keys into the Registry which lets you +efficiently re-access those intermediate keys. This is slightly +less efficient if you never reuse those intermediate keys. + +=item Chaining in a single statement + + $tip18= $Registry->{"LMachine/Software/Microsoft/"}-> + {"Windows/CurrentVersion/Explorer/Tips/"}->{"/18"}; + +Like above, this creates intermediate key objects then uses +them to access other data. Once this statement finishes, the +intermediate key objects are destroyed. Several handles into +the Registry are opened and closed by this statement so it is +less efficient but there are times when this will be useful. + +=item Even less efficient example of chaining + + $tip18= $Registry->{"LMachine/Software/Microsoft"}-> + {"Windows/CurrentVersion/Explorer/Tips"}->{"/18"}; + +Because we left off the trailing delimiters, I<Win32::TieRegistry> +doesn't know whether final names, C<"Microsoft"> and C<"Tips">, +are subkey names or value names. So this statement ends up +executing the same code as the next one. + +=item What the above really does + + $tip18= $Registry->{"LMachine/Software/"}->{"Microsoft"}-> + {"Windows/CurrentVersion/Explorer/"}->{"Tips"}->{"/18"}; + +With more chains to go through, more temporary objects are created +and later destroyed than in our first chaining example. Also, +when C<"Microsoft"> is looked up, I<Win32::TieRegistry> first +tries to open it as a value and fails then tries it as a subkey. +The same is true for when it looks up C<"Tips">. + +=item Getting all of the tips + + $tips= $Registry->{"LMachine/Software/Microsoft/"}-> + {"Windows/CurrentVersion/Explorer/Tips/"} + or die "Can't find the Windows tips: $^E\n"; + foreach( keys %$tips ) { + print "$_: ", $tips->{$_}, "\n"; + } + +First notice that we actually check for failure for the first +time. We are assuming that the C<"Tips"> key contains no subkeys. +Otherwise the C<print> statement would show something like +C<"Win32::TieRegistry=HASH(0xc03ebc)"> for each subkey. + +The output from the above code will start something like: + + /0: If you don't know how to do something,[...] + +=back + +=head3 Deleting items + +You can use the Perl C<delete> function to delete a value from a +Registry key or to delete a subkey as long that subkey contains +no subkeys of its own. See L<More Examples>, below, for more +information. + +=head3 Storing items + +You can use the Perl assignment operator [C<=>] to create new +keys, create new values, or replace values. The values you store +should be in the same format as the values you would fetch from a +tied hash. For example, you can use a single assignment statement +to copy an entire Registry tree. The following statement: + + $Registry->{"LMachine/Software/Classes/Tie_Registry/"}= + $Registry->{"LMachine/Software/Classes/batfile/"}; + +creates a C<"Tie_Registry"> subkey under the C<"Software\\Classes"> +subkey of the C<HKEY_LOCAL_MACHINE> key. Then it populates it +with copies of all of the subkeys and values in the C<"batfile"> +subkey and all of its subkeys. Note that you need to have +called C<$Registry-E<gt>ArrayValues(1)> for the proper value data +type information to be copied. Note also that this release of +I<Win32::TieRegistry> does not copy key attributes such as class +name and security information [this is planned for a future release]. + +The following statement creates a whole subtree in the Registry: + + $Registry->{"LMachine/Software/FooCorp/"}= { + "FooWriter/" => { + "/Version" => "4.032", + "Startup/" => { + "/Title" => "Foo Writer Deluxe ][", + "/WindowSize" => [ pack("LL",$wid,$ht), "REG_BINARY" ], + "/TaskBarIcon" => [ "0x0001", "REG_DWORD" ], + }, + "Compatibility/" => { + "/AutoConvert" => "Always", + "/Default Palette" => "Windows Colors", + }, + }, + "/License", => "0123-9C8EF1-09-FC", + }; + +Note that all but the last Registry key used on the left-hand +side of the assignment [that is, "LMachine/Software/" but not +"FooCorp/"] must already exist for this statement to succeed. + +By using the leading a trailing delimiters on each subkey name and +value name, I<Win32::TieRegistry> will tell you if you try to assign +subkey information to a value or visa-versa. + +=head3 More examples + +=over + +=item Adding a new tip + + $tips= $Registry->{"LMachine/Software/Microsoft/"}-> + {"Windows/CurrentVersion/Explorer/Tips/"} + or die "Can't find the Windows tips: $^E\n"; + $tips{'/186'}= "Be very careful when making changes to the Registry!"; + +=item Deleting our new tip + + $tips= $Registry->{"LMachine/Software/Microsoft/"}-> + {"Windows/CurrentVersion/Explorer/Tips/"} + or die "Can't find the Windows tips: $^E\n"; + $tip186= delete $tips{'/186'}; + +Note that Perl's C<delete> function returns the value that was deleted. + +=item Adding a new tip differently + + $Registry->{"LMachine/Software/Microsoft/" . + "Windows/CurrentVersion/Explorer/Tips//186"}= + "Be very careful when making changes to the Registry!"; + +=item Deleting differently + + $tip186= delete $Registry->{"LMachine/Software/Microsoft/Windows/" . + "CurrentVersion/Explorer/Tips//186"}; + +Note that this only deletes the tail of what we looked up, the +C<"186"> value, not any of the keys listed. + +=item Deleting a key + +WARNING: The following code will delete all information about the +current user's tip preferences. Actually executing this command +would probably cause the user to see the Welcome screen the next +time they log in and may cause more serious problems. This +statement is shown as an example only and should not be used when +experimenting. + + $tips= delete $Registry->{"CUser/Software/Microsoft/Windows/" . + "CurrentVersion/Explorer/Tips/"}; + +This deletes the C<"Tips"> key and the values it contains. The +C<delete> function will return a reference to a hash [not a tied +hash] containing the value names and value data that were deleted. + +The information to be returned is copied from the Registry into a +regular Perl hash before the key is deleted. If the key has many +subkeys, this copying could take a significant amount of memory +and/or processor time. So you can disable this process by calling +the C<FastDelete> member function: + + $prevSetting= $regKey->FastDelete(1); + +which will cause all subsequent delete operations via C<$regKey> +to simply return a true value if they succeed. This optimization +is automatically done if you use C<delete> in a void context. + +=item Technical notes on deleting + +If you use C<delete> to delete a Registry key or value and use +the return value, then I<Win32::TieRegistry> usually looks up the +current contents of that key or value so they can be returned if +the deletion is successful. If the deletion succeeds but the +attempt to lookup the old contents failed, then the return value +of C<delete> will be C<$^E> from the failed part of the operation. + +=item Undeleting a key + + $Registry->{"LMachine/Software/Microsoft/Windows/" . + "CurrentVersion/Explorer/Tips/"}= $tips; + +This adds back what we just deleted. Note that this version of +I<Win32::TieRegistry> will use defaults for the key attributes +[such as class name and security] and will not restore the +previous attributes. + +=item Not deleting a key + +WARNING: Actually executing the following code could cause +serious problems. This statement is shown as an example only and +should not be used when experimenting. + + $res= delete $Registry->{"CUser/Software/Microsoft/Windows/"} + defined($res) || die "Can't delete URL key: $^E\n"; + +Since the "Windows" key should contain subkeys, that C<delete> +statement should make no changes to the Registry, return C<undef>, +and set C<$^E> to "Access is denied". + +=item Not deleting again + + $tips= $Registry->{"CUser/Software/Microsoft/Windows/" . + "CurrentVersion/Explorer/Tips/"}; + delete $tips; + +The Perl C<delete> function requires that its argument be an +expression that ends in a hash element lookup [or hash slice], +which is not the case here. The C<delete> function doesn't +know which hash $tips came from and so can't delete it. + +=back + +=head2 Objects Documentation + +The following member functions are defined for use on +I<Win32::TieRegistry> objects: + +=over + +=item new + +The C<new> method creates a new I<Win32::TieRegistry> object. +C<new> is mostly a synonym for C<Open()> so see C<Open()> below for +information on what arguments to pass in. Examples: + + $machKey= new Win32::TieRegistry "LMachine" + or die "Can't access HKEY_LOCAL_MACHINE key: $^E\n"; + $userKey= Win32::TieRegistry->new("CUser") + or die "Can't access HKEY_CURRENT_USER key: $^E\n"; + +Note that calling C<new> via a reference to a tied hash returns +a simple object, not a reference to a tied hash. + +=item Open + +=item $subKey= $key->Open( $sSubKey, $rhOptions ) + +The C<Open> method opens a Registry key and returns a new +I<Win32::TieRegistry> object associated with that Registry key. +If C<Open> is called via a reference to a tied hash, then C<Open> +returns another reference to a tied hash. Otherwise C<Open> +returns a simple object and you should then use C<TiedRef> to get +a reference to a tied hash. + +C<$sSubKey> is a string specifying a subkey to be opened. +Alternately C<$sSubKey> can be a reference to an array value +containing the list of increasingly deep subkeys specifying the +path to the subkey to be opened. + +C<$rhOptions> is an optional reference to a hash containing extra +options. The C<Open> method supports two options, C<"Delimiter"> +and C<"Access">, and C<$rhOptions> should have only have zero or +more of these strings as keys. See the "Examples" section below +for more information. + +The C<"Delimiter"> option specifies what string [usually a single +character] will be used as the delimiter to be appended to subkey +names and prepended to value names. If this option is not specified, +the new key [C<$subKey>] inherits the delimiter of the old key +[C<$key>]. + +The C<"Access"> option specifies what level of access to the +Registry key you wish to have once it has been opened. If this +option is not specified, the new key [C<$subKey>] is opened with +the same access level used when the old key [C<$key>] was opened. +The virtual root of the Registry pretends it was opened with +access C<KEY_READ()|KEY_WRITE()> so this is the default access when +opening keys directory via C<$Registry>. If you don't plan on +modifying a key, you should open it with C<KEY_READ> access as +you may not have C<KEY_WRITE> access to it or some of its subkeys. + +If the C<"Access"> option value is a string that starts with +C<"KEY_">, then it should match E<one> of the predefined access +levels [probably C<"KEY_READ">, C<"KEY_WRITE">, or +C<"KEY_ALL_ACCESS">] exported by the I<Win32API::Registry> module. +Otherwise, a numeric value is expected. For maximum flexibility, +include C<use Win32::TieRegistry qw(:KEY_);>, for example, near +the top of your script so you can specify more complicated access +levels such as C<KEY_READ()|KEY_WRITE()>. + +If C<$sSubKey> does not begin with the delimiter [or C<$sSubKey> +is an array reference], then the path to the subkey to be opened +will be relative to the path of the original key [C<$key>]. If +C<$sSubKey> begins with a single delimiter, then the path to the +subkey to be opened will be relative to the virtual root of the +Registry on whichever machine the original key resides. If +C<$sSubKey> begins with two consectutive delimiters, then those +must be followed by a machine name which causes the C<Connect()> +method function to be called. + +Examples: + + $machKey= $Registry->Open( "LMachine", {Access=>KEY_READ(),Delimiter=>"/"} ) + or die "Can't open HKEY_LOCAL_MACHINE key: $^E\n"; + $swKey= $machKey->Open( "Software" ); + $logonKey= $swKey->Open( "Microsoft/Windows NT/CurrentVersion/Winlogon/" ); + $NTversKey= $swKey->Open( ["Microsoft","Windows NT","CurrentVersion"] ); + $versKey= $swKey->Open( qw(Microsoft Windows CurrentVersion) ); + + $remoteKey= $Registry->Open( "//HostA/LMachine/System/", {Delimiter=>"/"} ) + or die "Can't connect to HostA or can't open subkey: $^E\n"; + +=item Clone + +=item $copy= $key->Clone + +Creates a new object that is associated with the same Registry key +as the invoking object. + +=item Connect + +=item $remoteKey= $Registry->Connect( $sMachineName, $sKeyPath, $rhOptions ) + +The C<Connect> method connects to the Registry of a remote machine, +and opens a key within it, then returns a new I<Win32::TieRegistry> +object associated with that remote Registry key. If C<Connect> +was called using a reference to a tied hash, then the return value +will also be a reference to a tied hash [or C<undef>]. Otherwise, +if you wish to use the returned object as a tied hash [not just as +an object], then use the C<TiedRef> method function after C<Connect>. + +C<$sMachineName> is the name of the remote machine. You don't have +to preceed the machine name with two delimiter characters. + +C<$sKeyPath> is a string specifying the remote key to be opened. +Alternately C<$sKeyPath> can be a reference to an array value +containing the list of increasingly deep keys specifying the path +to the key to be opened. + +C<$rhOptions> is an optional reference to a hash containing extra +options. The C<Connect> method supports two options, C<"Delimiter"> +and C<"Access">. See the C<Open> method documentation for more +information on these options. + +C<$sKeyPath> is already relative to the virtual root of the Registry +of the remote machine. A single leading delimiter on C<sKeyPath> +will be ignored and is not required. + +C<$sKeyPath> can be empty in which case C<Connect> will return an +object representing the virtual root key of the remote Registry. +Each subsequent use of C<Open> on this virtual root key will call +the system C<RegConnectRegistry> function. + +The C<Connect> method can be called via any I<Win32::TieRegistry> +object, not just C<$Registry>. Attributes such as the desired +level of access and the delimiter will be inherited from the +object used but the C<$sKeyPath> will always be relative to the +virtual root of the remote machine's registry. + +Examples: + + $remMachKey= $Registry->Connect( "HostA", "LMachine", {Delimiter->"/"} ) + or die "Can't connect to HostA's HKEY_LOCAL_MACHINE key: $^E\n"; + + $remVersKey= $remMachKey->Connect( "www.microsoft.com", + "LMachine/Software/Microsoft/Inetsrv/CurrentVersion/", + { Access=>KEY_READ, Delimiter=>"/" } ) + or die "Can't check what version of IIS Microsoft is running: $^E\n"; + + $remVersKey= $remMachKey->Connect( "www", + qw(LMachine Software Microsoft Inetsrv CurrentVersion) ) + or die "Can't check what version of IIS we are running: $^E\n"; + +=item ObjectRef + +=item $object_ref= $obj_or_hash_ref->ObjectRef + +For a simple object, just returns itself [C<$obj == $obj->ObjectRef>]. + +For a reference to a tied hash [if it is also an object], C<ObjectRef> +returns the simple object that the hash is tied to. + +This is primarilly useful when debugging since typing C<x $Registry> +will try to display your I<entire> registry contents to your screen. +But the debugger command C<x $Registry->ObjectRef> will just dump +the implementation details of the underlying object to your screen. + +=item Flush( $bFlush ) + +Flushes all cached information about the Registry key so that future +uses will get fresh data from the Registry. + +If the optional C<$bFlush> is specified and a true value, then +C<RegFlushKey()> will be called, which is almost never necessary. + +=item GetValue + +=item $ValueData= $key->GetValue( $sValueName ) + +=item ($ValueData,$ValueType)= $key->GetValue( $sValueName ) + +Gets a Registry value's data and data type. + +C<$ValueData> is usually just a Perl string that contains the +value data [packed into it]. For certain types of data, however, +C<$ValueData> may be processed as described below. + +C<$ValueType> is the C<REG_*> constant describing the type of value +data stored in C<$ValueData>. If the C<DualTypes()> option is on, +then C<$ValueType> will be a dual value. That is, when used in a +numeric context, C<$ValueType> will give the numeric value of a +C<REG_*> constant. However, when used in a non-numeric context, +C<$ValueType> will return the name of the C<REG_*> constant, for +example C<"REG_SZ"> [note the quotes]. So both of the following +can be true at the same time: + + $ValueType == REG_SZ() + $ValueType eq "REG_SZ" + +=over + +=item REG_SZ and REG_EXPAND_SZ + +If the C<FixSzNulls()> option is on, then the trailing C<'\0'> will be +stripped [unless there isn't one] before values of type C<REG_SZ> +and C<REG_EXPAND_SZ> are returned. Note that C<SetValue()> will add +a trailing C<'\0'> under similar circumstances. + +=item REG_MULTI_SZ + +If the C<SplitMultis()> option is on, then values of this type are +returned as a reference to an array containing the strings. For +example, a value that, with C<SplitMultis()> off, would be returned as: + + "Value1\000Value2\000\000" + +would be returned, with C<SplitMultis()> on, as: + + [ "Value1", "Value2" ] + +=item REG_DWORD + +If the C<DualBinVals()> option is on, then the value is returned +as a scalar containing both a string and a number [much like +the C<$!> variable -- see the L<SetDualVar> module for more +information] where the number part is the "unpacked" value. +Use the returned value in a numeric context to access this part +of the value. For example: + + $num= 0 + $Registry->{"CUser/Console//ColorTable01"}; + +If the C<DWordsToHex()> option is off, the string part of the +returned value is a packed, 4-byte string [use C<unpack("L",$value)> +to get the numeric value. + +If C<DWordsToHex()> is on, the string part of the returned value is +a 10-character hex strings [with leading "0x"]. You can use +C<hex($value)> to get the numeric value. + +Note that C<SetValue()> will properly understand each of these +returned value formats no matter how C<DualBinVals()> is set. + +=back + +=item ValueNames + +=item @names= $key->ValueNames + +Returns the list of value names stored directly in a Registry key. +Note that the names returned do I<not> have a delimiter prepended +to them like with C<MemberNames()> and tied hashes. + +Once you request this information, it is cached in the object and +future requests will always return the same list unless C<Flush()> +has been called. + +=item SubKeyNames + +=item @key_names= $key->SubKeyNames + +Returns the list of subkey names stored directly in a Registry key. +Note that the names returned do I<not> have a delimiter appended +to them like with C<MemberNames()> and tied hashes. + +Once you request this information, it is cached in the object and +future requests will always return the same list unless C<Flush()> +has been called. + +=item SubKeyClasses + +=item @classes= $key->SubKeyClasses + +Returns the list of classes for subkeys stored directly in a +Registry key. The classes are returned in the same order as +the subkey names returned by C<SubKeyNames()>. + +=item SubKeyTimes + +=item @times= $key->SubKeyTimes + +Returns the list of last-modified times for subkeys stored +directly in a Registry key. The times are returned in the same +order as the subkey names returned by C<SubKeyNames()>. Each +time is a C<FILETIME> structure packed into a Perl string. + +Once you request this information, it is cached in the object and +future requests will always return the same list unless C<Flush()> +has been called. + +=item MemberNames + +=item @members= $key->MemberNames + +Returns the list of subkey names and value names stored directly +in a Registry key. Subkey names have a delimiter appended to the +end and value names have a delimiter prepended to the front. + +Note that a value name could end in a delimiter [or could be C<""> +so that the member name returned is just a delimiter] so the +presence or absence of the leading delimiter is what should be +used to determine whether a particular name is for a subkey or a +value, not the presence or absence of a trailing delimiter. + +Once you request this information, it is cached in the object and +future requests will always return the same list unless C<Flush()> +has been called. + +=item Information + +=item %info= $key->Information + +=item @items= $key->Information( @itemNames ); + +Returns the following information about a Registry key: + +=over + +=item LastWrite + +A C<FILETIME> structure indicating when the key was last modified +and packed into a Perl string. + +=item CntSubKeys + +The number of subkeys stored directly in this key. + +=item CntValues + +The number of values stored directly in this key. + +=item SecurityLen + +The length [in bytes] of the largest[?] C<SECURITY_DESCRIPTOR> +associated with the Registry key. + +=item MaxValDataLen + +The length [in bytes] of the longest value data associated with +a value stored in this key. + +=item MaxSubKeyLen + +The length [in chars] of the longest subkey name associated with +a subkey stored in this key. + +=item MaxSubClassLen + +The length [in chars] of the longest class name associated with +a subkey stored directly in this key. + +=item MaxValNameLen + +The length [in chars] of the longest value name associated with +a value stored in this key. + +=back + +With no arguments, returns a hash [not a reference to a hash] where +the keys are the names for the items given above and the values +are the information describe above. For example: + + %info= ( "CntValues" => 25, # Key contains 25 values. + "MaxValNameLen" => 20, # One of which has a 20-char name. + "MaxValDataLen" => 42, # One of which has a 42-byte value. + "CntSubKeys" => 1, # Key has 1 immediate subkey. + "MaxSubKeyLen" => 13, # One of which has a 12-char name. + "MaxSubClassLen" => 0, # All of which have class names of "". + "SecurityLen" => 232, # One SECURITY_DESCRIPTOR is 232 bytes. + "LastWrite" => "\x90mZ\cX{\xA3\xBD\cA\c@\cA" + # Key was last modifed 1998/06/01 16:29:32 GMT + ); + +With arguments, each one must be the name of a item given above. +The return value is the information associated with the listed +names. In other words: + + return $key->Information( @names ); + +returns the same list as: + + %info= $key->Information; + return @info{@names}; + +=item Delimiter + +=item $oldDelim= $key->Delimiter + +=item $oldDelim= $key->Delimiter( $newDelim ) + +Gets and possibly changes the delimiter used for this object. The +delimiter is appended to subkey names and prepended to value names +in many return values. It is also used when parsing keys passed +to tied hashes. + +The delimiter defaults to backslash (C<'\\'>) but is inherited from +the object used to create a new object and can be specified by an +option when a new object is created. + +=item Handle + +=item $handle= $key->Handle + +Returns the raw C<HKEY> handle for the associated Registry key as +an integer value. This value can then be used to Reg*() calls +from I<Win32API::Registry>. However, it is usually easier to just +call the I<Win32API::Registry> calls directly via: + + $key->RegNotifyChangeKeyValue( ... ); + +For the virtual root of the local or a remote Registry, +C<Handle()> return C<"NONE">. + +=item Path + +=item $path= $key->Path + +Returns a string describing the path of key names to this +Registry key. The string is built so that if it were passed +to C<$Registry->Open()>, it would reopen the same Registry key +[except in the rare case where one of the key names contains +C<$key->Delimiter>]. + +=item Machine + +=item $computerName= $key->Machine + +Returns the name of the computer [or "machine"] on which this Registry +key resides. Returns C<""> for local Registry keys. + +=item Access + +Returns the numeric value of the bit mask used to specify the +types of access requested when this Registry key was opened. Can +be compared to C<KEY_*> values. + +=item OS_Delimiter + +Returns the delimiter used by the operating system's RegOpenKeyEx() +call. For Win32, this is always backslash (C<"\\">). + +=item Roots + +Returns the mapping from root key names like C<"LMachine"> to their +associated C<HKEY_*> constants. Primarily for internal use and +subject to change. + +=item Tie + +=item $key->Tie( \%hash ); + +Ties the referenced hash to that Registry key. Pretty much the +same as + + tie %hash, ref($key), $key; + +Since C<ref($key)> is the class [package] to tie the hash to and +C<TIEHASH()> just returns its argument, C<$key>, [without calling +C<new()>] when it sees that it is already a blessed object. + +=item TiedRef + +=item $TiedHashRef= $hash_or_obj_ref->TiedRef + +For a simple object, returns a reference to a hash tied to the +object. Used to promote a simple object into a combined object +and hash ref. + +If already a reference to a tied hash [that is also an object], +it just returns itself [C<$ref == $ref->TiedRef>]. + +Mostly used internally. + +=item ArrayValues + +=item $oldBool= $key->ArrayValues + +=item $oldBool= $key->ArrayValues( $newBool ) + +Gets the current setting of the C<ArrayValues> option and possibly +turns it on or off. + +When off, Registry values fetched via a tied hash are returned as +just a value scalar [the same as C<GetValue()> in a scalar context]. +When on, they are returned as a reference to an array containing +the value data as the C<[0]> element and the data type as the C<[1]> +element. + +=item TieValues + +=item $oldBool= TieValues + +=item $oldBool= TieValues( $newBool ) + +Gets the current setting of the C<TieValues> option and possibly +turns it on or off. + +Turning this option on is not yet supported in this release of +I<Win32::TieRegistry>. In a future release, turning this option +on will cause Registry values returned from a tied hash to be +a tied array that you can use to modify the value in the Registry. + +=item FastDelete + +=item $oldBool= $key->FastDelete + +=item $oldBool= $key->FastDelete( $newBool ) + +Gets the current setting of the C<FastDelete> option and possibly +turns it on or off. + +When on, successfully deleting a Registry key [via a tied hash] +simply returns C<1>. + +When off, successfully deleting a Registry key [via a tied hash +and not in a void context] returns a reference to a hash that +contains the values present in the key when it was deleted. This +hash is just like that returned when referencing the key before it +was deleted except that it is an ordinary hash, not one tied to +the I<Win32::TieRegistry> package. + +Note that deleting either a Registry key or value via a tied hash +I<in a void context> prevents any overhead in trying to build an +appropriate return value. + +Note that deleting a Registry I<value> via a tied hash [not in +a void context] returns the value data even if <FastDelete> is on. + +=item SplitMultis + +=item $oldBool= $key->SplitMultis + +=item $oldBool= $key->SplitMultis( $newBool ) + +Gets the current setting of the C<SplitMultis> option and possibly +turns it on or off. + +If on, Registry values of type C<REG_MULTI_SZ> are returned as +a reference to an array of strings. See C<GetValue()> for more +information. + +=item DWordsToHex + +=item $oldBool= $key->DWordsToHex + +=item $oldBool= $key->DWordsToHex( $newBool ) + +Gets the current setting of the C<DWordsToHex> option and possibly +turns it on or off. + +If on, Registry values of type C<REG_DWORD> are returned as a hex +string with leading C<"0x"> and longer than 4 characters. See +C<GetValue()> for more information. + +=item FixSzNulls + +=item $oldBool= $key->FixSzNulls + +=item $oldBool= $key->FixSzNulls( $newBool ) + +Gets the current setting of the C<FixSzNulls> option and possibly +turns it on or off. + +If on, Registry values of type C<REG_SZ> and C<REG_EXPAND_SZ> have +trailing C<'\0'>s added before they are set and stripped before +they are returned. See C<GetValue()> and C<SetValue()> for more +information. + +=item DualTypes + +=item $oldBool= $key->DualTypes + +=item $oldBool= $key->DualTypes( $newBool ) + +Gets the current setting of the C<DualTypes> option and possibly +turns it on or off. + +If on, data types are returned as a combined numeric/string value +holding both the numeric value of a C<REG_*> constant and the +string value of the constant's name. See C<GetValue()> for +more information. + +=item DualBinVals + +=item $oldBool= $key->DualBinVals + +=item $oldBool= $key->DualBinVals( $newBool ) + +Gets the current setting of the C<DualBinVals> option and possibly +turns it on or off. + +If on, Registry value data of type C<REG_BINARY> and no more than +4 bytes long and Registry values of type C<REG_DWORD> are returned +as a combined numeric/string value where the numeric value is the +"unpacked" binary value as returned by: + + hex reverse unpack( "h*", $valData ) + +on a "little-endian" computer. [Would be C<hex unpack("H*",$valData)> +on a "big-endian" computer if this module is ever ported to one.] + +See C<GetValue()> for more information. + +=item GetOptions + +=item @oldOptValues= $key->GetOptions( @optionNames ) + +=item $refHashOfOldOpts= $key->GetOptions() + +=item $key->GetOptions( \%hashForOldOpts ) + +Returns the current setting of any of the following options: + + Delimiter FixSzNulls DWordsToHex + ArrayValues SplitMultis DualBinVals + TieValues FastDelete DualTypes + +Pass in one or more of the above names (as strings) to get back +an array of the corresponding current settings in the same order: + + my( $fastDel, $delim )= $key->GetOptions("FastDelete","Delimiter"); + +Pass in no arguments to get back a reference to a hash where +the above option names are the keys and the values are +the corresponding current settings for each option: + + my $href= $key->GetOptions(); + my $delim= $href->{Delimiter}; + +Pass in a single reference to a hash to have the above key/value +pairs I<added> to the referenced hash. For this case, the +return value is the original object so further methods can be +chained after the call to GetOptions: + + my %oldOpts; + $key->GetOptions( \%oldOpts )->SetOptions( Delimiter => "/" ); + +=item SetOptions + +=item @oldOpts= $key->SetOptions( optNames=>$optValue,... ) + +Changes the current setting of any of the following options, +returning the previous setting(s): + + Delimiter FixSzNulls DWordsToHex AllowLoad + ArrayValues SplitMultis DualBinVals AllowSave + TieValues FastDelete DualTypes + +For C<AllowLoad> and C<AllowSave>, instead of the previous +setting, C<SetOptions> returns whether or not the change was +successful. + +In a scalar context, returns only the last item. The last +option can also be specified as C<"ref"> or C<"r"> [which doesn't +need to be followed by a value] to allow chaining: + + $key->SetOptions(AllowSave=>1,"ref")->RegSaveKey(...) + +=item SetValue + +=item $okay= $key->SetValue( $ValueName, $ValueData ); + +=item $okay= $key->SetValue( $ValueName, $ValueData, $ValueType ); + +Adds or replaces a Registry value. Returns a true value if +successfully, false otherwise. + +C<$ValueName> is the name of the value to add or replace and +should I<not> have a delimiter prepended to it. Case is ignored. + +C<$ValueType> is assumed to be C<REG_SZ> if it is omitted. Otherwise, +it should be one the C<REG_*> constants. + +C<$ValueData> is the data to be stored in the value, probably packed +into a Perl string. Other supported formats for value data are +listed below for each posible C<$ValueType>. + +=over + +=item REG_SZ or REG_EXPAND_SZ + +The only special processing for these values is the addition of +the required trailing C<'\0'> if it is missing. This can be +turned off by disabling the C<FixSzNulls> option. + +=item REG_MULTI_SZ + +These values can also be specified as a reference to a list of +strings. For example, the following two lines are equivalent: + + $key->SetValue( "Val1\000Value2\000LastVal\000\000", "REG_MULTI_SZ" ); + $key->SetValue( ["Val1","Value2","LastVal"], "REG_MULTI_SZ" ); + +Note that if the required two trailing nulls (C<"\000\000">) are +missing, then this release of C<SetValue()> will I<not> add them. + +=item REG_DWORD + +These values can also be specified as a hex value with the leading +C<"0x"> included and totaling I<more than> 4 bytes. These will be +packed into a 4-byte string via: + + $data= pack( "L", hex($data) ); + +=item REG_BINARY + +This value type is listed just to emphasize that no alternate +format is supported for it. In particular, you should I<not> pass +in a numeric value for this type of data. C<SetValue()> cannot +distinguish such from a packed string that just happens to match +a numeric value and so will treat it as a packed string. + +=back + +An alternate calling format: + + $okay= $key->SetValue( $ValueName, [ $ValueData, $ValueType ] ); + +[two arguments, the second of which is a reference to an array +containing the value data and value type] is supported to ease +using tied hashes with C<SetValue()>. + +=item CreateKey + +=item $newKey= $key->CreateKey( $subKey ); + +=item $newKey= $key->CreateKey( $subKey, { Option=>OptVal,... } ); + +Creates a Registry key or just updates attributes of one. Calls +C<RegCreateKeyEx()> then, if it succeeded, creates an object +associated with the [possibly new] subkey. + +C<$subKey> is the name of a subkey [or a path to one] to be +created or updated. It can also be a reference to an array +containing a list of subkey names. + +The second argument, if it exists, should be a reference to a +hash specifying options either to be passed to C<RegCreateKeyEx()> +or to be used when creating the associated object. The following +items are the supported keys for this options hash: + +=over + +=item Delimiter + +Specifies the delimiter to be used to parse C<$subKey> and to be +used in the new object. Defaults to C<$key->Delimiter>. + +=item Access + +Specifies the types of access requested when the subkey is opened. +Should be a numeric bit mask that combines one or more C<KEY_*> +constant values. + +=item Class + +The name to assign as the class of the new or updated subkey. +Defaults to C<""> as we have never seen a use for this information. + +=item Disposition + +Lets you specify a reference to a scalar where, upon success, will be +stored either C<REG_CREATED_NEW_KEY()> or C<REG_OPENED_EXISTING_KEY()> +depending on whether a new key was created or an existing key was +opened. + +If you, for example, did C<use Win32::TieRegistry qw(REG_CREATED_NEW_KEY)> +then you can use C<REG_CREATED_NEW_KEY()> to compare against the numeric +value stored in the referenced scalar. + +If the C<DualTypes> option is enabled, then in addition to the +numeric value described above, the referenced scalar will also +have a string value equal to either C<"REG_CREATED_NEW_KEY"> or +C<"REG_OPENED_EXISTING_KEY">, as appropriate. + +=item Security + +Lets you specify a C<SECURITY_ATTRIBUTES> structure packed into a +Perl string. See C<Win32API::Registry::RegCreateKeyEx()> for more +information. + +=item Volatile + +If true, specifies that the new key should be volatile, that is, +stored only in memory and not backed by a hive file [and not saved +if the computer is rebooted]. This option is ignored under +Windows 95. Specifying C<Volatile=E<GT>1> is the same as +specifying C<Options=E<GT>REG_OPTION_VOLATILE>. + +=item Backup + +If true, specifies that the new key should be opened for +backup/restore access. The C<Access> option is ignored. If the +calling process has enabled C<"SeBackupPrivilege">, then the +subkey is opened with C<KEY_READ> access as the C<"LocalSystem"> +user which should have access to all subkeys. If the calling +process has enabled C<"SeRestorePrivilege">, then the subkey is +opened with C<KEY_WRITE> access as the C<"LocalSystem"> user which +should have access to all subkeys. + +This option is ignored under Windows 95. Specifying C<Backup=E<GT>1> +is the same as specifying C<Options=E<GT>REG_OPTION_BACKUP_RESTORE>. + +=item Options + +Lets you specify options to the C<RegOpenKeyEx()> call. The value +for this option should be a numeric value combining zero or more +of the C<REG_OPTION_*> bit masks. You may with to used the +C<Volatile> and/or C<Backup> options instead of this one. + +=back + +=item StoreKey + +=item $newKey= $key->StoreKey( $subKey, \%Contents ); + +Primarily for internal use. + +Used to create or update a Registry key and any number of subkeys +or values under it or its subkeys. + +C<$subKey> is the name of a subkey to be created [or a path of +subkey names separated by delimiters]. If that subkey already +exists, then it is updated. + +C<\%Contents> is a reference to a hash containing pairs of +value names with value data and/or subkey names with hash +references similar to C<\%Contents>. Each of these cause +a value or subkey of C<$subKey> to be created or updated. + +If C<$Contents{""}> exists and is a reference to a hash, then +it used as the options argument when C<CreateKey()> is called +for C<$subKey>. This allows you to specify ... + + if( defined( $$data{""} ) && "HASH" eq ref($$data{""}) ) { + $self= $this->CreateKey( $subKey, delete $$data{""} ); + +=item Load + +=item $newKey= $key->Load( $file ) + +=item $newKey= $key->Load( $file, $newSubKey ) + +=item $newKey= $key->Load( $file, $newSubKey, { Option=>OptVal... } ) + +=item $newKey= $key->Load( $file, { Option=>OptVal... } ) + +Loads a hive file into a Registry. That is, creates a new subkey +and associates a hive file with it. + +C<$file> is a hive file, that is a file created by calling +C<RegSaveKey()>. The C<$file> path is interpreted relative to +C<%SystemRoot%/System32/config> on the machine where C<$key> +resides. + +C<$newSubKey> is the name to be given to the new subkey. If +C<$newSubKey> is specified, then C<$key> must be +C<HKEY_LOCAL_MACHINE> or C<HKEY_USERS> of the local computer +or a remote computer and C<$newSubKey> should not contain any +occurrences of either the delimiter or the OS delimiter. + +If C<$newSubKey> is not specified, then it is as if C<$key> +was C<$Registry-E<GT>{LMachine}> and C<$newSubKey> is +C<"PerlTie:999"> where C<"999"> is actually a sequence number +incremented each time this process calls C<Load()>. + +You can specify as the last argument a reference to a hash +containing options. You can specify the same options that you +can specify to C<Open()>. See C<Open()> for more information on +those. In addition, you can specify the option C<"NewSubKey">. +The value of this option is interpretted exactly as if it was +specified as the C<$newSubKey> parameter and overrides the +C<$newSubKey> if one was specified. + +The hive is automatically unloaded when the returned object +[C<$newKey>] is destroyed. Registry key objects opened within +the hive will keep a reference to the C<$newKey> object so that +it will not be destroyed before these keys are closed. + +=item UnLoad + +=item $okay= $key->UnLoad + +Unloads a hive that was loaded via C<Load()>. Cannot unload other +hives. C<$key> must be the return from a previous call to C<Load()>. +C<$key> is closed and then the hive is unloaded. + +=item AllowSave + +=item $okay= AllowSave( $bool ) + +Enables or disables the C<"ReBackupPrivilege"> privilege for the +current process. You will probably have to enable this privilege +before you can use C<RegSaveKey()>. + +The return value indicates whether the operation succeeded, not +whether the privilege was previously enabled. + +=item AllowLoad + +=item $okay= AllowLoad( $bool ) + +Enables or disables the C<"ReRestorePrivilege"> privilege for the +current process. You will probably have to enable this privilege +before you can use C<RegLoadKey()>, C<RegUnLoadKey()>, +C<RegReplaceKey()>, or C<RegRestoreKey> and thus C<Load()> and +C<UnLoad()>. + +The return value indicates whether the operation succeeded, not +whether the privilege was previously enabled. + +=back + +=head2 Exports [C<use> and C<import()>] + +To have nothing imported into your package, use something like: + + use Win32::TieRegistry 0.20 (); + +which would verify that you have at least version 0.20 but wouldn't +call C<import()>. The F<Changes> file can be useful in figuring out +which, if any, prior versions of I<Win32::TieRegistry> you want to +support in your script. + +The code + + use Win32::TieRegistry; + +imports the variable C<$Registry> into your package and sets it +to be a reference to a hash tied to a copy of the master Registry +virtual root object with the default options. One disadvantage +to this "default" usage is that Perl does not support checking +the module version when you use it. + +Alternately, you can specify a list of arguments on the C<use> +line that will be passed to the C<Win32::TieRegistry->import()> +method to control what items to import into your package. These +arguments fall into the following broad categories: + +=over + +=item Import a reference to a hash tied to a Registry virtual root + +You can request that a scalar variable be imported (possibly) +and set to be a reference to a hash tied to a Registry virtual root +using any of the following types of arguments or argument pairs: + +=over + +=item "TiedRef", '$scalar' + +=item "TiedRef", '$pack::scalar' + +=item "TiedRef", 'scalar' + +=item "TiedRef", 'pack::scalar' + +All of the above import a scalar named C<$scalar> into your package +(or the package named "pack") and then sets it. + +=item '$scalar' + +=item '$pack::scalar' + +These are equivalent to the previous items to support a more +traditional appearance to the list of exports. Note that the +scalar name cannot be "RegObj" here. + +=item "TiedRef", \$scalar + +=item \$scalar + +These versions don't import anything but set the referenced C<$scalar>. + +=back + +=item Import a hash tied to the Registry virtual root + +You can request that a hash variable be imported (possibly) +and tied to a Registry virtual root using any of the following +types of arguments or argument pairs: + +=over + +=item "TiedHash", '%hash' + +=item "TiedHash", '%pack::hash' + +=item "TiedHash", 'hash' + +=item "TiedHash", 'pack::hash' + +All of the above import a hash named C<%hash> into your package +(or the package named "pack") and then sets it. + +=item '%hash' + +=item '%pack::hash' + +These are equivalent to the previous items to support a more +traditional appearance to the list of exports. + +=item "TiedHash", \%hash + +=item \%hash + +These versions don't import anything but set the referenced C<%hash>. + +=back + +=item Import a Registry virtual root object + +You can request that a scalar variable be imported (possibly) +and set to be a Registry virtual root object using any of the +following types of arguments or argument pairs: + +=over + +=item "ObjectRef", '$scalar' + +=item "ObjectRef", '$pack::scalar' + +=item "ObjectRef", 'scalar' + +=item "ObjectRef", 'pack::scalar' + +All of the above import a scalar named C<$scalar> into your package +(or the package named "pack") and then sets it. + +=item '$RegObj' + +This is equivalent to the previous items for backward compatibility. + +=item "ObjectRef", \$scalar + +This version doesn't import anything but sets the referenced C<$scalar>. + +=back + +=item Import constant(s) exported by I<Win32API::Registry> + +You can list any constants that are exported by I<Win32API::Registry> +to have them imported into your package. These constants have names +starting with "KEY_" or "REG_" (or even "HKEY_"). + +You can also specify C<":KEY_">, C<":REG_">, and even C<":HKEY_"> to +import a whole set of constants. + +See I<Win32API::Registry> documentation for more information. + +=item Options + +You can list any option names that can be listed in the C<SetOptions()> +method call, each folowed by the value to use for that option. +A Registry virtual root object is created, all of these options are +set for it, then each variable to be imported/set is associated with +this object. + +In addition, the following special options are supported: + +=over + +=item ExportLevel + +Whether to import variables into your package or some +package that uses your package. Defaults to the value of +C<$Exporter::ExportLevel> and has the same meaning. See +the L<Exporter> module for more information. + +=item ExportTo + +The name of the package to import variables and constants into. +Overrides I<ExportLevel>. + +=back + +=back + +=head3 Specifying constants in your Perl code + +This module was written with a strong emphasis on the convenience of +the module user. Therefore, most places where you can specify a +constant like C<REG_SZ()> also allow you to specify a string +containing the name of the constant, C<"REG_SZ">. This is convenient +because you may not have imported that symbolic constant. + +Perl also emphasizes programmer convenience so the code C<REG_SZ> +can be used to mean C<REG_SZ()> or C<"REG_SZ"> or be illegal. +Note that using C<®_SZ> (as we've seen in much Win32 Perl code) +is not a good idea since it passes the current C<@_> to the +C<constant()> routine of the module which, at the least, can give +you a warning under B<-w>. + +Although greatly a matter of style, the "safest" practice is probably +to specifically list all constants in the C<use Win32::TieRegistry> +statement, specify C<use strict> [or at least C<use strict qw(subs)>], +and use bare constant names when you want the numeric value. This will +detect mispelled constant names at compile time. + + use strict; + my $Registry; + use Win32::TieRegistry 0.20 ( + TiedRef => \$Registry, Delimiter => "/", ArrayValues => 1, + SplitMultis => 1, AllowLoad => 1, + qw( REG_SZ REG_EXPAND_SZ REG_DWORD REG_BINARY REG_MULTI_SZ + KEY_READ KEY_WRITE KEY_ALL_ACCESS ), + ); + $Registry->{"LMachine/Software/FooCorp/"}= { + "FooWriter/" => { + "/Fonts" => [ ["Times","Courier","Lucinda"], REG_MULTI_SZ ], + "/WindowSize" => [ pack("LL",24,80), REG_BINARY ], + "/TaskBarIcon" => [ "0x0001", REG_DWORD ], + }, + } or die "Can't create Software/FooCorp/: $^E\n"; + +If you don't want to C<use strict qw(subs)>, the second safest practice +is similar to the above but use the C<REG_SZ()> form for constants +when possible and quoted constant names when required. Note that +C<qw()> is a form of quoting. + + use Win32::TieRegistry 0.20 qw( + TiedRef $Registry + Delimiter / ArrayValues 1 SplitMultis 1 AllowLoad 1 + REG_SZ REG_EXPAND_SZ REG_DWORD REG_BINARY REG_MULTI_SZ + KEY_READ KEY_WRITE KEY_ALL_ACCESS + ); + $Registry->{"LMachine/Software/FooCorp/"}= { + "FooWriter/" => { + "/Fonts" => [ ["Times","Courier","Lucinda"], REG_MULTI_SZ() ], + "/WindowSize" => [ pack("LL",24,80), REG_BINARY() ], + "/TaskBarIcon" => [ "0x0001", REG_DWORD() ], + }, + } or die "Can't create Software/FooCorp/: $^E\n"; + +The examples in this document mostly use quoted constant names +(C<"REG_SZ">) since that works regardless of which constants +you imported and whether or not you have C<use strict> in your +script. It is not the best choice for you to use for real +scripts (vs. examples) because it is less efficient and is not +supported by most other similar modules. + +=head1 SUMMARY + +Most things can be done most easily via tied hashes. Skip down to the +the L<Tied Hashes Summary> to get started quickly. + +=head2 Objects Summary + +Here are quick examples that document the most common functionality +of all of the method functions [except for a few almost useless ones]. + + # Just another way of saying Open(): + $key= new Win32::TieRegistry "LMachine\\Software\\", + { Access=>KEY_READ()|KEY_WRITE(), Delimiter=>"\\" }; + + # Open a Registry key: + $subKey= $key->Open( "SubKey/SubSubKey/", + { Access=>KEY_ALL_ACCESS, Delimiter=>"/" } ); + + # Connect to a remote Registry key: + $remKey= $Registry->Connect( "MachineName", "LMachine/", + { Access=>KEY_READ, Delimiter=>"/" } ); + + # Get value data: + $valueString= $key->GetValue("ValueName"); + ( $valueString, $valueType )= $key->GetValue("ValueName"); + + # Get list of value names: + @valueNames= $key->ValueNames; + + # Get list of subkey names: + @subKeyNames= $key->SubKeyNames; + + # Get combined list of value names (with leading delimiters) + # and subkey names (with trailing delimiters): + @memberNames= $key->MemberNames; + + # Get all information about a key: + %keyInfo= $key->Information; + # keys(%keyInfo)= qw( Class LastWrite SecurityLen + # CntSubKeys MaxSubKeyLen MaxSubClassLen + # CntValues MaxValNameLen MaxValDataLen ); + + # Get selected information about a key: + ( $class, $cntSubKeys )= $key->Information( "Class", "CntSubKeys" ); + + # Get and/or set delimiter: + $delim= $key->Delimiter; + $oldDelim= $key->Delimiter( $newDelim ); + + # Get "path" for an open key: + $path= $key->Path; + # For example, "/CUser/Control Panel/Mouse/" + # or "//HostName/LMachine/System/DISK/". + + # Get name of machine where key is from: + $mach= $key->Machine; + # Will usually be "" indicating key is on local machine. + + # Control different options (see main documentation for descriptions): + $oldBool= $key->ArrayValues( $newBool ); + $oldBool= $key->FastDelete( $newBool ); + $oldBool= $key->FixSzNulls( $newBool ); + $oldBool= $key->SplitMultis( $newBool ); + $oldBool= $key->DWordsToHex( $newBool ); + $oldBool= $key->DualBinVals( $newBool ); + $oldBool= $key->DualTypes( $newBool ); + @oldBools= $key->SetOptions( ArrayValues=>1, FastDelete=>1, FixSzNulls=>0, + Delimiter=>"/", AllowLoad=>1, AllowSave=>1 ); + @oldBools= $key->GetOptions( ArrayValues, FastDelete, FixSzNulls ); + + # Add or set a value: + $key->SetValue( "ValueName", $valueDataString ); + $key->SetValue( "ValueName", pack($format,$valueData), "REG_BINARY" ); + + # Add or set a key: + $key->CreateKey( "SubKeyName" ); + $key->CreateKey( "SubKeyName", + { Access=>"KEY_ALL_ACCESS", Class=>"ClassName", + Delimiter=>"/", Volatile=>1, Backup=>1 } ); + + # Load an off-line Registry hive file into the on-line Registry: + $newKey= $Registry->Load( "C:/Path/To/Hive/FileName" ); + $newKey= $key->Load( "C:/Path/To/Hive/FileName", "NewSubKeyName", + { Access=>"KEY_READ" } ); + # Unload a Registry hive file loaded via the Load() method: + $newKey->UnLoad; + + # (Dis)Allow yourself to load Registry hive files: + $success= $Registry->AllowLoad( $bool ); + + # (Dis)Allow yourself to save a Registry key to a hive file: + $success= $Registry->AllowSave( $bool ); + + # Save a Registry key to a new hive file: + $key->RegSaveKey( "C:/Path/To/Hive/FileName", [] ); + +=head3 Other Useful Methods + +See I<Win32API::Registry> for more information on these methods. +These methods are provided for coding convenience and are +identical to the I<Win32API::Registry> functions except that these +don't take a handle to a Registry key, instead getting the handle +from the invoking object [C<$key>]. + + $key->RegGetKeySecurity( $iSecInfo, $sSecDesc, $lenSecDesc ); + $key->RegLoadKey( $sSubKeyName, $sPathToFile ); + $key->RegNotifyChangeKeyValue( + $bWatchSubtree, $iNotifyFilter, $hEvent, $bAsync ); + $key->RegQueryMultipleValues( + $structValueEnts, $cntValueEnts, $Buffer, $lenBuffer ); + $key->RegReplaceKey( $sSubKeyName, $sPathToNewFile, $sPathToBackupFile ); + $key->RegRestoreKey( $sPathToFile, $iFlags ); + $key->RegSetKeySecurity( $iSecInfo, $sSecDesc ); + $key->RegUnLoadKey( $sSubKeyName ); + +=head2 Tied Hashes Summary + +For fast learners, this may be the only section you need to read. +Always append one delimiter to the end of each Registry key name +and prepend one delimiter to the front of each Registry value name. + +=head3 Opening keys + + use Win32::TieRegistry ( Delimiter=>"/", ArrayValues=>1 ); + $Registry->Delimiter("/"); # Set delimiter to "/". + $swKey= $Registry->{"LMachine/Software/"}; + $winKey= $swKey->{"Microsoft/Windows/CurrentVersion/"}; + $userKey= $Registry-> + {"CUser/Software/Microsoft/Windows/CurrentVersion/"}; + $remoteKey= $Registry->{"//HostName/LMachine/"}; + +=head3 Reading values + + $progDir= $winKey->{"/ProgramFilesDir"}; # "C:\\Program Files" + $tip21= $winKey->{"Explorer/Tips//21"}; # Text of tip #21. + + $winKey->ArrayValues(1); + ( $devPath, $type )= $winKey->{"/DevicePath"}; + # $devPath eq "%SystemRoot%\\inf" + # $type eq "REG_EXPAND_SZ" [if you have SetDualVar.pm installed] + # $type == REG_EXPAND_SZ() [if did C<use Win32::TieRegistry qw(:REG_)>] + +=head3 Setting values + + $winKey->{"Setup//SourcePath"}= "\\\\SwServer\\SwShare\\Windows"; + # Simple. Assumes data type of REG_SZ. + + $winKey->{"Setup//Installation Sources"}= + [ "D:\x00\\\\SwServer\\SwShare\\Windows\0\0", "REG_MULTI_SZ" ]; + # "\x00" and "\0" used to mark ends of each string and end of list. + + $winKey->{"Setup//Installation Sources"}= + [ ["D:","\\\\SwServer\\SwShare\\Windows"], "REG_MULTI_SZ" ]; + # Alternate method that is easier to read. + + $userKey->{"Explorer/Tips//DisplayInitialTipWindow"}= + [ pack("L",0), "REG_DWORD" ]; + $userKey->{"Explorer/Tips//Next"}= [ pack("S",3), "REG_BINARY" ]; + $userKey->{"Explorer/Tips//Show"}= [ pack("L",0), "REG_BINARY" ]; + +=head3 Adding keys + + $swKey->{"FooCorp/"}= { + "FooWriter/" => { + "/Version" => "4.032", + "Startup/" => { + "/Title" => "Foo Writer Deluxe ][", + "/WindowSize" => [ pack("LL",$wid,$ht), "REG_BINARY" ], + "/TaskBarIcon" => [ "0x0001", "REG_DWORD" ], + }, + "Compatibility/" => { + "/AutoConvert" => "Always", + "/Default Palette" => "Windows Colors", + }, + }, + "/License", => "0123-9C8EF1-09-FC", + }; + +=head3 Listing all subkeys and values + + @members= keys( %{$swKey} ); + @subKeys= grep( m#^/#, keys( %{$swKey->{"Classes/batfile/"}} ) ); + # @subKeys= ( "/", "/EditFlags" ); + @valueNames= grep( ! m#^/#, keys( %{$swKey->{"Classes/batfile/"}} ) ); + # @valueNames= ( "DefaultIcon/", "shell/", "shellex/" ); + +=head3 Deleting values or keys with no subkeys + + $oldValue= delete $userKey->{"Explorer/Tips//Next"}; + + $oldValues= delete $userKey->{"Explorer/Tips/"}; + # $oldValues will be reference to hash containing deleted keys values. + +=head3 Closing keys + + undef $swKey; # Explicit way to close a key. + $winKey= "Anything else"; # Implicitly closes a key. + exit 0; # Implicitly closes all keys. + +=head2 Tie::Registry + +This module was originally called I<Tie::Registry>. Changing code +that used I<Tie::Registry> over to I<Win32::TieRegistry> is trivial +as the module name should only be mentioned once, in the C<use> +line. However, finding all of the places that used I<Tie::Registry> +may not be completely trivial so we have included F<Tie/Registry.pm> +which you can install to provide backward compatibility. + +=head1 AUTHOR + +Tye McQueen. See http://www.metronet.com/~tye/ or e-mail +tye@metronet.com with bug reports. + +=head1 SEE ALSO + +I<Win32API::Registry> - Provides access to C<Reg*()>, C<HKEY_*>, +C<KEY_*>, C<REG_*> [required]. + +I<Win32::WinError> - Defines C<ERROR_*> values [optional]. + +L<SetDualVar> - For returning C<REG_*> values as combined +string/integer values [optional]. + +=head1 BUGS + +Perl5.004_02 has bugs that make I<Win32::TieRegistry> fail in +strange and subtle ways. + +Using I<Win32::TieRegistry> with versions of Perl prior to 5.005 +can be tricky or impossible. Most notes about this have been +removed from the documentation (they get rather complicated +and confusing). This includes references to C<$^E> perhaps not +being meaningful. + +Because Perl hashes are case sensitive, certain lookups are also +case sensistive. In particular, the root keys ("Classes", "CUser", +"LMachine", "Users", "PerfData", "CConfig", "DynData", and HKEY_*) +must always be entered without changing between upper and lower +case letters. Also, the special rule for matching subkey names +that contain the user-selected delimiter only works if case is +matched. All other key name and value name lookups should be case +insensitive because the underlying Reg*() calls ignore case. + +Information about each key is cached when using a tied hash. +This cache is not flushed nor updated when changes are made, +I<even when the same tied hash is used> to make the changes. + +Current implementations of Perl's "global destruction" phase can +cause objects returned by C<Load()> to be destroyed while keys +within the hive are still open, if the objects still exist when +the script starts to exit. When this happens, the automatic +C<UnLoad()> will report a failure and the hive will remain loaded +in the Registry. + +Trying to C<Load()> a hive file that is located on a remote network +share may silently delete all data from the hive. This is a bug +in the Win32 APIs, not any Perl code or modules. This module does +not try to protect you from this bug. + +There is no test suite. + +=head1 FUTURE DIRECTIONS + +The following items are desired by the author and may appear in a +future release of this module. + +=over + +=item TieValues option + +Currently described in main documentation but no yet implemented. + +=item AutoRefresh option + +Trigger use of C<RegNotifyChangeKeyValue()> to keep tied hash +caches up-to-date even when other programs make changes. + +=item Error options + +Allow the user to have unchecked calls (calls in a "void context") +to automatically report errors via C<warn> or C<die>. + +For complex operations, such a copying an entire subtree, provide +access to detailed information about errors (and perhaps some +warnings) that were encountered. Let the user control whether +the complex operation continues in spite of errors. + +=back + +=cut + +# Autoload not currently supported by Perl under Windows. diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32API/Registry.pm b/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32API/Registry.pm new file mode 100644 index 00000000000..dbf98b4e2e9 --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32API/Registry.pm @@ -0,0 +1,1792 @@ +# Registry.pm -- Low-level access to functions/constants from WINREG.h + +package Win32API::Registry; + +use strict; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); #@EXPORT_FAIL); +$VERSION= '0.24'; + +require Exporter; +require DynaLoader; +@ISA= qw(Exporter DynaLoader); + +@EXPORT= qw(); +%EXPORT_TAGS= ( + Func => [qw( regConstant regLastError + AllowPriv AbortSystemShutdown InitiateSystemShutdown + RegCloseKey RegConnectRegistry RegCreateKey + RegCreateKeyEx RegDeleteKey RegDeleteValue + RegEnumKey RegEnumKeyEx RegEnumValue + RegFlushKey RegGetKeySecurity RegLoadKey + RegNotifyChangeKeyValue RegOpenKey RegOpenKeyEx + RegQueryInfoKey RegQueryMultipleValues RegQueryValue + RegQueryValueEx RegReplaceKey RegRestoreKey + RegSaveKey RegSetKeySecurity RegSetValue + RegSetValueEx RegUnLoadKey )], + FuncA => [qw( + AbortSystemShutdownA InitiateSystemShutdownA + RegConnectRegistryA RegCreateKeyA RegCreateKeyExA + RegDeleteKeyA RegDeleteValueA RegEnumKeyA + RegEnumKeyExA RegEnumValueA RegLoadKeyA + RegOpenKeyA RegOpenKeyExA RegQueryInfoKeyA + RegQueryMultipleValuesA RegQueryValueA RegQueryValueExA + RegReplaceKeyA RegRestoreKeyA RegSaveKeyA + RegSetValueA RegSetValueExA RegUnLoadKeyA )], + FuncW => [qw( + AbortSystemShutdownW InitiateSystemShutdownW + RegConnectRegistryW RegCreateKeyW RegCreateKeyExW + RegDeleteKeyW RegDeleteValueW RegEnumKeyW + RegEnumKeyExW RegEnumValueW RegLoadKeyW + RegOpenKeyW RegOpenKeyExW RegQueryInfoKeyW + RegQueryMultipleValuesW RegQueryValueW RegQueryValueExW + RegReplaceKeyW RegRestoreKeyW RegSaveKeyW + RegSetValueW RegSetValueExW RegUnLoadKeyW )], + HKEY_ => [qw( + HKEY_CLASSES_ROOT HKEY_CURRENT_CONFIG HKEY_CURRENT_USER + HKEY_DYN_DATA HKEY_LOCAL_MACHINE HKEY_PERFORMANCE_DATA + HKEY_USERS )], + KEY_ => [qw( + KEY_QUERY_VALUE KEY_SET_VALUE KEY_CREATE_SUB_KEY + KEY_ENUMERATE_SUB_KEYS KEY_NOTIFY KEY_CREATE_LINK + KEY_READ KEY_WRITE KEY_EXECUTE + KEY_ALL_ACCESS), + 'KEY_DELETE', # DELETE (0x00010000L) + 'KEY_READ_CONTROL', # READ_CONTROL (0x00020000L) + 'KEY_WRITE_DAC', # WRITE_DAC (0x00040000L) + 'KEY_WRITE_OWNER', # WRITE_OWNER (0x00080000L) + 'KEY_SYNCHRONIZE', # SYNCHRONIZE (0x00100000L) (not used) + ], + REG_ => [qw( + REG_OPTION_RESERVED REG_OPTION_NON_VOLATILE REG_OPTION_VOLATILE + REG_OPTION_CREATE_LINK REG_OPTION_BACKUP_RESTORE + REG_OPTION_OPEN_LINK REG_LEGAL_OPTION REG_CREATED_NEW_KEY + REG_OPENED_EXISTING_KEY REG_WHOLE_HIVE_VOLATILE REG_REFRESH_HIVE + REG_NO_LAZY_FLUSH REG_NOTIFY_CHANGE_ATTRIBUTES + REG_NOTIFY_CHANGE_NAME REG_NOTIFY_CHANGE_LAST_SET + REG_NOTIFY_CHANGE_SECURITY REG_LEGAL_CHANGE_FILTER + REG_NONE REG_SZ REG_EXPAND_SZ + REG_BINARY REG_DWORD REG_DWORD_LITTLE_ENDIAN + REG_DWORD_BIG_ENDIAN REG_LINK REG_MULTI_SZ + REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR + REG_RESOURCE_REQUIREMENTS_LIST )], + SE_ => [qw( + SE_ASSIGNPRIMARYTOKEN_NAME SE_AUDIT_NAME + SE_BACKUP_NAME SE_CHANGE_NOTIFY_NAME + SE_CREATE_PAGEFILE_NAME SE_CREATE_PERMANENT_NAME + SE_CREATE_TOKEN_NAME SE_DEBUG_NAME + SE_INCREASE_QUOTA_NAME SE_INC_BASE_PRIORITY_NAME + SE_LOAD_DRIVER_NAME SE_LOCK_MEMORY_NAME + SE_MACHINE_ACCOUNT_NAME SE_PROF_SINGLE_PROCESS_NAME + SE_REMOTE_SHUTDOWN_NAME SE_RESTORE_NAME + SE_SECURITY_NAME SE_SHUTDOWN_NAME + SE_SYSTEMTIME_NAME SE_SYSTEM_ENVIRONMENT_NAME + SE_SYSTEM_PROFILE_NAME SE_TAKE_OWNERSHIP_NAME + SE_TCB_NAME SE_UNSOLICITED_INPUT_NAME )], +); +@EXPORT_OK= (); +{ my $ref; + foreach $ref ( values(%EXPORT_TAGS) ) { + push( @EXPORT_OK, @$ref ) unless $ref->[0] =~ /^SE_/; + } +} +$EXPORT_TAGS{ALL}= [ @EXPORT_OK ]; # \@EXPORT_OK once SE_* settles down. +# push( @EXPORT_OK, "JHEREG_TACOSALAD" ); # Used to test Mkconst2perl +push( @EXPORT_OK, @{$EXPORT_TAGS{SE_}} ); + +bootstrap Win32API::Registry $VERSION; + +# Preloaded methods go here. + +# To convert C constants to Perl code in cRegistry.pc +# [instead of C or C++ code in cRegistry.h]: +# * Modify F<Makefile.PL> to add WriteMakeFile() => +# CONST2PERL/postamble => [[ "Win32API::Registry" => ]] WRITE_PERL => 1. +# * Either comment out C<#include "cRegistry.h"> from F<Registry.xs> +# or make F<cRegistry.h> an empty file. +# * Make sure the following C<if> block is not commented out. +# * "nmake clean", "perl Makefile.PL", "nmake" + +if( ! defined ®_NONE ) { + require "Win32API/Registry/cRegistry.pc"; +} + +# This would be convenient but inconsistant and hard to explain: +#push( @{$EXPORT_TAGS{ALL}}, @{$EXPORT_TAGS{SE_}} ) +# if defined &SE_TCB_NAME; + +sub regConstant +{ + my( $name )= @_; + if( 1 != @_ || ! $name || $name =~ /\W/ ) { + require Carp; + Carp::croak( 'Usage: ',__PACKAGE__,'::regConstant("CONST_NAME")' ); + } + my $proto= prototype $name; + if( defined \&$name + && defined $proto + && "" eq $proto ) { + no strict 'refs'; + return &$name; + } + return undef; +} + +# We provide this for backwards compatibility: +sub constant +{ + my( $name )= @_; + my $value= regConstant( $name ); + if( defined $value ) { + $!= 0; + return $value; + } + $!= 11; # EINVAL + return 0; +} + +# BEGIN { +# my $code= 'return _regLastError(@_)'; +# local( $!, $^E )= ( 1, 1 ); +# if( $! ne $^E ) { +# $code= ' +# local( $^E )= _regLastError(@_); +# my $ret= $^E; +# return $ret; +# '; +# } +# eval "sub regLastError { $code }"; +# die "$@" if $@; +# } + +package Win32API::Registry::_error; + +use overload + '""' => sub { + require Win32 unless defined &Win32::FormatMessage; + $_ = Win32::FormatMessage(Win32API::Registry::_regLastError()); + tr/\r\n//d; + return $_; + }, + '0+' => sub { Win32API::Registry::_regLastError() }, + 'fallback' => 1; + +sub new { return bless {}, shift } +sub set { Win32API::Registry::_regLastError($_[1]); return $_[0] } + +package Win32API::Registry; + +my $_error = new Win32API::Registry::_error; + +sub regLastError { + require Carp; + Carp::croak('Usage: ',__PACKAGE__,'::regLastError( [$setWin32ErrCode] )') if @_ > 1; + $_error->set($_[0]) if defined $_[0]; + return $_error; +} + +# Since we ISA DynaLoader which ISA AutoLoader, we ISA AutoLoader so we +# need this next chunk to prevent Win32API::Registry->nonesuch() from +# looking for "nonesuch.al" and producing confusing error messages: +use vars qw($AUTOLOAD); +sub AUTOLOAD { + require Carp; + Carp::croak( + "Can't locate method $AUTOLOAD via package Win32API::Registry" ); +} + +# Replace "&rout;" with "goto &rout;" when that is supported on Win32. + +# Let user omit all buffer sizes: +sub RegEnumKeyExA { + if( 6 == @_ ) { splice(@_,4,0,[]); splice(@_,2,0,[]); } + &_RegEnumKeyExA; +} +sub RegEnumKeyExW { + if( 6 == @_ ) { splice(@_,4,0,[]); splice(@_,2,0,[]); } + &_RegEnumKeyExW; +} +sub RegEnumValueA { + if( 6 == @_ ) { splice(@_,2,0,[]); push(@_,[]); } + &_RegEnumValueA; +} +sub RegEnumValueW { + if( 6 == @_ ) { splice(@_,2,0,[]); push(@_,[]); } + &_RegEnumValueW; +} +sub RegQueryInfoKeyA { + if( 11 == @_ ) { splice(@_,2,0,[]); } + &_RegQueryInfoKeyA; +} +sub RegQueryInfoKeyW { + if( 11 == @_ ) { splice(@_,2,0,[]); } + &_RegQueryInfoKeyW; +} + +sub RegEnumKeyA { + push(@_,[]) if 3 == @_; + &_RegEnumKeyA; +} +sub RegEnumKeyW { + push(@_,[]) if 3 == @_; + &_RegEnumKeyW; +} +sub RegGetKeySecurity { + push(@_,[]) if 3 == @_; + &_RegGetKeySecurity; +} +sub RegQueryMultipleValuesA { + push(@_,[]) if 4 == @_; + &_RegQueryMultipleValuesA; +} +sub RegQueryMultipleValuesW { + push(@_,[]) if 4 == @_; + &_RegQueryMultipleValuesW; +} +sub RegQueryValueA { + push(@_,[]) if 3 == @_; + &_RegQueryValueA; +} +sub RegQueryValueW { + push(@_,[]) if 3 == @_; + &_RegQueryValueW; +} +sub RegQueryValueExA { + push(@_,[]) if 5 == @_; + &_RegQueryValueExA; +} +sub RegQueryValueExW { + push(@_,[]) if 5 == @_; + &_RegQueryValueExW; +} +sub RegSetValueA { + push(@_,0) if 4 == @_; + &_RegSetValueA; +} +sub RegSetValueW { + push(@_,0) if 4 == @_; + &_RegSetValueW; +} +sub RegSetValueExA { + push(@_,0) if 5 == @_; + &_RegSetValueExA; +} +sub RegSetValueExW { + push(@_,0) if 5 == @_; + &_RegSetValueExW; +} + +# Aliases for non-Unicode functions: +sub AbortSystemShutdown { &AbortSystemShutdownA; } +sub InitiateSystemShutdown { &InitiateSystemShutdownA; } +sub RegConnectRegistry { &RegConnectRegistryA; } +sub RegCreateKey { &RegCreateKeyA; } +sub RegCreateKeyEx { &RegCreateKeyExA; } +sub RegDeleteKey { &RegDeleteKeyA; } +sub RegDeleteValue { &RegDeleteValueA; } +sub RegEnumKey { &RegEnumKeyA; } +sub RegEnumKeyEx { &RegEnumKeyExA; } +sub RegEnumValue { &RegEnumValueA; } +sub RegLoadKey { &RegLoadKeyA; } +sub RegOpenKey { &RegOpenKeyA; } +sub RegOpenKeyEx { &RegOpenKeyExA; } +sub RegQueryInfoKey { &RegQueryInfoKeyA; } +sub RegQueryMultipleValues { &RegQueryMultipleValuesA; } +sub RegQueryValue { &RegQueryValueA; } +sub RegQueryValueEx { &RegQueryValueExA; } +sub RegReplaceKey { &RegReplaceKeyA; } +sub RegRestoreKey { &RegRestoreKeyA; } +sub RegSaveKey { &RegSaveKeyA; } +sub RegSetValue { &RegSetValueA; } +sub RegSetValueEx { &RegSetValueExA; } +sub RegUnLoadKey { &RegUnLoadKeyA; } + +1; +__END__ + +=head1 NAME + +Win32API::Registry - Low-level access to Win32 system API calls from WINREG.H + +=head1 SYNOPSIS + + use Win32API::Registry 0.21 qw( :ALL ); + + RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\Disk", 0, KEY_READ, $key ); + or die "Can't open HKEY_LOCAL_MACHINE\\SYSTEM\\Disk: ", + regLastError(),"\n"; + RegQueryValueEx( $key, "Information", [], $type, $data, [] ); + or die "Can't read HKEY_L*MACHINE\\SYSTEM\\Disk\\Information: ", + regLastError(),"\n"; + [...] + RegCloseKey( $key ) + or die "Can't close HKEY_LOCAL_MACHINE\\SYSTEM\\Disk: ", + regLastError(),"\n"; + +=head1 DESCRIPTION + +This provides fairly low-level access to the Win32 System API +calls dealing with the Registry [mostly from WINREG.H]. This +is mostly intended to be used by other modules such as +C<Win32::TieRegistry> [which provides an extremely Perl-friendly +method for using the Registry]. + +For a description of the logical structure of the Registry, see +the documentation for the C<Win32::TieRegistry> module. + +To pass in C<NULL> as the pointer to an optional buffer, pass in +an empty list reference, C<[]>. + +Beyond raw access to the API calls and related constants, this module +handles smart buffer allocation and translation of return codes. + +All calls return a true value for success and a false value for +failure. After any failure, C<$^E> should automatically be set +to indicate the reason. However, current versions of Perl often +overwrite C<$^E> too quickly, so you can use C<regLastError()> +instead, which is only set by Win32API::Registry routines. + +Note that C<$!> is not set by these routines except by +C<Win32API::Registry::constant()> when a constant is not defined. + +=head2 Exports + +Nothing is exported by default. The following tags can be used to +have sets of symbols exported. + +[Note that much of the following documentation refers to the +behavior of the underlying API calls which may vary in current +and future versions of the Win32 API without any changes to this +module. Therefore you should check the Win32 API documentation +directly when needed.] + +=over + +=item :Func + +The basic function names: + +=over + +=item AllowPriv + +=item C<AllowPriv( $sPrivName, $bEnable )> + +Not a Win32 API call. Enables or disables a specific privilege for +the current process. Returns a true value if successful and a false +value [and sets C<$^E>/C<regLastError()>] on failure. This routine +does not provide a way to tell if a privilege is currently enabled. + +C<$sPrivname> is a Win32 privilege name [see L</:SE_>]. For example, +C<"SeBackupPrivilege"> [a.k.a. C<SE_BACKUP_NAME>] controls whether +you can use C<RegSaveKey()> and C<"SeRestorePrivilege"> [a.k.a. +C<SE_RESTORE_NAME>] controls whether you can use C<RegLoadKey()>. + +If C<$bEnable> is true, then C<AllowPriv()> tries to enable the +privilege. Otherwise it tries to disable the privilege. + +=item AbortSystemShutdown + +=item C<AbortSystemShutdown( $sComputerName )> + +Tries to abort a remote shutdown request previously made via +C<InitiateSystemShutdown()>. Returns a true value if successful +and a false value [and sets C<$^E>/C<regLastError()>] on failure. + +=item InitiateSystemShutdown + +=item C<InitiateSystemShutdown( $sComputer, $sMessage, $uTimeoutSecs, $bForce, $bReboot )> + +Requests that a [remote] computer be shutdown or rebooted. +Returns a true value if successful and a false value [and +sets C<$^E>/C<regLastError()>] on failure. + +C<$sComputer> is the name [or address] of the computer to be +shutdown or rebooted. You can use C<[]> [for C<NULL>] or C<""> +to indicate the local computer. + +C<$sMessage> is the message to be displayed in a pop-up window +on the desktop of the computer to be shutdown or rebooted until +the timeout expires or the shutdown is aborted via +C<AbortSystemShutdown()>. With C<$iTimeoutSecs == 0>, the +message will never be visible. + +C<$iTimeoutSecs> is the number of seconds to wait before starting +the shutdown. + +If C<$bForce> is false, then any applications running on the remote +computer get a chance to prompt the remote user whether they want +to save changes. Also, for any applications that do not exit quickly +enough, the operating system will prompt the user whether they wish +to wait longer for the application to exit or force it to exit now. +At any of these prompts the user can press B<CANCEL> to abort the +shutdown but if no applications have unsaved data, they will likely +all exit quickly and the shutdown will progress with the remote user +having no option to cancel the shutdown. + +If C<$bForce> is true, all applications are told to exit immediately +and so will not prompt the user even if there is unsaved data. Any +applications that take too long to exit will be forcibly killed after +a short time. The only way to abort the shutdown is to call +C<AbortSystemShutdown()> before the timeout expires and there is no +way to abort the shutdown once it has begun. + +If C<$bReboot> is true, the computer will automatically reboot once +the shutdown is complete. If C<$bReboot> is false, then when the +shutdown is complete the computer will halt at a screen indicating +that the shutdown is complete and offering a way for the user to +start to boot the computer. + +You must have the C<"SeRemoteShutdownPrivilege"> privilege +on the remote computer for this call to succeed. If shutting +down the local computer, then the calling process must have +the C<"SeShutdownPrivilege"> privilege and have it enabled. + +=item RegCloseKey + +=item C<RegCloseKey( $hKey )> + +Closes the handle to a Registry key returned by C<RegOpenKeyEx()>, +C<RegConnectRegistry()>, C<RegCreateKeyEx()>, or a few other +routines. Returns a true value if successful and a false value +[and sets C<$^E>/C<regLastError()>] on failure. + +=item RegConnectRegistry + +=item C<RegConnectRegistry( $sComputer, $hRootKey, $ohKey )> + +Connects to one of the root Registry keys of a remote computer. +Returns a true value if successful and a false value [and +sets C<$^E>/C<regLastError()>] on failure. + +C<$sComputer> is the name [or address] of a remote computer +whose Registry you wish to access. + +C<$hKey> must be either C<HKEY_LOCAL_MACHINE> or C<HKEY_USERS> +and specifies which root Registry key on the remote computer +you wish to have access to. + +C<$phKey> will be set to the handle to be used to access the +remote Registry key if the call succeeds. + +=item regConstant + +=item C<$value= regConstant( $sConstantName )> + +Fetch the value of a constant. Returns C<undef> if C<$sConstantName> +is not the name of a constant supported by this module. Never sets +C<$!> nor C<$^E>. + +This function is rarely used since you will usually get the value of a +constant by having that constant imported into your package by listing +the constant name in the C<use Win32API::Registry> statement and then +simply using the constant name in your code [perhaps followed by +C<()>]. This function is useful for verifying constant names not in +Perl code, for example, after prompting a user to type in a constant +name. + +=item RegCreateKey + +=item C<RegCreateKey( $hKey, $sSubKey, $ohSubKey )> + +This routine is meant only for compatibility with Windows version +3.1. Use C<RegCreateKeyEx()> instead. + +=item RegCreateKeyEx + +=item C<RegCreateKeyEx( $hKey, $sSubKey, $uZero, $sClass, $uOpts, $uAccess, $pSecAttr, $ohNewKey, $ouDisp )> + +Creates a new Registry subkey. Returns a true value if successful and +a false value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sSubKey> is the name of the new subkey to be created. + +C<$iZero> is reserved for future use and should always be specified +as C<0>. + +C<$sClass> is a string to be used as the class for the new +subkey. We are not aware of any current use for Registry key +class information so the empty string, C<"">, should usually +be used here. + +C<$iOpts> is a numeric value containing bits that control options +used while creating the new subkey. C<REG_OPTION_NON_VOLATILE> +is the default. C<REG_OPTION_VOLATILE> [which is ignored on +Windows 95] means the data stored under this key is not kept +in a file and will not be preserved when the system reboots. +C<REG_OPTION_BACKUP_RESTORE> [also ignored on Windows 95] means +ignore the C<$iAccess> parameter and try to open the new key with +the access required to backup or restore the key. + +C<$iAccess> is a numeric mask of bits specifying what type of +access is desired when opening the new subkey. See C<RegOpenKeyEx()>. + +C<$pSecAttr> is a C<SECURITY_ATTRIBUTES> structure packed into +a Perl string which controls whether the returned handle can be +inherited by child processes. Normally you would pass C<[]> for +this parameter to have C<NULL> passed to the underlying API +indicating that the handle cannot be inherited. If not under +Windows95, then C<$pSecAttr> also allows you to specify +C<SECURITY_DESCRIPTOR> that controls which users will have +what type of access to the new key -- otherwise the new key +inherits its security from its parent key. + +C<$phKey> will be set to the handle to be used to access the new +subkey if the call succeeds. + +C<$piDisp> will be set to either C<REG_CREATED_NEW_KEY> or +C<REG_OPENED_EXISTING_KEY> to indicate for which reason the +call succeeded. Can be specified as C<[]> if you don't care. + +If C<$phKey> and C<$piDisp> start out as integers, then they will +probably remain unchanged if the call fails. + +=item RegDeleteKey + +=item C<RegDeleteKey( $hKey, $sSubKey )> + +Deletes a subkey of an open Registry key provided that the subkey +contains no subkeys of its own [but the subkey may contain values]. +Returns a true value if successful and a false value [and sets +C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sSubKey> is the name of the subkey to be deleted. + +=item RegDeleteValue + +=item C<RegDeleteValue( $hKey, $sValueName )> + +Deletes a value from an open Registry key. Returns a true value if +successful and a false value [and sets C<$^E>/C<regLastError()>] on +failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sValueKey> is the name of the value to be deleted. + +=item RegEnumKey + +=item C<RegEnumKey( $hKey, $uIndex, $osName, $ilNameSize )> + +This routine is meant only for compatibility with Windows version +3.1. Use C<RegEnumKeyEx()> instead. + +=item RegEnumKeyEx + +=item C<RegEnumKeyEx( $hKey, $uIndex, $osName, $iolName, $pNull, $osClass, $iolClass, $opftLastWrite )> + +Lets you enumerate the names of all of the subkeys directly under +an open Registry key. Returns a true value if successful and a false +value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$iIndex> is the sequence number of the immediate subkey that +you want information on. Start with this value as C<0> then +repeat the call incrementing this value each time until the +call fails with C<$^E>/C<regLastError()> numerically equal to +C<ERROR_NO_MORE_ITEMS>. + +C<$sName> will be set to the name of the subkey. Can be C<[]> if +you don't care about the name. + +C<$plName> initially specifies the [minimum] buffer size to be +allocated for C<$sName>. Will be set to the length of the subkey +name if the requested subkey exists even if C<$sName> isn't +successfully set to the subkey name. See L<Buffer sizes> for +more information. + +C<$pNull> is reserved for future used and should be passed as C<[]>. + +C<$sClass> will be set to the class name for the subkey. Can be +C<[]> if you don't care about the class. + +C<$plClass> initially specifies the [minimum] buffer size to be +allocated for C<$sClass> and will be set to the length of the +subkey class name if the requested subkey exists. See L<Buffer +sizes> for more information. + +C<$pftLastWrite> will be set to a C<FILETIME> structure packed +into a Perl string and indicating when the subkey was last changed. +Can be C<[]>. + +You may omit both C<$plName> and C<$plClass> to get the same effect +as passing in C<[]> for each of them. + +=item RegEnumValue + +=item C<RegEnumValue( $hKey, $uIndex, $osValName, $iolValName, $pNull, $ouType, $opValData, $iolValData )> + +Lets you enumerate the names of all of the values contained in an +open Registry key. Returns a true value if successful and a false +value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$iIndex> is the sequence number of the value that you want +information on. Start with this value as C<0> then repeat the +call incrementing this value each time until the call fails with +C<ERROR_NO_MORE_ITEMS>. + +C<$sValName> will be set to the name of the value. Can be C<[]> +if you don't care about the name. + +C<$plValName> initially specifies the [minimum] buffer size to be +allocated for C<$sValName>. Will be set to the length of the value +name if the requested value exists even if C<$sValName> isn't +successfully set to the value name. See L<Buffer sizes> for +more information. + +C<$pNull> is reserved for future used and should be passed as C<[]>. + +C<$piType> will be set to the type of data stored in the value data. +If the call succeeds, it will be set to a C<REG_*> value unless +passed in as C<[]>. + +C<$pValData> will be set to the data [packed into a Perl string] +that is stored in the requested value. Can be C<[]> if you don't +care about the value data. + +C<$plValData> initially specifies the [minimum] buffer size to be +allocated for C<$sValData> and will be set to the length of the +value data if the requested value exists. See L<Buffer sizes> for +more information. + +You may omit both C<$plValName> and C<$plValData> to get the same +effect as passing in C<[]> for each of them. + +=item RegFlushKey + +=item C<RegFlushKey( $hKey )> + +Forces the data stored under an open Registry key to be flushed +to the disk file where the data is preserved between reboots. +Forced flushing is not guaranteed to be efficient so this routine +should almost never be called. Returns a true value if successful +and a false value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +=item RegGetKeySecurity + +=item C<RegGetKeySecurity( $hKey, $uSecInfo, $opSecDesc, $iolSecDesc )> + +Retrieves one of the C<SECURITY_DESCRIPTOR> structures describing +part of the security for an open Registry key. Returns a true value +if successful and a false value [and sets C<$^E>/C<regLastError()>] +on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$iSecInfo> is a numeric C<SECURITY_INFORMATION> value that +specifies which parts of the C<SECURITY_DESCRIPTOR> structure +to retrieve. Should be C<OWNER_SECURITY_INFORMATION>, +C<GROUP_SECURITY_INFORMATION>, C<DACL_SECURITY_INFORMATION>, or +or C<SACL_SECURITY_INFORMATION> or two or more of these bits +combined using C<|>. + +C<$pSecDesc> will be set to the requested C<SECURITY_DESCRIPTOR> +structure [packed into a Perl string]. + +C<$plSecDesc> initially specifies the [minimum] buffer size to be +allocated for C<$sSecDesc> and will be set to the length of the +security descriptor. See L<Buffer sizes> for more information. +You may omit this parameter to get the same effect as passing in +C<[]> for it. + +=item regLastError + +=item C<$svError= regLastError();> + +=item C<regLastError( $uError );> + +Returns the last error encountered by a routine from this module. +It is just like C<$^E> except it isn't changed by anything except +routines from this module. Ideally you could just use C<$^E>, but +current versions of Perl often overwrite C<$^E> before you get a +chance to check it and really old versions of Perl don't really +support C<$^E> under Win32. + +Just like C<$^E>, in a numeric context C<regLastError()> returns +the numeric error value while in a string context it returns a +text description of the error [actually it returns a Perl scalar +that contains both values so C<$x= regLastError()> causes C<$x> +to give different values in string vs. numeric contexts]. + +The last form sets the error returned by future calls to +C<regLastError()> and should not be used often. C<$uError> must +be a numeric error code. Also returns the dual-valued version +of C<$uError>. + +=item RegLoadKey + +=item C<RegLoadKey( $hKey, $sSubKey, $sFileName )> + +Loads a hive file. That is, it creates a new subkey in the +Registry and associates that subkey with a disk file that contains +a Registry hive so that the new subkey can be used to access the +keys and values stored in that hive. Hives are usually created +via C<RegSaveKey()>. Returns a true value if successful and a +false value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key that can have hives +loaded to it. This must be C<HKEY_LOCAL_MACHINE>, C<HKEY_USERS>, +or a remote version of one of these from a call to +C<RegConnectRegistry()>. + +C<$sSubKey> is the name of the new subkey to created and associated +with the hive file. + +C<$sFileName> is the name of the hive file to be loaded. This +file name is interpretted relative to the +C<%SystemRoot%/System32/config> directory on the computer where +the C<$hKey> key resides. If C<$sFileName> is on a FAT file +system, then its name must not have an extension. + +You must have the C<SE_RESTORE_NAME> privilege to use this routine. + +WARNING: Loading of hive files via a network share may silently +corrupt the hive and so should not be attempted [this is a problem +in at least some versions of the underlying API which this module +does not try to fix or avoid]. To access a hive file located on a +remote computer, connect to the remote computer's Registry and load +the hive via that. + +=item RegNotifyChangeKeyValue + +=item C<RegNotifyChangeKeyValue( $hKey, $bWatchSubtree, $uNotifyFilter, $hEvent, $bAsync )> + +Arranges for your process to be notified when part of the Registry +is changed. Returns a true value if successful and a false value +[and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call] for which you wish to be notified when any changes +are made to it. + +If C<$bWatchSubtree> is true, then changes to any subkey or +descendant of C<$hKey> are also reported. + +C<$iNotifyFilter> controllers what types of changes are reported. It +is a numeric value containing one or more of the following bit masks: + +=over + +=item C<REG_NOTIFY_CHANGE_NAME> + +Notify if a subkey is added or deleted to a monitored key. + +=item C<REG_NOTIFY_CHANGE_LAST_SET> + +Notify if a value in a monitored key is added, deleted, or modified. + +=item C<REG_NOTIFY_CHANGE_SECURITY> + +Notify if a security descriptor of a monitored key is changed. + +=item C<REG_NOTIFY_CHANGE_ATTRIBUTES> + +Notify if any attributes of a monitored key are changed [class +name or security descriptors]. + +=back + +C<$hEvent> is ignored unless C<$bAsync> is true. Otherwise, C<$hEvent> +is a handle to a Win32 I<event> that will be signaled when changes are +to be reported. + +If C<$bAsync> is true, then C<RegNotifyChangeKeyValue()> returns +immediately and uses C<$hEvent> to notify your process of changes. +If C<$bAsync> is false, then C<RegNotifyChangeKeyValue()> does +not return until there is a change to be notified of. + +This routine does not work with Registry keys on remote computers. + +=item RegOpenKey + +=item C<RegOpenKey( $hKey, $sSubKey, $ohSubKey )> + +This routine is meant only for compatibility with Windows version +3.1. Use C<RegOpenKeyEx()> instead. + +=item RegOpenKeyEx + +=item C<RegOpenKeyEx( $hKey, $sSubKey, $uOptions, $uAccess, $ohSubKey )> + +Opens an existing Registry key. Returns a true value if successful +and a false value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sSubKey> is the name of an existing subkey to be opened. +Can be C<""> or C<[]> to open an additional handle to the +key specified by C<$hKey>. + +C<$iOptions> is a numeric value containing bits that control options +used while opening the subkey. There are currently no supported +options so this parameter should be specified as C<0>. + +C<$iAccess> is a numeric mask of bits specifying what type of +access is desired when opening the new subkey. Should be a +combination of one or more of the following bit masks: + +=over + +=item C<KEY_ALL_ACCESS> + + KEY_READ | KEY_WRITE | KEY_CREATE_LINK + +=item C<KEY_READ> + + KEY_QUERY_VALUE | KEY_ENUMERATE_SUBKEYS | KEY_NOTIFY | STANDARD_RIGHTS_READ + +=item C<KEY_WRITE> + + KEY_SET_VALUE | KEY_CREATE_SUB_KEY | STANDARD_RIGHTS_WRITE + +=item C<KEY_QUERY_VALUE> + +=item C<KEY_SET_VALUE> + +=item C<KEY_ENUMERATE_SUB_KEYS> + +=item C<KEY_CREATE_SUB_KEY> + +=item C<KEY_NOTIFY> + +Allows you to use C<RegNotifyChangeKeyValue()> on the opened key. + +=item C<KEY_EXECUTE> + +Same as C<KEY_READ>. + +=item C<KEY_CREATE_LINK> + +Gives you permission to create a symbolic link like +C<HKEY_CLASSES_ROOT> and C<HKEY_CURRENT_USER>, though the method for +doing so is not documented [and probably requires use of the mostly +undocumented "native" routines, C<Nt*()> a.k.a. C<Zw*()>]. + +=back + +C<$phKey> will be set to the handle to be used to access the new subkey +if the call succeeds. + +=item RegQueryInfoKey + +=item C<RegQueryInfoKey( $hKey, $osClass, $iolClass, $pNull, $ocSubKeys, $olSubKey, $olSubClass, $ocValues, $olValName, $olValData, $olSecDesc, $opftTime )> + +Gets miscellaneous information about an open Registry key. +Returns a true value if successful and a false value [and +sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sClass> will be set to the class name for the key. Can be +C<[]> if you don't care about the class. + +C<$plClass> initially specifies the [minimum] buffer size to be +allocated for C<$sClass> and will be set to the length of the +key's class name. See L<Buffer sizes> for more information. +You may omit this parameter to get the same effect as passing in +C<[]> for it. + +C<$pNull> is reserved for future use and should be passed as C<[]>. + +C<$pcSubKeys> will be set to the count of the number of subkeys +directly under this key. Can be C<[]>. + +C<$plSubKey> will be set to the length of the longest subkey name. +Can be C<[]>. + +C<$plSubClass> will be set to the length of the longest class name +used with an immediate subkey of this key. Can be C<[]>. + +C<$pcValues> will be set to the count of the number of values in +this key. Can be C<[]>. + +C<$plValName> will be set to the length of the longest value name +in this key. Can be C<[]>. + +C<$plValData> will be set to the length of the longest value data +in this key. Can be C<[]>. + +C<$plSecDesc> will be set to the length of this key's full security +descriptor. + +C<$pftTime> will be set to a C<FILETIME> structure packed +into a Perl string and indicating when this key was last changed. +Can be C<[]>. + +=item RegQueryMultipleValues + +=item C<RegQueryMultipleValues( $hKey, $ioarValueEnts, $icValueEnts, $opBuffer, $iolBuffer )> + +Allows you to use a single call to query several values from a single +open Registry key to maximize efficiency. Returns a true value if +successful and a false value [and sets C<$^E>/C<regLastError()>] on +failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$pValueEnts> should contain a list of C<VALENT> structures packed +into a single Perl string. Each C<VALENT> structure should have +the C<ve_valuename> entry [the first 4 bytes] pointing to a string +containing the name of a value stored in this key. The remaining +fields are set if the function succeeds. + +C<$cValueEnts> should contain the count of the number of C<VALENT> +structures contained in C<$pValueEnts>. + +C<$pBuffer> will be set to the data from all of the requested values +concatenated into a single Perl string. + +C<$plBuffer> initially specifies the [minimum] buffer size to be +allocated for C<$sBuffer> and will be set to the total length of +the data to be written to C<$sBuffer>. See L<Buffer sizes> for +more information. You may omit this parameter to get the same +effect as passing in C<[]> for it. + +Here is sample code to populate C<$pValueEnts>: + + # @ValueNames= ...list of value name strings...; + $cValueEnts= @ValueNames; + $pValueEnts= pack( " p x4 x4 x4 " x $cValueEnts, @ValueNames ); + +Here is sample code to retrieve the data type and data length +returned in C<$pValueEnts>: + + @Lengths= unpack( " x4 L x4 x4 " x $cValueEnts, $pValueEnts ); + @Types= unpack( " x4 x4 x4 L " x $cValueEnts, $pValueEnts ); + +Given the above, and assuming you haven't modified C<$sBuffer> since +the call, you can also extract the value data strings from C<$sBuffer> +by using the pointers returned in C<$pValueEnts>: + + @Data= unpack( join( "", map {" x4 x4 P$_ x4 "} @Lengths ), + $pValueEnts ); + +Much better is to use the lengths and extract directly from +C<$sBuffer> using C<unpack()> [or C<substr()>]: + + @Data= unpack( join("",map("P$_",@Lengths)), $sBuffer ); + +=item RegQueryValue + +=item C<RegQueryValue( $hKey, $sSubKey, $osValueData, $iolValueData )> + +This routine is meant only for compatibility with Windows version +3.1. Use C<RegQueryValueEx()> instead. This routine can only +query unamed values [a.k.a. "default values"], that is, values with +a name of C<"">. + +=item RegQueryValueEx + +=item C<RegQueryValueEx( $hKey, $sValueName, $pNull, $ouType, $opValueData, $iolValueData )> + +Lets you look up value data stored in an open Registry key by +specifying the value name. Returns a true value if successful +and a false value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sValueName> is the name of the value whose data you wish to +retrieve. + +C<$pNull> this parameter is reserved for future use and should be +specified as C<[]>. + +C<$piType> will be set to indicate what type of data is stored in +the named value. Will be set to a C<REG_*> value if the function +succeeds. + +C<$pValueData> will be set to the value data [packed into a Perl +string] that is stored in the named value. Can be C<[]> if you +don't care about the value data. + +C<$plValueData> initially specifies the [minimum] buffer size to be +allocated for C<$sValueData> and will be set to the size [always +in bytes] of the data to be written to C<$sValueData>, even if +C<$sValueData> is not successfully written to. See L<Buffer sizes> +for more information. + +=item RegReplaceKey + +=item C<RegReplaceKey( $hKey, $sSubKey, $sNewFile, $sOldFile )> + +Lets you replace an entire hive when the system is next booted. +Returns a true value if successful and a false value [and sets +C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key that has hive(s) +loaded in it. This must be C<HKEY_LOCAL_MACHINE>, +C<HKEY_USERS>, or a remote version of one of these from +a call to C<RegConnectRegistry()>. + +C<$sSubKey> is the name of the subkey of C<$hKey> whose hive +you wish to have replaced on the next reboot. + +C<$sNewFile> is the name of a file that will replace the existing +hive file when the system reboots. + +C<$sOldFile> is the file name to save the current hive file to +when the system reboots. + +C<$sNewFile> and C<$sOldFile> are interpretted relative to the +C<%SystemRoot%/System32/config> directory on the computer where +the C<$hKey> key resides [I think]. If either file is [would be] +on a FAT file system, then its name must not have an extension. + +You must have the C<SE_RESTORE_NAME> privilege to use this routine. + +=item RegRestoreKey + +=item C<RegRestoreKey( $hKey, $sFileName, $uFlags )> + +Reads in a hive file and copies its contents over an existing +Registry tree. Returns a true value if successful and a false +value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sFileName> is the name of the hive file to be read. For each +value and subkey in this file, a value or subkey will be added +or replaced in C<$hKey>. + +C<$uFlags> is usally C<0>. It can also be C<REG_WHOLE_HIVE_VOLATILE> +which, rather than copying the hive over the existing key, +replaces the existing key with a temporary, memory-only Registry +key and then copies the hive contents into it. This option only +works if C<$hKey> is C<HKEY_LOCAL_MACHINE>, C<HKEY_USERS>, or a +remote version of one of these from a call to C<RegConnectRegistry()>. + +C<RegRestoreKey> does I<not> delete values nor keys from the +existing Registry tree when there is no corresponding value/key +in the hive file. + +=item RegSaveKey + +=item C<RegSaveKey( $hKey, $sFileName, $pSecAttr )> + +Dumps any open Registry key and all of its subkeys and values into +a new hive file. Returns a true value if successful and a false +value [and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sFileName> is the name of the file that the Registry tree +should be saved to. It is interpretted relative to the +C<%SystemRoot%/System32/config> directory on the computer where +the C<$hKey> key resides. If C<$sFileName> is on a FAT file system, +then it must not have an extension. + +C<$pSecAttr> contains a C<SECURITY_ATTRIBUTES> structure that specifies +the permissions to be set on the new file that is created. This can +be C<[]>. + +You must have the C<SE_RESTORE_NAME> privilege to use this routine. + +=item RegSetKeySecurity + +=item C<RegSetKeySecurity( $hKey, $uSecInfo, $pSecDesc )> + +Sets [part of] the C<SECURITY_DESCRIPTOR> structure describing part +of the security for an open Registry key. Returns a true value if +successful and a false value [and sets C<$^E>/C<regLastError()>] on +failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$uSecInfo> is a numeric C<SECURITY_INFORMATION> value that +specifies which C<SECURITY_DESCRIPTOR> structure to set. Should +be C<OWNER_SECURITY_INFORMATION>, C<GROUP_SECURITY_INFORMATION>, +C<DACL_SECURITY_INFORMATION>, or C<SACL_SECURITY_INFORMATION> +or two or more of these bits combined using C<|>. + +C<$pSecDesc> contains the new C<SECURITY_DESCRIPTOR> structure +packed into a Perl string. + +=item RegSetValue + +=item C<RegSetValue( $hKey, $sSubKey, $uType, $sValueData, $lValueData )> + +This routine is meant only for compatibility with Windows version +3.1. Use C<RegSetValueEx()> instead. This routine can only +set unamed values [a.k.a. "default values"]. + +=item RegSetValueEx + +=item C<RegSetValueEx( $hKey, $sName, $uZero, $uType, $pData, $lData )> + +Adds or replaces a value in an open Registry key. Returns +a true value if successful and a false value [and sets +C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key [either C<HKEY_*> or from +a previous call]. + +C<$sName> is the name of the value to be set. + +C<$uZero> is reserved for future use and should be specified as C<0>. + +C<$uType> is the type of data stored in C<$pData>. It should +be a C<REG_*> value. + +C<$pData> is the value data packed into a Perl string. + +C<$lData> is the length of the value data that is stored in C<$pData>. +You will usually omit this parameter or pass in C<0> to have +C<length($pData)> used. In both of these cases, if C<$iType> is +C<REG_SZ> or C<REG_EXPAND_SZ>, C<RegSetValueEx()> will append a +trailing C<'\0'> to the end of C<$pData> [unless there is already +one]. + +=item RegUnLoadKey + +=item C<RegUnLoadKey( $hKey, $sSubKey )> + +Unloads a previously loaded hive file. That is, closes the +hive file then deletes the subkey that was providing access +to it. Returns a true value if successful and a false value +[and sets C<$^E>/C<regLastError()>] on failure. + +C<$hKey> is the handle to a Registry key that has hives +loaded in it. This must be C<HKEY_LOCAL_MACHINE>, C<HKEY_USERS>, +or a remote version of one of these from a call to +C<RegConnectRegistry()>. + +C<$sSubKey> is the name of the subkey whose hive you wish to +have unloaded. + +=item :FuncA + +The ASCII-specific function names. + +Each of these is identical to the version listed above without the +trailing "A": + + AbortSystemShutdownA InitiateSystemShutdownA + RegConnectRegistryA RegCreateKeyA RegCreateKeyExA + RegDeleteKeyA RegDeleteValueA RegEnumKeyA + RegEnumKeyExA RegEnumValueA RegLoadKeyA + RegOpenKeyA RegOpenKeyExA RegQueryInfoKeyA + RegQueryMultipleValuesA RegQueryValueA RegQueryValueExA + RegReplaceKeyA RegRestoreKeyA RegSaveKeyA + RegSetValueA RegSetValueExA RegUnLoadKeyA + +=item :FuncW + +The UNICODE-specific function names. These are the same as the +versions listed above without the trailing "W" except that string +parameters are UNICODE strings rather than ASCII strings, as +indicated. + +=item AbortSystemShutdownW + +=item C<AbortSystemShutdownW( $swComputerName )> + +C<$swComputerName> is UNICODE. + +=item InitiateSystemShutdownW + +=item C<InitiateSystemShutdownW( $swComputer, $swMessage, $uTimeoutSecs, $bForce, $bReboot )> + +C<$swComputer> and C<$swMessage> are UNICODE. + +=item RegConnectRegistryW + +=item C<RegConnectRegistryW( $swComputer, $hRootKey, $ohKey )> + +C<$swComputer> is UNICODE. + +=item RegCreateKeyW + +=item C<RegCreateKeyW( $hKey, $swSubKey, $ohSubKey )> + +C<$swSubKey> is UNICODE. + +=item RegCreateKeyExW + +=item C<RegCreateKeyExW( $hKey, $swSubKey, $uZero, $swClass, $uOpts, $uAccess, $pSecAttr, $ohNewKey, $ouDisp )> + +C<$swSubKey> and C<$swClass> are UNICODE. + +=item RegDeleteKeyW + +=item C<RegDeleteKeyW( $hKey, $swSubKey )> + +C<$swSubKey> is UNICODE. + +=item RegDeleteValueW + +=item C<RegDeleteValueW( $hKey, $swValueName )> + +C<$swValueName> is UNICODE. + +=item RegEnumKeyW + +=item C<RegEnumKeyW( $hKey, $uIndex, $oswName, $ilwNameSize )> + +C<$oswName> is UNICODE and C<$ilwNameSize> is measured as number of +C<WCHAR>s. + +=item RegEnumKeyExW + +=item C<RegEnumKeyExW( $hKey, $uIndex, $oswName, $iolwName, $pNull, $oswClass, $iolwClass, $opftLastWrite )> + +C<$swName> and C<$swClass> are UNICODE and C<$iolwName> and C<$iolwClass> +are measured as number of C<WCHAR>s. + +=item RegEnumValueW + +=item C<RegEnumValueW( $hKey, $uIndex, $oswName, $iolwName, $pNull, $ouType, $opData, $iolData )> + +C<$oswName> is UNICODE and C<$iolwName> is measured as number +of C<WCHAR>s. + +C<$opData> is UNICODE if C<$piType> is C<REG_SZ>, C<REG_EXPAND_SZ>, +or C<REG_MULTI_SZ>. Note that C<$iolData> is measured as number +of bytes even in these cases. + +=item RegLoadKeyW + +=item C<RegLoadKeyW( $hKey, $swSubKey, $swFileName )> + +C<$swSubKey> and C<$swFileName> are UNICODE. + +=item RegOpenKeyW + +=item C<RegOpenKeyW( $hKey, $swSubKey, $ohSubKey )> + +C<$swSubKey> is UNICODE. + +=item RegOpenKeyExW + +=item C<RegOpenKeyExW( $hKey, $swSubKey, $uOptions, $uAccess, $ohSubKey )> + +C<$swSubKey> is UNICODE. + +=item RegQueryInfoKeyW + +=item C<RegQueryInfoKeyW( $hKey, $oswClass, $iolwClass, $pNull, $ocSubKeys, $olwSubKey, $olwSubClass, $ocValues, $olwValName, $olValData, $olSecDesc, $opftTime )> + +C<$swClass> is UNICODE. C<$iolwClass>, C<$olwSubKey>, C<$olwSubClass>, +and C<$olwValName> are measured as number of C<WCHAR>s. Note that +C<$olValData> is measured as number of bytes. + +=item RegQueryMultipleValuesW + +=item C<RegQueryMultipleValuesW( $hKey, $ioarValueEnts, $icValueEnts, $opBuffer, $iolBuffer )> + +The C<ve_valuename> fields of the C<VALENT> [actually C<VALENTW>] +structures in C<$ioarValueEnts> are UNICODE. Values of type C<REG_SZ>, +C<REG_EXPAND_SZ>, and C<REG_MULTI_SZ> are written to C<$opBuffer> +in UNICODE. Note that C<$iolBuffer> and the C<ve_valuelen> fields +of the C<VALENT> [C<VALENTW>] structures are measured as number of +bytes. + +=item RegQueryValueW + +=item C<RegQueryValueW( $hKey, $swSubKey, $oswValueData, $iolValueData )> + +C<$swSubKey> and C<$oswValueData> are UNICODE. Note that +C<$iolValueData> is measured as number of bytes. + +=item RegQueryValueExW + +=item C<RegQueryValueExW( $hKey, $swName, $pNull, $ouType, $opData, $iolData )> + +C<$swName> is UNICODE. + +C<$opData> is UNICODE if C<$ouType> is C<REG_SZ>, C<REG_EXPAND_SZ>, +or C<REG_MULTI_SZ>. Note that C<$iolData> is measured as number of +bytes even in these cases. + +=item RegReplaceKeyW + +=item C<RegReplaceKeyW( $hKey, $swSubKey, $swNewFile, $swOldFile )> + +C<$swSubKey>, C<$swNewFile>, and C<$swOldFile> are UNICODE. + +=item RegRestoreKeyW + +=item C<RegRestoreKeyW( $hKey, $swFileName, $uFlags )> + +C<$swFileName> is UNICODE. + +=item RegSaveKeyW + +=item C<RegSaveKeyW( $hKey, $swFileName, $pSecAttr )> + +C<$swFileName> is UNICODE. + +=item RegSetValueW + +=item C<RegSetValueW( $hKey, $swSubKey, $uType, $swValueData, $lValueData )> + +C<$swSubKey> and C<$swValueData> are UNICODE. Note that +C<$lValueData> is measured as number of bytes even though +C<$swValueData> is always UNICODE. + +=item RegSetValueExW + +=item C<RegSetValueExW( $hKey, $swName, $uZero, $uType, $pData, $lData )> + +C<$swName> is UNICODE. + +C<$pData> is UNICODE if C<$uType> is C<REG_SZ>, C<REG_EXPAND_SZ>, +or C<REG_MULTI_SZ>. Note that C<$lData> is measured as number of +bytes even in these cases. + +=item RegUnLoadKeyW + +=item C<RegUnLoadKeyW( $hKey, $swSubKey )> + +C<$swSubKey> is UNICODE. + +=item :HKEY_ + +All C<HKEY_*> constants: + + HKEY_CLASSES_ROOT HKEY_CURRENT_CONFIG HKEY_CURRENT_USER + HKEY_DYN_DATA HKEY_LOCAL_MACHINE HKEY_PERFORMANCE_DATA + HKEY_USERS + +=item :KEY_ + +All C<KEY_*> constants: + + KEY_QUERY_VALUE KEY_SET_VALUE KEY_CREATE_SUB_KEY + KEY_ENUMERATE_SUB_KEYS KEY_NOTIFY KEY_CREATE_LINK + KEY_READ KEY_WRITE KEY_EXECUTE + KEY_ALL_ACCESS + +=item :REG_ + +All C<REG_*> constants: + + REG_CREATED_NEW_KEY REG_OPENED_EXISTING_KEY + + REG_LEGAL_CHANGE_FILTER REG_NOTIFY_CHANGE_ATTRIBUTES + REG_NOTIFY_CHANGE_NAME REG_NOTIFY_CHANGE_LAST_SET + REG_NOTIFY_CHANGE_SECURITY REG_LEGAL_OPTION + + REG_OPTION_BACKUP_RESTORE REG_OPTION_CREATE_LINK + REG_OPTION_NON_VOLATILE REG_OPTION_OPEN_LINK + REG_OPTION_RESERVED REG_OPTION_VOLATILE + + REG_WHOLE_HIVE_VOLATILE REG_REFRESH_HIVE + REG_NO_LAZY_FLUSH + + REG_NONE REG_SZ + REG_EXPAND_SZ REG_BINARY + REG_DWORD REG_DWORD_LITTLE_ENDIAN + REG_DWORD_BIG_ENDIAN REG_LINK + REG_MULTI_SZ REG_RESOURCE_LIST + REG_FULL_RESOURCE_DESCRIPTOR REG_RESOURCE_REQUIREMENTS_LIST + +=item :ALL + +All of the above. + +=item :SE_ + +The strings for the following privilege names: + + SE_ASSIGNPRIMARYTOKEN_NAME SE_AUDIT_NAME + SE_BACKUP_NAME SE_CHANGE_NOTIFY_NAME + SE_CREATE_PAGEFILE_NAME SE_CREATE_PERMANENT_NAME + SE_CREATE_TOKEN_NAME SE_DEBUG_NAME + SE_INCREASE_QUOTA_NAME SE_INC_BASE_PRIORITY_NAME + SE_LOAD_DRIVER_NAME SE_LOCK_MEMORY_NAME + SE_MACHINE_ACCOUNT_NAME SE_PROF_SINGLE_PROCESS_NAME + SE_REMOTE_SHUTDOWN_NAME SE_RESTORE_NAME + SE_SECURITY_NAME SE_SHUTDOWN_NAME + SE_SYSTEMTIME_NAME SE_SYSTEM_ENVIRONMENT_NAME + SE_SYSTEM_PROFILE_NAME SE_TAKE_OWNERSHIP_NAME + SE_TCB_NAME SE_UNSOLICITED_INPUT_NAME + +It can be difficult to successfully build this module in a way +that makes these constants available. So some builds of this +module may not make them available. For such builds, trying +to export any of these constants will cause a fatal error. +For this reason, none of these symbols are currently included +in the C<":ALL"> grouping. + +=back + +=head2 The Win32API:: heirarchy + +This and the other Win32API:: modules are meant to expose the +nearly raw API calls so they can be used from Perl code in any +way they might be used from C code. This provides the following +advantages: + +=over + +=item Many modules can be written by people that don't have a C compiler. + +=item Encourages more module code to be written in Perl [not C]. + +Perl code is often much easier to inspect, debug, customize, and +enhance than XS code. + +=item Allows those already familiar with the Win32 API to get +off to a quick start. + +=item Provides an interactive tool for exploring even obscure +details of the Win32 API. + +It can be very useful to interactively explore ad-hoc calls into +parts of the Win32 API using: + + perl -de 0 + +=item Ensures that native Win32 data structures can be used. + +This allows maximum efficiency. It also allows data from one +module [for example, time or security information from the +C<Win32API::Registry> or C<Win32API::File> modules] to be used +with other modules [for example, C<Win32API::Time> and +C<Win32API::SecDesc>]. + +=item Provides a single version of the XS interface to each API +call where improvements can be collected. + +=back + +=head2 Buffer sizes + +For each parameter that specifies a buffer size, a value of C<0> +can be passed. For parameter that are pointers to buffer sizes, +you can also pass in C<NULL> by specifying an empty list reference, +C<[]>. Both of these cases will ensure that the variable has +I<some> buffer space allocated to it and pass in that buffer's +allocated size. Many of the calls indicate, via C<ERROR_MORE_DATA>, +that the buffer size was not sufficient and the F<Registry.xs> +code will automatically enlarge the buffer to the required size +and repeat the call. + +Numeric buffer sizes are used as minimum initial sizes for the +buffers. The larger of this size and the size of space already +allocated to the scalar will be passed to the underlying routine. +If that size was insufficient, and the underlying call provides +an easy method for determining the needed buffer size, then the +buffer will be enlarged and the call repeated as above. + +The underlying calls define buffer size parameter as unsigned, so +negative buffer sizes are treated as very large positive buffer +sizes which usually cause C<malloc()> to fail. + +To force the F<Registry.xs> code to pass in a specific value for +a buffer size, preceed the size with an equals sign via C<"=".>. +Buffer sizes that are passed in as strings starting with an equals +sign will have the equal sign stripped and the remainder of the string +interpretted as a number [via C's C<strtoul()> using only base 10] +which will be passed to the underlying routine [even if the allocated +buffer is actually larger]. The F<Registry.xs> code will enlarge the +buffer to the specified size, if needed, but will not enlarge the +buffer based on the underlying routine requesting more space. + +Some Reg*() calls may not currently set the buffer size when they +return C<ERROR_MORE_DATA>. But some that are not documented as +doing so, currently do so anyway. So the code assumes that any +routine I<might> do this and resizes any buffers and repeats the +call. We hope that eventually all routines will provide this +feature. + +When you use C<[]> for a buffer size, you can still find the +length of the data returned by using C<length($buffer)>. Note +that this length will be in bytes while a few of the buffer +sizes would have been in units of wide characters. + +Note that the RegQueryValueEx*() and RegEnumValue*() calls +will trim the trailing C<'\0'> [if present] from the returned data +values of type C<REG_SZ> or C<REG_EXPAND_SZ> but only if the +value data length parameter is omitted [or specified as C<[]>]. + +The RegSetValueEx*() calls will add a trailing C<'\0'> [if +missing] to the supplied data values of type C<REG_SZ> and +C<REG_EXPAND_SZ> but only if the value data length parameter +is omitted [or specified as C<0>]. + +=head2 Hungarian Notation + +The following abbreviations are used at the start of each parameter +name to hint at aspects of how the parameter is used. The prefix +is always in lower case and followed by a capital letter that starts +the descriptive part of the parameter name. Several of the following +abbreviations can be combined into a single prefix. + +Probably not all of these prefix notations are used by this module. +This document section may be included in any C<Win32API> module and +so covers some notations not used by this specific module. + +=over + +=item s + +A string. In C, a C<'\0'>-terminated C<char *>. In Perl, just a +string except that it will be truncated at the first C<"\0">, if +it contains one. + +=item sw + +A wide [UNICODE] string. In C, a C<L'\0'>-terminated C<WCHAR *>. +In Perl, a string that contains UNICODE data. You can convert a +string to UNICODE in Perl via: + + $string= "This is an example string"; + $unicode= pack( "S*", unpack("C*",$string), 0 ); + +Note how C<, 0> above causes an explicit C<L'\0'> to be added since +Perl's implicit C<'\0'> that it puts after each of its strings is not +wide enough to terminate a UNICODE string. So UNICODE strings are +different than regular strings in that the Perl version of a regular +string will not include the trialing C<'\0'> while the Perl version +of a UNICODE string must include the trailing C<L'\0'>. + +If a UNICODE string contains no non-ASCII characters, then you +can convert it back into a normal string via: + + $string= pack( "C*", unpack("S*",$unicode) ); + $string =~ s/\0$//; + +=item p + +A pointer to some buffer [usually containing some C<struct>]. In C, +a C<void *> or some other pointer type. In Perl, a string that is +usually manipulated using C<pack> and C<unpack>. The "p" is usually +followed by more prefix character(s) to indicate what type of data is +stored in the bufffer. + +=item a + +A packed array. In C, an array [usually of C<struct>s]. In Perl, a +string containing the packed data. The "a" is usually followed by +more prefix character(s) to indicate the data type of the elements. + +These packed arrays are also called "vectors" in places to avoid +confusion with Perl arrays. + +=item n + +A generic number. In C, any of the integer or floating point data +types. In Perl, a number; either an integer, unsigned, or double +[IV, UV, or NV, respectively]. Usually an integer. + +=item iv + +A signed integral value. In C, any of the signed integer data types. +In Perl, an integer [IV]. + +=item u + +An unsigned integral value. In C, any of the unsigned integer data +types. In Perl, an unsigned integer [UV]. + +=item d + +A floating-point number. In C, a C<float> or C<double> or, perhaps, +a C<long double>. In Perl, a double-precision floating-point number +[NV]. + +=item b + +A Boolean value. In C, any integer data type, though usually via +a type alias of C<bool> or C<BOOL>, containing either a 0 [false] or +non-zero [true] value. In Perl, a scalar containing a Boolean value +[C<0>, C<"">, or C<undef> for "false" and anything else for "true"]. + +=item c + +A count of items. In C, any integer data type. In Perl, an unsigned +integer [UV]. Usually used in conjunction with a "vector" parameter +[see L</a> above] to indicate the number of elements. + +=item l + +A length [in bytes]. In C, any integer data type. In Perl, an +unsigned integer [UV]. Usually used in conjunction with a "string" +or "pointer" parameter [see L</s> and L</p> above] to indicate the +buffer size or the size of the value stored in the buffer. + +For strings, there is no general rule as to whether the trailing +C<'\0'> is included in such sizes. For this reason, the C<Win32API> +modules follow the Perl rule of always allocating one extra byte +and reporting buffer sizes as being one smaller than allocated in +case the C<'\0'> is not included in the size. + +=item lw + +A length measured as number of UNICODE characters. In C, a count +of C<WCHAR>s. In Perl, an unsigned integer [UV] counting "shorts" +[see "s" and "S" in C<pack> and C<unpack>]. + +For UNICODE strings, the trailing C<L'\0'> may or may not be +included in a length so, again, we always allocate extra room +for one and don't report that extra space. + +=item h + +A handle. In C, a C<HANDLE> or more-specific handle data type. +In Perl, an unsigned integer [UV]. In C, these handles are often +actually some type of pointer, but Perl just treats them as opaque +numbers, as it should. This prefix is also used for other pointers +that are treated as integers in Perl code. + +=item r + +A record. In C, almost always a C<struct> or perhaps C<union>. Note +that C C<struct>s are rarely passed by value so the "r" is almost +always preceeded by a "p" or "a" [see L</p> and L</a> above]. For +the very rare unadorned "r", Perl stores the record in the same way +as a "pr", that is, in a string. For the very rare case where Perl +explicitly stores a pointer to the C<struct> rather than storing the +C<struct> directly in a Perl string, the prefix "pp" or "ppr" or even +"par" is used. + +=item sv + +=item rv + +=item hv + +=item av + +=item cv + +A Perl data type. Respectively, a scalar value [SV], a reference +[RV] [usually to a scalar], a hash [HV], a Perl array [AV], or a Perl +code reference [PVCV]. For the "hv", "av", and "cv" prefixes, a +leading "rv" is usually assumed. For a parameter to an XS subroutine, +a prefix of "sv" means the parameter is a scalar and so may be a string +or a number [or C<undef>] or even both at the same time. So "sv" +doesn't imply a leading "rv". + +=item Input or Output + +Whether a parameter is for input data, output data, or both is usually +not reflected by the data type prefix. In cases where this is not +obvious nor reflected in the parameter name proper, we may use the +following in front of the data type prefix. + +=over + +=item i + +An input parameter given to the API [usually omitted]. + +=item o + +An output-only parameter taken from the API. You should not get a +warning if such a parameter is C<undef> when you pass it into the +function. You should get an error if such a parameter is read-only. +You can [usually] pass in C<[]> for such a parameter to have the +parameter silently ignored. + +The output may be written directly into the Perl variable passed +to the subroutine, the same way the buffer parameter to Perl's +C<sysread()>. This method is often avoided in Perl because +the call then lacks any visual cue that some parameters are being +overwritten. But this method closely matches the C API which is +what we are trying to do. + +=item io + +Input given to the API then overwritten with output taken from the +API. You should get a warning [if B<-w> is in effect] if such a +parameter is C<undef> when you pass it into the function [unless it +is a buffer or buffer length parameter]. If the value is read-only, +then [for most parameters] the output is silently not written. This +is because it is often convenient to pass in read-only constants for +many such parameters. You can also usually pass in C<[]> for such +parameters. + +=back + +=item pp + +=item ppr + +=item par + +=item pap + +These are just unusual combinations of prefix characters described above. + +For each, a pointer is stored in a [4-byte] Perl string. You can +usually use C<unpack "P"> to access the real data from Perl. + +For "ppr" [and often for "pp"], the pointer points directly at a +C C<struct>. For "par", the pointer points to the first element +of a C [packed] array of C<struct>s. For "pap", the pointer points +to a C [packed] array of pointers to other things. + +=item ap + +Here we have a list of pointers packed into a single Perl string. + +=back + +=head1 BUGS + +The old ActiveState ports of Perl for Win32 [but not, ActivePerl, the +ActiveState distributions of standard Perl 5.004 and beyond] do not support +the tools for building extensions and so do not support this extension. + +No routines are provided for using the data returned in the C<FILETIME> +buffers. Those are in the C<Win32API::Time> module. + +No routines are provided for dealing with UNICODE data effectively. +See L</:FuncW> above for some simple-minded UNICODE methods. + +Parts of the module test will fail if used on a version of Perl +that does not yet set C<$^E> based on C<GetLastError()>. + +On NT 4.0 [at least], the RegEnum*() calls do not set the required +buffer sizes when returning C<ERROR_MORE_DATA> so this module will +not grow the buffers in such cases. C<Win32::TieRegistry> overcomes +this by using values from C<RegQueryInfoKey()> for buffer sizes in +RegEnum* calls. + +On NT 4.0 [at least], C<RegQueryInfoKey()> on C<HKEY_PERFORMANCE_DATA> +never succeeds. Also, C<RegQueryValueEx()> on C<HKEY_PERFORMANCE_DATA> +never returns the required buffer size. To access C<HKEY_PERFORMANCE_DATA> +you will need to keep growing the data buffer until the call succeeds. + +Because C<goto &subroutine> seems to be buggy under Win32 Perl, +it is not used in the stubs in F<Registry.pm>. + +=head1 AUTHOR + +Tye McQueen, tye@metronet.com, http://www.metronet.com/~tye/. + +=head1 SEE ALSO + +=over + +=item L<Win32::TieRegistry> + +=item L<Win32::Registry> + +=back + +=cut diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32API/Registry/cRegistry.pc b/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32API/Registry/cRegistry.pc new file mode 100644 index 00000000000..9659d0c4361 --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/Win32API/Registry/cRegistry.pc @@ -0,0 +1,87 @@ +# Generated by cRegistry_pc.cxx. +# Package Win32API::Registry with options: +# CPLUSPLUS => q[1] +# IFDEF => q[ /^SE_/ ? '__cplusplus' : /REG_/ ] +# IMPORT_LIST => [q[/._/], q[!/[a-z]/]] +# VALUES => { KEY_DELETE=>q[DELETE], KEY_READ_CONTROL=>q[READ_CONTROL], KEY_WRITE_OWNER=>q[WRITE_OWNER], KEY_SYNCHRONIZE=>q[SYNCHRONIZE], KEY_WRITE_DAC=>q[WRITE_DAC] } +# WRITE_PERL => q[1] +# Perl files eval'd: +# Registry.pm => last if /^\s*(bootstrap|XSLoader::load)\b/ +# C files included: +# Registry.xs => last if m#/[/*]\s*CONSTS_DEFINED\b|^\s*MODULE\b# +sub HKEY_CLASSES_ROOT () { 0x80000000 } +sub HKEY_CURRENT_CONFIG () { 0x80000005 } +sub HKEY_CURRENT_USER () { 0x80000001 } +sub HKEY_DYN_DATA () { 0x80000006 } +sub HKEY_LOCAL_MACHINE () { 0x80000002 } +sub HKEY_PERFORMANCE_DATA () { 0x80000004 } +sub HKEY_USERS () { 0x80000003 } +sub KEY_ALL_ACCESS () { 983103 } +sub KEY_CREATE_LINK () { 32 } +sub KEY_CREATE_SUB_KEY () { 4 } +sub KEY_DELETE () { 65536 } +sub KEY_ENUMERATE_SUB_KEYS () { 8 } +sub KEY_EXECUTE () { 131097 } +sub KEY_NOTIFY () { 16 } +sub KEY_QUERY_VALUE () { 1 } +sub KEY_READ () { 131097 } +sub KEY_READ_CONTROL () { 131072 } +sub KEY_SET_VALUE () { 2 } +sub KEY_SYNCHRONIZE () { 1048576 } +sub KEY_WRITE () { 131078 } +sub KEY_WRITE_DAC () { 262144 } +sub KEY_WRITE_OWNER () { 524288 } +sub REG_BINARY () { 3 } +sub REG_CREATED_NEW_KEY () { 1 } +sub REG_DWORD () { 4 } +sub REG_DWORD_BIG_ENDIAN () { 5 } +sub REG_DWORD_LITTLE_ENDIAN () { 4 } +sub REG_EXPAND_SZ () { 2 } +sub REG_FULL_RESOURCE_DESCRIPTOR () { 9 } +sub REG_LEGAL_CHANGE_FILTER () { 15 } +sub REG_LEGAL_OPTION () { 15 } +sub REG_LINK () { 6 } +sub REG_MULTI_SZ () { 7 } +sub REG_NONE () { 0 } +sub REG_NOTIFY_CHANGE_ATTRIBUTES () { 2 } +sub REG_NOTIFY_CHANGE_LAST_SET () { 4 } +sub REG_NOTIFY_CHANGE_NAME () { 1 } +sub REG_NOTIFY_CHANGE_SECURITY () { 8 } +sub REG_NO_LAZY_FLUSH () { 4 } +sub REG_OPENED_EXISTING_KEY () { 2 } +sub REG_OPTION_BACKUP_RESTORE () { 4 } +sub REG_OPTION_CREATE_LINK () { 2 } +sub REG_OPTION_NON_VOLATILE () { 0 } +sub REG_OPTION_OPEN_LINK () { 8 } +sub REG_OPTION_RESERVED () { 0 } +sub REG_OPTION_VOLATILE () { 1 } +sub REG_REFRESH_HIVE () { 2 } +sub REG_RESOURCE_LIST () { 8 } +sub REG_RESOURCE_REQUIREMENTS_LIST () { 10 } +sub REG_SZ () { 1 } +sub REG_WHOLE_HIVE_VOLATILE () { 1 } +sub SE_ASSIGNPRIMARYTOKEN_NAME () { 'SeAssignPrimaryTokenPrivilege' } +sub SE_AUDIT_NAME () { 'SeAuditPrivilege' } +sub SE_BACKUP_NAME () { 'SeBackupPrivilege' } +sub SE_CHANGE_NOTIFY_NAME () { 'SeChangeNotifyPrivilege' } +sub SE_CREATE_PAGEFILE_NAME () { 'SeCreatePagefilePrivilege' } +sub SE_CREATE_PERMANENT_NAME () { 'SeCreatePermanentPrivilege' } +sub SE_CREATE_TOKEN_NAME () { 'SeCreateTokenPrivilege' } +sub SE_DEBUG_NAME () { 'SeDebugPrivilege' } +sub SE_INCREASE_QUOTA_NAME () { 'SeIncreaseQuotaPrivilege' } +sub SE_INC_BASE_PRIORITY_NAME () { 'SeIncreaseBasePriorityPrivilege' } +sub SE_LOAD_DRIVER_NAME () { 'SeLoadDriverPrivilege' } +sub SE_LOCK_MEMORY_NAME () { 'SeLockMemoryPrivilege' } +sub SE_MACHINE_ACCOUNT_NAME () { 'SeMachineAccountPrivilege' } +sub SE_PROF_SINGLE_PROCESS_NAME () { 'SeProfileSingleProcessPrivilege' } +sub SE_REMOTE_SHUTDOWN_NAME () { 'SeRemoteShutdownPrivilege' } +sub SE_RESTORE_NAME () { 'SeRestorePrivilege' } +sub SE_SECURITY_NAME () { 'SeSecurityPrivilege' } +sub SE_SHUTDOWN_NAME () { 'SeShutdownPrivilege' } +sub SE_SYSTEMTIME_NAME () { 'SeSystemtimePrivilege' } +sub SE_SYSTEM_ENVIRONMENT_NAME () { 'SeSystemEnvironmentPrivilege' } +sub SE_SYSTEM_PROFILE_NAME () { 'SeSystemProfilePrivilege' } +sub SE_TAKE_OWNERSHIP_NAME () { 'SeTakeOwnershipPrivilege' } +sub SE_TCB_NAME () { 'SeTcbPrivilege' } +sub SE_UNSOLICITED_INPUT_NAME () { 'SeUnsolicitedInputPrivilege' } +1; diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/autosplit.ix b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/autosplit.ix new file mode 100644 index 00000000000..d7605efa074 --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/autosplit.ix @@ -0,0 +1,8 @@ +# Index created by AutoSplit for ../LIB\DynaLoader.pm +# (file acts as timestamp) +package DynaLoader; +sub dl_findfile ; +sub dl_expandspec ; +sub dl_find_symbol_anywhere +; +1; diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_expandspec.al b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_expandspec.al new file mode 100644 index 00000000000..0bea19a3e4d --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_expandspec.al @@ -0,0 +1,34 @@ +# NOTE: Derived from ../LIB\DynaLoader.pm. +# Changes made here will be lost when autosplit is run again. +# See AutoSplit.pm. +package DynaLoader; + +#line 377 "../LIB\DynaLoader.pm (autosplit into ..\lib\auto\DynaLoader\dl_expandspec.al)" +sub dl_expandspec { + my($spec) = @_; + # Optional function invoked if DynaLoader.pm sets $do_expand. + # Most systems do not require or use this function. + # Some systems may implement it in the dl_*.xs file in which case + # this autoload version will not be called but is harmless. + + # This function is designed to deal with systems which treat some + # 'filenames' in a special way. For example VMS 'Logical Names' + # (something like unix environment variables - but different). + # This function should recognise such names and expand them into + # full file paths. + # Must return undef if $spec is invalid or file does not exist. + + my $file = $spec; # default output to input + + if ($Is_VMS) { # dl_expandspec should be defined in dl_vms.xs + require Carp; + Carp::croak("dl_expandspec: should be defined in XS file!\n"); + } else { + return undef unless -f $file; + } + print STDERR "dl_expandspec($spec) => $file\n" if $dl_debug; + $file; +} + +# end of DynaLoader::dl_expandspec +1; diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_find_symbol_anywhere.al b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_find_symbol_anywhere.al new file mode 100644 index 00000000000..2232454ba69 --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_find_symbol_anywhere.al @@ -0,0 +1,19 @@ +# NOTE: Derived from ../LIB\DynaLoader.pm. +# Changes made here will be lost when autosplit is run again. +# See AutoSplit.pm. +package DynaLoader; + +#line 403 "../LIB\DynaLoader.pm (autosplit into ..\lib\auto\DynaLoader\dl_find_symbol_anywhere.al)" +sub dl_find_symbol_anywhere +{ + my $sym = shift; + my $libref; + foreach $libref (@dl_librefs) { + my $symref = dl_find_symbol($libref,$sym); + return $symref if $symref; + } + return undef; +} + +1; +# end of DynaLoader::dl_find_symbol_anywhere diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_findfile.al b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_findfile.al new file mode 100644 index 00000000000..9f8df39d00c --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/DynaLoader/dl_findfile.al @@ -0,0 +1,115 @@ +# NOTE: Derived from ../LIB\DynaLoader.pm. +# Changes made here will be lost when autosplit is run again. +# See AutoSplit.pm. +package DynaLoader; + +#line 269 "../LIB\DynaLoader.pm (autosplit into ..\lib\auto\DynaLoader\dl_findfile.al)" +sub dl_findfile { + # Read ext/DynaLoader/DynaLoader.doc for detailed information. + # This function does not automatically consider the architecture + # or the perl library auto directories. + my (@args) = @_; + my (@dirs, $dir); # which directories to search + my (@found); # full paths to real files we have found + my $dl_ext= 'dll'; # $Config::Config{'dlext'} suffix for perl extensions + my $dl_so = 'dll'; # $Config::Config{'so'} suffix for shared libraries + + print STDERR "dl_findfile(@args)\n" if $dl_debug; + + # accumulate directories but process files as they appear + arg: foreach(@args) { + # Special fast case: full filepath requires no search + if ($Is_VMS && m%[:>/\]]% && -f $_) { + push(@found,dl_expandspec(VMS::Filespec::vmsify($_))); + last arg unless wantarray; + next; + } + elsif ($Is_MacOS) { + if (m/:/ && -f $_) { + push(@found,$_); + last arg unless wantarray; + } + } + elsif (m:/: && -f $_ && !$do_expand) { + push(@found,$_); + last arg unless wantarray; + next; + } + + # Deal with directories first: + # Using a -L prefix is the preferred option (faster and more robust) + if (m:^-L:) { s/^-L//; push(@dirs, $_); next; } + + if ($Is_MacOS) { + # Otherwise we try to try to spot directories by a heuristic + # (this is a more complicated issue than it first appears) + if (m/:/ && -d $_) { push(@dirs, $_); next; } + # Only files should get this far... + my(@names, $name); # what filenames to look for + s/^-l//; + push(@names, $_); + foreach $dir (@dirs, @dl_library_path) { + next unless -d $dir; + $dir =~ s/^([^:]+)$/:$1/; + $dir =~ s/:$//; + foreach $name (@names) { + my($file) = "$dir:$name"; + print STDERR " checking in $dir for $name\n" if $dl_debug; + if (-f $file) { + push(@found, $file); + next arg; # no need to look any further + } + } + } + next; + } + + # Otherwise we try to try to spot directories by a heuristic + # (this is a more complicated issue than it first appears) + if (m:/: && -d $_) { push(@dirs, $_); next; } + + # VMS: we may be using native VMS directory syntax instead of + # Unix emulation, so check this as well + if ($Is_VMS && /[:>\]]/ && -d $_) { push(@dirs, $_); next; } + + # Only files should get this far... + my(@names, $name); # what filenames to look for + if (m:-l: ) { # convert -lname to appropriate library name + s/-l//; + push(@names,"lib$_.$dl_so"); + push(@names,"lib$_.a"); + } else { # Umm, a bare name. Try various alternatives: + # these should be ordered with the most likely first + push(@names,"$_.$dl_ext") unless m/\.$dl_ext$/o; + push(@names,"$_.$dl_so") unless m/\.$dl_so$/o; + push(@names,"lib$_.$dl_so") unless m:/:; + push(@names,"$_.a") if !m/\.a$/ and $dlsrc eq "dl_dld.xs"; + push(@names, $_); + } + foreach $dir (@dirs, @dl_library_path) { + next unless -d $dir; + chop($dir = VMS::Filespec::unixpath($dir)) if $Is_VMS; + foreach $name (@names) { + my($file) = "$dir/$name"; + print STDERR " checking in $dir for $name\n" if $dl_debug; + $file = ($do_expand) ? dl_expandspec($file) : (-f $file && $file); + #$file = _check_file($file); + if ($file) { + push(@found, $file); + next arg; # no need to look any further + } + } + } + } + if ($dl_debug) { + foreach(@dirs) { + print STDERR " dl_findfile ignored non-existent directory: $_\n" unless -d $_; + } + print STDERR "dl_findfile found: @found\n"; + } + return $found[0] unless wantarray; + @found; +} + +# end of DynaLoader::dl_findfile +1; diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/Win32API/Registry/Registry.bs b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/Win32API/Registry/Registry.bs new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/Win32API/Registry/Registry.bs diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/Win32API/Registry/Registry.dll b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/Win32API/Registry/Registry.dll Binary files differnew file mode 100644 index 00000000000..45b7bc0688a --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/auto/Win32API/Registry/Registry.dll diff --git a/Master/tlpkg/lib/Perl5_lib-TL_inst/overload.pm b/Master/tlpkg/lib/Perl5_lib-TL_inst/overload.pm new file mode 100644 index 00000000000..15b7e775e74 --- /dev/null +++ b/Master/tlpkg/lib/Perl5_lib-TL_inst/overload.pm @@ -0,0 +1,1434 @@ +package overload; + +our $VERSION = '1.04'; + +$overload::hint_bits = 0x20000; # HINT_LOCALIZE_HH + +sub nil {} + +sub OVERLOAD { + $package = shift; + my %arg = @_; + my ($sub, $fb); + $ {$package . "::OVERLOAD"}{dummy}++; # Register with magic by touching. + *{$package . "::()"} = \&nil; # Make it findable via fetchmethod. + for (keys %arg) { + if ($_ eq 'fallback') { + $fb = $arg{$_}; + } else { + $sub = $arg{$_}; + if (not ref $sub and $sub !~ /::/) { + $ {$package . "::(" . $_} = $sub; + $sub = \&nil; + } + #print STDERR "Setting `$ {'package'}::\cO$_' to \\&`$sub'.\n"; + *{$package . "::(" . $_} = \&{ $sub }; + } + } + ${$package . "::()"} = $fb; # Make it findable too (fallback only). +} + +sub import { + $package = (caller())[0]; + # *{$package . "::OVERLOAD"} = \&OVERLOAD; + shift; + $package->overload::OVERLOAD(@_); +} + +sub unimport { + $package = (caller())[0]; + ${$package . "::OVERLOAD"}{dummy}++; # Upgrade the table + shift; + for (@_) { + if ($_ eq 'fallback') { + undef $ {$package . "::()"}; + } else { + delete $ {$package . "::"}{"(" . $_}; + } + } +} + +sub Overloaded { + my $package = shift; + $package = ref $package if ref $package; + $package->can('()'); +} + +sub ov_method { + my $globref = shift; + return undef unless $globref; + my $sub = \&{*$globref}; + return $sub if $sub ne \&nil; + return shift->can($ {*$globref}); +} + +sub OverloadedStringify { + my $package = shift; + $package = ref $package if ref $package; + #$package->can('(""') + ov_method mycan($package, '(""'), $package + or ov_method mycan($package, '(0+'), $package + or ov_method mycan($package, '(bool'), $package + or ov_method mycan($package, '(nomethod'), $package; +} + +sub Method { + my $package = shift; + $package = ref $package if ref $package; + #my $meth = $package->can('(' . shift); + ov_method mycan($package, '(' . shift), $package; + #return $meth if $meth ne \&nil; + #return $ {*{$meth}}; +} + +sub AddrRef { + my $package = ref $_[0]; + return "$_[0]" unless $package; + + require Scalar::Util; + my $class = Scalar::Util::blessed($_[0]); + my $class_prefix = defined($class) ? "$class=" : ""; + my $type = Scalar::Util::reftype($_[0]); + my $addr = Scalar::Util::refaddr($_[0]); + return sprintf("$class_prefix$type(0x%x)", $addr); +} + +*StrVal = *AddrRef; + +sub mycan { # Real can would leave stubs. + my ($package, $meth) = @_; + return \*{$package . "::$meth"} if defined &{$package . "::$meth"}; + my $p; + foreach $p (@{$package . "::ISA"}) { + my $out = mycan($p, $meth); + return $out if $out; + } + return undef; +} + +%constants = ( + 'integer' => 0x1000, # HINT_NEW_INTEGER + 'float' => 0x2000, # HINT_NEW_FLOAT + 'binary' => 0x4000, # HINT_NEW_BINARY + 'q' => 0x8000, # HINT_NEW_STRING + 'qr' => 0x10000, # HINT_NEW_RE + ); + +%ops = ( with_assign => "+ - * / % ** << >> x .", + assign => "+= -= *= /= %= **= <<= >>= x= .=", + num_comparison => "< <= > >= == !=", + '3way_comparison'=> "<=> cmp", + str_comparison => "lt le gt ge eq ne", + binary => "& | ^", + unary => "neg ! ~", + mutators => '++ --', + func => "atan2 cos sin exp abs log sqrt int", + conversion => 'bool "" 0+', + iterators => '<>', + dereferencing => '${} @{} %{} &{} *{}', + special => 'nomethod fallback ='); + +use warnings::register; +sub constant { + # Arguments: what, sub + while (@_) { + if (@_ == 1) { + warnings::warnif ("Odd number of arguments for overload::constant"); + last; + } + elsif (!exists $constants {$_ [0]}) { + warnings::warnif ("`$_[0]' is not an overloadable type"); + } + elsif (!ref $_ [1] || "$_[1]" !~ /CODE\(0x[\da-f]+\)$/) { + # Can't use C<ref $_[1] eq "CODE"> above as code references can be + # blessed, and C<ref> would return the package the ref is blessed into. + if (warnings::enabled) { + $_ [1] = "undef" unless defined $_ [1]; + warnings::warn ("`$_[1]' is not a code reference"); + } + } + else { + $^H{$_[0]} = $_[1]; + $^H |= $constants{$_[0]} | $overload::hint_bits; + } + shift, shift; + } +} + +sub remove_constant { + # Arguments: what, sub + while (@_) { + delete $^H{$_[0]}; + $^H &= ~ $constants{$_[0]}; + shift, shift; + } +} + +1; + +__END__ + +=head1 NAME + +overload - Package for overloading Perl operations + +=head1 SYNOPSIS + + package SomeThing; + + use overload + '+' => \&myadd, + '-' => \&mysub; + # etc + ... + + package main; + $a = new SomeThing 57; + $b=5+$a; + ... + if (overload::Overloaded $b) {...} + ... + $strval = overload::StrVal $b; + +=head1 DESCRIPTION + +=head2 Declaration of overloaded functions + +The compilation directive + + package Number; + use overload + "+" => \&add, + "*=" => "muas"; + +declares function Number::add() for addition, and method muas() in +the "class" C<Number> (or one of its base classes) +for the assignment form C<*=> of multiplication. + +Arguments of this directive come in (key, value) pairs. Legal values +are values legal inside a C<&{ ... }> call, so the name of a +subroutine, a reference to a subroutine, or an anonymous subroutine +will all work. Note that values specified as strings are +interpreted as methods, not subroutines. Legal keys are listed below. + +The subroutine C<add> will be called to execute C<$a+$b> if $a +is a reference to an object blessed into the package C<Number>, or if $a is +not an object from a package with defined mathemagic addition, but $b is a +reference to a C<Number>. It can also be called in other situations, like +C<$a+=7>, or C<$a++>. See L<MAGIC AUTOGENERATION>. (Mathemagical +methods refer to methods triggered by an overloaded mathematical +operator.) + +Since overloading respects inheritance via the @ISA hierarchy, the +above declaration would also trigger overloading of C<+> and C<*=> in +all the packages which inherit from C<Number>. + +=head2 Calling Conventions for Binary Operations + +The functions specified in the C<use overload ...> directive are called +with three (in one particular case with four, see L<Last Resort>) +arguments. If the corresponding operation is binary, then the first +two arguments are the two arguments of the operation. However, due to +general object calling conventions, the first argument should always be +an object in the package, so in the situation of C<7+$a>, the +order of the arguments is interchanged. It probably does not matter +when implementing the addition method, but whether the arguments +are reversed is vital to the subtraction method. The method can +query this information by examining the third argument, which can take +three different values: + +=over 7 + +=item FALSE + +the order of arguments is as in the current operation. + +=item TRUE + +the arguments are reversed. + +=item C<undef> + +the current operation is an assignment variant (as in +C<$a+=7>), but the usual function is called instead. This additional +information can be used to generate some optimizations. Compare +L<Calling Conventions for Mutators>. + +=back + +=head2 Calling Conventions for Unary Operations + +Unary operation are considered binary operations with the second +argument being C<undef>. Thus the functions that overloads C<{"++"}> +is called with arguments C<($a,undef,'')> when $a++ is executed. + +=head2 Calling Conventions for Mutators + +Two types of mutators have different calling conventions: + +=over + +=item C<++> and C<--> + +The routines which implement these operators are expected to actually +I<mutate> their arguments. So, assuming that $obj is a reference to a +number, + + sub incr { my $n = $ {$_[0]}; ++$n; $_[0] = bless \$n} + +is an appropriate implementation of overloaded C<++>. Note that + + sub incr { ++$ {$_[0]} ; shift } + +is OK if used with preincrement and with postincrement. (In the case +of postincrement a copying will be performed, see L<Copy Constructor>.) + +=item C<x=> and other assignment versions + +There is nothing special about these methods. They may change the +value of their arguments, and may leave it as is. The result is going +to be assigned to the value in the left-hand-side if different from +this value. + +This allows for the same method to be used as overloaded C<+=> and +C<+>. Note that this is I<allowed>, but not recommended, since by the +semantic of L<"Fallback"> Perl will call the method for C<+> anyway, +if C<+=> is not overloaded. + +=back + +B<Warning.> Due to the presence of assignment versions of operations, +routines which may be called in assignment context may create +self-referential structures. Currently Perl will not free self-referential +structures until cycles are C<explicitly> broken. You may get problems +when traversing your structures too. + +Say, + + use overload '+' => sub { bless [ \$_[0], \$_[1] ] }; + +is asking for trouble, since for code C<$obj += $foo> the subroutine +is called as C<$obj = add($obj, $foo, undef)>, or C<$obj = [\$obj, +\$foo]>. If using such a subroutine is an important optimization, one +can overload C<+=> explicitly by a non-"optimized" version, or switch +to non-optimized version if C<not defined $_[2]> (see +L<Calling Conventions for Binary Operations>). + +Even if no I<explicit> assignment-variants of operators are present in +the script, they may be generated by the optimizer. Say, C<",$obj,"> or +C<',' . $obj . ','> may be both optimized to + + my $tmp = ',' . $obj; $tmp .= ','; + +=head2 Overloadable Operations + +The following symbols can be specified in C<use overload> directive: + +=over 5 + +=item * I<Arithmetic operations> + + "+", "+=", "-", "-=", "*", "*=", "/", "/=", "%", "%=", + "**", "**=", "<<", "<<=", ">>", ">>=", "x", "x=", ".", ".=", + +For these operations a substituted non-assignment variant can be called if +the assignment variant is not available. Methods for operations C<+>, +C<->, C<+=>, and C<-=> can be called to automatically generate +increment and decrement methods. The operation C<-> can be used to +autogenerate missing methods for unary minus or C<abs>. + +See L<"MAGIC AUTOGENERATION">, L<"Calling Conventions for Mutators"> and +L<"Calling Conventions for Binary Operations">) for details of these +substitutions. + +=item * I<Comparison operations> + + "<", "<=", ">", ">=", "==", "!=", "<=>", + "lt", "le", "gt", "ge", "eq", "ne", "cmp", + +If the corresponding "spaceship" variant is available, it can be +used to substitute for the missing operation. During C<sort>ing +arrays, C<cmp> is used to compare values subject to C<use overload>. + +=item * I<Bit operations> + + "&", "^", "|", "neg", "!", "~", + +C<neg> stands for unary minus. If the method for C<neg> is not +specified, it can be autogenerated using the method for +subtraction. If the method for C<!> is not specified, it can be +autogenerated using the methods for C<bool>, or C<"">, or C<0+>. + +=item * I<Increment and decrement> + + "++", "--", + +If undefined, addition and subtraction methods can be +used instead. These operations are called both in prefix and +postfix form. + +=item * I<Transcendental functions> + + "atan2", "cos", "sin", "exp", "abs", "log", "sqrt", "int" + +If C<abs> is unavailable, it can be autogenerated using methods +for "E<lt>" or "E<lt>=E<gt>" combined with either unary minus or subtraction. + +Note that traditionally the Perl function L<int> rounds to 0, thus for +floating-point-like types one should follow the same semantic. If +C<int> is unavailable, it can be autogenerated using the overloading of +C<0+>. + +=item * I<Boolean, string and numeric conversion> + + 'bool', '""', '0+', + +If one or two of these operations are not overloaded, the remaining ones can +be used instead. C<bool> is used in the flow control operators +(like C<while>) and for the ternary C<?:> operation. These functions can +return any arbitrary Perl value. If the corresponding operation for this value +is overloaded too, that operation will be called again with this value. + +As a special case if the overload returns the object itself then it will +be used directly. An overloaded conversion returning the object is +probably a bug, because you're likely to get something that looks like +C<YourPackage=HASH(0x8172b34)>. + +=item * I<Iteration> + + "<>" + +If not overloaded, the argument will be converted to a filehandle or +glob (which may require a stringification). The same overloading +happens both for the I<read-filehandle> syntax C<E<lt>$varE<gt>> and +I<globbing> syntax C<E<lt>${var}E<gt>>. + +B<BUGS> Even in list context, the iterator is currently called only +once and with scalar context. + +=item * I<Dereferencing> + + '${}', '@{}', '%{}', '&{}', '*{}'. + +If not overloaded, the argument will be dereferenced I<as is>, thus +should be of correct type. These functions should return a reference +of correct type, or another object with overloaded dereferencing. + +As a special case if the overload returns the object itself then it +will be used directly (provided it is the correct type). + +The dereference operators must be specified explicitly they will not be passed to +"nomethod". + +=item * I<Special> + + "nomethod", "fallback", "=", + +see L<SPECIAL SYMBOLS FOR C<use overload>>. + +=back + +See L<"Fallback"> for an explanation of when a missing method can be +autogenerated. + +A computer-readable form of the above table is available in the hash +%overload::ops, with values being space-separated lists of names: + + with_assign => '+ - * / % ** << >> x .', + assign => '+= -= *= /= %= **= <<= >>= x= .=', + num_comparison => '< <= > >= == !=', + '3way_comparison'=> '<=> cmp', + str_comparison => 'lt le gt ge eq ne', + binary => '& | ^', + unary => 'neg ! ~', + mutators => '++ --', + func => 'atan2 cos sin exp abs log sqrt', + conversion => 'bool "" 0+', + iterators => '<>', + dereferencing => '${} @{} %{} &{} *{}', + special => 'nomethod fallback =' + +=head2 Inheritance and overloading + +Inheritance interacts with overloading in two ways. + +=over + +=item Strings as values of C<use overload> directive + +If C<value> in + + use overload key => value; + +is a string, it is interpreted as a method name. + +=item Overloading of an operation is inherited by derived classes + +Any class derived from an overloaded class is also overloaded. The +set of overloaded methods is the union of overloaded methods of all +the ancestors. If some method is overloaded in several ancestor, then +which description will be used is decided by the usual inheritance +rules: + +If C<A> inherits from C<B> and C<C> (in this order), C<B> overloads +C<+> with C<\&D::plus_sub>, and C<C> overloads C<+> by C<"plus_meth">, +then the subroutine C<D::plus_sub> will be called to implement +operation C<+> for an object in package C<A>. + +=back + +Note that since the value of the C<fallback> key is not a subroutine, +its inheritance is not governed by the above rules. In the current +implementation, the value of C<fallback> in the first overloaded +ancestor is used, but this is accidental and subject to change. + +=head1 SPECIAL SYMBOLS FOR C<use overload> + +Three keys are recognized by Perl that are not covered by the above +description. + +=head2 Last Resort + +C<"nomethod"> should be followed by a reference to a function of four +parameters. If defined, it is called when the overloading mechanism +cannot find a method for some operation. The first three arguments of +this function coincide with the arguments for the corresponding method if +it were found, the fourth argument is the symbol +corresponding to the missing method. If several methods are tried, +the last one is used. Say, C<1-$a> can be equivalent to + + &nomethodMethod($a,1,1,"-") + +if the pair C<"nomethod" =E<gt> "nomethodMethod"> was specified in the +C<use overload> directive. + +The C<"nomethod"> mechanism is I<not> used for the dereference operators +( ${} @{} %{} &{} *{} ). + + +If some operation cannot be resolved, and there is no function +assigned to C<"nomethod">, then an exception will be raised via die()-- +unless C<"fallback"> was specified as a key in C<use overload> directive. + + +=head2 Fallback + +The key C<"fallback"> governs what to do if a method for a particular +operation is not found. Three different cases are possible depending on +the value of C<"fallback">: + +=over 16 + +=item * C<undef> + +Perl tries to use a +substituted method (see L<MAGIC AUTOGENERATION>). If this fails, it +then tries to calls C<"nomethod"> value; if missing, an exception +will be raised. + +=item * TRUE + +The same as for the C<undef> value, but no exception is raised. Instead, +it silently reverts to what it would have done were there no C<use overload> +present. + +=item * defined, but FALSE + +No autogeneration is tried. Perl tries to call +C<"nomethod"> value, and if this is missing, raises an exception. + +=back + +B<Note.> C<"fallback"> inheritance via @ISA is not carved in stone +yet, see L<"Inheritance and overloading">. + +=head2 Copy Constructor + +The value for C<"="> is a reference to a function with three +arguments, i.e., it looks like the other values in C<use +overload>. However, it does not overload the Perl assignment +operator. This would go against Camel hair. + +This operation is called in the situations when a mutator is applied +to a reference that shares its object with some other reference, such +as + + $a=$b; + ++$a; + +To make this change $a and not change $b, a copy of C<$$a> is made, +and $a is assigned a reference to this new object. This operation is +done during execution of the C<++$a>, and not during the assignment, +(so before the increment C<$$a> coincides with C<$$b>). This is only +done if C<++> is expressed via a method for C<'++'> or C<'+='> (or +C<nomethod>). Note that if this operation is expressed via C<'+'> +a nonmutator, i.e., as in + + $a=$b; + $a=$a+1; + +then C<$a> does not reference a new copy of C<$$a>, since $$a does not +appear as lvalue when the above code is executed. + +If the copy constructor is required during the execution of some mutator, +but a method for C<'='> was not specified, it can be autogenerated as a +string copy if the object is a plain scalar. + +=over 5 + +=item B<Example> + +The actually executed code for + + $a=$b; + Something else which does not modify $a or $b.... + ++$a; + +may be + + $a=$b; + Something else which does not modify $a or $b.... + $a = $a->clone(undef,""); + $a->incr(undef,""); + +if $b was mathemagical, and C<'++'> was overloaded with C<\&incr>, +C<'='> was overloaded with C<\&clone>. + +=back + +Same behaviour is triggered by C<$b = $a++>, which is consider a synonym for +C<$b = $a; ++$a>. + +=head1 MAGIC AUTOGENERATION + +If a method for an operation is not found, and the value for C<"fallback"> is +TRUE or undefined, Perl tries to autogenerate a substitute method for +the missing operation based on the defined operations. Autogenerated method +substitutions are possible for the following operations: + +=over 16 + +=item I<Assignment forms of arithmetic operations> + +C<$a+=$b> can use the method for C<"+"> if the method for C<"+="> +is not defined. + +=item I<Conversion operations> + +String, numeric, and boolean conversion are calculated in terms of one +another if not all of them are defined. + +=item I<Increment and decrement> + +The C<++$a> operation can be expressed in terms of C<$a+=1> or C<$a+1>, +and C<$a--> in terms of C<$a-=1> and C<$a-1>. + +=item C<abs($a)> + +can be expressed in terms of C<$aE<lt>0> and C<-$a> (or C<0-$a>). + +=item I<Unary minus> + +can be expressed in terms of subtraction. + +=item I<Negation> + +C<!> and C<not> can be expressed in terms of boolean conversion, or +string or numerical conversion. + +=item I<Concatenation> + +can be expressed in terms of string conversion. + +=item I<Comparison operations> + +can be expressed in terms of its "spaceship" counterpart: either +C<E<lt>=E<gt>> or C<cmp>: + + <, >, <=, >=, ==, != in terms of <=> + lt, gt, le, ge, eq, ne in terms of cmp + +=item I<Iterator> + + <> in terms of builtin operations + +=item I<Dereferencing> + + ${} @{} %{} &{} *{} in terms of builtin operations + +=item I<Copy operator> + +can be expressed in terms of an assignment to the dereferenced value, if this +value is a scalar and not a reference. + +=back + +=head1 Losing overloading + +The restriction for the comparison operation is that even if, for example, +`C<cmp>' should return a blessed reference, the autogenerated `C<lt>' +function will produce only a standard logical value based on the +numerical value of the result of `C<cmp>'. In particular, a working +numeric conversion is needed in this case (possibly expressed in terms of +other conversions). + +Similarly, C<.=> and C<x=> operators lose their mathemagical properties +if the string conversion substitution is applied. + +When you chop() a mathemagical object it is promoted to a string and its +mathemagical properties are lost. The same can happen with other +operations as well. + +=head1 Run-time Overloading + +Since all C<use> directives are executed at compile-time, the only way to +change overloading during run-time is to + + eval 'use overload "+" => \&addmethod'; + +You can also use + + eval 'no overload "+", "--", "<="'; + +though the use of these constructs during run-time is questionable. + +=head1 Public functions + +Package C<overload.pm> provides the following public functions: + +=over 5 + +=item overload::StrVal(arg) + +Gives string value of C<arg> as in absence of stringify overloading. If you +are using this to get the address of a reference (useful for checking if two +references point to the same thing) then you may be better off using +C<Scalar::Util::refaddr()>, which is faster. + +=item overload::Overloaded(arg) + +Returns true if C<arg> is subject to overloading of some operations. + +=item overload::Method(obj,op) + +Returns C<undef> or a reference to the method that implements C<op>. + +=back + +=head1 Overloading constants + +For some applications, the Perl parser mangles constants too much. +It is possible to hook into this process via C<overload::constant()> +and C<overload::remove_constant()> functions. + +These functions take a hash as an argument. The recognized keys of this hash +are: + +=over 8 + +=item integer + +to overload integer constants, + +=item float + +to overload floating point constants, + +=item binary + +to overload octal and hexadecimal constants, + +=item q + +to overload C<q>-quoted strings, constant pieces of C<qq>- and C<qx>-quoted +strings and here-documents, + +=item qr + +to overload constant pieces of regular expressions. + +=back + +The corresponding values are references to functions which take three arguments: +the first one is the I<initial> string form of the constant, the second one +is how Perl interprets this constant, the third one is how the constant is used. +Note that the initial string form does not +contain string delimiters, and has backslashes in backslash-delimiter +combinations stripped (thus the value of delimiter is not relevant for +processing of this string). The return value of this function is how this +constant is going to be interpreted by Perl. The third argument is undefined +unless for overloaded C<q>- and C<qr>- constants, it is C<q> in single-quote +context (comes from strings, regular expressions, and single-quote HERE +documents), it is C<tr> for arguments of C<tr>/C<y> operators, +it is C<s> for right-hand side of C<s>-operator, and it is C<qq> otherwise. + +Since an expression C<"ab$cd,,"> is just a shortcut for C<'ab' . $cd . ',,'>, +it is expected that overloaded constant strings are equipped with reasonable +overloaded catenation operator, otherwise absurd results will result. +Similarly, negative numbers are considered as negations of positive constants. + +Note that it is probably meaningless to call the functions overload::constant() +and overload::remove_constant() from anywhere but import() and unimport() methods. +From these methods they may be called as + + sub import { + shift; + return unless @_; + die "unknown import: @_" unless @_ == 1 and $_[0] eq ':constant'; + overload::constant integer => sub {Math::BigInt->new(shift)}; + } + +B<BUGS> Currently overloaded-ness of constants does not propagate +into C<eval '...'>. + +=head1 IMPLEMENTATION + +What follows is subject to change RSN. + +The table of methods for all operations is cached in magic for the +symbol table hash for the package. The cache is invalidated during +processing of C<use overload>, C<no overload>, new function +definitions, and changes in @ISA. However, this invalidation remains +unprocessed until the next C<bless>ing into the package. Hence if you +want to change overloading structure dynamically, you'll need an +additional (fake) C<bless>ing to update the table. + +(Every SVish thing has a magic queue, and magic is an entry in that +queue. This is how a single variable may participate in multiple +forms of magic simultaneously. For instance, environment variables +regularly have two forms at once: their %ENV magic and their taint +magic. However, the magic which implements overloading is applied to +the stashes, which are rarely used directly, thus should not slow down +Perl.) + +If an object belongs to a package using overload, it carries a special +flag. Thus the only speed penalty during arithmetic operations without +overloading is the checking of this flag. + +In fact, if C<use overload> is not present, there is almost no overhead +for overloadable operations, so most programs should not suffer +measurable performance penalties. A considerable effort was made to +minimize the overhead when overload is used in some package, but the +arguments in question do not belong to packages using overload. When +in doubt, test your speed with C<use overload> and without it. So far +there have been no reports of substantial speed degradation if Perl is +compiled with optimization turned on. + +There is no size penalty for data if overload is not used. The only +size penalty if overload is used in some package is that I<all> the +packages acquire a magic during the next C<bless>ing into the +package. This magic is three-words-long for packages without +overloading, and carries the cache table if the package is overloaded. + +Copying (C<$a=$b>) is shallow; however, a one-level-deep copying is +carried out before any operation that can imply an assignment to the +object $a (or $b) refers to, like C<$a++>. You can override this +behavior by defining your own copy constructor (see L<"Copy Constructor">). + +It is expected that arguments to methods that are not explicitly supposed +to be changed are constant (but this is not enforced). + +=head1 Metaphor clash + +One may wonder why the semantic of overloaded C<=> is so counter intuitive. +If it I<looks> counter intuitive to you, you are subject to a metaphor +clash. + +Here is a Perl object metaphor: + +I< object is a reference to blessed data> + +and an arithmetic metaphor: + +I< object is a thing by itself>. + +The I<main> problem of overloading C<=> is the fact that these metaphors +imply different actions on the assignment C<$a = $b> if $a and $b are +objects. Perl-think implies that $a becomes a reference to whatever +$b was referencing. Arithmetic-think implies that the value of "object" +$a is changed to become the value of the object $b, preserving the fact +that $a and $b are separate entities. + +The difference is not relevant in the absence of mutators. After +a Perl-way assignment an operation which mutates the data referenced by $a +would change the data referenced by $b too. Effectively, after +C<$a = $b> values of $a and $b become I<indistinguishable>. + +On the other hand, anyone who has used algebraic notation knows the +expressive power of the arithmetic metaphor. Overloading works hard +to enable this metaphor while preserving the Perlian way as far as +possible. Since it is not possible to freely mix two contradicting +metaphors, overloading allows the arithmetic way to write things I<as +far as all the mutators are called via overloaded access only>. The +way it is done is described in L<Copy Constructor>. + +If some mutator methods are directly applied to the overloaded values, +one may need to I<explicitly unlink> other values which references the +same value: + + $a = new Data 23; + ... + $b = $a; # $b is "linked" to $a + ... + $a = $a->clone; # Unlink $b from $a + $a->increment_by(4); + +Note that overloaded access makes this transparent: + + $a = new Data 23; + $b = $a; # $b is "linked" to $a + $a += 4; # would unlink $b automagically + +However, it would not make + + $a = new Data 23; + $a = 4; # Now $a is a plain 4, not 'Data' + +preserve "objectness" of $a. But Perl I<has> a way to make assignments +to an object do whatever you want. It is just not the overload, but +tie()ing interface (see L<perlfunc/tie>). Adding a FETCH() method +which returns the object itself, and STORE() method which changes the +value of the object, one can reproduce the arithmetic metaphor in its +completeness, at least for variables which were tie()d from the start. + +(Note that a workaround for a bug may be needed, see L<"BUGS">.) + +=head1 Cookbook + +Please add examples to what follows! + +=head2 Two-face scalars + +Put this in F<two_face.pm> in your Perl library directory: + + package two_face; # Scalars with separate string and + # numeric values. + sub new { my $p = shift; bless [@_], $p } + use overload '""' => \&str, '0+' => \&num, fallback => 1; + sub num {shift->[1]} + sub str {shift->[0]} + +Use it as follows: + + require two_face; + my $seven = new two_face ("vii", 7); + printf "seven=$seven, seven=%d, eight=%d\n", $seven, $seven+1; + print "seven contains `i'\n" if $seven =~ /i/; + +(The second line creates a scalar which has both a string value, and a +numeric value.) This prints: + + seven=vii, seven=7, eight=8 + seven contains `i' + +=head2 Two-face references + +Suppose you want to create an object which is accessible as both an +array reference and a hash reference, similar to the +L<pseudo-hash|perlref/"Pseudo-hashes: Using an array as a hash"> +builtin Perl type. Let's make it better than a pseudo-hash by +allowing index 0 to be treated as a normal element. + + package two_refs; + use overload '%{}' => \&gethash, '@{}' => sub { $ {shift()} }; + sub new { + my $p = shift; + bless \ [@_], $p; + } + sub gethash { + my %h; + my $self = shift; + tie %h, ref $self, $self; + \%h; + } + + sub TIEHASH { my $p = shift; bless \ shift, $p } + my %fields; + my $i = 0; + $fields{$_} = $i++ foreach qw{zero one two three}; + sub STORE { + my $self = ${shift()}; + my $key = $fields{shift()}; + defined $key or die "Out of band access"; + $$self->[$key] = shift; + } + sub FETCH { + my $self = ${shift()}; + my $key = $fields{shift()}; + defined $key or die "Out of band access"; + $$self->[$key]; + } + +Now one can access an object using both the array and hash syntax: + + my $bar = new two_refs 3,4,5,6; + $bar->[2] = 11; + $bar->{two} == 11 or die 'bad hash fetch'; + +Note several important features of this example. First of all, the +I<actual> type of $bar is a scalar reference, and we do not overload +the scalar dereference. Thus we can get the I<actual> non-overloaded +contents of $bar by just using C<$$bar> (what we do in functions which +overload dereference). Similarly, the object returned by the +TIEHASH() method is a scalar reference. + +Second, we create a new tied hash each time the hash syntax is used. +This allows us not to worry about a possibility of a reference loop, +which would lead to a memory leak. + +Both these problems can be cured. Say, if we want to overload hash +dereference on a reference to an object which is I<implemented> as a +hash itself, the only problem one has to circumvent is how to access +this I<actual> hash (as opposed to the I<virtual> hash exhibited by the +overloaded dereference operator). Here is one possible fetching routine: + + sub access_hash { + my ($self, $key) = (shift, shift); + my $class = ref $self; + bless $self, 'overload::dummy'; # Disable overloading of %{} + my $out = $self->{$key}; + bless $self, $class; # Restore overloading + $out; + } + +To remove creation of the tied hash on each access, one may an extra +level of indirection which allows a non-circular structure of references: + + package two_refs1; + use overload '%{}' => sub { ${shift()}->[1] }, + '@{}' => sub { ${shift()}->[0] }; + sub new { + my $p = shift; + my $a = [@_]; + my %h; + tie %h, $p, $a; + bless \ [$a, \%h], $p; + } + sub gethash { + my %h; + my $self = shift; + tie %h, ref $self, $self; + \%h; + } + + sub TIEHASH { my $p = shift; bless \ shift, $p } + my %fields; + my $i = 0; + $fields{$_} = $i++ foreach qw{zero one two three}; + sub STORE { + my $a = ${shift()}; + my $key = $fields{shift()}; + defined $key or die "Out of band access"; + $a->[$key] = shift; + } + sub FETCH { + my $a = ${shift()}; + my $key = $fields{shift()}; + defined $key or die "Out of band access"; + $a->[$key]; + } + +Now if $baz is overloaded like this, then C<$baz> is a reference to a +reference to the intermediate array, which keeps a reference to an +actual array, and the access hash. The tie()ing object for the access +hash is a reference to a reference to the actual array, so + +=over + +=item * + +There are no loops of references. + +=item * + +Both "objects" which are blessed into the class C<two_refs1> are +references to a reference to an array, thus references to a I<scalar>. +Thus the accessor expression C<$$foo-E<gt>[$ind]> involves no +overloaded operations. + +=back + +=head2 Symbolic calculator + +Put this in F<symbolic.pm> in your Perl library directory: + + package symbolic; # Primitive symbolic calculator + use overload nomethod => \&wrap; + + sub new { shift; bless ['n', @_] } + sub wrap { + my ($obj, $other, $inv, $meth) = @_; + ($obj, $other) = ($other, $obj) if $inv; + bless [$meth, $obj, $other]; + } + +This module is very unusual as overloaded modules go: it does not +provide any usual overloaded operators, instead it provides the L<Last +Resort> operator C<nomethod>. In this example the corresponding +subroutine returns an object which encapsulates operations done over +the objects: C<new symbolic 3> contains C<['n', 3]>, C<2 + new +symbolic 3> contains C<['+', 2, ['n', 3]]>. + +Here is an example of the script which "calculates" the side of +circumscribed octagon using the above package: + + require symbolic; + my $iter = 1; # 2**($iter+2) = 8 + my $side = new symbolic 1; + my $cnt = $iter; + + while ($cnt--) { + $side = (sqrt(1 + $side**2) - 1)/$side; + } + print "OK\n"; + +The value of $side is + + ['/', ['-', ['sqrt', ['+', 1, ['**', ['n', 1], 2]], + undef], 1], ['n', 1]] + +Note that while we obtained this value using a nice little script, +there is no simple way to I<use> this value. In fact this value may +be inspected in debugger (see L<perldebug>), but ony if +C<bareStringify> B<O>ption is set, and not via C<p> command. + +If one attempts to print this value, then the overloaded operator +C<""> will be called, which will call C<nomethod> operator. The +result of this operator will be stringified again, but this result is +again of type C<symbolic>, which will lead to an infinite loop. + +Add a pretty-printer method to the module F<symbolic.pm>: + + sub pretty { + my ($meth, $a, $b) = @{+shift}; + $a = 'u' unless defined $a; + $b = 'u' unless defined $b; + $a = $a->pretty if ref $a; + $b = $b->pretty if ref $b; + "[$meth $a $b]"; + } + +Now one can finish the script by + + print "side = ", $side->pretty, "\n"; + +The method C<pretty> is doing object-to-string conversion, so it +is natural to overload the operator C<""> using this method. However, +inside such a method it is not necessary to pretty-print the +I<components> $a and $b of an object. In the above subroutine +C<"[$meth $a $b]"> is a catenation of some strings and components $a +and $b. If these components use overloading, the catenation operator +will look for an overloaded operator C<.>; if not present, it will +look for an overloaded operator C<"">. Thus it is enough to use + + use overload nomethod => \&wrap, '""' => \&str; + sub str { + my ($meth, $a, $b) = @{+shift}; + $a = 'u' unless defined $a; + $b = 'u' unless defined $b; + "[$meth $a $b]"; + } + +Now one can change the last line of the script to + + print "side = $side\n"; + +which outputs + + side = [/ [- [sqrt [+ 1 [** [n 1 u] 2]] u] 1] [n 1 u]] + +and one can inspect the value in debugger using all the possible +methods. + +Something is still amiss: consider the loop variable $cnt of the +script. It was a number, not an object. We cannot make this value of +type C<symbolic>, since then the loop will not terminate. + +Indeed, to terminate the cycle, the $cnt should become false. +However, the operator C<bool> for checking falsity is overloaded (this +time via overloaded C<"">), and returns a long string, thus any object +of type C<symbolic> is true. To overcome this, we need a way to +compare an object to 0. In fact, it is easier to write a numeric +conversion routine. + +Here is the text of F<symbolic.pm> with such a routine added (and +slightly modified str()): + + package symbolic; # Primitive symbolic calculator + use overload + nomethod => \&wrap, '""' => \&str, '0+' => \# + + sub new { shift; bless ['n', @_] } + sub wrap { + my ($obj, $other, $inv, $meth) = @_; + ($obj, $other) = ($other, $obj) if $inv; + bless [$meth, $obj, $other]; + } + sub str { + my ($meth, $a, $b) = @{+shift}; + $a = 'u' unless defined $a; + if (defined $b) { + "[$meth $a $b]"; + } else { + "[$meth $a]"; + } + } + my %subr = ( n => sub {$_[0]}, + sqrt => sub {sqrt $_[0]}, + '-' => sub {shift() - shift()}, + '+' => sub {shift() + shift()}, + '/' => sub {shift() / shift()}, + '*' => sub {shift() * shift()}, + '**' => sub {shift() ** shift()}, + ); + sub num { + my ($meth, $a, $b) = @{+shift}; + my $subr = $subr{$meth} + or die "Do not know how to ($meth) in symbolic"; + $a = $a->num if ref $a eq __PACKAGE__; + $b = $b->num if ref $b eq __PACKAGE__; + $subr->($a,$b); + } + +All the work of numeric conversion is done in %subr and num(). Of +course, %subr is not complete, it contains only operators used in the +example below. Here is the extra-credit question: why do we need an +explicit recursion in num()? (Answer is at the end of this section.) + +Use this module like this: + + require symbolic; + my $iter = new symbolic 2; # 16-gon + my $side = new symbolic 1; + my $cnt = $iter; + + while ($cnt) { + $cnt = $cnt - 1; # Mutator `--' not implemented + $side = (sqrt(1 + $side**2) - 1)/$side; + } + printf "%s=%f\n", $side, $side; + printf "pi=%f\n", $side*(2**($iter+2)); + +It prints (without so many line breaks) + + [/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] + [n 1]] 2]]] 1] + [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]=0.198912 + pi=3.182598 + +The above module is very primitive. It does not implement +mutator methods (C<++>, C<-=> and so on), does not do deep copying +(not required without mutators!), and implements only those arithmetic +operations which are used in the example. + +To implement most arithmetic operations is easy; one should just use +the tables of operations, and change the code which fills %subr to + + my %subr = ( 'n' => sub {$_[0]} ); + foreach my $op (split " ", $overload::ops{with_assign}) { + $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}"; + } + my @bins = qw(binary 3way_comparison num_comparison str_comparison); + foreach my $op (split " ", "@overload::ops{ @bins }") { + $subr{$op} = eval "sub {shift() $op shift()}"; + } + foreach my $op (split " ", "@overload::ops{qw(unary func)}") { + print "defining `$op'\n"; + $subr{$op} = eval "sub {$op shift()}"; + } + +Due to L<Calling Conventions for Mutators>, we do not need anything +special to make C<+=> and friends work, except filling C<+=> entry of +%subr, and defining a copy constructor (needed since Perl has no +way to know that the implementation of C<'+='> does not mutate +the argument, compare L<Copy Constructor>). + +To implement a copy constructor, add C<< '=' => \&cpy >> to C<use overload> +line, and code (this code assumes that mutators change things one level +deep only, so recursive copying is not needed): + + sub cpy { + my $self = shift; + bless [@$self], ref $self; + } + +To make C<++> and C<--> work, we need to implement actual mutators, +either directly, or in C<nomethod>. We continue to do things inside +C<nomethod>, thus add + + if ($meth eq '++' or $meth eq '--') { + @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference + return $obj; + } + +after the first line of wrap(). This is not a most effective +implementation, one may consider + + sub inc { $_[0] = bless ['++', shift, 1]; } + +instead. + +As a final remark, note that one can fill %subr by + + my %subr = ( 'n' => sub {$_[0]} ); + foreach my $op (split " ", $overload::ops{with_assign}) { + $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}"; + } + my @bins = qw(binary 3way_comparison num_comparison str_comparison); + foreach my $op (split " ", "@overload::ops{ @bins }") { + $subr{$op} = eval "sub {shift() $op shift()}"; + } + foreach my $op (split " ", "@overload::ops{qw(unary func)}") { + $subr{$op} = eval "sub {$op shift()}"; + } + $subr{'++'} = $subr{'+'}; + $subr{'--'} = $subr{'-'}; + +This finishes implementation of a primitive symbolic calculator in +50 lines of Perl code. Since the numeric values of subexpressions +are not cached, the calculator is very slow. + +Here is the answer for the exercise: In the case of str(), we need no +explicit recursion since the overloaded C<.>-operator will fall back +to an existing overloaded operator C<"">. Overloaded arithmetic +operators I<do not> fall back to numeric conversion if C<fallback> is +not explicitly requested. Thus without an explicit recursion num() +would convert C<['+', $a, $b]> to C<$a + $b>, which would just rebuild +the argument of num(). + +If you wonder why defaults for conversion are different for str() and +num(), note how easy it was to write the symbolic calculator. This +simplicity is due to an appropriate choice of defaults. One extra +note: due to the explicit recursion num() is more fragile than sym(): +we need to explicitly check for the type of $a and $b. If components +$a and $b happen to be of some related type, this may lead to problems. + +=head2 I<Really> symbolic calculator + +One may wonder why we call the above calculator symbolic. The reason +is that the actual calculation of the value of expression is postponed +until the value is I<used>. + +To see it in action, add a method + + sub STORE { + my $obj = shift; + $#$obj = 1; + @$obj->[0,1] = ('=', shift); + } + +to the package C<symbolic>. After this change one can do + + my $a = new symbolic 3; + my $b = new symbolic 4; + my $c = sqrt($a**2 + $b**2); + +and the numeric value of $c becomes 5. However, after calling + + $a->STORE(12); $b->STORE(5); + +the numeric value of $c becomes 13. There is no doubt now that the module +symbolic provides a I<symbolic> calculator indeed. + +To hide the rough edges under the hood, provide a tie()d interface to the +package C<symbolic> (compare with L<Metaphor clash>). Add methods + + sub TIESCALAR { my $pack = shift; $pack->new(@_) } + sub FETCH { shift } + sub nop { } # Around a bug + +(the bug is described in L<"BUGS">). One can use this new interface as + + tie $a, 'symbolic', 3; + tie $b, 'symbolic', 4; + $a->nop; $b->nop; # Around a bug + + my $c = sqrt($a**2 + $b**2); + +Now numeric value of $c is 5. After C<$a = 12; $b = 5> the numeric value +of $c becomes 13. To insulate the user of the module add a method + + sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; } + +Now + + my ($a, $b); + symbolic->vars($a, $b); + my $c = sqrt($a**2 + $b**2); + + $a = 3; $b = 4; + printf "c5 %s=%f\n", $c, $c; + + $a = 12; $b = 5; + printf "c13 %s=%f\n", $c, $c; + +shows that the numeric value of $c follows changes to the values of $a +and $b. + +=head1 AUTHOR + +Ilya Zakharevich E<lt>F<ilya@math.mps.ohio-state.edu>E<gt>. + +=head1 DIAGNOSTICS + +When Perl is run with the B<-Do> switch or its equivalent, overloading +induces diagnostic messages. + +Using the C<m> command of Perl debugger (see L<perldebug>) one can +deduce which operations are overloaded (and which ancestor triggers +this overloading). Say, if C<eq> is overloaded, then the method C<(eq> +is shown by debugger. The method C<()> corresponds to the C<fallback> +key (in fact a presence of this method shows that this package has +overloading enabled, and it is what is used by the C<Overloaded> +function of module C<overload>). + +The module might issue the following warnings: + +=over 4 + +=item Odd number of arguments for overload::constant + +(W) The call to overload::constant contained an odd number of arguments. +The arguments should come in pairs. + +=item `%s' is not an overloadable type + +(W) You tried to overload a constant type the overload package is unaware of. + +=item `%s' is not a code reference + +(W) The second (fourth, sixth, ...) argument of overload::constant needs +to be a code reference. Either an anonymous subroutine, or a reference +to a subroutine. + +=back + +=head1 BUGS + +Because it is used for overloading, the per-package hash %OVERLOAD now +has a special meaning in Perl. The symbol table is filled with names +looking like line-noise. + +For the purpose of inheritance every overloaded package behaves as if +C<fallback> is present (possibly undefined). This may create +interesting effects if some package is not overloaded, but inherits +from two overloaded packages. + +Relation between overloading and tie()ing is broken. Overloading is +triggered or not basing on the I<previous> class of tie()d value. + +This happens because the presence of overloading is checked too early, +before any tie()d access is attempted. If the FETCH()ed class of the +tie()d value does not change, a simple workaround is to access the value +immediately after tie()ing, so that after this call the I<previous> class +coincides with the current one. + +B<Needed:> a way to fix this without a speed penalty. + +Barewords are not covered by overloaded string constants. + +This document is confusing. There are grammos and misleading language +used in places. It would seem a total rewrite is needed. + +=cut + |