/* alloc a debug event for a debugger */ static struct debug_event *alloc_debug_event( struct thread *thread, int code, void *arg, const CONTEXT *context ) { struct thread *debugger = thread->process->debugger; struct debug_event *event; assert( code > 0 && code <= NB_DEBUG_EVENTS ); /* cannot queue a debug event for myself */ assert( debugger->process != thread->process ); /* build the event */ if (!(event = alloc_object( &debug_event_ops ))) return NULL; event->state = EVENT_QUEUED; event->sender = (struct thread *)grab_object( thread ); event->debugger = (struct thread *)grab_object( debugger ); event->data.code = code; if (!fill_debug_event[code-1]( event, arg )) { event->data.code = -1; /* make sure we don't attempt to close handles */ release_object( event ); return NULL; } if (context) { memcpy( &event->context, context, sizeof(event->context) ); thread->context = &event->context; } return event; }
static void add_irp_to_queue( struct device_file *file, struct irp_call *irp, struct thread *thread ) { struct device_manager *manager = file->device->manager; assert( manager ); grab_object( irp ); /* grab reference for queued irp */ irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL; list_add_tail( &file->requests, &irp->dev_entry ); list_add_tail( &manager->requests, &irp->mgr_entry ); if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ }
/* 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 ); } }
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; if ((ioctl = alloc_object( &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 struct irp_call *create_irp( struct device_file *file, const irp_params_t *params, const void *in_data, data_size_t in_size, data_size_t out_size ) { struct irp_call *irp; if (!file->device->manager) /* it has been deleted */ { set_error( STATUS_FILE_DELETED ); return NULL; } if ((irp = alloc_object( &irp_call_ops ))) { irp->file = (struct device_file *)grab_object( file ); irp->thread = NULL; irp->async = NULL; irp->params = *params; irp->status = STATUS_PENDING; irp->result = 0; irp->in_size = in_size; irp->in_data = NULL; irp->out_size = out_size; irp->out_data = NULL; if (irp->in_size && !(irp->in_data = memdup( in_data, in_size ))) { release_object( irp ); irp = NULL; } } return irp; }
/* create a desktop object */ static struct desktop *create_desktop( const struct unicode_str *name, unsigned int attr, unsigned int flags, struct winstation *winstation ) { struct desktop *desktop; if (memchrW( name->str, '\\', name->len / sizeof(WCHAR) )) /* no backslash allowed in name */ { set_error( STATUS_INVALID_PARAMETER ); return NULL; } if ((desktop = create_named_object( winstation->desktop_names, &desktop_ops, name, attr ))) { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ desktop->flags = flags; desktop->winstation = (struct winstation *)grab_object( winstation ); desktop->top_window = NULL; desktop->msg_window = NULL; desktop->global_hooks = NULL; desktop->close_timeout = NULL; desktop->foreground_input = NULL; desktop->users = 0; memset( &desktop->cursor, 0, sizeof(desktop->cursor) ); memset( desktop->keystate, 0, sizeof(desktop->keystate) ); list_add_tail( &winstation->desktops, &desktop->entry ); list_init( &desktop->hotkeys ); } } return desktop; }
/* retrieve the object corresponding to a handle, incrementing its refcount */ struct object *get_handle_obj( struct process *process, obj_handle_t handle, unsigned int access, const struct object_ops *ops ) { struct handle_entry *entry; struct object *obj; if (!(obj = get_magic_handle( handle ))) { if (!(entry = get_handle( process, handle ))) { set_error( STATUS_INVALID_HANDLE ); return NULL; } obj = entry->ptr; if (ops && (obj->ops != ops)) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); /* not the right type */ return NULL; } if ((entry->access & access) != access) { set_error( STATUS_ACCESS_DENIED ); return NULL; } } else if (ops && (obj->ops != ops)) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); /* not the right type */ return NULL; } return grab_object( obj ); }
/* accept a socket (creates a new fd) */ static struct sock *accept_socket( obj_handle_t handle ) { struct sock *acceptsock; struct sock *sock; int acceptfd; sock = (struct sock *)get_handle_obj( current->process, handle, FILE_READ_DATA, &sock_ops ); if (!sock) return NULL; if ( sock->deferred ) { acceptsock = sock->deferred; sock->deferred = NULL; } else { if ((acceptfd = accept_new_fd( sock )) == -1) { release_object( sock ); return NULL; } if (!(acceptsock = alloc_object( &sock_ops ))) { close( acceptfd ); release_object( sock ); return NULL; } init_sock( acceptsock ); /* newly created socket gets the same properties of the listening socket */ acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE; if (sock->state & FD_WINE_NONBLOCKING) acceptsock->state |= FD_WINE_NONBLOCKING; acceptsock->mask = sock->mask; acceptsock->proto = sock->proto; acceptsock->type = sock->type; acceptsock->family = sock->family; acceptsock->window = sock->window; acceptsock->message = sock->message; if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event ); acceptsock->flags = sock->flags; if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj, get_fd_options( sock->fd ) ))) { release_object( acceptsock ); release_object( sock ); return NULL; } } clear_error(); sock->pmask &= ~FD_ACCEPT; sock->hmask &= ~FD_ACCEPT; sock_reselect( sock ); release_object( sock ); return acceptsock; }
/* 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) wake_up( &debug_ctx->obj, 0 ); }
/* find the shared PE mapping for a given mapping */ static struct shared_map *get_shared_file( struct fd *fd ) { struct shared_map *ptr; LIST_FOR_EACH_ENTRY( ptr, &shared_map_list, struct shared_map, entry ) if (is_same_file_fd( ptr->fd, fd )) return (struct shared_map *)grab_object( ptr ); return NULL; }
/* find the shared PE mapping for a given mapping */ static struct file *get_shared_file( struct mapping *mapping ) { struct mapping *ptr; LIST_FOR_EACH_ENTRY( ptr, &shared_list, struct mapping, shared_entry ) if (is_same_file( ptr->file, mapping->file )) return (struct file *)grab_object( ptr->shared_file ); return NULL; }
static struct object *create_file_obj( struct fd *fd, unsigned int access, unsigned int options ) { struct file *file = alloc_object( &file_ops ); if (!file) return NULL; file->access = access; file->options = options; file->fd = fd; grab_object( fd ); set_fd_user( fd, &file_fd_ops, &file->obj ); return &file->obj; }
static struct object *create_file_obj( struct fd *fd, unsigned int access, mode_t mode ) { struct file *file = alloc_object( &file_ops ); if (!file) return NULL; file->access = access; file->mode = mode; file->uid = ~(uid_t)0; file->fd = fd; grab_object( fd ); set_fd_user( fd, &file_fd_ops, &file->obj ); return &file->obj; }
void EditorInputCenter::add_path_node() { Path::Node new_node; new_node.position = sector_pos; new_node.time = 1; edited_path->nodes.insert(last_node_marker->node + 1, new_node); GameObjectPtr marker; marker = std::make_shared<NodeMarker>(edited_path, edited_path->nodes.end() - 1, edited_path->nodes.size() - 1); Sector::current()->add_object(marker); //last_node_marker = dynamic_cast<NodeMarker*>(marker.get()); update_node_iterators(); Editor::current()->currentsector->update(0); grab_object(); }
static void gen_pair(struct aoi_space * space, struct object * watcher, struct object * marker, aoi_Callback cb, void *ud) { if (watcher == marker) { return; } float distance2 = dist2(watcher, marker); if (distance2 < AOI_RADIS2) { cb(ud, watcher->id, marker->id); return; } if (distance2 > AOI_RADIS2 * 4) { return; } struct pair_list * p = space->alloc(space->alloc_ud, NULL, sizeof(*p)); p->watcher = watcher; grab_object(watcher); p->marker = marker; grab_object(marker); p->watcher_version = watcher->version; p->marker_version = marker->version; p->next = space->hot; space->hot = p; }
static struct object *device_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ) { struct device *device = (struct device *)obj; struct device_file *file; if (!(file = alloc_object( &device_file_ops ))) return NULL; file->device = (struct device *)grab_object( device ); file->user_ptr = 0; list_init( &file->requests ); list_add_tail( &device->files, &file->entry ); if (device->unix_path) { mode_t mode = 0666; access = file->obj.ops->map_access( &file->obj, access ); file->fd = open_fd( NULL, device->unix_path, O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options ); if (file->fd) set_fd_user( file->fd, &device_file_fd_ops, &file->obj ); } else file->fd = alloc_pseudo_fd( &device_file_fd_ops, &file->obj, 0 ); if (!file->fd) { release_object( file ); return NULL; } if (device->manager) { struct irp_call *irp; irp_params_t params; memset( ¶ms, 0, sizeof(params) ); params.create.major = IRP_MJ_CREATE; params.create.access = access; params.create.sharing = sharing; params.create.options = options; params.create.device = file->device->user_ptr; if ((irp = create_irp( file, ¶ms, NULL, 0, 0 ))) { add_irp_to_queue( file, irp, NULL ); release_object( irp ); } } return &file->obj; }
/* terminate a process with the given exit code */ void terminate_process(struct w32process *process, int exit_code) { struct list_head *ptr; grab_object(process); /* make sure it doesn't get freed when threads die */ while ((ptr = list_head(&process->thread_list))) { struct w32thread *thread = LIST_ENTRY(ptr, struct w32thread, proc_entry); remove_process_thread(process, thread); release_object(thread); } if (process->dummyfd != -1) { close(process->dummyfd); process->dummyfd = -1; } release_object(process); }
void EditorInputCenter::process_left_click() { dragging = true; dragging_right = false; drag_start = sector_pos; switch (Editor::current()->tileselect.input_type) { case EditorInputGui::IP_TILE: { switch (Editor::current()->tileselect.select_mode->get_mode()) { case 0: put_tile(); break; case 1: draw_rectangle(); break; case 2: fill(); break; default: break; } } break; case EditorInputGui::IP_OBJECT: switch (Editor::current()->tileselect.move_mode->get_mode()) { case 0: grab_object(); break; case 1: clone_object(); break; default: break; } if (!Editor::current()->tileselect.object.empty()) { if (!dragged_object) { put_object(); } } else { rubber_object(); } break; default: break; } }
static obj_handle_t device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data, int blocking, 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 thread *)grab_object( current ); ioctl->user_arg = async_data->arg; if (!(handle = alloc_handle( current->process, ioctl, SYNCHRONIZE, 0 ))) { release_object( ioctl ); return 0; } if (!(ioctl->async = fd_queue_async( device->fd, async_data, ASYNC_TYPE_WAIT ))) { close_handle( current->process, handle ); release_object( ioctl ); return 0; } list_add_tail( &device->requests, &ioctl->dev_entry ); list_add_tail( &device->manager->requests, &ioctl->mgr_entry ); if (list_head( &device->manager->requests ) == &ioctl->mgr_entry) /* first one */ wake_up( &device->manager->obj, 0 ); /* don't release ioctl since it is now queued in the device */ set_error( STATUS_PENDING ); return handle; }
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; }
/* allocate and fill the temp file for a shared PE image mapping */ static int build_shared_mapping( struct mapping *mapping, int fd, IMAGE_SECTION_HEADER *sec, unsigned int nb_sec ) { struct shared_map *shared; struct file *file; unsigned int i; mem_size_t total_size; size_t file_size, map_size, max_size; off_t shared_pos, read_pos, write_pos; char *buffer = NULL; int shared_fd; long toread; /* compute the total size of the shared mapping */ total_size = max_size = 0; for (i = 0; i < nb_sec; i++) { if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) && (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { get_section_sizes( &sec[i], &map_size, &read_pos, &file_size ); if (file_size > max_size) max_size = file_size; total_size += map_size; } } if (!total_size) return 1; /* nothing to do */ if ((mapping->shared = get_shared_file( mapping->fd ))) return 1; /* create a temp file for the mapping */ if ((shared_fd = create_temp_file( total_size )) == -1) return 0; if (!(file = create_file_for_fd( shared_fd, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0 ))) return 0; if (!(buffer = malloc( max_size ))) goto error; /* copy the shared sections data into the temp file */ shared_pos = 0; for (i = 0; i < nb_sec; i++) { if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue; if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue; get_section_sizes( &sec[i], &map_size, &read_pos, &file_size ); write_pos = shared_pos; shared_pos += map_size; if (!sec[i].PointerToRawData || !file_size) continue; toread = file_size; while (toread) { long res = pread( fd, buffer + file_size - toread, toread, read_pos ); if (!res && toread < 0x200) /* partial sector at EOF is not an error */ { file_size -= toread; break; } if (res <= 0) goto error; toread -= res; read_pos += res; } if (pwrite( shared_fd, buffer, file_size, write_pos ) != file_size) goto error; } if (!(shared = alloc_object( &shared_map_ops ))) goto error; shared->fd = (struct fd *)grab_object( mapping->fd ); shared->file = file; list_add_head( &shared_map_list, &shared->entry ); mapping->shared = shared; free( buffer ); return 1; error: release_object( file ); free( buffer ); return 0; }
/* receive a file descriptor on the process socket */ int receive_fd( struct process *process ) { struct send_fd data; int fd, ret; #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS msghdr.msg_accrightslen = sizeof(int); msghdr.msg_accrights = (void *)&fd; #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ msghdr.msg_control = &cmsg; msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd); cmsg.fd = -1; #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ myiovec.iov_base = (void *)&data; myiovec.iov_len = sizeof(data); ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 ); #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS fd = cmsg.fd; #endif if (ret == sizeof(data)) { struct thread *thread; if (data.tid) thread = get_thread_from_id( data.tid ); else thread = (struct thread *)grab_object( get_process_first_thread( process )); if (!thread || thread->process != process || thread->state == TERMINATED) { if (debug_level) fprintf( stderr, "%04x: *fd* %d <- %d bad thread id\n", data.tid, data.fd, fd ); close( fd ); } else { if (debug_level) fprintf( stderr, "%04x: *fd* %d <- %d\n", thread->id, data.fd, fd ); thread_add_inflight_fd( thread, data.fd, fd ); } if (thread) release_object( thread ); return 0; } if (!ret) { kill_process( process, NULL, 0 ); } else if (ret > 0) { fprintf( stderr, "Protocol error: process %04x: partial recvmsg %d for fd\n", process->id, ret ); kill_process( process, NULL, 1 ); } else { if (errno != EWOULDBLOCK && errno != EAGAIN) { fprintf( stderr, "Protocol error: process %04x: ", process->id ); perror( "recvmsg" ); kill_process( process, NULL, 1 ); } } return -1; }
static struct fd *device_file_get_fd( struct object *obj ) { struct device_file *file = (struct device_file *)obj; return (struct fd *)grab_object( file->fd ); }
static struct fd *sock_get_fd( struct object *obj ) { struct sock *sock = (struct sock *)obj; return (struct fd *)grab_object( sock->fd ); }
static struct object *device_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ) { return grab_object( obj ); }
/* receive a file descriptor on the process socket */ int receive_fd( struct process *process ) { struct iovec vec; struct send_fd data; struct msghdr msghdr; int fd = -1, ret; #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS msghdr.msg_accrightslen = sizeof(int); msghdr.msg_accrights = (void *)&fd; #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ char cmsg_buffer[256]; msghdr.msg_control = cmsg_buffer; msghdr.msg_controllen = sizeof(cmsg_buffer); msghdr.msg_flags = 0; #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = &vec; msghdr.msg_iovlen = 1; vec.iov_base = (void *)&data; vec.iov_len = sizeof(data); ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 ); #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS if (ret > 0) { struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg )) { if (cmsg->cmsg_level != SOL_SOCKET) continue; if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg); } } #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ if (ret == sizeof(data)) { struct thread *thread; if (data.tid) thread = get_thread_from_id( data.tid ); else thread = (struct thread *)grab_object( get_process_first_thread( process )); if (!thread || thread->process != process || thread->state == TERMINATED) { if (debug_level) fprintf( stderr, "%04x: *fd* %d <- %d bad thread id\n", data.tid, data.fd, fd ); close( fd ); } else { if (debug_level) fprintf( stderr, "%04x: *fd* %d <- %d\n", thread->id, data.fd, fd ); thread_add_inflight_fd( thread, data.fd, fd ); } if (thread) release_object( thread ); return 0; } if (!ret) { kill_process( process, 0 ); } else if (ret > 0) { fprintf( stderr, "Protocol error: process %04x: partial recvmsg %d for fd\n", process->id, ret ); if (fd != -1) close( fd ); kill_process( process, 1 ); } else { if (errno != EWOULDBLOCK && errno != EAGAIN) { fprintf( stderr, "Protocol error: process %04x: ", process->id ); perror( "recvmsg" ); kill_process( process, 1 ); } } return -1; }
/* grab an object and increment its handle count */ static struct object *grab_object_for_handle( struct object *obj ) { obj->handle_count++; return grab_object( obj ); }
static struct fd *mapping_get_fd( struct object *obj ) { struct mapping *mapping = (struct mapping *)obj; return (struct fd *)grab_object( mapping->fd ); }
static struct fd *file_get_fd( struct object *obj ) { struct file *file = (struct file *)obj; assert( obj->ops == &file_ops ); return (struct fd *)grab_object( file->fd ); }
/* accept a socket (creates a new fd) */ static struct sock *accept_socket( obj_handle_t handle ) { struct sock *acceptsock; struct sock *sock; int acceptfd; struct sockaddr saddr; sock = (struct sock *)get_handle_obj( current->process, handle, FILE_READ_DATA, &sock_ops ); if (!sock) return NULL; if ( sock->deferred ) { acceptsock = sock->deferred; sock->deferred = NULL; } else { /* Try to accept(2). We can't be safe that this an already connected socket * or that accept() is allowed on it. In those cases we will get -1/errno * return. */ unsigned int slen = sizeof(saddr); acceptfd = accept( get_unix_fd(sock->fd), &saddr, &slen); if (acceptfd==-1) { sock_set_error(); release_object( sock ); return NULL; } if (!(acceptsock = alloc_object( &sock_ops ))) { close( acceptfd ); release_object( sock ); return NULL; } /* newly created socket gets the same properties of the listening socket */ fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE; if (sock->state & FD_WINE_NONBLOCKING) acceptsock->state |= FD_WINE_NONBLOCKING; acceptsock->mask = sock->mask; acceptsock->hmask = 0; acceptsock->pmask = 0; acceptsock->polling = 0; acceptsock->type = sock->type; acceptsock->family = sock->family; acceptsock->event = NULL; acceptsock->window = sock->window; acceptsock->message = sock->message; acceptsock->wparam = 0; if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event ); acceptsock->flags = sock->flags; acceptsock->deferred = NULL; acceptsock->read_q = NULL; acceptsock->write_q = NULL; memset( acceptsock->errors, 0, sizeof(acceptsock->errors) ); if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj, get_fd_options( sock->fd ) ))) { release_object( acceptsock ); release_object( sock ); return NULL; } } clear_error(); sock->pmask &= ~FD_ACCEPT; sock->hmask &= ~FD_ACCEPT; sock_reselect( sock ); release_object( sock ); return acceptsock; }