almut has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone,

while trying to get a couple of modules to work on 64-bit Windows, I accidentally stumbled across a problem with Win32::TieRegistry, which is that make test is failing for 3 of the 4 tests that come with the module:

...\Win32-TieRegistry-0.25> nmake test >debug.out 2>&1 ...\Win32-TieRegistry-0.25> type debug.out Microsoft (R) Program Maintenance Utility Version 7.00.8882 Copyright (C) Microsoft Corp 1988-2000. All rights reserved. C:\Temp\perl-5.8.8-64\5.8.8\bin\MSWin32-AMD64-multi-thread\perl.ex +e "-Iblib\lib" "-Iblib\arch" test.pl 1..4 ok 1 # Can't open CU/SW/MS/Win/CV/Pol/Exp//NoDriveTypeAutoRun: The handle i +s invalid not ok 2 Use of uninitialized value in print at test.pl line 28. # REG_DWORD is 4, type is Use of uninitialized value in numeric eq (==) at test.pl line 29. not ok 3 Use of uninitialized value in print at test.pl line 31. # $val->[0] is "". Use of uninitialized value in pattern match (m//) at test.pl line 32. not ok 4

(the "uninitialized values" are just secondary errors due to the registry lookup failing in the first place)

As so often, the Windows system error message $^E (here The handle is invalid) wasn't all that useful, but a bit of digging through the sources revealed that the real problem is the access permissions, which are defaulting to KEY_READ | KEY_WRITE. This apparently doesn't harmonise well with the default settings (for regular users) on more recent versions of Windows (the system where this initially popped up is a "Windows Server 2003, Standard x64 Edition").

Adding the following line to TieRegistry.pm:454:

... $sam= defined($opts->{Access}) ? $opts->{Access} : $this->Access; $sam= _constant($sam,"key access type") if $sam =~ /^KEY_/; $sam = KEY_READ; # <--- force value for debugging ...

immediately solved the problem, i.e. all 4 tests passed.

But it goes without saying that this isn't the proper place to fix the issue... So I've instead tried to set the correct access default in the test script, where it does belong. However, I've failed miserably so far. I've made about a dozen different attempts to force my KEY_READ argument down the throat of the use statement. But no luck.

Here's the relevant part of Win32::TieRegistry's test.pl:

my $reg; use Win32::TieRegistry ( Delimiter=>"/", ArrayValues=>1, TiedRef=>\$reg, ":REG_" ); ... my $val= $reg->{ "CUser/Software/Microsoft/Windows/CurrentVersion/" . "Policies/Explorer//NoDriveTypeAutoRun" };

This is obviously using tied hashes - as opposed to the object oriented API.   I know that with the latter I can pass options like { Access => KEY_READ() } to Open(), but how do I do that with the tied hash?

Reading The Fine Manual then ruined my last hopes - but maybe some wise monk is going to be my saviour? ;)

OK, seriously, it's not so much that very test.pl I'm worried about. I'm reasonably confident now that things are working fine. What's bothering me more is that I have taken over a couple of rather largish legacy scripts which do no longer work on more recent Windowses, most likely for exactly the same reason (they are, too, using the tied hash API). I'd be more than happy if I wouldn't have to rewrite them to use the object syntax...

Thanks,
Almut

Replies are listed 'Best First'.
Re: Win32::TieRegistry: Setting Access Permissions for Tied Hash API
by tye (Sage) on Jan 30, 2007 at 04:47 UTC
    $reg= $reg->Open( "", { Access => "KEY_READ" } );

    Yes, that should be easier and more obvious (one long-standing improvement I've wanted to make). But a second long-standing improvement is even better; to change the default access to "max allowed" which pretty much removes the need to specify desired access levels.

    - tye        

      Thanks tye, you're my saviour! :)

      I think adding a related note to the docs is all that's required. Also, I agree that - in the long run - "max allowed" would be the most suitable default.