2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
24 #ifndef PROT_NONE /* FreeBSD doesn't define PROT_NONE */
33 virtual_mem_t *mem = 0;
37 /*******************************************************************
39 * A VRANGE denotes a contiguous part of the address space. It is used
40 * for house keeping, and will be obtained by higher-level memory allocation
41 * functions (VirtualAlloc, MapViewOfFile)
42 * There can be at most one VRANGE object covering any address at any time.
43 * Currently, all VRANGE objects are stored in a sorted list. Wine does not
44 * attempt to give a complete list of in-use address ranges, only those
45 * allocated via Win32.
46 * An exception is IsVrangeFree, which should test the OS specific
47 * mappings, too. As a default, an range not known to be allocated is
49 *******************************************************************/
51 VRANGE_OBJECT *MEMORY_ranges=0;
53 VRANGE_OBJECT *MEMORY_FindVrange(DWORD start)
56 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
58 if(range->start<start && start<range->start+range->size)
64 static int MEMORY_IsVrangeFree(DWORD start,DWORD size)
70 /* First, check our lists*/
72 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
74 if((range->start<start && start<range->start+range->size) ||
75 (range->start<end && end<range->start+range->size))
78 /* Now, check the maps that are not under our control */
81 FILE *f=fopen("/proc/self/maps","r");
88 if(!fgets(line,sizeof(line),f))
91 lower=strtoul(it,&it,16);
93 fprintf(stderr,"Format of /proc/self/maps changed\n");
94 upper=strtoul(it,&it,16);
95 if((lower<start && start<upper) || (lower<start+size && start+size<upper))
109 fprintf(stdnimp, "Don't know how to perform MEMORY_IsVrangeFree on "
110 "this system.\n Please fix\n");
118 /* FIXME: might need to consolidate ranges */
119 void MEMORY_InsertVrange(VRANGE_OBJECT *r)
121 VRANGE_OBJECT *it,*last;
122 if(!MEMORY_ranges || r->start<MEMORY_ranges->start)
124 r->next=MEMORY_ranges;
127 for(it=MEMORY_ranges,last=0;it && it->start<r->start;it=it->next)
134 VRANGE_OBJECT *MEMORY_AllocVrange(int start,int size)
136 VRANGE_OBJECT *ret=CreateKernelObject(sizeof(VRANGE_OBJECT));
137 ret->common.magic=KERNEL_OBJECT_VRANGE;
138 MEMORY_InsertVrange(ret);
142 void MEMORY_ReleaseVrange(VRANGE_OBJECT *r)
147 MEMORY_ranges=r->next;
148 ReleaseKernelObject(r);
151 for(it=MEMORY_ranges;it;it=it->next)
152 if(it->next==r)break;
155 fprintf(stderr,"VRANGE not found\n");
159 ReleaseKernelObject(r);
162 /***********************************************************************
163 * VirtualAlloc (KERNEL32.548)
165 int TranslateProtectionFlags(DWORD);
166 LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize,
167 DWORD fdwAllocationType, DWORD fdwProtect)
171 virtual_mem_t *tmp_mem;
173 static int fdzero = -1;
177 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
179 perror( "/dev/zero: open" );
184 dprintf_win32(stddeb, "VirtualAlloc: size = %ld, address=%p\n", cbSize, lpvAddress);
185 if (fdwAllocationType & MEM_RESERVE || !lpvAddress) {
186 ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L)
188 cbSize, PROT_NONE, MAP_PRIVATE, fdzero, 0 );
189 if (ptr == (caddr_t) -1) {
190 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
191 return (LPVOID) NULL;
193 if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) {
196 ptr = mmap(lpvAddress, cbSize,
197 PROT_NONE, MAP_PRIVATE, fdzero, 0 );
198 if (ptr == (caddr_t) -1) {
199 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
200 return (LPVOID) NULL;
202 ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L);
204 /* remember the size for VirtualFree since it's going to be handed
207 if (mem_count == mem_used) {
208 tmp_mem = realloc(mem,(mem_count+10)*sizeof(virtual_mem_t));
209 if (!tmp_mem) return 0;
211 memset(mem+mem_count, 0, 10*sizeof(virtual_mem_t));
214 for (i=0; i<mem_count; i++) {
217 (mem+i)->size = cbSize;
226 if (fdwAllocationType & MEM_COMMIT) {
227 prot = TranslateProtectionFlags(fdwProtect &
228 ~(PAGE_GUARD | PAGE_NOCACHE));
229 mprotect(ptr, cbSize, prot);
232 /* kludge for gnu-win32 */
233 if (fdwAllocationType & MEM_RESERVE) return sbrk(0);
234 ptr = malloc(cbSize + 65536);
237 /* Round it up to the next 64K boundary and zero it.
239 ptr = (void *)(((unsigned long)ptr & 0xFFFF0000L) + 0x00010000L);
240 memset(ptr, 0, cbSize);
243 dprintf_win32(stddeb, "VirtualAlloc: got pointer %p\n", ptr);
247 /***********************************************************************
248 * VirtualFree (KERNEL32.550)
250 BOOL VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType)
254 if (fdwFreeType & MEM_RELEASE) {
255 for (i=0; i<mem_count; i++) {
256 if ((mem+i)->ptr == lpvAddress) {
257 munmap(lpvAddress, (mem+i)->size);
264 mprotect(lpvAddress, cbSize, PROT_NONE);
273 int TranslateProtectionFlags(DWORD protection_flags)
277 switch(protection_flags) {
282 prot=PROT_READ|PROT_WRITE;
290 case PAGE_EXECUTE_READ:
291 prot=PROT_EXEC|PROT_READ;
293 case PAGE_EXECUTE_READWRITE:
294 prot=PROT_EXEC|PROT_READ|PROT_WRITE;
296 case PAGE_EXECUTE_WRITECOPY:
297 prot=PROT_EXEC|PROT_WRITE;
308 /******************************************************************
311 BOOL WIN32_IsBadReadPtr(void* ptr, unsigned int bytes)
313 dprintf_global(stddeb,"IsBadReadPtr(%x,%x)\n",ptr,bytes);
314 /* FIXME: Should make check based on actual mappings, here */
318 /******************************************************************
321 BOOL WIN32_IsBadWritePtr(void* ptr, unsigned int bytes)
323 dprintf_global(stddeb,"IsBadWritePtr(%x,%x)\n",ptr,bytes);
324 /* FIXME: Should make check based on actual mappings, here */
327 /******************************************************************
330 BOOL WIN32_IsBadCodePtr(void* ptr, unsigned int bytes)
332 dprintf_global(stddeb,"IsBadCodePtr(%x,%x)\n",ptr,bytes);
333 /* FIXME: Should make check based on actual mappings, here */