public static IList<Win32StreamInfo> ListStreams(string filePath) {
            if (string.IsNullOrEmpty(filePath)) {
                throw new ArgumentNullException("filePath");
            }
            if (-1 != filePath.IndexOfAny(Path.GetInvalidPathChars())) {
                throw new ArgumentException(Resources.Error_InvalidFileChars, "filePath");
            }

            var result = new List<Win32StreamInfo>();

            using (
                var hFile = SafeCreateFile(filePath, NativeFileAccess.GenericRead, FileShare.Read, IntPtr.Zero, FileMode.Open,
                    NativeFileAttributesAndFlags.BackupSemantics, IntPtr.Zero)) {
                using (var hName = new StreamName()) {
                    if (!hFile.IsInvalid) {
                        var streamId = new Win32StreamId();
                        var dwStreamHeaderSize = Marshal.SizeOf(streamId);
                        var finished = false;
                        var context = IntPtr.Zero;
                        int bytesRead;
                        string name;

                        try {
                            while (!finished) {
                                // Read the next stream header:
                                if (!Kernel32.BackupRead(hFile, ref streamId, dwStreamHeaderSize, out bytesRead, false, false, ref context)) {
                                    finished = true;
                                } else if (dwStreamHeaderSize != bytesRead) {
                                    finished = true;
                                } else {
                                    // Read the stream name:
                                    if (0 >= streamId.StreamNameSize) {
                                        name = null;
                                    } else {
                                        hName.EnsureCapacity(streamId.StreamNameSize);
                                        if (!Kernel32.BackupRead(hFile, hName.MemoryBlock, streamId.StreamNameSize, out bytesRead, false, false, ref context)) {
                                            name = null;
                                            finished = true;
                                        } else {
                                            // Unicode chars are 2 bytes:
                                            name = hName.ReadStreamName(bytesRead >> 1);
                                        }
                                    }

                                    // Add the stream info to the result:
                                    if (!string.IsNullOrEmpty(name)) {
                                        result.Add(new Win32StreamInfo {
                                            StreamType = (FileStreamType)streamId.StreamId,
                                            StreamAttributes = (FileStreamAttributes)streamId.StreamAttributes,
                                            StreamSize = streamId.Size,
                                            StreamName = name
                                        });
                                    }

                                    // Skip the contents of the stream:
                                    int bytesSeekedLow,
                                        bytesSeekedHigh;

                                    if (!finished &&
                                        !Kernel32.BackupSeek(hFile, (int)(streamId.Size & 0xffffffff), (int)(streamId.Size >> 32), out bytesSeekedLow,
                                            out bytesSeekedHigh, ref context)) {
                                        finished = true;
                                    }
                                }
                            }
                        } finally {
                            // Abort the backup:
                            Kernel32.BackupRead(hFile, hName.MemoryBlock, 0, out bytesRead, true, false, ref context);
                        }
                    }
                }
            }

            return result;
        }
Пример #2
0
        public static IList <Win32StreamInfo> ListStreams(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException("filePath");
            }
            if (-1 != filePath.IndexOfAny(Path.GetInvalidPathChars()))
            {
                throw new ArgumentException(Resources.Error_InvalidFileChars, "filePath");
            }

            var result = new List <Win32StreamInfo>();

            using (
                var hFile = SafeCreateFile(filePath, NativeFileAccess.GenericRead, FileShare.Read, IntPtr.Zero, FileMode.Open,
                                           NativeFileAttributesAndFlags.BackupSemantics, IntPtr.Zero)) {
                using (var hName = new StreamName()) {
                    if (!hFile.IsInvalid)
                    {
                        var    streamId           = new Win32StreamId();
                        var    dwStreamHeaderSize = Marshal.SizeOf(streamId);
                        var    finished           = false;
                        var    context            = IntPtr.Zero;
                        int    bytesRead;
                        string name;

                        try {
                            while (!finished)
                            {
                                // Read the next stream header:
                                if (!Kernel32.BackupRead(hFile, ref streamId, dwStreamHeaderSize, out bytesRead, false, false, ref context))
                                {
                                    finished = true;
                                }
                                else if (dwStreamHeaderSize != bytesRead)
                                {
                                    finished = true;
                                }
                                else
                                {
                                    // Read the stream name:
                                    if (0 >= streamId.StreamNameSize)
                                    {
                                        name = null;
                                    }
                                    else
                                    {
                                        hName.EnsureCapacity(streamId.StreamNameSize);
                                        if (!Kernel32.BackupRead(hFile, hName.MemoryBlock, streamId.StreamNameSize, out bytesRead, false, false, ref context))
                                        {
                                            name     = null;
                                            finished = true;
                                        }
                                        else
                                        {
                                            // Unicode chars are 2 bytes:
                                            name = hName.ReadStreamName(bytesRead >> 1);
                                        }
                                    }

                                    // Add the stream info to the result:
                                    if (!string.IsNullOrEmpty(name))
                                    {
                                        result.Add(new Win32StreamInfo {
                                            StreamType       = (FileStreamType)streamId.StreamId,
                                            StreamAttributes = (FileStreamAttributes)streamId.StreamAttributes,
                                            StreamSize       = streamId.Size,
                                            StreamName       = name
                                        });
                                    }

                                    // Skip the contents of the stream:
                                    int bytesSeekedLow,
                                        bytesSeekedHigh;

                                    if (!finished &&
                                        !Kernel32.BackupSeek(hFile, (int)(streamId.Size & 0xffffffff), (int)(streamId.Size >> 32), out bytesSeekedLow,
                                                             out bytesSeekedHigh, ref context))
                                    {
                                        finished = true;
                                    }
                                }
                            }
                        } finally {
                            // Abort the backup:
                            Kernel32.BackupRead(hFile, hName.MemoryBlock, 0, out bytesRead, true, false, ref context);
                        }
                    }
                }
            }

            return(result);
        }