コード例 #1
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;
            }));
        }
コード例 #2
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));
            }));
        }
コード例 #3
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));
            }));
        }