2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
23 #ifndef PROT_NONE /* FreeBSD doesn't define PROT_NONE */
35 virtual_mem_t
*mem
= 0;
39 /*******************************************************************
41 * A VRANGE denotes a contiguous part of the address space. It is used
42 * for house keeping, and will be obtained by higher-level memory allocation
43 * functions (VirtualAlloc, MapViewOfFile)
44 * There can be at most one VRANGE object covering any address at any time.
45 * Currently, all VRANGE objects are stored in a sorted list. Wine does not
46 * attempt to give a complete list of in-use address ranges, only those
47 * allocated via Win32.
48 * An exception is IsVrangeFree, which should test the OS specific
49 * mappings, too. As a default, an range not known to be allocated is
51 *******************************************************************/
53 VRANGE_OBJECT
*MEMORY_ranges
=0;
55 VRANGE_OBJECT
*MEMORY_FindVrange(DWORD start
)
58 for(range
=MEMORY_ranges
;range
&& range
->start
<start
;range
=range
->next
)
60 if(range
->start
<start
&& start
<range
->start
+range
->size
)
66 static int MEMORY_IsVrangeFree(DWORD start
,DWORD size
)
72 /* First, check our lists*/
74 for(range
=MEMORY_ranges
;range
&& range
->start
<start
;range
=range
->next
)
76 if((range
->start
<start
&& start
<range
->start
+range
->size
) ||
77 (range
->start
<end
&& end
<range
->start
+range
->size
))
80 /* Now, check the maps that are not under our control */
83 FILE *f
=fopen("/proc/self/maps","r");
90 if(!fgets(line
,sizeof(line
),f
))
93 lower
=strtoul(it
,&it
,16);
95 fprintf(stderr
,"Format of /proc/self/maps changed\n");
96 upper
=strtoul(it
,&it
,16);
97 if((lower
<start
&& start
<upper
) || (lower
<start
+size
&& start
+size
<upper
))
111 fprintf(stdnimp
, "Don't know how to perform MEMORY_IsVrangeFree on "
112 "this system.\n Please fix\n");
120 /* FIXME: might need to consolidate ranges */
121 void MEMORY_InsertVrange(VRANGE_OBJECT
*r
)
123 VRANGE_OBJECT
*it
,*last
;
124 if(!MEMORY_ranges
|| r
->start
<MEMORY_ranges
->start
)
126 r
->next
=MEMORY_ranges
;
129 for(it
=MEMORY_ranges
,last
=0;it
&& it
->start
<r
->start
;it
=it
->next
)
136 VRANGE_OBJECT
*MEMORY_AllocVrange(int start
,int size
)
138 VRANGE_OBJECT
*ret
=CreateKernelObject(sizeof(VRANGE_OBJECT
));
139 ret
->common
.magic
=KERNEL_OBJECT_VRANGE
;
140 MEMORY_InsertVrange(ret
);
144 void MEMORY_ReleaseVrange(VRANGE_OBJECT
*r
)
149 MEMORY_ranges
=r
->next
;
150 ReleaseKernelObject(r
);
153 for(it
=MEMORY_ranges
;it
;it
=it
->next
)
154 if(it
->next
==r
)break;
157 fprintf(stderr
,"VRANGE not found\n");
161 ReleaseKernelObject(r
);
164 /***********************************************************************
165 * VirtualAlloc (KERNEL32.548)
167 int TranslateProtectionFlags(DWORD
);
168 LPVOID
VirtualAlloc(LPVOID lpvAddress
, DWORD cbSize
,
169 DWORD fdwAllocationType
, DWORD fdwProtect
)
173 virtual_mem_t
*tmp_mem
;
176 dprintf_win32(stddeb
, "VirtualAlloc: size = %ld, address=%p\n", cbSize
, lpvAddress
);
177 if (fdwAllocationType
& MEM_RESERVE
|| !lpvAddress
) {
178 ptr
= mmap((void *)((((unsigned long)lpvAddress
-1) & 0xFFFF0000L
)
180 cbSize
, PROT_NONE
, MAP_ANON
|MAP_PRIVATE
,-1,0);
181 if (ptr
== (caddr_t
) -1) {
182 dprintf_win32(stddeb
, "VirtualAlloc: returning NULL");
183 return (LPVOID
) NULL
;
185 if (lpvAddress
&& ((unsigned long)ptr
& 0xFFFF0000L
)) {
188 ptr
= mmap(lpvAddress
, cbSize
,
189 PROT_NONE
, MAP_ANON
|MAP_PRIVATE
,-1,0);
190 if (ptr
== (caddr_t
) -1) {
191 dprintf_win32(stddeb
, "VirtualAlloc: returning NULL");
192 return (LPVOID
) NULL
;
194 ptr
= (void *)((((unsigned long)ptr
-1) & 0xFFFF0000L
)+0x00010000L
);
196 /* remember the size for VirtualFree since it's going to be handed
199 if (mem_count
== mem_used
) {
200 tmp_mem
= realloc(mem
,(mem_count
+10)*sizeof(virtual_mem_t
));
201 if (!tmp_mem
) return 0;
203 memset(mem
+mem_count
, 0, 10*sizeof(virtual_mem_t
));
206 for (i
=0; i
<mem_count
; i
++) {
209 (mem
+i
)->size
= cbSize
;
218 if (fdwAllocationType
& MEM_COMMIT
) {
219 prot
= TranslateProtectionFlags(fdwProtect
&
220 ~(PAGE_GUARD
| PAGE_NOCACHE
));
221 mprotect(ptr
, cbSize
, prot
);
224 /* kludge for gnu-win32 */
225 if (fdwAllocationType
& MEM_RESERVE
) return sbrk(0);
226 ptr
= malloc(cbSize
+ 65536);
229 /* Round it up to the next 64K boundary and zero it.
231 ptr
= (void *)(((unsigned long)ptr
& 0xFFFF0000L
) + 0x00010000L
);
232 memset(ptr
, 0, cbSize
);
235 dprintf_win32(stddeb
, "VirtualAlloc: got pointer %p\n", ptr
);
239 /***********************************************************************
240 * VirtualFree (KERNEL32.550)
242 BOOL
VirtualFree(LPVOID lpvAddress
, DWORD cbSize
, DWORD fdwFreeType
)
246 if (fdwFreeType
& MEM_RELEASE
) {
247 for (i
=0; i
<mem_count
; i
++) {
248 if ((mem
+i
)->ptr
== lpvAddress
) {
249 munmap(lpvAddress
, (mem
+i
)->size
);
256 mprotect(lpvAddress
, cbSize
, PROT_NONE
);
265 int TranslateProtectionFlags(DWORD protection_flags
)
269 switch(protection_flags
) {
274 prot
=PROT_READ
|PROT_WRITE
;
282 case PAGE_EXECUTE_READ
:
283 prot
=PROT_EXEC
|PROT_READ
;
285 case PAGE_EXECUTE_READWRITE
:
286 prot
=PROT_EXEC
|PROT_READ
|PROT_WRITE
;
288 case PAGE_EXECUTE_WRITECOPY
:
289 prot
=PROT_EXEC
|PROT_WRITE
;