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

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

Rewrote algorithm for 64kb alignment in VirtualAlloc'ed memory; allocation changes for heap (in 64kb chunks) & PE image (align at 64kb)

File size: 28.1 KB
Line 
1/* $Id: virtual.cpp,v 1.48 2002-07-15 14:28:52 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 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 pmbiBuffer->AllocationBase = OSLibDosFindMemBase(lpBase);
668
669 dprintf(("Memory region alloc base 0x%08x", pmbiBuffer->AllocationBase));
670 dprintf(("Memory region alloc protect flags %x", pmbiBuffer->AllocationProtect));
671 dprintf(("Memory region base 0x%08x", pmbiBuffer->BaseAddress));
672 dprintf(("Memory region protect flags %x", pmbiBuffer->Protect));
673 dprintf(("Memory region region size 0x%08x", pmbiBuffer->RegionSize));
674 dprintf(("Memory region state 0x%08x", pmbiBuffer->State));
675 dprintf(("Memory region type 0x%08x", pmbiBuffer->Type));
676 return sizeof(MEMORY_BASIC_INFORMATION);
677}
678//******************************************************************************
679//******************************************************************************
680BOOL WIN32API VirtualLock(LPVOID lpAddress, DWORD dwSize)
681{
682 dprintf(("VirtualLock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
683 SetLastError(ERROR_SUCCESS);
684 return TRUE;
685}
686
687//******************************************************************************
688BOOL WIN32API VirtualUnlock(LPVOID lpAddress, DWORD dwSize)
689{
690 dprintf(("VirtualUnlock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
691 SetLastError(ERROR_SUCCESS);
692 return TRUE;
693}
694
695/*****************************************************************************
696 * Name : BOOL VirtualProtectEx
697 * Purpose : The VirtualProtectEx function changes the access protection on
698 * a region of committed pages in the virtual address space of a specified
699 * process. Note that this function differs from VirtualProtect,
700 * which changes the access protection on the calling process only.
701 * Parameters: HANDLE hProcess handle of process
702 * LPVOID lpvAddress address of region of committed pages
703 * DWORD cbSize size of region
704 * DWORD fdwNewProtect desired access protection
705 * PDWORD pfdwOldProtect address of variable to get old protection
706 * Variables :
707 * Result : size of target buffer
708 * Remark :
709 * Status : UNTESTED STUB
710 *
711 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
712 *****************************************************************************/
713
714BOOL WIN32API VirtualProtectEx(HANDLE hProcess,
715 LPVOID lpvAddress,
716 DWORD cbSize,
717 DWORD fdwNewProtect,
718 LPDWORD pfdwOldProtect)
719{
720 // only execute API, if this is the current process !
721 if (GetCurrentProcess() == hProcess)
722 return VirtualProtect(lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect);
723 else
724 {
725 SetLastError(ERROR_ACCESS_DENIED); // deny access to other processes
726 return FALSE;
727 }
728}
729
730
731/*****************************************************************************
732 * Name : DWORD VirtualQueryEx
733 * Purpose : The VirtualQueryEx function provides information about a range
734 * of pages within the virtual address space of a specified process.
735 * Parameters: HANDLE hProcess handle of process
736 * LPCVOID lpvAddress address of region
737 * LPMEMORY_BASIC_INFORMATION pmbiBuffer address of information buffer
738 * DWORD cbLength size of buffer
739 * Variables :
740 * Result : number of bytes returned in buffer
741 * Remark :
742 * Status : UNTESTED STUB
743 *
744 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
745 *****************************************************************************/
746
747DWORD WIN32API VirtualQueryEx(HANDLE hProcess,
748 LPCVOID lpvAddress,
749 LPMEMORY_BASIC_INFORMATION pmbiBuffer,
750 DWORD cbLength)
751{
752 // only execute API, if this is the current process !
753 if (GetCurrentProcess() == hProcess)
754 return VirtualQuery(lpvAddress, pmbiBuffer, cbLength);
755 else
756 {
757 SetLastError(ERROR_ACCESS_DENIED); // deny access to other processes
758 return FALSE;
759 }
760}
761
762//******************************************************************************
763//SvL: Private api
764//******************************************************************************
765LPVOID VirtualAllocShared(DWORD cbSize, DWORD fdwAllocationType,
766 DWORD fdwProtect, LPSTR name)
767{
768 LPVOID Address;
769 ULONG flag = 0, base;
770 DWORD rc;
771
772 dprintf(("VirtualAllocShared: %x %x %x %s", cbSize, fdwAllocationType, fdwProtect, name));
773
774 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */
775 {
776 dprintf(("VirtualAllocShared: size too large"));
777 SetLastError( ERROR_OUTOFMEMORY );
778 return NULL;
779 }
780
781 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||
782 (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
783 {
784 dprintf(("VirtualAllocShared: Invalid parameter"));
785 SetLastError( ERROR_INVALID_PARAMETER );
786 return NULL;
787 }
788
789 if(fdwAllocationType & MEM_COMMIT)
790 {
791 dprintf(("VirtualAllocShared: commit\n"));
792 flag = PAG_COMMIT;
793 }
794
795 if(fdwProtect & PAGE_READONLY) flag |= PAG_READ;
796 if(fdwProtect & PAGE_NOACCESS) flag |= PAG_READ; //can't do this in OS/2
797 if(fdwProtect & PAGE_READWRITE) flag |= (PAG_READ | PAG_WRITE);
798 if(fdwProtect & PAGE_WRITECOPY) flag |= (PAG_READ | PAG_WRITE);
799
800 if(fdwProtect & PAGE_EXECUTE_READWRITE) flag |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
801 if(fdwProtect & PAGE_EXECUTE_READ) flag |= (PAG_EXECUTE | PAG_READ);
802 if(fdwProtect & PAGE_EXECUTE) flag |= PAG_EXECUTE;
803
804 if(fdwProtect & PAGE_GUARD) {
805 dprintf(("ERROR: PAGE_GUARD bit set for VirtualAllocShared -> we don't support this right now!"));
806 flag |= PAG_GUARD;
807 }
808
809 //just do this if other options are used
810 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0)
811 {
812 dprintf(("VirtualAllocShared: Unknown protection flags, default to read/write"));
813 flag |= PAG_READ | PAG_WRITE;
814 }
815
816 rc = OSLibDosAllocSharedMem(&Address, cbSize, flag, name);
817
818 if(rc)
819 {
820 dprintf(("DosAllocSharedMem returned %d\n", rc));
821 SetLastError( ERROR_OUTOFMEMORY );
822 return(NULL);
823 }
824
825 dprintf(("VirtualAllocShared returned %X\n", Address));
826 return(Address);
827}
Note: See TracBrowser for help on using the repository browser.