Esempio n. 1
0
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 );
    }
}
Esempio n. 3
0
/* 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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
/* 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;
}
Esempio n. 6
0
/* 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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
/* 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;
    }
}
Esempio n. 10
0
/* 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;
}
Esempio n. 11
0
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( &params, 0, sizeof(params) );
    params.flush.major = IRP_MJ_FLUSH_BUFFERS;
    params.flush.file  = file->user_ptr;

    irp = create_irp( file, &params, NULL, 0, 0 );
    if (!irp) return 0;

    handle = queue_irp( file, irp, async_data, blocking );
    release_object( irp );
    return handle;
}
Esempio n. 12
0
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;		
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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();
    }
}
Esempio n. 15
0
/* 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);
}
Esempio n. 16
0
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);
}
Esempio n. 17
0
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( &params, 0, sizeof(params) );
        params.close.major = IRP_MJ_CLOSE;
        params.close.file  = file->user_ptr;

        if ((irp = create_irp( file, &params, NULL, 0, 0 )))
        {
            add_irp_to_queue( file, irp, NULL );
            release_object( irp );
        }
    }
    return 1;
}
Esempio n. 18
0
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( &params, 0, sizeof(params) );
    params.ioctl.major = IRP_MJ_DEVICE_CONTROL;
    params.ioctl.code  = code;
    params.ioctl.file = file->user_ptr;

    irp = create_irp( file, &params, 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;
}
Esempio n. 19
0
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( &params, 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, &params, 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;
}
Esempio n. 20
0
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( &params, 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, &params, NULL, 0, get_reply_max_size() );
    if (!irp) return 0;

    handle = queue_irp( file, irp, async_data, blocking );
    release_object( irp );
    return handle;
}
Esempio n. 21
0
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;
}
Esempio n. 22
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;
}
Esempio n. 23
0
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;
}
Esempio n. 24
0
/* 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);
}
Esempio n. 25
0
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;
}
Esempio n. 26
0
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;
}
Esempio n. 27
0
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 );
}
Esempio n. 28
0
File: file.c Progetto: ccpgames/wine
/* 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;
}
Esempio n. 29
0
/* 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;
}
Esempio n. 30
0
/* 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);
}