Release 970305
[wine/multimedia.git] / memory / virtual.c
blob0cc397a4f3ed0c6e50baa1284e2f3ef8249ebe91
1 /*
2 * Win32 virtual memory functions
4 * Copyright 1997 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/mman.h>
14 #include "winbase.h"
15 #include "winerror.h"
16 #include "file.h"
17 #include "heap.h"
18 #include "process.h"
19 #include "xmalloc.h"
20 #include "stddebug.h"
21 #include "debug.h"
23 /* File mapping */
24 typedef struct
26 K32OBJ header;
27 DWORD size_high;
28 DWORD size_low;
29 FILE_OBJECT *file;
30 BYTE protect;
31 } FILE_MAPPING;
33 /* File view */
34 typedef struct _FV
36 struct _FV *next; /* Next view */
37 struct _FV *prev; /* Prev view */
38 UINT32 base; /* Base address */
39 UINT32 size; /* Size in bytes */
40 UINT32 flags; /* Allocation flags */
41 FILE_MAPPING *mapping; /* File mapping */
42 BYTE protect; /* Protection for all pages at allocation time */
43 BYTE prot[1]; /* Protection byte for each page */
44 } FILE_VIEW;
46 /* Per-page protection byte values */
47 #define VPROT_READ 0x01
48 #define VPROT_WRITE 0x02
49 #define VPROT_EXEC 0x04
50 #define VPROT_WRITECOPY 0x08
51 #define VPROT_GUARD 0x10
52 #define VPROT_NOCACHE 0x20
53 #define VPROT_COMMITTED 0x40
55 /* Per-view flags */
56 #define VFLAG_SYSTEM 0x01
58 /* Conversion from VPROT_* to Win32 flags */
59 static const BYTE VIRTUAL_Win32Flags[16] =
61 PAGE_NOACCESS, /* 0 */
62 PAGE_READONLY, /* READ */
63 PAGE_READWRITE, /* WRITE */
64 PAGE_READWRITE, /* READ | WRITE */
65 PAGE_EXECUTE, /* EXEC */
66 PAGE_EXECUTE_READ, /* READ | EXEC */
67 PAGE_EXECUTE_READWRITE, /* WRITE | EXEC */
68 PAGE_EXECUTE_READWRITE, /* READ | WRITE | EXEC */
69 PAGE_WRITECOPY, /* WRITECOPY */
70 PAGE_WRITECOPY, /* READ | WRITECOPY */
71 PAGE_WRITECOPY, /* WRITE | WRITECOPY */
72 PAGE_WRITECOPY, /* READ | WRITE | WRITECOPY */
73 PAGE_EXECUTE_WRITECOPY, /* EXEC | WRITECOPY */
74 PAGE_EXECUTE_WRITECOPY, /* READ | EXEC | WRITECOPY */
75 PAGE_EXECUTE_WRITECOPY, /* WRITE | EXEC | WRITECOPY */
76 PAGE_EXECUTE_WRITECOPY /* READ | WRITE | EXEC | WRITECOPY */
80 static FILE_VIEW *VIRTUAL_FirstView;
82 static UINT32 page_shift;
83 static UINT32 page_mask;
85 #define ROUND_ADDR(addr) \
86 ((UINT32)(addr) & ~page_mask)
88 #define ROUND_SIZE(addr,size) \
89 (((UINT32)(size) + ((UINT32)(addr) & page_mask) + page_mask) & ~page_mask)
92 /***********************************************************************
93 * VIRTUAL_DestroyMapping
95 * Destroy a FILE_MAPPING object.
97 void VIRTUAL_DestroyMapping( K32OBJ *ptr )
99 FILE_MAPPING *mapping = (FILE_MAPPING *)ptr;
100 assert( ptr->type == K32OBJ_MEM_MAPPED_FILE );
102 if (mapping->file) K32OBJ_DecCount( &mapping->file->header );
103 ptr->type = K32OBJ_UNKNOWN;
104 HeapFree( SystemHeap, 0, mapping );
108 /***********************************************************************
109 * VIRTUAL_GetProtStr
111 static const char *VIRTUAL_GetProtStr( BYTE prot )
113 static char buffer[6];
114 buffer[0] = (prot & VPROT_COMMITTED) ? 'c' : '-';
115 buffer[1] = (prot & VPROT_GUARD) ? 'g' : '-';
116 buffer[2] = (prot & VPROT_READ) ? 'r' : '-';
117 buffer[3] = (prot & VPROT_WRITE) ?
118 ((prot & VPROT_WRITECOPY) ? 'w' : 'W') : '-';
119 buffer[4] = (prot & VPROT_EXEC) ? 'x' : '-';
120 buffer[5] = 0;
121 return buffer;
125 /***********************************************************************
126 * VIRTUAL_DumpView
128 static void VIRTUAL_DumpView( FILE_VIEW *view )
130 UINT32 i, count;
131 UINT32 addr = view->base;
132 BYTE prot = view->prot[0];
134 dprintf_virtual( stddeb, "View: %08x - %08x%s\n",
135 view->base, view->base + view->size - 1,
136 (view->flags & VFLAG_SYSTEM) ? " (system)" : "" );
138 for (count = i = 1; i < view->size >> page_shift; i++, count++)
140 if (view->prot[i] == prot) continue;
141 dprintf_virtual( stddeb, " %08x - %08x %s\n",
142 addr, addr + (count << page_shift) - 1,
143 VIRTUAL_GetProtStr(prot) );
144 addr += (count << page_shift);
145 prot = view->prot[i];
146 count = 0;
148 if (count)
149 dprintf_virtual( stddeb, " %08x - %08x %s\n",
150 addr, addr + (count << page_shift) - 1,
151 VIRTUAL_GetProtStr(prot) );
155 /***********************************************************************
156 * VIRTUAL_Dump
158 void VIRTUAL_Dump(void)
160 FILE_VIEW *view = VIRTUAL_FirstView;
161 dprintf_virtual( stddeb, "\nDump of all virtual memory views:\n\n" );
162 while (view)
164 VIRTUAL_DumpView( view );
165 view = view->next;
170 /***********************************************************************
171 * VIRTUAL_FindView
173 * Find the view containing a given address.
175 static FILE_VIEW *VIRTUAL_FindView( UINT32 addr )
177 FILE_VIEW *view = VIRTUAL_FirstView;
178 while (view)
180 if (view->base > addr) return NULL;
181 if (view->base + view->size > addr) return view;
182 view = view->next;
184 return NULL;
188 /***********************************************************************
189 * VIRTUAL_CreateView
191 * Create a new view and add it in the linked list.
193 static FILE_VIEW *VIRTUAL_CreateView( UINT32 base, UINT32 size,
194 UINT32 flags, BYTE vprot )
196 FILE_VIEW *view, *prev;
198 /* Create the view structure */
200 size >>= page_shift;
201 view = (FILE_VIEW *)xmalloc( sizeof(*view) + size - 1 );
202 view->base = base;
203 view->size = size << page_shift;
204 view->flags = flags;
205 view->protect = vprot;
206 memset( view->prot, vprot, size );
208 /* Insert it in the linked list */
210 if (!VIRTUAL_FirstView || (VIRTUAL_FirstView->base > base))
212 view->next = VIRTUAL_FirstView;
213 view->prev = NULL;
214 if (view->next) view->next->prev = view;
215 VIRTUAL_FirstView = view;
217 else
219 prev = VIRTUAL_FirstView;
220 while (prev->next && (prev->next->base < base)) prev = prev->next;
221 view->next = prev->next;
222 view->prev = prev;
223 if (view->next) view->next->prev = view;
224 prev->next = view;
226 if (debugging_virtual) VIRTUAL_DumpView( view );
227 return view;
231 /***********************************************************************
232 * VIRTUAL_DeleteView
234 * Delete an view.
236 static void VIRTUAL_DeleteView( FILE_VIEW *view )
238 munmap( (void *)view->base, view->size );
239 if (view->next) view->next->prev = view->prev;
240 if (view->prev) view->prev->next = view->next;
241 else VIRTUAL_FirstView = view->next;
242 free( view );
246 /***********************************************************************
247 * VIRTUAL_GetUnixProt
249 * Convert page protections to protection for mmap/mprotect.
251 static int VIRTUAL_GetUnixProt( BYTE vprot )
253 int prot = 0;
254 if ((vprot & VPROT_COMMITTED) && !(vprot & VPROT_GUARD))
256 if (vprot & VPROT_READ) prot |= PROT_READ;
257 if (vprot & VPROT_WRITE) prot |= PROT_WRITE;
258 if (vprot & VPROT_EXEC) prot |= PROT_EXEC;
260 return prot;
264 /***********************************************************************
265 * VIRTUAL_GetWin32Prot
267 * Convert page protections to Win32 flags.
269 static void VIRTUAL_GetWin32Prot( BYTE vprot, DWORD *protect, DWORD *state )
271 *protect = VIRTUAL_Win32Flags[vprot & 0x0f];
272 if (vprot & VPROT_GUARD) *protect |= PAGE_GUARD;
273 if (vprot & VPROT_NOCACHE) *protect |= PAGE_NOCACHE;
275 if (state) *state = (vprot & VPROT_COMMITTED) ? MEM_COMMIT : MEM_RESERVE;
279 /***********************************************************************
280 * VIRTUAL_GetProt
282 * Build page protections from Win32 flags.
284 static BYTE VIRTUAL_GetProt( DWORD protect )
286 BYTE vprot;
288 switch(protect & 0xff)
290 case PAGE_READONLY:
291 vprot = VPROT_READ;
292 break;
293 case PAGE_READWRITE:
294 vprot = VPROT_READ | VPROT_WRITE;
295 break;
296 case PAGE_WRITECOPY:
297 vprot = VPROT_READ | VPROT_WRITE | VPROT_WRITECOPY;
298 break;
299 case PAGE_EXECUTE:
300 vprot = VPROT_EXEC;
301 break;
302 case PAGE_EXECUTE_READ:
303 vprot = VPROT_EXEC | VPROT_READ;
304 break;
305 case PAGE_EXECUTE_READWRITE:
306 vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITE | VPROT_WRITECOPY;
307 break;
308 case PAGE_EXECUTE_WRITECOPY:
309 vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITE;
310 break;
311 case PAGE_NOACCESS:
312 default:
313 vprot = 0;
314 break;
316 if (protect & PAGE_GUARD) vprot |= VPROT_GUARD;
317 if (protect & PAGE_NOCACHE) vprot |= VPROT_NOCACHE;
318 return vprot;
322 /***********************************************************************
323 * VIRTUAL_SetProt
325 * Change the protection of a range of pages.
327 static BOOL32 VIRTUAL_SetProt( FILE_VIEW *view, UINT32 base,
328 UINT32 size, BYTE vprot )
330 dprintf_virtual( stddeb, "VIRTUAL_SetProt: %08x-%08x %s\n",
331 base, base + size - 1, VIRTUAL_GetProtStr( vprot ) );
333 if (mprotect( (void *)base, size, VIRTUAL_GetUnixProt(vprot) ))
334 return FALSE; /* FIXME: last error */
336 memset( view->prot + ((base - view->base) >> page_shift),
337 vprot, size >> page_shift );
338 if (debugging_virtual) VIRTUAL_DumpView( view );
339 return TRUE;
343 /***********************************************************************
344 * VIRTUAL_CheckFlags
346 * Check that all pages in a range have the given flags.
348 static BOOL32 VIRTUAL_CheckFlags( UINT32 base, UINT32 size, BYTE flags )
350 FILE_VIEW *view;
351 UINT32 page;
353 if (!size) return TRUE;
354 if (!(view = VIRTUAL_FindView( base ))) return FALSE;
355 if (view->base + view->size < base + size) return FALSE;
356 page = (base - view->base) >> page_shift;
357 size = ROUND_SIZE( base, size ) >> page_shift;
358 while (size--) if ((view->prot[page++] & flags) != flags) return FALSE;
359 return TRUE;
363 /***********************************************************************
364 * VIRTUAL_Init
366 BOOL32 VIRTUAL_Init(void)
368 SYSTEM_INFO sysinfo;
369 GetSystemInfo( &sysinfo );
371 page_mask = sysinfo.dwPageSize - 1;
372 /* Make sure we have a power of 2 */
373 assert( !(sysinfo.dwPageSize & page_mask) );
374 page_shift = 0;
375 while ((1 << page_shift) != sysinfo.dwPageSize) page_shift++;
377 #ifdef linux
379 FILE *f = fopen( "/proc/self/maps", "r" );
380 if (f)
382 char buffer[80];
383 while (fgets( buffer, sizeof(buffer), f ))
385 int start, end, offset;
386 char r, w, x, p;
387 BYTE vprot = VPROT_COMMITTED;
389 sscanf( buffer, "%x-%x %c%c%c%c %x",
390 &start, &end, &r, &w, &x, &p, &offset );
391 if (r == 'r') vprot |= VPROT_READ;
392 if (w == 'w') vprot |= VPROT_WRITE;
393 if (x == 'x') vprot |= VPROT_EXEC;
394 if (p == 'p') vprot |= VPROT_WRITECOPY;
395 VIRTUAL_CreateView( start, end - start, VFLAG_SYSTEM, vprot );
397 fclose( f );
400 #endif /* linux */
401 return TRUE;
405 /***********************************************************************
406 * VirtualAlloc (KERNEL32.548)
408 LPVOID VirtualAlloc( LPVOID addr, DWORD size, DWORD type, DWORD protect )
410 FILE_VIEW *view;
411 UINT32 base, ptr, view_size;
412 BYTE vprot;
414 dprintf_virtual( stddeb, "VirtualAlloc: %08x %08lx %lx %08lx\n",
415 (UINT32)addr, size, type, protect );
417 /* Round parameters to a page boundary */
419 if (size > 0x7fc00000) /* 2Gb - 4Mb */
421 SetLastError( ERROR_OUTOFMEMORY );
422 return NULL;
424 if (addr)
426 if (type & MEM_RESERVE) /* Round down to 64k boundary */
427 base = ((UINT32)addr + 0xffff) & ~0xffff;
428 else
429 base = ROUND_ADDR( addr );
430 size = (((UINT32)addr + size + page_mask) & ~page_mask) - base;
431 if (base + size < base) /* Disallow wrap-around */
433 SetLastError( ERROR_INVALID_PARAMETER );
434 return NULL;
437 else
439 base = 0;
440 size = (size + page_mask) & ~page_mask;
443 /* Compute the protection flags */
445 if (!(type & (MEM_COMMIT | MEM_RESERVE)) ||
446 (type & ~(MEM_COMMIT | MEM_RESERVE)))
448 SetLastError( ERROR_INVALID_PARAMETER );
449 return NULL;
451 if (type & MEM_COMMIT)
452 vprot = VIRTUAL_GetProt( protect ) | VPROT_COMMITTED;
453 else vprot = 0;
455 /* Reserve the memory */
457 if ((type & MEM_RESERVE) || !base)
459 view_size = size + (base ? 0 : 0x10000);
460 ptr = (UINT32)FILE_mmap( NULL, (LPVOID)base, 0, view_size, 0, 0,
461 VIRTUAL_GetUnixProt( vprot ), MAP_PRIVATE );
462 if (ptr == (UINT32)-1)
464 SetLastError( ERROR_OUTOFMEMORY );
465 return NULL;
467 if (!base)
469 /* Release the extra memory while keeping the range */
470 /* starting on a 64k boundary. */
472 if (ptr & 0xffff0000)
474 munmap( (void *)ptr, 0x10000 - (ptr & 0xffff) );
475 view_size -= (ptr & 0xffff);
476 ptr = (ptr + 0x10000) & 0xffff0000;
478 if (view_size > size)
479 munmap( (void *)(ptr + size), view_size - size );
481 if (!(view = VIRTUAL_CreateView( ptr, size, 0, vprot )))
483 munmap( (void *)ptr, size );
484 return NULL; /* FIXME: last error */
486 if (debugging_virtual) VIRTUAL_DumpView( view );
487 return (LPVOID)ptr;
490 /* Commit the pages */
492 if (!(view = VIRTUAL_FindView( base )) ||
493 (base + size > view->base + view->size))
495 SetLastError( ERROR_INVALID_PARAMETER );
496 return NULL;
499 if (!VIRTUAL_SetProt( view, base, size, vprot )) return NULL;
500 return (LPVOID)base;
504 /***********************************************************************
505 * VirtualFree (KERNEL32.550)
507 BOOL32 VirtualFree( LPVOID addr, DWORD size, DWORD type )
509 FILE_VIEW *view;
510 UINT32 base;
512 dprintf_virtual( stddeb, "VirtualFree: %08x %08lx %lx\n",
513 (UINT32)addr, size, type );
515 /* Fix the parameters */
517 size = ROUND_SIZE( addr, size );
518 base = ROUND_ADDR( addr );
520 if (!(view = VIRTUAL_FindView( base )) ||
521 (base + size > view->base + view->size))
523 SetLastError( ERROR_INVALID_PARAMETER );
524 return FALSE;
527 /* Compute the protection flags */
529 if ((type != MEM_DECOMMIT) && (type != MEM_RELEASE))
531 SetLastError( ERROR_INVALID_PARAMETER );
532 return FALSE;
535 /* Free the pages */
537 if (type == MEM_RELEASE)
539 if (size || (base != view->base))
541 SetLastError( ERROR_INVALID_PARAMETER );
542 return FALSE;
544 VIRTUAL_DeleteView( view );
545 return TRUE;
548 /* Decommit the pages */
550 return VIRTUAL_SetProt( view, base, size, 0 );
554 /***********************************************************************
555 * VirtualLock (KERNEL32.551)
557 BOOL32 VirtualLock( LPVOID addr, DWORD size )
559 return TRUE;
563 /***********************************************************************
564 * VirtualUnlock (KERNEL32.556)
566 BOOL32 VirtualUnlock( LPVOID addr, DWORD size )
568 return TRUE;
572 /***********************************************************************
573 * VirtualProtect (KERNEL32.552)
575 BOOL32 VirtualProtect( LPVOID addr, DWORD size, DWORD new_prot,
576 LPDWORD old_prot )
578 FILE_VIEW *view;
579 UINT32 base, i;
580 BYTE vprot, *p;
582 dprintf_virtual( stddeb, "VirtualProtect: %08x %08lx %08lx\n",
583 (UINT32)addr, size, new_prot );
585 /* Fix the parameters */
587 size = ROUND_SIZE( addr, size );
588 base = ROUND_ADDR( addr );
590 if (!(view = VIRTUAL_FindView( base )) ||
591 (base + size > view->base + view->size))
593 SetLastError( ERROR_INVALID_PARAMETER );
594 return FALSE;
597 /* Make sure all the pages are committed */
599 p = view->prot + ((base - view->base) >> page_shift);
600 for (i = size >> page_shift; i; i--, p++)
602 if (!(*p & VPROT_COMMITTED))
604 SetLastError( ERROR_INVALID_PARAMETER );
605 return FALSE;
609 VIRTUAL_GetWin32Prot( view->prot[0], old_prot, NULL );
610 vprot = VIRTUAL_GetProt( new_prot ) | VPROT_COMMITTED;
611 return VIRTUAL_SetProt( view, base, size, vprot );
615 /***********************************************************************
616 * VirtualProtectEx (KERNEL32.553)
618 BOOL32 VirtualProtectEx( HANDLE32 handle, LPVOID addr, DWORD size,
619 DWORD new_prot, LPDWORD old_prot )
621 BOOL32 ret = FALSE;
623 PDB32 *pdb = (PDB32 *)PROCESS_GetObjPtr( handle, K32OBJ_PROCESS );
624 if (pdb)
626 if (pdb == pCurrentProcess)
627 ret = VirtualProtect( addr, size, new_prot, old_prot );
628 else
629 fprintf(stderr,"Unsupported: VirtualProtectEx on other process\n");
630 K32OBJ_DecCount( &pdb->header );
632 return ret;
636 /***********************************************************************
637 * VirtualQuery (KERNEL32.554)
639 BOOL32 VirtualQuery( LPCVOID addr, LPMEMORY_BASIC_INFORMATION info, DWORD len )
641 FILE_VIEW *view = VIRTUAL_FirstView;
642 UINT32 base = ROUND_ADDR( addr );
643 UINT32 alloc_base = 0;
644 UINT32 size = 0;
646 /* Find the view containing the address */
648 for (;;)
650 if (!view)
652 size = 0xffff0000 - alloc_base;
653 break;
655 if (view->base > base)
657 size = view->base - alloc_base;
658 view = NULL;
659 break;
661 if (view->base + view->size > base)
663 alloc_base = view->base;
664 size = view->size;
665 break;
667 alloc_base = view->base + view->size;
668 view = view->next;
671 /* Fill the info structure */
673 if (!view)
675 info->State = MEM_FREE;
676 info->Protect = 0;
677 info->AllocationProtect = 0;
678 info->Type = 0;
680 else
682 BYTE vprot = view->prot[(base - alloc_base) >> page_shift];
683 VIRTUAL_GetWin32Prot( vprot, &info->Protect, &info->State );
684 for (size = base - alloc_base; size < view->size; size += page_mask+1)
685 if (view->prot[size >> page_shift] != vprot) break;
686 info->AllocationProtect = view->protect;
687 info->Type = MEM_PRIVATE; /* FIXME */
690 info->BaseAddress = (LPVOID)base;
691 info->AllocationBase = (LPVOID)alloc_base;
692 info->RegionSize = size - (base - alloc_base);
693 return TRUE;
697 /***********************************************************************
698 * VirtualQueryEx (KERNEL32.555)
700 BOOL32 VirtualQueryEx( HANDLE32 handle, LPCVOID addr,
701 LPMEMORY_BASIC_INFORMATION info, DWORD len )
703 BOOL32 ret = FALSE;
705 PDB32 *pdb = (PDB32 *)PROCESS_GetObjPtr( handle, K32OBJ_PROCESS );
706 if (pdb)
708 if (pdb == pCurrentProcess)
709 ret = VirtualQuery( addr, info, len );
710 else
711 fprintf(stderr,"Unsupported: VirtualQueryEx on other process\n");
712 K32OBJ_DecCount( &pdb->header );
714 return ret;
718 /***********************************************************************
719 * IsBadReadPtr32 (KERNEL32.354)
721 BOOL32 IsBadReadPtr32( LPCVOID ptr, UINT32 size )
723 return !VIRTUAL_CheckFlags( (UINT32)ptr, size,
724 VPROT_READ | VPROT_COMMITTED );
728 /***********************************************************************
729 * IsBadWritePtr32 (KERNEL32.357)
731 BOOL32 IsBadWritePtr32( LPVOID ptr, UINT32 size )
733 return !VIRTUAL_CheckFlags( (UINT32)ptr, size,
734 VPROT_WRITE | VPROT_COMMITTED );
738 /***********************************************************************
739 * IsBadHugeReadPtr32 (KERNEL32.352)
741 BOOL32 IsBadHugeReadPtr32( LPCVOID ptr, UINT32 size )
743 return IsBadReadPtr32( ptr, size );
747 /***********************************************************************
748 * IsBadHugeWritePtr32 (KERNEL32.353)
750 BOOL32 IsBadHugeWritePtr32( LPVOID ptr, UINT32 size )
752 return IsBadWritePtr32( ptr, size );
756 /***********************************************************************
757 * IsBadCodePtr32 (KERNEL32.351)
759 BOOL32 IsBadCodePtr32( FARPROC32 ptr )
761 return !VIRTUAL_CheckFlags( (UINT32)ptr, 1, VPROT_EXEC | VPROT_COMMITTED );
765 /***********************************************************************
766 * IsBadStringPtr32A (KERNEL32.355)
768 BOOL32 IsBadStringPtr32A( LPCSTR str, UINT32 max )
770 FILE_VIEW *view;
771 UINT32 page, count;
773 if (!max) return FALSE;
774 if (!(view = VIRTUAL_FindView( (UINT32)str ))) return TRUE;
775 page = ((UINT32)str - view->base) >> page_shift;
776 count = page_mask + 1 - ((UINT32)str & page_mask);
778 while (max)
780 if ((view->prot[page] & (VPROT_READ | VPROT_COMMITTED)) !=
781 (VPROT_READ | VPROT_COMMITTED))
782 return TRUE;
783 if (count > max) count = max;
784 max -= count;
785 while (count--) if (!*str++) return FALSE;
786 if (++page >= view->size >> page_shift) return TRUE;
787 count = page_mask + 1;
789 return FALSE;
793 /***********************************************************************
794 * IsBadStringPtr32W (KERNEL32.356)
796 BOOL32 IsBadStringPtr32W( LPCWSTR str, UINT32 max )
798 FILE_VIEW *view;
799 UINT32 page, count;
801 if (!max) return FALSE;
802 if (!(view = VIRTUAL_FindView( (UINT32)str ))) return TRUE;
803 page = ((UINT32)str - view->base) >> page_shift;
804 count = (page_mask + 1 - ((UINT32)str & page_mask)) / sizeof(WCHAR);
806 while (max)
808 if ((view->prot[page] & (VPROT_READ | VPROT_COMMITTED)) !=
809 (VPROT_READ | VPROT_COMMITTED))
810 return TRUE;
811 if (count > max) count = max;
812 max -= count;
813 while (count--) if (!*str++) return FALSE;
814 if (++page >= view->size >> page_shift) return TRUE;
815 count = (page_mask + 1) / sizeof(WCHAR);
817 return FALSE;
821 /***********************************************************************
822 * CreateFileMapping32A (KERNEL32.46)
824 HANDLE32 CreateFileMapping32A( HFILE32 hFile, LPSECURITY_ATTRIBUTES attr,
825 DWORD protect, DWORD size_high, DWORD size_low,
826 LPCSTR name )
828 FILE_MAPPING *mapping = NULL;
829 HANDLE32 handle;
831 K32OBJ *obj = K32OBJ_FindName( name );
832 if (obj)
834 if (obj->type == K32OBJ_MEM_MAPPED_FILE)
836 SetLastError( ERROR_ALREADY_EXISTS );
837 return PROCESS_AllocHandle( obj, 0 );
839 SetLastError( ERROR_DUP_NAME );
840 return 0;
843 printf( "CreateFileMapping32A(%x,%p,%08lx,%08lx%08lx,%s)\n",
844 hFile, attr, protect, size_high, size_low, name );
846 if (hFile == INVALID_HANDLE_VALUE32)
848 if (!size_high && !size_low)
850 SetLastError( ERROR_INVALID_PARAMETER );
851 return 0;
853 obj = NULL;
855 else /* We have a file */
857 BY_HANDLE_FILE_INFORMATION info;
858 if (!(obj = PROCESS_GetObjPtr( hFile, K32OBJ_FILE ))) goto error;
859 if (!GetFileInformationByHandle( hFile, &info )) goto error;
860 if (!size_high && !size_low)
862 size_high = info.nFileSizeHigh;
863 size_low = info.nFileSizeLow;
865 else if ((size_high > info.nFileSizeHigh) ||
866 ((size_high == info.nFileSizeHigh) &&
867 (size_low > info.nFileSizeLow)))
869 /* We have to grow the file */
870 if (SetFilePointer( hFile, size_low, &size_high,
871 FILE_BEGIN ) == 0xffffffff) goto error;
872 if (!SetEndOfFile( hFile )) goto error;
876 if (!(mapping = HeapAlloc( SystemHeap, 0, sizeof(*mapping) ))) goto error;
877 mapping->protect = VIRTUAL_GetProt( protect ) | VPROT_COMMITTED;
878 mapping->size_high = size_high;
879 mapping->size_low = size_low;
880 mapping->file = (FILE_OBJECT *)obj;
882 handle = PROCESS_AllocHandle( &mapping->header, 0 );
883 if (handle != INVALID_HANDLE_VALUE32) return handle;
885 error:
886 if (obj) K32OBJ_DecCount( obj );
887 if (mapping) HeapFree( SystemHeap, 0, mapping );
888 return 0;
892 /***********************************************************************
893 * CreateFileMapping32W (KERNEL32.47)
895 HANDLE32 CreateFileMapping32W( HFILE32 hFile, LPSECURITY_ATTRIBUTES attr,
896 DWORD protect, DWORD size_high, DWORD size_low,
897 LPCWSTR name )
899 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
900 HANDLE32 ret = CreateFileMapping32A( hFile, attr, protect,
901 size_high, size_low, nameA );
902 HeapFree( GetProcessHeap(), 0, nameA );
903 return ret;
907 /***********************************************************************
908 * OpenFileMapping32A (KERNEL32.397)
910 HANDLE32 OpenFileMapping32A( DWORD access, BOOL32 inherit, LPCSTR name )
912 K32OBJ *obj = K32OBJ_FindNameType( name, K32OBJ_MEM_MAPPED_FILE );
913 if (!obj) return 0;
914 return PROCESS_AllocHandle( obj, 0 );
918 /***********************************************************************
919 * OpenFileMapping32W (KERNEL32.398)
921 HANDLE32 OpenFileMapping32W( DWORD access, BOOL32 inherit, LPCWSTR name )
923 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
924 HANDLE32 ret = OpenFileMapping32A( access, inherit, nameA );
925 HeapFree( GetProcessHeap(), 0, nameA );
926 return ret;
930 /***********************************************************************
931 * MapViewOfFile (KERNEL32.385)
933 LPVOID MapViewOfFile( HANDLE32 mapping, DWORD access, DWORD offset_high,
934 DWORD offset_low, DWORD count )
936 return MapViewOfFileEx( mapping, access, offset_high,
937 offset_low, count, NULL );
941 /***********************************************************************
942 * MapViewOfFileEx (KERNEL32.386)
944 LPVOID MapViewOfFileEx( HANDLE32 handle, DWORD access, DWORD offset_high,
945 DWORD offset_low, DWORD count, LPVOID addr )
947 FILE_MAPPING *mapping;
948 LPVOID ret;
950 if (!(mapping = (FILE_MAPPING *)PROCESS_GetObjPtr( handle,
951 K32OBJ_MEM_MAPPED_FILE )))
952 return NULL;
954 ret = FILE_mmap(mapping->file, addr, mapping->size_high, mapping->size_low,
955 offset_high, offset_low, mapping->protect, MAP_PRIVATE );
957 K32OBJ_DecCount( &mapping->header );
958 return ret;
962 /***********************************************************************
963 * UnmapViewOfFile (KERNEL32.540)
965 BOOL32 UnmapViewOfFile( LPVOID addr )
967 FILE_VIEW *view;
968 UINT32 base = ROUND_ADDR( addr );
969 if (!(view = VIRTUAL_FindView( base )) || (base != view->base))
971 SetLastError( ERROR_INVALID_PARAMETER );
972 return FALSE;
974 VIRTUAL_DeleteView( view );
975 return TRUE;