Release 970112
[wine/multimedia.git] / win32 / memory.c
blob9a226151604e41f55e55f2c58c1e8348dfed5282
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
5 */
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/time.h>
11 #include <unistd.h>
12 #include <sys/mman.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include "windows.h"
16 #include "winerror.h"
17 #include "winbase.h"
18 #include "heap.h"
19 #include "stddebug.h"
20 #include "debug.h"
22 #ifndef PROT_NONE /* FreeBSD doesn't define PROT_NONE */
23 #define PROT_NONE 0
24 #endif
26 typedef struct {
27 caddr_t ptr;
28 long size;
29 } virtual_mem_t;
31 typedef struct _VRANGE_OBJECT
33 DWORD start;
34 DWORD size;
35 struct _VRANGE_OBJECT *next;
36 } VRANGE_OBJECT;
38 virtual_mem_t *mem = 0;
39 int mem_count = 0;
40 int mem_used = 0;
42 /*******************************************************************
43 * VRANGE
44 * A VRANGE denotes a contiguous part of the address space. It is used
45 * for house keeping, and will be obtained by higher-level memory allocation
46 * functions (VirtualAlloc, MapViewOfFile)
47 * There can be at most one VRANGE object covering any address at any time.
48 * Currently, all VRANGE objects are stored in a sorted list. Wine does not
49 * attempt to give a complete list of in-use address ranges, only those
50 * allocated via Win32.
51 * An exception is IsVrangeFree, which should test the OS specific
52 * mappings, too. As a default, an range not known to be allocated is
53 * considered free.
54 *******************************************************************/
56 VRANGE_OBJECT *MEMORY_ranges=0;
58 VRANGE_OBJECT *MEMORY_FindVrange(DWORD start)
60 VRANGE_OBJECT *range;
61 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
63 if(range->start<start && start<range->start+range->size)
64 return range;
66 return 0;
69 static int MEMORY_IsVrangeFree(DWORD start,DWORD size)
71 DWORD end;
72 VRANGE_OBJECT *range;
73 if(!size)
74 return 1;
75 /* First, check our lists*/
76 end=start+size;
77 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
79 if((range->start<start && start<range->start+range->size) ||
80 (range->start<end && end<range->start+range->size))
81 return 0;
83 /* Now, check the maps that are not under our control */
84 #ifdef linux
86 FILE *f=fopen("/proc/self/maps","r");
87 char line[80];
88 int found=0;
89 while(1)
91 char *it;
92 int lower,upper;
93 if(!fgets(line,sizeof(line),f))
94 break;
95 it=line;
96 lower=strtoul(it,&it,16);
97 if(*it++!='-')
98 fprintf(stderr,"Format of /proc/self/maps changed\n");
99 upper=strtoul(it,&it,16);
100 if((lower<start && start<upper) || (lower<start+size && start+size<upper))
102 found=1;
103 break;
106 fclose(f);
107 return !found;
109 #else
111 static int warned=0;
112 if(!warned)
114 fprintf(stdnimp, "Don't know how to perform MEMORY_IsVrangeFree on "
115 "this system.\n Please fix\n");
116 warned=0;
118 return 1;
120 #endif
123 /* FIXME: might need to consolidate ranges */
124 void MEMORY_InsertVrange(VRANGE_OBJECT *r)
126 VRANGE_OBJECT *it,*last;
127 if(!MEMORY_ranges || r->start<MEMORY_ranges->start)
129 r->next=MEMORY_ranges;
130 MEMORY_ranges=r;
132 for(it=MEMORY_ranges,last=0;it && it->start<r->start;it=it->next)
133 last=it;
134 r->next=last->next;
135 last->next=r;
139 VRANGE_OBJECT *MEMORY_AllocVrange(int start,int size)
141 VRANGE_OBJECT *ret=HeapAlloc( SystemHeap, 0, sizeof(VRANGE_OBJECT));
142 MEMORY_InsertVrange(ret);
143 return ret;
146 void MEMORY_ReleaseVrange(VRANGE_OBJECT *r)
148 VRANGE_OBJECT *it;
149 if(MEMORY_ranges==r)
151 MEMORY_ranges=r->next;
152 HeapFree( SystemHeap, 0, r );
153 return;
155 for(it=MEMORY_ranges;it;it=it->next)
156 if(it->next==r)break;
157 if(!it)
159 fprintf(stderr,"VRANGE not found\n");
160 return;
162 it->next=r->next;
163 HeapFree( SystemHeap, 0, r );
166 /***********************************************************************
167 * VirtualAlloc (KERNEL32.548)
169 int TranslateProtectionFlags(DWORD);
170 LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize,
171 DWORD fdwAllocationType, DWORD fdwProtect)
173 caddr_t ptr;
174 int i;
175 virtual_mem_t *tmp_mem;
176 int prot;
177 static int fdzero = -1;
179 if (fdzero == -1)
181 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
183 perror( "/dev/zero: open" );
184 return (LPVOID)NULL;
188 dprintf_win32(stddeb, "VirtualAlloc: size = %ld, address=%p\n", cbSize, lpvAddress);
189 if (fdwAllocationType & MEM_RESERVE || !lpvAddress) {
190 ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L)
191 + 0x00010000L),
192 cbSize, PROT_NONE, MAP_PRIVATE, fdzero, 0 );
193 if (ptr == (caddr_t) -1) {
194 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
195 return (LPVOID) NULL;
197 if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) {
198 munmap(ptr, cbSize);
199 cbSize += 65535;
200 ptr = mmap(lpvAddress, cbSize,
201 PROT_NONE, MAP_PRIVATE, fdzero, 0 );
202 if (ptr == (caddr_t) -1) {
203 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
204 return (LPVOID) NULL;
206 ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L);
208 /* remember the size for VirtualFree since it's going to be handed
209 a zero len */
210 if (ptr) {
211 if (mem_count == mem_used) {
212 tmp_mem = realloc(mem,(mem_count+10)*sizeof(virtual_mem_t));
213 if (!tmp_mem) return 0;
214 mem = tmp_mem;
215 memset(mem+mem_count, 0, 10*sizeof(virtual_mem_t));
216 mem_count += 10;
218 for (i=0; i<mem_count; i++) {
219 if (!(mem+i)->ptr) {
220 (mem+i)->ptr = ptr;
221 (mem+i)->size = cbSize;
222 mem_used++;
223 break;
227 } else {
228 ptr = lpvAddress;
230 if (fdwAllocationType & MEM_COMMIT) {
231 prot = TranslateProtectionFlags(fdwProtect &
232 ~(PAGE_GUARD | PAGE_NOCACHE));
233 mprotect(ptr, cbSize, prot);
235 #if 0
236 /* kludge for gnu-win32 */
237 if (fdwAllocationType & MEM_RESERVE) return sbrk(0);
238 ptr = malloc(cbSize + 65536);
239 if(ptr)
241 /* Round it up to the next 64K boundary and zero it.
243 ptr = (void *)(((unsigned long)ptr & 0xFFFF0000L) + 0x00010000L);
244 memset(ptr, 0, cbSize);
246 #endif
247 dprintf_win32(stddeb, "VirtualAlloc: got pointer %p\n", ptr);
248 return ptr;
251 /***********************************************************************
252 * VirtualFree (KERNEL32.550)
254 BOOL32 VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType)
256 int i;
258 if (fdwFreeType & MEM_RELEASE) {
259 for (i=0; i<mem_count; i++) {
260 if ((mem+i)->ptr == lpvAddress) {
261 munmap(lpvAddress, (mem+i)->size);
262 (mem+i)->ptr = 0;
263 mem_used--;
264 break;
267 } else {
268 mprotect(lpvAddress, cbSize, PROT_NONE);
270 #if 0
271 if(lpvAddress)
272 free(lpvAddress);
273 #endif
274 return 1;
277 /***********************************************************************
278 * VirtualQuery (KERNEL32.554)
280 BOOL32 VirtualQuery(LPCVOID address,LPMEMORY_BASIC_INFORMATION buf,DWORD len)
282 /* FIXME: fill out structure ... */
283 return TRUE;
286 int TranslateProtectionFlags(DWORD protection_flags)
288 int prot;
290 switch(protection_flags) {
291 case PAGE_READONLY:
292 prot=PROT_READ;
293 break;
294 case PAGE_READWRITE:
295 prot=PROT_READ|PROT_WRITE;
296 break;
297 case PAGE_WRITECOPY:
298 prot=PROT_WRITE;
299 break;
300 case PAGE_EXECUTE:
301 prot=PROT_EXEC;
302 break;
303 case PAGE_EXECUTE_READ:
304 prot=PROT_EXEC|PROT_READ;
305 break;
306 case PAGE_EXECUTE_READWRITE:
307 prot=PROT_EXEC|PROT_READ|PROT_WRITE;
308 break;
309 case PAGE_EXECUTE_WRITECOPY:
310 prot=PROT_EXEC|PROT_WRITE;
311 break;
312 case PAGE_NOACCESS:
313 default:
314 prot=PROT_NONE;
315 break;
317 return prot;
321 /******************************************************************
322 * IsBadReadPtr
324 BOOL WIN32_IsBadReadPtr(void* ptr, unsigned int bytes)
326 dprintf_global(stddeb,"IsBadReadPtr(%x,%x)\n",(int)ptr,bytes);
327 /* FIXME: Should make check based on actual mappings, here */
328 return FALSE;
331 /******************************************************************
332 * IsBadWritePtr
334 BOOL WIN32_IsBadWritePtr(void* ptr, unsigned int bytes)
336 dprintf_global(stddeb,"IsBadWritePtr(%x,%x)\n",(int)ptr,bytes);
337 /* FIXME: Should make check based on actual mappings, here */
338 return FALSE;
340 /******************************************************************
341 * IsBadWritePtr
343 BOOL WIN32_IsBadCodePtr(void* ptr, unsigned int bytes)
345 dprintf_global(stddeb,"IsBadCodePtr(%x,%x)\n",(int)ptr,bytes);
346 /* FIXME: Should make check based on actual mappings, here */
347 return FALSE;