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

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

VirtualFree; don't allow app to decommit stack pages (VAC runtime uses last stack page to store some internal data; if freed pe/pec will crash during exit)

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