public void WindowsErrorToHresultMappings(WindowsError error, HRESULT expected) { HRESULT result = ErrorMacros.HRESULT_FROM_WIN32(error); result.Should().Be(expected); }
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)); } } }
public void OpenFileWithTrailingSeparator() { using (var cleaner = new TestFileCleaner()) { string testFile = cleaner.CreateTestFile(nameof(OpenFileWithTrailingSeparator)); string fullName = FileMethods.GetFullPathName(Paths.AddTrailingSeparator(testFile)); FindOperation <string> find = new FindOperation <string>(testFile); Action action = () => find.FirstOrDefault(); action.ShouldThrow <ArgumentException>().And.HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_INVALID_PARAMETER)); action = () => FileMethods.CreateFile(Paths.AddTrailingSeparator(testFile), CreationDisposition.OpenExisting, DesiredAccess.ReadAttributes); action.ShouldThrow <WInteropIOException>().And.HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_INVALID_NAME)); } }
public void CreateSymbolicLinkToLongPathFile() { using (var cleaner = new TestFileCleaner()) { string longPath = @"\\?\" + PathGenerator.CreatePathOfLength(cleaner.TempFolder, 500); FileHelper.CreateDirectoryRecursive(longPath); string filePath = cleaner.CreateTestFile("CreateSymbolicLinkToLongPathFile", longPath); string symbolicLink = cleaner.GetTestPath(); Action action = () => FileMethods.CreateSymbolicLink(symbolicLink, filePath); if (CanCreateSymbolicLinks()) { action(); var attributes = FileMethods.GetFileAttributes(symbolicLink); attributes.Should().HaveFlag(FileAttributes.ReparsePoint); } else { action.ShouldThrow <System.IO.IOException>().And.HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_PRIVILEGE_NOT_HELD)); } } }
public void LockedFileDirectoryDeletion() { using (var cleaner = new TestFileCleaner()) { string directory = cleaner.GetTestPath(); DirectoryMethods.CreateDirectory(directory); FileMethods.DirectoryExists(directory).Should().BeTrue(); string file = cleaner.CreateTestFile(nameof(LockedFileDirectoryDeletion), directory); using (var handle = FileMethods.CreateFile(file, CreationDisposition.OpenExisting, DesiredAccess.GenericRead, ShareModes.ReadWrite | ShareModes.Delete)) { handle.IsInvalid.Should().BeFalse(); // Mark the file for deletion FileMethods.DeleteFile(file); // RemoveDirectory API call will throw Action action = () => DirectoryMethods.RemoveDirectory(directory); action.ShouldThrow <WInteropIOException>().And.HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_DIR_NOT_EMPTY)); // Opening the directory for deletion will succeed, but have no impact using (var directoryHandle = FileMethods.CreateFile( directory, CreationDisposition.OpenExisting, DesiredAccess.ListDirectory | DesiredAccess.Delete, ShareModes.ReadWrite | ShareModes.Delete, FileAttributes.None, FileFlags.BackupSemantics | FileFlags.DeleteOnClose)) { directoryHandle.IsInvalid.Should().BeFalse(); } } // File will be gone now that the handle is closed FileMethods.FileExists(file).Should().BeFalse(); // But the directory will still exist as it doesn't respect DeleteOnClose with an open handle when it is closed FileMethods.DirectoryExists(directory).Should().BeTrue(); // Create a handle to the directory again with DeleteOnClose and it will actually delete the directory using (var directoryHandle = FileMethods.CreateFile( directory, CreationDisposition.OpenExisting, DesiredAccess.ListDirectory | DesiredAccess.Delete, ShareModes.ReadWrite | ShareModes.Delete, FileAttributes.None, FileFlags.BackupSemantics | FileFlags.DeleteOnClose)) { directoryHandle.IsInvalid.Should().BeFalse(); } FileMethods.DirectoryExists(directory).Should().BeFalse(); } }