Release 960928
[wine/multimedia.git] / win32 / memory.c
bloba08b07f4f40f98d40c68060beaca819c4c129d51
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 "handle32.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 virtual_mem_t *mem = 0;
32 int mem_count = 0;
33 int mem_used = 0;
35 /*******************************************************************
36 * VRANGE
37 * A VRANGE denotes a contiguous part of the address space. It is used
38 * for house keeping, and will be obtained by higher-level memory allocation
39 * functions (VirtualAlloc, MapViewOfFile)
40 * There can be at most one VRANGE object covering any address at any time.
41 * Currently, all VRANGE objects are stored in a sorted list. Wine does not
42 * attempt to give a complete list of in-use address ranges, only those
43 * allocated via Win32.
44 * An exception is IsVrangeFree, which should test the OS specific
45 * mappings, too. As a default, an range not known to be allocated is
46 * considered free.
47 *******************************************************************/
49 VRANGE_OBJECT *MEMORY_ranges=0;
51 VRANGE_OBJECT *MEMORY_FindVrange(DWORD start)
53 VRANGE_OBJECT *range;
54 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
56 if(range->start<start && start<range->start+range->size)
57 return range;
59 return 0;
62 static int MEMORY_IsVrangeFree(DWORD start,DWORD size)
64 DWORD end;
65 VRANGE_OBJECT *range;
66 if(!size)
67 return 1;
68 /* First, check our lists*/
69 end=start+size;
70 for(range=MEMORY_ranges;range && range->start<start;range=range->next)
72 if((range->start<start && start<range->start+range->size) ||
73 (range->start<end && end<range->start+range->size))
74 return 0;
76 /* Now, check the maps that are not under our control */
77 #ifdef linux
79 FILE *f=fopen("/proc/self/maps","r");
80 char line[80];
81 int found=0;
82 while(1)
84 char *it;
85 int lower,upper;
86 if(!fgets(line,sizeof(line),f))
87 break;
88 it=line;
89 lower=strtoul(it,&it,16);
90 if(*it++!='-')
91 fprintf(stderr,"Format of /proc/self/maps changed\n");
92 upper=strtoul(it,&it,16);
93 if((lower<start && start<upper) || (lower<start+size && start+size<upper))
95 found=1;
96 break;
99 fclose(f);
100 return !found;
102 #else
104 static int warned=0;
105 if(!warned)
107 fprintf(stdnimp, "Don't know how to perform MEMORY_IsVrangeFree on "
108 "this system.\n Please fix\n");
109 warned=0;
111 return 1;
113 #endif
116 /* FIXME: might need to consolidate ranges */
117 void MEMORY_InsertVrange(VRANGE_OBJECT *r)
119 VRANGE_OBJECT *it,*last;
120 if(!MEMORY_ranges || r->start<MEMORY_ranges->start)
122 r->next=MEMORY_ranges;
123 MEMORY_ranges=r;
125 for(it=MEMORY_ranges,last=0;it && it->start<r->start;it=it->next)
126 last=it;
127 r->next=last->next;
128 last->next=r;
132 VRANGE_OBJECT *MEMORY_AllocVrange(int start,int size)
134 VRANGE_OBJECT *ret=CreateKernelObject(sizeof(VRANGE_OBJECT));
135 ret->common.magic=KERNEL_OBJECT_VRANGE;
136 MEMORY_InsertVrange(ret);
137 return ret;
140 void MEMORY_ReleaseVrange(VRANGE_OBJECT *r)
142 VRANGE_OBJECT *it;
143 if(MEMORY_ranges==r)
145 MEMORY_ranges=r->next;
146 ReleaseKernelObject(r);
147 return;
149 for(it=MEMORY_ranges;it;it=it->next)
150 if(it->next==r)break;
151 if(!it)
153 fprintf(stderr,"VRANGE not found\n");
154 return;
156 it->next=r->next;
157 ReleaseKernelObject(r);
160 /***********************************************************************
161 * VirtualAlloc (KERNEL32.548)
163 int TranslateProtectionFlags(DWORD);
164 LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize,
165 DWORD fdwAllocationType, DWORD fdwProtect)
167 caddr_t ptr;
168 int i;
169 virtual_mem_t *tmp_mem;
170 int prot;
171 static int fdzero = -1;
173 if (fdzero == -1)
175 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
177 perror( "/dev/zero: open" );
178 return (LPVOID)NULL;
182 dprintf_win32(stddeb, "VirtualAlloc: size = %ld, address=%p\n", cbSize, lpvAddress);
183 if (fdwAllocationType & MEM_RESERVE || !lpvAddress) {
184 ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L)
185 + 0x00010000L),
186 cbSize, PROT_NONE, MAP_PRIVATE, fdzero, 0 );
187 if (ptr == (caddr_t) -1) {
188 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
189 return (LPVOID) NULL;
191 if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) {
192 munmap(ptr, cbSize);
193 cbSize += 65535;
194 ptr = mmap(lpvAddress, cbSize,
195 PROT_NONE, MAP_PRIVATE, fdzero, 0 );
196 if (ptr == (caddr_t) -1) {
197 dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
198 return (LPVOID) NULL;
200 ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L);
202 /* remember the size for VirtualFree since it's going to be handed
203 a zero len */
204 if (ptr) {
205 if (mem_count == mem_used) {
206 tmp_mem = realloc(mem,(mem_count+10)*sizeof(virtual_mem_t));
207 if (!tmp_mem) return 0;
208 mem = tmp_mem;
209 memset(mem+mem_count, 0, 10*sizeof(virtual_mem_t));
210 mem_count += 10;
212 for (i=0; i<mem_count; i++) {
213 if (!(mem+i)->ptr) {
214 (mem+i)->ptr = ptr;
215 (mem+i)->size = cbSize;
216 mem_used++;
217 break;
221 } else {
222 ptr = lpvAddress;
224 if (fdwAllocationType & MEM_COMMIT) {
225 prot = TranslateProtectionFlags(fdwProtect &
226 ~(PAGE_GUARD | PAGE_NOCACHE));
227 mprotect(ptr, cbSize, prot);
229 #if 0
230 /* kludge for gnu-win32 */
231 if (fdwAllocationType & MEM_RESERVE) return sbrk(0);
232 ptr = malloc(cbSize + 65536);
233 if(ptr)
235 /* Round it up to the next 64K boundary and zero it.
237 ptr = (void *)(((unsigned long)ptr & 0xFFFF0000L) + 0x00010000L);
238 memset(ptr, 0, cbSize);
240 #endif
241 dprintf_win32(stddeb, "VirtualAlloc: got pointer %p\n", ptr);
242 return ptr;
245 /***********************************************************************
246 * VirtualFree (KERNEL32.550)
248 BOOL32 VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType)
250 int i;
252 if (fdwFreeType & MEM_RELEASE) {
253 for (i=0; i<mem_count; i++) {
254 if ((mem+i)->ptr == lpvAddress) {
255 munmap(lpvAddress, (mem+i)->size);
256 (mem+i)->ptr = 0;
257 mem_used--;
258 break;
261 } else {
262 mprotect(lpvAddress, cbSize, PROT_NONE);
264 #if 0
265 if(lpvAddress)
266 free(lpvAddress);
267 #endif
268 return 1;
271 /***********************************************************************
272 * VirtualQuery (KERNEL32.554)
274 BOOL32 VirtualQuery(LPCVOID address,LPMEMORY_BASIC_INFORMATION buf,DWORD len)
276 /* FIXME: fill out structure ... */
277 return TRUE;
280 int TranslateProtectionFlags(DWORD protection_flags)
282 int prot;
284 switch(protection_flags) {
285 case PAGE_READONLY:
286 prot=PROT_READ;
287 break;
288 case PAGE_READWRITE:
289 prot=PROT_READ|PROT_WRITE;
290 break;
291 case PAGE_WRITECOPY:
292 prot=PROT_WRITE;
293 break;
294 case PAGE_EXECUTE:
295 prot=PROT_EXEC;
296 break;
297 case PAGE_EXECUTE_READ:
298 prot=PROT_EXEC|PROT_READ;
299 break;
300 case PAGE_EXECUTE_READWRITE:
301 prot=PROT_EXEC|PROT_READ|PROT_WRITE;
302 break;
303 case PAGE_EXECUTE_WRITECOPY:
304 prot=PROT_EXEC|PROT_WRITE;
305 break;
306 case PAGE_NOACCESS:
307 default:
308 prot=PROT_NONE;
309 break;
311 return prot;
315 /******************************************************************
316 * IsBadReadPtr
318 BOOL WIN32_IsBadReadPtr(void* ptr, unsigned int bytes)
320 dprintf_global(stddeb,"IsBadReadPtr(%x,%x)\n",(int)ptr,bytes);
321 /* FIXME: Should make check based on actual mappings, here */
322 return FALSE;
325 /******************************************************************
326 * IsBadWritePtr
328 BOOL WIN32_IsBadWritePtr(void* ptr, unsigned int bytes)
330 dprintf_global(stddeb,"IsBadWritePtr(%x,%x)\n",(int)ptr,bytes);
331 /* FIXME: Should make check based on actual mappings, here */
332 return FALSE;
334 /******************************************************************
335 * IsBadWritePtr
337 BOOL WIN32_IsBadCodePtr(void* ptr, unsigned int bytes)
339 dprintf_global(stddeb,"IsBadCodePtr(%x,%x)\n",(int)ptr,bytes);
340 /* FIXME: Should make check based on actual mappings, here */
341 return FALSE;