mirror of
https://github.com/gogcom/galaxy-integrations-python-api.git
synced 2026-01-29 17:11:15 -05:00
100 lines
2.9 KiB
Python
100 lines
2.9 KiB
Python
import sys
|
|
|
|
|
|
if sys.platform == "win32":
|
|
import logging
|
|
import ctypes
|
|
from ctypes.wintypes import LONG, HKEY, LPCWSTR, DWORD, BOOL, HANDLE, LPVOID
|
|
|
|
LPSECURITY_ATTRIBUTES = LPVOID
|
|
|
|
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]
|
|
|
|
RegNotifyChangeKeyValue = ctypes.windll.advapi32.RegNotifyChangeKeyValue
|
|
RegNotifyChangeKeyValue.restype = LONG
|
|
RegNotifyChangeKeyValue.argtypes = [HKEY, BOOL, DWORD, HANDLE, BOOL]
|
|
|
|
CloseHandle = ctypes.windll.kernel32.CloseHandle
|
|
CloseHandle.restype = BOOL
|
|
CloseHandle.argtypes = [HANDLE]
|
|
|
|
CreateEvent = ctypes.windll.kernel32.CreateEventW
|
|
CreateEvent.restype = BOOL
|
|
CreateEvent.argtypes = [LPSECURITY_ATTRIBUTES, BOOL, BOOL, LPCWSTR]
|
|
|
|
WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
|
|
WaitForSingleObject.restype = DWORD
|
|
WaitForSingleObject.argtypes = [HANDLE, DWORD]
|
|
|
|
ERROR_SUCCESS = 0x00000000
|
|
|
|
KEY_READ = 0x00020019
|
|
KEY_QUERY_VALUE = 0x00000001
|
|
|
|
REG_NOTIFY_CHANGE_NAME = 0x00000001
|
|
REG_NOTIFY_CHANGE_LAST_SET = 0x00000004
|
|
|
|
WAIT_OBJECT_0 = 0x00000000
|
|
WAIT_TIMEOUT = 0x00000102
|
|
|
|
class RegistryMonitor:
|
|
|
|
def __init__(self, root, subkey):
|
|
self._root = root
|
|
self._subkey = subkey
|
|
self._event = CreateEvent(None, False, False, None)
|
|
|
|
self._key = None
|
|
self._open_key()
|
|
if self._key:
|
|
self._set_key_update_notification()
|
|
|
|
def close(self):
|
|
CloseHandle(self._event)
|
|
if self._key:
|
|
RegCloseKey(self._key)
|
|
self._key = None
|
|
|
|
def is_updated(self):
|
|
wait_result = WaitForSingleObject(self._event, 0)
|
|
|
|
# previously watched
|
|
if wait_result == WAIT_OBJECT_0:
|
|
self._set_key_update_notification()
|
|
return True
|
|
|
|
# no changes or no key before
|
|
if wait_result != WAIT_TIMEOUT:
|
|
# unexpected error
|
|
logging.warning("Unexpected WaitForSingleObject result %s", wait_result)
|
|
return False
|
|
|
|
if self._key is None:
|
|
self._open_key()
|
|
|
|
if self._key is not None:
|
|
self._set_key_update_notification()
|
|
|
|
return False
|
|
|
|
def _set_key_update_notification(self):
|
|
filter_ = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET
|
|
status = RegNotifyChangeKeyValue(self._key, True, filter_, self._event, True)
|
|
if status != ERROR_SUCCESS:
|
|
# key was deleted
|
|
RegCloseKey(self._key)
|
|
self._key = None
|
|
|
|
def _open_key(self):
|
|
access = KEY_QUERY_VALUE | KEY_READ
|
|
self._key = HKEY()
|
|
rc = RegOpenKeyEx(self._root, self._subkey, 0, access, ctypes.byref(self._key))
|
|
if rc != ERROR_SUCCESS:
|
|
self._key = None
|