Mailing List Archive

Windows registry PermissionError
I'm trying to copy a value from HKLM to HKCU for application rollout via
bulk installation by an administrator but individual Windows user setup.

Getting this ...

Traceback (most recent call last):
  File "D:\Users\mike\envs\chemdata\registry\wreg\wreg.py", line 84, in
<module>
    curegistry.setvalue('Country', anz)
  File "D:\Users\mike\envs\chemdata\registry\wreg\wreg.py", line 51, in
setvalue
    return wr.SetValueEx(self.select(), vname, 0, 1, value)
PermissionError: [WinError 5] Access is denied

... on my very own laptop where my login has admistrator permissions ...
which I realise means nothing in this case.

But I would not have been surprised if it worked here but not in the
field where users are firefighters and definitely not administrators and
cannot install software on their workstations.

import winreg as wr


class Registry:

def __init__(self, computer=None, hkey=None, sub_key=None):
# computer is None means this computer
self.computer = computer
self.key = hkey
self.sub_key = sub_key

def connect(self):
return wr.ConnectRegistry(self.computer, self.key)

def select(self):
# also tried OpenKeyEx()
return wr.OpenKey(
key=self.key,
sub_key=self.sub_key,
access=wr.KEY_ALL_ACCESS + wr.KEY_WRITE,
)

def query(self, vname):
return wr.QueryValueEx(self.select(), vname)

def setvalue(self, vname, value):
return wr.SetValueEx(self.select(), vname, 0, 1, value)

if __name__ == "__main__":

lmregistry = Registry(
hkey=wr.HKEY_LOCAL_MACHINE,
sub_key="SOFTWARE\WOW6432Node\XXX Technology\AppName",
)
print(f"\n{lmregistry.sub_key}")
anz = lmregistry.query('Country')[0]
print(f"\n{anz}") # works fine

curegistry = Registry(
hkey=wr.HKEY_CURRENT_USER,
sub_key="SOFTWARE\XXX Technology\AppName",
)
curegistry.setvalue('Country', anz) <<<<< BOOM <<<<<
...

Any hints appreciated.

Cheers

Mike

--
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.
Re: Windows registry PermissionError [ In reply to ]
On 5/12/22, Mike Dewhirst <miked@dewhirst.com.au> wrote:
>
> access=wr.KEY_ALL_ACCESS + wr.KEY_WRITE,

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.
--
https://mail.python.org/mailman/listinfo/python-list