VOID init_symbol_link(VOID) { UNICODE_STRING Name; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; /* Create the object type for the "SymbolicLink" object. */ memset(&ObjectTypeInitializer, 0, sizeof(OBJECT_TYPE_INITIALIZER)); init_unistr(&Name, (PWSTR)LinkName); ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(OBJECT_SYMBOLIC_LINK); ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS; ObjectTypeInitializer.GenericMapping = symbol_link_mapping; ObjectTypeInitializer.DeleteProcedure = delete_symbol_link; ObjectTypeInitializer.ParseProcedure = parse_symbol_link; create_type_object(&ObjectTypeInitializer, &Name, &symbol_link_type); } /* end init_symbol_link */
VOID init_completion_implement(VOID) { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; UNICODE_STRING Name; memset(&ObjectTypeInitializer, 0, sizeof(ObjectTypeInitializer)); init_unistr(&Name, completion_type_name); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(struct uk_completion); ObjectTypeInitializer.GenericMapping = completion_mapping; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS; ObjectTypeInitializer.UseDefaultObject = TRUE; create_type_object(&ObjectTypeInitializer, &Name, &completion_object_type); }
VOID init_section_implement(VOID) { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; UNICODE_STRING Name; /* Initialize the Section object type */ memset(&ObjectTypeInitializer, 0, sizeof(ObjectTypeInitializer)); init_unistr(&Name, (PWSTR)section_type_name); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(struct win32_section); ObjectTypeInitializer.PoolType = PagedPool; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.GenericMapping = section_mapping; ObjectTypeInitializer.DeleteProcedure = delete_section; create_type_object(&ObjectTypeInitializer, &Name, §ion_object_type); } /* end init_section_implement */
VOID init_mutant_implement(VOID) { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; UNICODE_STRING Name; memset(&ObjectTypeInitializer, 0, sizeof(ObjectTypeInitializer)); init_unistr(&Name, (PWSTR)mutant_type_name); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(struct kmutant); ObjectTypeInitializer.GenericMapping = mutant_mapping; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.DeleteProcedure = delete_mutant; create_type_object(&ObjectTypeInitializer, &Name, &mutant_object_type); }
VOID init_thread_mgmt(VOID) { UNICODE_STRING Name; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; ktrace("Creating Thread Object Type\n"); /* Initialize the Thread type */ memset(&ObjectTypeInitializer, 0, sizeof(ObjectTypeInitializer)); init_unistr(&Name, (PWSTR)ThreadTypeName); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(struct ethread); ObjectTypeInitializer.GenericMapping = PiThreadMapping; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = THREAD_ALL_ACCESS; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.DeleteProcedure = delete_thread; ObjectTypeInitializer.PollProcedure = poll_thread; create_type_object(&ObjectTypeInitializer, &Name, &thread_object_type); }
/* destroy a process when its refcount is 0 */ void process_destroy(struct object *obj) { struct w32process *process = (struct w32process *)obj; ktrace("obj %p\n", obj); set_process_startup_state(process, STARTUP_ABORTED); if (process->console) release_object(process->console); if (process->parent) release_object(process->parent); #if 0 if (process->msg_fd) release_object(process->msg_fd); #endif list_remove(&process->entry); /* to terminate the services.exe.so */ if (is_last_list(&process_list)) { OBJECT_ATTRIBUTES attr; WCHAR process_system[] = {'_','_','p','r','o','c','e','s','s','_','s','y','s','t','e','m',0}; UNICODE_STRING name; NTSTATUS status; HANDLE handle = NULL; init_unistr(&name, (PWSTR)process_system); INIT_OBJECT_ATTR(&attr, &name, 0, base_dir_handle, NULL); status = NtCreateEvent(&handle, 0, &attr, 1, 0); if (status && status != STATUS_OBJECT_NAME_EXISTS) return; NtSetEvent(handle, NULL); NtClose(handle); } if (process->idle_event) release_object(process->idle_event); if (process->queue) release_object(process->queue); if (process->token) release_object(process->token); }
NTSTATUS SERVICECALL NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PVOID Buffer, IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL) { PVOID TempBuffer; ULONG SkipEntries, SkipEntries2, Bucket, EntrySize; ULONG RequiredSize = 0; ULONG NextEntry = 0; ULONG EntriesFound = 0; POBJECT_DIRECTORY Directory; POBJECT_DIRECTORY_ENTRY DirectoryEntry; POBJECT_HEADER ObjectHeader; POBJECT_HEADER_NAME_INFO NameInfo; UNICODE_STRING ObjectName; POBJECT_DIRECTORY_INFORMATION DirInfo; NTSTATUS Status = STATUS_SUCCESS; MODE previous_mode; previous_mode = (unsigned long)Buffer > TASK_SIZE ? KernelMode : UserMode; if (RestartScan) { if (previous_mode == UserMode) { if (copy_from_user(&SkipEntries, Context, sizeof(ULONG))) return STATUS_NO_MEMORY; } else SkipEntries = *Context; } else SkipEntries = 0; SkipEntries2 = SkipEntries; Status = ref_object_by_handle(DirectoryHandle, DIRECTORY_QUERY, dir_object_type, KernelMode, (PVOID *)&Directory, NULL); if (!NT_SUCCESS(Status)) return Status; for (Bucket = 0; Bucket < NUMBER_HASH_BUCKETS; Bucket++) { DirectoryEntry = Directory->HashBuckets[Bucket]; while (DirectoryEntry) { if (SkipEntries == NextEntry++) { EntriesFound ++; if (ReturnSingleEntry) goto found; else SkipEntries++; } DirectoryEntry = DirectoryEntry->ChainLink; } } if (EntriesFound == 0) { *Context = 0; deref_object(Directory); return STATUS_NO_MORE_ENTRIES; } found: TempBuffer = kmalloc(EntriesFound * sizeof(OBJECT_DIRECTORY_INFORMATION), GFP_KERNEL); if (!TempBuffer) { deref_object(Directory); return STATUS_NO_MEMORY; } if (previous_mode == UserMode) { if (copy_from_user(TempBuffer, Buffer, EntriesFound * sizeof(OBJECT_DIRECTORY_INFORMATION))) { deref_object(Directory); return STATUS_NO_MEMORY; } } else TempBuffer = Buffer; DirInfo = (POBJECT_DIRECTORY_INFORMATION)TempBuffer; Status = STATUS_NO_MORE_ENTRIES; NextEntry = 0; for (Bucket = 0; Bucket < NUMBER_HASH_BUCKETS; Bucket++) { DirectoryEntry = Directory->HashBuckets[Bucket]; while (DirectoryEntry) { if (SkipEntries2 == NextEntry++) { ObjectHeader = BODY_TO_HEADER(DirectoryEntry->Object); NameInfo = HEADER_TO_OBJECT_NAME(ObjectHeader); if (NameInfo) ObjectName = NameInfo->Name; else init_unistr(&ObjectName, NULL); EntrySize = sizeof(OBJECT_DIRECTORY_INFORMATION) + (ObjectName.Length + sizeof(WCHAR)) + (ObjectHeader->Type->Name.Length + sizeof(WCHAR)); if (RequiredSize + EntrySize > BufferLength) { if (ReturnSingleEntry) { RequiredSize += EntrySize; Status = STATUS_BUFFER_TOO_SMALL; } else Status = STATUS_MORE_ENTRIES; NextEntry--; goto done; } DirInfo->ObjectName.Length = ObjectName.Length; DirInfo->ObjectName.MaximumLength = (USHORT)(ObjectName.Length + sizeof(WCHAR)); memcpy(DirInfo->ObjectName.Buffer, ObjectName.Buffer, ObjectName.Length); DirInfo->ObjectTypeName.Length = ObjectHeader->Type->Name.Length; DirInfo->ObjectTypeName.MaximumLength = (USHORT)(ObjectHeader->Type->Name.Length + sizeof(WCHAR)); memcpy(DirInfo->ObjectTypeName.Buffer, ObjectHeader->Type->Name.Buffer, ObjectHeader->Type->Name.Length); Status = STATUS_SUCCESS; RequiredSize += EntrySize; DirInfo++; if (ReturnSingleEntry) goto done; else SkipEntries2++; } DirectoryEntry = DirectoryEntry->ChainLink; } } done: if (!NT_SUCCESS(Status)) goto out; if (previous_mode == UserMode) { if (copy_to_user(Buffer, TempBuffer, NextEntry * sizeof(OBJECT_DIRECTORY_INFORMATION))) { Status = STATUS_NO_MEMORY; goto out; } } else memcpy(Buffer, TempBuffer, NextEntry * sizeof(OBJECT_DIRECTORY_INFORMATION)); if (previous_mode == UserMode) { if (copy_to_user(Context, &NextEntry, sizeof(ULONG))) { Status = STATUS_NO_MEMORY; goto out; } } else *Context = NextEntry; if (ReturnLength) { if (previous_mode == UserMode) { if (copy_to_user(ReturnLength, &RequiredSize, sizeof(ULONG))) { Status = STATUS_NO_MEMORY; goto out; } } else *ReturnLength = RequiredSize; } out: deref_object(Directory); kfree(TempBuffer); return Status; } /* end NtQueryDirectoryObject */
void init_service_description_buffer(SERVICE_DESCRIPTION *desc, const char *service_desc ) { desc->unknown = 0x04; /* always 0x0000 0004 (no idea what this is) */ init_unistr( &desc->description, service_desc ); }