From 845b896803e2b0f5cdd27ed3223736d2a37d1d52 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 16 Jan 2016 21:13:12 +0530 Subject: [PATCH] Code to iterate over descendants of a device --- src/calibre/devices/winusb.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/calibre/devices/winusb.py b/src/calibre/devices/winusb.py index 9ea3c406e6..10402ab8f5 100644 --- a/src/calibre/devices/winusb.py +++ b/src/calibre/devices/winusb.py @@ -253,7 +253,7 @@ def bool_err_check(result, func, args): def config_err_check(result, func, args): if result != CR_CODES['CR_SUCCESS']: - raise WindowsError((result, 'The cfgmgr32 function failed with err: %s' % CR_CODE_NAMES.get(result, result))) + raise WindowsError(result, 'The cfgmgr32 function failed with err: %s' % CR_CODE_NAMES.get(result, result)) return args GetLogicalDrives = cwrap('GetLogicalDrives', DWORD, errcheck=bool_err_check, lib=kernel32) @@ -275,9 +275,12 @@ SetupDiGetDeviceRegistryProperty = cwrap( 'SetupDiGetDeviceRegistryPropertyW', BOOL, HDEVINFO, PSP_DEVINFO_DATA, DWORD, POINTER(DWORD), POINTER(BYTE), DWORD, POINTER(DWORD)) CM_Get_Parent = cwrap('CM_Get_Parent', CONFIGRET, POINTER(DEVINST), DEVINST, ULONG, errcheck=config_err_check) +CM_Get_Child = cwrap('CM_Get_Child', CONFIGRET, POINTER(DEVINST), DEVINST, ULONG, errcheck=config_err_check) +CM_Get_Sibling = cwrap('CM_Get_Sibling', CONFIGRET, POINTER(DEVINST), DEVINST, ULONG, errcheck=config_err_check) CM_Get_Device_ID_Size = cwrap('CM_Get_Device_ID_Size', CONFIGRET, POINTER(ULONG), DEVINST, ULONG) CM_Get_Device_ID = cwrap('CM_Get_Device_IDW', CONFIGRET, DEVINST, LPWSTR, ULONG, ULONG) CM_Request_Device_Eject = cwrap('CM_Request_Device_EjectW', CONFIGRET, DEVINST, c_void_p, LPWSTR, ULONG, ULONG, errcheck=config_err_check) + # }}} # Utility functions {{{ @@ -287,6 +290,32 @@ def get_device_set(guid=byref(GUID_DEVINTERFACE_VOLUME), enumerator=None, flags= yield dev_list SetupDiDestroyDeviceInfoList(dev_list) + +def iterchildren(parent_devinst): + child = DEVINST(0) + NO_MORE = CR_CODES['CR_NO_SUCH_DEVINST'] + try: + CM_Get_Child(byref(child), parent_devinst, 0) + except WindowsError as err: + if err.winerror == NO_MORE: + return + raise + yield child + while True: + try: + CM_Get_Sibling(byref(child), child, 0) + except WindowsError as err: + if err.winerror == NO_MORE: + break + raise + yield child + +def iterdescendants(parent_devinst): + for child in iterchildren(parent_devinst): + yield child + for gc in iterdescendants(child): + yield gc + def get_all_removable_drives(): mask = GetLogicalDrives() ans = {}