public static extern bool BackupRead(SafeFileHandle hFile, ref Win32StreamId pBuffer, int numberOfBytesToRead, out int numberOfBytesRead, [MarshalAs(UnmanagedType.Bool)] bool abort, [MarshalAs(UnmanagedType.Bool)] bool processSecurity, ref IntPtr context);
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; }
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); }