source: branches/gcc-kmk/src/kernel32/virtual.cpp@ 21720

Last change on this file since 21720 was 21720, checked in by dmik, 13 years ago

Replace "\" with "/" in include statements.

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