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

Last change on this file since 7334 was 7334, checked in by phaller, 24 years ago

replaced heap alloc by stack alloc

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