static struct object *create_mapping( struct object *root, const struct unicode_str *name, unsigned int attr, mem_size_t size, unsigned int flags, obj_handle_t handle, unsigned int file_access, const struct security_descriptor *sd ) { struct mapping *mapping; struct file *file; struct fd *fd; int unix_fd; struct stat st; if (!page_mask) page_mask = sysconf( _SC_PAGESIZE ) - 1; if (!(mapping = create_named_object( root, &mapping_ops, name, attr, sd ))) return NULL; if (get_error() == STATUS_OBJECT_NAME_EXISTS) return &mapping->obj; /* Nothing else to do */ mapping->size = size; mapping->fd = NULL; mapping->shared = NULL; mapping->committed = NULL; if (!(mapping->flags = get_mapping_flags( handle, flags ))) goto error; if (handle) { const unsigned int sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; unsigned int mapping_access = FILE_MAPPING_ACCESS; if (!(file = get_file_obj( current->process, handle, file_access ))) goto error; fd = get_obj_fd( (struct object *)file ); /* file sharing rules for mappings are different so we use magic the access rights */ if (flags & SEC_IMAGE) mapping_access |= FILE_MAPPING_IMAGE; else if (file_access & FILE_WRITE_DATA) mapping_access |= FILE_MAPPING_WRITE; if (!(mapping->fd = get_fd_object_for_mapping( fd, mapping_access, sharing ))) { mapping->fd = dup_fd_object( fd, mapping_access, sharing, FILE_SYNCHRONOUS_IO_NONALERT ); if (mapping->fd) set_fd_user( mapping->fd, &mapping_fd_ops, NULL ); } release_object( file ); release_object( fd ); if (!mapping->fd) goto error; if ((unix_fd = get_unix_fd( mapping->fd )) == -1) goto error; if (fstat( unix_fd, &st ) == -1) { file_set_error(); goto error; } if (flags & SEC_IMAGE) { unsigned int err = get_image_params( mapping, st.st_size, unix_fd ); if (!err) return &mapping->obj; set_error( err ); goto error; } if (!mapping->size) { if (!(mapping->size = st.st_size)) { set_error( STATUS_MAPPED_FILE_SIZE_ZERO ); goto error; } } else if (st.st_size < mapping->size) { if (!(file_access & FILE_WRITE_DATA)) { set_error( STATUS_SECTION_TOO_BIG ); goto error; } if (!grow_file( unix_fd, mapping->size )) goto error; } } else /* Anonymous mapping (no associated file) */ { if (!mapping->size) { set_error( STATUS_INVALID_PARAMETER ); goto error; } if ((flags & SEC_RESERVE) && !(mapping->committed = create_ranges())) goto error; mapping->size = (mapping->size + page_mask) & ~((mem_size_t)page_mask); if ((unix_fd = create_temp_file( mapping->size )) == -1) goto error; if (!(mapping->fd = create_anonymous_fd( &mapping_fd_ops, unix_fd, &mapping->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) goto error; allow_fd_caching( mapping->fd ); } return &mapping->obj; error: release_object( mapping ); return NULL; }
static struct fd *mapping_get_fd( struct object *obj ) { struct mapping *mapping = (struct mapping *)obj; return get_obj_fd( (struct object *)mapping->file ); }