public void ReadIntInCapacityPasses() { using (var buffer = new HeapBuffer(4)) { var reader = new CheckedReader(buffer); reader.ByteOffset = buffer.ByteCapacity - 4; reader.ReadInt(); } }
public void ReadLongInCapacityPasses() { using (var buffer = new HeapBuffer(8)) { var reader = new CheckedReader(buffer); reader.ByteOffset = buffer.ByteCapacity - 8; reader.ReadLong(); } }
/// <summary> /// Get the list of data streams for the given handle. /// </summary> public static IEnumerable <StreamInformation> GetStreamInformationByHandle(SafeFileHandle fileHandle) { // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364406.aspx // typedef struct _FILE_STREAM_INFO // { // DWORD NextEntryOffset; // DWORD StreamNameLength; // LARGE_INTEGER StreamSize; // LARGE_INTEGER StreamAllocationSize; // WCHAR StreamName[1]; // } FILE_STREAM_INFO, *PFILE_STREAM_INFO; return(BufferHelper.CachedInvoke <IEnumerable <StreamInformation>, HeapBuffer>((buffer) => { unsafe { while (!Direct.GetFileInformationByHandleEx(fileHandle, FILE_INFO_BY_HANDLE_CLASS.FileStreamInfo, buffer.VoidPointer, checked ((uint)buffer.ByteCapacity))) { WindowsError error = ErrorHelper.GetLastError(); switch (error) { case WindowsError.ERROR_HANDLE_EOF: // No streams return Enumerable.Empty <StreamInformation>(); case WindowsError.ERROR_MORE_DATA: buffer.EnsureByteCapacity(buffer.ByteCapacity * 2); break; default: throw ErrorHelper.GetIoExceptionForError(error); } } } var infos = new List <StreamInformation>(); var reader = new CheckedReader(buffer); uint offset = 0; do { reader.ByteOffset = offset; offset = reader.ReadUint(); uint nameLength = reader.ReadUint(); infos.Add(new StreamInformation { Size = reader.ReadUlong(), AllocationSize = reader.ReadUlong(), Name = reader.ReadString((int)(nameLength / 2)) }); } while (offset != 0); return infos; })); }
public static IEnumerable <ObjectInformation> GetDirectoryEntries(SafeDirectoryObjectHandle directoryHandle) { List <ObjectInformation> infos = new List <ObjectInformation>(); BufferHelper.CachedInvoke((StringBuffer buffer) => { buffer.EnsureCharCapacity(1024); uint context = 0; uint returnLength; NTSTATUS status; do { status = Direct.NtQueryDirectoryObject( DirectoryHandle: directoryHandle, Buffer: buffer, Length: (uint)buffer.ByteCapacity, ReturnSingleEntry: false, RestartScan: false, Context: ref context, ReturnLength: out returnLength); if (status != NTSTATUS.STATUS_SUCCESS && status != NTSTATUS.STATUS_MORE_ENTRIES) { break; } CheckedReader reader = new CheckedReader(buffer); do { UNICODE_STRING name = reader.ReadStruct <UNICODE_STRING>(); if (name.Length == 0) { break; } UNICODE_STRING type = reader.ReadStruct <UNICODE_STRING>(); infos.Add(new ObjectInformation { Name = name.ToString(), TypeName = type.ToString() }); } while (true); } while (status == NTSTATUS.STATUS_MORE_ENTRIES); if (status != NTSTATUS.STATUS_SUCCESS) { throw ErrorHelper.GetIoExceptionForNTStatus(status); } }); return(infos.OrderBy(i => i.Name));; }
public void SetOffsetPastEndOfStreamFails() { using (var buffer = new HeapBuffer(0)) { var reader = new CheckedReader(buffer); reader.ByteOffset = buffer.ByteCapacity; Action action = () => reader.ByteOffset = buffer.ByteCapacity + 1; action.Should().Throw <ArgumentOutOfRangeException>(); } }
public void ReadStringPastEndFails() { using (var buffer = new HeapBuffer(1)) { var reader = new CheckedReader(buffer); Action action = () => reader.ReadString(1); reader.ByteOffset = buffer.ByteCapacity - 1; action.Should().Throw <ArgumentOutOfRangeException>(); } }
public void ReadAlignedString() { using (var buffer = new HeapBuffer(4)) { buffer[0] = 65; buffer[1] = 0; buffer[2] = 66; buffer[3] = 0; var reader = new CheckedReader(buffer); reader.ReadString(1).Should().Be("A"); reader.ReadString(1).Should().Be("B"); } }
public void ReadTwoLongs() { using (var buffer = new HeapBuffer(16)) { for (ulong i = 0; i < 16; i++) { buffer[i] = (byte)(i + 1); } var reader = new CheckedReader(buffer); reader.ReadLong().Should().Be(0x0807060504030201); reader.ReadLong().Should().Be(0x100F0E0D0C0B0A09); } }
public void ReadLong(ulong offset, long expected) { using (var buffer = new HeapBuffer(16)) { for (ulong i = 0; i < 16; i++) { buffer[i] = (byte)(i + 1); } var reader = new CheckedReader(buffer); reader.ByteOffset = offset; reader.ReadLong().Should().Be(expected, $"offset is {offset}"); } }
public void ReadTwoInts() { using (var buffer = new HeapBuffer(8)) { for (ulong i = 0; i < 8; i++) { buffer[i] = (byte)(i + 1); } var reader = new CheckedReader(buffer); reader.ReadInt().Should().Be(0x04030201); reader.ReadInt().Should().Be(0x08070605); } }
public void ReadTwoShorts() { using (var buffer = new HeapBuffer(4)) { for (ulong i = 0; i < 4; i++) { buffer[i] = (byte)(i + 1); } var reader = new CheckedReader(buffer); reader.ReadShort().Should().Be(0x0201); reader.ReadShort().Should().Be(0x0403); } }
public void ReadLongPastCapacityFails() { using (var buffer = new HeapBuffer(sizeof(long))) { var reader = new CheckedReader(buffer); Action action = () => reader.ReadLong(); for (uint i = 1; i < sizeof(long); i++) { reader.ByteOffset = buffer.ByteCapacity - i; action.Should().Throw <System.IO.EndOfStreamException>(); } } }
public void ReadUnalignedString() { using (var buffer = new HeapBuffer(5)) { buffer[0] = 67; buffer[1] = 65; buffer[2] = 0; buffer[3] = 66; buffer[4] = 0; var reader = new CheckedReader(buffer); reader.ByteOffset = 1; reader.ReadString(1).Should().Be("A"); reader.ReadString(1).Should().Be("B"); } }
private static string GetFileInformationString(SafeFileHandle fileHandle, FILE_INFORMATION_CLASS fileInformationClass) { return(BufferHelper.CachedInvoke((StringBuffer buffer) => { NTSTATUS status = NTSTATUS.STATUS_BUFFER_OVERFLOW; uint nameLength = 260 * sizeof(char); IO_STATUS_BLOCK ioStatus; var reader = new CheckedReader(buffer); while (status == NTSTATUS.STATUS_BUFFER_OVERFLOW) { // Add space for the FileNameLength buffer.EnsureByteCapacity(nameLength + sizeof(uint)); unsafe { status = Direct.NtQueryInformationFile( FileHandle: fileHandle, IoStatusBlock: out ioStatus, FileInformation: buffer.VoidPointer, Length: checked ((uint)buffer.ByteCapacity), FileInformationClass: fileInformationClass); } if (status == NTSTATUS.STATUS_SUCCESS || status == NTSTATUS.STATUS_BUFFER_OVERFLOW) { reader.ByteOffset = 0; nameLength = reader.ReadUint(); } } if (status != NTSTATUS.STATUS_SUCCESS) { throw ErrorHelper.GetIoExceptionForNTStatus(status); } // The string isn't null terminated so we have to explicitly pass the size return reader.ReadString(checked ((int)nameLength) / sizeof(char)); })); }
/// <summary> /// Gets the file name from the given handle. This uses GetFileInformationByHandleEx, which does not give back the drive /// name for the path- but is available from Windows Store apps. /// </summary> public static string GetFileNameByHandle(SafeFileHandle fileHandle) { return(BufferHelper.CachedInvoke((HeapBuffer buffer) => { unsafe { while (!Direct.GetFileInformationByHandleEx( fileHandle, FILE_INFO_BY_HANDLE_CLASS.FileNameInfo, buffer.VoidPointer, checked ((uint)buffer.ByteCapacity))) { WindowsError error = ErrorHelper.GetLastError(); if (error != WindowsError.ERROR_MORE_DATA) { throw ErrorHelper.GetIoExceptionForError(error); } buffer.EnsureByteCapacity(buffer.ByteCapacity * 2); } } var reader = new CheckedReader(buffer); return reader.ReadString((int)(reader.ReadUint() / 2)); })); }