NTSTATUS SERVICECALL NtTerminateProcess(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus) { struct eprocess *process; struct ethread *cur_thread; NTSTATUS status; ktrace("\n"); if ((status = ref_object_by_handle(ProcessHandle ? ProcessHandle : NtCurrentProcess(), PROCESS_TERMINATE, process_object_type, get_pre_mode(), (PVOID *) &process, NULL))) return status; cur_thread = (struct ethread *) get_current_ethread(); terminate_process(process->win32process, ExitStatus); release_object(process->win32process); lock_process(process); if (process->exit_time.quad) { unlock_process(process); deref_object(process); return STATUS_PROCESS_IS_TERMINATING; } query_sys_time(&process->exit_time); process->exit_status = (unsigned long)ExitStatus; unlock_process(process); deref_object(process); if (process == get_current_eprocess()) { cur_thread->exit_status = ExitStatus; do_group_exit((ExitStatus & 0xff) << 8); } else { struct ethread *first_thread = get_first_thread(process); first_thread->exit_status = ExitStatus; send_sig_info(SIGKILL, SEND_SIG_FORCED, first_thread->et_task->group_leader); } return STATUS_SUCCESS; }
/* link an event at the end of the queue */ static void link_event( struct debug_event *event ) { struct debug_ctx *debug_ctx = event->debugger->debug_ctx; assert( debug_ctx ); grab_object( event ); list_add_tail( &debug_ctx->event_queue, &event->entry ); if (!event->sender->debug_event) { /* grab reference since debugger could be killed while trying to wake up */ grab_object( debug_ctx ); wake_up( &debug_ctx->obj, 0 ); release_object( debug_ctx ); } }
/* allocate a new handle table */ struct handle_table *alloc_handle_table( struct process *process, int count ) { struct handle_table *table; if (count < MIN_HANDLE_ENTRIES) count = MIN_HANDLE_ENTRIES; if (!(table = alloc_object( &handle_table_ops ))) return NULL; table->process = process; table->count = count; table->last = -1; table->free = 0; if ((table->entries = mem_alloc( count * sizeof(*table->entries) ))) return table; release_object( table ); return NULL; }
static obj_handle_t device_ioctl(struct fd *fd, ioctl_code_t code, const async_data_t *async_data, const void *data, data_size_t size) { struct device *device = get_fd_user(fd); struct ioctl_call *ioctl; obj_handle_t handle; if (!device->manager) /* it has been deleted */ { set_error(STATUS_FILE_DELETED); return 0; } if (!(ioctl = create_ioctl(device, code, data, size, get_reply_max_size()))) return 0; ioctl->thread = (struct w32thread *)grab_object(current_thread); ioctl->user_arg = async_data->arg; if (!(handle = alloc_handle(get_current_w32process(), ioctl, SYNCHRONIZE, 0))) { release_object(ioctl); return 0; } if (!(ioctl->async = fd_queue_async(device->fd, async_data, ASYNC_TYPE_WAIT, 0))) { close_handle(get_current_eprocess(), handle); release_object(ioctl); return 0; } list_add_before(&device->requests, &ioctl->dev_entry); list_add_before(&device->manager->requests, &ioctl->mgr_entry); if (list_head(&device->manager->requests) == &ioctl->mgr_entry) /* first one */ uk_wake_up(&device->manager->obj, 0); /* don't release ioctl since it is now queued in the device */ set_error(STATUS_PENDING); return handle; }
/* open a new handle to an existing object */ obj_handle_t open_object( struct process *process, obj_handle_t parent, unsigned int access, const struct object_ops *ops, const struct unicode_str *name, unsigned int attributes ) { obj_handle_t handle = 0; struct directory *root = NULL; struct object *obj; if (name->len >= 65534) { set_error( STATUS_OBJECT_NAME_INVALID ); return 0; } if (parent && !(root = get_directory_obj( process, parent, 0 ))) return 0; if ((obj = open_object_dir( root, name, attributes, ops ))) { handle = alloc_handle( process, obj, access, attributes ); release_object( obj ); } if (root) release_object( root ); return handle; }
/* if the function fails the fd is closed */ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing ) { struct file *file; if ((file = alloc_object( &file_ops ))) { file->access = file_map_access( &file->obj, access ); file->options = FILE_SYNCHRONOUS_IO_NONALERT; if (!(file->fd = create_anonymous_fd( &file_fd_ops, fd, &file->obj ))) { release_object( file ); return NULL; } } return file; }
static int dir_gc(lua_State *L) { lua_apr_dir *directory = checkdir(L, 1, 0); if (object_collectable((lua_apr_refobj*)directory)) { if (directory->handle != NULL) { apr_dir_close(directory->handle); directory->handle = NULL; } if (directory->memory_pool != NULL) { apr_pool_destroy(directory->memory_pool); directory->memory_pool = NULL; } } release_object((lua_apr_refobj*)directory); return 0; }
/* duplicate a handle */ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, struct process *dst, unsigned int access, unsigned int attr, unsigned int options ) { obj_handle_t res; struct handle_entry *entry; unsigned int src_access; struct object *obj = get_handle_obj( src, src_handle, 0, NULL ); if (!obj) return 0; if ((entry = get_handle( src, src_handle ))) src_access = entry->access; else /* pseudo-handle, give it full access */ src_access = obj->ops->map_access( obj, GENERIC_ALL ); src_access &= ~RESERVED_ALL; if (options & DUP_HANDLE_SAME_ACCESS) access = src_access; else access = obj->ops->map_access( obj, access ) & ~RESERVED_ALL; /* asking for the more access rights than src_access? */ if (access & ~src_access) { if (options & DUP_HANDLE_MAKE_GLOBAL) res = alloc_global_handle( obj, access ); else res = alloc_handle( dst, obj, access, attr ); } else { if (options & DUP_HANDLE_MAKE_GLOBAL) res = alloc_global_handle_no_access_check( obj, access ); else if ((options & DUP_HANDLE_CLOSE_SOURCE) && src == dst && entry && !(entry->access & RESERVED_CLOSE_PROTECT)) { if (attr & OBJ_INHERIT) access |= RESERVED_INHERIT; entry->access = access; res = src_handle; } else res = alloc_handle_entry( dst, obj, access, attr ); } release_object( obj ); return res; }
/* a thread is exiting */ void debug_exit_thread( struct thread *thread ) { if (thread->debug_ctx) /* this thread is a debugger */ { if (thread->debug_ctx->kill_on_exit) { /* kill all debugged processes */ kill_debugged_processes( thread, thread->exit_code ); } else { detach_debugged_processes( thread ); } release_object( thread->debug_ctx ); thread->debug_ctx = NULL; } }
/* create a new and unconnected socket */ static struct object *create_socket( int family, int type, int protocol, unsigned int flags ) { struct sock *sock; int sockfd; sockfd = socket( family, type, protocol ); if (debug_level) fprintf(stderr,"socket(%d,%d,%d)=%d\n",family,type,protocol,sockfd); if (sockfd == -1) { sock_set_error(); return NULL; } fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ if (!(sock = alloc_object( &sock_ops ))) { close( sockfd ); return NULL; } sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0; sock->mask = 0; sock->hmask = 0; sock->pmask = 0; sock->polling = 0; sock->flags = flags; sock->type = type; sock->family = family; sock->event = NULL; sock->window = 0; sock->message = 0; sock->wparam = 0; sock->deferred = NULL; sock->read_q = NULL; sock->write_q = NULL; memset( sock->errors, 0, sizeof(sock->errors) ); if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj, (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT ))) { release_object( sock ); return NULL; } sock_reselect( sock ); clear_error(); return &sock->obj; }
static obj_handle_t device_file_flush( struct fd *fd, const async_data_t *async_data, int blocking ) { struct device_file *file = get_fd_user( fd ); struct irp_call *irp; obj_handle_t handle; irp_params_t params; memset( ¶ms, 0, sizeof(params) ); params.flush.major = IRP_MJ_FLUSH_BUFFERS; params.flush.file = file->user_ptr; irp = create_irp( file, ¶ms, NULL, 0, 0 ); if (!irp) return 0; handle = queue_irp( file, irp, async_data, blocking ); release_object( irp ); return handle; }
NTSTATUS SERVICECALL NtTerminateThread(IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus) { struct ethread * thread; struct w32thread *w32thread; NTSTATUS status; ktrace("%p\n", ThreadHandle); status = ref_object_by_handle(ThreadHandle, THREAD_TERMINATE, thread_object_type, get_pre_mode(), (PVOID *)&thread, NULL); if (!NT_SUCCESS(status)) return status; if (!thread->et_task){ deref_object(thread); return STATUS_THREAD_IS_TERMINATING; } w32thread = thread->tcb.win32thread; remove_process_thread(w32thread->process, w32thread); thread->tcb.win32thread = NULL; release_object(w32thread); /* FIXME Make sure this is not a system thread */ if (thread != get_current_ethread()) { terminate_thread_by_pointer(thread, ExitStatus); deref_object(thread); } else { deref_object(thread); thread->exit_status = ExitStatus; do_exit((ExitStatus & 0xff) << 8); } return STATUS_SUCCESS; }
static struct device *create_device(HANDLE root, const struct unicode_str *name, struct device_manager *manager, unsigned int attr) { struct device *device; if ((device = create_named_object_dir(root, name, attr, &device_ops))) { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ device->manager = manager; list_add_before(&manager->devices, &device->entry); INIT_LIST_HEAD(&device->requests); if (!(device->fd = alloc_pseudo_fd(&device_fd_ops, &device->obj, 0))) { release_object(device); device = NULL; } } } return device; }
static void handler_poll_event( struct fd *fd, int event ) { struct handler *handler = get_fd_user( fd ); if (event & (POLLERR | POLLHUP)) { /* this is not supposed to happen */ fprintf( stderr, "wineserver: Error on signal handler pipe\n" ); release_object( handler ); } else if (event & POLLIN) { char dummy; handler->pending = 0; read( get_unix_fd( handler->fd ), &dummy, 1 ); handler->callback(); } }
/* Called when thread terminates to allow release of clipboard */ void cleanup_clipboard_thread(struct w32thread *thread) { struct clipboard *clipboard; struct winstation *winstation = get_process_winstation(thread->process, WINSTA_ACCESSCLIPBOARD); if (!winstation) return; if ((clipboard = winstation->clipboard)) { if (thread == clipboard->open_thread) { clipboard->open_win = 0; clipboard->open_thread = NULL; } if (thread == clipboard->owner_thread) { clipboard->owner_win = 0; clipboard->owner_thread = NULL; } } release_object(winstation); }
int key_hook(unsigned int key, t_core *c) { if (key == K_ESC) { release_object(&c->otest); exit(0); } else if (key == K_A) c->anim = !c->anim; else if (key == K_T) c->tex_enabled = !c->tex_enabled; else if (key == K_1 || key == K_N1) change_rotation(&c->rotations.x); else if (key == K_2 || key == K_N2) change_rotation(&c->rotations.y); else if (key == K_3 || key == K_N3) change_rotation(&c->rotations.z); else if (key == K_HOME) c->current_texture = (c->current_texture + 1) % c->texture_max; return (1); }
static int device_file_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) { struct device_file *file = (struct device_file *)obj; if (file->device->manager && obj->handle_count == 1) /* last handle */ { struct irp_call *irp; irp_params_t params; memset( ¶ms, 0, sizeof(params) ); params.close.major = IRP_MJ_CLOSE; params.close.file = file->user_ptr; if ((irp = create_irp( file, ¶ms, NULL, 0, 0 ))) { add_irp_to_queue( file, irp, NULL ); release_object( irp ); } } return 1; }
static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data, int blocking ) { struct device_file *file = get_fd_user( fd ); struct irp_call *irp; obj_handle_t handle; irp_params_t params; memset( ¶ms, 0, sizeof(params) ); params.ioctl.major = IRP_MJ_DEVICE_CONTROL; params.ioctl.code = code; params.ioctl.file = file->user_ptr; irp = create_irp( file, ¶ms, get_req_data(), get_req_data_size(), get_reply_max_size() ); if (!irp) return 0; handle = queue_irp( file, irp, async_data, blocking ); release_object( irp ); return handle; }
static obj_handle_t device_file_write( struct fd *fd, const async_data_t *async_data, int blocking, file_pos_t pos, data_size_t *written ) { struct device_file *file = get_fd_user( fd ); struct irp_call *irp; obj_handle_t handle; irp_params_t params; memset( ¶ms, 0, sizeof(params) ); params.write.major = IRP_MJ_WRITE; params.write.key = 0; params.write.pos = pos; params.write.file = file->user_ptr; irp = create_irp( file, ¶ms, get_req_data(), get_req_data_size(), 0 ); if (!irp) return 0; handle = queue_irp( file, irp, async_data, blocking ); release_object( irp ); return handle; }
static obj_handle_t device_file_read( struct fd *fd, const async_data_t *async_data, int blocking, file_pos_t pos ) { struct device_file *file = get_fd_user( fd ); struct irp_call *irp; obj_handle_t handle; irp_params_t params; memset( ¶ms, 0, sizeof(params) ); params.read.major = IRP_MJ_READ; params.read.key = 0; params.read.pos = pos; params.read.file = file->user_ptr; irp = create_irp( file, ¶ms, NULL, 0, get_reply_max_size() ); if (!irp) return 0; handle = queue_irp( file, irp, async_data, blocking ); release_object( irp ); return handle; }
static int proc_gc(lua_State *L) { lua_apr_proc *process = proc_check(L, 1); if (object_collectable((lua_apr_refobj*)process)) { lua_settop(L, 1); lua_getfenv(L, 1); if (lua_type(L, -1) == LUA_TTABLE) { close_pipe(L, "in_child"); close_pipe(L, "in_parent"); close_pipe(L, "out_child"); close_pipe(L, "out_parent"); close_pipe(L, "err_child"); close_pipe(L, "err_parent"); } if (process->memory_pool != NULL) { apr_pool_destroy(process->memory_pool); process->memory_pool = NULL; } } release_object((lua_apr_refobj*)process); return 0; }
/* retrieve the clipboard info for the current process, allocating it if needed */ static struct clipboard *get_process_clipboard(void) { NTSTATUS status; struct clipboard *clipboard; struct winstation *winstation = get_process_winstation(get_current_w32process(), WINSTA_ACCESSCLIPBOARD); if (!winstation) { ktrace("get_process_winstation return NULL!\n"); return NULL; } if (!(clipboard = winstation->clipboard)) { status = create_object(KernelMode, clipboard_object_type, NULL /* obj_attr*/, KernelMode, NULL, sizeof(struct clipboard), 0, 0, (PVOID *)&clipboard); if (NT_SUCCESS(status) && clipboard) { INIT_DISP_HEADER(&clipboard->obj.header, CLIPBOARD, sizeof(struct clipboard) / sizeof(ULONG), 0); BODY_TO_HEADER(&(clipboard->obj))->ops = &clipboard_ops; clipboard->open_thread = NULL; clipboard->open_win = 0; clipboard->owner_thread = NULL; clipboard->owner_win = 0; clipboard->viewer = 0; clipboard->seqno = 0; clipboard->seqno_timestamp = 0; winstation->clipboard = clipboard; } } release_object(winstation); return clipboard; }
static struct object *symlink_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr ) { struct symlink *symlink = (struct symlink *)obj; struct unicode_str target_str, name_left; struct object *target; assert( obj->ops == &symlink_ops ); if (!name->len && (attr & OBJ_OPENLINK)) return NULL; target_str.str = symlink->target; target_str.len = symlink->len; if ((target = find_object_dir( NULL, &target_str, attr, &name_left ))) { if (name_left.len) { release_object( target ); target = NULL; set_error( STATUS_OBJECT_PATH_NOT_FOUND ); } } return target; }
/* a process has been killed (i.e. its last thread died) */ static void process_killed(struct w32process *process) { struct list_head *ptr; ktrace("process %p\n", process); if (!process->is_system) close_process_desktop(process); /* close the console attached to this process, if any */ free_console(process); while ((ptr = list_head(&process->dlls))) { struct process_dll *dll = LIST_ENTRY(ptr, struct process_dll, entry); if (dll->file) release_object(dll->file); free(dll->filename); list_remove(&dll->entry); free(dll); } destroy_process_classes(process); remove_process_locks(process); set_process_startup_state(process, STARTUP_ABORTED); }
struct symlink *create_symlink( struct directory *root, const struct unicode_str *name, unsigned int attr, const struct unicode_str *target ) { struct symlink *symlink; if (!target->len) { set_error( STATUS_INVALID_PARAMETER ); return NULL; } if ((symlink = create_named_object_dir( root, name, attr, &symlink_ops )) && (get_error() != STATUS_OBJECT_NAME_EXISTS)) { if ((symlink->target = memdup( target->str, target->len ))) symlink->len = target->len; else { release_object( symlink ); symlink = NULL; } } return symlink; }
static struct ioctl_call *create_ioctl(struct device *device, ioctl_code_t code, const void *in_data, data_size_t in_size, data_size_t out_size) { struct ioctl_call *ioctl; NTSTATUS status; status = create_object(KernelMode, ioctl_call_object_type, NULL /* obj_attr*/, KernelMode, NULL, sizeof(struct ioctl_call), 0, 0, (PVOID *)&ioctl); if (NT_SUCCESS(status) && ioctl) { INIT_DISP_HEADER(&ioctl->obj.header, IOCTL_CALL, sizeof(struct ioctl_call) / sizeof(ULONG), 0); BODY_TO_HEADER(&ioctl->obj)->ops = &ioctl_call_ops; ioctl->device = (struct device *)grab_object(device); ioctl->code = code; ioctl->async = NULL; ioctl->status = STATUS_PENDING; ioctl->in_size = in_size; ioctl->in_data = NULL; ioctl->out_size = out_size; ioctl->out_data = NULL; if (ioctl->in_size && !(ioctl->in_data = memdup(in_data, in_size))) { release_object(ioctl); ioctl = NULL; } } return ioctl; }
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count ) { struct sock *sock = get_fd_user( fd ); struct async *async; struct async_queue *queue; assert( sock->obj.ops == &sock_ops ); switch (type) { case ASYNC_TYPE_READ: if (!sock->read_q && !(sock->read_q = create_async_queue( sock->fd ))) return; queue = sock->read_q; break; case ASYNC_TYPE_WRITE: if (!sock->write_q && !(sock->write_q = create_async_queue( sock->fd ))) return; queue = sock->write_q; break; default: set_error( STATUS_INVALID_PARAMETER ); return; } if ( ( !( sock->state & (FD_READ|FD_CONNECT|FD_WINE_LISTENING) ) && type == ASYNC_TYPE_READ ) || ( !( sock->state & (FD_WRITE|FD_CONNECT) ) && type == ASYNC_TYPE_WRITE ) ) { set_error( STATUS_PIPE_DISCONNECTED ); return; } if (!(async = create_async( current, queue, data ))) return; release_object( async ); sock_reselect( sock ); set_error( STATUS_PENDING ); }
/* create a file by duplicating an fd object */ struct file *create_file_for_fd_obj( struct fd *fd, unsigned int access, unsigned int sharing ) { struct file *file; struct stat st; if (fstat( get_unix_fd(fd), &st ) == -1) { file_set_error(); return NULL; } if ((file = alloc_object( &file_ops ))) { file->mode = st.st_mode; file->access = default_fd_map_access( &file->obj, access ); if (!(file->fd = dup_fd_object( fd, access, sharing, FILE_SYNCHRONOUS_IO_NONALERT ))) { release_object( file ); return NULL; } set_fd_user( file->fd, &file_fd_ops, &file->obj ); } return file; }
/* retrieve the clipboard info for the current_thread process, allocating it if needed */ static struct clipboard *get_process_clipboard(void) { struct clipboard *clipboard; struct winstation *winstation = get_process_winstation( current_thread->process, WINSTA_ACCESSCLIPBOARD ); if (!winstation) return NULL; if (!(clipboard = winstation->clipboard)) { if ((clipboard = alloc_object( &clipboard_ops ))) { clipboard->open_thread = NULL; clipboard->open_win = 0; clipboard->owner_thread = NULL; clipboard->owner_win = 0; clipboard->viewer = 0; clipboard->seqno = 0; clipboard->seqno_timestamp = 0; winstation->clipboard = clipboard; } } release_object( winstation ); return clipboard; }
/* 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); }