/// <summary> /// Enumerates rights explicitly given to the specified SID. If the given SID /// doesn't have any directly applied rights, returns an empty collection. /// </summary> public static IEnumerable <string> LsaEnumerateAccountRights(LsaHandle policyHandle, ref SID sid) { NTSTATUS status = Imports.LsaEnumerateAccountRights(policyHandle, ref sid, out var rightsBuffer, out uint rightsCount); switch (status) { case NTSTATUS.STATUS_OBJECT_NAME_NOT_FOUND: return(Enumerable.Empty <string>()); case NTSTATUS.STATUS_SUCCESS: break; default: throw ErrorMethods.GetIoExceptionForNTStatus(status); } List <string> rights = new List <string>(); Reader reader = new Reader(rightsBuffer); for (int i = 0; i < rightsCount; i++) { rights.Add(reader.ReadUNICODE_STRING()); } return(rights); }
/// <summary> /// Get the ids for all processes that have a handle to this file system object. /// Does not include the current process. /// </summary> public unsafe static IEnumerable <UIntPtr> GetProcessIds(SafeFileHandle fileHandle) { return(BufferHelper.BufferInvoke((HeapBuffer buffer) => { NTSTATUS status = NTSTATUS.STATUS_INFO_LENGTH_MISMATCH; while (status == NTSTATUS.STATUS_INFO_LENGTH_MISMATCH) { status = Imports.NtQueryInformationFile(fileHandle, out IO_STATUS_BLOCK statusBlock, buffer.VoidPointer, (uint)buffer.ByteCapacity, FileInformationClass.FileProcessIdsUsingFileInformation); switch (status) { case NTSTATUS.STATUS_SUCCESS: break; case NTSTATUS.STATUS_INFO_LENGTH_MISMATCH: // Not a big enough buffer buffer.EnsureByteCapacity((ulong)statusBlock.Information); break; default: throw ErrorMethods.GetIoExceptionForNTStatus(status); } } return ((FILE_PROCESS_IDS_USING_FILE_INFORMATION *)buffer.VoidPointer)->ProcessIdList.ToArray(); })); }
private void GetData() { NTSTATUS status = FileMethods.Imports.NtQueryDirectoryFile( FileHandle: _directory, Event: IntPtr.Zero, ApcRoutine: null, ApcContext: IntPtr.Zero, IoStatusBlock: out IO_STATUS_BLOCK statusBlock, FileInformation: _buffer.VoidPointer, Length: (uint)_buffer.ByteCapacity, FileInformationClass: FileInformationClass.FileFullDirectoryInformation, ReturnSingleEntry: false, FileName: null, RestartScan: false); switch (status) { case NTSTATUS.STATUS_NO_MORE_FILES: NoMoreFiles(); return; case NTSTATUS.STATUS_SUCCESS: Debug.Assert(statusBlock.Information.ToInt64() != 0); break; default: throw ErrorMethods.GetIoExceptionForNTStatus(status); } }
public static void LsaFreeMemory(IntPtr handle) { NTSTATUS status = Imports.LsaFreeMemory(handle); if (status != NTSTATUS.STATUS_SUCCESS) { throw ErrorMethods.GetIoExceptionForNTStatus(status); } }
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); } }
/// <summary> /// Get the access rights applied to the given file handle. /// </summary> public unsafe static FileAccessRights GetRights(SafeFileHandle fileHandle) { FILE_ACCESS_INFORMATION access = new FILE_ACCESS_INFORMATION(); NTSTATUS result = Imports.NtQueryInformationFile(fileHandle, out _, &access, (uint)sizeof(FILE_ACCESS_INFORMATION), FileInformationClass.FileAccessInformation); if (result != NTSTATUS.STATUS_SUCCESS) { throw ErrorMethods.GetIoExceptionForNTStatus(result); } return(access.AccessFlags); }
unsafe private static void GetFileInformation(SafeFileHandle fileHandle, FileInformationClass fileInformationClass, void *value, uint size) { NTSTATUS status = Imports.NtQueryInformationFile( FileHandle: fileHandle, IoStatusBlock: out _, FileInformation: value, Length: size, FileInformationClass: fileInformationClass); if (status != NTSTATUS.STATUS_SUCCESS) { throw ErrorMethods.GetIoExceptionForNTStatus(status); } }
public static LsaHandle LsaOpenLocalPolicy(PolicyAccessRights access) { LSA_OBJECT_ATTRIBUTES attributes = new LSA_OBJECT_ATTRIBUTES(); LsaHandle handle; NTSTATUS status; unsafe { status = Imports.LsaOpenPolicy(null, &attributes, access, out handle); } if (status != NTSTATUS.STATUS_SUCCESS) { throw ErrorMethods.GetIoExceptionForNTStatus(status); } return(handle); }
// Windows Kernel Architecture Internals // http://research.microsoft.com/en-us/um/redmond/events/wincore2010/Dave_Probert_1.pdf // Object Manager Routines (kernel-mode file systems and file system filter drivers) // https://msdn.microsoft.com/en-us/library/windows/hardware/ff550969.aspx // https://msdn.microsoft.com/en-us/library/windows/hardware/ff557759.aspx // Managing Kernel Objects // https://msdn.microsoft.com/en-us/library/windows/hardware/ff554383.aspx /// <summary> /// Open a handle to a directory object at the given NT path. /// </summary> public static DirectoryObjectHandle OpenDirectoryObject( string path, DirectoryObjectRights desiredAccess = DirectoryObjectRights.Query) { return((DirectoryObjectHandle)OpenObjectHelper(path, (attributes) => { NTSTATUS status = Imports.NtOpenDirectoryObject( DirectoryHandle: out var directory, DesiredAccess: desiredAccess, ObjectAttributes: ref attributes); if (status != NTSTATUS.STATUS_SUCCESS) { throw ErrorMethods.GetIoExceptionForNTStatus(status, path); } return directory; }));
public unsafe static string QueryKeyName(RegistryKeyHandle key) { return(BufferHelper.BufferInvoke((HeapBuffer buffer) => { NTSTATUS status; uint resultLength; while ((status = Imports.NtQueryKey(key, KEY_INFORMATION_CLASS.KeyNameInformation, buffer.VoidPointer, (uint)buffer.ByteCapacity, out resultLength)) == NTSTATUS.STATUS_BUFFER_TOO_SMALL || status == NTSTATUS.STATUS_BUFFER_OVERFLOW) { buffer.EnsureByteCapacity(resultLength); } if (status != NTSTATUS.STATUS_SUCCESS) { ErrorMethods.GetIoExceptionForNTStatus(status); } return ((KEY_NAME_INFORMATION *)buffer.VoidPointer)->Name.CreateString(); })); }
public unsafe static IntPtr CreateFileRelative( ReadOnlySpan <char> path, IntPtr rootDirectory, CreateDisposition createDisposition, DesiredAccess desiredAccess = DesiredAccess.GenericReadWrite | DesiredAccess.Synchronize, ShareModes shareAccess = ShareModes.ReadWrite, FileAttributes fileAttributes = FileAttributes.None, CreateOptions createOptions = CreateOptions.SynchronousIoNonalert, ObjectAttributes objectAttributes = ObjectAttributes.CaseInsensitive) { fixed(char *c = &path.DangerousGetPinnableReference()) { UNICODE_STRING name = new UNICODE_STRING(c, path.Length); OBJECT_ATTRIBUTES attributes = new OBJECT_ATTRIBUTES( &name, objectAttributes, rootDirectory, null, null); NTSTATUS status = Imports.NtCreateFile( out IntPtr handle, desiredAccess, ref attributes, out IO_STATUS_BLOCK statusBlock, AllocationSize: null, FileAttributes: fileAttributes, ShareAccess: shareAccess, CreateDisposition: createDisposition, CreateOptions: createOptions, EaBuffer: null, EaLength: 0); if (status != NTSTATUS.STATUS_SUCCESS) { throw ErrorMethods.GetIoExceptionForNTStatus(status, path.ToString()); } return(handle); } }
private unsafe static string GetFileInformationString(SafeFileHandle fileHandle, FileInformationClass fileInformationClass) { return(BufferHelper.BufferInvoke((HeapBuffer buffer) => { NTSTATUS status = NTSTATUS.STATUS_BUFFER_OVERFLOW; // Start with MAX_PATH uint byteLength = 260 * sizeof(char); FILE_NAME_INFORMATION *value = null; while (status == NTSTATUS.STATUS_BUFFER_OVERFLOW) { // Add space for the FileNameLength buffer.EnsureByteCapacity(byteLength + sizeof(uint)); status = Imports.NtQueryInformationFile( FileHandle: fileHandle, IoStatusBlock: out _, FileInformation: buffer.VoidPointer, Length: checked ((uint)buffer.ByteCapacity), FileInformationClass: fileInformationClass); if (status == NTSTATUS.STATUS_SUCCESS || status == NTSTATUS.STATUS_BUFFER_OVERFLOW) { value = (FILE_NAME_INFORMATION *)buffer.VoidPointer; byteLength = value->FileNameLength; } } if (status != NTSTATUS.STATUS_SUCCESS) { throw ErrorMethods.GetIoExceptionForNTStatus(status); } return value->FileName.CreateString(); })); }
/// <summary> /// Gets the key's value data directly from NtEnumerateValueKey. This is slightly faster /// and uses less memory, but only works for keys in the local machine registry and does /// not work with performance keys (such as HKEY_PERFORMANCE_DATA). /// /// This also doesn't give the same results for "special" (HKCR) keys that are normally /// redirected to user specific settings by RegEnumValue. /// </summary> /// <param name="filterTo"> /// Only return data of the given type, or REG_NONE for all types. /// </param> /// <remarks> /// RegEnumValue doesn't map directly to NtEnumerateValueKey and requires allocating a /// temporary buffer for *each* invocation- making the direct call here avoids this extra /// buffer. /// </remarks> public unsafe static IEnumerable <object> GetValueDataDirect(RegistryKeyHandle key, RegistryValueType filterTo = RegistryValueType.REG_NONE) { List <object> data = new List <object>(); BufferHelper.BufferInvoke((HeapBuffer buffer) => { NTSTATUS status; while ((status = Imports.NtEnumerateValueKey( key, (uint)data.Count, KEY_VALUE_INFORMATION_CLASS.KeyValuePartialInformation, buffer.VoidPointer, checked ((uint)buffer.ByteCapacity), out uint resultLength)) != NTSTATUS.STATUS_NO_MORE_ENTRIES) { switch (status) { case NTSTATUS.STATUS_SUCCESS: KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer.VoidPointer; if (filterTo == RegistryValueType.REG_NONE || (*info).Type == filterTo) { data.Add(ReadValue(&(*info).Data, (*info).DataLength, (*info).Type)); } break; case NTSTATUS.STATUS_BUFFER_OVERFLOW: case NTSTATUS.STATUS_BUFFER_TOO_SMALL: buffer.EnsureByteCapacity(resultLength); break; default: throw ErrorMethods.GetIoExceptionForNTStatus(status); } } }); return(data); }
/// <summary> /// Gets the key's value names directly from NtEnumerateValueKey. This is slightly faster /// and uses less memory, but only works for keys in the local machine registry and does /// not work with performance keys (such as HKEY_PERFORMANCE_DATA). /// /// This also doesn't give the same results for "special" (HKCR) keys that are normally /// redirected to user specific settings by RegEnumValue. /// </summary> /// <param name="filterTo"> /// Only return names that have the given type, or REG_NONE for all types. /// </param> /// <remarks> /// RegEnumValue doesn't map directly to NtEnumerateValueKey and requires allocating a /// temporary buffer for *each* invocation- making the direct call here avoids this extra /// buffer. /// </remarks> public unsafe static IEnumerable <string> GetValueNamesDirect(RegistryKeyHandle key, RegistryValueType filterTo = RegistryValueType.REG_NONE) { List <string> names = new List <string>(); BufferHelper.BufferInvoke((HeapBuffer buffer) => { NTSTATUS status; while ((status = Imports.NtEnumerateValueKey( key, (uint)names.Count, KEY_VALUE_INFORMATION_CLASS.KeyValueBasicInformation, buffer.VoidPointer, checked ((uint)buffer.ByteCapacity), out uint resultLength)) != NTSTATUS.STATUS_NO_MORE_ENTRIES) { switch (status) { case NTSTATUS.STATUS_SUCCESS: KEY_VALUE_BASIC_INFORMATION *info = (KEY_VALUE_BASIC_INFORMATION *)buffer.VoidPointer; if (filterTo == RegistryValueType.REG_NONE || info->Type == filterTo) { names.Add(info->Name.CreateString()); } break; case NTSTATUS.STATUS_BUFFER_OVERFLOW: case NTSTATUS.STATUS_BUFFER_TOO_SMALL: buffer.EnsureByteCapacity(resultLength); break; default: throw ErrorMethods.GetIoExceptionForNTStatus(status); } } }); return(names); }