First version of DLL preloader.
[wincetools.git] / loader / server_mapping.c
1 /* From wine1.2-1.1.42/server/mapping.c  */\r
2 \r
3 /*\r
4  * Server-side file mapping management\r
5  *\r
6  * Copyright (C) 1999 Alexandre Julliard\r
7  * Copyright 2010 g10 Code GmbH\r
8  *\r
9  * This library is free software; you can redistribute it and/or\r
10  * modify it under the terms of the GNU Lesser General Public\r
11  * License as published by the Free Software Foundation; either\r
12  * version 2.1 of the License, or (at your option) any later version.\r
13  *\r
14  * This library is distributed in the hope that it will be useful,\r
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
17  * Lesser General Public License for more details.\r
18  *\r
19  * You should have received a copy of the GNU Lesser General Public\r
20  * License along with this library; if not, write to the Free Software\r
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA\r
22  */\r
23 \r
24 #include "wine.h"\r
25 #include <assert.h>\r
26 \r
27 /* These are always the same.  */\r
28 # define page_mask  0xfff\r
29 # define page_shift 12\r
30 # define init_page_size() do { /* nothing */ } while(0)\r
31 \r
32 #define set_error(x) SetLastError(x)\r
33 \r
34 #define ROUND_SIZE(size)  (((size) + page_mask) & ~page_mask)\r
35 \r
36 \r
37 \r
38 struct mapping\r
39 {\r
40   void           *obj;\r
41   mem_size_t      size;            /* mapping size */\r
42   int             protect;         /* protection flags */\r
43   HANDLE         *fhnd;             /* handle for file */\r
44   HANDLE         *hnd;             /* handle for mapped file */\r
45   int             header_size;     /* size of headers (for PE image mapping) */\r
46   void           *base;            /* default base addr (for PE image mapping) */\r
47 };\r
48 \r
49 \r
50 \r
51 /* retrieve the mapping parameters for an executable (PE) image */\r
52 static int get_image_params( struct mapping *mapping, HANDLE unix_fd )\r
53 {\r
54   IMAGE_DOS_HEADER dos;\r
55   IMAGE_SECTION_HEADER *sec = NULL;\r
56   struct\r
57   {\r
58     DWORD Signature;\r
59     IMAGE_FILE_HEADER FileHeader;\r
60     union\r
61     {\r
62       IMAGE_OPTIONAL_HEADER32 hdr32;\r
63       IMAGE_OPTIONAL_HEADER64 hdr64;\r
64     } opt;\r
65   } nt;\r
66   off_t pos;\r
67   int size;\r
68 \r
69     /* load the headers */\r
70 \r
71     if (pread( unix_fd, (char *) &dos, sizeof(dos), 0 ) != sizeof(dos)) goto error;\r
72     if (dos.e_magic != IMAGE_DOS_SIGNATURE) goto error;\r
73     pos = dos.e_lfanew;\r
74 \r
75     size = pread( unix_fd, (char *) &nt, sizeof(nt), pos );\r
76     if (size < sizeof(nt.Signature) + sizeof(nt.FileHeader)) goto error;\r
77     /* zero out Optional header in the case it's not present or partial */\r
78     if (size < sizeof(nt)) memset( (char *)&nt + size, 0, sizeof(nt) - size );\r
79     if (nt.Signature != IMAGE_NT_SIGNATURE) goto error;\r
80 \r
81     switch (nt.opt.hdr32.Magic)\r
82       {\r
83       case IMAGE_NT_OPTIONAL_HDR32_MAGIC:\r
84         mapping->size        = ROUND_SIZE( nt.opt.hdr32.SizeOfImage );\r
85         mapping->base        = (void *) nt.opt.hdr32.ImageBase;\r
86         mapping->header_size = nt.opt.hdr32.SizeOfHeaders;\r
87         break;\r
88       case IMAGE_NT_OPTIONAL_HDR64_MAGIC:\r
89         mapping->size        = ROUND_SIZE( nt.opt.hdr64.SizeOfImage );\r
90         mapping->base        = (void *) nt.opt.hdr64.ImageBase;\r
91         mapping->header_size = nt.opt.hdr64.SizeOfHeaders;\r
92         break;\r
93       default:\r
94         goto error;\r
95       }\r
96 \r
97     /* load the section headers */\r
98 \r
99     pos += sizeof(nt.Signature) + sizeof(nt.FileHeader) + nt.FileHeader.SizeOfOptionalHeader;\r
100     size = sizeof(*sec) * nt.FileHeader.NumberOfSections;\r
101     if (pos + size > mapping->size) goto error;\r
102     if (pos + size > mapping->header_size) mapping->header_size = pos + size;\r
103     if (!(sec = malloc( size ))) goto error;\r
104     if (pread( unix_fd, (void *) sec, size, pos ) != size) goto error;\r
105 \r
106     // if (!build_shared_mapping( mapping, unix_fd, sec, nt.FileHeader.NumberOfSections )) goto error;\r
107 \r
108     // if (mapping->shared_file) list_add_head( &shared_list, &mapping->shared_entry );\r
109 \r
110     mapping->protect = VPROT_IMAGE;\r
111     free( sec );\r
112     return 1;\r
113 \r
114  error:\r
115     free( sec );\r
116     set_error( STATUS_INVALID_FILE_FOR_SECTION );\r
117     return 0;\r
118 }\r
119 \r
120 \r
121 void *create_mapping(/* struct directory *root */ void *root,\r
122                      /* const struct unicode_str *name */ void *name,\r
123                      unsigned int attr, mem_size_t size, int protect,\r
124                      HANDLE handle, /* const struct security_descriptor *sd */ void *sd)\r
125 {\r
126   struct mapping *mapping;\r
127 #if 0\r
128   struct file *file;\r
129   struct fd *fd;\r
130 #endif\r
131   int access = 0;\r
132 #if 0\r
133   int unix_fd;\r
134 #endif\r
135 \r
136   if (!page_mask) init_page_size();\r
137 \r
138   if (!(mapping = malloc (sizeof (struct mapping))))\r
139     return NULL;\r
140 \r
141   mapping->obj         = NULL;\r
142   mapping->header_size = 0;\r
143   mapping->base        = 0;\r
144   mapping->fhnd        = handle;\r
145   mapping->hnd         = 0;\r
146 \r
147   if (protect & VPROT_READ) access |= FILE_READ_DATA;\r
148   if (protect & VPROT_WRITE) access |= FILE_WRITE_DATA;\r
149 \r
150   if (handle)\r
151     {\r
152       // unsigned int mapping_access = FILE_MAPPING_ACCESS;\r
153 \r
154       if (!(protect & VPROT_COMMITTED))\r
155         {\r
156           SetLastError( STATUS_INVALID_PARAMETER );\r
157           goto error;\r
158         }\r
159     \r
160       mapping->hnd = CreateFileMapping (handle, NULL, get_prot_flags (protect),\r
161                                         0, size, NULL);\r
162       if (mapping->hnd == INVALID_HANDLE_VALUE)\r
163         goto error;\r
164 \r
165 #if 0\r
166       /* file sharing rules for mappings are different so we use magic the access rights */\r
167       if (protect & VPROT_IMAGE) mapping_access |= FILE_MAPPING_IMAGE;\r
168       else if (protect & VPROT_WRITE) mapping_access |= FILE_MAPPING_WRITE;\r
169 #endif\r
170 \r
171       if (protect & VPROT_IMAGE)\r
172         {\r
173           if (!get_image_params( mapping, handle )) goto error;\r
174           return &mapping->obj;\r
175         }\r
176 #if 0\r
177       if (fstat( unix_fd, &st ) == -1)\r
178         {\r
179           file_set_error();\r
180           goto error;\r
181         }\r
182       if (!size)\r
183         {\r
184           if (!(size = st.st_size))\r
185             {\r
186               set_error( STATUS_MAPPED_FILE_SIZE_ZERO );\r
187               goto error;\r
188             }\r
189         }\r
190       else if (st.st_size < size && !grow_file( unix_fd, size )) goto error;\r
191 #endif\r
192     }\r
193   else  /* Anonymous mapping (no associated file) */\r
194     {\r
195 #if 0\r
196       if (!size || (protect & VPROT_IMAGE))\r
197         {\r
198           set_error( STATUS_INVALID_PARAMETER );\r
199           goto error;\r
200         }\r
201       if (!(protect & VPROT_COMMITTED))\r
202         {\r
203           if (!(mapping->committed = mem_alloc( offsetof(struct ranges, ranges[8]) ))) goto error;\r
204           mapping->committed->count = 0;\r
205           mapping->committed->max   = 8;\r
206         }\r
207       if ((unix_fd = create_temp_file( size )) == -1) goto error;\r
208       if (!(mapping->fd = create_anonymous_fd( &mapping_fd_ops, unix_fd, &mapping->obj,\r
209                                                FILE_SYNCHRONOUS_IO_NONALERT ))) goto error;\r
210 #endif\r
211       assert (!"Not implemented.");\r
212     }\r
213   mapping->size    = (size + page_mask) & ~((mem_size_t)page_mask);\r
214   mapping->protect = protect;\r
215   return &mapping->obj;\r
216   \r
217  error:\r
218   free( mapping );\r
219   return NULL;\r
220 }\r
221 \r
222 \r
223 /* create a file mapping */\r
224 NTSTATUS SERVER_create_mapping (ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,\r
225                                 HANDLE file_handle, long long size, unsigned int protect, HANDLE *handle)\r
226 {\r
227   void *obj;\r
228   \r
229   *handle = 0;\r
230 \r
231   obj = create_mapping( NULL, NULL, 0, (mem_size_t) size, protect, file_handle, NULL );\r
232   if (! obj)\r
233     return GetLastError ();\r
234 \r
235   *handle = (HANDLE)obj;\r
236 \r
237   return STATUS_SUCCESS;\r
238 }\r
239 \r
240 \r
241 NTSTATUS SERVER_get_mapping_info (HANDLE _mapping, ACCESS_MASK access, unsigned int *protect,\r
242                                   void **base, mem_size_t *size, int *header_size, HANDLE *fhandle,\r
243                                   HANDLE *handle)\r
244 {\r
245   struct mapping *mapping = (struct mapping *) _mapping;\r
246 \r
247   /* Ignore access.  */\r
248 \r
249   *size        = mapping->size;\r
250   *protect     = mapping->protect;\r
251   *fhandle     = mapping->fhnd;\r
252   *handle      = mapping->hnd;\r
253   *header_size = mapping->header_size;\r
254   *base        = mapping->base;\r
255 \r
256   return STATUS_SUCCESS;\r
257 }\r
258 \r