Exemplo n.º 1
0
        /// <summary>Initializes a new instance of the <see cref="T:AlternateDataStreamInfo"/> class.</summary>
        /// <param name="stream">The <see cref="T:NativeMethods.Win32StreamId"/> stream ID.</param>
        /// <param name="transaction"></param>
        /// <param name="path">The path to an existing file or directory.</param>
        /// <param name="name">The originalName of the stream.</param>
        /// <param name="originalName">The alternative data stream name originally specified by the user.</param>
        /// <param name="isFolder">Specifies that <paramref name="path"/> is a file or directory. <c>null</c> to retrieve automatically.</param>
        /// <param name="isFullPath">
        ///    <para><c>true</c> <paramref name="path"/> is an absolute path. Unicode prefix is applied.</para>
        ///    <para><c>false</c> <paramref name="path"/> will be checked and resolved to an absolute path. Unicode prefix is applied.</para>
        ///    <para><c>null</c> <paramref name="path"/> is already an absolute path with Unicode prefix. Use as is.</para>
        /// </param>
        private AlternateDataStreamInfo(NativeMethods.Win32StreamId stream, KernelTransaction transaction, string path, string name, string originalName, bool?isFolder, bool?isFullPath)
        {
            if (Utils.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            _isFullPath = isFullPath;

            Transaction = transaction;

            OriginalName = originalName;
            Name         = name ?? string.Empty;

            Attributes = stream.StreamAttributes;
            Type       = stream.StreamType;
            Size       = (long)stream.StreamSize;

            FullName = path + Name;

            if (isFolder == null)
            {
                FileAttributes attrs = File.GetAttributesExInternal <FileAttributes>(transaction, LongFullName, null);
                IsDirectory = (attrs & FileAttributes.Directory) == FileAttributes.Directory;
            }
            else
            {
                IsDirectory = (bool)isFolder;
            }
        }
Exemplo n.º 2
0
        internal static IEnumerable <AlternateDataStreamInfo> EnumerateStreamsInternal(bool?isFolder, KernelTransaction transaction, SafeFileHandle safeHandle, string path, string originalName, StreamType?streamType, bool?isFullPath)
        {
            string pathLp = null;

            bool callerHandle = safeHandle != null;

            if (!callerHandle)
            {
                pathLp = isFullPath == null
               ? path
               : (bool)isFullPath
                  ? Path.GetLongPathInternal(path, false, false, false, false)
                  : Path.GetFullPathInternal(transaction, path, true, false, false, true, false, true, false);

                if (isFolder == null)
                {
                    FileAttributes attrs = File.GetAttributesExInternal <FileAttributes>(transaction, pathLp, null);
                    isFolder = (attrs & FileAttributes.Directory) == FileAttributes.Directory;
                }

                safeHandle = File.CreateFileInternal(transaction, pathLp,
                                                     (bool)isFolder
                  ? ExtendedFileAttributes.BackupSemantics
                  : ExtendedFileAttributes.Normal, null,
                                                     FileMode.Open, FileSystemRights.Read, FileShare.ReadWrite, false, null);
            }
            else
            {
                NativeMethods.IsValidHandle(safeHandle);
            }


            try
            {
                using (new PrivilegeEnabler(Privilege.Backup))
                    using (SafeGlobalMemoryBufferHandle safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                    {
                        Type   typeWin32Stream = typeof(NativeMethods.Win32StreamId);
                        uint   sizeOfType      = (uint)Marshal.SizeOf(typeWin32Stream);
                        uint   numberOfBytesRead;
                        IntPtr context;

                        bool doLoop = true;
                        while (doLoop)
                        {
                            if (!NativeMethods.BackupRead(safeHandle, safeBuffer, sizeOfType, out numberOfBytesRead, false, true, out context))
                            {
                                // Throws IOException.
                                NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp, true);
                            }

                            doLoop = numberOfBytesRead == sizeOfType;
                            if (doLoop)
                            {
                                string streamName       = null;
                                string streamSearchName = null;


                                // CA2001:AvoidCallingProblematicMethods

                                IntPtr buffer     = IntPtr.Zero;
                                bool   successRef = false;
                                safeBuffer.DangerousAddRef(ref successRef);

                                // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                                if (successRef)
                                {
                                    buffer = safeBuffer.DangerousGetHandle();
                                }

                                safeBuffer.DangerousRelease();

                                if (buffer == IntPtr.Zero)
                                {
                                    NativeError.ThrowException(Resources.HandleDangerousRef);
                                }

                                // CA2001:AvoidCallingProblematicMethods


                                NativeMethods.Win32StreamId stream = Utils.MarshalPtrToStructure <NativeMethods.Win32StreamId>(0, buffer);

                                if (streamType == null || stream.StreamType == streamType)
                                {
                                    if (stream.StreamNameSize > 0)
                                    {
                                        if (!NativeMethods.BackupRead(safeHandle, safeBuffer, stream.StreamNameSize, out numberOfBytesRead, false, true, out context))
                                        {
                                            // Throws IOException.
                                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp, true);
                                        }


                                        // CA2001:AvoidCallingProblematicMethods

                                        buffer     = IntPtr.Zero;
                                        successRef = false;
                                        safeBuffer.DangerousAddRef(ref successRef);

                                        // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                                        if (successRef)
                                        {
                                            buffer = safeBuffer.DangerousGetHandle();
                                        }

                                        safeBuffer.DangerousRelease();

                                        if (buffer == IntPtr.Zero)
                                        {
                                            NativeError.ThrowException(Resources.HandleDangerousRef);
                                        }

                                        // CA2001:AvoidCallingProblematicMethods


                                        streamName = Marshal.PtrToStringUni(buffer, (int)numberOfBytesRead / 2);

                                        // Returned stream name format: ":streamName:$DATA"
                                        streamSearchName = streamName.TrimStart(Path.StreamSeparatorChar).Replace(Path.StreamSeparator + "$DATA", string.Empty);
                                    }

                                    if (originalName == null || (streamSearchName != null && streamSearchName.Equals(originalName, StringComparison.OrdinalIgnoreCase)))
                                    {
                                        yield return(new AlternateDataStreamInfo(stream, transaction, pathLp ?? path, streamName, originalName ?? streamSearchName, isFolder, isFullPath));
                                    }
                                }

                                uint lo, hi;
                                doLoop = !NativeMethods.BackupSeek(safeHandle, uint.MinValue, uint.MaxValue, out lo, out hi, out context);
                            }
                        }

                        // MSDN: To release the memory used by the data structure,
                        // call BackupRead with the bAbort parameter set to TRUE when the backup operation is complete.
                        if (!NativeMethods.BackupRead(safeHandle, safeBuffer, 0, out numberOfBytesRead, true, false, out context))
                        {
                            // Throws IOException.
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp, true);
                        }
                    }
            }
            finally
            {
                // Handle is ours, dispose.
                if (!callerHandle && safeHandle != null)
                {
                    safeHandle.Close();
                }
            }
        }