Mailing List Archive

[Solved] Re: Windows registry PermissionError
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@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.
Re: [Solved] Re: Windows registry PermissionError [ In reply to ]
Since self.connect() is always called, you should document that the
initial hkey parameter has to be one of the following predefined key
handles:

HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_PERFORMANCE_DATA

WinAPI RegConnectRegistryW() only matters when the target computer is
a different machine, in which case an RPC proxy handle is returned.
--
https://mail.python.org/mailman/listinfo/python-list
Re: [Solved] Re: Windows registry PermissionError [ In reply to ]
On 13/05/2022 4:14 pm, Eryk Sun wrote:
> Since self.connect() is always called, you should document that the
> initial hkey parameter has to be one of the following predefined key
> handles:
>
> HKEY_LOCAL_MACHINE
> HKEY_USERS

I'm targeting HKEY_CURRENT_USER so I assume HK_USERS includes that.

Thanks again Eryk

Cheers

mike

> HKEY_PERFORMANCE_DATA
>
> WinAPI RegConnectRegistryW() only matters when the target computer is
> a different machine, in which case an RPC proxy handle is returned.


--
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: [Solved] Re: Windows registry PermissionError [ In reply to ]
On 5/13/22, Mike Dewhirst <miked@dewhirst.com.au> wrote:
> On 13/05/2022 4:14 pm, Eryk Sun wrote:
>> Since self.connect() is always called, you should document that the
>> initial hkey parameter has to be one of the following predefined key
>> handles:
>>
>> HKEY_LOCAL_MACHINE
>> HKEY_USERS
>
> I'm targeting HKEY_CURRENT_USER so I assume HK_USERS includes that.

Using HKEY_CURRENT_USER with RegConnectRegistryW() to access a remote
registry isn't well defined and not documented as supported. If it
works at all, the API probably just opens a subkey of the remote
HKEY_USERS based on the string SID (security identifier string) of the
current user. That may fail as not found since user SIDs are unique to
machines, unless it's on a domain.

Bear in mind that the remote registry service is running on the remote
machine as SYSTEM (S-1-5-18) in the non-interactive services session.
If it literally accessed its "current user", then it would open
"HKEY_USERS\S-1-5-18".
--
https://mail.python.org/mailman/listinfo/python-list
Re: [Solved] Re: Windows registry PermissionError [ In reply to ]
On 13/05/2022 4:37 pm, Eryk Sun wrote:
> On 5/13/22, Mike Dewhirst<miked@dewhirst.com.au> wrote:
>> On 13/05/2022 4:14 pm, Eryk Sun wrote:
>>> Since self.connect() is always called, you should document that the
>>> initial hkey parameter has to be one of the following predefined key
>>> handles:
>>>
>>> HKEY_LOCAL_MACHINE
>>> HKEY_USERS
>> I'm targeting HKEY_CURRENT_USER so I assume HK_USERS includes that.
> Using HKEY_CURRENT_USER with RegConnectRegistryW() to access a remote
> registry isn't well defined and not documented as supported. If it
> works at all, the API probably just opens a subkey of the remote
> HKEY_USERS based on the string SID (security identifier string) of the
> current user. That may fail as not found since user SIDs are unique to
> machines, unless it's on a domain.
>
> Bear in mind that the remote registry service is running on the remote
> machine as SYSTEM (S-1-5-18) in the non-interactive services session.
> If it literally accessed its "current user", then it would open
> "HKEY_USERS\S-1-5-18".
In that case, I'll remove 'computer' as a parameter and lock it in as
None. I'll document why and if I ever need to access a remote registry
I'll do some research along the lines you suggest.

My case demands execution of this code via login script for end-user
configuration after the IT department has done a bulk installation
rollout. One of key items is ComputerName which is in HKLM and needs to
be in HKCU for whichever user logs in. The application looks in HKCU for
a unique Device Reference and ComputerName suffices and is attractive
because it is also the asset number of the machine.


--
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.