Added DebugBreak.
[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 "winerror.h"
14 #include "winnt.h"
15 #include "winbase.h"
16
17 #include "handle.h"
18 #include "thread.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     mapping_dump,
35     no_add_queue,
36     NULL,  /* should never get called */
37     NULL,  /* should never get called */
38     NULL,  /* should never get called */
39     no_read_fd,
40     no_write_fd,
41     no_flush,
42     no_get_file_info,
43     mapping_destroy
44 };
45
46 #ifdef __i386__
47
48 /* These are always the same on an i386, and it will be faster this way */
49 # define page_mask  0xfff
50 # define page_shift 12
51 # define init_page_size() /* nothing */
52
53 #else  /* __i386__ */
54
55 static int page_shift, page_mask;
56
57 static void init_page_size(void)
58 {
59     int page_size;
60 # ifdef HAVE_GETPAGESIZE
61     page_size = getpagesize();
62 # else
63 #  ifdef __svr4__
64     page_size = sysconf(_SC_PAGESIZE);
65 #  else
66 #   error Cannot get the page size on this platform
67 #  endif
68 # endif
69     page_mask = page_size - 1;
70     /* Make sure we have a power of 2 */
71     assert( !(page_size & page_mask) );
72     page_shift = 0;
73     while ((1 << page_shift) != page_size) page_shift++;
74 }
75 #endif  /* __i386__ */
76
77 #define ROUND_ADDR(addr) \
78    ((int)(addr) & ~page_mask)
79
80 #define ROUND_SIZE(addr,size) \
81    (((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask)
82
83
84 static struct object *create_mapping( int size_high, int size_low, int protect,
85                                       int handle, const char *name )
86 {
87     struct mapping *mapping;
88     int access = 0;
89
90     if (!page_mask) init_page_size();
91
92     if (!(mapping = (struct mapping *)create_named_object( name, &mapping_ops,
93                                                            sizeof(*mapping) )))
94         return NULL;
95     if (GET_ERROR() == ERROR_ALREADY_EXISTS)
96         return &mapping->obj;  /* Nothing else to do */
97
98     if (protect & VPROT_READ) access |= GENERIC_READ;
99     if (protect & VPROT_WRITE) access |= GENERIC_WRITE;
100
101     if (handle != -1)
102     {
103         if (!(mapping->file = get_file_obj( current->process, handle, access ))) goto error;
104         if (!size_high && !size_low)
105         {
106             struct get_file_info_reply reply;
107             struct object *obj = (struct object *)mapping->file;
108             obj->ops->get_file_info( obj, &reply );
109             size_high = reply.size_high;
110             size_low  = ROUND_SIZE( 0, reply.size_low );
111         }
112         else if (!grow_file( mapping->file, size_high, size_low )) goto error;
113     }
114     else  /* Anonymous mapping (no associated file) */
115     {
116         if (!size_high && !size_low)
117         {
118             SET_ERROR( ERROR_INVALID_PARAMETER );
119             mapping->file = NULL;
120             goto error;
121         }
122         if (!(mapping->file = create_temp_file( access ))) goto error;
123         if (!grow_file( mapping->file, size_high, size_low )) goto error;
124     }
125     mapping->size_high = size_high;
126     mapping->size_low  = ROUND_SIZE( 0, size_low );
127     mapping->protect   = protect;
128     return &mapping->obj;
129
130  error:
131     release_object( mapping );
132     return NULL;
133 }
134
135 static int get_mapping_info( int handle, struct get_mapping_info_reply *reply )
136 {
137     struct mapping *mapping;
138     int fd;
139
140     if (!(mapping = (struct mapping *)get_handle_obj( current->process, handle,
141                                                       0, &mapping_ops )))
142         return -1;
143     reply->size_high = mapping->size_high;
144     reply->size_low  = mapping->size_low;
145     reply->protect   = mapping->protect;
146     if (mapping->file) fd = file_get_mmap_fd( mapping->file );
147     else fd = -1;
148     release_object( mapping );
149     return fd;
150 }
151
152 static void mapping_dump( struct object *obj, int verbose )
153 {
154     struct mapping *mapping = (struct mapping *)obj;
155     assert( obj->ops == &mapping_ops );
156     fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p name='%s'\n",
157              mapping->size_high, mapping->size_low, mapping->protect,
158              mapping->file, get_object_name( &mapping->obj ) );
159 }
160
161 static void mapping_destroy( struct object *obj )
162 {
163     struct mapping *mapping = (struct mapping *)obj;
164     assert( obj->ops == &mapping_ops );
165     if (mapping->file) release_object( mapping->file );
166     free( mapping );
167 }
168
169 /* create a file mapping */
170 DECL_HANDLER(create_mapping)
171 {
172     struct object *obj;
173     struct create_mapping_reply reply = { -1 };
174     char *name = (char *)data;
175     if (!len) name = NULL;
176     else CHECK_STRING( "create_mapping", name, len );
177
178     if ((obj = create_mapping( req->size_high, req->size_low,
179                                req->protect, req->handle, name )))
180     {
181         int access = FILE_MAP_ALL_ACCESS;
182         if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
183         reply.handle = alloc_handle( current->process, obj, access, req->inherit );
184         release_object( obj );
185     }
186     send_reply( current, -1, 1, &reply, sizeof(reply) );
187 }
188
189 /* open a handle to a mapping */
190 DECL_HANDLER(open_mapping)
191 {
192     struct open_mapping_reply reply;
193     char *name = (char *)data;
194     if (!len) name = NULL;
195     else CHECK_STRING( "open_mapping", name, len );
196
197     reply.handle = open_object( name, &mapping_ops, req->access, req->inherit );
198     send_reply( current, -1, 1, &reply, sizeof(reply) );
199 }
200
201 /* get a mapping information */
202 DECL_HANDLER(get_mapping_info)
203 {
204     struct get_mapping_info_reply reply;
205     int map_fd = get_mapping_info( req->handle, &reply );
206     send_reply( current, map_fd, 1, &reply, sizeof(reply) );
207 }