[Solved] Re: Windows registry PermissionError

Mike Dewhirst miked at dewhirst.com.au
Fri May 13 01:36:44 EDT 2022


Eryk

Many thanks. It is working perfectly now. See below for the reworked code.

Cheers

Mike

On 13/05/2022 1:42 pm, Eryk Sun wrote:
> On 5/12/22, Mike Dewhirst<miked at dewhirst.com.au>  wrote:
>>               access=wr.KEY_ALL_ACCESS + wr.KEY_WRITE,

import winreg as wr class Registry: def __init__(self, computer=None, 
hkey=None, sub_key=None): self.computer = computer self.key = hkey 
self.sub_key = sub_key def connect(self): return 
wr.ConnectRegistry(self.computer, self.key) def select(self, 
access=None): with self.connect() as hkey: return wr.OpenKeyEx(key=hkey, 
sub_key=self.sub_key, access=access) def count(self): access = 
wr.KEY_QUERY_VALUE return wr.QueryInfoKey(self.select(access=access)) 
def query(self, vname, access=None): if access is None: access = 
wr.KEY_READ | wr.KEY_WOW64_32KEY return 
wr.QueryValueEx(self.select(access=access), vname) def setvalue(self, 
vname, value, access=None): if access is None: access = wr.KEY_SET_VALUE 
with self.select(access=access) as hkey: return wr.SetValueEx(hkey, 
vname, 0, wr.REG_SZ, value) if __name__ == "__main__": lmregistry = 
Registry( hkey=wr.HKEY_LOCAL_MACHINE, sub_key=r"SOFTWARE\XXX 
Technology\AppName", ) print(f"\n{lmregistry.sub_key}") anz = 
lmregistry.query('Country')[0] print(f"\n{anz}") db = 
lmregistry.query('Database')[0] print(f"\n{db}") devref = 
lmregistry.query('v135')[0] print(f"\n{devref}") orgid = 
lmregistry.query('v136')[0] print(f"\n{orgid}") curegistry = Registry( 
hkey=wr.HKEY_CURRENT_USER, sub_key=r"SOFTWARE\XXX Technology\AppName", ) 
print(f"\n{curegistry.sub_key}") anz = curegistry.query('Country')[0] 
print(f"\n{anz}") db = curegistry.query('Database')[0] print(f"\n{db}") 
devref = curegistry.query('v135')[0] print(f"\n{devref}") orgid = 
curegistry.query('v136')[0] print(f"\n{orgid}") 
curegistry.setvalue('Country', 'nz') curegistry.setvalue('Database', 
'2022.2') curegistry.setvalue('v135', 'Asus10') 
curegistry.setvalue('v136', orgid.replace('ALL', 'Most')) anz = 
curegistry.query('Country')[0] print(f"\n{anz}") db = 
curegistry.query('Database')[0] print(f"\n{db}") devref = 
curegistry.query('v135')[0] print(f"\n{devref}") orgid = 
curegistry.query('v136')[0] print(f"\n{orgid}")

Again, many thanks for putting so much effort into educating me.

Cheers

Mike
> The access parameter is a bit mask of access rights that combine via
> bitwise OR (|), not via arithmetic addition.
>
> KEY_ALL_ACCESS (0x000F_003F) is a superset of KEY_WRITE (0x0002_0006):
>
>      KEY_WRITE = (
>          READ_CONTROL           | # 0x0002_0000
>          KEY_SET_VALUE          | # 0x0000_0002
>          KEY_CREATE_SUB_KEY     | # 0x0000_0004
>      )                            # 0x0002_0006
>
>      KEY_ALL_ACCESS = (
>          DELETE                 | # 0x0001_0000
>          READ_CONTROL           | # 0x0002_0000
>          WRITE_DAC              | # 0x0004_0000
>          WRITE_OWNER            | # 0x0008_0000
>          KEY_QUERY_VALUE        | # 0x0000_0001
>          KEY_SET_VALUE          | # 0x0000_0002
>          KEY_CREATE_SUB_KEY     | # 0x0000_0004
>          KEY_ENUMERATE_SUB_KEYS | # 0x0000_0008
>          KEY_NOTIFY             | # 0x0000_0010
>          KEY_CREATE_LINK        | # 0x0000_0020
>      )                            # 0x000F_003F
>
> The result of the arithmetic addition `KEY_ALL_ACCESS + KEY_WRITE` is
> 0x0011_0045, which is wrong and meaningless. Registry key objects do
> not support SYNCHRONIZE (0x0010_0000) access; DELETE (0x0001_0000)
> access isn't needed; 0x0000_0040 is not a supported key right;
> KEY_CREATE_SUB_KEY (0x0000_0004) access isn't needed; and
> KEY_QUERY_VALUE (0x0000_0001) isn't sufficient.
>
> You should limit the requested access to the specific access rights
> that are required for querying and setting values in the key:
>
>      access=(wr.KEY_QUERY_VALUE | wr.KEY_SET_VALUE)
>
>>      def setvalue(self, vname, value):
>>         return wr.SetValueEx(self.select(), vname, 0, 1, value)
> You shouldn't hard code the value of the data type constant. Use
> wr.REG_SZ instead of 1.
>
> The return value of self.select() is a winreg PyHKEY object that wraps
> the OS handle for the key object. You're relying on implicit closing
> of this handle based on referencing counting. It's cleaner to use it
> in a `with` statement, as you would for a file object returned by
> open(). For example:
>
>      with self.select() as hkey:
>          wr.SetValueEx(hkey, vname, 0, wr.REG_SZ, value)
>
>>       lmregistry = Registry(
>>           hkey=wr.HKEY_LOCAL_MACHINE,
>>           sub_key="SOFTWARE\WOW6432Node\XXX Technology\AppName",
> You really shouldn't open the "WOW6432Node" key directly. It is an
> implementation detail of the WOW64 subsystem that runs 32-bit
> applications on a 64-bit system. If you need to operate on the
> registry keys of 32-bit applications from a native 64-bit process,
> open the normal path using the access right KEY_WOW64_32KEY
> (0x0000_0200). For example:
>
>      hkey = wr.HKEY_LOCAL_MACHINE
>      subkey = r"SOFTWARE\XXX Technology\AppName"
>      access = (
>          wr.KEY_QUERY_VALUE |
>          wr.KEY_SET_VALUE |
>          wr.KEY_WOW64_32KEY
>      )
>
> Typically you'd first try opening the path without either
> KEY_WOW64_32KEY or KEY_WOW64_64KEY. The default view matches the
> current process.
>
> https://docs.microsoft.com/en-us/windows/win32/winprog64/accessing-an-alternate-registry-view
>
> Remember to escape the backslash separators in string literals of key
> paths, or use raw string literals as I used in the above example.


-- 
Signed email is an absolute defence against phishing. This email has
been signed with my private key. If you import my public key you can
automatically decrypt my signature and be sure it came from me. Just
ask and I'll send it to you. Your email software can handle signing.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 495 bytes
Desc: OpenPGP digital signature
URL: <https://mail.python.org/pipermail/python-list/attachments/20220513/fa2657e3/attachment.sig>


More information about the Python-list mailing list