コード例 #1
0
 public void ReadIntInCapacityPasses()
 {
     using (var buffer = new HeapBuffer(4))
     {
         var reader = new CheckedReader(buffer);
         reader.ByteOffset = buffer.ByteCapacity - 4;
         reader.ReadInt();
     }
 }
コード例 #2
0
 public void ReadLongInCapacityPasses()
 {
     using (var buffer = new HeapBuffer(8))
     {
         var reader = new CheckedReader(buffer);
         reader.ByteOffset = buffer.ByteCapacity - 8;
         reader.ReadLong();
     }
 }
コード例 #3
0
        /// <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;
            }));
        }
コード例 #4
0
        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));;
        }
コード例 #5
0
        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>();
            }
        }
コード例 #6
0
        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>();
            }
        }
コード例 #7
0
        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");
            }
        }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
        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}");
            }
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
        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);
            }
        }
コード例 #12
0
        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>();
                }
            }
        }
コード例 #13
0
        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");
            }
        }
コード例 #14
0
        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));
            }));
        }
コード例 #15
0
        /// <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));
            }));
        }