Made request tracing more robust against bogus lengths.
[wine] / server / mapping.c
1 /*
2  * Server-side file mapping management
3  *
4  * Copyright (C) 1999 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11
12 #include "config.h"
13 #include "winnt.h"
14 #include "winbase.h"
15
16 #include "handle.h"
17 #include "thread.h"
18 #include "request.h"
19
20 struct mapping
21 {
22     struct object  obj;             /* object header */
23     int            size_high;       /* mapping size */
24     int            size_low;        /* mapping size */
25     int            protect;         /* protection flags */
26     struct file   *file;            /* file mapped */
27 };
28
29 static void mapping_dump( struct object *obj, int verbose );
30 static void mapping_destroy( struct object *obj );
31
32 static const struct object_ops mapping_ops =
33 {
34     sizeof(struct mapping),      /* size */
35     mapping_dump,                /* dump */
36     no_add_queue,                /* add_queue */
37     NULL,                        /* remove_queue */
38     NULL,                        /* signaled */
39     NULL,                        /* satisfied */
40     NULL,                        /* get_poll_events */
41     NULL,                        /* poll_event */
42     no_read_fd,                  /* get_read_fd */
43     no_write_fd,                 /* get_write_fd */
44     no_flush,                    /* flush */
45     no_get_file_info,            /* get_file_info */
46     mapping_destroy              /* destroy */
47 };
48
49 #ifdef __i386__
50
51 /* These are always the same on an i386, and it will be faster this way */
52 # define page_mask  0xfff
53 # define page_shift 12
54 # define init_page_size() /* nothing */
55
56 #else  /* __i386__ */
57
58 static int page_shift, page_mask;
59
60 static void init_page_size(void)
61 {
62     int page_size;
63 # ifdef HAVE_GETPAGESIZE
64     page_size = getpagesize();
65 # else
66 #  ifdef __svr4__
67     page_size = sysconf(_SC_PAGESIZE);
68 #  else
69 #   error Cannot get the page size on this platform
70 #  endif
71 # endif
72     page_mask = page_size - 1;
73     /* Make sure we have a power of 2 */
74     assert( !(page_size & page_mask) );
75     page_shift = 0;
76     while ((1 << page_shift) != page_size) page_shift++;
77 }
78 #endif  /* __i386__ */
79
80 #define ROUND_ADDR(addr) \
81    ((int)(addr) & ~page_mask)
82
83 #define ROUND_SIZE(addr,size) \
84    (((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask)
85
86
87 static struct object *create_mapping( int size_high, int size_low, int protect,
88                                       int handle, const WCHAR *name, size_t len )
89 {
90     struct mapping *mapping;
91     int access = 0;
92
93     if (!page_mask) init_page_size();
94
95     if (!(mapping = create_named_object( &mapping_ops, name, len )))
96         return NULL;
97     if (get_error() == STATUS_OBJECT_NAME_COLLISION)
98         return &mapping->obj;  /* Nothing else to do */
99
100     if (protect & VPROT_READ) access |= GENERIC_READ;
101     if (protect & VPROT_WRITE) access |= GENERIC_WRITE;
102
103     if (handle != -1)
104     {
105         if (!(mapping->file = get_file_obj( current->process, handle, access ))) goto error;
106         if (!size_high && !size_low)
107         {
108             struct get_file_info_request req;
109             struct object *obj = (struct object *)mapping->file;
110             obj->ops->get_file_info( obj, &req );
111             size_high = req.size_high;
112             size_low  = ROUND_SIZE( 0, req.size_low );
113         }
114         else if (!grow_file( mapping->file, size_high, size_low )) goto error;
115     }
116     else  /* Anonymous mapping (no associated file) */
117     {
118         if (!size_high && !size_low)
119         {
120             set_error( STATUS_INVALID_PARAMETER );
121             mapping->file = NULL;
122             goto error;
123         }
124         if (!(mapping->file = create_temp_file( access ))) goto error;
125         if (!grow_file( mapping->file, size_high, size_low )) goto error;
126     }
127     mapping->size_high = size_high;
128     mapping->size_low  = ROUND_SIZE( 0, size_low );
129     mapping->protect   = protect;
130     return &mapping->obj;
131
132  error:
133     release_object( mapping );
134     return NULL;
135 }
136
137 static void mapping_dump( struct object *obj, int verbose )
138 {
139     struct mapping *mapping = (struct mapping *)obj;
140     assert( obj->ops == &mapping_ops );
141     fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p ",
142              mapping->size_high, mapping->size_low, mapping->protect, mapping->file );
143     dump_object_name( &mapping->obj );
144     fputc( '\n', stderr );
145 }
146
147 static void mapping_destroy( struct object *obj )
148 {
149     struct mapping *mapping = (struct mapping *)obj;
150     assert( obj->ops == &mapping_ops );
151     if (mapping->file) release_object( mapping->file );
152 }
153
154 int get_page_size(void)
155 {
156     if (!page_mask) init_page_size();
157     return page_mask + 1;
158 }
159
160 /* create a file mapping */
161 DECL_HANDLER(create_mapping)
162 {
163     size_t len = get_req_strlenW( req, req->name );
164     struct object *obj;
165
166     req->handle = -1;
167     if ((obj = create_mapping( req->size_high, req->size_low,
168                                req->protect, req->file_handle, req->name, len )))
169     {
170         int access = FILE_MAP_ALL_ACCESS;
171         if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
172         req->handle = alloc_handle( current->process, obj, access, req->inherit );
173         release_object( obj );
174     }
175 }
176
177 /* open a handle to a mapping */
178 DECL_HANDLER(open_mapping)
179 {
180     size_t len = get_req_strlenW( req, req->name );
181     req->handle = open_object( req->name, len, &mapping_ops, req->access, req->inherit );
182 }
183
184 /* get a mapping information */
185 DECL_HANDLER(get_mapping_info)
186 {
187     struct mapping *mapping;
188
189     if ((mapping = (struct mapping *)get_handle_obj( current->process, req->handle,
190                                                      0, &mapping_ops )))
191     {
192         req->size_high = mapping->size_high;
193         req->size_low  = mapping->size_low;
194         req->protect   = mapping->protect;
195         if (mapping->file) set_reply_fd( current, file_get_mmap_fd( mapping->file ) );
196         release_object( mapping );
197     }
198 }
199