From b0a21e76fedc6cd6d68f408534caef003d130a33 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 4 May 2015 02:22:07 +0100 Subject: [PATCH] Implemented NtCreateFile() calling to get file handles and NtClose() to dispose of them. --- Claunia.IO/ChangeLog | 8 + Claunia.IO/Claunia.IO.csproj | 2 + .../Interop/Windows/Interop.Windows.Files.cs | 198 +++++++++++++++ .../Interop/Windows/Interop.Windows.types.cs | 235 ++++++++++++++++++ 4 files changed, 443 insertions(+) create mode 100644 Claunia.IO/Interop/Windows/Interop.Windows.Files.cs create mode 100644 Claunia.IO/Interop/Windows/Interop.Windows.types.cs diff --git a/Claunia.IO/ChangeLog b/Claunia.IO/ChangeLog index e49c4a1..db4e9a9 100644 --- a/Claunia.IO/ChangeLog +++ b/Claunia.IO/ChangeLog @@ -1,3 +1,11 @@ +2015-05-04 Natalia Portillo + + * Claunia.IO.csproj: + * Interop/Windows/Interop.Windows.Files.cs: + * Interop/Windows/Interop.Windows.types.cs: + Implemented NtCreateFile() calling to get file handles and + NtClose() to dispose of them. + 2015-05-04 Natalia Portillo * Claunia.IO.csproj: diff --git a/Claunia.IO/Claunia.IO.csproj b/Claunia.IO/Claunia.IO.csproj index 29c2dad..d6f1413 100644 --- a/Claunia.IO/Claunia.IO.csproj +++ b/Claunia.IO/Claunia.IO.csproj @@ -70,6 +70,8 @@ + + diff --git a/Claunia.IO/Interop/Windows/Interop.Windows.Files.cs b/Claunia.IO/Interop/Windows/Interop.Windows.Files.cs new file mode 100644 index 0000000..c9d48c2 --- /dev/null +++ b/Claunia.IO/Interop/Windows/Interop.Windows.Files.cs @@ -0,0 +1,198 @@ +// +// Interop.Windows.Files.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2015 © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System.Runtime.InteropServices; +using System; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Windows + { + + public enum CreateDispositionFlags : uint + { + /// + /// Replaces the file if it exists. + /// Creates a new file if it does not. + /// + FILE_SUPERSEDE = 0x00000000, + /// + /// Opens the file if it exists, error otherwise. + /// + FILE_OPEN = 0x00000001, + /// + /// Create the file if it does not exists, error otherwise. + /// + FILE_CREATE = 0x00000002, + /// + /// Opens the file if it exists, creates it if it does not. + /// + FILE_OPEN_IF = 0x00000003, + /// + /// Overwrites the file if it exists, error otherwise. + /// + FILE_OVERWRITE = 0x00000004, + /// + /// Overwrites the file if it exists, creates it if it does not. + /// + FILE_OVERWRITE_IF = 0x00000005, + FILE_MAXIMUM_DISPOSITION = FILE_OVERWRITE_IF + } + + public enum CreateOptionsFlags : uint + { + /// + /// The file is a directory. + /// + FILE_DIRECTORY_FILE = 0x00000001, + /// + /// System services, file-system drivers, and drivers that write data to the file must actually transfer the data to the file before any requested write operation is considered complete. + /// + FILE_WRITE_THROUGH = 0x00000002, + /// + /// All access to the file will be sequential. + /// + FILE_SEQUENTIAL_ONLY = 0x00000004, + /// + /// The file cannot be cached or buffered in a driver's internal buffers. This flag is incompatible with the flag. + /// + FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008, + + /// + /// All operations on the file are performed synchronously. Any wait on behalf of the caller is subject to premature termination from alerts. This flag also causes the I/O system to maintain the file-position pointer. If this flag is set, must be set. + /// + FILE_SYNCHRONOUS_IO_ALERT = 0x00000010, + /// + /// All operations on the file are performed synchronously. Waits in the system that synchronize I/O queuing and completion are not subject to alerts. This flag also causes the I/O system to maintain the file-position context. If this flag is set, must be set. + /// + FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020, + /// + /// The file is not a directory. The file object to open can represent a data file; a logical, virtual, or physical device; or a volume. + /// + FILE_NON_DIRECTORY_FILE = 0x00000040, + /// + /// Create a tree connection for this file in order to open it over the network. + /// + FILE_CREATE_TREE_CONNECTION = 0x00000080, + + /// + /// Complete this operation immediately with an alternate success code of if the target file is oplocked, rather than blocking the caller's thread. If the file is oplocked, another caller already has access to the file. This flag is not used by device and intermediate drivers. + /// + FILE_COMPLETE_IF_OPLOCKED = 0x00000100, + /// + /// If the extended attributes (EAs) for an existing file being opened indicate that the caller must understand EAs to properly interpret the file, NtCreateFile should return an error. + /// + FILE_NO_EA_KNOWLEDGE = 0x00000200, + /// + /// Undocumented + /// + FILE_OPEN_REMOTE_INSTANCE = 0x00000400, + /// + /// Access to the file can be random, so no sequential read-ahead operations should be performed by file-system drivers or by the system. + /// + FILE_RANDOM_ACCESS = 0x00000800, + + /// + /// The system deletes the file when the last handle to the file is passed to NtClose. If this flag is set, the flag must be set. + /// + FILE_DELETE_ON_CLOSE = 0x00001000, + /// + /// The file name that is specified by the ObjectAttributes parameter includes a binary 8-byte or 16-byte file reference number or object ID for the file, depending on the file system. + /// + FILE_OPEN_BY_FILE_ID = 0x00002000, + /// + /// The file is being opened for backup intent. Therefore, the system should check for certain access rights and grant the caller the appropriate access to the file—before checking the DesiredAccess parameter against the file's security descriptor. + /// + FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000, + /// + /// Undocumented + /// + FILE_NO_COMPRESSION = 0x00008000, + + /// + /// The file is being opened and an opportunistic lock (oplock) on the file is being requested as a single atomic operation. The file system checks for oplocks before it performs the create operation, and will fail the create with a return code of if the result would be to break an existing oplock. + /// + FILE_OPEN_REQUIRING_OPLOCK = 0x00010000, + /// + /// Undocumented + /// + FILE_DISALLOW_EXCLUSIVE = 0x00020000, + + /// + /// This flag allows an application to request a Filter opportunistic lock (oplock) to prevent other applications from getting share violations. If there are already open handles, the create request will fail with . + /// + FILE_RESERVE_OPFILTER = 0x00100000, + /// + /// Open a file with a reparse point and bypass normal reparse point processing for the file. + /// + FILE_OPEN_REPARSE_POINT = 0x00200000, + /// + /// Undocumented + /// + FILE_OPEN_NO_RECALL = 0x00400000, + /// + /// Undocumented + /// + FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000, + + FILE_VALID_OPTION_FLAGS = 0x00ffffff, + FILE_VALID_PIPE_OPTION_FLAGS = 0x00000032, + FILE_VALID_MAILSLOT_OPTION_FLAGS = 0x00000032, + FILE_VALID_SET_FLAGS = 0x00000036 + } + + /// + /// Creates a new file or opens an existing file. + /// + /// ZwCreateFile returns on success or an appropriate error code on failure. In the latter case, the caller can determine the cause of the failure by checking the parameter. + /// A pointer to a HANDLE variable that receives a handle to the file. + /// Specifies an value that determines the requested access to the object. In addition to the access rights that are defined for all types of objects, the caller can specify any of the following access rights, which are specific to files. + /// A pointer to an structure that specifies the object name and other attributes. + /// A pointer to an structure that receives the final completion status and other information about the requested operation. + /// A pointer to a LARGE_INTEGER that contains the initial allocation size, in bytes, for a file that is created or overwritten. If AllocationSize is null, no allocation size is specified. If no file is created or overwritten, AllocationSize is ignored. + /// Specifies one or more FILE_ATTRIBUTE_XXX flags, which represent the file attributes to set if you create or overwrite a file. The caller usually specifies FILE_ATTRIBUTE_NORMAL, which sets the default attributes. For a list of valid FILE_ATTRIBUTE_XXX flags, see the CreateFile routine in the Microsoft Windows SDK documentation. If no file is created or overwritten, FileAttributes is ignored. + /// Type of share access. + /// Specifies the action to perform if the file does or does not exist. + /// Specifies the options to apply when the file is created or opened. + /// Pointer to a -structured buffer that contains the starting attributes to write to the file when creating, replacing or overwriting it. + /// Length of the buffer pointed by + [DllImport(Libraries.NTDLL)] + public static extern NTSTATUS NtCreateFile(out SafeFileHandle FileHandle, + ACCESS_MASK DesiredAccess, ref OBJECT_ATTRIBUTES ObjectAttributes, + ref IO_STATUS_BLOCK IoStatusBlock, ref long AllocationSize, uint FileAttributes, + System.IO.FileShare ShareAccess, CreateDispositionFlags CreateDisposition, CreateOptionsFlags CreateOptions, + IntPtr EaBuffer, uint EaLength); + + /// + /// Closes an object handle + /// + /// returns on success, or the appropriate error code on failure. In particular, it returns if Handle is not a valid handle, or if the calling thread does not have permission to close the handle. + /// Handle to an object of any type. + [DllImport(Libraries.NTDLL)] + public static extern NTSTATUS NtClose(SafeFileHandle handle); + } +} + diff --git a/Claunia.IO/Interop/Windows/Interop.Windows.types.cs b/Claunia.IO/Interop/Windows/Interop.Windows.types.cs new file mode 100644 index 0000000..43c242f --- /dev/null +++ b/Claunia.IO/Interop/Windows/Interop.Windows.types.cs @@ -0,0 +1,235 @@ +// +// Interop.Windows.types.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2015 © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System.Runtime.InteropServices; +using System; + +internal static partial class Interop +{ + internal static partial class Windows + { + [Flags] + public enum ACCESS_MASK : UInt32 + { + /// Right to read data from the file. (FILE) + FILE_READ_DATA = 0x00000001, + /// Right to list contents of a directory. (DIRECTORY) + FILE_LIST_DIRECTORY = 0x00000001, + + /// Right to write data to the file. (FILE) + FILE_WRITE_DATA = 0x00000002, + /// Right to create a file in the directory. (DIRECTORY) + FILE_ADD_FILE = 0x00000002, + + /// Right to append data to the file. (FILE) + FILE_APPEND_DATA = 0x00000004, + /// Right to create a subdirectory. (DIRECTORY) + FILE_ADD_SUBDIRECTORY = 0x00000004, + + /// Right to read extended attributes. (FILE/DIRECTORY) + FILE_READ_EA = 0x00000008, + + /// Right to write extended attributes. (FILE/DIRECTORY) + FILE_WRITE_EA = 0x00000010, + + /// Right to execute a file. (FILE) + FILE_EXECUTE = 0x00000020, + /// Right to traverse the directory. (DIRECTORY) + FILE_TRAVERSE = 0x00000020, + + /// + /// Right to delete a directory and all the files it contains (its + /// children, even if the files are read-only. (DIRECTORY) + /// + FILE_DELETE_CHILD = 0x00000040, + + /// Right to read file attributes. (FILE/DIRECTORY) + FILE_READ_ATTRIBUTES = 0x00000080, + + /// Right to change file attributes. (FILE/DIRECTORY) + FILE_WRITE_ATTRIBUTES = 0x00000100, + + /// + /// The standard rights (bits 16 to 23). Are independent of the type of + /// object being secured. + /// + + /// Right to delete the object. + DELETE = 0x00010000, + + /// + /// Right to read the information in the object's security descriptor, + /// not including the information in the SACL. I.e. right to read the + /// security descriptor and owner. + /// + READ_CONTROL = 0x00020000, + + /// Right to modify the DACL in the object's security descriptor. + WRITE_DAC = 0x00040000, + + /// Right to change the owner in the object's security descriptor. + WRITE_OWNER = 0x00080000, + + /// + /// Right to use the object for synchronization. Enables a process to + /// wait until the object is in the signalled state. Some object types + /// do not support this access right. + /// + SYNCHRONIZE = 0x00100000, + + /// + /// The following STANDARD_RIGHTS_* are combinations of the above for + /// convenience and are defined by the Win32 API. + /// + + /// These are currently defined to READ_CONTROL. + STANDARD_RIGHTS_READ = 0x00020000, + STANDARD_RIGHTS_WRITE = 0x00020000, + STANDARD_RIGHTS_EXECUTE = 0x00020000, + + /// Combines DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER access. + STANDARD_RIGHTS_REQUIRED = 0x000f0000, + + /// + /// Combines DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER, and + /// SYNCHRONIZE access. + /// + STANDARD_RIGHTS_ALL = 0x001f0000, + + /// + /// The access system ACL and maximum allowed access types (bits 24 to + /// 25, bits 26 to 27 are reserved). + /// + ACCESS_SYSTEM_SECURITY = 0x01000000, + MAXIMUM_ALLOWED = 0x02000000, + + /// + /// The generic rights (bits 28 to 31). These map onto the standard and + /// specific rights. + /// + + /// Read, write, and execute access. + GENERIC_ALL = 0x10000000, + + /// Execute access. + GENERIC_EXECUTE = 0x20000000, + + /// + /// Write access. For files, this maps onto: + /// FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | + /// FILE_WRITE_EA | STANDARD_RIGHTS_WRITE | SYNCHRONIZE + /// For directories, the mapping has the same numerical value. See + /// above for the descriptions of the rights granted. + /// + GENERIC_WRITE = 0x40000000, + + /// + /// Read access. For files, this maps onto: + /// FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA | + /// STANDARD_RIGHTS_READ | SYNCHRONIZE + /// For directories, the mapping has the same numerical value. See + /// above for the descriptions of the rights granted. + /// + GENERIC_READ = 0x80000000, + } + + [StructLayout(LayoutKind.Sequential)] + public struct UNICODE_STRING : IDisposable + { + public ushort Length; + public ushort MaximumLength; + private IntPtr buffer; + + public UNICODE_STRING(string s) + { + Length = (ushort)(s.Length * 2); + MaximumLength = (ushort)(Length + 2); + buffer = Marshal.StringToHGlobalUni(s); + } + + public void Dispose() + { + Marshal.FreeHGlobal(buffer); + buffer = IntPtr.Zero; + } + + public override string ToString() + { + return Marshal.PtrToStringUni(buffer); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct OBJECT_ATTRIBUTES : IDisposable + { + public int Length; + public IntPtr RootDirectory; + private IntPtr objectName; + public uint Attributes; + public IntPtr SecurityDescriptor; + public IntPtr SecurityQualityOfService; + + public OBJECT_ATTRIBUTES(string name, uint attrs) + { + Length = 0; + RootDirectory = IntPtr.Zero; + objectName = IntPtr.Zero; + Attributes = attrs; + SecurityDescriptor = IntPtr.Zero; + SecurityQualityOfService = IntPtr.Zero; + + Length = Marshal.SizeOf(this); + ObjectName = new UNICODE_STRING(name); + } + + public UNICODE_STRING ObjectName + { + get + { + return (UNICODE_STRING)Marshal.PtrToStructure( + objectName, typeof(UNICODE_STRING)); + } + + set + { + bool fDeleteOld = objectName != IntPtr.Zero; + if (!fDeleteOld) + objectName = Marshal.AllocHGlobal(Marshal.SizeOf(value)); + Marshal.StructureToPtr(value, objectName, fDeleteOld); + } + } + + public void Dispose() + { + if (objectName != IntPtr.Zero) + { + Marshal.DestroyStructure(objectName, typeof(UNICODE_STRING)); + Marshal.FreeHGlobal(objectName); + objectName = IntPtr.Zero; + } + } + } + } +} \ No newline at end of file