1 /* From wine1.2-1.1.42/dlls/ntdll/virtual.c */
\r
4 * Win32 virtual memory functions
\r
6 * Copyright 1997, 2002 Alexandre Julliard
\r
7 * Copyright 2010 g10 Code GmbH
\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
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
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
25 #include <windows.h>
\r
31 typedef struct file_view
\r
33 void *base; /* Base address */
\r
34 size_t size; /* Size in bytes */
\r
35 HANDLE mapping; /* Handle to the file mapping */
\r
36 unsigned int protect; /* Protection for all pages at allocation time */
\r
40 # define page_mask 0xfff
\r
41 # define page_shift 12
\r
42 # define page_size 0x1000
\r
45 #define ROUND_SIZE(addr,size) \
\r
46 (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
\r
49 static size_t get_mask( ULONG zero_bits )
\r
51 if (!zero_bits) return 0xffff; /* allocations are aligned to 64K by default */
\r
52 if (zero_bits < page_shift) zero_bits = page_shift;
\r
53 return (1 << zero_bits) - 1;
\r
57 static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot )
\r
59 switch(protect & 0xff)
\r
62 *vprot = VPROT_READ;
\r
64 case PAGE_READWRITE:
\r
65 *vprot = VPROT_READ | VPROT_WRITE;
\r
67 case PAGE_WRITECOPY:
\r
68 *vprot = VPROT_READ | VPROT_WRITECOPY;
\r
71 *vprot = VPROT_EXEC;
\r
73 case PAGE_EXECUTE_READ:
\r
74 *vprot = VPROT_EXEC | VPROT_READ;
\r
76 case PAGE_EXECUTE_READWRITE:
\r
77 *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITE;
\r
79 case PAGE_EXECUTE_WRITECOPY:
\r
80 *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITECOPY;
\r
86 return STATUS_INVALID_PARAMETER;
\r
88 if (protect & PAGE_GUARD) *vprot |= VPROT_GUARD;
\r
89 if (protect & PAGE_NOCACHE) *vprot |= VPROT_NOCACHE;
\r
90 return STATUS_SUCCESS;
\r
94 static void delete_view( struct file_view *view ) /* [in] View */
\r
96 VirtualFree (view->base, view->size, MEM_RELEASE);
\r
97 // if (view->mapping) NtClose( view->mapping );
\r
102 static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, size_t mask,
\r
103 int top_down, unsigned int vprot )
\r
105 int prot = get_prot_flags (vprot);
\r
106 struct file_view *view;
\r
110 view = malloc (sizeof (struct file_view));
\r
112 return STATUS_NO_MEMORY;
\r
114 // FIXME: Only with NOACCESS does Windows CE prefer the high mem area
\r
115 // even for smaller areas.
\r
116 ptr = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS /*prot*/);
\r
120 return GetLastError();
\r
122 /* We have to zero map the whole thing. */
\r
123 new_ptr = VirtualAlloc (ptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
\r
124 if (new_ptr != ptr)
\r
127 return GetLastError();
\r
131 view->protect = vprot;
\r
134 return STATUS_SUCCESS;
\r
138 static NTSTATUS map_file_into_view( struct file_view *view, HANDLE fhandle, size_t start, size_t size,
\r
139 off_t offset, unsigned int vprot, BOOL removable )
\r
142 int prot = get_prot_flags (vprot);
\r
143 BOOL shared_write = (vprot & VPROT_WRITE) != 0;
\r
145 assert( start < view->size );
\r
146 assert( start + size <= view->size );
\r
149 /* only try mmap if media is not removable (or if we require write access) */
\r
150 if (!removable || shared_write)
\r
152 int flags = MAP_FIXED | (shared_write ? MAP_SHARED : MAP_PRIVATE);
\r
154 if (mmap( (char *)view->base + start, size, prot, flags, fd, offset ) != (void *)-1)
\r
157 /* mmap() failed; if this is because the file offset is not */
\r
158 /* page-aligned (EINVAL), or because the underlying filesystem */
\r
159 /* does not support mmap() (ENOEXEC,ENODEV), we do it by hand. */
\r
160 if ((errno != ENOEXEC) && (errno != EINVAL) && (errno != ENODEV)) return FILE_GetNtStatus();
\r
161 if (shared_write) /* we cannot fake shared write mappings */
\r
163 if (errno == EINVAL) return STATUS_INVALID_PARAMETER;
\r
164 ERR( "shared writable mmap not supported, broken filesystem?\n" );
\r
165 return STATUS_NOT_SUPPORTED;
\r
171 /* Already done by map_view. */
\r
172 /* Reserve the memory with an anonymous mmap */
\r
173 ptr = VirtualAlloc ((char *)view->base + start, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
\r
174 if (ptr == (void *)-1) return GetLastError();
\r
176 ptr = (char *)view->base + start;
\r
179 /* Now read in the file */
\r
180 pread( fhandle, ptr, size, offset );
\r
181 // if (prot != (PROT_READ|PROT_WRITE)) mprotect( ptr, size, prot ); /* Set the right protection */
\r
183 // memset( view->prot + (start >> page_shift), vprot, ROUND_SIZE(start,size) >> page_shift );
\r
184 return STATUS_SUCCESS;
\r
188 static NTSTATUS map_image (HANDLE hmapping, HANDLE hfile, HANDLE hmap, char *base, SIZE_T total_size, SIZE_T mask,
\r
189 SIZE_T header_size, int shared_fd, HANDLE dup_mapping, PVOID *addr_ptr)
\r
191 IMAGE_DOS_HEADER *dos;
\r
192 IMAGE_NT_HEADERS *nt;
\r
193 IMAGE_SECTION_HEADER *sec;
\r
194 IMAGE_DATA_DIRECTORY *imports;
\r
195 NTSTATUS status = STATUS_CONFLICTING_ADDRESSES;
\r
199 struct file_view *view = NULL;
\r
200 char *ptr, *header_end;
\r
204 /* zero-map the whole range */
\r
206 if (base >= (char *)0x110000) /* make sure the DOS area remains free */
\r
207 status = map_view( &view, base, total_size, mask, FALSE,
\r
208 VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY | VPROT_IMAGE );
\r
210 if (status != STATUS_SUCCESS)
\r
211 status = map_view( &view, NULL, total_size, mask, FALSE,
\r
212 VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY | VPROT_IMAGE );
\r
214 if (status != STATUS_SUCCESS) goto error;
\r
217 TRACE( "mapped PE file at %p-%p\n", ptr, ptr + total_size );
\r
219 /* map the header */
\r
221 fsize = GetFileSize (hfile, NULL);
\r
222 if (fsize == INVALID_FILE_SIZE)
\r
224 status = GetLastError();
\r
227 status = STATUS_INVALID_IMAGE_FORMAT; /* generic error */
\r
228 header_size = min( header_size, fsize );
\r
229 if (map_file_into_view( view, hfile, 0, header_size, 0, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
\r
230 !dup_mapping ) != STATUS_SUCCESS) goto error;
\r
231 dos = (IMAGE_DOS_HEADER *)ptr;
\r
232 nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);
\r
233 header_end = ptr + ROUND_SIZE( 0, header_size );
\r
234 memset( ptr + header_size, 0, header_end - (ptr + header_size) );
\r
235 if ((char *)(nt + 1) > header_end) goto error;
\r
236 sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
\r
237 if ((char *)(sec + nt->FileHeader.NumberOfSections) > header_end) goto error;
\r
239 imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;
\r
240 if (!imports->Size || !imports->VirtualAddress) imports = NULL;
\r
242 /* check the architecture */
\r
244 if (nt->FileHeader.Machine != IMAGE_FILE_MACHINE_ARM
\r
245 && nt->FileHeader.Machine != IMAGE_FILE_MACHINE_THUMB)
\r
247 TRACE("Trying to load PE image for unsupported architecture (");
\r
248 switch (nt->FileHeader.Machine)
\r
250 case IMAGE_FILE_MACHINE_UNKNOWN: TRACE("Unknown"); break;
\r
251 case IMAGE_FILE_MACHINE_I386: TRACE("I386"); break;
\r
252 case IMAGE_FILE_MACHINE_R3000: TRACE("R3000"); break;
\r
253 case IMAGE_FILE_MACHINE_R4000: TRACE("R4000"); break;
\r
254 case IMAGE_FILE_MACHINE_R10000: TRACE("R10000"); break;
\r
255 case IMAGE_FILE_MACHINE_ALPHA: TRACE("Alpha"); break;
\r
256 case IMAGE_FILE_MACHINE_POWERPC: TRACE("PowerPC"); break;
\r
257 case IMAGE_FILE_MACHINE_IA64: TRACE("IA-64"); break;
\r
258 case IMAGE_FILE_MACHINE_ALPHA64: TRACE("Alpha-64"); break;
\r
259 case IMAGE_FILE_MACHINE_ARM: TRACE("ARM"); break;
\r
260 default: TRACE("Unknown-%04x", nt->FileHeader.Machine); break;
\r
266 /* check for non page-aligned binary */
\r
268 if (nt->OptionalHeader.SectionAlignment <= page_mask)
\r
270 /* unaligned sections, this happens for native subsystem binaries */
\r
271 /* in that case Windows simply maps in the whole file */
\r
273 if (map_file_into_view( view, hfile, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ,
\r
274 !dup_mapping ) != STATUS_SUCCESS) goto error;
\r
276 /* check that all sections are loaded at the right offset */
\r
277 if (nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) goto error;
\r
278 for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
\r
280 if (sec[i].VirtualAddress != sec[i].PointerToRawData)
\r
281 goto error; /* Windows refuses to load in that case too */
\r
284 /* set the image protections */
\r
285 VIRTUAL_SetProt( view, ptr, total_size,
\r
286 VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY | VPROT_EXEC );
\r
290 /* no relocations are performed on non page-aligned binaries */
\r
298 /* map all the sections */
\r
300 for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
\r
302 static const SIZE_T sector_align = 0x1ff;
\r
303 SIZE_T map_size, file_start, file_size, end;
\r
305 if (!sec->Misc.VirtualSize)
\r
306 map_size = ROUND_SIZE( 0, sec->SizeOfRawData );
\r
308 map_size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
\r
310 /* file positions are rounded to sector boundaries regardless of OptionalHeader.FileAlignment */
\r
311 file_start = sec->PointerToRawData & ~sector_align;
\r
312 file_size = (sec->SizeOfRawData + (sec->PointerToRawData & sector_align) + sector_align) & ~sector_align;
\r
313 if (file_size > map_size) file_size = map_size;
\r
315 /* a few sanity checks */
\r
316 end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size );
\r
317 if (sec->VirtualAddress > total_size || end > total_size || end < sec->VirtualAddress)
\r
319 ERR ( "Section %.8s too large (%x+%lx/%lx)\n",
\r
320 sec->Name, sec->VirtualAddress, map_size, total_size );
\r
324 if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&
\r
325 (sec->Characteristics & IMAGE_SCN_MEM_WRITE))
\r
327 TRACE( "mapping shared section %.8s at %p off %x (%x) size %lx (%lx) flags %x\n",
\r
328 sec->Name, ptr + sec->VirtualAddress,
\r
329 sec->PointerToRawData, (int)pos, file_size, map_size,
\r
330 sec->Characteristics );
\r
331 if (map_file_into_view( view, hfile, sec->VirtualAddress, map_size, pos,
\r
332 VPROT_COMMITTED | VPROT_READ | VPROT_WRITE,
\r
333 FALSE ) != STATUS_SUCCESS)
\r
335 ERR ( "Could not map shared section %.8s\n", sec->Name );
\r
339 /* check if the import directory falls inside this section */
\r
340 if (imports && imports->VirtualAddress >= sec->VirtualAddress &&
\r
341 imports->VirtualAddress < sec->VirtualAddress + map_size)
\r
343 UINT_PTR base = imports->VirtualAddress & ~page_mask;
\r
344 UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );
\r
345 if (end > sec->VirtualAddress + map_size) end = sec->VirtualAddress + map_size;
\r
347 map_file_into_view( view, hfile, base, end - base,
\r
348 pos + (base - sec->VirtualAddress),
\r
349 VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
\r
356 ERR( "mapping section %.8s at %p off %x size %x virt %x flags %x\n",
\r
357 sec->Name, ptr + sec->VirtualAddress,
\r
358 sec->PointerToRawData, sec->SizeOfRawData,
\r
359 sec->Misc.VirtualSize, sec->Characteristics );
\r
361 if (!sec->PointerToRawData || !file_size) continue;
\r
363 /* Note: if the section is not aligned properly map_file_into_view will magically
\r
364 * fall back to read(), so we don't need to check anything here.
\r
366 end = file_start + file_size;
\r
367 if (sec->PointerToRawData >= fsize ||
\r
368 end > ((fsize + sector_align) & ~sector_align) ||
\r
369 end < file_start ||
\r
370 map_file_into_view( view, hfile, sec->VirtualAddress, file_size, file_start,
\r
371 VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
\r
372 !dup_mapping ) != STATUS_SUCCESS)
\r
374 ERR( "Could not map section %.8s, file probably truncated\n", sec->Name );
\r
378 if (file_size & page_mask)
\r
380 end = ROUND_SIZE( 0, file_size );
\r
381 if (end > map_size) end = map_size;
\r
382 TRACE("clearing %p - %p\n",
\r
383 ptr + sec->VirtualAddress + file_size,
\r
384 ptr + sec->VirtualAddress + end );
\r
385 memset( ptr + sec->VirtualAddress + file_size, 0, end - file_size );
\r
390 /* perform base relocation, if necessary */
\r
394 // ((nt->FileHeader.Characteristics & IMAGE_FILE_DLL) ||
\r
395 // !NtCurrentTeb()->Peb->ImageBaseAddress) )
\r
397 IMAGE_BASE_RELOCATION *rel, *end;
\r
398 const IMAGE_DATA_DIRECTORY *relocs;
\r
400 if (nt->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
\r
402 TRACE( "Need to relocate module from %p to %p, but there are no relocation records\n",
\r
404 status = STATUS_CONFLICTING_ADDRESSES;
\r
408 TRACE( "relocating from %p-%p to %p-%p\n",
\r
409 base, base + total_size, ptr, ptr + total_size );
\r
411 relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
\r
412 rel = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress);
\r
413 end = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress + relocs->Size);
\r
414 delta = ptr - base;
\r
416 while (rel < end - 1 && rel->SizeOfBlock)
\r
418 if (rel->VirtualAddress >= total_size)
\r
420 TRACE( "invalid address %p in relocation %p\n", ptr + rel->VirtualAddress, rel );
\r
421 status = STATUS_ACCESS_VIOLATION;
\r
424 rel = MyLdrProcessRelocationBlock( ptr + rel->VirtualAddress,
\r
425 (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
\r
426 (USHORT *)(rel + 1), delta );
\r
427 if (!rel) goto error;
\r
431 /* set the image protections */
\r
432 VIRTUAL_SetProt( view, ptr, ROUND_SIZE( 0, header_size ), VPROT_COMMITTED | VPROT_READ );
\r
434 sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
\r
435 for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
\r
438 BYTE vprot = VPROT_COMMITTED;
\r
440 if (sec->Misc.VirtualSize)
\r
441 size = ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
\r
443 size = ROUND_SIZE( sec->VirtualAddress, sec->SizeOfRawData );
\r
445 if (sec->Characteristics & IMAGE_SCN_MEM_READ) vprot |= VPROT_READ;
\r
446 if (sec->Characteristics & IMAGE_SCN_MEM_WRITE) vprot |= VPROT_READ|VPROT_WRITECOPY;
\r
447 if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;
\r
449 /* Dumb game crack lets the AOEP point into a data section. Adjust. */
\r
450 if ((nt->OptionalHeader.AddressOfEntryPoint >= sec->VirtualAddress) &&
\r
451 (nt->OptionalHeader.AddressOfEntryPoint < sec->VirtualAddress + size))
\r
452 vprot |= VPROT_EXEC;
\r
454 VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
\r
460 #ifdef VALGRIND_LOAD_PDB_DEBUGINFO
\r
461 VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta);
\r
463 if (ptr != base) return STATUS_IMAGE_NOT_AT_BASE;
\r
464 return STATUS_SUCCESS;
\r
467 if (view) delete_view( view );
\r
472 NTSTATUS MyNtCreateSection (HANDLE *handle, ACCESS_MASK access,
\r
473 /* const OBJECT_ATTRIBUTES *attr */ void *attr,
\r
474 const LARGE_INTEGER *size, ULONG protect,
\r
475 ULONG sec_flags, HANDLE file)
\r
478 unsigned int vprot;
\r
480 if ((ret = get_vprot_flags( protect, &vprot ))) return ret;
\r
482 assert (attr == NULL);
\r
484 if (!(sec_flags & SEC_RESERVE)) vprot |= VPROT_COMMITTED;
\r
485 if (sec_flags & SEC_NOCACHE) vprot |= VPROT_NOCACHE;
\r
486 if (sec_flags & SEC_IMAGE) vprot |= VPROT_IMAGE;
\r
488 ret = SERVER_create_mapping (access, attr, file, size ? size->QuadPart : 0,
\r
495 NTSTATUS MyNtMapViewOfSection (HANDLE handle, HANDLE process, PVOID *addr_ptr, ULONG zero_bits,
\r
496 SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr,
\r
497 SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect)
\r
500 mem_size_t full_size;
\r
501 ACCESS_MASK access;
\r
502 SIZE_T size, mask = get_mask( zero_bits );
\r
503 unsigned int map_vprot;
\r
504 // unsigned int vprot;
\r
506 // struct file_view *view;
\r
510 LARGE_INTEGER offset;
\r
512 offset.QuadPart = offset_ptr ? offset_ptr->QuadPart : 0;
\r
514 TRACE("handle=%p process=%p addr=%p off=%x%08x size=%lx access=%x\n",
\r
515 handle, process, *addr_ptr, offset.u.HighPart, offset.u.LowPart, *size_ptr, protect );
\r
517 /* Check parameters */
\r
519 if ((offset.u.LowPart & mask) || (*addr_ptr && ((UINT_PTR)*addr_ptr & mask)))
\r
520 return STATUS_INVALID_PARAMETER;
\r
524 case PAGE_NOACCESS:
\r
527 case PAGE_READWRITE:
\r
528 case PAGE_EXECUTE_READWRITE:
\r
529 access = SECTION_MAP_WRITE;
\r
531 case PAGE_READONLY:
\r
532 case PAGE_WRITECOPY:
\r
534 case PAGE_EXECUTE_READ:
\r
535 case PAGE_EXECUTE_WRITECOPY:
\r
536 access = SECTION_MAP_READ;
\r
539 return STATUS_INVALID_PARAMETER;
\r
542 res = SERVER_get_mapping_info (handle, access, &map_vprot, &base, &full_size, &header_size, &fhandle, &mhandle);
\r
543 if (res) return res;
\r
545 if (map_vprot & VPROT_IMAGE)
\r
548 if (size != full_size) /* truncated */
\r
550 TRACE( "Modules larger than 4Gb not supported\n");
\r
551 res = STATUS_INVALID_PARAMETER;
\r
554 res = map_image( handle, fhandle, mhandle, base, size, mask, header_size,
\r
555 -1, INVALID_HANDLE_VALUE, addr_ptr );
\r
556 if (res >= 0) *size_ptr = size;
\r
560 assert (!"Not supported");
\r
562 res = STATUS_INVALID_PARAMETER;
\r
563 if (offset.QuadPart >= full_size) goto done;
\r
566 if (*size_ptr > full_size - offset.QuadPart) goto done;
\r
567 size = ROUND_SIZE( offset.u.LowPart, *size_ptr );
\r
568 if (size < *size_ptr) goto done; /* wrap-around */
\r
572 size = full_size - offset.QuadPart;
\r
573 if (size != full_size - offset.QuadPart) /* truncated */
\r
575 WARN( "Files larger than 4Gb (%s) not supported on this platform\n",
\r
576 wine_dbgstr_longlong(full_size) );
\r
581 /* Reserve a properly aligned area */
\r
583 server_enter_uninterrupted_section( &csVirtual, &sigset );
\r
585 get_vprot_flags( protect, &vprot );
\r
586 vprot |= (map_vprot & VPROT_COMMITTED);
\r
587 res = map_view( &view, *addr_ptr, size, mask, FALSE, vprot );
\r
590 server_leave_uninterrupted_section( &csVirtual, &sigset );
\r
596 TRACE("handle=%p size=%lx offset=%x%08x\n",
\r
597 handle, size, offset.u.HighPart, offset.u.LowPart );
\r
599 res = map_file_into_view( view, unix_handle, 0, size, offset.QuadPart, vprot, !dup_mapping );
\r
600 if (res == STATUS_SUCCESS)
\r
602 *addr_ptr = view->base;
\r
604 view->mapping = dup_mapping;
\r
605 dup_mapping = 0; /* don't close it */
\r
609 ERR( "map_file_into_view %p %lx %x%08x failed\n",
\r
610 view->base, size, offset.u.HighPart, offset.u.LowPart );
\r
611 delete_view( view );
\r
614 server_leave_uninterrupted_section( &csVirtual, &sigset );
\r
620 // *addr_ptr = MapViewOfFile (handle,
\r
621 // protect == PAGE_READONLY ? FILE_MAP_READ : FILE_MAP_WRITE,
\r
622 // offset_ptr ? offset_ptr->HighPart : 0,
\r
623 // offset_ptr ? offset_ptr->LowPart : 0,
\r
624 // size_ptr ? size_ptr->LowPart : 0);
\r
625 // if (*addr_ptr == NULL)
\r
626 // return GetLastError ();
\r
628 // return STATUS_SUCCESS;
\r