Exemplo n.º 1
0
        /// <summary>Refreshes the state of the object.</summary>
        public void Refresh()
        {
            Reset();

            // ChangeErrorMode is for the Win32 SetThreadErrorMode() method, used to suppress possible pop-ups.
            using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
            {
                int lastError = (int)Win32Errors.NO_ERROR;

                #region Get size information.

                if (_initGetSpaceInfo)
                {
                    ulong freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes;

                    if (!NativeMethods.GetDiskFreeSpaceEx(DriveName, out freeBytesAvailable, out totalNumberOfBytes, out totalNumberOfFreeBytes))
                    {
                        lastError = Marshal.GetLastWin32Error();
                    }

                    else
                    {
                        FreeBytesAvailable     = freeBytesAvailable;
                        TotalNumberOfBytes     = totalNumberOfBytes;
                        TotalNumberOfFreeBytes = totalNumberOfFreeBytes;
                    }

                    if (!_continueOnAccessError && (lastError != Win32Errors.NO_ERROR && lastError != Win32Errors.ERROR_NOT_READY))
                    {
                        NativeError.ThrowException(DriveName);
                    }
                }

                #endregion // Get size information.

                #region Get cluster information.

                if (_initGetClusterInfo)
                {
                    uint sectorsPerCluster, bytesPerSector, numberOfFreeClusters, totalNumberOfClusters;

                    if (!NativeMethods.GetDiskFreeSpace(DriveName, out sectorsPerCluster, out bytesPerSector, out numberOfFreeClusters, out totalNumberOfClusters))
                    {
                        lastError = Marshal.GetLastWin32Error();
                    }

                    else
                    {
                        BytesPerSector        = bytesPerSector;
                        NumberOfFreeClusters  = numberOfFreeClusters;
                        SectorsPerCluster     = sectorsPerCluster;
                        TotalNumberOfClusters = totalNumberOfClusters;
                    }

                    if (!_continueOnAccessError && (lastError != Win32Errors.NO_ERROR && lastError != Win32Errors.ERROR_NOT_READY))
                    {
                        NativeError.ThrowException(DriveName);
                    }
                }

                #endregion // Get cluster information.
            }
        }
Exemplo n.º 2
0
        internal static IEnumerable <DriveInfo> EnumerateLogicalDrivesCore(bool fromEnvironment, bool isReady)
        {
            #region Get from Environment

            if (fromEnvironment)
            {
                IEnumerable <string> drivesEnv = isReady
               ? Environment.GetLogicalDrives().Where(ld => File.ExistsCore(true, null, ld, PathFormat.FullPath))
               : Environment.GetLogicalDrives().Select(ld => ld);

                foreach (string drive in drivesEnv)
                {
                    // Optionally check Drive .IsReady.
                    if (isReady)
                    {
                        if (File.ExistsCore(true, null, drive, PathFormat.FullPath))
                        {
                            yield return(new DriveInfo(drive));
                        }
                    }
                    else
                    {
                        yield return(new DriveInfo(drive));
                    }
                }

                yield break;
            }

            #endregion // Get from Environment

            #region Get through NativeMethod

            uint lastError = NativeMethods.GetLogicalDrives();
            if (lastError == Win32Errors.ERROR_SUCCESS)
            {
                NativeError.ThrowException((int)lastError);
            }

            uint drives = lastError;
            int  count  = 0;
            while (drives != 0)
            {
                if ((drives & 1) != 0)
                {
                    ++count;
                }

                drives >>= 1;
            }

            string[] result = new string[count];
            char[]   root   = { 'A', Path.VolumeSeparatorChar };

            drives = lastError;
            count  = 0;

            while (drives != 0)
            {
                if ((drives & 1) != 0)
                {
                    string drive = new string(root);

                    if (isReady)
                    {
                        // Optionally check Drive .IsReady.
                        if (File.ExistsCore(true, null, drive, PathFormat.FullPath))
                        {
                            yield return(new DriveInfo(drive));
                        }
                    }
                    else
                    {
                        // Ready or not.
                        yield return(new DriveInfo(drive));
                    }

                    result[count++] = drive;
                }

                drives >>= 1;
                root[0]++;
            }

            #endregion // Get through NativeMethod
        }
Exemplo n.º 3
0
        internal static IEnumerable <FileIdBothDirectoryInfo> EnumerateFileIdBothDirectoryInfoCore(KernelTransaction transaction, SafeFileHandle safeHandle, string path, FileShare shareMode, bool continueOnException, PathFormat pathFormat)
        {
            if (!NativeMethods.IsAtLeastWindowsVista)
            {
                throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher);
            }

            bool callerHandle = safeHandle != null;

            if (!callerHandle)
            {
                if (Utils.IsNullOrWhiteSpace(path))
                {
                    throw new ArgumentNullException("path");
                }

                string pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);

                safeHandle = File.CreateFileCore(transaction, pathLp, ExtendedFileAttributes.BackupSemantics, null, FileMode.Open, FileSystemRights.ReadData, shareMode, true, PathFormat.LongFullPath);
            }


            try
            {
                if (!NativeMethods.IsValidHandle(safeHandle, Marshal.GetLastWin32Error(), !continueOnException))
                {
                    yield break;
                }

                var fileNameOffset = (int)Marshal.OffsetOf(typeof(NativeMethods.FILE_ID_BOTH_DIR_INFO), "FileName");

                using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                {
                    while (true)
                    {
                        if (!NativeMethods.GetFileInformationByHandleEx(safeHandle, NativeMethods.FileInfoByHandleClass.FileIdBothDirectoryInfo, safeBuffer, (uint)safeBuffer.Capacity))
                        {
                            uint lastError = (uint)Marshal.GetLastWin32Error();
                            switch (lastError)
                            {
                            case Win32Errors.ERROR_SUCCESS:
                            case Win32Errors.ERROR_NO_MORE_FILES:
                            case Win32Errors.ERROR_HANDLE_EOF:
                                yield break;

                            case Win32Errors.ERROR_MORE_DATA:
                                continue;

                            default:
                                NativeError.ThrowException(lastError, path);
                                yield break; // we should never get to this yield break.
                            }
                        }

                        int offset = 0;
                        NativeMethods.FILE_ID_BOTH_DIR_INFO fibdi;
                        do
                        {
                            fibdi = safeBuffer.PtrToStructure <NativeMethods.FILE_ID_BOTH_DIR_INFO>(offset);
                            string fileName = safeBuffer.PtrToStringUni(offset + fileNameOffset, (int)(fibdi.FileNameLength / 2));

                            if (!fileName.Equals(Path.CurrentDirectoryPrefix, StringComparison.OrdinalIgnoreCase) &&
                                !fileName.Equals(Path.ParentDirectoryPrefix, StringComparison.OrdinalIgnoreCase))
                            {
                                yield return(new FileIdBothDirectoryInfo(fibdi, fileName));
                            }

                            offset += fibdi.NextEntryOffset;
                        }while (fibdi.NextEntryOffset != 0);
                    }
                }
            }
            finally
            {
                // Handle is ours, dispose.
                if (!callerHandle && safeHandle != null)
                {
                    safeHandle.Close();
                }
            }
        }
Exemplo n.º 4
0
        internal static IEnumerable <DeviceInfo> EnumerateDevicesCore(string hostName, DeviceGuid deviceGuid, bool getAllProperties)
        {
            if (Utils.IsNullOrWhiteSpace(hostName))
            {
                hostName = Environment.MachineName;
            }


            // CM_Connect_Machine()
            // MSDN Note: Beginning in Windows 8 and Windows Server 2012 functionality to access remote machines has been removed.
            // You cannot access remote machines when running on these versions of Windows.
            // http://msdn.microsoft.com/en-us/library/windows/hardware/ff537948%28v=vs.85%29.aspx


            SafeCmConnectMachineHandle safeMachineHandle;

            var lastError = NativeMethods.CM_Connect_Machine(Host.GetUncName(hostName), out safeMachineHandle);

            NativeMethods.IsValidHandle(safeMachineHandle, lastError);


            var classGuid = new Guid(Utils.GetEnumDescription(deviceGuid));


            // Start at the "Root" of the device tree of the specified machine.

            using (safeMachineHandle)
                using (var safeHandle = NativeMethods.SetupDiGetClassDevsEx(ref classGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.SetupDiGetClassDevsExFlags.Present | NativeMethods.SetupDiGetClassDevsExFlags.DeviceInterface, IntPtr.Zero, hostName, IntPtr.Zero))
                {
                    NativeMethods.IsValidHandle(safeHandle, Marshal.GetLastWin32Error());

                    uint memberInterfaceIndex = 0;
                    var  interfaceStructSize  = (uint)Marshal.SizeOf(typeof(NativeMethods.SP_DEVICE_INTERFACE_DATA));
                    var  dataStructSize       = (uint)Marshal.SizeOf(typeof(NativeMethods.SP_DEVINFO_DATA));


                    // Start enumerating device interfaces.

                    while (true)
                    {
                        var interfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA {
                            cbSize = interfaceStructSize
                        };

                        var success = NativeMethods.SetupDiEnumDeviceInterfaces(safeHandle, IntPtr.Zero, ref classGuid, memberInterfaceIndex++, ref interfaceData);

                        lastError = Marshal.GetLastWin32Error();

                        if (!success)
                        {
                            if (lastError != Win32Errors.NO_ERROR && lastError != Win32Errors.ERROR_NO_MORE_ITEMS)
                            {
                                NativeError.ThrowException(lastError, hostName);
                            }

                            break;
                        }


                        // Create DeviceInfo instance.

                        var diData = new NativeMethods.SP_DEVINFO_DATA {
                            cbSize = dataStructSize
                        };

                        var deviceInfo = new DeviceInfo(hostName)
                        {
                            DevicePath = GetDeviceInterfaceDetail(safeHandle, ref interfaceData, ref diData).DevicePath
                        };


                        if (getAllProperties)
                        {
                            deviceInfo.InstanceId = GetDeviceInstanceId(safeMachineHandle, hostName, diData);

                            SetDeviceProperties(safeHandle, deviceInfo, diData);
                        }

                        else
                        {
                            SetMinimalDeviceProperties(safeHandle, deviceInfo, diData);
                        }


                        yield return(deviceInfo);
                    }
                }
        }
        internal static void EncryptDecryptFileCore(bool isFolder, string path, bool encrypt, PathFormat pathFormat)
        {
            if (pathFormat != PathFormat.LongFullPath)
            {
                path = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);

                pathFormat = PathFormat.LongFullPath;
            }


            // MSDN: If lpFileName specifies a read-only file, the function fails and GetLastError returns ERROR_FILE_READ_ONLY.

            var attrs      = GetAttributesExCore <NativeMethods.WIN32_FILE_ATTRIBUTE_DATA>(null, path, pathFormat, true);
            var isReadOnly = (attrs.dwFileAttributes & FileAttributes.ReadOnly) != 0;

            if (isReadOnly)
            {
                SetAttributesCore(null, isFolder, path, attrs.dwFileAttributes &= ~FileAttributes.ReadOnly, pathFormat);
            }


            // EncryptFile() / DecryptFile()
            // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

            var success   = encrypt ? NativeMethods.EncryptFile(path) : NativeMethods.DecryptFile(path, 0);
            var lastError = Marshal.GetLastWin32Error();


            if (isReadOnly)
            {
                var isHidden = (attrs.dwFileAttributes & FileAttributes.Hidden) != 0;

                // Get most current attributes.
                attrs = GetAttributesExCore <NativeMethods.WIN32_FILE_ATTRIBUTE_DATA>(null, path, pathFormat, true);

                attrs.dwFileAttributes |= FileAttributes.ReadOnly;

                if (isHidden)
                {
                    attrs.dwFileAttributes |= FileAttributes.Hidden;
                }


                SetAttributesCore(null, isFolder, path, attrs.dwFileAttributes, pathFormat);
            }


            if (!success)
            {
                switch ((uint)lastError)
                {
                case Win32Errors.ERROR_ACCESS_DENIED:
                    if (!string.Equals("NTFS", new DriveInfo(path).DriveFormat, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "The drive does not support NTFS encryption: [{0}]", Path.GetPathRoot(path, false)));
                    }

                    break;


                case Win32Errors.ERROR_FILE_READ_ONLY:
                    if (IsDirectory(attrs.dwFileAttributes))
                    {
                        throw new DirectoryReadOnlyException(path);
                    }
                    else
                    {
                        throw new FileReadOnlyException(path);
                    }


                default:
                    if (lastError == Win32Errors.ERROR_FILE_NOT_FOUND && isFolder)
                    {
                        lastError = (int)Win32Errors.ERROR_PATH_NOT_FOUND;
                    }

                    NativeError.ThrowException(lastError, path);
                    break;
                }
            }
        }
        private static void DeleteDirectoryCore(KernelTransaction transaction, string pathLp, bool ignoreReadOnly, bool continueOnNotFound)
        {
startRemoveDirectory:

            var success = transaction == null || !NativeMethods.IsAtLeastWindowsVista

                          // RemoveDirectory() / RemoveDirectoryTransacted()
                          // 2014-09-09: MSDN confirms LongPath usage.

                          // RemoveDirectory on a symbolic link will remove the link itself.

            ? NativeMethods.RemoveDirectory(pathLp)
            : NativeMethods.RemoveDirectoryTransacted(pathLp, transaction.SafeHandle);


            var lastError = Marshal.GetLastWin32Error();

            if (!success)
            {
                switch ((uint)lastError)
                {
                case Win32Errors.ERROR_DIR_NOT_EMPTY:
                    // MSDN: .NET 3.5+: IOException: The directory specified by path is not an empty directory.
                    throw new DirectoryNotEmptyException(pathLp, true);


                case Win32Errors.ERROR_DIRECTORY:
                    // MSDN: .NET 3.5+: DirectoryNotFoundException: Path refers to a file instead of a directory.
                    if (File.ExistsCore(transaction, false, pathLp, PathFormat.LongFullPath))
                    {
                        throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "({0}) {1}", lastError, string.Format(CultureInfo.InvariantCulture, Resources.Target_Directory_Is_A_File, pathLp)));
                    }
                    break;


                case Win32Errors.ERROR_PATH_NOT_FOUND:
                    if (continueOnNotFound)
                    {
                        return;
                    }
                    break;


                case Win32Errors.ERROR_SHARING_VIOLATION:
                    // MSDN: .NET 3.5+: IOException: The directory is being used by another process or there is an open handle on the directory.
                    NativeError.ThrowException(lastError, pathLp);
                    break;


                case Win32Errors.ERROR_ACCESS_DENIED:
                    var attrs           = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA();
                    var dataInitialised = File.FillAttributeInfoCore(transaction, pathLp, ref attrs, false, true);


                    if (File.IsReadOnly(attrs.dwFileAttributes))
                    {
                        // MSDN: .NET 3.5+: IOException: The directory specified by path is read-only.

                        if (ignoreReadOnly)
                        {
                            // Reset directory attributes to Normal.
                            File.SetAttributesCore(transaction, true, pathLp, FileAttributes.Normal, PathFormat.LongFullPath);

                            goto startRemoveDirectory;
                        }


                        // MSDN: .NET 3.5+: IOException: The directory is read-only.
                        throw new DirectoryReadOnlyException(pathLp);
                    }


                    // MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission.
                    if (dataInitialised == Win32Errors.ERROR_SUCCESS)
                    {
                        NativeError.ThrowException(lastError, pathLp);
                    }

                    break;
                }

                // MSDN: .NET 3.5+: IOException:
                // A file with the same name and location specified by path exists.
                // The directory specified by path is read-only, or recursive is false and path is not an empty directory.
                // The directory is the application's current working directory.
                // The directory contains a read-only file.
                // The directory is being used by another process.

                NativeError.ThrowException(lastError, pathLp);
            }
        }
        internal static IEnumerable <FileIdBothDirectoryInfo> EnumerateFileIdBothDirectoryInfoCore(KernelTransaction transaction, SafeFileHandle safeFileHandle, string path, FileShare shareMode, bool continueOnException, PathFormat pathFormat)
        {
            if (!NativeMethods.IsAtLeastWindowsVista)
            {
                throw new PlatformNotSupportedException(new Win32Exception((int)Win32Errors.ERROR_OLD_WIN_VERSION).Message);
            }


            var pathLp = path;

            var callerHandle = null != safeFileHandle;

            if (!callerHandle)
            {
                if (Utils.IsNullOrWhiteSpace(path))
                {
                    throw new ArgumentNullException("path");
                }

                pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);

                safeFileHandle = File.CreateFileCore(transaction, true, pathLp, ExtendedFileAttributes.BackupSemantics, null, FileMode.Open, FileSystemRights.ReadData, shareMode, true, false, PathFormat.LongFullPath);
            }


            try
            {
                if (!NativeMethods.IsValidHandle(safeFileHandle, Marshal.GetLastWin32Error(), !continueOnException))
                {
                    yield break;
                }

                var fileNameOffset = (int)Marshal.OffsetOf(typeof(NativeMethods.FILE_ID_BOTH_DIR_INFO), "FileName");

                using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                {
                    while (true)
                    {
                        var success = NativeMethods.GetFileInformationByHandleEx(safeFileHandle, NativeMethods.FILE_INFO_BY_HANDLE_CLASS.FILE_ID_BOTH_DIR_INFO, safeBuffer, (uint)safeBuffer.Capacity);

                        var lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            switch ((uint)lastError)
                            {
                            case Win32Errors.ERROR_SUCCESS:
                            case Win32Errors.ERROR_NO_MORE_FILES:
                            case Win32Errors.ERROR_HANDLE_EOF:
                                yield break;

                            case Win32Errors.ERROR_MORE_DATA:
                                continue;

                            default:
                                NativeError.ThrowException(lastError, pathLp);

                                // Keep the compiler happy as we never get here.
                                yield break;
                            }
                        }


                        var offset = 0;
                        NativeMethods.FILE_ID_BOTH_DIR_INFO fibdi;

                        do
                        {
                            fibdi = safeBuffer.PtrToStructure <NativeMethods.FILE_ID_BOTH_DIR_INFO>(offset);

                            var fileName = safeBuffer.PtrToStringUni(offset + fileNameOffset, (int)(fibdi.FileNameLength / UnicodeEncoding.CharSize));

                            offset += fibdi.NextEntryOffset;


                            if (File.IsDirectory(fibdi.FileAttributes) &&
                                (fileName.Equals(Path.CurrentDirectoryPrefix, StringComparison.Ordinal) ||
                                 fileName.Equals(Path.ParentDirectoryPrefix, StringComparison.Ordinal)))
                            {
                                continue;
                            }


                            yield return(new FileIdBothDirectoryInfo(fibdi, fileName));


                            //offset += fibdi.NextEntryOffset;
                        } while (fibdi.NextEntryOffset != 0);
                    }
                }
            }
            finally
            {
                // Handle is ours, dispose.
                if (!callerHandle && null != safeFileHandle)
                {
                    safeFileHandle.Close();
                }
            }
        }
Exemplo n.º 8
0
        internal static string GetFullPathCore(KernelTransaction transaction, string path, GetFullPathOptions options)
        {
            // Skip the special paths recognised by Windows kernel only.

            if (null != path)
            {
                if (path.StartsWith(GlobalRootPrefix, StringComparison.OrdinalIgnoreCase) ||
                    path.StartsWith(VolumePrefix, StringComparison.OrdinalIgnoreCase) ||
                    path.StartsWith(NonInterpretedPathPrefix, StringComparison.Ordinal))
                {
                    return(path);
                }
            }


            if (options != GetFullPathOptions.None)
            {
                if ((options & GetFullPathOptions.CheckInvalidPathChars) != 0)
                {
                    var checkAdditional = (options & GetFullPathOptions.CheckAdditional) != 0;

                    CheckInvalidPathChars(path, checkAdditional, false);

                    // Prevent duplicate checks.
                    options &= ~GetFullPathOptions.CheckInvalidPathChars;

                    if (checkAdditional)
                    {
                        options &= ~GetFullPathOptions.CheckAdditional;
                    }
                }

                // Do not remove trailing directory separator when path points to a drive like: "C:\"
                // Doing so makes path point to the current directory.

                // ".", "C:", "C:\"
                if (null == path || path.Length <= 3 || !path.StartsWith(LongPathPrefix, StringComparison.Ordinal) && path[1] != VolumeSeparatorChar)
                {
                    options &= ~GetFullPathOptions.RemoveTrailingDirectorySeparator;
                }
            }


            var  pathLp     = GetLongPathCore(path, options);
            uint bufferSize = NativeMethods.MaxPathUnicode;

            using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
            {
startGetFullPathName:

                var buffer = new StringBuilder((int)bufferSize);
                var returnLength = null == transaction || !NativeMethods.IsAtLeastWindowsVista

                                   // GetFullPathName() / GetFullPathNameTransacted()
                                   // 2013-04-15: MSDN confirms LongPath usage.

               ? NativeMethods.GetFullPathName(pathLp, bufferSize, buffer, IntPtr.Zero)
               : NativeMethods.GetFullPathNameTransacted(pathLp, bufferSize, buffer, IntPtr.Zero, transaction.SafeHandle);


                if (returnLength != Win32Errors.NO_ERROR)
                {
                    if (returnLength > bufferSize)
                    {
                        bufferSize = returnLength;
                        goto startGetFullPathName;
                    }
                }
                else
                {
                    if ((options & GetFullPathOptions.ContinueOnNonExist) != 0)
                    {
                        return(null);
                    }

                    NativeError.ThrowException(returnLength, pathLp);
                }


                var finalFullPath = (options & GetFullPathOptions.AsLongPath) != 0 ? GetLongPathCore(buffer.ToString(), GetFullPathOptions.None) : GetRegularPathCore(buffer.ToString(), GetFullPathOptions.None, false);


                finalFullPath = NormalizePath(finalFullPath, options);


                if ((options & GetFullPathOptions.KeepDotOrSpace) != 0)
                {
                    if (pathLp.EndsWith(CurrentDirectoryPrefix, StringComparison.Ordinal))
                    {
                        finalFullPath += CurrentDirectoryPrefix;
                    }

                    var lastChar = pathLp[pathLp.Length - 1];
                    if (char.IsWhiteSpace(lastChar))
                    {
                        finalFullPath += lastChar;
                    }
                }


                return(finalFullPath);
            }
        }
        /// <summary>[AlphaFS] Creates an enumeration of all the hard links to the specified <paramref name="path"/>.</summary>
        /// <exception cref="PlatformNotSupportedException">Thrown when a Platform Not Supported error condition occurs.</exception>
        /// <param name="transaction">The transaction.</param>
        /// <param name="path">The name of the file.</param>
        /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
        /// <returns>An enumerable collection of <see cref="string"/> of all the hard links to the specified <paramref name="path"/></returns>
        internal static IEnumerable <string> EnumerateHardlinksInternal(KernelTransaction transaction, string path, PathFormat pathFormat)
        {
            if (!NativeMethods.IsAtLeastWindowsVista)
            {
                throw new PlatformNotSupportedException(Resources.RequiresWindowsVistaOrHigher);
            }

            string pathLp = Path.GetExtendedLengthPathInternal(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);

            // Default buffer length, will be extended if needed, although this should not happen.
            uint          length  = NativeMethods.MaxPathUnicode;
            StringBuilder builder = new StringBuilder((int)length);


getFindFirstFileName:

            using (SafeFindFileHandle handle = transaction == null

                                               // FindFirstFileName() / FindFirstFileNameTransacted()
                                               // In the ANSI version of this function, the name is limited to MAX_PATH characters.
                                               // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                                               // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

            ? NativeMethods.FindFirstFileName(pathLp, 0, out length, builder)
            : NativeMethods.FindFirstFileNameTransacted(pathLp, 0, out length, builder, transaction.SafeHandle))
            {
                if (handle.IsInvalid)
                {
                    int lastError = Marshal.GetLastWin32Error();
                    switch ((uint)lastError)
                    {
                    case Win32Errors.ERROR_MORE_DATA:
                        builder = new StringBuilder((int)length);
                        handle.Close();
                        goto getFindFirstFileName;

                    default:
                        // If the function fails, the return value is INVALID_HANDLE_VALUE.
                        NativeError.ThrowException(lastError, pathLp);
                        break;
                    }
                }

                yield return(builder.ToString());


                //length = NativeMethods.MaxPathUnicode;
                //builder = new StringBuilder((int)length);

                do
                {
                    while (!NativeMethods.FindNextFileName(handle, out length, builder))
                    {
                        int lastError = Marshal.GetLastWin32Error();
                        switch ((uint)lastError)
                        {
                        // We've reached the end of the enumeration.
                        case Win32Errors.ERROR_HANDLE_EOF:
                            yield break;

                        case Win32Errors.ERROR_MORE_DATA:
                            builder = new StringBuilder((int)length);
                            continue;

                        default:
                            //If the function fails, the return value is zero (0).
                            NativeError.ThrowException(lastError);
                            break;
                        }
                    }

                    yield return(builder.ToString());
                } while (true);
            }
        }
Exemplo n.º 10
0
        internal static void DeleteFileCore(KernelTransaction transaction, string path, bool ignoreReadOnly, PathFormat pathFormat)
        {
            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            var pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator);

            // If the path points to a symbolic link, the symbolic link is deleted, not the target.


startDeleteFile:

            if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista

                  // DeleteFile() / DeleteFileTransacted()
                  // 2013-01-13: MSDN confirms LongPath usage.

            ? NativeMethods.DeleteFile(pathLp)
            : NativeMethods.DeleteFileTransacted(pathLp, transaction.SafeHandle)))
            {
                var lastError = Marshal.GetLastWin32Error();
                switch ((uint)lastError)
                {
                case Win32Errors.ERROR_FILE_NOT_FOUND:
                    // MSDN: .NET 3.5+: If the file to be deleted does not exist, no exception is thrown.
                    return;

                case Win32Errors.ERROR_PATH_NOT_FOUND:
                    // MSDN: .NET 3.5+: DirectoryNotFoundException: The specified path is invalid (for example, it is on an unmapped drive).
                    NativeError.ThrowException(lastError, pathLp);
                    return;

                case Win32Errors.ERROR_SHARING_VIOLATION:
                    // MSDN: .NET 3.5+: IOException: The specified file is in use or there is an open handle on the file.
                    NativeError.ThrowException(lastError, pathLp);
                    break;

                case Win32Errors.ERROR_ACCESS_DENIED:
                    var attrs           = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA();
                    var dataInitialised = FillAttributeInfoCore(transaction, pathLp, ref attrs, false, true);


                    if (IsDirectory(attrs.dwFileAttributes))
                    {
                        // MSDN: .NET 3.5+: UnauthorizedAccessException: Path is a directory.
                        throw new UnauthorizedAccessException(string.Format(CultureInfo.InvariantCulture, "({0}) {1}",
                                                                            Win32Errors.ERROR_INVALID_PARAMETER, string.Format(CultureInfo.InvariantCulture, Resources.Target_File_Is_A_Directory, pathLp)));
                    }


                    if (IsReadOnly(attrs.dwFileAttributes))
                    {
                        if (ignoreReadOnly)
                        {
                            // Reset file attributes to Normal.
                            SetAttributesCore(transaction, false, pathLp, FileAttributes.Normal, PathFormat.LongFullPath);

                            goto startDeleteFile;
                        }


                        // MSDN: .NET 3.5+: UnauthorizedAccessException: Path specified a read-only file.
                        throw new FileReadOnlyException(pathLp);
                    }


                    // MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission.
                    if (dataInitialised == Win32Errors.ERROR_SUCCESS)
                    {
                        NativeError.ThrowException(lastError, pathLp);
                    }

                    break;
                }

                // MSDN: .NET 3.5+: IOException:
                // The specified file is in use.
                // There is an open handle on the file, and the operating system is Windows XP or earlier.

                NativeError.ThrowException(lastError, pathLp);
            }
        }
Exemplo n.º 11
0
        /// <summary>Refreshes the state of the object.</summary>
        public void Refresh()
        {
            var  volumeNameBuffer     = new StringBuilder(NativeMethods.MaxPath + 1);
            var  fileSystemNameBuffer = new StringBuilder(NativeMethods.MaxPath + 1);
            int  maximumComponentLength;
            uint serialNumber;

            // ChangeErrorMode is for the Win32 SetThreadErrorMode() method, used to suppress possible pop-ups.
            using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
            {
                // GetVolumeInformationXxx()
                // In the ANSI version of this function, the name is limited to 248 characters.
                // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                // 2013-07-18: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                uint lastError;

                do
                {
                    if (!(_volumeHandle != null && NativeMethods.IsAtLeastWindowsVista

                          // GetVolumeInformationByHandle() / GetVolumeInformation()
                          // In the ANSI version of this function, the name is limited to 248 characters.
                          // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                          // 2013-07-18: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                  ? NativeMethods.GetVolumeInformationByHandle(_volumeHandle, volumeNameBuffer, (uint)volumeNameBuffer.Capacity, out serialNumber, out maximumComponentLength, out _volumeInfoAttributes, fileSystemNameBuffer, (uint)fileSystemNameBuffer.Capacity)
                  : NativeMethods.GetVolumeInformation(Path.AddTrailingDirectorySeparator(Name, false), volumeNameBuffer, (uint)volumeNameBuffer.Capacity, out serialNumber, out maximumComponentLength, out _volumeInfoAttributes, fileSystemNameBuffer, (uint)fileSystemNameBuffer.Capacity))
                        // A trailing backslash is required.
                        )
                    {
                        lastError = (uint)Marshal.GetLastWin32Error();
                        switch (lastError)
                        {
                        case Win32Errors.ERROR_NOT_READY:
                            if (!_continueOnAccessError)
                            {
                                throw new DeviceNotReadyException();
                            }
                            break;

                        case Win32Errors.ERROR_MORE_DATA:
                            // With a large enough buffer this code never executes.
                            volumeNameBuffer.Capacity     = volumeNameBuffer.Capacity * 2;
                            fileSystemNameBuffer.Capacity = fileSystemNameBuffer.Capacity * 2;
                            break;

                        default:
                            if (!_continueOnAccessError)
                            {
                                NativeError.ThrowException(Name);
                            }
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                } while (lastError == Win32Errors.ERROR_MORE_DATA);
            }

            FullPath = Path.GetRegularPathCore(Name, GetFullPathOptions.None);
            Name     = volumeNameBuffer.ToString();

            FileSystemName = fileSystemNameBuffer.ToString();
            FileSystemName = Utils.IsNullOrWhiteSpace(FileSystemName) ? null : FileSystemName;

            MaximumComponentLength = maximumComponentLength;
            SerialNumber           = serialNumber;
        }
      internal static T GetAccessControlInternal<T>(bool isFolder, string path, AccessControlSections includeSections, PathFormat pathFormat)
      {
         SecurityInformation securityInfo = 0;
         PrivilegeEnabler privilegeEnabler = null;

         if ((includeSections & AccessControlSections.Access) != 0)
            securityInfo |= SecurityInformation.Dacl;

         if ((includeSections & AccessControlSections.Group) != 0)
            securityInfo |= SecurityInformation.Group;

         if ((includeSections & AccessControlSections.Owner) != 0)
            securityInfo |= SecurityInformation.Owner;

         if ((includeSections & AccessControlSections.Audit) != 0)
         {
            // We need the SE_SECURITY_NAME privilege enabled to be able to get the
            // SACL descriptor. So we enable it here for the remainder of this function.
            privilegeEnabler = new PrivilegeEnabler(Privilege.Security);
            securityInfo |= SecurityInformation.Sacl;
         }

         using (privilegeEnabler)
         {
            string pathLp = Path.GetExtendedLengthPathInternal(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);

            IntPtr pSidOwner, pSidGroup, pDacl, pSacl;
            SafeGlobalMemoryBufferHandle pSecurityDescriptor;
            ObjectSecurity objectSecurity;

            uint lastError = Security.NativeMethods.GetNamedSecurityInfo(pathLp, ObjectType.FileObject, securityInfo, out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor);

            try
            {
               if (lastError == Win32Errors.ERROR_FILE_NOT_FOUND || lastError == Win32Errors.ERROR_PATH_NOT_FOUND)
                  lastError = (isFolder ? Win32Errors.ERROR_PATH_NOT_FOUND : Win32Errors.ERROR_FILE_NOT_FOUND);

               // If the function fails, the return value is zero.
               if (lastError != Win32Errors.ERROR_SUCCESS)
                  NativeError.ThrowException(lastError, pathLp);

               if (!NativeMethods.IsValidHandle(pSecurityDescriptor, false))
                  throw new IOException(Resources.InvalidSecurityDescriptorReturnedFromSystem);


               uint length = Security.NativeMethods.GetSecurityDescriptorLength(pSecurityDescriptor);

               // Seems not to work: Method .CopyTo: length > Capacity, so an Exception is thrown.
               //byte[] managedBuffer = new byte[length];
               //pSecurityDescriptor.CopyTo(managedBuffer, 0, (int) length);

               byte[] managedBuffer = pSecurityDescriptor.ToByteArray(0, (int)length);

               objectSecurity = (isFolder) ? (ObjectSecurity)new DirectorySecurity() : new FileSecurity();
               objectSecurity.SetSecurityDescriptorBinaryForm(managedBuffer);
            }
            finally
            {
               if (pSecurityDescriptor != null)
                  pSecurityDescriptor.Close();
            }

            return (T)(object)objectSecurity;
         }
      }
        public IEnumerable <T> Enumerate <T>()
        {
            // MSDN: Queue
            // Represents a first-in, first-out collection of objects.
            // The capacity of a Queue is the number of elements the Queue can hold.
            // As elements are added to a Queue, the capacity is automatically increased as required through reallocation. The capacity can be decreased by calling TrimToSize.
            // The growth factor is the number by which the current capacity is multiplied when a greater capacity is required. The growth factor is determined when the Queue is constructed.
            // The capacity of the Queue will always increase by a minimum value, regardless of the growth factor; a growth factor of 1.0 will not prevent the Queue from increasing in size.
            // If the size of the collection can be estimated, specifying the initial capacity eliminates the need to perform a number of resizing operations while adding elements to the Queue.
            // This constructor is an O(n) operation, where n is capacity.

            var dirs = new Queue <string>(1000);

            // Removes the object at the beginning of your Queue.
            // The algorithmic complexity of this is O(1). It doesn't loop over elements.
            dirs.Enqueue(InputPath);

            // ChangeErrorMode is for the Win32 SetThreadErrorMode() method, used to suppress possible pop-ups.
            using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
                while (dirs.Count > 0)
                {
                    string path   = Path.AddTrailingDirectorySeparator(dirs.Dequeue(), false);
                    string pathLp = path + Path.WildcardStarMatchAll;
                    NativeMethods.WIN32_FIND_DATA win32FindData;

                    using (SafeFindFileHandle handle = FindFirstFile(pathLp, out win32FindData))
                    {
                        if (handle != null && handle.IsInvalid && ContinueOnException)
                        {
                            handle.Close();
                            continue;
                        }

                        do
                        {
                            string fileName = win32FindData.cFileName;

                            // Skip entries "." and ".."
                            if (fileName.Equals(Path.CurrentDirectoryPrefix, StringComparison.OrdinalIgnoreCase) ||
                                fileName.Equals(Path.ParentDirectoryPrefix, StringComparison.OrdinalIgnoreCase))
                            {
                                continue;
                            }

                            // Skip reparse points here to cleanly separate regular directories from links.
                            if (SkipReparsePoints && (win32FindData.dwFileAttributes & FileAttributes.ReparsePoint) != 0)
                            {
                                continue;
                            }


                            string fseiFullPathLp = path + fileName;
                            bool   fseiIsFolder   = (win32FindData.dwFileAttributes & FileAttributes.Directory) != 0;

                            // If object is a directory, add it to the queue for later traversal.
                            if (fseiIsFolder && Recursive)
                            {
                                dirs.Enqueue(fseiFullPathLp);
                            }


                            // Determine yield.
                            if (!(_nameFilter == null || (_nameFilter != null && _nameFilter.IsMatch(fileName))))
                            {
                                continue;
                            }

                            var res = NewFileSystemEntryType <T>(win32FindData, fseiFullPathLp, fseiIsFolder);
                            if (res == null)
                            {
                                continue;
                            }

                            yield return(res);
                        } while (NativeMethods.FindNextFile(handle, out win32FindData));


                        var lastError = (uint)Marshal.GetLastWin32Error();

                        if (!ContinueOnException)
                        {
                            switch (lastError)
                            {
                            case Win32Errors.ERROR_NO_MORE_FILES:
                                lastError = Win32Errors.NO_ERROR;
                                break;

                            case Win32Errors.ERROR_FILE_NOT_FOUND:
                            case Win32Errors.ERROR_PATH_NOT_FOUND:
                                if (lastError == Win32Errors.ERROR_FILE_NOT_FOUND && IsDirectory)
                                {
                                    lastError = Win32Errors.ERROR_PATH_NOT_FOUND;
                                }
                                break;
                            }

                            if (lastError != Win32Errors.NO_ERROR)
                            {
                                NativeError.ThrowException(lastError, pathLp);
                            }
                        }
                    }
                }
        }
Exemplo n.º 14
0
        /// <summary>Refreshes the state of the object.</summary>
        public void Refresh()
        {
            var  volumeNameBuffer     = new StringBuilder(NativeMethods.MaxPath + 1);
            var  fileSystemNameBuffer = new StringBuilder(NativeMethods.MaxPath + 1);
            int  maximumComponentLength;
            uint serialNumber;

            using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
            {
                // GetVolumeInformationXxx()
                // 2013-07-18: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                uint lastError;

                do
                {
                    var success = null != _volumeHandle && NativeMethods.IsAtLeastWindowsVista

                                  // GetVolumeInformationByHandle() / GetVolumeInformation()
                                  // 2013-07-18: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                  ? NativeMethods.GetVolumeInformationByHandle(_volumeHandle, volumeNameBuffer, (uint)volumeNameBuffer.Capacity, out serialNumber, out maximumComponentLength, out _volumeInfoAttributes, fileSystemNameBuffer, (uint)fileSystemNameBuffer.Capacity)

                                  // A trailing backslash is required.
                  : NativeMethods.GetVolumeInformation(Path.AddTrailingDirectorySeparator(Name, false), volumeNameBuffer, (uint)volumeNameBuffer.Capacity, out serialNumber, out maximumComponentLength, out _volumeInfoAttributes, fileSystemNameBuffer, (uint)fileSystemNameBuffer.Capacity);


                    lastError = (uint)Marshal.GetLastWin32Error();
                    if (!success)
                    {
                        switch (lastError)
                        {
                        case Win32Errors.ERROR_NOT_READY:
                            if (!_continueOnAccessError)
                            {
                                throw new DeviceNotReadyException(Name, true);
                            }
                            break;

                        case Win32Errors.ERROR_MORE_DATA:
                            // With a large enough buffer this code never executes.
                            volumeNameBuffer.Capacity     = volumeNameBuffer.Capacity * 2;
                            fileSystemNameBuffer.Capacity = fileSystemNameBuffer.Capacity * 2;
                            break;

                        default:
                            if (!_continueOnAccessError)
                            {
                                NativeError.ThrowException(lastError, Name);
                            }
                            break;
                        }
                    }

                    else
                    {
                        break;
                    }
                } while (lastError == Win32Errors.ERROR_MORE_DATA);
            }

            FullPath = Path.GetRegularPathCore(Name, GetFullPathOptions.None, false);
            Name     = volumeNameBuffer.ToString();

            FileSystemName = fileSystemNameBuffer.ToString();
            FileSystemName = !Utils.IsNullOrWhiteSpace(FileSystemName) ? FileSystemName : null;

            MaximumComponentLength = maximumComponentLength;
            SerialNumber           = serialNumber;
        }
Exemplo n.º 15
0
        internal static void SetAccessControlCore(string path, SafeFileHandle handle, ObjectSecurity objectSecurity, AccessControlSections includeSections, PathFormat pathFormat)
        {
            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            if (objectSecurity == null)
            {
                throw new ArgumentNullException("objectSecurity");
            }


            var managedDescriptor = objectSecurity.GetSecurityDescriptorBinaryForm();

            using (var safeBuffer = new SafeGlobalMemoryBufferHandle(managedDescriptor.Length))
            {
                var pathLp = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.CheckInvalidPathChars);

                safeBuffer.CopyFrom(managedDescriptor, 0, managedDescriptor.Length);

                SECURITY_DESCRIPTOR_CONTROL control;
                uint revision;


                var success = Security.NativeMethods.GetSecurityDescriptorControl(safeBuffer, out control, out revision);

                var lastError = Marshal.GetLastWin32Error();
                if (!success)
                {
                    NativeError.ThrowException(lastError, pathLp);
                }


                PrivilegeEnabler privilegeEnabler = null;

                try
                {
                    var securityInfo = SECURITY_INFORMATION.None;
                    var pDacl        = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Access) != 0)
                    {
                        bool daclDefaulted, daclPresent;


                        success = Security.NativeMethods.GetSecurityDescriptorDacl(safeBuffer, out daclPresent, out pDacl, out daclDefaulted);

                        lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }


                        if (daclPresent)
                        {
                            securityInfo |= SECURITY_INFORMATION.DACL_SECURITY_INFORMATION;
                            securityInfo |= (control & SECURITY_DESCRIPTOR_CONTROL.SE_DACL_PROTECTED) != 0 ? SECURITY_INFORMATION.PROTECTED_DACL_SECURITY_INFORMATION : SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION;
                        }
                    }


                    var pSacl = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Audit) != 0)
                    {
                        bool saclDefaulted, saclPresent;


                        success = Security.NativeMethods.GetSecurityDescriptorSacl(safeBuffer, out saclPresent, out pSacl, out saclDefaulted);

                        lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }


                        if (saclPresent)
                        {
                            securityInfo |= SECURITY_INFORMATION.SACL_SECURITY_INFORMATION;
                            securityInfo |= (control & SECURITY_DESCRIPTOR_CONTROL.SE_SACL_PROTECTED) != 0 ? SECURITY_INFORMATION.PROTECTED_SACL_SECURITY_INFORMATION : SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION;

                            privilegeEnabler = new PrivilegeEnabler(Privilege.Security);
                        }
                    }


                    var pOwner = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Owner) != 0)
                    {
                        bool ownerDefaulted;


                        success = Security.NativeMethods.GetSecurityDescriptorOwner(safeBuffer, out pOwner, out ownerDefaulted);

                        lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }


                        if (pOwner != IntPtr.Zero)
                        {
                            securityInfo |= SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION;
                        }
                    }


                    var pGroup = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Group) != 0)
                    {
                        bool groupDefaulted;


                        success = Security.NativeMethods.GetSecurityDescriptorGroup(safeBuffer, out pGroup, out groupDefaulted);

                        lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }


                        if (pGroup != IntPtr.Zero)
                        {
                            securityInfo |= SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION;
                        }
                    }



                    if (!Utils.IsNullOrWhiteSpace(pathLp))
                    {
                        // SetNamedSecurityInfo()
                        // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                        lastError = (int)Security.NativeMethods.SetNamedSecurityInfo(pathLp, SE_OBJECT_TYPE.SE_FILE_OBJECT, securityInfo, pOwner, pGroup, pDacl, pSacl);

                        if (lastError != Win32Errors.ERROR_SUCCESS)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }
                    }

                    else
                    {
                        if (NativeMethods.IsValidHandle(handle))
                        {
                            lastError = (int)Security.NativeMethods.SetSecurityInfo(handle, SE_OBJECT_TYPE.SE_FILE_OBJECT, securityInfo, pOwner, pGroup, pDacl, pSacl);

                            if (lastError != Win32Errors.ERROR_SUCCESS)
                            {
                                NativeError.ThrowException(lastError);
                            }
                        }
                    }
                }
                finally
                {
                    if (null != privilegeEnabler)
                    {
                        privilegeEnabler.Dispose();
                    }
                }
            }
        }
Exemplo n.º 16
0
        internal static LinkTargetInfo GetLinkTargetInfoCore(SafeFileHandle safeHandle)
        {
            // Start with a large buffer to prevent a 2nd call.
            // MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384
            uint bytesReturned = 4 * NativeMethods.DefaultFileBufferSize;

            using (var safeBuffer = new SafeGlobalMemoryBufferHandle((int)bytesReturned))
            {
                while (true)
                {
                    // DeviceIoControlMethod.Buffered = 0,
                    // DeviceIoControlFileDevice.FileSystem = 9
                    // FsctlGetReparsePoint = (DeviceIoControlFileDevice.FileSystem << 16) | (42 << 2) | DeviceIoControlMethod.Buffered | (0 << 14)

                    if (!NativeMethods.DeviceIoControl(safeHandle, ((9 << 16) | (42 << 2) | 0 | (0 << 14)), IntPtr.Zero, 0, safeBuffer, (uint)safeBuffer.Capacity, out bytesReturned, IntPtr.Zero))
                    {
                        var lastError = Marshal.GetLastWin32Error();
                        switch ((uint)lastError)
                        {
                        case Win32Errors.ERROR_MORE_DATA:
                        case Win32Errors.ERROR_INSUFFICIENT_BUFFER:
                            if (safeBuffer.Capacity < bytesReturned)
                            {
                                safeBuffer.Close();
                                break;
                            }

                            NativeError.ThrowException(lastError);
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }


                var marshalReparseBuffer = (int)Marshal.OffsetOf(typeof(NativeMethods.ReparseDataBufferHeader), "data");

                var header = safeBuffer.PtrToStructure <NativeMethods.ReparseDataBufferHeader>(0);

                var dataOffset = (int)(marshalReparseBuffer + (header.ReparseTag == ReparsePointTag.MountPoint
               ? Marshal.OffsetOf(typeof(NativeMethods.MountPointReparseBuffer), "data")
               : Marshal.OffsetOf(typeof(NativeMethods.SymbolicLinkReparseBuffer), "data")).ToInt64());

                var dataBuffer = new byte[bytesReturned - dataOffset];


                switch (header.ReparseTag)
                {
                case ReparsePointTag.MountPoint:
                    var mountPoint = safeBuffer.PtrToStructure <NativeMethods.MountPointReparseBuffer>(marshalReparseBuffer);

                    safeBuffer.CopyTo(dataOffset, dataBuffer, 0, dataBuffer.Length);

                    return(new LinkTargetInfo(
                               Encoding.Unicode.GetString(dataBuffer, mountPoint.SubstituteNameOffset, mountPoint.SubstituteNameLength),
                               Encoding.Unicode.GetString(dataBuffer, mountPoint.PrintNameOffset, mountPoint.PrintNameLength)));


                case ReparsePointTag.SymLink:
                    var symLink = safeBuffer.PtrToStructure <NativeMethods.SymbolicLinkReparseBuffer>(marshalReparseBuffer);

                    safeBuffer.CopyTo(dataOffset, dataBuffer, 0, dataBuffer.Length);

                    return(new SymbolicLinkTargetInfo(
                               Encoding.Unicode.GetString(dataBuffer, symLink.SubstituteNameOffset, symLink.SubstituteNameLength),
                               Encoding.Unicode.GetString(dataBuffer, symLink.PrintNameOffset, symLink.PrintNameLength), symLink.Flags));


                default:
                    throw new UnrecognizedReparsePointException();
                }
            }
        }
Exemplo n.º 17
0
        internal static void ImportExportEncryptedFileDirectoryRawCore(bool isExport, bool isFolder, Stream stream, string destinationPath, PathFormat pathFormat, bool overwriteHidden)
        {
            string destinationPathLp = Path.GetExtendedLengthPathCore(null, destinationPath, pathFormat, GetFullPathOptions.FullCheck | GetFullPathOptions.TrimEnd);

            NativeMethods.EncryptedFileRawMode mode = isExport
            ? NativeMethods.EncryptedFileRawMode.CreateForExport
            : NativeMethods.EncryptedFileRawMode.CreateForImport;

            if (isFolder)
            {
                mode = mode | NativeMethods.EncryptedFileRawMode.CreateForDir;
            }

            if (overwriteHidden)
            {
                mode = mode | NativeMethods.EncryptedFileRawMode.OverwriteHidden;
            }


            // OpenEncryptedFileRaw()
            // In the ANSI version of this function, the name is limited to 248 characters.
            // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
            // 2015-08-02: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

            SafeEncryptedFileRawHandle context;
            int lastError = NativeMethods.OpenEncryptedFileRaw(destinationPathLp, mode, out context);

            try
            {
                if (lastError != Win32Errors.ERROR_SUCCESS)
                {
                    NativeError.ThrowException(lastError, destinationPathLp);
                }


                lastError = isExport
               ? NativeMethods.ReadEncryptedFileRaw((pbData, pvCallbackContext, length) =>
                {
                    try
                    {
                        var data = new byte[length];

                        Marshal.Copy(pbData, data, 0, (int)length);

                        stream.Write(data, 0, (int)length);
                    }
                    catch (Exception ex)
                    {
                        return(Marshal.GetHRForException(ex) & NativeMethods.OverflowExceptionBitShift);
                    }

                    return((int)Win32Errors.ERROR_SUCCESS);
                }, IntPtr.Zero, context)


               : NativeMethods.WriteEncryptedFileRaw((IntPtr pbData, IntPtr pvCallbackContext, ref uint length) =>
                {
                    try
                    {
                        var data = new byte[length];

                        length = (uint)stream.Read(data, 0, (int)length);
                        if (length == 0)
                        {
                            return((int)Win32Errors.ERROR_SUCCESS);
                        }

                        Marshal.Copy(data, 0, pbData, (int)length);
                    }
                    catch (Exception ex)
                    {
                        return(Marshal.GetHRForException(ex) & NativeMethods.OverflowExceptionBitShift);
                    }

                    return((int)Win32Errors.ERROR_SUCCESS);
                }, IntPtr.Zero, context);


                if (lastError != Win32Errors.ERROR_SUCCESS)
                {
                    NativeError.ThrowException(lastError, destinationPathLp);
                }
            }
            finally
            {
                if (context != null)
                {
                    context.Dispose();
                }
            }
        }
Exemplo n.º 18
0
        internal static IEnumerable <DeviceInfo> EnumerateDevicesCore(SafeHandle safeHandle, string hostName, DeviceGuid deviceInterfaceGuid)
        {
            var callerHandle = safeHandle != null;
            var deviceGuid   = new Guid(Utils.GetEnumDescription(deviceInterfaceGuid));


            // CM_Connect_Machine()
            // MSDN Note: Beginning in Windows 8 and Windows Server 2012 functionality to access remote machines has been removed.
            // You cannot access remote machines when running on these versions of Windows.
            // http://msdn.microsoft.com/en-us/library/windows/hardware/ff537948%28v=vs.85%29.aspx

            SafeCmConnectMachineHandle safeMachineHandle;
            var lastError = NativeMethods.CM_Connect_Machine(Path.LocalToUncCore(Host.GetUncName(hostName), false, false, false), out safeMachineHandle);

            if (safeMachineHandle != null && safeMachineHandle.IsInvalid)
            {
                safeMachineHandle.Close();
                NativeError.ThrowException(lastError, Resources.Handle_Is_Invalid);
            }

            using (safeMachineHandle)
            {
                // Start at the "Root" of the device tree of the specified machine.
                if (!callerHandle)
                {
                    safeHandle = NativeMethods.SetupDiGetClassDevsEx(ref deviceGuid, IntPtr.Zero, IntPtr.Zero,
                                                                     NativeMethods.SetupDiGetClassDevsExFlags.Present |
                                                                     NativeMethods.SetupDiGetClassDevsExFlags.DeviceInterface,
                                                                     IntPtr.Zero, hostName, IntPtr.Zero);
                }

                if (safeHandle != null && safeHandle.IsInvalid)
                {
                    safeHandle.Close();
                    NativeError.ThrowException(Marshal.GetLastWin32Error(), Resources.Handle_Is_Invalid);
                }


                try
                {
                    uint memberInterfaceIndex = 0;
                    var  deviceInterfaceData  = CreateDeviceInterfaceDataInstance();

                    // Start enumerating Device Interfaces.
                    while (NativeMethods.SetupDiEnumDeviceInterfaces(safeHandle, IntPtr.Zero, ref deviceGuid, memberInterfaceIndex++, ref deviceInterfaceData))
                    {
                        lastError = Marshal.GetLastWin32Error();
                        if (lastError != Win32Errors.NO_ERROR)
                        {
                            NativeError.ThrowException(lastError, hostName);
                        }


                        var deviceInfoData            = CreateDeviceInfoDataInstance();
                        var deviceInterfaceDetailData = GetDeviceInterfaceDetailDataInstance(safeHandle, deviceInterfaceData, deviceInfoData);

                        // Get device interace details.
                        if (!NativeMethods.SetupDiGetDeviceInterfaceDetail(safeHandle, ref deviceInterfaceData, ref deviceInterfaceDetailData, NativeMethods.DefaultFileBufferSize, IntPtr.Zero, ref deviceInfoData))
                        {
                            lastError = Marshal.GetLastWin32Error();
                            if (lastError != Win32Errors.NO_ERROR)
                            {
                                NativeError.ThrowException(lastError, hostName);
                            }
                        }

                        // Create DeviceInfo instance.
                        // Set DevicePath property of DeviceInfo instance.
                        var deviceInfo = new DeviceInfo(hostName)
                        {
                            DevicePath = deviceInterfaceDetailData.DevicePath
                        };


                        // Current InstanceId is at the "USBSTOR" level, so we
                        // need up "move up" one level to get to the "USB" level.
                        uint ptrPrevious;

                        // CM_Get_Parent_Ex()
                        // Note: Using this function to access remote machines is not supported
                        // beginning with Windows 8 and Windows Server 2012, as this functionality has been removed.
                        // http://msdn.microsoft.com/en-us/library/windows/hardware/ff538615%28v=vs.85%29.aspx

                        lastError = NativeMethods.CM_Get_Parent_Ex(out ptrPrevious, deviceInfoData.DevInst, 0, safeMachineHandle);
                        if (lastError != Win32Errors.CR_SUCCESS)
                        {
                            NativeError.ThrowException(lastError, hostName);
                        }


                        // Now we get the InstanceID of the USB level device.
                        using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                        {
                            // CM_Get_Device_ID_Ex()
                            // Note: Using this function to access remote machines is not supported beginning with Windows 8 and Windows Server 2012,
                            // as this functionality has been removed.
                            // http://msdn.microsoft.com/en-us/library/windows/hardware/ff538411%28v=vs.85%29.aspx

                            lastError = NativeMethods.CM_Get_Device_ID_Ex(deviceInfoData.DevInst, safeBuffer, (uint)safeBuffer.Capacity, 0, safeMachineHandle);
                            if (lastError != Win32Errors.CR_SUCCESS)
                            {
                                NativeError.ThrowException(lastError, hostName);
                            }

                            // Add to instance.
                            deviceInfo.InstanceId = safeBuffer.PtrToStringUni();
                        }

                        #region Get Registry Properties

                        using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                        {
                            uint   regType;
                            string dataString;
                            var    safeBufferCapacity = (uint)safeBuffer.Capacity;


                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.BaseContainerId, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                dataString = safeBuffer.PtrToStringUni();
                                if (!Utils.IsNullOrWhiteSpace(dataString))
                                {
                                    deviceInfo.BaseContainerId = new Guid(dataString);
                                }
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.ClassGuid, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                dataString = safeBuffer.PtrToStringUni();
                                if (!Utils.IsNullOrWhiteSpace(dataString))
                                {
                                    deviceInfo.ClassGuid = new Guid(dataString);
                                }
                            }


                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.Class, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.Class = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.CompatibleIds, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.CompatibleIds = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.DeviceDescription, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.DeviceDescription = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.Driver, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.Driver = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.EnumeratorName, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.EnumeratorName = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.FriendlyName, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.FriendlyName = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.HardwareId, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.HardwareId = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.LocationInformation, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.LocationInformation = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.LocationPaths, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.LocationPaths = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.Manufacturer, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.Manufacturer = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.PhysicalDeviceObjectName, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.PhysicalDeviceObjectName = safeBuffer.PtrToStringUni();
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.Service, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.Service = safeBuffer.PtrToStringUni();
                            }
                        }

                        #endregion // Get Registry Properties

                        yield return(deviceInfo);

                        // Get new structure instance.
                        deviceInterfaceData = CreateDeviceInterfaceDataInstance();
                    }
                }
                finally
                {
                    // Handle is ours, dispose.
                    if (!callerHandle && safeHandle != null)
                    {
                        safeHandle.Close();
                    }
                }
            }
        }
Exemplo n.º 19
0
        internal static void DeleteFileInternal(KernelTransaction transaction, string path, bool ignoreReadOnly, PathFormat pathFormat)
        {
            #region Setup

            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckValidPath(path, true, true);
            }

            string pathLp = Path.GetExtendedLengthPathInternal(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator);

            // If the path points to a symbolic link, the symbolic link is deleted, not the target.

            #endregion // Setup

startDeleteFile:

            if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista

                  // DeleteFile() / DeleteFileTransacted()
                  // In the ANSI version of this function, the name is limited to MAX_PATH characters.
                  // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                  // 2013-01-13: MSDN confirms LongPath usage.

            ? NativeMethods.DeleteFile(pathLp)
            : NativeMethods.DeleteFileTransacted(pathLp, transaction.SafeHandle)))
            {
                int lastError = Marshal.GetLastWin32Error();
                switch ((uint)lastError)
                {
                case Win32Errors.ERROR_FILE_NOT_FOUND:
                    // MSDN: .NET 3.5+: If the file to be deleted does not exist, no exception is thrown.
                    return;

                case Win32Errors.ERROR_PATH_NOT_FOUND:
                    // MSDN: .NET 3.5+: DirectoryNotFoundException: The specified path is invalid (for example, it is on an unmapped drive).
                    NativeError.ThrowException(lastError, pathLp);
                    return;

                case Win32Errors.ERROR_SHARING_VIOLATION:
                    // MSDN: .NET 3.5+: IOException: The specified file is in use or there is an open handle on the file.
                    NativeError.ThrowException(lastError, pathLp);
                    break;

                case Win32Errors.ERROR_ACCESS_DENIED:
                    var data            = new NativeMethods.Win32FileAttributeData();
                    int dataInitialised = FillAttributeInfoInternal(transaction, pathLp, ref data, false, true);

                    if (data.FileAttributes != (FileAttributes)(-1))
                    {
                        if ((data.FileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
                        {
                            // MSDN: .NET 3.5+: UnauthorizedAccessException: Path is a directory.
                            throw new UnauthorizedAccessException(string.Format(CultureInfo.CurrentCulture, "({0}) {1}",
                                                                                Win32Errors.ERROR_INVALID_PARAMETER, string.Format(CultureInfo.CurrentCulture, Resources.DirectoryExistsWithSameNameSpecifiedByPath, pathLp)));
                        }


                        if ((data.FileAttributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                        {
                            if (ignoreReadOnly)
                            {
                                // Reset file attributes.
                                SetAttributesInternal(false, transaction, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath);
                                goto startDeleteFile;
                            }

                            // MSDN: .NET 3.5+: UnauthorizedAccessException: Path specified a read-only file.
                            throw new FileReadOnlyException(pathLp);
                        }
                    }

                    if (dataInitialised == Win32Errors.ERROR_SUCCESS)
                    {
                        // MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission.
                        NativeError.ThrowException(lastError, pathLp);
                    }

                    break;
                }

                // MSDN: .NET 3.5+: IOException:
                // The specified file is in use.
                // There is an open handle on the file, and the operating system is Windows XP or earlier.

                NativeError.ThrowException(lastError, pathLp);
            }
        }
        internal static IEnumerable <FileIdBothDirectoryInfo> EnumerateFileIdBothDirectoryInfoInternal(KernelTransaction transaction, SafeFileHandle safeHandle, string path, FileShare shareMode, bool continueOnException, PathFormat pathFormat)
        {
            if (!NativeMethods.IsAtLeastWindowsVista)
            {
                throw new PlatformNotSupportedException(Resources.RequiresWindowsVistaOrHigher);
            }

            bool callerHandle = safeHandle != null;

            if (!callerHandle)
            {
                if (Utils.IsNullOrWhiteSpace(path))
                {
                    throw new ArgumentNullException("path");
                }

                string pathLp = Path.GetExtendedLengthPathInternal(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);

                safeHandle = File.CreateFileInternal(transaction, pathLp, ExtendedFileAttributes.BackupSemantics, null, FileMode.Open, FileSystemRights.ReadData, shareMode, true, PathFormat.LongFullPath);
            }


            try
            {
                if (!NativeMethods.IsValidHandle(safeHandle, Marshal.GetLastWin32Error(), !continueOnException))
                {
                    yield break;
                }

                // 2014-10-16: Number of returned items depends on the size of the buffer.
                // That does not seem right, investigate.
                using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                {
                    NativeMethods.IsValidHandle(safeBuffer, Marshal.GetLastWin32Error());

                    long fileNameOffset = Marshal.OffsetOf(typeof(NativeMethods.FileIdBothDirInfo), "FileName").ToInt64();

                    while (NativeMethods.GetFileInformationByHandleEx(safeHandle, NativeMethods.FileInfoByHandleClass.FileIdBothDirectoryInfo, safeBuffer.DangerousGetHandle(), NativeMethods.DefaultFileBufferSize))
                    {
                        // 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


                        while (buffer != IntPtr.Zero)
                        {
                            NativeMethods.FileIdBothDirInfo fibdi = Utils.MarshalPtrToStructure <NativeMethods.FileIdBothDirInfo>(0, buffer);

                            string fileName = Marshal.PtrToStringUni(new IntPtr(fileNameOffset + buffer.ToInt64()), (int)(fibdi.FileNameLength / 2));

                            if (!Utils.IsNullOrWhiteSpace(fileName) &&
                                !fileName.Equals(Path.CurrentDirectoryPrefix, StringComparison.OrdinalIgnoreCase) &&
                                !fileName.Equals(Path.ParentDirectoryPrefix, StringComparison.OrdinalIgnoreCase))
                            {
                                yield return(new FileIdBothDirectoryInfo(fibdi, fileName));
                            }


                            buffer = fibdi.NextEntryOffset == 0
                        ? IntPtr.Zero
                        : new IntPtr(buffer.ToInt64() + fibdi.NextEntryOffset);
                        }
                    }

                    int lastError = Marshal.GetLastWin32Error();
                    switch ((uint)lastError)
                    {
                    case Win32Errors.ERROR_SUCCESS:
                    case Win32Errors.ERROR_NO_MORE_FILES:
                    case Win32Errors.ERROR_HANDLE_EOF:
                        yield break;

                    default:
                        NativeError.ThrowException(lastError, path);
                        break;
                    }
                }
            }
            finally
            {
                // Handle is ours, dispose.
                if (!callerHandle && safeHandle != null)
                {
                    safeHandle.Close();
                }
            }
        }
Exemplo n.º 21
0
        internal static SafeFileHandle CreateFileCore(KernelTransaction transaction, string path, ExtendedFileAttributes attributes, FileSecurity fileSecurity, FileMode fileMode, FileSystemRights fileSystemRights, FileShare fileShare, bool checkPath, bool continueOnException, PathFormat pathFormat)
        {
            if (checkPath && pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }


            // When isFile == null, we're working with a device.
            // When opening a VOLUME or removable media drive (for example, a floppy disk drive or flash memory thumb drive),
            // the path string should be the following form: "\\.\X:"
            // Do not use a trailing backslash ('\'), which indicates the root.

            var pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator);


            // CreateFileXxx() does not support FileMode.Append mode.
            var isAppend = fileMode == FileMode.Append;

            if (isAppend)
            {
                fileMode          = FileMode.OpenOrCreate;
                fileSystemRights |= FileSystemRights.AppendData;
            }


            if (null != fileSecurity)
            {
                fileSystemRights |= (FileSystemRights)SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION;
            }


            using ((fileSystemRights & (FileSystemRights)SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION) != 0 || (fileSystemRights & (FileSystemRights)SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION) != 0 ? new PrivilegeEnabler(Privilege.Security) : null)
                using (var securityAttributes = new Security.NativeMethods.SecurityAttributes(fileSecurity))
                {
                    var safeHandle = transaction == null || !NativeMethods.IsAtLeastWindowsVista

                                     // CreateFile() / CreateFileTransacted()
                                     // 2013-01-13: MSDN confirms LongPath usage.

               ? NativeMethods.CreateFile(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero)
               : NativeMethods.CreateFileTransacted(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero, transaction.SafeHandle, IntPtr.Zero, IntPtr.Zero);


                    var lastError = Marshal.GetLastWin32Error();

                    NativeMethods.IsValidHandle(safeHandle, lastError, pathLp, !continueOnException);


                    if (isAppend)
                    {
                        var success = NativeMethods.SetFilePointerEx(safeHandle, 0, IntPtr.Zero, SeekOrigin.End);

                        lastError = Marshal.GetLastWin32Error();

                        if (!success)
                        {
                            if (!safeHandle.IsClosed)
                            {
                                safeHandle.Close();
                            }

                            NativeError.ThrowException(lastError, path);
                        }
                    }

                    return(safeHandle);
                }
        }
Exemplo n.º 22
0
      internal static void DeleteDirectoryInternal(FileSystemEntryInfo fileSystemEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, bool requireEmpty, bool continueOnNotExist, PathFormat pathFormat)
      {
         #region Setup

         if (pathFormat == PathFormat.RelativePath)
            Path.CheckValidPath(path, true, true);

         if (fileSystemEntryInfo == null)
         {
            // MSDN: .NET 3.5+: DirectoryNotFoundException:
            // Path does not exist or could not be found.
            // Path refers to a file instead of a directory.
            // The specified path is invalid (for example, it is on an unmapped drive). 

            fileSystemEntryInfo = File.GetFileSystemEntryInfoInternal(transaction,
               Path.GetExtendedLengthPathInternal(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator),
                  continueOnNotExist, pathFormat);
         }

         if (fileSystemEntryInfo == null)
            return;

         string pathLp = fileSystemEntryInfo.LongFullPath;

         #endregion // Setup

         // Do not follow mount points nor symbolic links, but do delete the reparse point itself.

         // If directory is reparse point, disable recursion.
         if (recursive && fileSystemEntryInfo.IsReparsePoint)
            recursive = false;


         // Check to see if this is a mount point, and unmount it.
         if (fileSystemEntryInfo.IsMountPoint)
         {
            int lastError = Volume.DeleteVolumeMountPointInternal(pathLp, true);

            if (lastError != Win32Errors.ERROR_SUCCESS && lastError != Win32Errors.ERROR_PATH_NOT_FOUND)
               NativeError.ThrowException(lastError, pathLp);

            // Now it is safe to delete the actual directory.
         }


         if (recursive)
         {
            // Enumerate all file system objects.
            foreach (FileSystemEntryInfo fsei in EnumerateFileSystemEntryInfosInternal<FileSystemEntryInfo>(transaction, pathLp, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath))
            {
               if (fsei.IsDirectory)
                  DeleteDirectoryInternal(fsei, transaction, null, true, ignoreReadOnly, requireEmpty, true, PathFormat.LongFullPath);
               else
                  File.DeleteFileInternal(transaction, fsei.LongFullPath, ignoreReadOnly, PathFormat.LongFullPath);
            }
         }

         #region Remove

      startRemoveDirectory:

         if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista

            // RemoveDirectory() / RemoveDirectoryTransacted()
            // In the ANSI version of this function, the name is limited to MAX_PATH characters.
            // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
            // 2014-09-09: MSDN confirms LongPath usage.

            // RemoveDirectory on a symbolic link will remove the link itself.

            ? NativeMethods.RemoveDirectory(pathLp)
            : NativeMethods.RemoveDirectoryTransacted(pathLp, transaction.SafeHandle)))
         {
            int lastError = Marshal.GetLastWin32Error();
            switch ((uint)lastError)
            {
               case Win32Errors.ERROR_DIR_NOT_EMPTY:
                  if (requireEmpty)
                     // MSDN: .NET 3.5+: IOException: The directory specified by path is not an empty directory. 
                     throw new DirectoryNotEmptyException(pathLp);

                  goto startRemoveDirectory;


               case Win32Errors.ERROR_DIRECTORY:
                  // MSDN: .NET 3.5+: DirectoryNotFoundException: Path refers to a file instead of a directory.
                  if (File.ExistsInternal(false, transaction, pathLp, PathFormat.LongFullPath))
                     throw new DirectoryNotFoundException(String.Format(CultureInfo.CurrentCulture, "({0}) {1}",
                        Win32Errors.ERROR_INVALID_PARAMETER, String.Format(CultureInfo.CurrentCulture, Resources.FileExistsWithSameNameSpecifiedByPath, pathLp)));
                  break;


               case Win32Errors.ERROR_PATH_NOT_FOUND:
                  if (continueOnNotExist)
                     return;
                  break;

               case Win32Errors.ERROR_SHARING_VIOLATION:
                  // MSDN: .NET 3.5+: IOException: The directory is being used by another process or there is an open handle on the directory.
                  NativeError.ThrowException(lastError, pathLp);
                  break;

               case Win32Errors.ERROR_ACCESS_DENIED:
                  NativeMethods.Win32FileAttributeData data = new NativeMethods.Win32FileAttributeData();
                  int dataInitialised = File.FillAttributeInfoInternal(transaction, pathLp, ref data, false, true);

                  if (data.FileAttributes != (FileAttributes)(-1))
                  {
                     if ((data.FileAttributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                     {
                        // MSDN: .NET 3.5+: IOException: The directory specified by path is read-only.

                        if (ignoreReadOnly)
                        {
                           // Reset directory attributes.
                           File.SetAttributesInternal(true, transaction, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath);
                           goto startRemoveDirectory;
                        }

                        // MSDN: .NET 3.5+: IOException: The directory is read-only.
                        throw new DirectoryReadOnlyException(pathLp);
                     }
                  }

                  if (dataInitialised == Win32Errors.ERROR_SUCCESS)
                     // MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission.
                     NativeError.ThrowException(lastError, pathLp);

                  break;
            }

            // MSDN: .NET 3.5+: IOException:
            // A file with the same name and location specified by path exists.
            // The directory specified by path is read-only, or recursive is false and path is not an empty directory. 
            // The directory is the application's current working directory. 
            // The directory contains a read-only file.
            // The directory is being used by another process.

            NativeError.ThrowException(lastError, pathLp);
         }

         #endregion // Remove
      }
Exemplo n.º 23
0
        internal static string GetFinalPathNameByHandleCore(SafeFileHandle handle, FinalPathFormats finalPath)
        {
            NativeMethods.IsValidHandle(handle);

            var buffer = new StringBuilder(NativeMethods.MaxPathUnicode);

            using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
            {
                if (NativeMethods.IsAtLeastWindowsVista)
                {
                    if (NativeMethods.GetFinalPathNameByHandle(handle, buffer, (uint)buffer.Capacity, finalPath) == Win32Errors.ERROR_SUCCESS)
                    {
                        NativeError.ThrowException(Marshal.GetLastWin32Error());
                    }

                    return(buffer.ToString());
                }
            }

            #region Older OperatingSystem

            // Obtaining a File Name From a File Handle
            // http://msdn.microsoft.com/en-us/library/aa366789%28VS.85%29.aspx

            // Be careful when using GetFileSizeEx to check the size of hFile handle of an unknown "File" type object.
            // This is more towards returning a filename from a file handle. If the handle is a named pipe handle it seems to hang the thread.
            // Check for: FileTypes.DiskFile

            // Can't map a 0 byte file.
            long fileSizeHi;
            if (!NativeMethods.GetFileSizeEx(handle, out fileSizeHi))
            {
                if (fileSizeHi == 0)
                {
                    return(string.Empty);
                }
            }


            // PAGE_READONLY
            // Allows views to be mapped for read-only or copy-on-write access. An attempt to write to a specific region results in an access violation.
            // The file handle that the hFile parameter specifies must be created with the GENERIC_READ access right.
            // PageReadOnly = 0x02,
            using (SafeFileHandle handle2 = NativeMethods.CreateFileMapping(handle, null, 2, 0, 1, null))
            {
                NativeMethods.IsValidHandle(handle, Marshal.GetLastWin32Error());

                // FILE_MAP_READ
                // Read = 4
                using (SafeLocalMemoryBufferHandle pMem = NativeMethods.MapViewOfFile(handle2, 4, 0, 0, (UIntPtr)1))
                {
                    if (NativeMethods.IsValidHandle(pMem, Marshal.GetLastWin32Error()))
                    {
                        if (NativeMethods.GetMappedFileName(Process.GetCurrentProcess().Handle, pMem, buffer, (uint)buffer.Capacity))
                        {
                            NativeMethods.UnmapViewOfFile(pMem);
                        }
                    }
                }
            }


            // Default output from GetMappedFileName(): "\Device\HarddiskVolumeX\path\filename.ext"
            string dosDevice = buffer.Length > 0 ? buffer.ToString() : string.Empty;

            // Select output format.
            switch (finalPath)
            {
            // As-is: "\Device\HarddiskVolumeX\path\filename.ext"
            case FinalPathFormats.VolumeNameNT:
                return(dosDevice);

            // To: "\path\filename.ext"
            case FinalPathFormats.VolumeNameNone:
                return(DosDeviceToDosPath(dosDevice, string.Empty));

            // To: "\\?\Volume{GUID}\path\filename.ext"
            case FinalPathFormats.VolumeNameGuid:
                string dosPath = DosDeviceToDosPath(dosDevice, null);
                if (!Utils.IsNullOrWhiteSpace(dosPath))
                {
                    string path        = GetSuffixedDirectoryNameWithoutRootCore(null, dosPath);
                    string driveLetter = RemoveTrailingDirectorySeparator(GetPathRoot(dosPath, false), false);
                    string file        = GetFileName(dosPath, true);

                    if (!Utils.IsNullOrWhiteSpace(file))
                    {
                        foreach (string drive in Directory.EnumerateLogicalDrivesCore(false, false).Select(drv => drv.Name).Where(drv => driveLetter.Equals(RemoveTrailingDirectorySeparator(drv, false), StringComparison.OrdinalIgnoreCase)))
                        {
                            return(CombineCore(false, Volume.GetUniqueVolumeNameForPath(drive), path, file));
                        }
                    }
                }

                break;
            }

            // To: "\\?\C:\path\filename.ext"
            return(Utils.IsNullOrWhiteSpace(dosDevice)
            ? string.Empty
            : LongPathPrefix + DosDeviceToDosPath(dosDevice, null));

            #endregion // Older OperatingSystem
        }
Exemplo n.º 24
0
        public static LinkTargetInfo GetLinkTargetInfo(SafeHandle device)
        {
            UInt32 bytesReturned;

            int       lastError   = 0;
            const int maxCapacity = 0x3FF0;

            SafeGlobalMemoryBufferHandle buffer = new SafeGlobalMemoryBufferHandle(512);

            try
            {
                do
                {
                    if (!NativeMethods.DeviceIoControl(device, IoControlCode.FsctlGetReparsePoint, new SafeGlobalMemoryBufferHandle(), 0, buffer, (uint)buffer.Capacity, out bytesReturned, IntPtr.Zero))
                    {
                        lastError = Marshal.GetLastWin32Error();
                        if (lastError == Win32Errors.ERROR_INSUFFICIENT_BUFFER && buffer.Capacity < maxCapacity)
                        {
                            buffer.Dispose();
                            buffer = null;
                            buffer = new SafeGlobalMemoryBufferHandle(maxCapacity);
                            continue;
                        }
                        NativeError.ThrowException(lastError);
                    }
                    else
                    {
                        break;
                    }
                }while (true);

                IntPtr bufPtr = buffer.DangerousGetHandle();
                ReparseDataBufferHeader header = (ReparseDataBufferHeader)Marshal.PtrToStructure(bufPtr, typeof(ReparseDataBufferHeader));

                if (header.ReparseTag == ReparsePointTag.MountPoint)
                {
                    MountPointReparseBuffer mpBuf = (MountPointReparseBuffer)Marshal.PtrToStructure(AddPtr(bufPtr, Marshal.OffsetOf(typeof(ReparseDataBufferHeader), "data")), typeof(MountPointReparseBuffer));
                    IntPtr dataPos    = AddPtr(Marshal.OffsetOf(typeof(ReparseDataBufferHeader), "data"), Marshal.OffsetOf(typeof(MountPointReparseBuffer), "data"));
                    byte[] dataBuffer = new byte[bytesReturned - dataPos.ToInt64()];
                    Marshal.Copy(AddPtr(bufPtr, dataPos), dataBuffer, 0, dataBuffer.Length);
                    return(new LinkTargetInfo(
                               Encoding.Unicode.GetString(dataBuffer, mpBuf.SubstituteNameOffset, mpBuf.SubstituteNameLength),
                               Encoding.Unicode.GetString(dataBuffer, mpBuf.PrintNameOffset, mpBuf.PrintNameLength)
                               ));
                }
                else if (header.ReparseTag == ReparsePointTag.SymLink)
                {
                    SymbolicLinkReparseBuffer mpBuf = (SymbolicLinkReparseBuffer)Marshal.PtrToStructure(AddPtr(bufPtr, Marshal.OffsetOf(typeof(ReparseDataBufferHeader), "data")), typeof(SymbolicLinkReparseBuffer));
                    IntPtr dataPos    = AddPtr(Marshal.OffsetOf(typeof(ReparseDataBufferHeader), "data"), Marshal.OffsetOf(typeof(SymbolicLinkReparseBuffer), "data"));
                    byte[] dataBuffer = new byte[bytesReturned - dataPos.ToInt64()];
                    Marshal.Copy(AddPtr(bufPtr, dataPos), dataBuffer, 0, dataBuffer.Length);
                    return(new SymbolicLinkTargetInfo(
                               Encoding.Unicode.GetString(dataBuffer, mpBuf.SubstituteNameOffset, mpBuf.SubstituteNameLength),
                               Encoding.Unicode.GetString(dataBuffer, mpBuf.PrintNameOffset, mpBuf.PrintNameLength),
                               (SymbolicLinkType)mpBuf.Flags
                               ));
                }
                else
                {
                    throw new UnrecognizedReparsePointException();
                }
            }
            finally
            {
                if (buffer != null)
                {
                    buffer.Dispose();
                }
            }
        }
Exemplo n.º 25
0
        internal static SafeFileHandle CreateFileCore(KernelTransaction transaction, string path, ExtendedFileAttributes attributes, FileSecurity fileSecurity, FileMode fileMode, FileSystemRights fileSystemRights, FileShare fileShare, bool checkPath, PathFormat pathFormat)
        {
            if (checkPath && pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            // When isFile == null, we're working with a device.
            // When opening a VOLUME or removable media drive (for example, a floppy disk drive or flash memory thumb drive),
            // the path string should be the following form: "\\.\X:"
            // Do not use a trailing backslash (\), which indicates the root.

            string pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator);

            PrivilegeEnabler privilegeEnabler = null;


            // CreateFileXxx() does not support FileMode.Append mode.
            if (fileMode == FileMode.Append)
            {
                fileMode          = FileMode.OpenOrCreate;
                fileSystemRights &= FileSystemRights.AppendData; // Add right.
            }


            if (fileSecurity != null)
            {
                fileSystemRights |= (FileSystemRights)0x1000000; // Set right.
            }
            // AccessSystemSecurity = 0x1000000    AccessSystemAcl access type.
            // MaximumAllowed       = 0x2000000    MaximumAllowed  access type.

            if ((fileSystemRights & (FileSystemRights)0x1000000) != 0 ||
                (fileSystemRights & (FileSystemRights)0x2000000) != 0)
            {
                privilegeEnabler = new PrivilegeEnabler(Privilege.Security);
            }


            using (privilegeEnabler)
                using (var securityAttributes = new Security.NativeMethods.SecurityAttributes(fileSecurity))
                {
                    SafeFileHandle handle = transaction == null || !NativeMethods.IsAtLeastWindowsVista

                                            // CreateFile() / CreateFileTransacted()
                                            // In the ANSI version of this function, the name is limited to MAX_PATH characters.
                                            // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                                            // 2013-01-13: MSDN confirms LongPath usage.

               ? NativeMethods.CreateFile(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero)
               : NativeMethods.CreateFileTransacted(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero, transaction.SafeHandle, IntPtr.Zero, IntPtr.Zero);

                    int lastError = Marshal.GetLastWin32Error();

                    if (handle != null && handle.IsInvalid)
                    {
                        handle.Close();
                        NativeError.ThrowException(lastError, pathLp);
                    }

                    return(handle);
                }
        }
Exemplo n.º 26
0
        public bool MoveNext()
        {
            NativeMethods.WIN32_FIND_DATA findData = new NativeMethods.WIN32_FIND_DATA();

            if (mHandle == null)
            {
                if (mTransaction == null)
                {
                    mHandle = NativeMethods.FindFirstFileExW(mSearchString,
                                                             NativeMethods.FINDEX_INFO_LEVELS.FindExInfoStandard,
                                                             findData, mFindexSearchOptions,
                                                             IntPtr.Zero, NativeMethods.FINDEX_FLAGS.FIND_FIRST_EX_NONE);
                }
                else
                {
                    mHandle = NativeMethods.FindFirstFileTransactedW(mSearchString,
                                                                     NativeMethods.FINDEX_INFO_LEVELS.FindExInfoStandard,
                                                                     findData, mFindexSearchOptions, IntPtr.Zero,
                                                                     NativeMethods.FINDEX_FLAGS.FIND_FIRST_EX_NONE, mTransaction.SafeHandle);
                }

                if (mHandle.IsInvalid)
                {
                    uint error = (uint)Marshal.GetLastWin32Error();
                    if (error == Win32Errors.ERROR_FILE_NOT_FOUND)
                    {
                        return(false);
                    }
                    else
                    {
                        NativeError.ThrowException(error, mSearchString, mSearchString);
                    }
                }
                mSysEntryInfo = new FileSystemEntryInfo(findData);
                return(Filter());
            }
            else if (mHandle.IsInvalid)
            {
                return(false);
            }
            else
            {
                if (!NativeMethods.FindNextFileW(mHandle, findData))
                {
                    uint error = (uint)Marshal.GetLastWin32Error();
                    if (error == Win32Errors.ERROR_NO_MORE_FILES)
                    {
                        mHandle.Close();
                        return(false);
                    }
                    else
                    {
                        NativeError.ThrowException(error);
                    }
                }
                else
                {
                    mSysEntryInfo = new FileSystemEntryInfo(findData);
                    return(Filter());
                }
            }
            // Actually unreachable code, but seems to be neccessary.
            return(false);
        }
Exemplo n.º 27
0
        internal static void SetAccessControlInternal(string path, SafeHandle handle, ObjectSecurity objectSecurity, AccessControlSections includeSections, PathFormat pathFormat)
        {
            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckValidPath(path, true, true);
            }

            if (objectSecurity == null)
            {
                throw new ArgumentNullException("objectSecurity");
            }

            byte[] managedDescriptor = objectSecurity.GetSecurityDescriptorBinaryForm();
            using (var safeBuffer = new SafeGlobalMemoryBufferHandle(managedDescriptor.Length))
            {
                string pathLp = Path.GetExtendedLengthPathInternal(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.CheckInvalidPathChars);

                safeBuffer.CopyFrom(managedDescriptor, 0, managedDescriptor.Length);

                SecurityDescriptorControl control;
                uint revision;
                if (!Security.NativeMethods.GetSecurityDescriptorControl(safeBuffer, out control, out revision))
                {
                    NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                }

                PrivilegeEnabler privilegeEnabler = null;
                try
                {
                    var securityInfo = SecurityInformation.None;

                    IntPtr pDacl = IntPtr.Zero;
                    if ((includeSections & AccessControlSections.Access) != 0)
                    {
                        bool daclDefaulted, daclPresent;
                        if (!Security.NativeMethods.GetSecurityDescriptorDacl(safeBuffer, out daclPresent, out pDacl, out daclDefaulted))
                        {
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                        }

                        if (daclPresent)
                        {
                            securityInfo |= SecurityInformation.Dacl;
                            securityInfo |= (control & SecurityDescriptorControl.DaclProtected) != 0
                        ? SecurityInformation.ProtectedDacl
                        : SecurityInformation.UnprotectedDacl;
                        }
                    }

                    IntPtr pSacl = IntPtr.Zero;
                    if ((includeSections & AccessControlSections.Audit) != 0)
                    {
                        bool saclDefaulted, saclPresent;
                        if (!Security.NativeMethods.GetSecurityDescriptorSacl(safeBuffer, out saclPresent, out pSacl, out saclDefaulted))
                        {
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                        }

                        if (saclPresent)
                        {
                            securityInfo |= SecurityInformation.Sacl;
                            securityInfo |= (control & SecurityDescriptorControl.SaclProtected) != 0
                        ? SecurityInformation.ProtectedSacl
                        : SecurityInformation.UnprotectedSacl;

                            privilegeEnabler = new PrivilegeEnabler(Privilege.Security);
                        }
                    }

                    IntPtr pOwner = IntPtr.Zero;
                    if ((includeSections & AccessControlSections.Owner) != 0)
                    {
                        bool ownerDefaulted;
                        if (!Security.NativeMethods.GetSecurityDescriptorOwner(safeBuffer, out pOwner, out ownerDefaulted))
                        {
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                        }

                        if (pOwner != IntPtr.Zero)
                        {
                            securityInfo |= SecurityInformation.Owner;
                        }
                    }

                    IntPtr pGroup = IntPtr.Zero;
                    if ((includeSections & AccessControlSections.Group) != 0)
                    {
                        bool groupDefaulted;
                        if (!Security.NativeMethods.GetSecurityDescriptorGroup(safeBuffer, out pGroup, out groupDefaulted))
                        {
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                        }

                        if (pGroup != IntPtr.Zero)
                        {
                            securityInfo |= SecurityInformation.Group;
                        }
                    }


                    uint lastError;
                    if (!Utils.IsNullOrWhiteSpace(pathLp))
                    {
                        // SetNamedSecurityInfo()
                        // In the ANSI version of this function, the name is limited to MAX_PATH characters.
                        // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                        // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                        lastError = Security.NativeMethods.SetNamedSecurityInfo(pathLp, ObjectType.FileObject, securityInfo, pOwner, pGroup, pDacl, pSacl);
                        if (lastError != Win32Errors.ERROR_SUCCESS)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }
                    }
                    else if (NativeMethods.IsValidHandle(handle))
                    {
                        lastError = Security.NativeMethods.SetSecurityInfo(handle, ObjectType.FileObject, securityInfo, pOwner, pGroup, pDacl, pSacl);
                        if (lastError != Win32Errors.ERROR_SUCCESS)
                        {
                            NativeError.ThrowException((int)lastError);
                        }
                    }
                }
                finally
                {
                    if (privilegeEnabler != null)
                    {
                        privilegeEnabler.Dispose();
                    }
                }
            }
        }
        internal static string GetFullPathCore(KernelTransaction transaction, string path, GetFullPathOptions options)
        {
            if (path != null)
            {
                if (path.StartsWith(GlobalRootPrefix, StringComparison.OrdinalIgnoreCase) ||
                    path.StartsWith(VolumePrefix, StringComparison.OrdinalIgnoreCase))
                {
                    return(path);
                }
            }

            if (options != GetFullPathOptions.None)
            {
                if ((options & GetFullPathOptions.CheckInvalidPathChars) != 0)
                {
                    bool checkAdditional = (options & GetFullPathOptions.CheckAdditional) != 0;

                    CheckInvalidPathChars(path, checkAdditional);

                    // Prevent duplicate checks.
                    options &= ~GetFullPathOptions.CheckInvalidPathChars;

                    if (checkAdditional)
                    {
                        options &= ~GetFullPathOptions.CheckAdditional;
                    }
                }

                // Do not remove trailing directory separator when path points to a drive like: "C:\"
                // Doing so makes path point to the current directory.

                if (path == null || path.Length <= 3 || (!path.StartsWith(LongPathPrefix, StringComparison.OrdinalIgnoreCase) && path[1] != VolumeSeparatorChar))
                {
                    options &= ~GetFullPathOptions.RemoveTrailingDirectorySeparator;
                }
            }


            string pathLp = GetLongPathCore(path, options);

            uint bufferSize = NativeMethods.MaxPathUnicode;


            // ChangeErrorMode is for the Win32 SetThreadErrorMode() method, used to suppress possible pop-ups.
            using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
            {
startGetFullPathName:

                var buffer = new StringBuilder((int)bufferSize);
                uint returnLength = (transaction == null || !NativeMethods.IsAtLeastWindowsVista

                                     // GetFullPathName() / GetFullPathNameTransacted()
                                     // In the ANSI version of this function, the name is limited to MAX_PATH characters.
                                     // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                                     // 2013-04-15: MSDN confirms LongPath usage.

               ? NativeMethods.GetFullPathName(pathLp, bufferSize, buffer, IntPtr.Zero)
               : NativeMethods.GetFullPathNameTransacted(pathLp, bufferSize, buffer, IntPtr.Zero, transaction.SafeHandle));

                if (returnLength != Win32Errors.NO_ERROR)
                {
                    if (returnLength > bufferSize)
                    {
                        bufferSize = returnLength;
                        goto startGetFullPathName;
                    }
                }
                else
                {
                    if ((options & GetFullPathOptions.ContinueOnNonExist) != 0)
                    {
                        return(null);
                    }

                    NativeError.ThrowException(pathLp);
                }

                return((options & GetFullPathOptions.AsLongPath) != 0
               ? GetLongPathCore(buffer.ToString(), GetFullPathOptions.None)
               : GetRegularPathCore(buffer.ToString(), GetFullPathOptions.None));
            }
        }
Exemplo n.º 29
0
        internal static int FillAttributeInfoCore(KernelTransaction transaction, string pathLp, ref NativeMethods.WIN32_FILE_ATTRIBUTE_DATA win32AttrData, bool tryagain, bool returnErrorOnNotFound)
        {
            int dataInitialised = (int)Win32Errors.ERROR_SUCCESS;

            #region Try Again

            // Someone has a handle to the file open, or other error.
            if (tryagain)
            {
                NativeMethods.WIN32_FIND_DATA findData;

                using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
                {
                    bool error = false;

                    SafeFindFileHandle handle = transaction == null || !NativeMethods.IsAtLeastWindowsVista

                                                // FindFirstFileEx() / FindFirstFileTransacted()
                                                // In the ANSI version of this function, the name is limited to MAX_PATH characters.
                                                // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                                                // 2013-01-13: MSDN confirms LongPath usage.

                                                // A trailing backslash is not allowed.
                  ? NativeMethods.FindFirstFileEx(Path.RemoveTrailingDirectorySeparator(pathLp, false), NativeMethods.FindexInfoLevels, out findData, NativeMethods.FINDEX_SEARCH_OPS.SearchNameMatch, IntPtr.Zero, NativeMethods.LargeCache)
                  : NativeMethods.FindFirstFileTransacted(Path.RemoveTrailingDirectorySeparator(pathLp, false), NativeMethods.FindexInfoLevels, out findData, NativeMethods.FINDEX_SEARCH_OPS.SearchNameMatch, IntPtr.Zero, NativeMethods.LargeCache, transaction.SafeHandle);

                    try
                    {
                        if (handle.IsInvalid)
                        {
                            error           = true;
                            dataInitialised = Marshal.GetLastWin32Error();

                            if (dataInitialised == Win32Errors.ERROR_FILE_NOT_FOUND ||
                                dataInitialised == Win32Errors.ERROR_PATH_NOT_FOUND ||
                                dataInitialised == Win32Errors.ERROR_NOT_READY) // Floppy device not ready.
                            {
                                if (!returnErrorOnNotFound)
                                {
                                    // Return default value for backward compatibility
                                    dataInitialised = (int)Win32Errors.ERROR_SUCCESS;
                                    win32AttrData.dwFileAttributes = (FileAttributes)(-1);
                                }
                            }

                            return(dataInitialised);
                        }
                    }
                    finally
                    {
                        try
                        {
                            if (handle != null)
                            {
                                handle.Close();
                            }
                        }
                        catch
                        {
                            // If we're already returning an error, don't throw another one.
                            if (!error)
                            {
                                NativeError.ThrowException(dataInitialised, pathLp);
                            }
                        }
                    }
                }

                // Copy the attribute information.
                win32AttrData = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA(findData);
            }

            #endregion // Try Again

            else
            {
                using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
                {
                    if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista

                          // GetFileAttributesEx() / GetFileAttributesTransacted()
                          // In the ANSI version of this function, the name is limited to MAX_PATH characters.
                          // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
                          // 2013-01-13: MSDN confirms LongPath usage.

                  ? NativeMethods.GetFileAttributesEx(pathLp, NativeMethods.GetFileExInfoLevels.GetFileExInfoStandard, out win32AttrData)
                  : NativeMethods.GetFileAttributesTransacted(pathLp, NativeMethods.GetFileExInfoLevels.GetFileExInfoStandard, out win32AttrData, transaction.SafeHandle)))
                    {
                        dataInitialised = Marshal.GetLastWin32Error();

                        if (dataInitialised != Win32Errors.ERROR_FILE_NOT_FOUND &&
                            dataInitialised != Win32Errors.ERROR_PATH_NOT_FOUND &&
                            dataInitialised != Win32Errors.ERROR_NOT_READY) // Floppy device not ready.
                        {
                            // In case someone latched onto the file. Take the perf hit only for failure.
                            return(FillAttributeInfoCore(transaction, pathLp, ref win32AttrData, true, returnErrorOnNotFound));
                        }

                        if (!returnErrorOnNotFound)
                        {
                            // Return default value for backward compbatibility.
                            dataInitialised = (int)Win32Errors.ERROR_SUCCESS;
                            win32AttrData.dwFileAttributes = (FileAttributes)(-1);
                        }
                    }
                }
            }

            return(dataInitialised);
        }
Exemplo n.º 30
0
Arquivo: Device.cs Projeto: CDEApp/CDE
        internal static LinkTargetInfo GetLinkTargetInfoInternal(SafeFileHandle safeHandle)
        {
            // Start with a large buffer to prevent a 2nd call.
            uint bytesReturned = NativeMethods.MaxPathUnicode;

            using (SafeGlobalMemoryBufferHandle safeBuffer = new SafeGlobalMemoryBufferHandle((int)bytesReturned))
            {
                do
                {
                    // Possible PInvoke signature bug: safeBuffer.Capacity and bytesReturned are always the same.
                    // Since a large buffer is used, we are not affected.

                    // DeviceIoControlMethod.Buffered = 0,
                    // DeviceIoControlFileDevice.FileSystem = 9
                    // FsctlGetReparsePoint = (DeviceIoControlFileDevice.FileSystem << 16) | (42 << 2) | DeviceIoControlMethod.Buffered | (0 << 14)

                    if (!NativeMethods.DeviceIoControl(safeHandle, ((9 << 16) | (42 << 2) | 0 | (0 << 14)), IntPtr.Zero, 0, safeBuffer, (uint)safeBuffer.Capacity, out bytesReturned, IntPtr.Zero))
                    {
                        int lastError = Marshal.GetLastWin32Error();
                        switch ((uint)lastError)
                        {
                        case Win32Errors.ERROR_MORE_DATA:
                        case Win32Errors.ERROR_INSUFFICIENT_BUFFER:
                            if (safeBuffer.Capacity < bytesReturned)
                            {
                                safeBuffer.Close();
                                break;
                            }

                            // Throws IOException.
                            NativeError.ThrowException(lastError, true);
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                } while (true);



                // 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


                Type   toMountPointReparseBuffer   = typeof(NativeMethods.MountPointReparseBuffer);
                Type   toReparseDataBufferHeader   = typeof(NativeMethods.ReparseDataBufferHeader);
                Type   toSymbolicLinkReparseBuffer = typeof(NativeMethods.SymbolicLinkReparseBuffer);
                IntPtr marshalReparseBuffer        = Marshal.OffsetOf(toReparseDataBufferHeader, "data");

                NativeMethods.ReparseDataBufferHeader header = Utils.MarshalPtrToStructure <NativeMethods.ReparseDataBufferHeader>(0, buffer);

                IntPtr dataPos;
                byte[] dataBuffer;

                switch (header.ReparseTag)
                {
                case ReparsePointTag.MountPoint:
                    NativeMethods.MountPointReparseBuffer mprb = Utils.MarshalPtrToStructure <NativeMethods.MountPointReparseBuffer>(0, new IntPtr(buffer.ToInt64() + marshalReparseBuffer.ToInt64()));

                    dataPos    = new IntPtr(marshalReparseBuffer.ToInt64() + Marshal.OffsetOf(toMountPointReparseBuffer, "data").ToInt64());
                    dataBuffer = new byte[bytesReturned - dataPos.ToInt64()];

                    Marshal.Copy(new IntPtr(buffer.ToInt64() + dataPos.ToInt64()), dataBuffer, 0, dataBuffer.Length);

                    return(new LinkTargetInfo(
                               Encoding.Unicode.GetString(dataBuffer, mprb.SubstituteNameOffset, mprb.SubstituteNameLength),
                               Encoding.Unicode.GetString(dataBuffer, mprb.PrintNameOffset, mprb.PrintNameLength)));


                case ReparsePointTag.SymLink:
                    NativeMethods.SymbolicLinkReparseBuffer slrb = Utils.MarshalPtrToStructure <NativeMethods.SymbolicLinkReparseBuffer>(0, new IntPtr(buffer.ToInt64() + marshalReparseBuffer.ToInt64()));

                    dataPos    = new IntPtr(marshalReparseBuffer.ToInt64() + Marshal.OffsetOf(toSymbolicLinkReparseBuffer, "data").ToInt64());
                    dataBuffer = new byte[bytesReturned - dataPos.ToInt64()];

                    Marshal.Copy(new IntPtr(buffer.ToInt64() + dataPos.ToInt64()), dataBuffer, 0, dataBuffer.Length);

                    return(new SymbolicLinkTargetInfo(
                               Encoding.Unicode.GetString(dataBuffer, slrb.SubstituteNameOffset, slrb.SubstituteNameLength),
                               Encoding.Unicode.GetString(dataBuffer, slrb.PrintNameOffset, slrb.PrintNameLength), slrb.Flags));


                default:
                    throw new UnrecognizedReparsePointException();
                }
            }
        }