source: trunk/src/kernel32/virtual.cpp

Last change on this file was 21980, checked in by dmik, 13 years ago

kernel32: Support guard page exceptions.

This is in particular necessary for Java yellow and red zone
implementations.

Coses #76.

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