NTSTATUS NTAPI NtCreateNamedPipeFile( PHANDLE PipeHandle, ACCESS_MASK AccessMask, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, BOOLEAN TypeMessage, BOOLEAN ReadModeMessage, BOOLEAN NonBlocking, ULONG MaxInstances, ULONG InBufferSize, ULONG OutBufferSize, PLARGE_INTEGER DefaultTimeout) { LARGE_INTEGER timeout; object_attributes_t oa; NTSTATUS r; if (CreateDisposition != FILE_OPEN_IF) return STATUS_INVALID_PARAMETER; if (MaxInstances == 0) return STATUS_INVALID_PARAMETER; if (ObjectAttributes == NULL) return STATUS_INVALID_PARAMETER; if (!(ShareAccess & FILE_SHARE_READ)) return STATUS_INVALID_PARAMETER; if (!(ShareAccess & FILE_SHARE_WRITE)) return STATUS_INVALID_PARAMETER; r = copy_from_user( &timeout, DefaultTimeout, sizeof timeout ); if (r < STATUS_SUCCESS) return r; if (timeout.QuadPart > 0) return STATUS_INVALID_PARAMETER; r = verify_for_write( PipeHandle, sizeof *PipeHandle ); if (r < STATUS_SUCCESS) return r; r = verify_for_write( IoStatusBlock, sizeof IoStatusBlock ); if (r < STATUS_SUCCESS) return r; pipe_factory factory( MaxInstances ); return factory.create( PipeHandle, AccessMask, ObjectAttributes ); }
NTSTATUS NTAPI NtQuerySymbolicLinkObject( HANDLE SymbolicLinkHandle, PUNICODE_STRING LinkName, PULONG DataWritten ) { UNICODE_STRING name; NTSTATUS r; r = copy_from_user( &name, LinkName, sizeof name ); if (r < STATUS_SUCCESS) return r; // make sure we can write back the length r = verify_for_write( &LinkName->Length, sizeof LinkName->Length ); if (r < STATUS_SUCCESS) return r; if (DataWritten) { r = verify_for_write( DataWritten, sizeof DataWritten ); if (r < STATUS_SUCCESS) return r; } symlink_t *symlink = 0; r = object_from_handle( symlink, SymbolicLinkHandle, 0 ); if (r < STATUS_SUCCESS) return r; const unicode_string_t& target = symlink->get_target(); if (name.MaximumLength < target.Length) return STATUS_BUFFER_TOO_SMALL; r = copy_to_user( name.Buffer, target.Buffer, target.Length ); if (r < STATUS_SUCCESS) return r; copy_to_user( &LinkName->Length, &target.Length, sizeof target.Length ); if (DataWritten) { // convert from USHORT to ULONG ULONG len = target.Length; copy_to_user( DataWritten, &len, sizeof len ); } return r; }
NTSTATUS NTAPI NtEnumerateKey( HANDLE KeyHandle, ULONG Index, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG KeyInformationLength, PULONG ResultLength) { regkey_t *key = 0; NTSTATUS r = object_from_handle( key, KeyHandle, KEY_ENUMERATE_SUB_KEYS ); if (r < STATUS_SUCCESS) return r; if (ResultLength) { r = verify_for_write( ResultLength, sizeof *ResultLength ); if (r < STATUS_SUCCESS) return r; } if (!key_info_class_valid(KeyInformationClass)) return STATUS_INVALID_INFO_CLASS; regkey_t *child = key->get_child( Index ); if (!child) return STATUS_NO_MORE_ENTRIES; return child->query( KeyInformationClass, KeyInformation, KeyInformationLength, ResultLength ); }
NTSTATUS NTAPI NtCreateKey( PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG TitleIndex, PUNICODE_STRING Class, ULONG CreateOptions, PULONG Disposition ) { object_attributes_t oa; NTSTATUS r; regkey_t *key = NULL; trace("%p %08lx %p %lu %p %lu %p\n", KeyHandle, DesiredAccess, ObjectAttributes, TitleIndex, Class, CreateOptions, Disposition ); if (Disposition) { r = verify_for_write( Disposition, sizeof *Disposition ); if (r < STATUS_SUCCESS) return r; } r = oa.copy_from_user( ObjectAttributes ); if (r < STATUS_SUCCESS) return r; trace("len %08lx root %p attr %08lx %pus\n", oa.Length, oa.RootDirectory, oa.Attributes, oa.ObjectName); unicode_string_t cls; if (Class) { r = cls.copy_from_user( Class ); if (r < STATUS_SUCCESS) return r; } bool opened_existing = false; r = create_key( &key, &oa, opened_existing ); if (r == STATUS_SUCCESS) { if (Disposition) { ULONG dispos = opened_existing ? REG_OPENED_EXISTING_KEY : REG_CREATED_NEW_KEY; copy_to_user( Disposition, &dispos, sizeof *Disposition ); } key->cls.copy( &cls ); r = alloc_user_handle( key, DesiredAccess, KeyHandle ); //release( event ); } return r; }
// pg 108 NTSTATUS NTAPI NtMapViewOfSection( HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress, ULONG ZeroBits, ULONG CommitSize, PLARGE_INTEGER SectionOffset, PULONG ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Protect ) { process_t *p = NULL; BYTE *addr = NULL; NTSTATUS r; trace("%p %p %p %lu %08lx %p %p %u %08lx %08lx\n", SectionHandle, ProcessHandle, BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, InheritDisposition, AllocationType, Protect ); r = process_from_handle( ProcessHandle, &p ); if (r < STATUS_SUCCESS) return r; section_t *section = 0; r = object_from_handle( section, SectionHandle, 0 ); if (r < STATUS_SUCCESS) return r; r = copy_from_user( &addr, BaseAddress, sizeof addr ); if (r < STATUS_SUCCESS) return r; if (addr) trace("requested specific address %p\n", addr); r = verify_for_write( ViewSize, sizeof *ViewSize ); if (r < STATUS_SUCCESS) return r; r = section->mapit( p->vm, addr, ZeroBits, MEM_COMMIT | (AllocationType&MEM_TOP_DOWN), Protect ); if (r < STATUS_SUCCESS) return r; r = copy_to_user( BaseAddress, &addr, sizeof addr ); trace("mapped at %p\n", addr ); return r; }
NTSTATUS NTAPI NtCreateMailslotFile( PHANDLE MailslotHandle, ACCESS_MASK AccessMask, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG CreateOptions, ULONG InBufferSize, ULONG MaxMessageSize, PLARGE_INTEGER ReadTimeout) { trace("%p %08lx %p %p %08lx %lu %lu %p\n", MailslotHandle, AccessMask, ObjectAttributes, IoStatusBlock, CreateOptions, InBufferSize, MaxMessageSize, ReadTimeout); NTSTATUS r; r = verify_for_write( IoStatusBlock, sizeof *IoStatusBlock ); if (r < STATUS_SUCCESS) return r; if (!ObjectAttributes) return STATUS_INVALID_PARAMETER; object_attributes_t oa; r = oa.copy_from_user( ObjectAttributes ); if (r < STATUS_SUCCESS) return r; if (!oa.ObjectName) return STATUS_OBJECT_PATH_SYNTAX_BAD; // FIXME: these checks should be done in the object manager UNICODE_STRING &us = *oa.ObjectName; if (us.Length<2) return STATUS_OBJECT_PATH_SYNTAX_BAD; if (us.Length&1) return STATUS_OBJECT_NAME_INVALID; if (us.Length == 2 && us.Buffer[0] == '\\') return STATUS_OBJECT_TYPE_MISMATCH; PCWSTR ptr = (PCWSTR) L"\\??\\mailslot\\"; if (us.Length < 26 || memcmp(ptr, us.Buffer, 26)) return STATUS_OBJECT_NAME_NOT_FOUND; mailslot_factory factory; return factory.create( MailslotHandle, AccessMask, ObjectAttributes ); }
NTSTATUS NTAPI NtQueryValueKey( HANDLE KeyHandle, PUNICODE_STRING ValueName, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG KeyValueInformationLength, PULONG ResultLength ) { unicode_string_t us; NTSTATUS r; ULONG len; regkey_t *key; regval_t *val; trace("%p %p %d %p %lu %p\n", KeyHandle, ValueName, KeyValueInformationClass, KeyValueInformation, KeyValueInformationLength, ResultLength ); r = check_key_value_info_class( KeyValueInformationClass ); if (r < STATUS_SUCCESS) return r; r = object_from_handle( key, KeyHandle, KEY_QUERY_VALUE ); if (r < STATUS_SUCCESS) return r; r = us.copy_from_user( ValueName ); if (r < STATUS_SUCCESS) return r; r = verify_for_write( ResultLength, sizeof *ResultLength ); if (r < STATUS_SUCCESS) return r; trace("%pus\n", &us ); val = key_find_value( key, &us ); if (!val) return STATUS_OBJECT_NAME_NOT_FOUND; r = reg_query_value( val, KeyValueInformationClass, KeyValueInformation, KeyValueInformationLength, len ); copy_to_user( ResultLength, &len, sizeof len ); return r; }
NTSTATUS NTAPI NtQueryKey( HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG KeyInformationLength, PULONG ReturnLength) { if (!key_info_class_valid(KeyInformationClass)) return STATUS_INVALID_INFO_CLASS; NTSTATUS r; r = verify_for_write( ReturnLength, sizeof *ReturnLength ); if (r < STATUS_SUCCESS) return r; regkey_t *key = 0; r = object_from_handle( key, KeyHandle, KEY_QUERY_VALUE ); if (r < STATUS_SUCCESS) return r; return key->query( KeyInformationClass, KeyInformation, KeyInformationLength, ReturnLength ); }
NTSTATUS NTAPI NtEnumerateValueKey( HANDLE KeyHandle, ULONG Index, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG KeyValueInformationLength, PULONG ResultLength ) { regkey_t *key; ULONG len = 0; NTSTATUS r = STATUS_SUCCESS; trace("%p %lu %u %p %lu %p\n", KeyHandle, Index, KeyValueInformationClass, KeyValueInformation, KeyValueInformationLength, ResultLength ); r = object_from_handle( key, KeyHandle, KEY_QUERY_VALUE ); if (r < STATUS_SUCCESS) return r; r = verify_for_write( ResultLength, sizeof *ResultLength ); if (r < STATUS_SUCCESS) return r; regval_iter i(key->values); for ( ; i && Index; i.next()) Index--; if (!i) return STATUS_NO_MORE_ENTRIES; r = reg_query_value( i, KeyValueInformationClass, KeyValueInformation, KeyValueInformationLength, len ); copy_to_user( ResultLength, &len, sizeof len ); return r; }
NTSTATUS nteventfunc( HANDLE Handle, PULONG PreviousState, void (event_t::*fn)(PULONG) ) { NTSTATUS r; ULONG prev; if (PreviousState) { r = verify_for_write( PreviousState, sizeof PreviousState ); if (r < STATUS_SUCCESS) return r; } event_t *event = 0; r = object_from_handle( event, Handle, EVENT_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; (event->*fn)( &prev ); if (PreviousState) copy_to_user( PreviousState, &prev, sizeof prev ); return r; }
NTSTATUS NTAPI NtQueryInformationThread( HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength, PULONG ReturnLength) { union { THREAD_BASIC_INFORMATION basic; KERNEL_USER_TIMES times; ULONG last_thread; } info; ULONG sz = 0; NTSTATUS r; thread_impl_t *t; dprintf("%p %d %p %lu %p\n", ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength, ReturnLength); switch( ThreadInformationClass ) { case ThreadBasicInformation: sz = sizeof info.basic; break; case ThreadTimes: sz = sizeof info.times; break; case ThreadAmILastThread: sz = sizeof info.last_thread; break; default: dprintf("info class %d\n", ThreadInformationClass); return STATUS_INVALID_INFO_CLASS; } if (sz != ThreadInformationLength) return STATUS_INFO_LENGTH_MISMATCH; memset( &info, 0, sizeof info ); r = object_from_handle( t, ThreadHandle, 0 ); if (r < STATUS_SUCCESS) return r; if (ReturnLength) { r = verify_for_write( ReturnLength, sizeof *ReturnLength ); if (r < STATUS_SUCCESS) return r; } switch( ThreadInformationClass ) { case ThreadBasicInformation: t->query_information( info.basic ); break; case ThreadTimes: t->query_information( info.times ); break; case ThreadAmILastThread: info.last_thread = t->is_last_thread(); break; default: assert(0); } r = copy_to_user( ThreadInformation, &info, sz ); if (r == STATUS_SUCCESS && ReturnLength) copy_to_user( ReturnLength, &sz, sizeof sz ); return r; }
NTSTATUS NTAPI NtCreateSection( PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER SectionSize, ULONG Protect, ULONG Attributes, HANDLE FileHandle ) { NTSTATUS r; object_t *file = NULL; LARGE_INTEGER sz; trace("%p %08lx %p %p %08lx %08lx %p\n", SectionHandle, DesiredAccess, ObjectAttributes, SectionSize, Protect, Attributes, FileHandle ); // check there's no bad flags if (Attributes & ~VALID_SECTION_FLAGS) return STATUS_INVALID_PARAMETER_6; switch (Attributes & (SEC_IMAGE|SEC_COMMIT|SEC_RESERVE)) { case SEC_IMAGE: case SEC_RESERVE: case SEC_COMMIT: break; default: return STATUS_INVALID_PARAMETER_6; } r = verify_for_write( SectionHandle, sizeof *SectionHandle ); if (r < STATUS_SUCCESS) return r; // PE sections cannot be written to if (Attributes & SEC_IMAGE) { switch (Protect) { case PAGE_READONLY: case PAGE_EXECUTE: case PAGE_EXECUTE_READ: break; default: return STATUS_INVALID_PAGE_PROTECTION; } if (!FileHandle) return STATUS_INVALID_FILE_FOR_SECTION; r = object_from_handle( file, FileHandle, 0 ); if (r < STATUS_SUCCESS) return r; SectionSize = 0; } else { switch (Protect) { case PAGE_READONLY: case PAGE_READWRITE: case PAGE_EXECUTE: case PAGE_EXECUTE_READ: case PAGE_WRITECOPY: case PAGE_EXECUTE_READWRITE: case PAGE_EXECUTE_WRITECOPY: break; default: return STATUS_INVALID_PAGE_PROTECTION; } if (FileHandle) { r = object_from_handle( file, FileHandle, 0 ); if (r < STATUS_SUCCESS) return r; } } if (SectionSize) { r = copy_from_user( &sz, SectionSize, sizeof sz ); if (r < STATUS_SUCCESS) return r; if (sz.QuadPart == 0) return STATUS_INVALID_PARAMETER_4; SectionSize = &sz; } section_factory factory( file, SectionSize, Attributes, Protect ); return factory.create( SectionHandle, DesiredAccess, ObjectAttributes ); }