public void RegisterClass_UnregisterClassName() { WindowClass myClass = new WindowClass { ClassName = "RegisterClass_UnregisterClassName", Style = ClassStyle.HorizontalRedraw, WindowProcedure = CallDefaultProcedure }; Atom atom = WindowMethods.RegisterClass(ref myClass); atom.IsValid.Should().BeTrue(); try { var info = WindowMethods.GetClassInfo(ModuleMethods.GetModuleHandle(null), "RegisterClass_UnregisterClassName"); info.ClassName.Should().Be("RegisterClass_UnregisterClassName"); info.ClassAtom.Should().Be(Atom.Null); info.Style.Should().Be(ClassStyle.HorizontalRedraw); } finally { WindowMethods.UnregisterClass("RegisterClass_UnregisterClassName", null); Action action = () => WindowMethods.GetClassInfo(ModuleMethods.GetModuleHandle(null), "RegisterClass_UnregisterClassName"); action.ShouldThrow <IOException>().And .HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_CLASS_DOES_NOT_EXIST)); } }
public void RegisterClass_UnregisterActiveWindow() { WindowClass myClass = new WindowClass { ClassName = "RegisterClass_UnregisterActiveWindow", WindowProcedure = CallDefaultProcedure, }; Atom atom = WindowMethods.RegisterClass(ref myClass); atom.IsValid.Should().BeTrue(); try { WindowHandle window = WindowMethods.CreateWindow(atom, "RegisterClass_UnregisterActiveWindow", WindowStyles.Diabled | WindowStyles.Minimize); window.IsValid.Should().BeTrue(); try { Action action = () => WindowMethods.UnregisterClass(atom, null); action.ShouldThrow <IOException>().And .HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_CLASS_HAS_WINDOWS)); } finally { WindowMethods.DestroyWindow(window); } } finally { WindowMethods.UnregisterClass(atom, null); } }
public void GetClassInfo_NotRegistered() { Action action = () => WindowMethods.GetClassInfo(null, Path.GetRandomFileName()); action.ShouldThrow <IOException>().And .HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_CLASS_DOES_NOT_EXIST)); }
/// <summary> /// Get the type name of the given object. /// </summary> public static string GetObjectType(SafeHandle handle) { using (HeapBuffer buffer = new HeapBuffer()) { NTSTATUS status = NTSTATUS.STATUS_BUFFER_OVERFLOW; // We'll initially give room for 50 characters for the type name uint returnLength = (uint)Marshal.SizeOf <OBJECT_TYPE_INFORMATION>() + 50 * sizeof(char); while (status == NTSTATUS.STATUS_BUFFER_OVERFLOW || status == NTSTATUS.STATUS_BUFFER_TOO_SMALL || status == NTSTATUS.STATUS_INFO_LENGTH_MISMATCH) { buffer.EnsureByteCapacity(returnLength); status = Direct.NtQueryObject( Handle: handle, ObjectInformationClass: OBJECT_INFORMATION_CLASS.ObjectTypeInformation, ObjectInformation: buffer.DangerousGetHandle(), ObjectInformationLength: checked ((uint)buffer.ByteCapacity), ReturnLength: out returnLength); } if (!ErrorMacros.NT_SUCCESS(status)) { throw ErrorHelper.GetIoExceptionForNTStatus(status); } return(new CheckedReader(buffer).ReadStruct <OBJECT_TYPE_INFORMATION>().TypeName.ToString()); } }
public static unsafe void ToUpperInvariant(ref UNICODE_STRING value) { NTSTATUS status = Imports.RtlUpcaseUnicodeString( (UNICODE_STRING *)Structs.AddressOf(ref value), (UNICODE_STRING *)Structs.AddressOf(ref value), false); if (!ErrorMacros.NT_SUCCESS(status)) { ErrorMethods.GetIoExceptionForNTStatus(status); } }
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)); } }
public void CopyFile_NotOverExisting(bool useCreateFile) { using (var cleaner = new TestFileCleaner()) { string source = cleaner.CreateTestFile(CompressedFile2); string destination = cleaner.CreateTestFile($"CopyFile_NotOverExisting({useCreateFile})"); Action action = () => CompressionMethods.LzCopyFile(source, destination, overwrite: false, useCreateFile: useCreateFile); action.ShouldThrow <IOException>().And.HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_FILE_EXISTS)); } }
/// <summary> /// CopyFile2 wrapper. Only available on Windows8 and above. /// </summary> public static void CopyFile2(string source, string destination, bool overwrite = false) { unsafe { int cancel = 0; COPYFILE2_EXTENDED_PARAMETERS parameters = new COPYFILE2_EXTENDED_PARAMETERS(); parameters.dwSize = (uint)Marshal.SizeOf <COPYFILE2_EXTENDED_PARAMETERS>(); parameters.pfCanel = &cancel; parameters.dwCopyFlags = overwrite ? 0 : CopyFileFlags.COPY_FILE_FAIL_IF_EXISTS; HRESULT hr = Direct.CopyFile2(source, destination, ¶meters); if (ErrorMacros.FAILED(hr)) { throw ErrorHelper.GetIoExceptionForHResult(hr, source); } } }
/// <summary> /// CopyFile2 wrapper. Only available on Windows8 and above. /// </summary> public static void CopyFile2(string source, string destination, bool overwrite = false) { unsafe { int cancel = 0; COPYFILE2_EXTENDED_PARAMETERS parameters = new COPYFILE2_EXTENDED_PARAMETERS() { dwSize = (uint)sizeof(COPYFILE2_EXTENDED_PARAMETERS), pfCanel = &cancel, dwCopyFlags = overwrite ? 0 : CopyFileFlags.COPY_FILE_FAIL_IF_EXISTS }; HRESULT hr = Imports.CopyFile2(source, destination, ¶meters); if (ErrorMacros.FAILED(hr)) { throw Errors.GetIoExceptionForHResult(hr, source); } } }
/// <summary> /// Get the name fot he given handle. This is typically the NT path of the object. /// </summary> public static string GetObjectName(SafeHandle handle) { // IoQueryFileDosDeviceName wraps this for file handles, but requires calling ExFreePool to free the allocated memory // https://msdn.microsoft.com/en-us/library/windows/hardware/ff548474.aspx // // http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FType%20independed%2FOBJECT_NAME_INFORMATION.html // // typedef struct _OBJECT_NAME_INFORMATION // { // UNICODE_STRING Name; // WCHAR NameBuffer[0]; // } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; // // The above definition means the API expects a buffer where it can stick a UNICODE_STRING with the buffer immediately following. using (HeapBuffer buffer = new HeapBuffer()) { NTSTATUS status = NTSTATUS.STATUS_BUFFER_OVERFLOW; uint returnLength = 260 * sizeof(char); while (status == NTSTATUS.STATUS_BUFFER_OVERFLOW || status == NTSTATUS.STATUS_BUFFER_TOO_SMALL) { buffer.EnsureByteCapacity(returnLength); status = Direct.NtQueryObject( Handle: handle, ObjectInformationClass: OBJECT_INFORMATION_CLASS.ObjectNameInformation, ObjectInformation: buffer.DangerousGetHandle(), ObjectInformationLength: checked ((uint)buffer.ByteCapacity), ReturnLength: out returnLength); } if (!ErrorMacros.NT_SUCCESS(status)) { throw ErrorHelper.GetIoExceptionForNTStatus(status); } return(new CheckedReader(buffer).ReadStruct <UNICODE_STRING>().ToString()); } }
public DriveNotReadyException(string message, Exception innerException) : base(message, innerException) { HResult = (int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_NOT_READY); }
public DriveNotReadyException() : base() { HResult = (int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_NOT_READY); }
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 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 WindowsErrorToHresultMappings(WindowsError error, HRESULT expected) { HRESULT result = ErrorMacros.HRESULT_FROM_WIN32(error); result.Should().Be(expected); }
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(); } }
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 = () => FileDesktopMethods.CreateSymbolicLink(symbolicLink, filePath); if (CanCreateSymbolicLinks()) { action(); var attributes = FileDesktopMethods.GetFileAttributes(symbolicLink); attributes.Should().HaveFlag(FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT); } else { action.ShouldThrow <System.IO.IOException>().And.HResult.Should().Be((int)ErrorMacros.HRESULT_FROM_WIN32(WindowsError.ERROR_PRIVILEGE_NOT_HELD)); } } }
public void CreateSymbolicLinkToFile() { using (var cleaner = new TestFileCleaner()) { string filePath = cleaner.CreateTestFile("CreateSymbolicLinkToFile"); string symbolicLink = cleaner.GetTestPath(); Action action = () => FileDesktopMethods.CreateSymbolicLink(symbolicLink, filePath); if (CanCreateSymbolicLinks()) { action(); var attributes = FileDesktopMethods.GetFileAttributes(symbolicLink); attributes.Should().HaveFlag(FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT); } 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)); } } }