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

Last change on this file since 6823 was 6693, checked in by sandervl, 24 years ago

VirtualQuery fix (region size must be round up to next page boundary)

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