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

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

Fixed stack address detection in VirtualFree

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