1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-12 15:27:14 +03:00

Switch to built-in winreg module on Windows

This commit is contained in:
Jonathan Harris 2019-09-30 00:03:34 +01:00 committed by Athanasius
parent 9f456b8261
commit 823f8caf0a
2 changed files with 51 additions and 134 deletions

116
config.py
View File

@ -21,6 +21,7 @@ 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}')
@ -33,47 +34,6 @@ elif platform=='win32':
CoTaskMemFree = ctypes.windll.ole32.CoTaskMemFree
CoTaskMemFree.argtypes = [ctypes.c_void_p]
# _winreg that ships with Python 2 doesn't support unicode, so do this instead
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)):
@ -193,76 +153,58 @@ class Config(object):
self.identifier = applongname
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()
if disposition.value == REG_CREATED_NEW_KEY:
# Migrate pre-1.3.4 registry location
oldkey = HKEY()
if not RegOpenKeyEx(HKEY_CURRENT_USER, r'Software\EDMarketConnector', 0, KEY_ALL_ACCESS, ctypes.byref(oldkey)):
RegCopyTree(oldkey, None, self.hkey)
RegCloseKey(oldkey)
RegDeleteKey(HKEY_CURRENT_USER, r'Software\EDMarketConnector')
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 = 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)
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)
if not self.get('outdir') or not isdir(self.get('outdir')):
self.set('outdir', KnownFolderPath(FOLDERID_Documents) or self.home)
def get(self, key):
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]:
try:
(value, typ) = QueryValueEx(self.hkey, key)
except:
return None
buf = ctypes.create_unicode_buffer(int(size.value / 2))
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), buf, ctypes.byref(size)):
if typ not in [REG_SZ, REG_MULTI_SZ]:
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)
return value
def getint(self, key):
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
try:
(value, typ) = QueryValueEx(self.hkey, key)
except:
return None
if typ != REG_DWORD:
return None
return value
def set(self, key, val):
if isinstance(val, str):
buf = ctypes.create_unicode_buffer(val)
RegSetValueEx(self.hkey, key, 0, REG_SZ, buf, len(buf)*2)
SetValueEx(self.hkey, key, 0, REG_SZ, val)
elif isinstance(val, numbers.Integral):
RegSetValueEx(self.hkey, key, 0, REG_DWORD, ctypes.byref(DWORD(val)), 4)
SetValueEx(self.hkey, key, 0, REG_DWORD, val)
elif hasattr(val, '__iter__'): # iterable
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)
SetValueEx(self.hkey, key, 0, REG_MULTI_SZ, val)
else:
raise NotImplementedError()
def delete(self, key):
RegDeleteValue(self.hkey, key)
try:
DeleteValue(self.hkey, key)
except:
pass
def save(self):
pass # Redundant since registry keys are written immediately
def close(self):
RegCloseKey(self.hkey)
CloseKey(self.hkey)
self.hkey = None
elif platform=='linux':

View File

@ -9,29 +9,7 @@ if platform == 'win32':
import subprocess
import ctypes
from ctypes.wintypes import *
HKEY_CLASSES_ROOT = 0x80000000
HKEY_CURRENT_USER = 0x80000001
KEY_READ = 0x00020019
KEY_ALL_ACCESS = 0x000F003F
REG_SZ = 1
REG_DWORD = 4
REG_MULTI_SZ = 7
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)]
from winreg import CloseKey, OpenKeyEx, QueryValueEx, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, KEY_READ, REG_SZ, REG_MULTI_SZ
# A clickable ttk Label
#
@ -138,34 +116,31 @@ def openurl(url):
# so discover and launch the browser directly.
# https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553
hkey = HKEY()
cls = 'http'
if not RegOpenKeyEx(HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice', 0, KEY_READ, ctypes.byref(hkey)):
typ = DWORD()
size = DWORD()
if not RegQueryValueEx(hkey, 'ProgId', 0, ctypes.byref(typ), None, ctypes.byref(size)) and typ.value in [REG_SZ, REG_MULTI_SZ]:
buf = ctypes.create_unicode_buffer('', int(size.value / 2))
if not RegQueryValueEx(hkey, 'ProgId', 0, ctypes.byref(typ), buf, ctypes.byref(size)):
if buf.value in ['IE.HTTP', 'AppXq0fevzme2pys62n3e0fbqa7peapykr8v']:
# IE and Edge can't handle long arguments so just use webbrowser.open and hope
# https://blogs.msdn.microsoft.com/ieinternals/2014/08/13/url-length-limits/
cls = None
else:
cls = buf.value
RegCloseKey(hkey)
try:
hkey = OpenKeyEx(HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice')
(value, typ) = QueryValueEx(hkey, 'ProgId')
CloseKey(hkey)
if value in ['IE.HTTP', 'AppXq0fevzme2pys62n3e0fbqa7peapykr8v']:
# IE and Edge can't handle long arguments so just use webbrowser.open and hope
# https://blogs.msdn.microsoft.com/ieinternals/2014/08/13/url-length-limits/
cls = None
else:
cls = value
except:
cls = 'https'
if cls and not RegOpenKeyEx(HKEY_CLASSES_ROOT, r'%s\shell\open\command' % cls, 0, KEY_READ, ctypes.byref(hkey)):
typ = DWORD()
size = DWORD()
if not RegQueryValueEx(hkey, None, 0, ctypes.byref(typ), None, ctypes.byref(size)) and typ.value in [REG_SZ, REG_MULTI_SZ]:
buf = ctypes.create_unicode_buffer('', int(size.value / 2))
if not RegQueryValueEx(hkey, None, 0, ctypes.byref(typ), buf, ctypes.byref(size)) and 'iexplore' not in buf.value.lower():
RegCloseKey(hkey)
if '%1' in buf.value:
if cls:
try:
hkey = OpenKeyEx(HKEY_CLASSES_ROOT, r'%s\shell\open\command' % cls)
(value, typ) = QueryValueEx(hkey, None)
CloseKey(hkey)
if 'iexplore' not in value.lower():
if '%1' in value:
subprocess.Popen(buf.value.replace('%1', url))
else:
subprocess.Popen('%s "%s"' % (buf.value, url))
return
RegCloseKey(hkey)
except:
pass
webbrowser.open(url)