mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-12 23:37:14 +03:00
winreg in Python <= 3.7.4 handles REG_MULTI_SZ incorrectly
https://bugs.python.org/issue32587 Partially reverts 5989acd0d3263e54429ff99769ff73a20476d863
This commit is contained in:
parent
d71e3445c7
commit
0ef0f017f1
109
config.py
109
config.py
@ -21,7 +21,6 @@ elif platform=='win32':
|
||||
import ctypes
|
||||
from ctypes.wintypes import *
|
||||
import uuid
|
||||
from winreg import CloseKey, CreateKeyEx, OpenKeyEx, DeleteValue, QueryValueEx, SetValueEx, HKEY_CURRENT_USER, KEY_ALL_ACCESS, REG_SZ, REG_DWORD, REG_MULTI_SZ
|
||||
|
||||
FOLDERID_Documents = uuid.UUID('{FDD39AD0-238F-46AF-ADB4-6C85480369C7}')
|
||||
FOLDERID_LocalAppData = uuid.UUID('{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}')
|
||||
@ -34,6 +33,47 @@ elif platform=='win32':
|
||||
CoTaskMemFree = ctypes.windll.ole32.CoTaskMemFree
|
||||
CoTaskMemFree.argtypes = [ctypes.c_void_p]
|
||||
|
||||
# winreg in Python <= 3.7.4 handles REG_MULTI_SZ incorrectly, so do this instead. https://bugs.python.org/issue32587
|
||||
HKEY_CURRENT_USER = 0x80000001
|
||||
KEY_ALL_ACCESS = 0x000F003F
|
||||
REG_CREATED_NEW_KEY = 0x00000001
|
||||
REG_OPENED_EXISTING_KEY = 0x00000002
|
||||
REG_SZ = 1
|
||||
REG_DWORD = 4
|
||||
REG_MULTI_SZ = 7
|
||||
|
||||
RegCreateKeyEx = ctypes.windll.advapi32.RegCreateKeyExW
|
||||
RegCreateKeyEx.restype = LONG
|
||||
RegCreateKeyEx.argtypes = [HKEY, LPCWSTR, DWORD, LPCVOID, DWORD, DWORD, LPCVOID, ctypes.POINTER(HKEY), ctypes.POINTER(DWORD)]
|
||||
|
||||
RegOpenKeyEx = ctypes.windll.advapi32.RegOpenKeyExW
|
||||
RegOpenKeyEx.restype = LONG
|
||||
RegOpenKeyEx.argtypes = [HKEY, LPCWSTR, DWORD, DWORD, ctypes.POINTER(HKEY)]
|
||||
|
||||
RegCloseKey = ctypes.windll.advapi32.RegCloseKey
|
||||
RegCloseKey.restype = LONG
|
||||
RegCloseKey.argtypes = [HKEY]
|
||||
|
||||
RegQueryValueEx = ctypes.windll.advapi32.RegQueryValueExW
|
||||
RegQueryValueEx.restype = LONG
|
||||
RegQueryValueEx.argtypes = [HKEY, LPCWSTR, LPCVOID, ctypes.POINTER(DWORD), LPCVOID, ctypes.POINTER(DWORD)]
|
||||
|
||||
RegSetValueEx = ctypes.windll.advapi32.RegSetValueExW
|
||||
RegSetValueEx.restype = LONG
|
||||
RegSetValueEx.argtypes = [HKEY, LPCWSTR, LPCVOID, DWORD, LPCVOID, DWORD]
|
||||
|
||||
RegCopyTree = ctypes.windll.advapi32.RegCopyTreeW
|
||||
RegCopyTree.restype = LONG
|
||||
RegCopyTree.argtypes = [HKEY, LPCWSTR, HKEY]
|
||||
|
||||
RegDeleteKey = ctypes.windll.advapi32.RegDeleteTreeW
|
||||
RegDeleteKey.restype = LONG
|
||||
RegDeleteKey.argtypes = [HKEY, LPCWSTR]
|
||||
|
||||
RegDeleteValue = ctypes.windll.advapi32.RegDeleteValueW
|
||||
RegDeleteValue.restype = LONG
|
||||
RegDeleteValue.argtypes = [HKEY, LPCWSTR]
|
||||
|
||||
def KnownFolderPath(guid):
|
||||
buf = ctypes.c_wchar_p()
|
||||
if SHGetKnownFolderPath(ctypes.create_string_buffer(guid.bytes_le), 0, 0, ctypes.byref(buf)):
|
||||
@ -153,58 +193,67 @@ class Config(object):
|
||||
|
||||
self.identifier = applongname
|
||||
|
||||
self.hkey = CreateKeyEx(HKEY_CURRENT_USER, r'Software\Marginal\EDMarketConnector', access=KEY_ALL_ACCESS)
|
||||
try:
|
||||
sparklekey = OpenKeyEx(hkey, 'WinSparkle')
|
||||
except:
|
||||
# set WinSparkle defaults - https://github.com/vslavik/winsparkle/wiki/Registry-Settings
|
||||
sparklekey = CreateKeyEx(self.hkey, 'WinSparkle', access=KEY_ALL_ACCESS)
|
||||
SetValueEx(sparklekey, 'CheckForUpdates', 0, REG_SZ, '1')
|
||||
SetValueEx(sparklekey, 'UpdateInterval', 0, REG_SZ, str(update_interval))
|
||||
CloseKey(sparklekey)
|
||||
self.hkey = HKEY()
|
||||
disposition = DWORD()
|
||||
if RegCreateKeyEx(HKEY_CURRENT_USER, r'Software\Marginal\EDMarketConnector', 0, None, 0, KEY_ALL_ACCESS, None, ctypes.byref(self.hkey), ctypes.byref(disposition)):
|
||||
raise Exception()
|
||||
|
||||
# set WinSparkle defaults - https://github.com/vslavik/winsparkle/wiki/Registry-Settings
|
||||
sparklekey = HKEY()
|
||||
if not RegCreateKeyEx(self.hkey, 'WinSparkle', 0, None, 0, KEY_ALL_ACCESS, None, ctypes.byref(sparklekey), ctypes.byref(disposition)):
|
||||
if disposition.value == REG_CREATED_NEW_KEY:
|
||||
buf = ctypes.create_unicode_buffer('1')
|
||||
RegSetValueEx(sparklekey, 'CheckForUpdates', 0, 1, buf, len(buf)*2)
|
||||
buf = ctypes.create_unicode_buffer(str(update_interval))
|
||||
RegSetValueEx(sparklekey, 'UpdateInterval', 0, 1, buf, len(buf)*2)
|
||||
RegCloseKey(sparklekey)
|
||||
|
||||
if not self.get('outdir') or not isdir(self.get('outdir')):
|
||||
self.set('outdir', KnownFolderPath(FOLDERID_Documents) or self.home)
|
||||
|
||||
def get(self, key):
|
||||
try:
|
||||
(value, typ) = QueryValueEx(self.hkey, key)
|
||||
if typ not in [REG_SZ, REG_MULTI_SZ]:
|
||||
raise ValueError()
|
||||
return value
|
||||
except:
|
||||
typ = DWORD()
|
||||
size = DWORD()
|
||||
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), None, ctypes.byref(size)) or typ.value not in [REG_SZ, REG_MULTI_SZ]:
|
||||
return None
|
||||
buf = ctypes.create_unicode_buffer(int(size.value / 2))
|
||||
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), buf, ctypes.byref(size)):
|
||||
return None
|
||||
elif typ.value == REG_MULTI_SZ:
|
||||
return [x for x in ctypes.wstring_at(buf, len(buf)-2).split(u'\x00')]
|
||||
else:
|
||||
return str(buf.value)
|
||||
|
||||
def getint(self, key):
|
||||
try:
|
||||
(value, typ) = QueryValueEx(self.hkey, key)
|
||||
if typ != REG_DWORD:
|
||||
raise ValueError()
|
||||
return value
|
||||
except:
|
||||
typ = DWORD()
|
||||
size = DWORD(4)
|
||||
val = DWORD()
|
||||
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), ctypes.byref(val), ctypes.byref(size)) or typ.value != REG_DWORD:
|
||||
return 0
|
||||
else:
|
||||
return val.value
|
||||
|
||||
def set(self, key, val):
|
||||
if isinstance(val, str):
|
||||
SetValueEx(self.hkey, key, 0, REG_SZ, val)
|
||||
buf = ctypes.create_unicode_buffer(val)
|
||||
RegSetValueEx(self.hkey, key, 0, REG_SZ, buf, len(buf)*2)
|
||||
elif isinstance(val, numbers.Integral):
|
||||
SetValueEx(self.hkey, key, 0, REG_DWORD, val)
|
||||
RegSetValueEx(self.hkey, key, 0, REG_DWORD, ctypes.byref(DWORD(val)), 4)
|
||||
elif hasattr(val, '__iter__'): # iterable
|
||||
SetValueEx(self.hkey, key, 0, REG_MULTI_SZ, val)
|
||||
stringval = u'\x00'.join([str(x) or u' ' for x in val] + [u'']) # null terminated non-empty strings
|
||||
buf = ctypes.create_unicode_buffer(stringval)
|
||||
RegSetValueEx(self.hkey, key, 0, REG_MULTI_SZ, buf, len(buf)*2)
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete(self, key):
|
||||
try:
|
||||
DeleteValue(self.hkey, key)
|
||||
except:
|
||||
pass
|
||||
RegDeleteValue(self.hkey, key)
|
||||
|
||||
def save(self):
|
||||
pass # Redundant since registry keys are written immediately
|
||||
|
||||
def close(self):
|
||||
CloseKey(self.hkey)
|
||||
RegCloseKey(self.hkey)
|
||||
self.hkey = None
|
||||
|
||||
elif platform=='linux':
|
||||
|
Loading…
x
Reference in New Issue
Block a user