/* 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; }
/* 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; }
struct file *get_file_obj( struct process *process, obj_handle_t handle, unsigned int access ) { return (struct file *)get_handle_obj( process, handle, access, &file_ops ); }
struct keyed_event *get_keyed_event_obj( struct process *process, obj_handle_t handle, unsigned int access ) { return (struct keyed_event *)get_handle_obj( process, handle, access, &keyed_event_ops ); }
struct mapping *get_mapping_obj( struct process *process, obj_handle_t handle, unsigned int access ) { return (struct mapping *)get_handle_obj( process, handle, access, &mapping_ops ); }
/* retrieve a pointer to a desktop object */ struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle, unsigned int access ) { return (struct desktop *)get_handle_obj( process, handle, access, &desktop_ops ); }
/* retrieve the process window station, checking the handle access rights */ struct winstation *get_process_winstation( struct process *process, unsigned int access ) { return (struct winstation *)get_handle_obj( process, process->winstation, access, &winstation_ops ); }
/* 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; }