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 CreateProcess(name, command_line, process_attr, thread_attr, inherit, flags, env, start_dir, startup_info): si = _ffi.new("STARTUPINFO *") if startup_info is not None: si.dwFlags = startup_info.dwFlags si.wShowWindow = startup_info.wShowWindow # CPython: these three handles are expected to be _handle objects if startup_info.hStdInput: si.hStdInput = startup_info.hStdInput.c_handle if startup_info.hStdOutput: si.hStdOutput = startup_info.hStdOutput.c_handle if startup_info.hStdError: si.hStdError = startup_info.hStdError.c_handle pi = _ffi.new("PROCESS_INFORMATION *") if env is not None: envbuf = "" for k, v in env.iteritems(): envbuf += "%s=%s\0" % (k, v) envbuf += '\0' else: envbuf = _ffi.NULL res = _kernel32.CreateProcessA(_z(name), _z(command_line), _ffi.NULL, _ffi.NULL, inherit, flags, envbuf, _z(start_dir), si, pi) if not res: raise _WinError() return (_handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessId, pi.dwThreadId)
def WriteFile(handle, buffer, overlapped=False): written = _ffi.new("DWORD*") use_overlapped = overlapped overlapped = None err = 0 if use_overlapped: overlapped = Overlapped(handle) if not overlapped: return _ffi.NULL overlapped.writebuffer = bytes(buffer) buf = overlapped.writebuffer ret = _kernel32.WriteFile(_int2handle(handle), buf , len(buf), written, overlapped.overlapped) if not ret: err = _kernel32.GetLastError() if err == ERROR_IO_PENDING: overlapped.pending = 1 else: return_WinError(IOError) return overlapped, err else: buf = _ffi.new("CHAR[]", bytes(buffer)) ret = _kernel32.WriteFile(_int2handle(handle), buf , len(buf), written, _ffi.NULL) if not ret: raise_WinError(IOError) return written[0], err
def ReadFile(handle, size, overlapped): nread = _ffi.new("DWORD*") use_overlapped = overlapped buf = _ffi.new("CHAR[]", size) if not buf: raise_WinError(IOError) err = 0 if use_overlapped: overlapped = Overlapped(handle) overlapped.readbuffer = buf ret = _kernel32.ReadFile(_int2handle(handle), buf, size, nread, overlapped.overlapped) if not ret: err = _kernel32.GetLastError() if err == ERROR_IO_PENDING: overlapped.pending = 1 elif err != ERROR_MORE_DATA: raise_WinError(IOError) return overlapped, err else: ret = _kernel32.ReadFile(_int2handle(handle), buf, size, nread, _ffi.NULL) if not ret: err = _kernel32.GetLastError() if err != ERROR_MORE_DATA: raise_WinError(IOError) return nread[0], err
def AcceptEx(self, listensocket, acceptsocket): listensocket = _int2handle(listensocket) acceptsocket = _int2handle(acceptsocket) bytesreceived = _ffi.new("DWORD[1]") if self.type != OverlappedType.TYPE_NONE: _winapi.raise_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 RaiseFromWindowsErr(0)
def WSASend(self, handle, bufobj, flags): """ Send bufobj using handle. Raises on error. Returns None """ handle = _int2handle(handle) if self.type != OverlappedType.TYPE_NONE: _winapi.raise_WinError() self.write_buffer = bytes(bufobj) self.type = OverlappedType.TYPE_WRITE self.handle = handle wsabuff = _ffi.new("WSABUF[1]") lgt = len(self.write_buffer) wsabuff[0].len = lgt wsabuff[0].buf = _ffi.new('CHAR[]', self.write_buffer) 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 not in [_winapi.ERROR_SUCCESS, _winapi.ERROR_IO_PENDING]: self.type = OverlappedType.TYPE_NOT_STARTED RaiseFromWindowsErr(self.error)
def PeekNamedPipe(handle, size=0): nread = _ffi.new("DWORD*") navail = _ffi.new("DWORD*") nleft = _ffi.new("DWORD*") if size < 0: raise ValueError("negative size") if size: buf = _ffi.new("CHAR[]", size) if not buf: return _ffi.NULL ret = _kernel32.PeekNamedPipe(_int2handle(handle), buf, size, nread, navail, nleft) if not ret: # In CPython SetExcFromWindowsErr is called here. # Not sure what that is doing currently. RaiseFromWindowsErr(0) return buf, navail[0], nleft[0] else: ret = _kernel32.PeekNamedPipe(_int2handle(handle), _ffi.NULL, 0, _ffi.NULL, navail, nleft) if not ret: # In CPython SetExcFromWindowsErr is called here. # Not sure what that is doing currently. RaiseFromWindowsErr(0) return navail[0], nleft[0]
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) RaiseFromWindowsErr(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 RaiseFromWindowsErr(self.error)
def CreateProcess(name, command_line, process_attr, thread_attr, inherit, flags, env, start_dir, startup_info): si = _ffi.new("STARTUPINFO *") if startup_info is not None: si.dwFlags = startup_info.dwFlags si.wShowWindow = startup_info.wShowWindow # CPython: these three handles are expected to be # subprocess.Handle (int) objects if startup_info.hStdInput: si.hStdInput = _int2handle(startup_info.hStdInput) if startup_info.hStdOutput: si.hStdOutput = _int2handle(startup_info.hStdOutput) if startup_info.hStdError: si.hStdError = _int2handle(startup_info.hStdError) pi = _ffi.new("PROCESS_INFORMATION *") flags |= CREATE_UNICODE_ENVIRONMENT if env is not None: envbuf = "" for k, v in env.items(): envbuf += "%s=%s\0" % (k, v) envbuf += '\0' else: envbuf = _ffi.NULL res = _kernel32.CreateProcessW(_Z(name), _Z(command_line), _ffi.NULL, _ffi.NULL, inherit, flags, envbuf, _Z(start_dir), si, pi) if not res: raise _WinError() return (_handle2int(pi.hProcess), _handle2int(pi.hThread), pi.dwProcessId, pi.dwThreadId)
def SetNamedPipeHandleState(namedpipe, mode, max_collection_count, collect_data_timeout): d0 = _ffi.new('DWORD[1]', [mode]) if max_collection_count is None: d1 = NULL else: d1 = _ffi.new('DWORD[1]', [max_collection_count]) if collect_data_timeout is None: d2 = NULL else: d2 = _ffi.new('DWORD[1]', [collect_data_timeout]) ret = _kernel32.SetNamedPipeHandleState(namedpipe, d0, d1, d2) if not ret: raise _WinError()
def ConnectEx(self, socket, addressobj): socket = _int2handle(socket) if self.type != OverlappedType.TYPE_NONE: _winapi.raise_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 RaiseFromWindowsErr(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: _winapi.raise_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 RaiseFromWindowsErr(self.error)
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 ])): RaiseFromWindowsErr(err) if self.type == OverlappedType.TYPE_READ: return _ffi.unpack(self.read_buffer, transferred[0]) else: return transferred[0]
def initiailize_function_ptrs(): ## importing socket ensures that WSAStartup() is called import _socket s = _winsock2.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) dwBytes = _ffi.new("DWORD[1]", [0]) if s == INVALID_SOCKET: _winapi.raise_WinError() result = _winsock2.WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \ WSAID_ACCEPTEX, _ffi.sizeof(WSAID_ACCEPTEX[0]), _accept_ex, \ _ffi.sizeof(_accept_ex[0]), dwBytes, _ffi.NULL, _ffi.NULL) if result == INVALID_SOCKET: _winsock2.closesocket(s) _winapi.raise_WinError() result = _winsock2.WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \ WSAID_CONNECTEX, _ffi.sizeof(WSAID_CONNECTEX[0]), _connect_ex, \ _ffi.sizeof(_connect_ex[0]), dwBytes, _ffi.NULL, _ffi.NULL) if result == INVALID_SOCKET: _winsock2.closesocket(s) _winapi.raise_WinError() result = _winsock2.WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \ WSAID_DISCONNECTEX, _ffi.sizeof(WSAID_DISCONNECTEX[0]), _disconnect_ex, \ _ffi.sizeof(_disconnect_ex[0]), dwBytes, _ffi.NULL, _ffi.NULL) _winsock2.closesocket(s) if result == INVALID_SOCKET: _winapi.raise_WinError()
def GetModuleFileName(module): buf = _ffi.new("wchar_t[]", _MAX_PATH) res = _kernel32.GetModuleFileNameW(_int2handle(module), buf, _MAX_PATH) if not res: raise _WinError() return _ffi.string(buf)
def CreatePipe(attributes, size): handles = _ffi.new("HANDLE[2]") res = _kernel32.CreatePipe(handles, handles + 1, NULL, size) if not res: RaiseFromWindowsErr(GetLastError()) return _handle2int(handles[0]), _handle2int(handles[1])
def CreatePipe(attributes, size): handles = _ffi.new("HANDLE[2]") res = _kernel32.CreatePipe(handles, handles + 1, _ffi.NULL, size) if not res: raise _WinError() return _handle(handles[0]), _handle(handles[1])
def __init__(self, handle): self.overlapped = _ffi.new('OVERLAPPED[1]') self.handle = handle self.readbuffer = None self.pending = 0 self.completed = 0 self.writebuffer = None self.overlapped[0].hEvent = \ _kernel32.CreateEventW(NULL, True, False, NULL)
def CreatePipe(attributes, size): handles = _ffi.new("HANDLE[2]") res = _kernel32.CreatePipe(handles, handles + 1, NULL, size) if not res: raise _WinError() return _handle2int(handles[0]), _handle2int(handles[1])
def GetExitCodeProcess(handle): # CPython: the first argument is expected to be an integer. code = _ffi.new("DWORD[1]") res = _kernel32.GetExitCodeProcess(_int2handle(handle), code) if not res: raise _WinError() return code[0]
def WSARecv(self, handle, size, flags): handle = _int2handle(handle) flags = _int2dword(flags) if self.type != OverlappedType.TYPE_NONE: _winapi.raise_WinError() self.type = OverlappedType.TYPE_READ self.handle = _int2handle(handle) self.read_buffer = _ffi.new("CHAR[]", max(1, size)) return self.do_WSARecv(handle, self.read_buffer, size, flags)
def __init__(self, handle): self.overlapped = _ffi.new('OVERLAPPED[1]') self.handle = _handle2int(handle) self.readbuffer = None self.pending = 0 self.completed = 0 self.writebuffer = None self.overlapped[0].hEvent = \ _kernel32.CreateEventW(NULL, True, False, NULL) if not self.overlapped[0].hEvent: raise_WinError(IOError)
def WaitForMultipleObjects(handle_sequence, waitflag, milliseconds): if len(handle_sequence) > MAXIMUM_WAIT_OBJECTS: return None handle_sequence = list(map(_int2handle, handle_sequence)) handle_sequence = _ffi.new("HANDLE[]", handle_sequence) # CPython makes the wait interruptible by ctrl-c. We need to add this in at some point res = _kernel32.WaitForMultipleObjects(len(handle_sequence), handle_sequence, waitflag, milliseconds) if res == WAIT_FAILED: raise_WinError() return int(res)
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: RaiseFromWindowsErr(err) return _handle2int(handle)
def __del__(self): # do this somehow else xxx err = _kernel32.GetLastError() bytes = _ffi.new('DWORD[1]') o = overlapped[0] if overlapped[0].pending: if _kernel32.CancelIoEx(o.handle, o.overlapped) & \ self.GetOverlappedResult(o.handle, o.overlapped, _ffi.addressof(bytes), True): # The operation is no longer pending, nothing to do pass else: raise RuntimeError('deleting an overlapped strucwith a pending operation not supported')
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: RaiseFromWindowsErr(0)
def ReadFile(handle, size, overlapped): nread = _ffi.new("DWORD*") err = _ffi.new("DWORD*") use_overlapped = overlapped overlapped = None buf = _ffi.new("CHAR[]", size) if not buf: return _ffi.NULL if use_overlapped: overlapped = Overlapped(handle) if not overlapped: return _ffi.NULL overlapped.readbuffer = buf if overlapped: ret = _kernel32.ReadFile(_int2handle(handle), buf, size, nread, overlapped.overlapped) else: ret = _kernel32.ReadFile(_int2handle(handle), buf, size, nread, _ffi.NULL) if ret: err = 0 else: err = _kernel32.GetLastError() if use_overlapped: if not ret: if err == ERROR_IO_PENDING: overlapped.pending = 1 elif err != ERROR_MORE_DATA: return _WinError(IOError) return overlapped, err if (not ret) and err != ERROR_MORE_DATA: return _WinError(IOError) return buf, err
def GetOverlappedResult(self, wait): transferred = _ffi.new('DWORD[1]', [0]) res = _kernel32.GetOverlappedResult(_int2handle(self.handle), self.overlapped, transferred, wait != 0) if res: err = ERROR_SUCCESS else: err = _kernel32.GetLastError() if err in (ERROR_SUCCESS, ERROR_MORE_DATA, ERROR_OPERATION_ABORTED): self.completed = 1 self.pending = 0 elif res != ERROR_IO_INCOMPLETE: self.pending = 0 print('GetOverlappedResult got err', err) raise_WinError(IOError) if self.completed and self.readbuffer: if transferred[0] != len(self.readbuffer): tempbuffer = _ffi.new("CHAR[]", transferred[0]) _ffi.memmove(tempbuffer, self.readbuffer, transferred[0]) self.readbuffer = tempbuffer return transferred[0], err
def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): # CPython: the first three arguments are expected to be integers target = _ffi.new("HANDLE[1]") res = _kernel32.DuplicateHandle( _int2handle(source_process), _int2handle(source), _int2handle(target_process), target, access, inherit, options) if not res: raise _WinError() return _handle(target[0])
def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): # CPython: the first three arguments are expected to be integers target = _ffi.new("HANDLE[1]") res = _kernel32.DuplicateHandle( _int2handle(source_process), _int2handle(source), _int2handle(target_process), target, access, inherit, options) if not res: raise _WinError() return _handle2int(target[0])
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: RaiseFromWindowsErr(0) return _handle2int(newwaitobject[0])
def __del__(self): # do this somehow else err = _kernel32.GetLastError() bytes = _ffi.new('DWORD[1]') if self.pending: result = _kernel32.CancelIoEx(_int2handle(self.handle), self.overlapped) if result: _kernel32.GetOverlappedResult(_int2handle(self.handle), self.overlapped, bytes, True) # The operation is no longer pending, nothing to do #else: # We need to raise a warning here and not crash pypy #raise RuntimeError('deleting an overlapped struct with a pending operation not supported') CloseHandle(_int2handle(self.overlapped[0].hEvent)) _kernel32.SetLastError(err)