Re: [Solved] Re: Windows registry PermissionError
On 13/05/2022 4:37 pm, Eryk Sun wrote: On 5/13/22, Mike Dewhirst 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. OpenPGP_signature Description: OpenPGP digital signature -- https://mail.python.org/mailman/listinfo/python-list
Re: [Solved] Re: Windows registry PermissionError
On 5/13/22, Mike Dewhirst 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
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. OpenPGP_signature Description: OpenPGP digital signature -- https://mail.python.org/mailman/listinfo/python-list
Re: [Solved] Re: Windows registry PermissionError
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
[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 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_ KEY_SET_VALUE | # 0x_0002 KEY_CREATE_SUB_KEY | # 0x_0004 )# 0x0002_0006 KEY_ALL_ACCESS = ( DELETE | # 0x0001_ READ_CONTROL | # 0x0002_ WRITE_DAC | # 0x0004_ WRITE_OWNER| # 0x0008_ KEY_QUERY_VALUE| # 0x_0001 KEY_SET_VALUE | # 0x_0002 KEY_CREATE_SUB_KEY | # 0x_0004 KEY_ENUMERATE_SUB_KEYS | # 0x_0008 KEY_NOTIFY | # 0x_0010 KEY_CREATE_LINK| # 0x_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_) access; DELETE (0x0001_) access isn't needed; 0x_0040 is not a supported key right; KEY_CREATE_SUB_KEY (0x_0004) access isn't needed; and KEY_QUERY_VALUE (0x_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 (0x_0200). For example: hkey = wr.HKEY_LOCAL_MACHINE subkey = r"SOFTWARE\XXX Technology\AppName" access = ( wr.KEY_QUERY_VALUE |