source: trunk/src/kernel32/virtual.cpp@ 9824

Last change on this file since 9824 was 9824, checked in by sandervl, 23 years ago

Cleaned up memory map code

File size: 28.5 KB
Line 
1/* $Id: virtual.cpp,v 1.50 2003-02-18 18:48:55 sandervl Exp $ */
2
3/*
4 * Win32 virtual memory functions
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Knut St. Osmundsen
8 * Copyright 1998 Peter FitzSimmons
9 *
10 * Parts (VIRTUAL_MapFileA/W) based on Wine code (memory\virtual.c):
11 *
12 * Copyright 1997 Alexandre Julliard
13 *
14 * Project Odin Software License can be found in LICENSE.TXT
15 *
16 */
17
18#include <odin.h>
19#include <odinwrap.h>
20
21#include <os2win.h>
22#include <stdlib.h>
23#include <string.h>
24#include <win\virtual.h>
25#include <win\thread.h>
26#include <heapstring.h>
27#include <handlemanager.h>
28#include "mmap.h"
29#include "oslibdos.h"
30#include "oslibmem.h"
31
32#define DBG_LOCALLOG DBG_virtual
33#include "dbglocal.h"
34
35ODINDEBUGCHANNEL(KERNEL32-VIRTUAL)
36
37#define PAGE_SHIFT 12
38
39/***********************************************************************
40 * CreateFileMapping32A (KERNEL32.46)
41 * Creates a named or unnamed file-mapping object for the specified file
42 *
43 * RETURNS
44 * Handle: Success
45 * 0: Mapping object does not exist
46 * NULL: Failure
47 */
48HANDLE WINAPI CreateFileMappingA(
49 HFILE hFile, /* [in] Handle of file to map */
50 SECURITY_ATTRIBUTES *sa, /* [in] Optional security attributes*/
51 DWORD protect, /* [in] Protection for mapping object */
52 DWORD size_high, /* [in] High-order 32 bits of object size */
53 DWORD size_low, /* [in] Low-order 32 bits of object size */
54 LPCSTR name /* [in] Name of file-mapping object */ )
55{
56 HANDLE hFileMap;
57
58 dprintf(("CreateFileMappingA: %x %x %x%x %s", hFile, protect, size_high, size_low, name));
59 hFileMap = HMCreateFileMapping(hFile, sa, protect, size_high, size_low, name);
60 dprintf(("CreateFileMappingA returned %x", hFileMap));
61 return hFileMap;
62}
63
64
65/***********************************************************************
66 * CreateFileMapping32W (KERNEL32.47)
67 * See CreateFileMapping32A
68 */
69HANDLE WINAPI CreateFileMappingW( HFILE hFile, LPSECURITY_ATTRIBUTES attr,
70 DWORD protect, DWORD size_high,
71 DWORD size_low, LPCWSTR name )
72{
73 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
74 HANDLE ret = CreateFileMappingA( hFile, attr, protect,
75 size_high, size_low, nameA );
76 HeapFree( GetProcessHeap(), 0, nameA );
77 return ret;
78}
79
80
81/***********************************************************************
82 * OpenFileMapping32A (KERNEL32.397)
83 * Opens a named file-mapping object.
84 *
85 * RETURNS
86 * Handle: Success
87 * NULL: Failure
88 */
89HANDLE WINAPI OpenFileMappingA(
90 DWORD access, /* [in] Access mode */
91 BOOL inherit, /* [in] Inherit flag */
92 LPCSTR name ) /* [in] Name of file-mapping object */
93{
94 dprintf(("OpenFileMappingA: %x %d %s", access, inherit, name));
95 return HMOpenFileMapping(access, inherit, name);
96}
97
98
99/***********************************************************************
100 * OpenFileMapping32W (KERNEL32.398)
101 * See OpenFileMapping32A
102 */
103HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
104{
105 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
106 HANDLE ret = OpenFileMappingA( access, inherit, nameA );
107 HeapFree( GetProcessHeap(), 0, nameA );
108 return ret;
109}
110
111
112/***********************************************************************
113 * MapViewOfFile (KERNEL32.385)
114 * Maps a view of a file into the address space
115 *
116 * RETURNS
117 * Starting address of mapped view
118 * NULL: Failure
119 */
120LPVOID WINAPI MapViewOfFile(
121 HANDLE mapping, /* [in] File-mapping object to map */
122 DWORD access, /* [in] Access mode */
123 DWORD offset_high, /* [in] High-order 32 bits of file offset */
124 DWORD offset_low, /* [in] Low-order 32 bits of file offset */
125 DWORD count /* [in] Number of bytes to map */
126)
127{
128 return MapViewOfFileEx( mapping, access, offset_high,
129 offset_low, count, NULL );
130}
131
132
133/***********************************************************************
134 * MapViewOfFileEx (KERNEL32.386)
135 * Maps a view of a file into the address space
136 *
137 * RETURNS
138 * Starting address of mapped view
139 * NULL: Failure
140 */
141LPVOID WINAPI MapViewOfFileEx(
142 HANDLE handle, /* [in] File-mapping object to map */
143 DWORD access, /* [in] Access mode */
144 DWORD offset_high, /* [in] High-order 32 bits of file offset */
145 DWORD offset_low, /* [in] Low-order 32 bits of file offset */
146 DWORD count, /* [in] Number of bytes to map */
147 LPVOID addr /* [in] Suggested starting address for mapped view */
148)
149{
150 return HMMapViewOfFileEx(handle, access, offset_high, offset_low, count, addr);
151}
152
153
154/***********************************************************************
155 * FlushViewOfFile (KERNEL32.262)
156 * Writes to the disk a byte range within a mapped view of a file
157 *
158 * RETURNS
159 * TRUE: Success
160 * FALSE: Failure
161 */
162BOOL WINAPI FlushViewOfFile(
163 LPCVOID base, /* [in] Start address of byte range to flush */
164 DWORD cbFlush /* [in] Number of bytes in range */
165)
166{
167 Win32MemMap *map;
168 DWORD offset;
169 BOOL ret;
170
171 if (!base)
172 {
173 SetLastError( ERROR_INVALID_PARAMETER );
174 return FALSE;
175 }
176 map = Win32MemMapView::findMapByView((ULONG)base, &offset, MEMMAP_ACCESS_READ);
177 if(map == NULL) {
178 SetLastError( ERROR_FILE_NOT_FOUND );
179 return FALSE;
180 }
181 ret = map->flushView(offset, cbFlush);
182 map->Release();
183 return ret;
184}
185
186
187/***********************************************************************
188 * UnmapViewOfFile (KERNEL32.540)
189 * Unmaps a mapped view of a file.
190 *
191 * NOTES
192 * Should addr be an LPCVOID?
193 *
194 * RETURNS
195 * TRUE: Success
196 * FALSE: Failure
197 */
198BOOL WINAPI UnmapViewOfFile(LPVOID addr /* [in] Address where mapped view begins */
199)
200{
201 Win32MemMap *map;
202 BOOL ret;
203
204 if (!addr)
205 {
206 SetLastError( ERROR_INVALID_PARAMETER );
207 return FALSE;
208 }
209 map = Win32MemMapView::findMapByView((ULONG)addr);
210 if(map == NULL) {
211 SetLastError( ERROR_FILE_NOT_FOUND );
212 return FALSE;
213 }
214 ret = map->unmapViewOfFile(addr);
215 map->Release();
216 return ret;
217}
218
219/***********************************************************************
220 * VIRTUAL_MapFileW
221 *
222 * Helper function to map a file to memory:
223 * name - file name
224 * [RETURN] ptr - pointer to mapped file
225 */
226HANDLE WINAPI VIRTUAL_MapFileW( LPCWSTR name , LPVOID *lpMapping, BOOL fReadIntoMemory)
227{
228 HANDLE hFile, hMapping = -1;
229
230 hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
231 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);
232 if (hFile != INVALID_HANDLE_VALUE)
233 {
234 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | ((fReadIntoMemory) ? SEC_COMMIT : 0), 0, 0, NULL );
235 CloseHandle( hFile );
236 if (hMapping)
237 {
238 *lpMapping = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
239 }
240 }
241 return hMapping;
242}
243
244/***********************************************************************
245 * VIRTUAL_MapFileA
246 *
247 * Helper function to map a file to memory:
248 * name - file name
249 * [RETURN] ptr - pointer to mapped file
250 */
251HANDLE WINAPI VIRTUAL_MapFileA( LPCSTR name , LPVOID *lpMapping, BOOL fReadIntoMemory)
252{
253 HANDLE hFile, hMapping = -1;
254
255 hFile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
256 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);
257 if (hFile != INVALID_HANDLE_VALUE)
258 {
259 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | ((fReadIntoMemory) ? SEC_COMMIT : 0), 0, 0, NULL );
260 CloseHandle( hFile );
261 if (hMapping)
262 {
263 *lpMapping = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
264 }
265 }
266 return hMapping;
267}
268
269//******************************************************************************
270//******************************************************************************
271LPVOID WIN32API VirtualAlloc(LPVOID lpvAddress,
272 DWORD cbSize,
273 DWORD fdwAllocationType,
274 DWORD fdwProtect)
275{
276 PVOID Address = lpvAddress;
277 ULONG flag = 0, base;
278 DWORD rc;
279
280 SetLastError(ERROR_SUCCESS);
281
282 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */
283 {
284 dprintf(("VirtualAlloc: size too large"));
285 SetLastError( ERROR_OUTOFMEMORY );
286 return NULL;
287 }
288
289 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||
290 (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
291 {
292 dprintf(("VirtualAlloc: Invalid parameter"));
293 SetLastError( ERROR_INVALID_PARAMETER );
294 return NULL;
295 }
296
297 if(fdwAllocationType & MEM_COMMIT)
298 {
299 dprintf(("VirtualAlloc: commit\n"));
300 flag = PAG_COMMIT;
301 }
302
303 if(fdwAllocationType & MEM_RESERVE) {
304 //SvL: DosRead crashes if memory is initially reserved with write
305 // access disabled (OS/2 bug) even if the commit sets the page
306 // flags to read/write:
307 // DosSetMem does not alter the 16 bit selectors so if you change memory
308 // attributes and then access the memory with a 16 bit API (such as DosRead),
309 // it will have the old (alloc time) attributes
310 flag |= PAG_READ|PAG_WRITE;
311 }
312 if(fdwProtect & PAGE_READONLY) flag |= PAG_READ;
313 if(fdwProtect & PAGE_NOACCESS) flag |= PAG_READ; //can't do this in OS/2
314 if(fdwProtect & PAGE_READWRITE) flag |= (PAG_READ | PAG_WRITE);
315 if(fdwProtect & PAGE_WRITECOPY) flag |= (PAG_READ | PAG_WRITE);
316
317 if(fdwProtect & PAGE_EXECUTE_READWRITE) flag |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
318 if(fdwProtect & PAGE_EXECUTE_READ) flag |= (PAG_EXECUTE | PAG_READ);
319 if(fdwProtect & PAGE_EXECUTE) flag |= PAG_EXECUTE;
320
321 if(fdwProtect & PAGE_GUARD) {
322 dprintf(("ERROR: PAGE_GUARD bit set for VirtualAlloc -> we don't support this right now!"));
323 flag |= PAG_GUARD;
324 }
325
326 //just do this if other options are used
327 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0)
328 {
329 dprintf(("VirtualAlloc: Unknown protection flags, default to read/write"));
330 flag |= PAG_READ | PAG_WRITE;
331 }
332
333 if(lpvAddress)
334 {
335 Win32MemMap *map;
336 ULONG offset, nrpages, accessflags = 0;
337
338 nrpages = cbSize >> PAGE_SHIFT;
339 if(cbSize & 0xFFF)
340 nrpages++;
341
342 if(flag & PAG_READ) {
343 accessflags |= MEMMAP_ACCESS_READ;
344 }
345 if(flag & PAG_WRITE) {
346 accessflags |= MEMMAP_ACCESS_WRITE;
347 }
348 if(flag & PAG_EXECUTE) {
349 accessflags |= MEMMAP_ACCESS_EXECUTE;
350 }
351 map = Win32MemMapView::findMapByView((ULONG)lpvAddress, &offset, accessflags);
352 if(map) {
353 //TODO: We don't allow protection flag changes for mmaped files now
354 map->commitPage(offset, FALSE, nrpages);
355 map->Release();
356 return lpvAddress;
357 }
358 }
359
360 // commit memory
361 if(fdwAllocationType & MEM_COMMIT)
362 {
363 Address = lpvAddress;
364
365 rc = OSLibDosSetMem(lpvAddress, cbSize, flag);
366
367 //might try to commit larger part with same base address
368 if(rc == OSLIB_ERROR_ACCESS_DENIED && cbSize > 4096 )
369 { //knut: AND more than one page
370 char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page!
371 ULONG size, os2flags;
372
373 while(newbase >= (char *)lpvAddress)
374 { //knut: should check first page to!!
375 size = 4096;
376 os2flags = 0;
377 rc = OSLibDosQueryMem(newbase, &size, &os2flags);
378 if(rc)
379 break;
380
381 if(os2flags & PAG_COMMIT)
382 {
383 newbase += 4096;
384 break;
385 }
386 newbase -= 4096;
387 }
388
389 if(rc == 0)
390 {
391 //In case it wants to commit bytes that fall into the last
392 //page of the previous commit command
393 if(cbSize > ((int)newbase - (int)lpvAddress))
394 rc = OSLibDosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag);
395 }
396 else return(NULL);
397 }
398 else
399 {
400 if(rc == OSLIB_ERROR_INVALID_ADDRESS) {
401 rc = OSLibDosAllocMem(&Address, cbSize, flag );
402 }
403 else {
404 if(rc) {
405 //check if the app tries to commit an already commited part of memory or change the protection flags
406 ULONG size = cbSize, os2flags, newrc;
407 newrc = OSLibDosQueryMem(lpvAddress, &size, &os2flags);
408 if(newrc == 0) {
409 if(size >= cbSize && (os2flags & PAG_COMMIT)) {
410 dprintf(("VirtualAlloc: commit on committed memory"));
411 if((flag & (PAG_READ|PAG_WRITE|PAG_EXECUTE)) != (os2flags & (PAG_READ|PAG_WRITE|PAG_EXECUTE)))
412 { //change protection flags
413 DWORD tmp;
414 if(VirtualProtect(lpvAddress, cbSize, fdwProtect, &tmp) == TRUE) {
415 return lpvAddress;
416 }
417 dprintf(("ERROR: VirtualAlloc: commit on committed memory -> VirtualProtect failed!!"));
418 return NULL;
419 }
420 //else everything ok
421 return lpvAddress;
422 }
423 else dprintf(("Unexpected DosSetMem error %x", rc));
424 }
425 else {
426 dprintf(("Unexpected DosQueryMem error %x", newrc));
427 }
428 }
429 }
430 }
431 }
432 else
433 {
434 rc = OSLibDosAllocMem(&Address, cbSize, flag);
435 }
436
437 if(rc)
438 {
439 dprintf(("DosSetMem returned %d\n", rc));
440 SetLastError( ERROR_OUTOFMEMORY );
441 return(NULL);
442 }
443
444 dprintf(("VirtualAlloc returned %X\n", Address));
445 return(Address);
446}
447//******************************************************************************
448//******************************************************************************
449BOOL WIN32API VirtualFree(LPVOID lpvAddress,
450 DWORD cbSize,
451 DWORD FreeType)
452{
453 DWORD rc;
454
455 SetLastError(ERROR_SUCCESS);
456
457 // verify parameters
458 if((FreeType & MEM_RELEASE) && (cbSize != 0))
459 {
460 dprintf(("WARNING: VirtualFree: invalid parameter!!"));
461 SetLastError(ERROR_INVALID_PARAMETER);
462 return(FALSE);
463 }
464
465 if((FreeType & MEM_DECOMMIT) && (FreeType & MEM_RELEASE))
466 {
467 dprintf(("WARNING: VirtualFree: invalid parameter!!"));
468 SetLastError(ERROR_INVALID_PARAMETER);
469 return(FALSE);
470 }
471
472 // decommit memory
473 if (FreeType & MEM_DECOMMIT)
474 {
475 // check if app wants to decommit stack pages -> don't allow that!
476 // (VAC runtime uses last stack page to store some internal
477 // data; if freed pe/pec will crash during exit)
478
479 TEB *teb = GetThreadTEB();
480 if(teb) {
481 DWORD stacktop = (DWORD)teb->stack_top;
482 DWORD stackbottom = (DWORD)teb->stack_low;
483
484 stackbottom = stackbottom & ~0xFFFF; //round down to 64kb boundary
485 stacktop = stacktop & ~0xFFF;
486
487 if(lpvAddress >= (PVOID)stackbottom && lpvAddress < (PVOID)stacktop) {
488 //pretend we did was was asked
489 dprintf(("WARNING: app tried to decommit stack pages; pretend success"));
490 return TRUE;
491 }
492 }
493 // decommit memory block
494 rc = OSLibDosSetMem(lpvAddress, cbSize, PAG_DECOMMIT);
495 if(rc)
496 {
497 if(rc == 32803) { //SvL: ERROR_ALIAS
498 dprintf(("KERNEL32:VirtualFree:OsLibSetMem rc = #%d; app tries to decommit aliased memory; ignore", rc));
499 return(TRUE);
500 }
501 dprintf(("KERNEL32:VirtualFree:OsLibSetMem rc = #%d\n", rc));
502 SetLastError(ERROR_INVALID_ADDRESS);
503 return(FALSE);
504 }
505 }
506
507 // release memory
508 if (FreeType & MEM_RELEASE)
509 {
510 rc = OSLibDosFreeMem(lpvAddress); // free the memory block
511 if(rc)
512 {
513 dprintf(("KERNEL32:VirtualFree:OsLibFreeMem rc = #%d\n", rc));
514 SetLastError(ERROR_INVALID_ADDRESS);
515 return(FALSE);
516 }
517 }
518 return TRUE;
519}
520//******************************************************************************
521//LPVOID lpvAddress; /* address of region of committed pages */
522//DWORD cbSize; /* size of the region */
523//DWORD fdwNewProtect; /* desired access protection */
524//PDWORD pfdwOldProtect; /* address of variable to get old protection */
525//TODO: Not 100% complete
526//TODO: SetLastError on failure
527//******************************************************************************
528
529BOOL WIN32API VirtualProtect(LPVOID lpvAddress,
530 DWORD cbSize,
531 DWORD fdwNewProtect,
532 DWORD* pfdwOldProtect)
533{
534 DWORD rc;
535 DWORD cb = cbSize;
536 ULONG pageFlags = 0;
537 int npages;
538
539 if(pfdwOldProtect == NULL) {
540 dprintf(("WARNING: pfdwOldProtect == NULL"));
541 SetLastError(ERROR_INVALID_PARAMETER);
542 return(FALSE);
543 }
544
545 SetLastError(ERROR_SUCCESS);
546
547 rc = OSLibDosQueryMem(lpvAddress, &cb, &pageFlags);
548 if(rc) {
549 dprintf(("DosQueryMem returned %d\n", rc));
550 return(FALSE);
551 }
552 dprintf(("Old memory flags %X\n", pageFlags));
553 *pfdwOldProtect = 0;
554 if(pageFlags & PAG_READ && !(pageFlags & PAG_WRITE))
555 *pfdwOldProtect |= PAGE_READONLY;
556 if(pageFlags & (PAG_WRITE))
557 *pfdwOldProtect |= PAGE_READWRITE;
558
559 if((pageFlags & (PAG_WRITE | PAG_EXECUTE)) == (PAG_WRITE | PAG_EXECUTE))
560 *pfdwOldProtect |= PAGE_EXECUTE_READWRITE;
561 else
562 if(pageFlags & PAG_EXECUTE)
563 *pfdwOldProtect |= PAGE_EXECUTE_READ;
564
565 if(pageFlags & PAG_GUARD)
566 *pfdwOldProtect |= PAGE_GUARD;
567 pageFlags = 0;
568
569 if(fdwNewProtect & PAGE_READONLY) pageFlags |= PAG_READ;
570 if(fdwNewProtect & PAGE_READWRITE) pageFlags |= (PAG_READ | PAG_WRITE);
571 if(fdwNewProtect & PAGE_WRITECOPY) pageFlags |= (PAG_READ | PAG_WRITE);
572 if(fdwNewProtect & PAGE_EXECUTE_READ) pageFlags |= (PAG_EXECUTE | PAG_READ);
573 if(fdwNewProtect & PAGE_EXECUTE_READWRITE)
574 pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
575 if(fdwNewProtect & PAGE_EXECUTE_WRITECOPY)
576 pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
577 if(fdwNewProtect & PAGE_GUARD) pageFlags |= PAG_GUARD;
578//Not supported in OS/2??
579// if(fdwNewProtect & PAGE_NOACCESS)
580
581 dprintf(("New memory flags %X\n", pageFlags));
582 if(pageFlags == 0) {
583 dprintf(("pageFlags == 0\n"));
584 return(TRUE); //nothing to do
585 }
586 ULONG offset = ((ULONG)lpvAddress & 0xFFF);
587 npages = (cbSize >> 12);
588
589 cb = (cbSize & 0xFFF) + offset; // !!! added, some optimization :)
590 if( cb > 0 ) { // changed
591 npages++;
592 }
593 if( cb > 4096 ) { // changed, note '>' sign ( not '>=' ) 4096 is exactly one page
594 npages++;
595 }
596
597 lpvAddress = (LPVOID)((int)lpvAddress & ~0xFFF);
598 cbSize = npages*4096;
599 dprintf(("lpvAddress = %X, cbSize = %d\n", lpvAddress, cbSize));
600
601 rc = OSLibDosSetMem(lpvAddress, cbSize, pageFlags);
602 if(rc) {
603 dprintf(("DosSetMem returned %d\n", rc));
604 return(FALSE);
605 }
606 return(TRUE);
607}
608//******************************************************************************
609//******************************************************************************
610DWORD WIN32API VirtualQuery(LPCVOID lpvAddress,
611 LPMEMORY_BASIC_INFORMATION pmbiBuffer,
612 DWORD cbLength)
613{
614 ULONG cbRangeSize, dAttr;
615 DWORD rc;
616 LPVOID lpBase;
617
618 SetLastError(ERROR_SUCCESS);
619
620 if(pmbiBuffer == NULL || cbLength != sizeof(MEMORY_BASIC_INFORMATION)) // check parameters
621 {
622 dprintf(("WARNING: invalid parameter"));
623 SetLastError(ERROR_INVALID_PARAMETER);
624 return 0; // nothing to return
625 }
626
627 // determine exact page range
628 lpBase = (LPVOID)((ULONG)lpvAddress & 0xFFFFF000);
629 cbRangeSize = -1;
630
631 rc = OSLibDosQueryMem(lpBase, &cbRangeSize, &dAttr);
632 if(rc)
633 {
634 dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n",
635 lpBase, cbLength, rc));
636 SetLastError(ERROR_INVALID_PARAMETER);
637 return 0;
638 }
639
640 memset(pmbiBuffer, 0, sizeof(MEMORY_BASIC_INFORMATION));
641
642 pmbiBuffer->BaseAddress = lpBase;
643 //round to next page boundary
644 pmbiBuffer->RegionSize = (cbRangeSize + 0xFFF) & 0xFFFFF000;
645
646 if(dAttr & PAG_READ && !(dAttr & PAG_WRITE))
647 pmbiBuffer->Protect |= PAGE_READONLY;
648
649 if(dAttr & PAG_WRITE)
650 pmbiBuffer->Protect |= PAGE_READWRITE;
651
652 if((dAttr & (PAG_WRITE | PAG_EXECUTE)) == (PAG_WRITE | PAG_EXECUTE))
653 pmbiBuffer->Protect |= PAGE_EXECUTE_READWRITE;
654 else
655 if(dAttr & PAG_EXECUTE)
656 pmbiBuffer->Protect |= PAGE_EXECUTE_READ;
657
658 if(dAttr & PAG_GUARD)
659 pmbiBuffer->Protect |= PAGE_GUARD;
660
661 if(dAttr & PAG_FREE)
662 pmbiBuffer->State = MEM_FREE;
663 else
664 if(dAttr & PAG_COMMIT)
665 pmbiBuffer->State = MEM_COMMIT;
666 else
667 pmbiBuffer->State = MEM_RESERVE;
668
669 //TODO: MEM_MAPPED & MEM_IMAGE (==SEC_IMAGE)
670 if(!(dAttr & PAG_SHARED))
671 pmbiBuffer->Type = MEM_PRIVATE;
672
673 // Pages can be committed but not necessarily accessible!!
674 if (!(dAttr & (PAG_READ | PAG_WRITE | PAG_EXECUTE | PAG_GUARD)))
675 pmbiBuffer->Protect = PAGE_NOACCESS;
676
677 //TODO: This is not correct: AllocationProtect should contain the protection
678 // flags used in the initial call to VirtualAlloc
679 pmbiBuffer->AllocationProtect = pmbiBuffer->Protect;
680 pmbiBuffer->AllocationBase = OSLibDosFindMemBase(lpBase);
681
682 dprintf(("Memory region alloc base 0x%08x", pmbiBuffer->AllocationBase));
683 dprintf(("Memory region alloc protect flags %x", pmbiBuffer->AllocationProtect));
684 dprintf(("Memory region base 0x%08x", pmbiBuffer->BaseAddress));
685 dprintf(("Memory region protect flags %x", pmbiBuffer->Protect));
686 dprintf(("Memory region region size 0x%08x", pmbiBuffer->RegionSize));
687 dprintf(("Memory region state 0x%08x", pmbiBuffer->State));
688 dprintf(("Memory region type 0x%08x", pmbiBuffer->Type));
689 return sizeof(MEMORY_BASIC_INFORMATION);
690}
691//******************************************************************************
692//******************************************************************************
693BOOL WIN32API VirtualLock(LPVOID lpAddress, DWORD dwSize)
694{
695 dprintf(("VirtualLock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
696 SetLastError(ERROR_SUCCESS);
697 return TRUE;
698}
699
700//******************************************************************************
701BOOL WIN32API VirtualUnlock(LPVOID lpAddress, DWORD dwSize)
702{
703 dprintf(("VirtualUnlock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
704 SetLastError(ERROR_SUCCESS);
705 return TRUE;
706}
707
708/*****************************************************************************
709 * Name : BOOL VirtualProtectEx
710 * Purpose : The VirtualProtectEx function changes the access protection on
711 * a region of committed pages in the virtual address space of a specified
712 * process. Note that this function differs from VirtualProtect,
713 * which changes the access protection on the calling process only.
714 * Parameters: HANDLE hProcess handle of process
715 * LPVOID lpvAddress address of region of committed pages
716 * DWORD cbSize size of region
717 * DWORD fdwNewProtect desired access protection
718 * PDWORD pfdwOldProtect address of variable to get old protection
719 * Variables :
720 * Result : size of target buffer
721 * Remark :
722 * Status : UNTESTED STUB
723 *
724 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
725 *****************************************************************************/
726
727BOOL WIN32API VirtualProtectEx(HANDLE hProcess,
728 LPVOID lpvAddress,
729 DWORD cbSize,
730 DWORD fdwNewProtect,
731 LPDWORD pfdwOldProtect)
732{
733 // only execute API, if this is the current process !
734 if (GetCurrentProcess() == hProcess)
735 return VirtualProtect(lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect);
736 else
737 {
738 SetLastError(ERROR_ACCESS_DENIED); // deny access to other processes
739 return FALSE;
740 }
741}
742
743
744/*****************************************************************************
745 * Name : DWORD VirtualQueryEx
746 * Purpose : The VirtualQueryEx function provides information about a range
747 * of pages within the virtual address space of a specified process.
748 * Parameters: HANDLE hProcess handle of process
749 * LPCVOID lpvAddress address of region
750 * LPMEMORY_BASIC_INFORMATION pmbiBuffer address of information buffer
751 * DWORD cbLength size of buffer
752 * Variables :
753 * Result : number of bytes returned in buffer
754 * Remark :
755 * Status : UNTESTED STUB
756 *
757 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
758 *****************************************************************************/
759
760DWORD WIN32API VirtualQueryEx(HANDLE hProcess,
761 LPCVOID lpvAddress,
762 LPMEMORY_BASIC_INFORMATION pmbiBuffer,
763 DWORD cbLength)
764{
765 // only execute API, if this is the current process !
766 if (GetCurrentProcess() == hProcess)
767 return VirtualQuery(lpvAddress, pmbiBuffer, cbLength);
768 else
769 {
770 SetLastError(ERROR_ACCESS_DENIED); // deny access to other processes
771 return FALSE;
772 }
773}
774
775//******************************************************************************
776//SvL: Private api
777//******************************************************************************
778LPVOID VirtualAllocShared(DWORD cbSize, DWORD fdwAllocationType,
779 DWORD fdwProtect, LPSTR name)
780{
781 LPVOID Address;
782 ULONG flag = 0, base;
783 DWORD rc;
784
785 dprintf(("VirtualAllocShared: %x %x %x %s", cbSize, fdwAllocationType, fdwProtect, name));
786
787 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */
788 {
789 dprintf(("VirtualAllocShared: size too large"));
790 SetLastError( ERROR_OUTOFMEMORY );
791 return NULL;
792 }
793
794 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||
795 (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
796 {
797 dprintf(("VirtualAllocShared: Invalid parameter"));
798 SetLastError( ERROR_INVALID_PARAMETER );
799 return NULL;
800 }
801
802 if(fdwAllocationType & MEM_COMMIT)
803 {
804 dprintf(("VirtualAllocShared: commit\n"));
805 flag = PAG_COMMIT;
806 }
807
808 if(fdwProtect & PAGE_READONLY) flag |= PAG_READ;
809 if(fdwProtect & PAGE_NOACCESS) flag |= PAG_READ; //can't do this in OS/2
810 if(fdwProtect & PAGE_READWRITE) flag |= (PAG_READ | PAG_WRITE);
811 if(fdwProtect & PAGE_WRITECOPY) flag |= (PAG_READ | PAG_WRITE);
812
813 if(fdwProtect & PAGE_EXECUTE_READWRITE) flag |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
814 if(fdwProtect & PAGE_EXECUTE_READ) flag |= (PAG_EXECUTE | PAG_READ);
815 if(fdwProtect & PAGE_EXECUTE) flag |= PAG_EXECUTE;
816
817 if(fdwProtect & PAGE_GUARD) {
818 dprintf(("ERROR: PAGE_GUARD bit set for VirtualAllocShared -> we don't support this right now!"));
819 flag |= PAG_GUARD;
820 }
821
822 //just do this if other options are used
823 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0)
824 {
825 dprintf(("VirtualAllocShared: Unknown protection flags, default to read/write"));
826 flag |= PAG_READ | PAG_WRITE;
827 }
828
829 rc = OSLibDosAllocSharedMem(&Address, cbSize, flag, name);
830
831 if(rc)
832 {
833 dprintf(("DosAllocSharedMem returned %d\n", rc));
834 SetLastError( ERROR_OUTOFMEMORY );
835 return(NULL);
836 }
837
838 dprintf(("VirtualAllocShared returned %X\n", Address));
839 return(Address);
840}
Note: See TracBrowser for help on using the repository browser.