/* * Win32 kernel functions * * Copyright 1995 Martin von Loewis and Cameron Heide */ #include #include #include #include #include #include #include #include #include "windows.h" #include "winerror.h" #include "winbase.h" #include "heap.h" #include "stddebug.h" #include "debug.h" #ifndef PROT_NONE /* FreeBSD doesn't define PROT_NONE */ #define PROT_NONE 0 #endif typedef struct { caddr_t ptr; long size; } virtual_mem_t; typedef struct _VRANGE_OBJECT { DWORD start; DWORD size; struct _VRANGE_OBJECT *next; } VRANGE_OBJECT; virtual_mem_t *mem = 0; int mem_count = 0; int mem_used = 0; /******************************************************************* * VRANGE * A VRANGE denotes a contiguous part of the address space. It is used * for house keeping, and will be obtained by higher-level memory allocation * functions (VirtualAlloc, MapViewOfFile) * There can be at most one VRANGE object covering any address at any time. * Currently, all VRANGE objects are stored in a sorted list. Wine does not * attempt to give a complete list of in-use address ranges, only those * allocated via Win32. * An exception is IsVrangeFree, which should test the OS specific * mappings, too. As a default, an range not known to be allocated is * considered free. *******************************************************************/ VRANGE_OBJECT *MEMORY_ranges=0; VRANGE_OBJECT *MEMORY_FindVrange(DWORD start) { VRANGE_OBJECT *range; for(range=MEMORY_ranges;range && range->startnext) { if(range->startstart+range->size) return range; } return 0; } static int MEMORY_IsVrangeFree(DWORD start,DWORD size) { DWORD end; VRANGE_OBJECT *range; if(!size) return 1; /* First, check our lists*/ end=start+size; for(range=MEMORY_ranges;range && range->startnext) { if((range->startstart+range->size) || (range->startstart+range->size)) return 0; } /* Now, check the maps that are not under our control */ #ifdef linux { FILE *f=fopen("/proc/self/maps","r"); char line[80]; int found=0; while(1) { char *it; int lower,upper; if(!fgets(line,sizeof(line),f)) break; it=line; lower=strtoul(it,&it,16); if(*it++!='-') fprintf(stderr,"Format of /proc/self/maps changed\n"); upper=strtoul(it,&it,16); if((lowerstartstart) { r->next=MEMORY_ranges; MEMORY_ranges=r; } for(it=MEMORY_ranges,last=0;it && it->startstart;it=it->next) last=it; r->next=last->next; last->next=r; } VRANGE_OBJECT *MEMORY_AllocVrange(int start,int size) { VRANGE_OBJECT *ret=HeapAlloc( SystemHeap, 0, sizeof(VRANGE_OBJECT)); MEMORY_InsertVrange(ret); return ret; } void MEMORY_ReleaseVrange(VRANGE_OBJECT *r) { VRANGE_OBJECT *it; if(MEMORY_ranges==r) { MEMORY_ranges=r->next; HeapFree( SystemHeap, 0, r ); return; } for(it=MEMORY_ranges;it;it=it->next) if(it->next==r)break; if(!it) { fprintf(stderr,"VRANGE not found\n"); return; } it->next=r->next; HeapFree( SystemHeap, 0, r ); } /*********************************************************************** * VirtualAlloc (KERNEL32.548) */ int TranslateProtectionFlags(DWORD); LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize, DWORD fdwAllocationType, DWORD fdwProtect) { caddr_t ptr; int i; virtual_mem_t *tmp_mem; int prot; static int fdzero = -1; if (fdzero == -1) { if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1) { perror( "/dev/zero: open" ); return (LPVOID)NULL; } } dprintf_win32(stddeb, "VirtualAlloc: size = %ld, address=%p\n", cbSize, lpvAddress); if (fdwAllocationType & MEM_RESERVE || !lpvAddress) { ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L) + 0x00010000L), cbSize, PROT_NONE, MAP_PRIVATE, fdzero, 0 ); if (ptr == (caddr_t) -1) { dprintf_win32(stddeb, "VirtualAlloc: returning NULL"); return (LPVOID) NULL; } if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) { munmap(ptr, cbSize); cbSize += 65535; ptr = mmap(lpvAddress, cbSize, PROT_NONE, MAP_PRIVATE, fdzero, 0 ); if (ptr == (caddr_t) -1) { dprintf_win32(stddeb, "VirtualAlloc: returning NULL"); return (LPVOID) NULL; } ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L); } /* remember the size for VirtualFree since it's going to be handed a zero len */ if (ptr) { if (mem_count == mem_used) { tmp_mem = realloc(mem,(mem_count+10)*sizeof(virtual_mem_t)); if (!tmp_mem) return 0; mem = tmp_mem; memset(mem+mem_count, 0, 10*sizeof(virtual_mem_t)); mem_count += 10; } for (i=0; iptr) { (mem+i)->ptr = ptr; (mem+i)->size = cbSize; mem_used++; break; } } } } else { ptr = lpvAddress; } if (fdwAllocationType & MEM_COMMIT) { prot = TranslateProtectionFlags(fdwProtect & ~(PAGE_GUARD | PAGE_NOCACHE)); mprotect(ptr, cbSize, prot); } #if 0 /* kludge for gnu-win32 */ if (fdwAllocationType & MEM_RESERVE) return sbrk(0); ptr = malloc(cbSize + 65536); if(ptr) { /* Round it up to the next 64K boundary and zero it. */ ptr = (void *)(((unsigned long)ptr & 0xFFFF0000L) + 0x00010000L); memset(ptr, 0, cbSize); } #endif dprintf_win32(stddeb, "VirtualAlloc: got pointer %p\n", ptr); return ptr; } /*********************************************************************** * VirtualFree (KERNEL32.550) */ BOOL32 VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType) { int i; if (fdwFreeType & MEM_RELEASE) { for (i=0; iptr == lpvAddress) { munmap(lpvAddress, (mem+i)->size); (mem+i)->ptr = 0; mem_used--; break; } } } else { mprotect(lpvAddress, cbSize, PROT_NONE); } #if 0 if(lpvAddress) free(lpvAddress); #endif return 1; } /*********************************************************************** * VirtualQuery (KERNEL32.554) */ BOOL32 VirtualQuery(LPCVOID address,LPMEMORY_BASIC_INFORMATION buf,DWORD len) { /* FIXME: fill out structure ... */ return TRUE; } int TranslateProtectionFlags(DWORD protection_flags) { int prot; switch(protection_flags) { case PAGE_READONLY: prot=PROT_READ; break; case PAGE_READWRITE: prot=PROT_READ|PROT_WRITE; break; case PAGE_WRITECOPY: prot=PROT_WRITE; break; case PAGE_EXECUTE: prot=PROT_EXEC; break; case PAGE_EXECUTE_READ: prot=PROT_EXEC|PROT_READ; break; case PAGE_EXECUTE_READWRITE: prot=PROT_EXEC|PROT_READ|PROT_WRITE; break; case PAGE_EXECUTE_WRITECOPY: prot=PROT_EXEC|PROT_WRITE; break; case PAGE_NOACCESS: default: prot=PROT_NONE; break; } return prot; } /****************************************************************** * IsBadReadPtr */ BOOL WIN32_IsBadReadPtr(void* ptr, unsigned int bytes) { dprintf_global(stddeb,"IsBadReadPtr(%x,%x)\n",(int)ptr,bytes); /* FIXME: Should make check based on actual mappings, here */ return FALSE; } /****************************************************************** * IsBadWritePtr */ BOOL WIN32_IsBadWritePtr(void* ptr, unsigned int bytes) { dprintf_global(stddeb,"IsBadWritePtr(%x,%x)\n",(int)ptr,bytes); /* FIXME: Should make check based on actual mappings, here */ return FALSE; } /****************************************************************** * IsBadWritePtr */ BOOL WIN32_IsBadCodePtr(void* ptr, unsigned int bytes) { dprintf_global(stddeb,"IsBadCodePtr(%x,%x)\n",(int)ptr,bytes); /* FIXME: Should make check based on actual mappings, here */ return FALSE; }