def _reconfigurePort(self): """Set communication parameters on opened port.""" if not self.hComPort: raise SerialException("Can only operate on a valid port handle") # Set Windows timeout values # timeouts is a tuple with the following items: # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier, # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier, # WriteTotalTimeoutConstant) if self._timeout is None: timeouts = (0, 0, 0, 0, 0) elif self._timeout == 0: timeouts = (win32.MAXDWORD, 0, 0, 0, 0) else: timeouts = (0, 0, int(self._timeout * 1000), 0, 0) if self._timeout != 0 and self._interCharTimeout is not None: timeouts = (int(self._interCharTimeout * 1000), ) + timeouts[1:] if self._writeTimeout is None: pass elif self._writeTimeout == 0: timeouts = timeouts[:-2] + (0, win32.MAXDWORD) else: timeouts = timeouts[:-2] + (0, int(self._writeTimeout * 1000)) win32.SetCommTimeouts(self.hComPort, ctypes.byref(win32.COMMTIMEOUTS(*timeouts))) win32.SetCommMask(self.hComPort, win32.EV_ERR) # Setup the connection info. # Get state and modify it: comDCB = win32.DCB() win32.GetCommState(self.hComPort, ctypes.byref(comDCB)) comDCB.BaudRate = self._baudrate if self._bytesize == FIVEBITS: comDCB.ByteSize = 5 elif self._bytesize == SIXBITS: comDCB.ByteSize = 6 elif self._bytesize == SEVENBITS: comDCB.ByteSize = 7 elif self._bytesize == EIGHTBITS: comDCB.ByteSize = 8 else: raise ValueError("Unsupported number of data bits: %r" % self._bytesize) if self._parity == PARITY_NONE: comDCB.Parity = win32.NOPARITY comDCB.fParity = 0 # Disable Parity Check elif self._parity == PARITY_EVEN: comDCB.Parity = win32.EVENPARITY comDCB.fParity = 1 # Enable Parity Check elif self._parity == PARITY_ODD: comDCB.Parity = win32.ODDPARITY comDCB.fParity = 1 # Enable Parity Check elif self._parity == PARITY_MARK: comDCB.Parity = win32.MARKPARITY comDCB.fParity = 1 # Enable Parity Check elif self._parity == PARITY_SPACE: comDCB.Parity = win32.SPACEPARITY comDCB.fParity = 1 # Enable Parity Check else: raise ValueError("Unsupported parity mode: %r" % self._parity) if self._stopbits == STOPBITS_ONE: comDCB.StopBits = win32.ONESTOPBIT elif self._stopbits == STOPBITS_ONE_POINT_FIVE: comDCB.StopBits = win32.ONE5STOPBITS elif self._stopbits == STOPBITS_TWO: comDCB.StopBits = win32.TWOSTOPBITS else: raise ValueError("Unsupported number of stop bits: %r" % self._stopbits) comDCB.fBinary = 1 # Enable Binary Transmission # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE) if self._rtscts: comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE elif self._rtsToggle: comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE else: comDCB.fRtsControl = self._rtsState if self._dsrdtr: comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE else: comDCB.fDtrControl = self._dtrState if self._rtsToggle: comDCB.fOutxCtsFlow = 0 else: comDCB.fOutxCtsFlow = self._rtscts comDCB.fOutxDsrFlow = self._dsrdtr comDCB.fOutX = self._xonxoff comDCB.fInX = self._xonxoff comDCB.fNull = 0 comDCB.fErrorChar = 0 comDCB.fAbortOnError = 0 comDCB.XonChar = XON comDCB.XoffChar = XOFF if not win32.SetCommState(self.hComPort, ctypes.byref(comDCB)): raise ValueError( "Cannot configure port, some setting was wrong. Original message: %s" % ctypes.WinError())
def __init__(self, message): message += " (%s)" % ctypes.WinError() super(PyperclipWindowsException, self).__init__(message)
def errcheck_bool(result, func, args): if not result: raise ctypes.WinError(ctypes.get_last_error()) return args
def __enter__(self): cmd = self.cmd mergeout = self.mergeout self.hstdout, self.hstdin, self.hstderr = None, None, None self.piProcInfo = None try: p_hstdout, c_hstdout, p_hstderr, \ c_hstderr, p_hstdin, c_hstdin = [None]*6 # SECURITY_ATTRIBUTES with inherit handle set to True saAttr = SECURITY_ATTRIBUTES() saAttr.nLength = ctypes.sizeof(saAttr) saAttr.bInheritHandle = True saAttr.lpSecurityDescriptor = None def create_pipe(uninherit): """Creates a Windows pipe, which consists of two handles. The 'uninherit' parameter controls which handle is not inherited by the child process. """ handles = HANDLE(), HANDLE() if not CreatePipe(ctypes.byref(handles[0]), ctypes.byref(handles[1]), ctypes.byref(saAttr), 0): raise ctypes.WinError() if not SetHandleInformation(handles[uninherit], HANDLE_FLAG_INHERIT, 0): raise ctypes.WinError() return handles[0].value, handles[1].value p_hstdout, c_hstdout = create_pipe(uninherit=0) # 'mergeout' signals that stdout and stderr should be merged. # We do that by using one pipe for both of them. if mergeout: c_hstderr = HANDLE() if not DuplicateHandle(GetCurrentProcess(), c_hstdout, GetCurrentProcess(), ctypes.byref(c_hstderr), 0, True, DUPLICATE_SAME_ACCESS): raise ctypes.WinError() else: p_hstderr, c_hstderr = create_pipe(uninherit=0) c_hstdin, p_hstdin = create_pipe(uninherit=1) # Create the process object piProcInfo = PROCESS_INFORMATION() siStartInfo = STARTUPINFO() siStartInfo.cb = ctypes.sizeof(siStartInfo) siStartInfo.hStdInput = c_hstdin siStartInfo.hStdOutput = c_hstdout siStartInfo.hStdError = c_hstderr siStartInfo.dwFlags = STARTF_USESTDHANDLES dwCreationFlags = CREATE_SUSPENDED | CREATE_NO_WINDOW # | CREATE_NEW_CONSOLE if not CreateProcess(None, "cmd.exe /c " + cmd, None, None, True, dwCreationFlags, None, None, ctypes.byref(siStartInfo), ctypes.byref(piProcInfo)): raise ctypes.WinError() # Close this process's versions of the child handles CloseHandle(c_hstdin) c_hstdin = None CloseHandle(c_hstdout) c_hstdout = None if c_hstderr != None: CloseHandle(c_hstderr) c_hstderr = None # Transfer ownership of the parent handles to the object self.hstdin = p_hstdin p_hstdin = None self.hstdout = p_hstdout p_hstdout = None if not mergeout: self.hstderr = p_hstderr p_hstderr = None self.piProcInfo = piProcInfo finally: if p_hstdin: CloseHandle(p_hstdin) if c_hstdin: CloseHandle(c_hstdin) if p_hstdout: CloseHandle(p_hstdout) if c_hstdout: CloseHandle(c_hstdout) if p_hstderr: CloseHandle(p_hstderr) if c_hstderr: CloseHandle(c_hstderr) return self
def check(result, _func, args): if result == error_result: raise ctypes.WinError(ctypes.get_last_error()) return args
kernel32 = ctypes.WinDLL('kernel32.dll', use_last_error=True) with_load_library_flags = hasattr(kernel32, 'AddDllDirectory') prev_error_mode = kernel32.SetErrorMode(0x0001) kernel32.LoadLibraryW.restype = ctypes.c_void_p if with_load_library_flags: kernel32.AddDllDirectory.restype = ctypes.c_void_p kernel32.LoadLibraryExW.restype = ctypes.c_void_p for dll_path in dll_paths: if sys.version_info >= (3, 8): os.add_dll_directory(dll_path) elif with_load_library_flags: res = kernel32.AddDllDirectory(dll_path) if res is None: err = ctypes.WinError(ctypes.get_last_error()) err.strerror += f' Error adding "{dll_path}" to the DLL directories.' raise err try: ctypes.CDLL('vcruntime140.dll') ctypes.CDLL('msvcp140.dll') if cuda_version not in ('9.2', '10.0'): ctypes.CDLL('vcruntime140_1.dll') except OSError: print( '''Microsoft Visual C++ Redistributable is not installed, this may lead to the DLL load failure. It can be downloaded at https://aka.ms/vs/16/release/vc_redist.x64.exe''' ) dlls = glob.glob(os.path.join(th_dll_path, '*.dll'))
def __init__(self, handle, size=4096): #4096): #16384): "Allocate the memory" self.memAddress = 0 self.size = size self.process = 0 if handle == 0xffffffff80000000: raise Exception('Incorrect handle: ' + str(handle)) self._as_parameter_ = self.memAddress if sysinfo.is_x64_Python(): process_id = ctypes.c_ulonglong() else: process_id = ctypes.c_ulong() win32functions.GetWindowThreadProcessId(handle, ctypes.byref(process_id)) if not process_id.value: raise AccessDenied( str(ctypes.WinError()) + " Cannot get process ID from handle.") self.process = win32functions.OpenProcess( win32defines.PROCESS_VM_OPERATION | win32defines.PROCESS_VM_READ | win32defines.PROCESS_VM_WRITE, 0, process_id) if not self.process: raise AccessDenied( str(ctypes.WinError()) + "process: %d", process_id.value) self.memAddress = win32functions.VirtualAllocEx( ctypes.c_void_p(self.process), # remote process ctypes.c_void_p(0), # let Valloc decide where win32structures.ULONG_PTR(self.size + 4), # how much to allocate win32defines.MEM_RESERVE | win32defines.MEM_COMMIT, # allocation type win32defines.PAGE_READWRITE # protection ) if hasattr(self.memAddress, 'value'): self.memAddress = self.memAddress.value if self.memAddress == 0: raise ctypes.WinError() if hex(self.memAddress) == '0xffffffff80000000' or hex( self.memAddress).upper() == '0xFFFFFFFF00000000': raise Exception('Incorrect allocation: ' + hex(self.memAddress)) self._as_parameter_ = self.memAddress # write guard signature at the end of memory block signature = win32structures.LONG(0x66666666) ret = win32functions.WriteProcessMemory( ctypes.c_void_p(self.process), ctypes.c_void_p(self.memAddress + self.size), ctypes.pointer(signature), win32structures.ULONG_PTR(4), win32structures.ULONG_PTR(0)) if ret == 0: print( '================== Error: Failed to write guard signature: address = ', self.memAddress, ', size = ', self.size) last_error = win32api.GetLastError() print('LastError = ', last_error, ': ', win32api.FormatMessage(last_error).rstrip()) sys.stdout.flush()
def open(self): """\ Open port with current settings. This may throw a SerialException if the port cannot be opened. """ if self._port is None: raise SerialException( "Port must be configured before it can be used.") if self.is_open: raise SerialException("Port is already open.") # the "\\.\COMx" format is required for devices other than COM1-COM8 # not all versions of windows seem to support this properly # so that the first few ports are used with the DOS device name port = self.name try: if port.upper().startswith('COM') and int(port[3:]) > 8: port = '\\\\.\\' + port except ValueError: # for like COMnotanumber pass self._port_handle = win32.CreateFile( port, win32.GENERIC_READ | win32.GENERIC_WRITE, 0, # exclusive access None, # no security win32.OPEN_EXISTING, win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED, 0) if self._port_handle == win32.INVALID_HANDLE_VALUE: self._port_handle = None # 'cause __del__ is called anyway raise SerialException("could not open port {!r}: {!r}".format( self.portstr, ctypes.WinError())) try: self._overlapped_read = win32.OVERLAPPED() self._overlapped_read.hEvent = win32.CreateEvent(None, 1, 0, None) self._overlapped_write = win32.OVERLAPPED() #~ self._overlapped_write.hEvent = win32.CreateEvent(None, 1, 0, None) self._overlapped_write.hEvent = win32.CreateEvent(None, 0, 0, None) # Setup a 4k buffer win32.SetupComm(self._port_handle, 4096, 4096) # Save original timeout values: self._orgTimeouts = win32.COMMTIMEOUTS() win32.GetCommTimeouts(self._port_handle, ctypes.byref(self._orgTimeouts)) self._reconfigure_port() # Clear buffers: # Remove anything that was there win32.PurgeComm( self._port_handle, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT | win32.PURGE_RXCLEAR | win32.PURGE_RXABORT) except: try: self._close() except: # ignore any exception when closing the port # also to keep original exception that happened when setting up pass self._port_handle = None raise else: self.is_open = True
def _check_count(self, result, func, args): """ Private function to return ctypes errors cleanly """ if result == 0: raise ctypes.WinError(ctypes.get_last_error()) return args
def _check(ret, expectederr=None): if ret == 0: winerrno = ctypes.GetLastError() if winerrno == expectederr: return True raise ctypes.WinError(winerrno)
def _reconfigure_port(self): """Set communication parameters on opened port.""" if not self._port_handle: raise SerialException("Can only operate on a valid port handle") # Set Windows timeout values # timeouts is a tuple with the following items: # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier, # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier, # WriteTotalTimeoutConstant) timeouts = win32.COMMTIMEOUTS() if self._timeout is None: pass # default of all zeros is OK elif self._timeout == 0: timeouts.ReadIntervalTimeout = win32.MAXDWORD else: timeouts.ReadTotalTimeoutConstant = max(int(self._timeout * 1000), 1) if self._timeout != 0 and self._inter_byte_timeout is not None: timeouts.ReadIntervalTimeout = max( int(self._inter_byte_timeout * 1000), 1) if self._write_timeout is None: pass elif self._write_timeout == 0: timeouts.WriteTotalTimeoutConstant = win32.MAXDWORD else: timeouts.WriteTotalTimeoutConstant = max( int(self._write_timeout * 1000), 1) win32.SetCommTimeouts(self._port_handle, ctypes.byref(timeouts)) win32.SetCommMask(self._port_handle, win32.EV_ERR) # Setup the connection info. # Get state and modify it: comDCB = win32.DCB() win32.GetCommState(self._port_handle, ctypes.byref(comDCB)) comDCB.BaudRate = self._baudrate if self._bytesize == serial.FIVEBITS: comDCB.ByteSize = 5 elif self._bytesize == serial.SIXBITS: comDCB.ByteSize = 6 elif self._bytesize == serial.SEVENBITS: comDCB.ByteSize = 7 elif self._bytesize == serial.EIGHTBITS: comDCB.ByteSize = 8 else: raise ValueError("Unsupported number of data bits: {!r}".format( self._bytesize)) if self._parity == serial.PARITY_NONE: comDCB.Parity = win32.NOPARITY comDCB.fParity = 0 # Disable Parity Check elif self._parity == serial.PARITY_EVEN: comDCB.Parity = win32.EVENPARITY comDCB.fParity = 1 # Enable Parity Check elif self._parity == serial.PARITY_ODD: comDCB.Parity = win32.ODDPARITY comDCB.fParity = 1 # Enable Parity Check elif self._parity == serial.PARITY_MARK: comDCB.Parity = win32.MARKPARITY comDCB.fParity = 1 # Enable Parity Check elif self._parity == serial.PARITY_SPACE: comDCB.Parity = win32.SPACEPARITY comDCB.fParity = 1 # Enable Parity Check else: raise ValueError("Unsupported parity mode: {!r}".format( self._parity)) if self._stopbits == serial.STOPBITS_ONE: comDCB.StopBits = win32.ONESTOPBIT elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE: comDCB.StopBits = win32.ONE5STOPBITS elif self._stopbits == serial.STOPBITS_TWO: comDCB.StopBits = win32.TWOSTOPBITS else: raise ValueError("Unsupported number of stop bits: {!r}".format( self._stopbits)) comDCB.fBinary = 1 # Enable Binary Transmission # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE) if self._rs485_mode is None: if self._rtscts: comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE else: comDCB.fRtsControl = win32.RTS_CONTROL_ENABLE if self._rts_state else win32.RTS_CONTROL_DISABLE comDCB.fOutxCtsFlow = self._rtscts else: # checks for unsupported settings # XXX verify if platform really does not have a setting for those if not self._rs485_mode.rts_level_for_tx: raise ValueError( 'Unsupported value for RS485Settings.rts_level_for_tx: {!r}' .format(self._rs485_mode.rts_level_for_tx, )) if self._rs485_mode.rts_level_for_rx: raise ValueError( 'Unsupported value for RS485Settings.rts_level_for_rx: {!r}' .format(self._rs485_mode.rts_level_for_rx, )) if self._rs485_mode.delay_before_tx is not None: raise ValueError( 'Unsupported value for RS485Settings.delay_before_tx: {!r}' .format(self._rs485_mode.delay_before_tx, )) if self._rs485_mode.delay_before_rx is not None: raise ValueError( 'Unsupported value for RS485Settings.delay_before_rx: {!r}' .format(self._rs485_mode.delay_before_rx, )) if self._rs485_mode.loopback: raise ValueError( 'Unsupported value for RS485Settings.loopback: {!r}'. format(self._rs485_mode.loopback, )) comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE comDCB.fOutxCtsFlow = 0 if self._dsrdtr: comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE else: comDCB.fDtrControl = win32.DTR_CONTROL_ENABLE if self._dtr_state else win32.DTR_CONTROL_DISABLE comDCB.fOutxDsrFlow = self._dsrdtr comDCB.fOutX = self._xonxoff comDCB.fInX = self._xonxoff comDCB.fNull = 0 comDCB.fErrorChar = 0 comDCB.fAbortOnError = 0 comDCB.XonChar = serial.XON comDCB.XoffChar = serial.XOFF if not win32.SetCommState(self._port_handle, ctypes.byref(comDCB)): raise SerialException( 'Cannot configure port, something went wrong. ' 'Original message: {!r}'.format(ctypes.WinError()))
def ValidHandle(value, func, arguments): if value == 0: raise ctypes.WinError() return value
def comports(): """This generator scans the device registry for com ports and yields port, desc, hwid""" g_hdi = SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT), None, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE) #~ for i in range(256): for dwIndex in range(256): did = SP_DEVICE_INTERFACE_DATA() did.cbSize = ctypes.sizeof(did) if not SetupDiEnumDeviceInterfaces( g_hdi, None, ctypes.byref(GUID_CLASS_COMPORT), dwIndex, ctypes.byref(did)): if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: raise ctypes.WinError() break dwNeeded = DWORD() # get the size if not SetupDiGetDeviceInterfaceDetail(g_hdi, ctypes.byref(did), None, 0, ctypes.byref(dwNeeded), None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # allocate buffer class SP_DEVICE_INTERFACE_DETAIL_DATA_A(ctypes.Structure): _fields_ = [ ('cbSize', DWORD), ('DevicePath', CHAR * (dwNeeded.value - ctypes.sizeof(DWORD))), ] def __str__(self): return "DevicePath:%s" % (self.DevicePath, ) idd = SP_DEVICE_INTERFACE_DETAIL_DATA_A() if is_64bit(): idd.cbSize = 8 else: idd.cbSize = 5 devinfo = SP_DEVINFO_DATA() devinfo.cbSize = ctypes.sizeof(devinfo) if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), ctypes.byref(idd), dwNeeded, None, ctypes.byref(devinfo)): raise ctypes.WinError() # hardware ID szHardwareID = byte_buffer(250) if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID, None, ctypes.byref(szHardwareID), ctypes.sizeof(szHardwareID) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # friendly name szFriendlyName = byte_buffer(250) if SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(devinfo), SPDRP_FRIENDLYNAME, None, ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1, None): # the real com port name has to read differently... hkey = SetupDiOpenDevRegKey(g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) port_name_buffer = byte_buffer(250) port_name_length = ULONG(ctypes.sizeof(port_name_buffer)) RegQueryValueEx(hkey, PortName, None, None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length)) RegCloseKey(hkey) yield string(port_name_buffer), string(szFriendlyName), string( szHardwareID) SetupDiDestroyDeviceInfoList(g_hdi)
def iterate_comports(): """Return a generator that yields descriptions for serial ports""" GUIDs = (GUID * 8)() # so far only seen one used, so hope 8 are enough... guids_size = DWORD() if not SetupDiClassGuidsFromName("Ports", GUIDs, ctypes.sizeof(GUIDs), ctypes.byref(guids_size)): raise ctypes.WinError() # repeat for all possible GUIDs for index in range(guids_size.value): g_hdi = SetupDiGetClassDevs( ctypes.byref(GUIDs[index]), None, NULL, DIGCF_PRESENT ) # was DIGCF_PRESENT|DIGCF_DEVICEINTERFACE which misses CDC ports devinfo = SP_DEVINFO_DATA() devinfo.cbSize = ctypes.sizeof(devinfo) index = 0 while SetupDiEnumDeviceInfo(g_hdi, index, ctypes.byref(devinfo)): index += 1 # get the real com port name hkey = SetupDiOpenDevRegKey( g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, # DIREG_DRV for SW info KEY_READ) port_name_buffer = ctypes.create_unicode_buffer(250) port_name_length = ULONG(ctypes.sizeof(port_name_buffer)) RegQueryValueEx(hkey, "PortName", None, None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length)) RegCloseKey(hkey) # unfortunately does this method also include parallel ports. # we could check for names starting with COM or just exclude LPT # and hope that other "unknown" names are serial ports... if port_name_buffer.value.startswith('LPT'): continue # hardware ID szHardwareID = ctypes.create_unicode_buffer(250) # try to get ID that includes serial number if not SetupDiGetDeviceInstanceId( g_hdi, ctypes.byref(devinfo), #~ ctypes.byref(szHardwareID), szHardwareID, ctypes.sizeof(szHardwareID) - 1, None): # fall back to more generic hardware ID if that would fail if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID, None, ctypes.byref(szHardwareID), ctypes.sizeof(szHardwareID) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # stringify szHardwareID_str = szHardwareID.value info = list_ports_common.ListPortInfo(port_name_buffer.value) # in case of USB, make a more readable string, similar to that form # that we also generate on other platforms if szHardwareID_str.startswith('USB'): m = re.search( r'VID_([0-9a-f]{4})(&PID_([0-9a-f]{4}))?(\\(\w+))?', szHardwareID_str, re.I) if m: info.vid = int(m.group(1), 16) if m.group(3): info.pid = int(m.group(3), 16) if m.group(5): info.serial_number = m.group(5) # calculate a location string loc_path_str = ctypes.create_unicode_buffer(250) if SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_LOCATION_PATHS, None, ctypes.byref(loc_path_str), ctypes.sizeof(loc_path_str) - 1, None): m = re.finditer(r'USBROOT\((\w+)\)|#USB\((\w+)\)', loc_path_str.value) location = [] for g in m: if g.group(1): location.append('{:d}'.format(int(g.group(1)) + 1)) else: if len(location) > 1: location.append('.') else: location.append('-') location.append(g.group(2)) if location: info.location = ''.join(location) info.hwid = info.usb_info() elif szHardwareID_str.startswith('FTDIBUS'): m = re.search( r'VID_([0-9a-f]{4})\+PID_([0-9a-f]{4})(\+(\w+))?', szHardwareID_str, re.I) if m: info.vid = int(m.group(1), 16) info.pid = int(m.group(2), 16) if m.group(4): info.serial_number = m.group(4) # USB location is hidden by FDTI driver :( info.hwid = info.usb_info() else: info.hwid = szHardwareID_str # friendly name szFriendlyName = ctypes.create_unicode_buffer(250) if SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_FRIENDLYNAME, #~ SPDRP_DEVICEDESC, None, ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1, None): info.description = szFriendlyName.value #~ else: # Ignore ERROR_INSUFFICIENT_BUFFER #~ if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: #~ raise IOError("failed to get details for %s (%s)" % (devinfo, szHardwareID.value)) # ignore errors and still include the port in the list, friendly name will be same as port name yield info SetupDiDestroyDeviceInfoList(g_hdi)
def default_errcheck(result, func, args): if result != getattr(winerror, 'ERROR_SUCCESS', 0): # On shutdown winerror becomes None raise ctypes.WinError(result) return args
def listComPorts(onlyAvailable=True): """List com ports on the system. @param onlyAvailable: Only return ports that are currently available. @type onlyAvailable: bool @return: Generates dicts including keys of port, friendlyName and hardwareID. @rtype: generator of (str, str, str) """ flags = DIGCF_DEVICEINTERFACE if onlyAvailable: flags |= DIGCF_PRESENT buf = ctypes.create_unicode_buffer(1024) g_hdi = SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT), None, NULL, flags) try: for dwIndex in xrange(256): entry = {} did = SP_DEVICE_INTERFACE_DATA() did.cbSize = ctypes.sizeof(did) if not SetupDiEnumDeviceInterfaces( g_hdi, None, ctypes.byref(GUID_CLASS_COMPORT), dwIndex, ctypes.byref(did) ): if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: raise ctypes.WinError() break dwNeeded = DWORD() # get the size if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), None, 0, ctypes.byref(dwNeeded), None ): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # allocate buffer class SP_DEVICE_INTERFACE_DETAIL_DATA_W(ctypes.Structure): _fields_ = ( ('cbSize', DWORD), ('DevicePath', WCHAR*(dwNeeded.value - ctypes.sizeof(DWORD))), ) def __str__(self): return "DevicePath:%s" % (self.DevicePath,) idd = SP_DEVICE_INTERFACE_DETAIL_DATA_W() idd.cbSize = SIZEOF_SP_DEVICE_INTERFACE_DETAIL_DATA_W devinfo = SP_DEVINFO_DATA() devinfo.cbSize = ctypes.sizeof(devinfo) if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), ctypes.byref(idd), dwNeeded, None, ctypes.byref(devinfo) ): raise ctypes.WinError() # hardware ID if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID, None, ctypes.byref(buf), ctypes.sizeof(buf) - 1, None ): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() else: hwID = entry["hardwareID"] = buf.value regKey = ctypes.windll.setupapi.SetupDiOpenDevRegKey(g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, winreg.KEY_READ) port = entry["port"] = winreg.QueryValueEx(regKey, "PortName")[0] if hwID.startswith("BTHENUM\\"): # This is a Microsoft bluetooth port. try: addr = winreg.QueryValueEx(regKey, "Bluetooth_UniqueID")[0].split("#", 1)[1].split("_", 1)[0] addr = int(addr, 16) entry["bluetoothAddress"] = addr if addr: entry["bluetoothName"] = getBluetoothDeviceInfo(addr).szName except: pass elif hwID == r"Bluetooth\0004&0002": # This is a Toshiba bluetooth port. try: entry["bluetoothAddress"], entry["bluetoothName"] = getToshibaBluetoothPortInfo(port) except: pass ctypes.windll.advapi32.RegCloseKey(regKey) # friendly name if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_FRIENDLYNAME, None, ctypes.byref(buf), ctypes.sizeof(buf) - 1, None ): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() else: entry["friendlyName"] = buf.value yield entry finally: SetupDiDestroyDeviceInfoList(g_hdi)
def check_code(code): if code == ERROR_SUCCESS: return raise ctypes.WinError(2)
def ValidHandle(value): if value == 0: raise ctypes.WinError() return value
def Read(self, data, address=None, size=None): "Read data from the memory block" if not address: address = self.memAddress if hasattr(address, 'value'): address = address.value if size: nSize = win32structures.ULONG_PTR(size) else: nSize = win32structures.ULONG_PTR(ctypes.sizeof(data)) if self.size < nSize.value: raise Exception('Read: RemoteMemoryBlock is too small (' + str(self.size) + ' bytes), ' + str(nSize.value) + ' is required.') if hex(address).lower().startswith('0xffffff'): raise Exception('Read: RemoteMemoryBlock has incorrect address =' + hex(address)) lpNumberOfBytesRead = ctypes.c_size_t(0) ret = win32functions.ReadProcessMemory( ctypes.c_void_p(self.process), ctypes.c_void_p(address), ctypes.byref(data), nSize, ctypes.byref(lpNumberOfBytesRead)) # disabled as it often returns an error - but # seems to work fine anyway!! if ret == 0: # try again ret = win32functions.ReadProcessMemory( ctypes.c_void_p(self.process), ctypes.c_void_p(address), ctypes.byref(data), nSize, ctypes.byref(lpNumberOfBytesRead)) if ret == 0: last_error = win32api.GetLastError() if last_error != win32defines.ERROR_PARTIAL_COPY: print('\nError: Read: WARNING! self.memAddress =', self.memAddress, ' data address =', ctypes.byref(data)) print('LastError = ', last_error, ': ', win32api.FormatMessage(last_error).rstrip()) print('lpNumberOfBytesRead =', lpNumberOfBytesRead, ' nSize =', nSize) print('Caller stack:') for frame in inspect.stack(): print(frame[1:]) print() sys.stdout.flush() raise ctypes.WinError() else: print('Error: ERROR_PARTIAL_COPY') print('\nRead: WARNING! self.memAddress =', self.memAddress, ' data address =', ctypes.byref(data)) print('lpNumberOfBytesRead =', lpNumberOfBytesRead, ' nSize =', nSize) print('Caller stack:') for frame in inspect.stack(): print('\t\t', frame[1:]) print() sys.stdout.flush() else: print('Read OK: 2nd attempt!') #else: # print 'Read OK: lpNumberOfBytesRead =', lpNumberOfBytesRead, ' nSize =', nSize self.CheckGuardSignature() return data
def getBluetoothDeviceInfo(address): devInfo = BLUETOOTH_DEVICE_INFO(address=address) res = ctypes.windll["bthprops.cpl"].BluetoothGetDeviceInfo(None, ctypes.byref(devInfo)) if res != 0: raise ctypes.WinError(res) return devInfo
def replace_file(filename, replacement): if not ReplaceFileW(_make_filename_unicode(filename), _make_filename_unicode(replacement), None, 0, 0, 0): raise ctypes.WinError()
def _check_invalid_handle(result, func, args): if result == INVALID_HANDLE_VALUE: raise ctypes.WinError(ctypes.get_last_error()) return args
] GetProcessMemoryInfo = ctypes.windll.psapi.GetProcessMemoryInfo GetProcessMemoryInfo.argtypes = [ wintypes.HANDLE, ctypes.POINTER(PROCESS_MEMORY_COUNTERS_EX), wintypes.DWORD, ] GetProcessMemoryInfo.restype = wintypes.BOOL counters = PROCESS_MEMORY_COUNTERS_EX() rv = GetProcessMemoryInfo( ctypes.windll.kernel32.GetCurrentProcess(), ctypes.byref(counters), ctypes.sizeof(counters), ) if not rv: raise ctypes.WinError() print("OK.") else: # TODO: How to get this to work. if False: libc = ctypes.CDLL("libc") printf = libc.printf printf("Hello, %s\n", "World!") print("OK.")
def Enumerate(): """See base class.""" hid_guid = GUID() hid.HidD_GetHidGuid(ctypes.byref(hid_guid)) devices = setupapi.SetupDiGetClassDevsA(ctypes.byref(hid_guid), None, None, 0x12) index = 0 interface_info = DeviceInterfaceData() interface_info.cbSize = ctypes.sizeof(DeviceInterfaceData) # pylint: disable=invalid-name out = [] while True: result = setupapi.SetupDiEnumDeviceInterfaces( devices, 0, ctypes.byref(hid_guid), index, ctypes.byref(interface_info)) index += 1 if not result: break detail_len = wintypes.DWORD() result = setupapi.SetupDiGetDeviceInterfaceDetailA( devices, ctypes.byref(interface_info), None, 0, ctypes.byref(detail_len), None) detail_len = detail_len.value if detail_len == 0: # skip this device, some kind of error continue buf = ctypes.create_string_buffer(detail_len) interface_detail = DeviceInterfaceDetailData.from_buffer(buf) interface_detail.cbSize = ctypes.sizeof(DeviceInterfaceDetailData) result = setupapi.SetupDiGetDeviceInterfaceDetailA( devices, ctypes.byref(interface_info), ctypes.byref(interface_detail), detail_len, None, None) if not result: raise ctypes.WinError() descriptor = base.DeviceDescriptor() # This is a bit of a hack to work around a limitation of ctypes and # "header" structures that are common in windows. DevicePath is a # ctypes array of length 1, but it is backed with a buffer that is much # longer and contains a null terminated string. So, we read the null # terminated string off DevicePath here. Per the comment above, the # alignment of this struct varies depending on architecture, but # in all cases the path string starts 1 DWORD into the structure. # # The path length is: # length of detail buffer - header length (1 DWORD) path_len = detail_len - ctypes.sizeof(wintypes.DWORD) descriptor.path = ctypes.string_at( ctypes.addressof(interface_detail.DevicePath), path_len) device = None try: device = OpenDevice(descriptor.path, True) except WindowsError as e: # pylint: disable=undefined-variable if e.winerror == ERROR_ACCESS_DENIED: # Access Denied, e.g. a keyboard continue else: raise e try: FillDeviceAttributes(device, descriptor) FillDeviceCapabilities(device, descriptor) out.append(descriptor.ToPublicDict()) finally: kernel32.CloseHandle(device) return out
def CloseKey(key): rc = RegCloseKey(key) if rc != ERROR_SUCCESS: raise ctypes.WinError(2)
def last_error_errcheck(result, func, args): if result == 0: raise ctypes.WinError() return args
def _check_count(result, func, args): if result == 0: raise ctypes.WinError(ctypes.get_last_error()) return args
def delete_value_errcheck(result, func, args): if result == winerror.ERROR_FILE_NOT_FOUND: return args if result != 0: raise ctypes.WinError(result) return args
def comports(): GUIDs = (GUID*8)() # so far only seen one used, so hope 8 are enough... guids_size = DWORD() if not SetupDiClassGuidsFromName( Ports, GUIDs, ctypes.sizeof(GUIDs), ctypes.byref(guids_size)): raise ctypes.WinError() # repeat for all possible GUIDs for index in range(guids_size.value): g_hdi = SetupDiGetClassDevs( ctypes.byref(GUIDs[index]), None, NULL, DIGCF_PRESENT) # was DIGCF_PRESENT|DIGCF_DEVICEINTERFACE which misses CDC ports devinfo = SP_DEVINFO_DATA() devinfo.cbSize = ctypes.sizeof(devinfo) index = 0 while SetupDiEnumDeviceInfo(g_hdi, index, ctypes.byref(devinfo)): index += 1 # get the real com port name hkey = SetupDiOpenDevRegKey( g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, # DIREG_DRV for SW info KEY_READ) port_name_buffer = byte_buffer(250) port_name_length = ULONG(ctypes.sizeof(port_name_buffer)) RegQueryValueEx( hkey, PortName, None, None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length)) RegCloseKey(hkey) # unfortunately does this method also include parallel ports. # we could check for names starting with COM or just exclude LPT # and hope that other "unknown" names are serial ports... if string(port_name_buffer).startswith('LPT'): continue # hardware ID szHardwareID = byte_buffer(250) # try to get ID that includes serial number if not SetupDiGetDeviceInstanceId( g_hdi, ctypes.byref(devinfo), ctypes.byref(szHardwareID), ctypes.sizeof(szHardwareID) - 1, None): # fall back to more generic hardware ID if that would fail if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID, None, ctypes.byref(szHardwareID), ctypes.sizeof(szHardwareID) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # stringify szHardwareID_str = string(szHardwareID) # in case of USB, make a more readable string, similar to that form # that we also generate on other platforms if szHardwareID_str.startswith('USB'): m = re.search(r'VID_([0-9a-f]{4})&PID_([0-9a-f]{4})(\\(\w+))?', szHardwareID_str, re.I) if m: if m.group(4): szHardwareID_str = 'USB VID:PID=%s:%s SNR=%s' % (m.group(1), m.group(2), m.group(4)) else: szHardwareID_str = 'USB VID:PID=%s:%s' % (m.group(1), m.group(2)) # friendly name szFriendlyName = byte_buffer(250) if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_FRIENDLYNAME, #~ SPDRP_DEVICEDESC, None, ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER #~ if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: #~ raise IOError("failed to get details for %s (%s)" % (devinfo, szHardwareID.value)) # ignore errors and still include the port in the list, friendly name will be same as port name yield string(port_name_buffer), 'n/a', szHardwareID_str else: yield string(port_name_buffer), string(szFriendlyName), szHardwareID_str SetupDiDestroyDeviceInfoList(g_hdi)
def CheckConnect(result, func, arguments): if result == 0: error = ctypes.get_last_error() if error != ERROR_PIPE_CONNECTED: raise ctypes.WinError(error) return result