예제 #1
0
        public void CreateSymbolicLinkToFile()
        {
            using (var cleaner = new TestFileCleaner())
            {
                string filePath     = cleaner.CreateTestFile("CreateSymbolicLinkToFile");
                string symbolicLink = cleaner.GetTestPath();
                Action action       = () => FileMethods.CreateSymbolicLink(symbolicLink, filePath);

                if (CanCreateSymbolicLinks())
                {
                    action();
                    var attributes = FileMethods.GetFileAttributes(symbolicLink);
                    attributes.Should().HaveFlag(FileAttributes.ReparsePoint);

                    using (var handle = FileMethods.CreateFile(symbolicLink, CreationDisposition.OpenExisting, DesiredAccess.ReadExtendedAttributes,
                                                               ShareModes.All, fileFlags: FileFlags.OpenReparsePoint))
                    {
                        handle.IsInvalid.Should().BeFalse();
                        var(printName, substituteName, tag) = DeviceMethods.GetReparsePointNames(handle);
                        tag.Should().Be(ReparseTag.SymbolicLink);
                        printName.Should().Be(filePath);
                        substituteName.Should().Be(@"\??\" + filePath);
                    }
                }
                else
                {
                    // Can't create links unless you have admin rights SE_CREATE_SYMBOLIC_LINK_NAME SeCreateSymbolicLinkPrivilege
                    action.ShouldThrow <System.IO.IOException>().And.HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_PRIVILEGE_NOT_HELD));
                }
            }
        }
예제 #2
0
        public static IEnumerable <BackupStreamInformation> GetAlternateStreamInformation(string path)
        {
            List <BackupStreamInformation> streams = new List <BackupStreamInformation>();

            using (var fileHandle = FileMethods.CreateFile(
                       path: path,
                       // To look at metadata we don't need read or write access
                       desiredAccess: 0,
                       shareMode: ShareMode.FILE_SHARE_READWRITE,
                       creationDisposition: CreationDisposition.OPEN_EXISTING,
                       fileAttributes: FileAttributes.NONE,
                       fileFlags: FileFlags.FILE_FLAG_BACKUP_SEMANTICS))
            {
                using (BackupReader reader = new BackupReader(fileHandle))
                {
                    BackupStreamInformation?info;
                    while ((info = reader.GetNextInfo()).HasValue)
                    {
                        if (info.Value.StreamType == BackupStreamType.BACKUP_ALTERNATE_DATA)
                        {
                            streams.Add(new BackupStreamInformation {
                                Name = info.Value.Name, Size = info.Value.Size
                            });
                        }
                    }
                }
            }

            return(streams);
        }
예제 #3
0
        public void DeleteDirectoryBasic()
        {
            using (var temp = new TestFileCleaner())
            {
                string directoryPath = temp.GetTestPath();
                DirectoryMethods.CreateDirectory(directoryPath);
                using (var directory = FileMethods.CreateFile(directoryPath, 0, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING,
                                                              FileAttributes.FILE_ATTRIBUTE_DIRECTORY, FileFlags.FILE_FLAG_BACKUP_SEMANTICS))
                {
                    directory.IsInvalid.Should().BeFalse();
                }

                DirectoryMethods.RemoveDirectory(directoryPath);

                Action action = () =>
                {
                    using (var directory = FileMethods.CreateFile(directoryPath, 0, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING,
                                                                  FileAttributes.FILE_ATTRIBUTE_DIRECTORY, FileFlags.FILE_FLAG_BACKUP_SEMANTICS))
                    {
                    }
                };

                action.ShouldThrow <System.IO.FileNotFoundException>();
            }
        }
예제 #4
0
        public void GetBasicInfoByHandleBasic()
        {
            string tempPath     = FileMethods.GetTempPath();
            string tempFileName = System.IO.Path.Combine(tempPath, System.IO.Path.GetRandomFileName());

            try
            {
                using (var directory = FileMethods.CreateFile(tempPath, DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING,
                                                              FileAttributes.NONE, FileFlags.FILE_FLAG_BACKUP_SEMANTICS))
                {
                    var directoryInfo = FileMethods.GetFileBasicInfoByHandle(directory);
                    directoryInfo.Attributes.Should().HaveFlag(FileAttributes.FILE_ATTRIBUTE_DIRECTORY);

                    using (var file = FileMethods.CreateFile(tempFileName, DesiredAccess.GENERIC_READ | DesiredAccess.GENERIC_WRITE, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.CREATE_NEW))
                    {
                        var fileInfo = FileMethods.GetFileBasicInfoByHandle(file);
                        fileInfo.Attributes.Should().NotHaveFlag(FileAttributes.FILE_ATTRIBUTE_DIRECTORY);
                        fileInfo.CreationTime.Should().BeAfter(directoryInfo.CreationTime);
                    }
                }
            }
            finally
            {
                FileMethods.DeleteFile(tempFileName);
            }
        }
예제 #5
0
        public void GetStreamInfoByHandleBasic()
        {
            string tempPath     = FileMethods.GetTempPath();
            string tempFileName = System.IO.Path.Combine(tempPath, System.IO.Path.GetRandomFileName());

            try
            {
                using (var directory = FileMethods.CreateFile(tempPath, DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING,
                                                              FileAttributes.NONE, FileFlags.FILE_FLAG_BACKUP_SEMANTICS))
                {
                    var directoryInfo = FileMethods.GetStreamInformationByHandle(directory);
                    directoryInfo.Should().BeEmpty();

                    using (var file = FileMethods.CreateFile(tempFileName, DesiredAccess.GENERIC_READ | DesiredAccess.GENERIC_WRITE, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.CREATE_NEW))
                    {
                        var fileInfo = FileMethods.GetStreamInformationByHandle(file);
                        fileInfo.Should().HaveCount(1);
                        var info = fileInfo.First();
                        info.Name.Should().Be(@"::$DATA");
                        info.Size.Should().Be(0);
                        info.AllocationSize.Should().Be(0);
                    }
                }
            }
            finally
            {
                FileMethods.DeleteFile(tempFileName);
            }
        }
예제 #6
0
        public void FinalPathNameVolumeNameBehavior()
        {
            // This test is asserting that the original volume name has nothing to do with the volume GetFinalPathNameByHandle returns
            using (var cleaner = new TestFileCleaner())
            {
                string filePath = cleaner.CreateTestFile("FinalPathNameVolumeNameBehavior");

                using (var handle = FileMethods.CreateFile(filePath.ToLower(),
                                                           DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING))
                {
                    handle.IsInvalid.Should().BeFalse();

                    string extendedPath = @"\\?\" + filePath;
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.FILE_NAME_NORMALIZED)
                    .Should().Be(extendedPath);
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.FILE_NAME_OPENED)
                    .Should().Be(extendedPath);
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_DOS)
                    .Should().Be(extendedPath);
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_GUID)
                    .Should().StartWith(@"\\?\Volume");
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_NT)
                    .Should().StartWith(@"\Device\");
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_NONE)
                    .Should().Be(filePath.Substring(2));
                }
            }
        }
        public void GetFileAttributesBehavior_DeletedFile()
        {
            using (var cleaner = new TestFileCleaner())
            {
                string path = cleaner.CreateTestFile(nameof(GetFileAttributesBehavior_DeletedFile));
                using (var handle = FileMethods.CreateFile(path, CreationDisposition.OpenExisting, shareMode: ShareModes.All))
                {
                    handle.IsInvalid.Should().BeFalse();
                    FileMethods.FileExists(path).Should().BeTrue();
                    FileMethods.DeleteFile(path);

                    // With the file deleted and the handle still open the file will still physically exist.
                    // Trying to access the file via a handle at this point will fail with access denied.

                    Action action = () => FileMethods.FileExists(path);
                    action.ShouldThrow <UnauthorizedAccessException>();

                    action = () => FileMethods.CreateFile(path, CreationDisposition.OpenExisting, shareMode: ShareModes.All,
                                                          desiredAccess: DesiredAccess.ReadAttributes);
                    action.ShouldThrow <UnauthorizedAccessException>();

                    // Find file will work at this point.
                    IntPtr findHandle = FileMethods.Imports.FindFirstFileW(path, out WIN32_FIND_DATA findData);
                    findHandle.Should().NotBe(IntPtr.Zero);
                    try
                    {
                        findData.cFileName.CreateString().Should().Be(Paths.GetLastSegment(path));
                    }
                    finally
                    {
                        FileMethods.Imports.FindClose(findHandle);
                    }
                }
            }
        }
예제 #8
0
        public void GetMultipleStreamInfoByHandle()
        {
            using (var temp = new TestFileCleaner())
            {
                string source = temp.GetTestPath();
                using (var file = FileMethods.CreateFile(source, DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.CREATE_NEW))
                {
                    file.IsInvalid.Should().BeFalse();
                }

                string destination = temp.GetTestPath();
                FileMethods.CopyFile(source, destination);

                string alternateStream = destination + @":Foo:$DATA";
                FileMethods.CopyFile(source, alternateStream);

                using (var file = FileMethods.CreateFile(destination, DesiredAccess.GENERIC_READ | DesiredAccess.GENERIC_WRITE, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING))
                {
                    var fileInfo = FileMethods.GetStreamInformationByHandle(file);
                    fileInfo.Should().BeEquivalentTo(new StreamInformation[]
                    {
                        new StreamInformation {
                            Name = @"::$DATA"
                        },
                        new StreamInformation {
                            Name = @":Foo:$DATA"
                        }
                    });
                }
            }
        }
예제 #9
0
        public void FinalPathNameLongPath()
        {
            using (var cleaner = new TestFileCleaner())
            {
                string longPath = @"\\?\" + PathGenerator.CreatePathOfLength(cleaner.TempFolder, 500);
                string filePath = Paths.Combine(longPath, System.IO.Path.GetRandomFileName());

                FileHelper.CreateDirectoryRecursive(longPath);
                FileHelper.WriteAllText(filePath, "FinalPathNameLongPathPrefixRoundTripBehavior");

                using (var handle = FileMethods.CreateFile(filePath,
                                                           DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING))
                {
                    handle.IsInvalid.Should().BeFalse();

                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.FILE_NAME_NORMALIZED)
                    .Should().Be(filePath);
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.FILE_NAME_OPENED)
                    .Should().Be(filePath);
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_DOS)
                    .Should().Be(filePath);
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_GUID)
                    .Should().StartWith(@"\\?\Volume");
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_NT)
                    .Should().StartWith(@"\Device\");
                    FileDesktopMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_NONE)
                    .Should().Be(filePath.Substring(6));
                }
            }
        }
예제 #10
0
        public void FinalPathNameBasic()
        {
            using (var cleaner = new TestFileCleaner())
            {
                string filePath = cleaner.CreateTestFile("FinalPathNameBehavior");

                using (var handle = FileMethods.CreateFile(filePath.ToLower(), CreationDisposition.OpenExisting, DesiredAccess.GenericRead))
                {
                    handle.IsInvalid.Should().BeFalse();

                    string extendedPath = @"\\?\" + filePath;
                    FileMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.FILE_NAME_NORMALIZED)
                    .Should().Be(extendedPath);
                    FileMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.FILE_NAME_OPENED)
                    .Should().Be(extendedPath);
                    FileMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_DOS)
                    .Should().Be(extendedPath);
                    FileMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_GUID)
                    .Should().StartWith(@"\\?\Volume");
                    FileMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_NT)
                    .Should().StartWith(@"\Device\");
                    FileMethods.GetFinalPathNameByHandle(handle, GetFinalPathNameByHandleFlags.VOLUME_NAME_NONE)
                    .Should().Be(filePath.Substring(2));
                }
            }
        }
예제 #11
0
        public void GetMultipleStreamInfoByHandle()
        {
            using (var temp = new TestFileCleaner())
            {
                string source = temp.GetTestPath();
                using (var file = FileMethods.CreateFile(source, CreationDisposition.CreateNew))
                {
                    file.IsInvalid.Should().BeFalse();
                }

                string destination = temp.GetTestPath();
                FileMethods.CopyFile(source, destination);

                string alternateStream = destination + @":Foo:$DATA";
                FileMethods.CopyFile(source, alternateStream);

                using (var file = FileMethods.CreateFile(destination, CreationDisposition.OpenExisting))
                {
                    var fileInfo = FileMethods.GetStreamInformation(file);
                    fileInfo.Should().BeEquivalentTo(new StreamInformation[]
                    {
                        new StreamInformation {
                            Name = @"::$DATA"
                        },
                        new StreamInformation {
                            Name = @":Foo:$DATA"
                        }
                    });
                }
            }
        }
예제 #12
0
        public void GetShortNameBasic()
        {
            string tempPath = FileMethods.GetTempPath();

            using (var directory = DirectoryMethods.CreateDirectoryHandle(tempPath))
            {
                // This will give back the NT volume path (\Device\HarddiskVolumen\)
                string directoryName = FileMethods.GetShortName(directory);
                directoryName.Should().Be("Temp");

                string tempFileName = "ExtraLongName" + System.IO.Path.GetRandomFileName();
                string tempFilePath = System.IO.Path.Combine(tempPath, tempFileName);
                try
                {
                    using (var file = FileMethods.CreateFile(tempFilePath, CreationDisposition.CreateNew, DesiredAccess.GenericRead))
                    {
                        string fileName = FileMethods.GetShortName(file);
                        fileName.Length.Should().BeLessOrEqualTo(12);
                    }
                }
                finally
                {
                    FileMethods.DeleteFile(tempFilePath);
                }
            }
        }
예제 #13
0
        public void GetStandardInfoByHandleBasic()
        {
            string tempPath     = FileMethods.GetTempPath();
            string tempFileName = System.IO.Path.Combine(tempPath, System.IO.Path.GetRandomFileName());

            try
            {
                using (var directory = FileMethods.CreateFile(tempPath, DesiredAccess.GENERIC_READWRITE, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING,
                                                              FileAttributes.NONE, FileFlags.FILE_FLAG_BACKUP_SEMANTICS))
                {
                    var info = FileMethods.GetFileStandardInfoByHandle(directory);
                    info.Directory.Should().BeTrue();
                }

                using (var file = FileMethods.CreateFile(tempFileName, DesiredAccess.GENERIC_READWRITE, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.CREATE_NEW))
                {
                    var info = FileMethods.GetFileStandardInfoByHandle(file);
                    info.Directory.Should().BeFalse();
                    info.NumberOfLinks.Should().Be(1);
                    info.DeletePending.Should().BeFalse();
                    info.AllocationSize.Should().Be(0);
                    info.EndOfFile.Should().Be(0);
                }
            }
            finally
            {
                FileMethods.DeleteFile(tempFileName);
            }
        }
예제 #14
0
        public void GetShortNameBasic()
        {
            string tempPath = FileMethods.GetTempPath();

            using (var directory = FileMethods.CreateFile(tempPath, DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING,
                                                          FileAttributes.NONE, FileFlags.FILE_FLAG_BACKUP_SEMANTICS))
            {
                // This will give back the NT volume path (\Device\HarddiskVolumen\)
                string directoryName = FileDesktopMethods.GetShortName(directory);
                directoryName.Should().Be("Temp");

                string tempFileName = "ExtraLongName" + System.IO.Path.GetRandomFileName();
                string tempFilePath = System.IO.Path.Combine(tempPath, tempFileName);
                try
                {
                    using (var file = FileMethods.CreateFile(tempFilePath, DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.CREATE_NEW))
                    {
                        string fileName = FileDesktopMethods.GetShortName(file);
                        fileName.Length.Should().BeLessOrEqualTo(12);
                    }
                }
                finally
                {
                    FileMethods.DeleteFile(tempFilePath);
                }
            }
        }
예제 #15
0
 public void QueryDeviceName()
 {
     // Need to open the handle with no rights (desiredAccess: 0) to avoid needing to run as admin
     using (var handle = FileMethods.CreateFile(@"\\.\C:", CreationDisposition.OpenExisting, desiredAccess: 0))
     {
         DeviceMethods.QueryDeviceName(handle).Should().StartWith(@"\Device\HarddiskVolume");
     }
 }
예제 #16
0
 public void QueryStableGuid()
 {
     // Need to open the handle with no rights (desiredAccess: 0) to avoid needing to run as admin
     using (var handle = FileMethods.CreateFile(@"\\.\C:", CreationDisposition.OpenExisting, desiredAccess: 0))
     {
         DeviceMethods.QueryStableGuid(handle).Should().NotBe(Guid.Empty);
     }
 }
예제 #17
0
 public void CreateFileComPort()
 {
     using (var file = FileMethods.CreateFile(@"COM4", CreationDisposition.OpenExisting, DesiredAccess.GenericRead))
     {
         file.IsInvalid.Should().BeFalse();
         FileMethods.GetFileType(file).Should().Be(FileType.Character);
     }
 }
예제 #18
0
 public void CreateFileHarddiskVolume()
 {
     using (var file = FileMethods.CreateFile(@"\\?\GLOBALROOT\Device\HarddiskVolume1", CreationDisposition.OpenExisting, DesiredAccess.GenericRead))
     {
         file.IsInvalid.Should().BeFalse();
         FileMethods.GetFileType(file).Should().Be(FileType.Disk);
     }
 }
예제 #19
0
 public void CreateFileRawParition()
 {
     // You can't open with read/write access unless running elevated
     using (var file = FileMethods.CreateFile(@"\\?\GLOBALROOT\Device\Harddisk0\Partition0", CreationDisposition.OpenExisting, 0))
     {
         file.IsInvalid.Should().BeFalse();
         FileMethods.GetFileType(file).Should().Be(FileType.Disk);
     }
 }
예제 #20
0
 public void CreateFileHarddiskVolume()
 {
     using (var file = FileMethods.CreateFile(@"\\?\GLOBALROOT\Device\HarddiskVolume1",
                                              DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING))
     {
         file.IsInvalid.Should().BeFalse();
         FileMethods.GetFileType(file).Should().Be(FileType.FILE_TYPE_DISK);
     }
 }
예제 #21
0
 /// <summary>
 /// Simple wrapper to allow creating a file handle for an existing directory.
 /// </summary>
 public static SafeFileHandle CreateDirectoryHandle(string directoryPath, DesiredAccess desiredAccess = DesiredAccess.ListDirectory)
 {
     return(FileMethods.CreateFile(
                directoryPath,
                CreationDisposition.OpenExisting,
                desiredAccess,
                ShareModes.ReadWrite | ShareModes.Delete,
                FileAttributes.None,
                FileFlags.BackupSemantics));
 }
예제 #22
0
 public void GetFilePositionForEmptyFile()
 {
     using (var temp = new TestFileCleaner())
     {
         using (var fileHandle = FileMethods.CreateFile(temp.GetTestPath(), CreationDisposition.CreateNew, DesiredAccess.GenericReadWrite, 0))
         {
             FileMethods.SetFilePointer(fileHandle, 0, MoveMethod.Current).Should().Be(0);
         }
     }
 }
예제 #23
0
        public void QueryInterfaceName()
        {
            // TODO: Need to conditionalize this on RS1

            // Need to open the handle with no rights (desiredAccess: 0) to avoid needing to run as admin
            using (var handle = FileMethods.CreateFile(@"\\.\C:", CreationDisposition.OpenExisting, desiredAccess: 0))
            {
                DeviceMethods.QueryInterfacename(handle).Should().StartWith(@"\\?\STORAGE#Volume#{");
            }
        }
예제 #24
0
 public void GetEmptyFileSize()
 {
     using (var temp = new TestFileCleaner())
     {
         using (var fileHandle = FileMethods.CreateFile(temp.GetTestPath(), CreationDisposition.CreateNew, DesiredAccess.GenericReadWrite, 0))
         {
             FileMethods.GetFileSize(fileHandle).Should().Be(0);
         }
     }
 }
예제 #25
0
 public void QuerySuggestedLinkName()
 {
     // Need to open the handle with no rights (desiredAccess: 0) to avoid needing to run as admin
     using (var handle = FileMethods.CreateFile(@"\\.\C:", CreationDisposition.OpenExisting, desiredAccess: 0))
     {
         Action action = () => DeviceMethods.QuerySuggestedLinkName(handle);
         action.ShouldThrow <WInteropIOException>("this is an optional query, not aware of which drivers support this").
         And.HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_NOT_FOUND));
     }
 }
예제 #26
0
 public void FileTypeOfFile()
 {
     using (var cleaner = new TestFileCleaner())
     {
         using (var testFile = FileMethods.CreateFile(cleaner.GetTestPath(), CreationDisposition.CreateNew))
         {
             FileMethods.GetFileType(testFile).Should().Be(FileType.Disk);
         }
     }
 }
예제 #27
0
 public void CreateFileRawParition()
 {
     // You can't open with read/write access unless running elevated
     using (var file = FileMethods.CreateFile(@"\\?\GLOBALROOT\Device\Harddisk0\Partition0",
                                              DesiredAccess.NONE, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING))
     {
         file.IsInvalid.Should().BeFalse();
         FileMethods.GetFileType(file).Should().Be(FileType.FILE_TYPE_DISK);
     }
 }
예제 #28
0
 public void CreateFileOpenDriveRoot()
 {
     StoreHelper.ValidateStoreGetsUnauthorizedAccess(() =>
     {
         using (var file = FileMethods.CreateFile(@"C:\.", 0, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING,
                                                  FileAttributes.NONE, FileFlags.FILE_FLAG_BACKUP_SEMANTICS))
         {
             file.IsInvalid.Should().BeFalse();
         }
     });
 }
예제 #29
0
        /// <summary>
        /// Gets the DOS drive letter for the given volume if it has one.
        /// </summary>
        public unsafe static string QueryDosVolumePath(string volume)
        {
            var mountManager = FileMethods.CreateFile(
                @"\\?\MountPointManager", CreationDisposition.OpenExisting, 0);

            ControlCode controlCode = ControlCodes.MountManager.QueryDosVolumePath;

            // Read ulong then get string
            string dosVolumePath = null;

            BufferHelper.BufferInvoke((StringBuffer inBuffer) =>
            {
                // The input is MOUNTMGR_TARGET_NAME which is a short length in bytes followed by the unicode string
                // https://msdn.microsoft.com/en-us/library/windows/hardware/ff562289.aspx

                inBuffer.Append((char)(volume.Length * sizeof(char)));
                inBuffer.Append(volume);

                BufferHelper.BufferInvoke((StringBuffer outBuffer) =>
                {
                    // Give enough for roughly 50 characters for a start
                    outBuffer.EnsureCharCapacity(50);

                    while (!Imports.DeviceIoControl(
                               hDevice: mountManager,
                               dwIoControlCode: controlCode,
                               lpInBuffer: inBuffer.VoidPointer,
                               nInBufferSize: checked ((uint)inBuffer.ByteCapacity),
                               lpOutBuffer: outBuffer.VoidPointer,
                               nOutBufferSize: checked ((uint)outBuffer.ByteCapacity),
                               lpBytesReturned: out _,
                               lpOverlapped: null))
                    {
                        WindowsError error = Errors.GetLastError();
                        switch (error)
                        {
                        case WindowsError.ERROR_MORE_DATA:
                            outBuffer.EnsureByteCapacity(checked (outBuffer.ByteCapacity * 2));
                            break;

                        default:
                            throw Errors.GetIoExceptionForError(error, volume);
                        }
                    }

                    // MOUNTMGR_VOLUME_PATHS is a uint length followed by a multi string (double null terminated)
                    // we only care about the first string in this case (should only be one?) so we can skip beyond
                    // the 4 bytes and read to null.
                    dosVolumePath = new string(outBuffer.CharPointer + 2);
                });
            });

            return(dosVolumePath);
        }
예제 #30
0
 public void CanCreateHandleToMountPointManager()
 {
     StoreHelper.ValidateStoreGetsUnauthorizedAccess(() =>
     {
         using (var mountPointManager = FileMethods.CreateFile(
                    @"\\.\MountPointManager", CreationDisposition.OpenExisting, 0, ShareModes.ReadWrite, FileAttributes.Normal))
         {
             mountPointManager.IsInvalid.Should().BeFalse();
         }
     });
 }