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

Last change on this file since 9971 was 9971, checked in by sandervl, 22 years ago

PF: Corrected HFILE definition as it is in Wine and in Win2k

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