From e74089cda3e6572acb2578e9ce23345cbbafb688 Mon Sep 17 00:00:00 2001 From: lucasg Date: Sun, 12 Apr 2020 18:29:31 +0200 Subject: [PATCH] [Device] Add cfgmgr.CM_Enumerate_Classes winproxy --- samples/device/device_manager.py | 18 ++++++++ windows/generated_def/windef.py | 64 +++++++++++++++++++++++++++++ windows/generated_def/winfuncs.py | 3 ++ windows/generated_def/winstructs.py | 1 + windows/winobject/device.py | 36 ++++++++++++++++ windows/winproxy/apis/__init__.py | 10 +++-- windows/winproxy/apis/cfgmgr32.py | 48 ++++++++++++++++++++++ windows/winproxy/apis/setupapi.py | 40 ++++++++++++++++++ 8 files changed, 216 insertions(+), 4 deletions(-) create mode 100644 samples/device/device_manager.py create mode 100644 windows/winobject/device.py create mode 100644 windows/winproxy/apis/cfgmgr32.py create mode 100644 windows/winproxy/apis/setupapi.py diff --git a/samples/device/device_manager.py b/samples/device/device_manager.py new file mode 100644 index 0000000..006623e --- /dev/null +++ b/samples/device/device_manager.py @@ -0,0 +1,18 @@ +import windows +from windows.winobject.device import DeviceManager + +def main(): + + for device_class in DeviceManager.enumerate_active_class(): + print("-Class : %s" % (device_class)) + + # for device in device_class.devices: + # print(" -Device : %s" % (device.name)) + + # for resource in device.resources: + # print(' -%s : [0x%08x - 0x%08x] (0x%04x)' % (resource.type, resource.start, resource.end, resource.flags)) + + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/windows/generated_def/windef.py b/windows/generated_def/windef.py index dce150b..342d0b9 100644 --- a/windows/generated_def/windef.py +++ b/windows/generated_def/windef.py @@ -2199,3 +2199,67 @@ SPC_MINIMAL_CRITERIA_OBJID = make_flag("SPC_MINIMAL_CRITERIA_OBJID", "1.3.6.1.4. SPC_FINANCIAL_CRITERIA_OBJID = make_flag("SPC_FINANCIAL_CRITERIA_OBJID", "1.3.6.1.4.1.311.2.1.27") SPC_LINK_OBJID = make_flag("SPC_LINK_OBJID", "1.3.6.1.4.1.311.2.1.28") SPC_SIGINFO_OBJID = make_flag("SPC_SIGINFO_OBJID", "1.3.6.1.4.1.311.2.1.30") +CR_SUCCESS = make_flag('CR_SUCCESS' , 0x00000000) +CR_DEFAULT = make_flag('CR_DEFAULT' , 0x00000001) +CR_OUT_OF_MEMORY = make_flag('CR_OUT_OF_MEMORY' , 0x00000002) +CR_INVALID_POINTER = make_flag('CR_INVALID_POINTER' , 0x00000003) +CR_INVALID_FLAG = make_flag('CR_INVALID_FLAG' , 0x00000004) +CR_INVALID_DEVNODE = make_flag('CR_INVALID_DEVNODE' , 0x00000005) +CR_INVALID_DEVINST = make_flag('CR_INVALID_DEVINST' , CR_INVALID_DEVNODE) +CR_INVALID_RES_DES = make_flag('CR_INVALID_RES_DES' , 0x00000006) +CR_INVALID_LOG_CONF = make_flag('CR_INVALID_LOG_CONF' , 0x00000007) +CR_INVALID_ARBITRATOR = make_flag('CR_INVALID_ARBITRATOR' , 0x00000008) +CR_INVALID_NODELIST = make_flag('CR_INVALID_NODELIST' , 0x00000009) +CR_DEVNODE_HAS_REQS = make_flag('CR_DEVNODE_HAS_REQS' , 0x0000000A) +CR_DEVINST_HAS_REQS = make_flag('CR_DEVINST_HAS_REQS' , CR_DEVNODE_HAS_REQS) +CR_INVALID_RESOURCEID = make_flag('CR_INVALID_RESOURCEID' , 0x0000000B) +CR_DLVXD_NOT_FOUND = make_flag('CR_DLVXD_NOT_FOUND' , 0x0000000C) +CR_NO_SUCH_DEVNODE = make_flag('CR_NO_SUCH_DEVNODE' , 0x0000000D) +CR_NO_SUCH_DEVINST = make_flag('CR_NO_SUCH_DEVINST' , CR_NO_SUCH_DEVNODE) +CR_NO_MORE_LOG_CONF = make_flag('CR_NO_MORE_LOG_CONF' , 0x0000000E) +CR_NO_MORE_RES_DES = make_flag('CR_NO_MORE_RES_DES' , 0x0000000F) +CR_ALREADY_SUCH_DEVNODE = make_flag('CR_ALREADY_SUCH_DEVNODE' , 0x00000010) +CR_ALREADY_SUCH_DEVINST = make_flag('CR_ALREADY_SUCH_DEVINST' , CR_ALREADY_SUCH_DEVNODE) +CR_INVALID_RANGE_LIST = make_flag('CR_INVALID_RANGE_LIST' , 0x00000011) +CR_INVALID_RANGE = make_flag('CR_INVALID_RANGE' , 0x00000012) +CR_FAILURE = make_flag('CR_FAILURE' , 0x00000013) +CR_NO_SUCH_LOGICAL_DEV = make_flag('CR_NO_SUCH_LOGICAL_DEV' , 0x00000014) +CR_CREATE_BLOCKED = make_flag('CR_CREATE_BLOCKED' , 0x00000015) +CR_NOT_SYSTEM_VM = make_flag('CR_NOT_SYSTEM_VM' , 0x00000016) +CR_REMOVE_VETOED = make_flag('CR_REMOVE_VETOED' , 0x00000017) +CR_APM_VETOED = make_flag('CR_APM_VETOED' , 0x00000018) +CR_INVALID_LOAD_TYPE = make_flag('CR_INVALID_LOAD_TYPE' , 0x00000019) +CR_BUFFER_SMALL = make_flag('CR_BUFFER_SMALL' , 0x0000001A) +CR_NO_ARBITRATOR = make_flag('CR_NO_ARBITRATOR' , 0x0000001B) +CR_NO_REGISTRY_HANDLE = make_flag('CR_NO_REGISTRY_HANDLE' , 0x0000001C) +CR_REGISTRY_ERROR = make_flag('CR_REGISTRY_ERROR' , 0x0000001D) +CR_INVALID_DEVICE_ID = make_flag('CR_INVALID_DEVICE_ID' , 0x0000001E) +CR_INVALID_DATA = make_flag('CR_INVALID_DATA' , 0x0000001F) +CR_INVALID_API = make_flag('CR_INVALID_API' , 0x00000020) +CR_DEVLOADER_NOT_READY = make_flag('CR_DEVLOADER_NOT_READY' , 0x00000021) +CR_NEED_RESTART = make_flag('CR_NEED_RESTART' , 0x00000022) +CR_NO_MORE_HW_PROFILES = make_flag('CR_NO_MORE_HW_PROFILES' , 0x00000023) +CR_DEVICE_NOT_THERE = make_flag('CR_DEVICE_NOT_THERE' , 0x00000024) +CR_NO_SUCH_VALUE = make_flag('CR_NO_SUCH_VALUE' , 0x00000025) +CR_WRONG_TYPE = make_flag('CR_WRONG_TYPE' , 0x00000026) +CR_INVALID_PRIORITY = make_flag('CR_INVALID_PRIORITY' , 0x00000027) +CR_NOT_DISABLEABLE = make_flag('CR_NOT_DISABLEABLE' , 0x00000028) +CR_FREE_RESOURCES = make_flag('CR_FREE_RESOURCES' , 0x00000029) +CR_QUERY_VETOED = make_flag('CR_QUERY_VETOED' , 0x0000002A) +CR_CANT_SHARE_IRQ = make_flag('CR_CANT_SHARE_IRQ' , 0x0000002B) +CR_NO_DEPENDENT = make_flag('CR_NO_DEPENDENT' , 0x0000002C) +CR_SAME_RESOURCES = make_flag('CR_SAME_RESOURCES' , 0x0000002D) +CR_NO_SUCH_REGISTRY_KEY = make_flag('CR_NO_SUCH_REGISTRY_KEY' , 0x0000002E) +CR_INVALID_MACHINENAME = make_flag('CR_INVALID_MACHINENAME' , 0x0000002F) +CR_REMOTE_COMM_FAILURE = make_flag('CR_REMOTE_COMM_FAILURE' , 0x00000030) +CR_MACHINE_UNAVAILABLE = make_flag('CR_MACHINE_UNAVAILABLE' , 0x00000031) +CR_NO_CM_SERVICES = make_flag('CR_NO_CM_SERVICES' , 0x00000032) +CR_ACCESS_DENIED = make_flag('CR_ACCESS_DENIED' , 0x00000033) +CR_CALL_NOT_IMPLEMENTED = make_flag('CR_CALL_NOT_IMPLEMENTED' , 0x00000034) +CR_INVALID_PROPERTY = make_flag('CR_INVALID_PROPERTY' , 0x00000035) +CR_DEVICE_INTERFACE_ACTI = make_flag('CR_DEVICE_INTERFACE_ACTIVE', 0x00000036) +CR_NO_SUCH_DEVICE_INTERF = make_flag('CR_NO_SUCH_DEVICE_INTERFACE', 0x00000037) +CR_INVALID_REFERENCE_STR = make_flag('CR_INVALID_REFERENCE_STRING', 0x00000038) +CR_INVALID_CONFLICT_LIST = make_flag('CR_INVALID_CONFLICT_LIST' , 0x00000039) +CR_INVALID_INDEX = make_flag('CR_INVALID_INDEX' , 0x0000003A) +CR_INVALID_STRUCTURE_SIZ = make_flag('CR_INVALID_STRUCTURE_SIZE', 0x0000003B) \ No newline at end of file diff --git a/windows/generated_def/winfuncs.py b/windows/generated_def/winfuncs.py index dd00a2d..ef4c18b 100644 --- a/windows/generated_def/winfuncs.py +++ b/windows/generated_def/winfuncs.py @@ -3155,3 +3155,6 @@ FindNextFileWParams = ((1, 'hFindFile'), (1, 'lpFindFileData')) FindClosePrototype = WINFUNCTYPE(BOOL, HANDLE) FindCloseParams = ((1, 'hFindFile'),) +CM_Enumerate_ClassesPrototype = WINFUNCTYPE(CR_STATUS, DWORD, POINTER(GUID), DWORD) +CM_Enumerate_ClassesParams = ((1, 'ClassIndex'), (1, 'pGUID'), (1,'Params'),) + diff --git a/windows/generated_def/winstructs.py b/windows/generated_def/winstructs.py index d59a7f8..fbe1556 100644 --- a/windows/generated_def/winstructs.py +++ b/windows/generated_def/winstructs.py @@ -165,6 +165,7 @@ SIZE_T = c_size_t PSIZE_T = POINTER(SIZE_T) PVOID = c_void_p NTSTATUS = DWORD +CR_STATUS = DWORD TDHSTATUS = ULONG DNS_STATUS = ULONG LSTATUS = LONG#Registryfunctionsreturnvalue|typedef_Return_type_success_(return==ERROR_SUCCESS)LONGLSTATUS; diff --git a/windows/winobject/device.py b/windows/winobject/device.py new file mode 100644 index 0000000..131bf38 --- /dev/null +++ b/windows/winobject/device.py @@ -0,0 +1,36 @@ +import windows +from windows import winproxy +from windows.generated_def import windef +import windows.generated_def as gdef + + +class DeviceManager(object): + + @staticmethod + def enumerate_active_class(): + return list(DeviceManager.enumerate_class()) + # return list(filter(lambda dc: len(dc.devices) > 0, DeviceManager.enumerate_class())) + + @staticmethod + def enumerate_class(): + + def _gen_all_class_guid(): + """ + Return every registered device classes in the system, generator-style + """ + + class_index = 0 + + while True: + class_guid = winproxy.CM_Enumerate_Classes(class_index, 0) + class_index+=1 + + if not class_guid: + return # stop iterating + + #yield DeviceClass(class_guid) + yield class_guid + + + + return (dc for dc in _gen_all_class_guid()) \ No newline at end of file diff --git a/windows/winproxy/apis/__init__.py b/windows/winproxy/apis/__init__.py index 3d8c348..dfbad8c 100644 --- a/windows/winproxy/apis/__init__.py +++ b/windows/winproxy/apis/__init__.py @@ -1,7 +1,9 @@ from .advapi32 import * +from .cfgmgr32 import * from .crypt32 import * from .cryptui import * from .dbghelp import * +from .dnsapi import * from .iphlpapi import * from .kernel32 import * from .ktmw32 import * @@ -9,12 +11,12 @@ from .ntdll import * from .ole32 import * from .oleacc import * from .psapi import * +from .setupapi import * from .shell32 import * from .shlwapi import * +from .tdh import * from .user32 import * from .version import * +from .virtdisk import * from .wevtapi import * -from .wintrust import * -from .tdh import * -from .dnsapi import * -from .virtdisk import * \ No newline at end of file +from .wintrust import * \ No newline at end of file diff --git a/windows/winproxy/apis/cfgmgr32.py b/windows/winproxy/apis/cfgmgr32.py new file mode 100644 index 0000000..42efb35 --- /dev/null +++ b/windows/winproxy/apis/cfgmgr32.py @@ -0,0 +1,48 @@ +import ctypes +import windows.generated_def as gdef + +from ..apiproxy import ApiProxy, NeededParameter, is_implemented +from ..error import succeed_on_zero, no_error_check + +class CfgMgr32Proxy(ApiProxy): + APIDLL = "CfgMgr32" + default_error_check = staticmethod(succeed_on_zero) + + +# We suppress error checks since CM_Enumerate_Classes return either : +# - CR_SUCCESS on success +# - usually CR_NO_SUCH_VALUE on an invalid class index +@CfgMgr32Proxy(error_check=no_error_check) +def CM_Enumerate_Classes(ClassIndex, Params): + """ + Given a class index, either return the class GUID or None. + """ + + guid = gdef.GUID() + cr_status = CM_Enumerate_Classes.ctypes_function(ClassIndex, ctypes.byref(guid), Params) + + if cr_status != gdef.CR_SUCCESS: + return None + + return guid + + +# @CfgMgr32Proxy() +# def CM_Get_First_Log_Conf(hDevInst): +# return CM_Get_First_Log_Conf.ctypes_function(hDevInst) + +# @CfgMgr32Proxy() +# def CM_Get_Next_Res_Des(hRes, ResourceType): +# return CM_Get_Next_Res_Des.ctypes_function(hRes, ResourceType) + +# @CfgMgr32Proxy() +# def CM_Get_Res_Des_Data_Size(hRes): +# return CM_Get_Res_Des_Data_Size.ctypes_function(hRes) + +# @CfgMgr32Proxy() +# def CM_Get_Res_Des_Data(hRes, ResourceSize): +# return CM_Get_Res_Des_Data.ctypes_function(hRes, ResourceSize) + +# @CfgMgr32Proxy() +# def CM_Free_Res_Des_Handle(hRes): +# return CM_Free_Res_Des_Handle.ctypes_function(hRes) diff --git a/windows/winproxy/apis/setupapi.py b/windows/winproxy/apis/setupapi.py new file mode 100644 index 0000000..93745b3 --- /dev/null +++ b/windows/winproxy/apis/setupapi.py @@ -0,0 +1,40 @@ +import ctypes +import windows.generated_def as gdef + +from ..apiproxy import ApiProxy, NeededParameter, is_implemented +from ..error import succeed_on_zero + +class SetupApiProxy(ApiProxy): + APIDLL = "SetupApi" + default_error_check = staticmethod(succeed_on_zero) + + +# @SetupApiProxy() +# def SetupDiClassNameFromGuidA(Guid): +# return SetupDiClassNameFromGuidA.ctypes_function() + +# @SetupApiProxy() +# def SetupDiClassNameFromGuidW(Guid): +# return SetupDiClassNameFromGuidW.ctypes_function() + +# @SetupApiProxy() +# def SetupDiGetClassDevsA(Guid): +# return SetupDiGetClassDevsA.ctypes_function() + +# @SetupApiProxy() +# def SetupDiEnumDeviceInfo(hDevInfo, NumDevice): +# return SetupDiEnumDeviceInfo.ctypes_function() + +# @SetupApiProxy() +# def SetupDiGetDeviceRegistryPropertyA(hDevInfo, DevData, Property, PropertyType): +# return SetupDiGetDeviceRegistryPropertyA.ctypes_function() + + +# @SetupApiProxy() +# def SetupDiGetDeviceRegistryPropertyW(hDevInfo, DevData, Property, PropertyType): +# return SetupDiGetDeviceRegistryPropertyW.ctypes_function() + + +# @SetupApiProxy() +# def SetupDiDestroyDeviceInfoList(hDevInfo): +# return SetupDiDestroyDeviceInfoList.ctypes_function(hDevInfo) \ No newline at end of file