def do_WSARecv(self, handle, allocatedbuffer, size, flags): nread = _ffi.new("LPDWORD") wsabuff = _ffi.new("WSABUF[1]") buffercount = _ffi.new("DWORD[1]", [1]) pflags = _ffi.new("LPDWORD") pflags[0] = flags wsabuff[0].len = size wsabuff[0].buf = allocatedbuffer result = _winsock2.WSARecv(handle, wsabuff, _int2dword(1), nread, pflags, self.overlapped, _ffi.NULL) if result == SOCKET_ERROR: self.error = _kernel32.GetLastError() else: self.error = _winapi.ERROR_SUCCESS if self.error == _winapi.ERROR_BROKEN_PIPE: mark_as_completed(self.overlapped) SetFromWindowsErr(self.error) elif self.error in [ _winapi.ERROR_SUCCESS, _winapi.ERROR_MORE_DATA, _winapi.ERROR_IO_PENDING ]: return None else: self.type = OverlappedType.TYPE_NOT_STARTED SetFromWindowsErr(self.error)
def ConnectEx(self, socket, addressobj): socket = _int2handle(socket) if self.type != OverlappedType.TYPE_NONE: raise _winapi._WinError() address = _ffi.new("struct sockaddr_in6*") length = _ffi.sizeof("struct sockaddr_in6") address, length = parse_address(addressobj, _ffi.cast("SOCKADDR*", address), length) if length < 0: return None self.type = OverlappedType.TYPE_CONNECT self.handle = socket res = _connect_ex[0](socket, address, length, \ _ffi.NULL, 0, _ffi.NULL, self.overlapped) if res: self.error = _winapi.ERROR_SUCCESS else: self.error = _kernel32.GetLastError() if self.error == _winapi.ERROR_SUCCESS or self.error == _winapi.ERROR_IO_PENDING: return None else: self.type = OverlappedType.TYPE_NOT_STARTED SetFromWindowsErr(0)
def GetOverlappedResult(self, wait): transferred = _ffi.new('DWORD[1]', [0]) if self.type == OverlappedType.TYPE_NONE: return _ffi.NULL if self.type == OverlappedType.TYPE_NOT_STARTED: return _ffi.NULL res = _kernel32.GetOverlappedResult(self.handle, self.overlapped, transferred, wait != 0) if res: err = _winapi.ERROR_SUCCESS else: err = _kernel32.GetLastError() self.error = err if err != _winapi.ERROR_SUCCESS and err != _winapi.ERROR_MORE_DATA: if not (err == _winapi.ERROR_BROKEN_PIPE and (self.type in [ OverlappedType.TYPE_READ, OverlappedType.TYPE_READINTO ])): SetFromWindowsErr(err) if self.type == OverlappedType.TYPE_READ: return _ffi.unpack(self.read_buffer, transferred[0]) else: return transferred[0]
def WriteFile(self, handle, buffer): self.handle = _int2handle(handle) self.write_buffer = buffer written = _ffi.new('DWORD[1]', [0]) # Check if we have already performed some IO if self.type != OverlappedType.TYPE_NONE: raise _winapi._WinError() self.type = OverlappedType.TYPE_WRITE ret = _kernel32.WriteFile(self.handle, self.write_buffer, len(self.write_buffer), written, self.overlapped) if ret: self.error = _winapi.ERROR_SUCCESS else: self.error = _kernel32.GetLastError() if self.error == _winapi.ERROR_SUCCESS or self.error == _winapi.ERROR_IO_PENDING: return None else: self.type = OverlappedType.TYPE_NOT_STARTED SetFromWindowsErr(self.error)
def UnregisterWait(handle): handle = _int2handle(handle) ret = _kernel32.UnregisterWait(handle) if not ret: SetFromWindowsErr(0)
def WSASend(self, handle, bufobj, flags): handle = _int2handle(handle) if self.type != OverlappedType.TYPE_NONE: raise _winapi._WinError() self.write_buffer = bufobj self.type = OverlappedType.TYPE_WRITE self.handle = handle wsabuff = _ffi.new("WSABUF[1]") wsabuff[0].len = len(bufobj) wsabuff[0].buf = _ffi.new("CHAR[]", bufobj) nwritten = _ffi.new("LPDWORD") result = _winsock2.WSASend(handle, wsabuff, _int2dword(1), nwritten, flags, self.overlapped, _ffi.NULL) if result == SOCKET_ERROR: self.error = _kernel32.GetLastError() else: self.error = _winapi.ERROR_SUCCESS if self.error in [_winapi.ERROR_SUCCESS, _winapi.ERROR_IO_PENDING]: return None else: self.type = OverlappedType.TYPE_NOT_STARTED SetFromWindowsErr(self.error)
def AcceptEx(self, listensocket, acceptsocket): listensocket = _int2handle(listensocket) acceptsocket = _int2handle(acceptsocket) bytesreceived = _ffi.new("DWORD[1]") if self.type != OverlappedType.TYPE_NONE: raise _winapi._WinError() size = _ffi.sizeof("struct sockaddr_in6") + 16 buf = _ffi.new("CHAR[]", size * 2) if not buf: return None self.type = OverlappedType.TYPE_ACCEPT self.handle = listensocket self.read_buffer = buf res = _accept_ex[0](listensocket, acceptsocket, buf, \ 0, size, size, bytesreceived, self.overlapped) if res: self.error = _winapi.ERROR_SUCCESS else: self.error = _kernel32.GetLastError() if self.error == _winapi.ERROR_SUCCESS or self.error == _winapi.ERROR_IO_PENDING: return None else: self.type = OverlappedType.TYPE_NOT_STARTED SetFromWindowsErr(0)
def UnregisterWaitEx(handle, event): waithandle = _int2handle(handle) waitevent = _int2handle(event) ret = _kernel32.UnregisterWaitEx(waithandle, waitevent) if not ret: SetFromWindowsErr(0)
def cancel(self): result = True if self.type == OverlappedType.TYPE_NOT_STARTED or self.type == OverlappedType.TYPE_WAIT_NAMED_PIPE_AND_CONNECT: return None if not HasOverlappedIoCompleted(self.overlapped[0]): ### If we are to support xp we will need to dynamically load the below method result = _kernel32.CancelIoEx(self.handle, self.overlapped) if (not result and _kernel32.GetLastError() != _winapi.ERROR_NOT_FOUND): SetFromWindowsErr(0)
def CreateIoCompletionPort(handle, existingcompletionport, completionkey, numberofconcurrentthreads): completionkey = _int2intptr(completionkey) existingcompletionport = _int2handle(existingcompletionport) numberofconcurrentthreads = _int2dword(numberofconcurrentthreads) handle = _int2handle(handle) result = _kernel32.CreateIoCompletionPort(handle, existingcompletionport, completionkey, numberofconcurrentthreads) if result == _ffi.NULL: raise SetFromWindowsErr(0) return _handle2int(result)
def do_ReadFile(self, handle, buf, size): nread = _ffi.new('DWORD[1]', [0]) ret = _kernel32.ReadFile(handle, buf, size, nread, self.overlapped) if ret: err = _winapi.ERROR_SUCCESS else: err = _kernel32.GetLastError() self.error = err if err == _winapi.ERROR_BROKEN_PIPE: mark_as_completed(self.overlapped) SetFromWindowsErr(err) elif err in [ _winapi.ERROR_SUCCESS, _winapi.ERROR_MORE_DATA, _winapi.ERROR_IO_PENDING ]: return None else: self.type = OverlappedType.TYPE_NOT_STARTED SetFromWindowsErr(err)
def ConnectPipe(address): err = _winapi.ERROR_PIPE_BUSY waddress = _ffi.new("wchar_t[]", address) handle = _kernel32.CreateFileW( waddress, _winapi.GENERIC_READ | _winapi.GENERIC_WRITE, 0, _ffi.NULL, _winapi.OPEN_EXISTING, _winapi.FILE_FLAG_OVERLAPPED, _ffi.NULL) err = _kernel32.GetLastError() if handle == INVALID_HANDLE_VALUE or err == _winapi.ERROR_PIPE_BUSY: SetFromWindowsErr(err) return _handle2int(handle)
def RegisterWaitWithQueue(object, completionport, ovaddress, miliseconds): data = _ffi.cast('PostCallbackData*', _winapi.malloc(_ffi.sizeof("PostCallbackData"))) newwaitobject = _ffi.new("HANDLE*") data[0].hCompletionPort = _int2handle(completionport) data[0].Overlapped = _int2overlappedptr(ovaddress) ret = _kernel32.RegisterWaitForSingleObject( newwaitobject, _int2handle(object), _ffi.cast("WAITORTIMERCALLBACK", post_to_queue_callback), data, miliseconds, _kernel32.WT_EXECUTEINWAITTHREAD | _kernel32.WT_EXECUTEONLYONCE) if not ret: SetFromWindowsErr(0) return _handle2int(newwaitobject[0])
def __del__(self): bytes = _ffi.new("DWORD[1]", [0]) olderr = _kernel32.GetLastError() hascompletedio = HasOverlappedIoCompleted(self.overlapped[0]) if not hascompletedio and self.type != OverlappedType.TYPE_NOT_STARTED: wait = _kernel32.CancelIoEx(self.handle, self.overlapped) ret = self.GetOverlappedResult(wait) err = _winapi.ERROR_SUCCESS if not ret: err = _kernel32.GetLastError() self.error = err if err != _winapi.ERROR_SUCCESS and \ err != _winapi.ERROR_NOT_FOUND and \ err != _winapi.ERROR_OPERATION_ABORTED: SetFromWindowsErr(err) if self.overlapped[0].hEvent != 0: _winapi.CloseHandle(self.overlapped[0].hEvent) _winapi.SetLastError(olderr)
def ConnectNamedPipe(self, handle): if self.type != OverlappedType.TYPE_NONE: raise _winapi._WinError() self.type = OverlappedType.TYPE_CONNECT_NAMED_PIPE self.handle = _int2handle(handle) success = _kernel32.ConnectNamedPipe(self.handle, self.overlapped) if success: err = _winapi.ERROR_SUCCESS else: err = _kernel32.GetLastError() self.error = err if err == _winapi.ERROR_IO_PENDING | _winapi.ERROR_SUCCESS: return False elif err == _winapi.ERROR_PIPE_CONNECTED: mark_as_completed(self.overlapped) return True else: SetFromWindowsErr(err)
def BindLocal(socket, family): socket = _int2handle(socket) if family == AF_INET: addr = _ffi.new("struct sockaddr_in*") addr[0].sin_family = AF_INET addr[0].sin_port = 0 addr[0].sin_addr.S_un.S_addr = INADDR_ANY paddr = _ffi.cast("PSOCKADDR", addr) result = _winsock2.bind(socket, paddr, _ffi.sizeof("struct sockaddr_in")) elif family == AF_INET6: addr = _ffi.new("struct sockaddr_in6*") addr.sin6_family = AF_INET6 addr.sin6_port = 0 addr.sin6_addr = in6addr_any[0] result = _winsock2.bind(socket, _ffi.cast("PSOCKADDR", addr), _ffi.sizeof("struct sockaddr_in")) else: raise ValueError() if result == SOCKET_ERROR: SetFromWindowsErr(0)
def GetQueuedCompletionStatus(completionport, milliseconds): numberofbytes = _ffi.new('DWORD[1]', [0]) completionkey = _ffi.new('ULONG**') completionport = _int2handle(completionport) if completionport is None: raise _winapi._WinError() overlapped = _ffi.new("OVERLAPPED**") overlapped[0] = _ffi.NULL result = _kernel32.GetQueuedCompletionStatus(completionport, numberofbytes, completionkey, overlapped, milliseconds) if result: err = _winapi.ERROR_SUCCESS else: err = _kernel32.GetLastError() if overlapped[0] == _ffi.NULL: if err == _winapi.WAIT_TIMEOUT: return None return SetFromWindowsErr(err) return (err, numberofbytes, _handle2int(completionkey[0]), _handle2int(_ffi.addressof(overlapped[0][0])))