Adapt lucasg winproxy code to match codebase behavvior

This commit is contained in:
hakril
2020-04-21 21:05:13 +02:00
parent 5aed4305d6
commit f491c510eb
7 changed files with 5775 additions and 5109 deletions
+5
View File
@@ -24,6 +24,9 @@ if bitness() == 32:
winstructs.PORT_MESSAGE = winstructs.PORT_MESSAGE32
winstructs.PPORT_MESSAGE = winstructs.PPORT_MESSAGE32
# CFGMGR32
winstructs.IRQ_RESOURCE = winstructs.IRQ_RESOURCE_32
else:
winstructs.CONTEXT = winstructs.CONTEXT64
winstructs.PCONTEXT = winstructs.PCONTEXT64
@@ -41,6 +44,8 @@ else:
winstructs.PORT_MESSAGE = winstructs.PORT_MESSAGE64
winstructs.PPORT_MESSAGE = winstructs.PPORT_MESSAGE64
# CFGMGR32
winstructs.IRQ_RESOURCE = winstructs.IRQ_RESOURCE_64
from . import winfuncs
from . import windef
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+106 -84
View File
@@ -3,114 +3,136 @@ from ctypes import wintypes
import windows.generated_def as gdef
from ..apiproxy import ApiProxy, NeededParameter, is_implemented
from ..error import succeed_on_zero, no_error_check
from ..error import WinproxyError, result_is_error_code
CFGMGR32_ERRORS = gdef.FlagMapper(
gdef.CR_SUCCESS,
gdef.CR_DEFAULT,
gdef.CR_OUT_OF_MEMORY,
gdef.CR_INVALID_POINTER,
gdef.CR_INVALID_FLAG,
gdef.CR_INVALID_DEVNODE,
gdef.CR_INVALID_DEVINST,
gdef.CR_INVALID_RES_DES,
gdef.CR_INVALID_LOG_CONF,
gdef.CR_INVALID_ARBITRATOR,
gdef.CR_INVALID_NODELIST,
gdef.CR_DEVNODE_HAS_REQS,
gdef.CR_DEVINST_HAS_REQS,
gdef.CR_INVALID_RESOURCEID,
gdef.CR_DLVXD_NOT_FOUND,
gdef.CR_NO_SUCH_DEVNODE,
gdef.CR_NO_SUCH_DEVINST,
gdef.CR_NO_MORE_LOG_CONF,
gdef.CR_NO_MORE_RES_DES,
gdef.CR_ALREADY_SUCH_DEVNODE,
gdef.CR_ALREADY_SUCH_DEVINST,
gdef.CR_INVALID_RANGE_LIST,
gdef.CR_INVALID_RANGE,
gdef.CR_FAILURE,
gdef.CR_NO_SUCH_LOGICAL_DEV,
gdef.CR_CREATE_BLOCKED,
gdef.CR_NOT_SYSTEM_VM,
gdef.CR_REMOVE_VETOED,
gdef.CR_APM_VETOED,
gdef.CR_INVALID_LOAD_TYPE,
gdef.CR_BUFFER_SMALL,
gdef.CR_NO_ARBITRATOR,
gdef.CR_NO_REGISTRY_HANDLE,
gdef.CR_REGISTRY_ERROR,
gdef.CR_INVALID_DEVICE_ID,
gdef.CR_INVALID_DATA,
gdef.CR_INVALID_API,
gdef.CR_DEVLOADER_NOT_READY,
gdef.CR_NEED_RESTART,
gdef.CR_NO_MORE_HW_PROFILES,
gdef.CR_DEVICE_NOT_THERE,
gdef.CR_NO_SUCH_VALUE,
gdef.CR_WRONG_TYPE,
gdef.CR_INVALID_PRIORITY,
gdef.CR_NOT_DISABLEABLE,
gdef.CR_FREE_RESOURCES,
gdef.CR_QUERY_VETOED,
gdef.CR_CANT_SHARE_IRQ,
gdef.CR_NO_DEPENDENT,
gdef.CR_SAME_RESOURCES,
gdef.CR_NO_SUCH_REGISTRY_KEY,
gdef.CR_INVALID_MACHINENAME,
gdef.CR_REMOTE_COMM_FAILURE,
gdef.CR_MACHINE_UNAVAILABLE,
gdef.CR_NO_CM_SERVICES,
gdef.CR_ACCESS_DENIED,
gdef.CR_CALL_NOT_IMPLEMENTED,
gdef.CR_INVALID_PROPERTY,
gdef.CR_DEVICE_INTERFACE_ACTIVE,
gdef.CR_NO_SUCH_DEVICE_INTERFACE,
gdef.CR_INVALID_REFERENCE_STRING,
gdef.CR_INVALID_CONFLICT_LIST,
gdef.CR_INVALID_INDEX,
gdef.CR_INVALID_STRUCTURE_SIZE
)
class CfgMgr32Error(WinproxyError):
def __new__(cls, func_name, error_code):
error_flag = CFGMGR32_ERRORS[error_code]
api_error = super(WinproxyError, cls).__new__(cls)
api_error.api_name = func_name
api_error.winerror = error_flag
api_error.strerror = error_flag.name
api_error.args = (func_name, api_error.winerror, api_error.strerror)
return api_error
def tst_error(func_name, result, func, args):
if result:
raise CfgMgr32Error(func_name, result)
return args
class CfgMgr32Proxy(ApiProxy):
APIDLL = "CfgMgr32"
# We can make a custom error_check taht translate error code to CR_ flags if needed
default_error_check = staticmethod(tst_error)
# We suppress error checks since CM_** APIs return either :
# - CR_SUCCESS on success
# - or a custom status, e.g. CR_NO_SUCH_VALUE on an invalid class index
# if necessary, we can convert them to Win32 error usign CM_MapCrToWin32Err
default_error_check = staticmethod(no_error_check)
@CfgMgr32Proxy()
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
def CM_Enumerate_Classes(ulClassIndex, ClassGuid, ulFlags):
return CM_Enumerate_Classes.ctypes_function(ulClassIndex, ClassGuid, ulFlags)
@CfgMgr32Proxy()
def CM_Get_First_Log_Conf(hDevInst, Flags):
def CM_Get_First_Log_Conf(plcLogConf, dnDevInst, ulFlags):
return CM_Get_First_Log_Conf.ctypes_function(plcLogConf, dnDevInst, ulFlags)
# TODO : test if process is running as wow64 on a windows >8 and raise an exception if true
@CfgMgr32Proxy()
def CM_Get_First_Log_Conf_Ex(plcLogConf, dnDevInst, ulFlags, hMachine):
return CM_Get_First_Log_Conf_Ex.ctypes_function(plcLogConf, dnDevInst, ulFlags, hMachine)
@CfgMgr32Proxy()
def CM_Get_Next_Log_Conf(plcLogConf, lcLogConf, ulFlags=0):
return CM_Get_Next_Log_Conf.ctypes_function(plcLogConf, lcLogConf, ulFlags)
conf = wintypes.HANDLE(0)
@CfgMgr32Proxy()
def CM_Get_Next_Log_Conf_Ex(plcLogConf, lcLogConf, ulFlags, hMachine):
return CM_Get_Next_Log_Conf_Ex.ctypes_function(plcLogConf, lcLogConf, ulFlags, hMachine)
cr_status = CM_Get_First_Log_Conf.ctypes_function(
ctypes.byref(conf),
hDevInst,
Flags
)
if cr_status != gdef.CR_SUCCESS:
return None
return conf
@CfgMgr32Proxy()
def CM_Free_Res_Des_Handle(hRes):
return CM_Free_Res_Des_Handle.ctypes_function(hRes)
@CfgMgr32Proxy()
def CM_Get_Next_Res_Des(hRes, ResourceType):
def CM_Get_Next_Res_Des(prdResDes, rdResDes, ForResource, pResourceID, ulFlags=0):
return CM_Get_Next_Res_Des.ctypes_function(prdResDes, rdResDes, ForResource, pResourceID, ulFlags)
# TODO : test if process is running as wow64 on a windows >8 and raise an exception if true
updated_hRes = wintypes.HANDLE(0)
# TODO : support ResType_All query (design change since we need to return the resource type queried)
if not ResourceType:
raise ValueError("ResType_All not supported")
if ResourceType > 7:
raise ValueError("ResourceType %x > ResType_MAX" % ResourceType)
status = CM_Get_Next_Res_Des.ctypes_function(
ctypes.byref(updated_hRes),
hRes,
ResourceType,
None,
0 # flags parameter is not used, and must always be 0
)
# clean up previous hRes
CM_Free_Res_Des_Handle(hRes)
if status != gdef.CR_SUCCESS:
return None
return updated_hRes
@CfgMgr32Proxy()
def CM_Get_Res_Des_Data_Size(hRes):
def CM_Get_Res_Des_Data_Size(pulSize, rdResDes, ulFlags=0):
return CM_Get_Res_Des_Data_Size.ctypes_function(pulSize, rdResDes, ulFlags)
resource_size = wintypes.ULONG(0)
status = CM_Get_Res_Des_Data_Size.ctypes_function(
ctypes.byref(resource_size),
hRes,
0 # flags parameter is not used, and must always be 0
)
if status != gdef.CR_SUCCESS:
return None
return resource_size.value
@CfgMgr32Proxy()
def CM_Get_Res_Des_Data(hRes, ResourceSize):
def CM_Get_Res_Des_Data(rdResDes, Buffer, BufferLen, ulFlags=0):
return CM_Get_Res_Des_Data.ctypes_function(rdResDes, Buffer, BufferLen, ulFlags)
resource_buffer = ctypes.create_string_buffer(ResourceSize)
result = CM_Get_Res_Des_Data.ctypes_function(
hRes,
ctypes.byref(resource_buffer),
ResourceSize,
0 # flags parameter is not used, and must always be 0
)
if result != gdef.CR_SUCCESS:
return None
# truncate and return data
return bytes(resource_buffer)[0:ResourceSize]
+25 -95
View File
@@ -16,130 +16,60 @@ class SetupApiProxy(ApiProxy):
@SetupApiProxy()
def SetupDiClassNameFromGuidA(Guid):
"""
def SetupDiClassNameFromGuidA(ClassGuid, ClassName, ClassNameSize=None, RequiredSize=None):
"""
Given a class Guid, return the name associated or raise an Exception
"""
if ClassNameSize is None:
ClassNameSize = ctypes.sizeof(ClassName)
return SetupDiClassNameFromGuidA.ctypes_function(ClassGuid, ClassName, ClassNameSize, RequiredSize)
class_name = ctypes.create_string_buffer(MAX_CLASS_NAME_LEN)
success = SetupDiClassNameFromGuidA.ctypes_function(
ctypes.byref(Guid),
ctypes.cast(ctypes.byref(class_name), wintypes.LPCSTR),
MAX_CLASS_NAME_LEN,
None
)
raw_class_name = bytes(class_name)
return raw_class_name.decode("utf-8").rstrip("\x00")
@SetupApiProxy()
def SetupDiClassNameFromGuidW(Guid):
"""
"""
Given a class Guid, return the name associated or raise an Exception
"""
if ClassNameSize is None:
ClassNameSize = ctypes.sizeof(ClassName)
return SetupDiClassNameFromGuidW.ctypes_function(ClassGuid, ClassName, ClassNameSize, RequiredSize)
class_name = ctypes.create_unicode_buffer(MAX_CLASS_NAME_LEN)
success = SetupDiClassNameFromGuidW.ctypes_function(
ctypes.byref(Guid),
ctypes.cast(ctypes.byref(class_name), wintypes.LPCWSTR),
MAX_CLASS_NAME_LEN,
None
)
raw_class_name = bytes(class_name)
return raw_class_name.decode("utf-16-le").rstrip("\x00")
@SetupApiProxy(error_check=result_is_handle)
def SetupDiGetClassDevsA(Guid, Enumerator = None, hwndParent = None, Flags=0):
"""
def SetupDiGetClassDevsA(Guid, Enumerator=None, hwndParent=None, Flags=0):
"""
Given a class GUID, return a HANDLE to the device's information set or raise an Exception
"""
return SetupDiGetClassDevsA.ctypes_function(
ctypes.byref(Guid),
Enumerator,
hwndParent,
Flags
)
return SetupDiGetClassDevsA.ctypes_function(Guid, Enumerator, hwndParent, Flags)
@SetupApiProxy(error_check=result_is_handle)
def SetupDiGetClassDevsW(Guid, Enumerator = None, hwndParent = None, Flags=0):
"""
def SetupDiGetClassDevsW(Guid, Enumerator=None, hwndParent=None, Flags=0):
"""
Given a class GUID, return a HANDLE to the device's information set or raise an Exception
"""
return SetupDiGetClassDevsW.ctypes_function(
ctypes.byref(Guid),
Enumerator,
hwndParent,
Flags
)
return SetupDiGetClassDevsW.ctypes_function(Guid, Enumerator, hwndParent, Flags)
@SetupApiProxy()
def SetupDiEnumDeviceInfo(hDevInfo, MemberIndex):
def SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, DeviceInfoData):
"""
Given a device information set, return the info associated with the index
or raise ERROR_NO_MORE_ITEMS if there is none anymore.
"""
data = gdef.winstructs.SP_DEVINFO_DATA()
data.cbSize = ctypes.sizeof(gdef.winstructs.SP_DEVINFO_DATA)
success = SetupDiEnumDeviceInfo.ctypes_function(
hDevInfo,
MemberIndex,
ctypes.byref(data)
)
return data
return SetupDiEnumDeviceInfo.ctypes_function(DeviceInfoSet, MemberIndex, DeviceInfoData)
@SetupApiProxy()
def SetupDiGetDeviceRegistryPropertyA(hDevInfo, DevData, Property, PropertyType, PropertySize = MAX_DEV_LEN*ctypes.sizeof(wintypes.CHAR)):
property_buffer = ctypes.create_string_buffer(PropertySize)
bytes_written = wintypes.DWORD(0)
success = SetupDiGetDeviceRegistryPropertyA.ctypes_function(
hDevInfo,
ctypes.byref(DevData),
Property,
PropertyType,
ctypes.cast(ctypes.byref(property_buffer), gdef.winstructs.PBYTE),
wintypes.DWORD(PropertySize),
ctypes.byref(bytes_written),
)
# Truncate read data
registry_data = bytes(property_buffer)
registry_data = registry_data[0:bytes_written.value]
return registry_data
def SetupDiEnumDeviceInterfaces(DeviceInfoSet, DeviceInfoData, InterfaceClassGuid, MemberIndex, DeviceInterfaceData):
return SetupDiEnumDeviceInterfaces.ctypes_function(DeviceInfoSet, DeviceInfoData, InterfaceClassGuid, MemberIndex, DeviceInterfaceData)
@SetupApiProxy()
def SetupDiGetDeviceRegistryPropertyW(hDevInfo, DevData, Property, PropertyType, PropertySize = MAX_DEV_LEN*ctypes.sizeof(wintypes.WCHAR)):
property_buffer = ctypes.create_unicode_buffer(PropertySize)
bytes_written = wintypes.DWORD(0)
success = SetupDiGetDeviceRegistryPropertyW.ctypes_function(
hDevInfo,
ctypes.byref(DevData),
Property,
PropertyType,
ctypes.cast(ctypes.byref(property_buffer), gdef.winstructs.PBYTE),
wintypes.DWORD(PropertySize),
ctypes.byref(bytes_written),
)
def SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize):
return SetupDiGetDeviceRegistryPropertyA.ctypes_function(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize)
@SetupApiProxy()
def SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize):
return SetupDiGetDeviceRegistryPropertyW.ctypes_function(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize)
# Truncate read data
registry_data = bytes(property_buffer)
registry_data = registry_data[0:bytes_written.value]
return registry_data