Convert to unix line endings.
[wincetools.git] / loader / ntdll_virtual.c
1 /* From wine1.2-1.1.42/dlls/ntdll/virtual.c  */
2
3 /*
4  * Win32 virtual memory functions
5  *
6  * Copyright 1997, 2002 Alexandre Julliard
7  * Copyright 2010 g10 Code GmbH
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24
25 #include <windows.h>
26 #include <assert.h>
27
28 #include "wine.h"
29
30 /* File view */
31 typedef struct file_view
32 {
33     void         *base;        /* Base address */
34     size_t        size;        /* Size in bytes */
35     HANDLE        mapping;     /* Handle to the file mapping */
36     unsigned int  protect;     /* Protection for all pages at allocation time */
37 } FILE_VIEW;
38
39
40 # define page_mask  0xfff
41 # define page_shift 12
42 # define page_size  0x1000
43
44
45 #define ROUND_SIZE(addr,size) \
46   (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
47
48
49 static size_t get_mask( ULONG zero_bits )
50 {
51   if (!zero_bits) return 0xffff;  /* allocations are aligned to 64K by default */
52   if (zero_bits < page_shift) zero_bits = page_shift;
53   return (1 << zero_bits) - 1;
54 }
55
56
57 static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot )
58 {
59   switch(protect & 0xff)
60     {
61     case PAGE_READONLY:
62       *vprot = VPROT_READ;
63       break;
64     case PAGE_READWRITE:
65       *vprot = VPROT_READ | VPROT_WRITE;
66       break;
67     case PAGE_WRITECOPY:
68       *vprot = VPROT_READ | VPROT_WRITECOPY;
69       break;
70     case PAGE_EXECUTE:
71       *vprot = VPROT_EXEC;
72       break;
73     case PAGE_EXECUTE_READ:
74       *vprot = VPROT_EXEC | VPROT_READ;
75       break;
76     case PAGE_EXECUTE_READWRITE:
77       *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITE;
78       break;
79     case PAGE_EXECUTE_WRITECOPY:
80       *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITECOPY;
81       break;
82     case PAGE_NOACCESS:
83       *vprot = 0;
84       break;
85     default:
86       return STATUS_INVALID_PARAMETER;
87     }
88   if (protect & PAGE_GUARD) *vprot |= VPROT_GUARD;
89   if (protect & PAGE_NOCACHE) *vprot |= VPROT_NOCACHE;
90   return STATUS_SUCCESS;
91 }
92
93
94 static void delete_view( struct file_view *view ) /* [in] View */
95 {
96   VirtualFree (view->base, view->size, MEM_RELEASE);
97   // if (view->mapping) NtClose( view->mapping );
98   free (view);
99 }
100
101
102 static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, size_t mask,
103                           int top_down, unsigned int vprot )
104 {
105   int prot = get_prot_flags (vprot);
106   struct file_view *view;
107   void *ptr;
108   void *new_ptr;
109
110   view = malloc (sizeof (struct file_view));
111   if (!view)
112     return STATUS_NO_MEMORY;
113   
114   // FIXME: Only with NOACCESS does Windows CE prefer the high mem area
115   // even for smaller areas.
116   ptr = VirtualAlloc(base, size < (2* 1024*1024) ? 2*1024*1024 : size, MEM_RESERVE, PAGE_NOACCESS /*prot*/);
117   if (!ptr)
118     {
119       free (view);
120       return GetLastError();
121     }
122   /* We have to zero map the whole thing.  */
123   new_ptr = VirtualAlloc (ptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
124   if (new_ptr != ptr)
125     {
126       free (view);
127       return GetLastError();
128     }
129   view->base = ptr;
130   view->size = size;
131   view->protect = vprot;
132   view->mapping = 0;
133   *view_ret = view;
134   return STATUS_SUCCESS;
135 }
136
137
138 static NTSTATUS map_file_into_view( struct file_view *view, HANDLE fhandle, size_t start, size_t size,
139                                     off_t offset, unsigned int vprot, BOOL removable )
140 {
141   void *ptr;
142   int prot = get_prot_flags (vprot);
143   BOOL shared_write = (vprot & VPROT_WRITE) != 0;
144
145   assert( start < view->size );
146   assert( start + size <= view->size );
147
148 #if 0
149   /* only try mmap if media is not removable (or if we require write access) */
150   if (!removable || shared_write)
151     {
152       int flags = MAP_FIXED | (shared_write ? MAP_SHARED : MAP_PRIVATE);
153
154       if (mmap( (char *)view->base + start, size, prot, flags, fd, offset ) != (void *)-1)
155         goto done;
156
157       /* mmap() failed; if this is because the file offset is not    */
158       /* page-aligned (EINVAL), or because the underlying filesystem */
159       /* does not support mmap() (ENOEXEC,ENODEV), we do it by hand. */
160       if ((errno != ENOEXEC) && (errno != EINVAL) && (errno != ENODEV)) return FILE_GetNtStatus();
161       if (shared_write)  /* we cannot fake shared write mappings */
162         {
163           if (errno == EINVAL) return STATUS_INVALID_PARAMETER;
164           ERR( "shared writable mmap not supported, broken filesystem?\n" );
165           return STATUS_NOT_SUPPORTED;
166         }
167     }
168 #endif
169
170 #if 0
171   /* Already done by map_view.  */
172   /* Reserve the memory with an anonymous mmap */
173   ptr = VirtualAlloc ((char *)view->base + start, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
174   if (ptr == (void *)-1) return GetLastError();
175 #else
176   ptr = (char *)view->base + start;
177 #endif
178
179   /* Now read in the file */
180   pread( fhandle, ptr, size, offset );
181   //  if (prot != (PROT_READ|PROT_WRITE)) mprotect( ptr, size, prot );  /* Set the right protection */
182   //done:
183   //  memset( view->prot + (start >> page_shift), vprot, ROUND_SIZE(start,size) >> page_shift );
184   return STATUS_SUCCESS;
185 }
186
187
188 static NTSTATUS map_image (HANDLE hmapping, HANDLE hfile, HANDLE hmap, char *base, SIZE_T total_size, SIZE_T mask,
189                            SIZE_T header_size, int shared_fd, HANDLE dup_mapping, PVOID *addr_ptr)
190 {
191     IMAGE_DOS_HEADER *dos;
192     IMAGE_NT_HEADERS *nt;
193     IMAGE_SECTION_HEADER *sec;
194     IMAGE_DATA_DIRECTORY *imports;
195     NTSTATUS status = STATUS_CONFLICTING_ADDRESSES;
196     int i;
197     off_t pos;
198     DWORD fsize;
199     struct file_view *view = NULL;
200     char *ptr, *header_end;
201     INT_PTR delta = 0;
202
203
204     /* zero-map the whole range */
205
206     if (base >= (char *)0x110000)  /* make sure the DOS area remains free */
207       status = map_view( &view, base, total_size, mask, FALSE,
208                          VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY | VPROT_IMAGE );
209
210     if (status != STATUS_SUCCESS)
211       status = map_view( &view, NULL, total_size, mask, FALSE,
212                          VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY | VPROT_IMAGE );
213
214     if (status != STATUS_SUCCESS) goto error;
215
216     ptr = view->base;
217     TRACE( "mapped PE file at %p-%p\n", ptr, ptr + total_size );
218
219     /* map the header */
220     
221     fsize = GetFileSize (hfile, NULL);
222     if (fsize == INVALID_FILE_SIZE)
223       {
224         status = GetLastError();
225         goto error;
226       }
227     status = STATUS_INVALID_IMAGE_FORMAT;  /* generic error */
228     header_size = min( header_size, fsize );
229     if (map_file_into_view( view, hfile, 0, header_size, 0, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
230                             !dup_mapping ) != STATUS_SUCCESS) goto error;
231     dos = (IMAGE_DOS_HEADER *)ptr;
232     nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);
233     header_end = ptr + ROUND_SIZE( 0, header_size );
234     memset( ptr + header_size, 0, header_end - (ptr + header_size) );
235     if ((char *)(nt + 1) > header_end) goto error;
236     sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
237     if ((char *)(sec + nt->FileHeader.NumberOfSections) > header_end) goto error;
238
239     imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;
240     if (!imports->Size || !imports->VirtualAddress) imports = NULL;
241
242     /* check the architecture */
243
244     if (nt->FileHeader.Machine != IMAGE_FILE_MACHINE_ARM
245         && nt->FileHeader.Machine != IMAGE_FILE_MACHINE_THUMB)
246         {
247           TRACE("Trying to load PE image for unsupported architecture (");
248           switch (nt->FileHeader.Machine)
249             {
250             case IMAGE_FILE_MACHINE_UNKNOWN: TRACE("Unknown"); break;
251             case IMAGE_FILE_MACHINE_I386:    TRACE("I386"); break;
252             case IMAGE_FILE_MACHINE_R3000:   TRACE("R3000"); break;
253             case IMAGE_FILE_MACHINE_R4000:   TRACE("R4000"); break;
254             case IMAGE_FILE_MACHINE_R10000:  TRACE("R10000"); break;
255             case IMAGE_FILE_MACHINE_ALPHA:   TRACE("Alpha"); break;
256             case IMAGE_FILE_MACHINE_POWERPC: TRACE("PowerPC"); break;
257             case IMAGE_FILE_MACHINE_IA64:    TRACE("IA-64"); break;
258             case IMAGE_FILE_MACHINE_ALPHA64: TRACE("Alpha-64"); break;
259             case IMAGE_FILE_MACHINE_ARM:     TRACE("ARM"); break;
260             default: TRACE("Unknown-%04x", nt->FileHeader.Machine); break;
261             }
262           TRACE(")\n");
263           goto error;
264         }
265     
266     /* check for non page-aligned binary */
267
268     if (nt->OptionalHeader.SectionAlignment <= page_mask)
269       {
270         /* unaligned sections, this happens for native subsystem binaries */
271         /* in that case Windows simply maps in the whole file */
272
273         if (map_file_into_view( view, hfile, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ,
274                                 !dup_mapping ) != STATUS_SUCCESS) goto error;
275
276         /* check that all sections are loaded at the right offset */
277         if (nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) goto error;
278         for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
279           {
280             if (sec[i].VirtualAddress != sec[i].PointerToRawData)
281               goto error;  /* Windows refuses to load in that case too */
282           }
283 #if 0
284         /* set the image protections */
285         VIRTUAL_SetProt( view, ptr, total_size,
286                          VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY | VPROT_EXEC );
287 #endif
288
289 #if 0
290         /* no relocations are performed on non page-aligned binaries */
291         goto done;
292 #else
293         goto reloc;
294 #endif
295       }
296
297
298     /* map all the sections */
299
300     for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
301       {
302         static const SIZE_T sector_align = 0x1ff;
303         SIZE_T map_size, file_start, file_size, end;
304
305         if (!sec->Misc.VirtualSize)
306           map_size = ROUND_SIZE( 0, sec->SizeOfRawData );
307         else
308           map_size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
309
310         /* file positions are rounded to sector boundaries regardless of OptionalHeader.FileAlignment */
311         file_start = sec->PointerToRawData & ~sector_align;
312         file_size = (sec->SizeOfRawData + (sec->PointerToRawData & sector_align) + sector_align) & ~sector_align;
313         if (file_size > map_size) file_size = map_size;
314
315         /* a few sanity checks */
316         end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size );
317         if (sec->VirtualAddress > total_size || end > total_size || end < sec->VirtualAddress)
318           {
319             ERR ( "Section %.8s too large (%x+%lx/%lx)\n",
320                   sec->Name, sec->VirtualAddress, map_size, total_size );
321             goto error;
322           }
323
324         if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&
325             (sec->Characteristics & IMAGE_SCN_MEM_WRITE))
326           {
327             TRACE( "mapping shared section %.8s at %p off %x (%x) size %lx (%lx) flags %x\n",
328                    sec->Name, ptr + sec->VirtualAddress,
329                    sec->PointerToRawData, (int)pos, file_size, map_size,
330                    sec->Characteristics );
331             if (map_file_into_view( view, hfile, sec->VirtualAddress, map_size, pos,
332                                     VPROT_COMMITTED | VPROT_READ | VPROT_WRITE,
333                                     FALSE ) != STATUS_SUCCESS)
334               {
335                 ERR ( "Could not map shared section %.8s\n", sec->Name );
336                 goto error;
337               }
338
339             /* check if the import directory falls inside this section */
340             if (imports && imports->VirtualAddress >= sec->VirtualAddress &&
341                 imports->VirtualAddress < sec->VirtualAddress + map_size)
342               {
343                 UINT_PTR base = imports->VirtualAddress & ~page_mask;
344                 UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );
345                 if (end > sec->VirtualAddress + map_size) end = sec->VirtualAddress + map_size;
346                 if (end > base)
347                   map_file_into_view( view, hfile, base, end - base,
348                                       pos + (base - sec->VirtualAddress),
349                                       VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
350                                       FALSE );
351               }
352             pos += map_size;
353             continue;
354           }
355
356         ERR( "mapping section %.8s at %p off %x size %x virt %x flags %x\n",
357              sec->Name, ptr + sec->VirtualAddress,
358              sec->PointerToRawData, sec->SizeOfRawData,
359              sec->Misc.VirtualSize, sec->Characteristics );
360         
361         if (!sec->PointerToRawData || !file_size) continue;
362
363         /* Note: if the section is not aligned properly map_file_into_view will magically
364          *       fall back to read(), so we don't need to check anything here.
365          */
366         end = file_start + file_size;
367         if (sec->PointerToRawData >= fsize ||
368             end > ((fsize + sector_align) & ~sector_align) ||
369             end < file_start ||
370             map_file_into_view( view, hfile, sec->VirtualAddress, file_size, file_start,
371                                 VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
372                                 !dup_mapping ) != STATUS_SUCCESS)
373           {
374             ERR( "Could not map section %.8s, file probably truncated\n", sec->Name );
375             goto error;
376           }
377
378         if (file_size & page_mask)
379           {
380             end = ROUND_SIZE( 0, file_size );
381             if (end > map_size) end = map_size;
382             TRACE("clearing %p - %p\n",
383                   ptr + sec->VirtualAddress + file_size,
384                   ptr + sec->VirtualAddress + end );
385             memset( ptr + sec->VirtualAddress + file_size, 0, end - file_size );
386           }
387       }
388
389  reloc:
390     /* perform base relocation, if necessary */
391
392     if (ptr != base)
393       // &&
394       //        ((nt->FileHeader.Characteristics & IMAGE_FILE_DLL) ||
395       //         !NtCurrentTeb()->Peb->ImageBaseAddress) )
396       {
397         IMAGE_BASE_RELOCATION *rel, *end;
398         const IMAGE_DATA_DIRECTORY *relocs;
399
400         if (nt->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
401           {
402             TRACE( "Need to relocate module from %p to %p, but there are no relocation records\n",
403                    base, ptr );
404             status = STATUS_CONFLICTING_ADDRESSES;
405             goto error;
406           }
407
408         TRACE( "relocating from %p-%p to %p-%p\n",
409                base, base + total_size, ptr, ptr + total_size );
410
411         relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
412         rel = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress);
413         end = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress + relocs->Size);
414         delta = ptr - base;
415
416         while (rel < end - 1 && rel->SizeOfBlock)
417           {
418             if (rel->VirtualAddress >= total_size)
419               {
420                 TRACE( "invalid address %p in relocation %p\n", ptr + rel->VirtualAddress, rel );
421                 status = STATUS_ACCESS_VIOLATION;
422                 goto error;
423               }
424             rel = MyLdrProcessRelocationBlock( ptr + rel->VirtualAddress,
425                                                (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
426                                                (USHORT *)(rel + 1), delta );
427             if (!rel) goto error;
428           }
429       }
430 #if 0
431     /* set the image protections */
432     VIRTUAL_SetProt( view, ptr, ROUND_SIZE( 0, header_size ), VPROT_COMMITTED | VPROT_READ );
433
434     sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
435     for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
436       {
437         SIZE_T size;
438         BYTE vprot = VPROT_COMMITTED;
439
440         if (sec->Misc.VirtualSize)
441           size = ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
442         else
443           size = ROUND_SIZE( sec->VirtualAddress, sec->SizeOfRawData );
444
445         if (sec->Characteristics & IMAGE_SCN_MEM_READ)    vprot |= VPROT_READ;
446         if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)   vprot |= VPROT_READ|VPROT_WRITECOPY;
447         if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;
448
449         /* Dumb game crack lets the AOEP point into a data section. Adjust. */
450         if ((nt->OptionalHeader.AddressOfEntryPoint >= sec->VirtualAddress) &&
451             (nt->OptionalHeader.AddressOfEntryPoint < sec->VirtualAddress + size))
452           vprot |= VPROT_EXEC;
453
454         VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
455       }
456 #endif
457
458     // done:
459     *addr_ptr = ptr;
460 #ifdef VALGRIND_LOAD_PDB_DEBUGINFO
461     VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta);
462 #endif
463     if (ptr != base) return STATUS_IMAGE_NOT_AT_BASE;
464     return STATUS_SUCCESS;
465
466  error:
467     if (view) delete_view( view );
468     return status;
469 }
470
471
472 NTSTATUS MyNtCreateSection (HANDLE *handle, ACCESS_MASK access,
473                             /* const OBJECT_ATTRIBUTES *attr */ void *attr,
474                             const LARGE_INTEGER *size, ULONG protect,
475                             ULONG sec_flags, HANDLE file)
476 {
477     NTSTATUS ret;
478     unsigned int vprot;
479     
480     if ((ret = get_vprot_flags( protect, &vprot ))) return ret;
481
482     assert (attr == NULL);
483
484     if (!(sec_flags & SEC_RESERVE)) vprot |= VPROT_COMMITTED;
485     if (sec_flags & SEC_NOCACHE) vprot |= VPROT_NOCACHE;
486     if (sec_flags & SEC_IMAGE) vprot |= VPROT_IMAGE;
487
488     ret = SERVER_create_mapping (access, attr, file, size ? size->QuadPart : 0,
489                                  vprot, handle);
490
491     return ret;
492 }
493
494
495 NTSTATUS MyNtMapViewOfSection (HANDLE handle, HANDLE process, PVOID *addr_ptr, ULONG zero_bits,
496                                SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr,
497                                SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect)
498 {
499   NTSTATUS res;
500   mem_size_t full_size;
501   ACCESS_MASK access;
502   SIZE_T size, mask = get_mask( zero_bits );
503   unsigned int map_vprot;
504   //  unsigned int vprot;
505   void *base;
506   //  struct file_view *view;
507   DWORD header_size;
508   HANDLE fhandle;
509   HANDLE mhandle;
510   LARGE_INTEGER offset;
511
512   offset.QuadPart = offset_ptr ? offset_ptr->QuadPart : 0;
513
514   TRACE("handle=%p process=%p addr=%p off=%x%08x size=%lx access=%x\n",
515         handle, process, *addr_ptr, offset.u.HighPart, offset.u.LowPart, *size_ptr, protect );
516
517   /* Check parameters */
518
519   if ((offset.u.LowPart & mask) || (*addr_ptr && ((UINT_PTR)*addr_ptr & mask)))
520     return STATUS_INVALID_PARAMETER;
521
522   switch(protect)
523     {
524     case PAGE_NOACCESS:
525       access = 0;
526       break;
527     case PAGE_READWRITE:
528     case PAGE_EXECUTE_READWRITE:
529       access = SECTION_MAP_WRITE;
530       break;
531     case PAGE_READONLY:
532     case PAGE_WRITECOPY:
533     case PAGE_EXECUTE:
534     case PAGE_EXECUTE_READ:
535     case PAGE_EXECUTE_WRITECOPY:
536       access = SECTION_MAP_READ;
537       break;
538     default:
539       return STATUS_INVALID_PARAMETER;
540     }
541
542   res = SERVER_get_mapping_info (handle, access, &map_vprot, &base, &full_size, &header_size, &fhandle, &mhandle);
543   if (res) return res;
544
545   if (map_vprot & VPROT_IMAGE)
546     {
547       size = full_size;
548       if (size != full_size)  /* truncated */
549         {
550           TRACE( "Modules larger than 4Gb not supported\n");
551           res = STATUS_INVALID_PARAMETER;
552           goto done;
553         }
554       res = map_image( handle, fhandle, mhandle, base, size, mask, header_size,
555                        -1, INVALID_HANDLE_VALUE, addr_ptr );
556       if (res >= 0) *size_ptr = size;
557       return res;
558     }
559
560   assert (!"Not supported");
561 #if 0
562   res = STATUS_INVALID_PARAMETER;
563   if (offset.QuadPart >= full_size) goto done;
564   if (*size_ptr)
565     {
566       if (*size_ptr > full_size - offset.QuadPart) goto done;
567       size = ROUND_SIZE( offset.u.LowPart, *size_ptr );
568       if (size < *size_ptr) goto done;  /* wrap-around */
569     }
570   else
571     {
572       size = full_size - offset.QuadPart;
573       if (size != full_size - offset.QuadPart)  /* truncated */
574         {
575           WARN( "Files larger than 4Gb (%s) not supported on this platform\n",
576                 wine_dbgstr_longlong(full_size) );
577           goto done;
578         }
579     }
580
581   /* Reserve a properly aligned area */
582
583   server_enter_uninterrupted_section( &csVirtual, &sigset );
584
585   get_vprot_flags( protect, &vprot );
586   vprot |= (map_vprot & VPROT_COMMITTED);
587   res = map_view( &view, *addr_ptr, size, mask, FALSE, vprot );
588   if (res)
589     {
590       server_leave_uninterrupted_section( &csVirtual, &sigset );
591       goto done;
592     }
593
594   /* Map the file */
595
596   TRACE("handle=%p size=%lx offset=%x%08x\n",
597         handle, size, offset.u.HighPart, offset.u.LowPart );
598
599   res = map_file_into_view( view, unix_handle, 0, size, offset.QuadPart, vprot, !dup_mapping );
600   if (res == STATUS_SUCCESS)
601     {
602       *addr_ptr = view->base;
603       *size_ptr = size;
604       view->mapping = dup_mapping;
605       dup_mapping = 0;  /* don't close it */
606     }
607   else
608     {
609       ERR( "map_file_into_view %p %lx %x%08x failed\n",
610            view->base, size, offset.u.HighPart, offset.u.LowPart );
611       delete_view( view );
612     }
613   
614   server_leave_uninterrupted_section( &csVirtual, &sigset );
615 #endif
616
617  done:
618   return res;
619
620   //  *addr_ptr = MapViewOfFile (handle, 
621   //                         protect == PAGE_READONLY ? FILE_MAP_READ : FILE_MAP_WRITE,
622   //                         offset_ptr ? offset_ptr->HighPart : 0,
623   //                         offset_ptr ? offset_ptr->LowPart : 0,
624   //                         size_ptr ? size_ptr->LowPart : 0);
625   //  if (*addr_ptr == NULL)
626   //    return GetLastError ();
627   //
628   //  return STATUS_SUCCESS;
629 }