mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-12 23:37:14 +03:00
Switch to built-in winreg module on Windows
This commit is contained in:
parent
9f456b8261
commit
823f8caf0a
116
config.py
116
config.py
@ -21,6 +21,7 @@ elif platform=='win32':
|
|||||||
import ctypes
|
import ctypes
|
||||||
from ctypes.wintypes import *
|
from ctypes.wintypes import *
|
||||||
import uuid
|
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_Documents = uuid.UUID('{FDD39AD0-238F-46AF-ADB4-6C85480369C7}')
|
||||||
FOLDERID_LocalAppData = uuid.UUID('{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}')
|
FOLDERID_LocalAppData = uuid.UUID('{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}')
|
||||||
@ -33,47 +34,6 @@ elif platform=='win32':
|
|||||||
CoTaskMemFree = ctypes.windll.ole32.CoTaskMemFree
|
CoTaskMemFree = ctypes.windll.ole32.CoTaskMemFree
|
||||||
CoTaskMemFree.argtypes = [ctypes.c_void_p]
|
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):
|
def KnownFolderPath(guid):
|
||||||
buf = ctypes.c_wchar_p()
|
buf = ctypes.c_wchar_p()
|
||||||
if SHGetKnownFolderPath(ctypes.create_string_buffer(guid.bytes_le), 0, 0, ctypes.byref(buf)):
|
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.identifier = applongname
|
||||||
|
|
||||||
self.hkey = HKEY()
|
self.hkey = CreateKeyEx(HKEY_CURRENT_USER, r'Software\Marginal\EDMarketConnector', access=KEY_ALL_ACCESS)
|
||||||
disposition = DWORD()
|
try:
|
||||||
if RegCreateKeyEx(HKEY_CURRENT_USER, r'Software\Marginal\EDMarketConnector', 0, None, 0, KEY_ALL_ACCESS, None, ctypes.byref(self.hkey), ctypes.byref(disposition)):
|
sparklekey = OpenKeyEx(hkey, 'WinSparkle')
|
||||||
raise Exception()
|
except:
|
||||||
|
|
||||||
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')
|
|
||||||
|
|
||||||
# set WinSparkle defaults - https://github.com/vslavik/winsparkle/wiki/Registry-Settings
|
# set WinSparkle defaults - https://github.com/vslavik/winsparkle/wiki/Registry-Settings
|
||||||
sparklekey = HKEY()
|
sparklekey = CreateKeyEx(self.hkey, 'WinSparkle', access=KEY_ALL_ACCESS)
|
||||||
if not RegCreateKeyEx(self.hkey, 'WinSparkle', 0, None, 0, KEY_ALL_ACCESS, None, ctypes.byref(sparklekey), ctypes.byref(disposition)):
|
SetValueEx(sparklekey, 'CheckForUpdates', 0, REG_SZ, '1')
|
||||||
if disposition.value == REG_CREATED_NEW_KEY:
|
SetValueEx(sparklekey, 'UpdateInterval', 0, REG_SZ, str(update_interval))
|
||||||
buf = ctypes.create_unicode_buffer('1')
|
CloseKey(sparklekey)
|
||||||
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')):
|
if not self.get('outdir') or not isdir(self.get('outdir')):
|
||||||
self.set('outdir', KnownFolderPath(FOLDERID_Documents) or self.home)
|
self.set('outdir', KnownFolderPath(FOLDERID_Documents) or self.home)
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
typ = DWORD()
|
try:
|
||||||
size = DWORD()
|
(value, typ) = QueryValueEx(self.hkey, key)
|
||||||
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), None, ctypes.byref(size)) or typ.value not in [REG_SZ, REG_MULTI_SZ]:
|
except:
|
||||||
return None
|
return None
|
||||||
buf = ctypes.create_unicode_buffer(int(size.value / 2))
|
if typ not in [REG_SZ, REG_MULTI_SZ]:
|
||||||
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), buf, ctypes.byref(size)):
|
|
||||||
return None
|
return None
|
||||||
elif typ.value == REG_MULTI_SZ:
|
return value
|
||||||
return [x for x in ctypes.wstring_at(buf, len(buf)-2).split(u'\x00')]
|
|
||||||
else:
|
|
||||||
return str(buf.value)
|
|
||||||
|
|
||||||
def getint(self, key):
|
def getint(self, key):
|
||||||
typ = DWORD()
|
try:
|
||||||
size = DWORD(4)
|
(value, typ) = QueryValueEx(self.hkey, key)
|
||||||
val = DWORD()
|
except:
|
||||||
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), ctypes.byref(val), ctypes.byref(size)) or typ.value != REG_DWORD:
|
return None
|
||||||
return 0
|
if typ != REG_DWORD:
|
||||||
else:
|
return None
|
||||||
return val.value
|
return value
|
||||||
|
|
||||||
def set(self, key, val):
|
def set(self, key, val):
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
buf = ctypes.create_unicode_buffer(val)
|
SetValueEx(self.hkey, key, 0, REG_SZ, val)
|
||||||
RegSetValueEx(self.hkey, key, 0, REG_SZ, buf, len(buf)*2)
|
|
||||||
elif isinstance(val, numbers.Integral):
|
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
|
elif hasattr(val, '__iter__'): # iterable
|
||||||
stringval = u'\x00'.join([str(x) or u' ' for x in val] + [u'']) # null terminated non-empty strings
|
SetValueEx(self.hkey, key, 0, REG_MULTI_SZ, val)
|
||||||
buf = ctypes.create_unicode_buffer(stringval)
|
|
||||||
RegSetValueEx(self.hkey, key, 0, REG_MULTI_SZ, buf, len(buf)*2)
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def delete(self, key):
|
def delete(self, key):
|
||||||
RegDeleteValue(self.hkey, key)
|
try:
|
||||||
|
DeleteValue(self.hkey, key)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
pass # Redundant since registry keys are written immediately
|
pass # Redundant since registry keys are written immediately
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
RegCloseKey(self.hkey)
|
CloseKey(self.hkey)
|
||||||
self.hkey = None
|
self.hkey = None
|
||||||
|
|
||||||
elif platform=='linux':
|
elif platform=='linux':
|
||||||
|
@ -9,29 +9,7 @@ if platform == 'win32':
|
|||||||
import subprocess
|
import subprocess
|
||||||
import ctypes
|
import ctypes
|
||||||
from ctypes.wintypes import *
|
from ctypes.wintypes import *
|
||||||
|
from winreg import CloseKey, OpenKeyEx, QueryValueEx, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, KEY_READ, REG_SZ, REG_MULTI_SZ
|
||||||
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)]
|
|
||||||
|
|
||||||
|
|
||||||
# A clickable ttk Label
|
# A clickable ttk Label
|
||||||
#
|
#
|
||||||
@ -138,34 +116,31 @@ def openurl(url):
|
|||||||
# so discover and launch the browser directly.
|
# so discover and launch the browser directly.
|
||||||
# https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553
|
# https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553
|
||||||
|
|
||||||
hkey = HKEY()
|
try:
|
||||||
cls = 'http'
|
hkey = OpenKeyEx(HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice')
|
||||||
if not RegOpenKeyEx(HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice', 0, KEY_READ, ctypes.byref(hkey)):
|
(value, typ) = QueryValueEx(hkey, 'ProgId')
|
||||||
typ = DWORD()
|
CloseKey(hkey)
|
||||||
size = DWORD()
|
if value in ['IE.HTTP', 'AppXq0fevzme2pys62n3e0fbqa7peapykr8v']:
|
||||||
if not RegQueryValueEx(hkey, 'ProgId', 0, ctypes.byref(typ), None, ctypes.byref(size)) and typ.value in [REG_SZ, REG_MULTI_SZ]:
|
# IE and Edge can't handle long arguments so just use webbrowser.open and hope
|
||||||
buf = ctypes.create_unicode_buffer('', int(size.value / 2))
|
# https://blogs.msdn.microsoft.com/ieinternals/2014/08/13/url-length-limits/
|
||||||
if not RegQueryValueEx(hkey, 'ProgId', 0, ctypes.byref(typ), buf, ctypes.byref(size)):
|
cls = None
|
||||||
if buf.value in ['IE.HTTP', 'AppXq0fevzme2pys62n3e0fbqa7peapykr8v']:
|
else:
|
||||||
# IE and Edge can't handle long arguments so just use webbrowser.open and hope
|
cls = value
|
||||||
# https://blogs.msdn.microsoft.com/ieinternals/2014/08/13/url-length-limits/
|
except:
|
||||||
cls = None
|
cls = 'https'
|
||||||
else:
|
|
||||||
cls = buf.value
|
|
||||||
RegCloseKey(hkey)
|
|
||||||
|
|
||||||
if cls and not RegOpenKeyEx(HKEY_CLASSES_ROOT, r'%s\shell\open\command' % cls, 0, KEY_READ, ctypes.byref(hkey)):
|
if cls:
|
||||||
typ = DWORD()
|
try:
|
||||||
size = DWORD()
|
hkey = OpenKeyEx(HKEY_CLASSES_ROOT, r'%s\shell\open\command' % cls)
|
||||||
if not RegQueryValueEx(hkey, None, 0, ctypes.byref(typ), None, ctypes.byref(size)) and typ.value in [REG_SZ, REG_MULTI_SZ]:
|
(value, typ) = QueryValueEx(hkey, None)
|
||||||
buf = ctypes.create_unicode_buffer('', int(size.value / 2))
|
CloseKey(hkey)
|
||||||
if not RegQueryValueEx(hkey, None, 0, ctypes.byref(typ), buf, ctypes.byref(size)) and 'iexplore' not in buf.value.lower():
|
if 'iexplore' not in value.lower():
|
||||||
RegCloseKey(hkey)
|
if '%1' in value:
|
||||||
if '%1' in buf.value:
|
|
||||||
subprocess.Popen(buf.value.replace('%1', url))
|
subprocess.Popen(buf.value.replace('%1', url))
|
||||||
else:
|
else:
|
||||||
subprocess.Popen('%s "%s"' % (buf.value, url))
|
subprocess.Popen('%s "%s"' % (buf.value, url))
|
||||||
return
|
return
|
||||||
RegCloseKey(hkey)
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
webbrowser.open(url)
|
webbrowser.open(url)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user