def test_basic(self): buf = ByteBuffer(4) assert buf.getlength() == 4 assert buf.getitem(2) == '\x00' buf.setitem(0, 'A') buf.setitem(3, 'Z') assert buf.as_str() == 'A\x00\x00Z'
def QueryValue(space, w_hkey, w_subkey): """ string = QueryValue(key, sub_key) - retrieves the unnamed value for a key. key is an already open key, or any one of the predefined HKEY_* constants. sub_key is a string that holds the name of the subkey with which the value is associated. If this parameter is None or empty, the function retrieves the value set by the SetValue() method for the key identified by key. Values in the registry have name, type, and data components. This method retrieves the data for a key's first value that has a NULL name. But the underlying API call doesn't return the type: Lame, DONT USE THIS!!!""" hkey = hkey_w(w_hkey, space) if space.is_w(w_subkey, space.w_None): subkey = None else: subkey = space.utf8_w(w_subkey).decode('utf8') with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: c_subkey = rffi.cast(rffi.CWCHARP, wide_subkey) with lltype.scoped_alloc(rwin32.PLONG.TO, 1) as bufsize_p: bufsize_p[0] = 0 ret = rwinreg.RegQueryValueW(hkey, c_subkey, None, bufsize_p) if ret == 0 and intmask(bufsize_p[0]) == 0: return space.newtext('', 0) elif ret != 0 and ret != rwinreg.ERROR_MORE_DATA: raiseWindowsError(space, ret, 'RegQueryValue') # Add extra space for a NULL ending buf = ByteBuffer(intmask(bufsize_p[0]) * 2 + 2) bufP = rffi.cast(rwin32.LPWSTR, buf.get_raw_address()) ret = rwinreg.RegQueryValueW(hkey, c_subkey, bufP, bufsize_p) if ret != 0: raiseWindowsError(space, ret, 'RegQueryValue') utf8, lgt = wbuf_to_utf8(space, buf[0:intmask(bufsize_p[0])]) return space.newtext(utf8, lgt)
def EnumKey(space, w_hkey, index): """string = EnumKey(key, index) - Enumerates subkeys of an open registry key. key is an already open key, or any one of the predefined HKEY_* constants. index is an integer that identifies the index of the key to retrieve. The function retrieves the name of one subkey each time it is called. It is typically called repeatedly until an EnvironmentError exception is raised, indicating no more values are available.""" hkey = hkey_w(w_hkey, space) null_dword = lltype.nullptr(rwin32.LPDWORD.TO) # The Windows docs claim that the max key name length is 255 # characters, plus a terminating nul character. However, # empirical testing demonstrates that it is possible to # create a 256 character key that is missing the terminating # nul. RegEnumKeyEx requires a 257 character buffer to # retrieve such a key name. buf = ByteBuffer(257 * 2) bufP = rffi.cast(rwin32.LPWSTR, buf.get_raw_address()) with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as valueSize: valueSize[0] = r_uint(257) # includes NULL terminator ret = rwinreg.RegEnumKeyExW(hkey, index, bufP, valueSize, null_dword, None, null_dword, lltype.nullptr(rwin32.PFILETIME.TO)) if ret != 0: raiseWindowsError(space, ret, 'RegEnumKeyEx') vlen = intmask(valueSize[0]) * 2 utf8, lgt = wbuf_to_utf8(space, buf[0:vlen]) return space.newtext(utf8, lgt)
def make_buffer(flag): if flag: buf = ByteBuffer(len(DATA)) buf.setslice(0, DATA) else: buf = StringBuffer(DATA) return buf
def _init(self, space): if self.buffer_size <= 0: raise oefmt(space.w_ValueError, "buffer size must be strictly positive") self.buffer = ByteBuffer(self.buffer_size) self.lock = TryLock(space) try: self._raw_tell(space) except OperationError: pass
def QueryValueEx(space, w_hkey, w_subkey): """ value,type_id = QueryValueEx(key, value_name) - Retrieves the type and data for a specified value name associated with an open registry key. key is an already open key, or any one of the predefined HKEY_* constants. value_name is a string indicating the value to query""" hkey = hkey_w(w_hkey, space) if space.is_w(w_subkey, space.w_None): subkey = None else: subkey = space.utf8_w(w_subkey).decode('utf8') null_dword = lltype.nullptr(rwin32.LPDWORD.TO) with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: c_subkey = rffi.cast(rffi.CWCHARP, wide_subkey) with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as dataSize: ret = rwinreg.RegQueryValueExW(hkey, c_subkey, null_dword, null_dword, None, dataSize) bufSize = intmask(dataSize[0]) if ret == rwinreg.ERROR_MORE_DATA: # Copy CPython behaviour, otherwise bufSize can be 0 bufSize = 256 elif ret != 0: raiseWindowsError(space, ret, 'RegQueryValue') while True: dataBuf = ByteBuffer(bufSize) dataBufP = rffi.cast(rffi.CWCHARP, dataBuf.get_raw_address()) with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retType: ret = rwinreg.RegQueryValueExW(hkey, c_subkey, null_dword, retType, dataBufP, dataSize) if ret == rwinreg.ERROR_MORE_DATA: # Resize and retry bufSize *= 2 dataSize[0] = rffi.cast(rwin32.DWORD, bufSize) continue if ret != 0: raiseWindowsError(space, ret, 'RegQueryValueEx') length = intmask(dataSize[0]) return space.newtuple([ convert_from_regdata(space, dataBuf, length, retType[0]), space.newint(intmask(retType[0])), ])
def _init(self, space): if self.buffer_size <= 0: raise oefmt(space.w_ValueError, "buffer size must be strictly positive") if space.config.translation.split_gc_address_space: # When using split GC address space, it is not possible to get the # raw address of a GC buffer. Therefore we use a buffer backed by # raw memory. self.buffer = RawByteBuffer(self.buffer_size) else: # TODO: test whether using the raw buffer is faster self.buffer = ByteBuffer(self.buffer_size) self.lock = TryLock(space) try: self._raw_tell(space) except OperationError: pass
def read_console_wide(space, handle, maxlen): """ Make a blocking call to ReadConsoleW, returns wchar-encoded bytes """ err = 0 sig = 0 # Windows uses a 16-bit wchar_t, we mimic that with bytes buf = ByteBuffer((maxlen + 2) * 2) addr = buf.get_raw_address() off = 0 # offset from the beginning of buf, in wchar # readlen is in 16 bits, readlen_b is in 8-bit bytes readlen = readlen_b = 0 bufsize = BUFSIZ with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as n: while readlen_b < maxlen: neg_one = rffi.cast(rwin32.DWORD, -1) n[0] = neg_one length = min(maxlen - off, bufsize) rwin32.SetLastError_saved(0) res = rwin32.ReadConsoleW( handle, rffi.cast(rwin32.LPWSTR, rffi.ptradd(addr, readlen_b)), length, n, rffi.cast(rwin32.LPVOID, 0)) nread = intmask(n[0]) err = rwin32.GetLastError_saved() if not res: break if nread == -1 and err == rwin32.ERROR_OPERATION_ABORTED: break if nread == 0: if err != rwin32.ERROR_OPERATION_ABORTED: break err = 0 # This will only catch CTRL-C on the main thread sleep(space, space.newfloat(0.1)) continue readlen += nread readlen_b = 2 * readlen # We didn't manage to read the whole buffer # don't try again as it will just block if nread < length: break if buf.getitem(readlen_b - 2) == '\n': # We read a new line break # If the buffer ends with a high surrogate, take an extra character. if (readlen_b + 1) >= maxlen: with lltype.scoped_alloc(rwin32.LPWORD.TO, 1) as char_type: ptr = rffi.cast(rffi.CWCHARP, rffi.ptradd(addr, +1)) rwin32.GetStringTypeW(rwin32.CT_CTYPE3, ptr, 1, char_type) if intmask(char_type[0]) == intmask( rwin32.C3_HIGHSURROGATE): readlen_b += 2 break if err: raise OperationError(space.w_WindowsError, space.newint(err)) if readlen_b <= 0 or buf.getitem(0) == '\x1a': return '' else: return buf.getslice(0, 1, readlen_b)
def bytebuffer(space, length): return space.newbuffer(ByteBuffer(length))
def _read_generic(self, space, n): """Generic read function: read from the stream until enough bytes are read, or until an EOF occurs or until read() would block.""" # Must run with the lock held! current_size = self._readahead() if n <= current_size: return self._read_fast(n) result_buffer = ByteBuffer(n) remaining = n written = 0 if current_size: result_buffer.setslice( written, self.buffer[self.pos:self.pos + current_size]) remaining -= current_size written += current_size self.pos += current_size # Flush the write buffer if necessary if self.writable: self._flush_and_rewind_unlocked(space) self._reader_reset_buf() # Read whole blocks, and don't buffer them while remaining > 0: r = self.buffer_size * (remaining // self.buffer_size) if r == 0: break try: size = self._raw_read(space, result_buffer, written, r) except BlockingIOError: if written == 0: return None size = 0 if size == 0: return result_buffer[0:written] remaining -= size written += size self.pos = 0 self.raw_pos = 0 self.read_end = 0 while remaining > 0 and self.read_end < self.buffer_size: try: size = self._fill_buffer(space) except BlockingIOError: # EOF or read() would block if written == 0: return None size = 0 if size == 0: break if remaining > 0: if size > remaining: size = remaining result_buffer.setslice(written, self.buffer[self.pos:self.pos + size]) self.pos += size written += size remaining -= size return result_buffer[0:written]
def test_getslice_shortcut(self): buf = ByteBuffer(4) buf.setslice(0, b"data") buf.getitem = None assert buf.getslice(0, 2, 1, 2) == b"da" # no crash!
def test_typed_read(self): data = struct.pack('HH', 0x1234, 0x5678) buf = ByteBuffer(4) buf.setslice(0, data) assert buf.typed_read(rffi.USHORT, 0) == 0x1234 assert buf.typed_read(rffi.USHORT, 2) == 0x5678
def test_typed_write(self): buf = ByteBuffer(4) buf.typed_write(rffi.USHORT, 0, 0x1234) buf.typed_write(rffi.USHORT, 2, 0x5678) expected = struct.pack('HH', 0x1234, 0x5678) assert buf.as_str() == expected
def bytebuffer(space, length): return SimpleView(ByteBuffer(length)).wrap(space)
def f(x): buf = ByteBuffer(8) return direct_write(buf), typed_write(buf)
def f(x): buf = ByteBuffer(8) return direct_read(buf), typed_read(buf)
def EnumValue(space, w_hkey, index): """tuple = EnumValue(key, index) - Enumerates values of an open registry key. key is an already open key, or any one of the predefined HKEY_* constants. index is an integer that identifies the index of the value to retrieve. The function retrieves the name of one subkey each time it is called. It is typically called repeatedly, until an EnvironmentError exception is raised, indicating no more values. The result is a tuple of 3 items: value_name is a string that identifies the value. value_data is an object that holds the value data, and whose type depends on the underlying registry type. data_type is an integer that identifies the type of the value data.""" hkey = hkey_w(w_hkey, space) null_dword = lltype.nullptr(rwin32.LPDWORD.TO) with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as valueSize: with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as dataSize: ret = rwinreg.RegQueryInfoKeyW(hkey, None, null_dword, null_dword, null_dword, null_dword, null_dword, null_dword, valueSize, dataSize, null_dword, lltype.nullptr(rwin32.PFILETIME.TO)) if ret != 0: raiseWindowsError(space, ret, 'RegQueryInfoKey') # include null terminators valueSize[0] += 1 dataSize[0] += 1 bufDataSize = intmask(dataSize[0]) bufValueSize = intmask(valueSize[0] * 2) valueBuf = ByteBuffer(bufValueSize) valueBufP = rffi.cast(rffi.CWCHARP, valueBuf.get_raw_address()) while True: dataBuf = ByteBuffer(bufDataSize) dataBufP = rffi.cast(rffi.CCHARP, dataBuf.get_raw_address()) with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retType: ret = rwinreg.RegEnumValueW(hkey, index, valueBufP, valueSize, null_dword, retType, dataBufP, dataSize) if ret == rwinreg.ERROR_MORE_DATA: # Resize and retry. For dynamic keys, the value of # dataSize[0] is useless (always 1) so do what CPython # does, except they use 2 instead of 4 bufDataSize *= 4 dataSize[0] = rffi.cast(rwin32.DWORD, bufDataSize) valueSize[0] = rffi.cast(rwin32.DWORD, bufValueSize) continue if ret != 0: raiseWindowsError(space, ret, 'RegEnumValue') length = intmask(dataSize[0]) vlen = (intmask(valueSize[0]) + 1) * 2 utf8v, lenv = wbuf_to_utf8(space, valueBuf[0:vlen]) return space.newtuple([ space.newtext(utf8v, lenv), convert_from_regdata(space, dataBuf, length, retType[0]), space.newint(intmask(retType[0])), ])