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 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"); } }
/// <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 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>(); } }
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)); })); }