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

Last change on this file since 21587 was 21587, checked in by dmik, 14 years ago

kernel32: VirtualQuery: Succeed with MEM_FREE for one page when querying
an unallocated address in the private arena (for which DosQueryMem fails
with ERROR_INVALID_ADDRESS).

File size: 31.5 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 if(fdwAllocationType & MEM_RESERVE) {
395 //SvL: DosRead crashes if memory is initially reserved with write
396 // access disabled (OS/2 bug) even if the commit sets the page
397 // flags to read/write:
398 // DosSetMem does not alter the 16 bit selectors so if you change memory
399 // attributes and then access the memory with a 16 bit API (such as DosRead),
400 // it will have the old (alloc time) attributes
401 flag |= PAG_READ|PAG_WRITE;
402 }
403
404 //just do this if other options are used
405 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0)
406 {
407 dprintf(("VirtualAlloc: Unknown protection flags, default to read/write"));
408 flag |= PAG_READ | PAG_WRITE;
409 }
410
411 if(lpvAddress)
412 {
413 Win32MemMap *map;
414 ULONG offset, nrpages, accessflags = 0;
415
416 nrpages = cbSize >> PAGE_SHIFT;
417 if(cbSize & 0xFFF)
418 nrpages++;
419
420 if(flag & PAG_READ) {
421 accessflags |= MEMMAP_ACCESS_READ;
422 }
423 if(flag & PAG_WRITE) {
424 accessflags |= MEMMAP_ACCESS_WRITE;
425 }
426 if(flag & PAG_EXECUTE) {
427 accessflags |= MEMMAP_ACCESS_EXECUTE;
428 }
429 map = Win32MemMapView::findMapByView((ULONG)lpvAddress, &offset, accessflags);
430 if(map) {
431 //TODO: We don't allow protection flag changes for mmaped files now
432 map->commitPage((ULONG)lpvAddress, offset, FALSE, nrpages);
433 map->Release();
434 return lpvAddress;
435 }
436 /* trying to allocate memory at specified address */
437 if(fdwAllocationType & MEM_RESERVE)
438 {
439 rc = OSLibDosAllocMem(&Address, cbSize, flag |OBJ_LOCSPECIFIC);
440 dprintf(("Allocation at specified address: %x. rc: %i", Address, rc));
441 if (rc)
442 {
443 SetLastError(ERROR_OUTOFMEMORY);
444 return NULL;
445 }
446 dprintf(("Allocated at specified address: %x. rc: %i", Address, rc));
447 return(Address);
448 }
449 }
450
451 // commit memory
452 if(fdwAllocationType & MEM_COMMIT)
453 {
454 Address = lpvAddress;
455
456 //try to commit the pages
457 rc = OSLibDosSetMem(lpvAddress, cbSize, flag);
458
459 //might try to commit larger part with same base address
460 if(rc == OSLIB_ERROR_ACCESS_DENIED && cbSize > PAGE_SIZE )
461 {
462 while(cbSize)
463 {
464 //check if the app tries to commit an already commited part of memory or change the protection flags
465 ULONG size = cbSize, os2flags, newrc;
466 newrc = OSLibDosQueryMem(lpvAddress, &size, &os2flags);
467 if(newrc == 0)
468 {
469 if(os2flags & PAG_COMMIT)
470 {
471 dprintf(("VirtualAlloc: commit on committed memory"));
472 if((flag & (PAG_READ|PAG_WRITE|PAG_EXECUTE)) != (os2flags & (PAG_READ|PAG_WRITE|PAG_EXECUTE)))
473 { //change protection flags
474 DWORD tmp;
475 if(VirtualProtect(lpvAddress, size, fdwProtect, &tmp) == FALSE)
476 {
477 dprintf(("ERROR: VirtualAlloc: commit on committed memory -> VirtualProtect failed!!"));
478 return NULL;
479 }
480 }
481 }
482 else
483 { //commit this page (or range of pages)
484 rc = OSLibDosSetMem(lpvAddress, size, flag);
485 if(rc) {
486 dprintf(("Unexpected DosSetMem error %x", rc));
487 break;
488 }
489 }
490 }
491 else {
492 dprintf(("Unexpected DosQueryMem error %x", newrc));
493 rc = newrc;
494 break;
495 }
496 cbSize -= size;
497
498 lpvAddress = (LPVOID)((char *)lpvAddress + size);
499 }//while(cbSize)
500
501 rc = 0; //success
502 }
503 else
504 {
505 if(rc == OSLIB_ERROR_INVALID_ADDRESS) {
506 rc = OSLibDosAllocMem(&Address, cbSize, flag );
507 }
508 else {
509 if(rc) {
510 //check if the app tries to commit an already commited part of memory or change the protection flags
511 ULONG size = cbSize, os2flags, newrc;
512 newrc = OSLibDosQueryMem(lpvAddress, &size, &os2flags);
513 if(newrc == 0) {
514 if(size >= cbSize && (os2flags & PAG_COMMIT)) {
515 dprintf(("VirtualAlloc: commit on committed memory"));
516 if((flag & (PAG_READ|PAG_WRITE|PAG_EXECUTE)) != (os2flags & (PAG_READ|PAG_WRITE|PAG_EXECUTE)))
517 { //change protection flags
518 DWORD tmp;
519 if(VirtualProtect(lpvAddress, cbSize, fdwProtect, &tmp) == TRUE) {
520 return lpvAddress;
521 }
522 dprintf(("ERROR: VirtualAlloc: commit on committed memory -> VirtualProtect failed!!"));
523 return NULL;
524 }
525 //else everything ok
526 return lpvAddress;
527 }
528 else dprintf(("Unexpected DosSetMem error %x", rc));
529 }
530 else {
531 dprintf(("Unexpected DosQueryMem error %x", newrc));
532 }
533 }
534 }
535 }
536 }
537 else
538 {
539 rc = OSLibDosAllocMem(&Address, cbSize, flag);
540 }
541
542 if(rc)
543 {
544 dprintf(("DosSetMem returned %d\n", rc));
545 SetLastError( ERROR_OUTOFMEMORY );
546 return(NULL);
547 }
548
549 dprintf(("VirtualAlloc returned %X\n", Address));
550 return(Address);
551}
552//******************************************************************************
553//NOTE: Do NOT set the last error to ERROR_SUCCESS if successful. Windows
554// does not do this either!
555//******************************************************************************
556BOOL WIN32API VirtualFree(LPVOID lpvAddress,
557 DWORD cbSize,
558 DWORD FreeType)
559{
560 DWORD rc;
561
562 // verify parameters
563 if((FreeType & MEM_RELEASE) && (cbSize != 0))
564 {
565 dprintf(("WARNING: VirtualFree: invalid parameter!!"));
566 SetLastError(ERROR_INVALID_PARAMETER);
567 return(FALSE);
568 }
569
570 if((FreeType & MEM_DECOMMIT) && (FreeType & MEM_RELEASE))
571 {
572 dprintf(("WARNING: VirtualFree: invalid parameter!!"));
573 SetLastError(ERROR_INVALID_PARAMETER);
574 return(FALSE);
575 }
576
577 /* Assuming that we don't allocate memory in the first 64kb. */
578 if ((unsigned)lpvAddress < 0x10000)
579 {
580 if (!lpvAddress)
581 dprintf(("WARNING: VirtualFree: bogus address %p!!", lpvAddress));
582 SetLastError(ERROR_INVALID_ADDRESS);
583 return FALSE;
584 }
585
586 // decommit memory
587 if (FreeType & MEM_DECOMMIT)
588 {
589 // check if app wants to decommit stack pages -> don't allow that!
590 // (VAC runtime uses last stack page to store some internal
591 // data; if freed pe/pec will crash during exit)
592
593 TEB *teb = GetThreadTEB();
594 if(teb) {
595 DWORD stacktop = (DWORD)teb->stack_top;
596 DWORD stackbottom = (DWORD)teb->stack_low;
597
598 stackbottom = stackbottom & ~0xFFFF; //round down to 64kb boundary
599 stacktop = stacktop & ~0xFFF;
600
601 if(lpvAddress >= (PVOID)stackbottom && lpvAddress < (PVOID)stacktop) {
602 //pretend we did was was asked
603 dprintf(("WARNING: app tried to decommit stack pages; pretend success"));
604 return TRUE;
605 }
606 }
607 // decommit memory block
608 rc = OSLibDosSetMem(lpvAddress, cbSize, PAG_DECOMMIT);
609 if(rc)
610 {
611 if(rc == 32803) { //SvL: ERROR_ALIAS
612 dprintf(("KERNEL32:VirtualFree:OsLibSetMem rc = #%d; app tries to decommit aliased memory; ignore", rc));
613 return(TRUE);
614 }
615 dprintf(("KERNEL32:VirtualFree:OsLibSetMem rc = #%d\n", rc));
616 SetLastError(ERROR_INVALID_ADDRESS);
617 return(FALSE);
618 }
619 }
620
621 // release memory
622 if (FreeType & MEM_RELEASE)
623 {
624 rc = OSLibDosFreeMem(lpvAddress); // free the memory block
625 if(rc)
626 {
627 dprintf(("KERNEL32:VirtualFree:OsLibFreeMem rc = #%d\n", rc));
628 SetLastError(ERROR_INVALID_ADDRESS);
629 return(FALSE);
630 }
631 }
632 return TRUE;
633}
634//******************************************************************************
635//LPVOID lpvAddress; /* address of region of committed pages */
636//DWORD cbSize; /* size of the region */
637//DWORD fdwNewProtect; /* desired access protection */
638//PDWORD pfdwOldProtect; /* address of variable to get old protection */
639//TODO: Not 100% complete
640//TODO: SetLastError on failure
641//******************************************************************************
642
643BOOL WIN32API VirtualProtect(LPVOID lpvAddress,
644 DWORD cbSize,
645 DWORD fdwNewProtect,
646 DWORD* pfdwOldProtect)
647{
648 DWORD rc;
649 DWORD cb = cbSize;
650 ULONG pageFlags = 0;
651 int npages;
652
653 if(pfdwOldProtect == NULL) {
654 dprintf(("WARNING: pfdwOldProtect == NULL"));
655 SetLastError(ERROR_INVALID_PARAMETER);
656 return(FALSE);
657 }
658
659 SetLastError(ERROR_SUCCESS);
660
661 rc = OSLibDosQueryMem(lpvAddress, &cb, &pageFlags);
662 if(rc) {
663 dprintf(("DosQueryMem returned %d\n", rc));
664 return(FALSE);
665 }
666 dprintf(("Old memory flags %X\n", pageFlags));
667 TranslateOS2PageAttr(pageFlags, pfdwOldProtect, NULL, NULL);
668
669 TranslateWinPageAttr(fdwNewProtect, &pageFlags);
670
671 dprintf(("New memory flags %X\n", pageFlags));
672 if(pageFlags == 0) {
673 dprintf(("pageFlags == 0\n"));
674 return(TRUE); //nothing to do
675 }
676 ULONG offset = ((ULONG)lpvAddress & 0xFFF);
677 npages = (cbSize >> 12);
678
679 cb = (cbSize & 0xFFF) + offset; // !!! added, some optimization :)
680 if( cb > 0 ) { // changed
681 npages++;
682 }
683 if( cb > 4096 ) { // changed, note '>' sign ( not '>=' ) 4096 is exactly one page
684 npages++;
685 }
686
687 lpvAddress = (LPVOID)((int)lpvAddress & ~0xFFF);
688 cbSize = npages*4096;
689 dprintf(("lpvAddress = %X, cbSize = %d\n", lpvAddress, cbSize));
690
691 rc = OSLibDosSetMem(lpvAddress, cbSize, pageFlags);
692 if(rc) {
693 dprintf(("DosSetMem returned %d\n", rc));
694 return(FALSE);
695 }
696 return(TRUE);
697}
698//******************************************************************************
699//******************************************************************************
700DWORD WIN32API VirtualQuery(LPCVOID lpvAddress,
701 LPMEMORY_BASIC_INFORMATION pmbiBuffer,
702 DWORD cbLength)
703{
704 ULONG cbRangeSize, dAttr;
705 DWORD rc;
706 LPVOID lpBase;
707
708 SetLastError(ERROR_SUCCESS);
709
710 if(pmbiBuffer == NULL || cbLength != sizeof(MEMORY_BASIC_INFORMATION)) // check parameters
711 {
712 dprintf(("WARNING: invalid parameter"));
713 SetLastError(ERROR_INVALID_PARAMETER);
714 return 0; // nothing to return
715 }
716
717 // determine exact page range
718 lpBase = (LPVOID)((ULONG)lpvAddress & 0xFFFFF000);
719 cbRangeSize = -1;
720
721 rc = OSLibDosQueryMem(lpBase, &cbRangeSize, &dAttr);
722 if(rc==487)
723 {
724 // On OS/2, ERROR_INVALID_ADDRESS (478) is returned for unallocated or
725 // freed private memory (for unallocated shared memory DosQueryMem
726 // succeeds with PAG_FREE). However on Windows (per MSDN), VirtualQuery
727 // succeeds with MEM_FREE for any address that is within the addressable
728 // space of the process. Provide a rough simulation here.
729
730 dprintf(("WARNING: VirtualQuery: OSLibDosQueryMem(0x%08X,%d) returned %d, "
731 "returning MEM_FREE for one page!",
732 lpBase, cbLength, rc));
733
734 memset(pmbiBuffer, 0, sizeof(MEMORY_BASIC_INFORMATION));
735 pmbiBuffer->BaseAddress = lpBase;
736 pmbiBuffer->RegionSize = 0x1000;
737 pmbiBuffer->State = MEM_FREE;
738 return sizeof(MEMORY_BASIC_INFORMATION);
739 }
740 if(rc)
741 {
742 dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n",
743 lpBase, cbLength, rc));
744 SetLastError(ERROR_INVALID_PARAMETER);
745 return 0;
746 }
747
748 memset(pmbiBuffer, 0, sizeof(MEMORY_BASIC_INFORMATION));
749
750 pmbiBuffer->BaseAddress = lpBase;
751 //round to next page boundary
752 pmbiBuffer->RegionSize = (cbRangeSize + 0xFFF) & 0xFFFFF000;
753
754 TranslateOS2PageAttr(dAttr, &pmbiBuffer->Protect, &pmbiBuffer->State, &pmbiBuffer->Type);
755
756 //TODO: This is not correct: AllocationProtect should contain the protection
757 // flags used in the initial call to VirtualAlloc
758 pmbiBuffer->AllocationProtect = pmbiBuffer->Protect;
759 pmbiBuffer->AllocationBase = OSLibDosFindMemBase(lpBase, &dAttr);
760 if(dAttr) {
761 TranslateOS2PageAttr(dAttr, &pmbiBuffer->AllocationProtect, NULL, NULL);
762 }
763#if 0
764 dprintf(("Memory region alloc base 0x%08x", pmbiBuffer->AllocationBase));
765 dprintf(("Memory region alloc protect flags %x", pmbiBuffer->AllocationProtect));
766 dprintf(("Memory region base 0x%08x", pmbiBuffer->BaseAddress));
767 dprintf(("Memory region protect flags %x", pmbiBuffer->Protect));
768 dprintf(("Memory region region size 0x%08x", pmbiBuffer->RegionSize));
769 dprintf(("Memory region state 0x%08x", pmbiBuffer->State));
770 dprintf(("Memory region type 0x%08x", pmbiBuffer->Type));
771#endif
772 return sizeof(MEMORY_BASIC_INFORMATION);
773}
774//******************************************************************************
775//******************************************************************************
776BOOL WIN32API VirtualLock(LPVOID lpAddress, DWORD dwSize)
777{
778 dprintf(("VirtualLock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
779 SetLastError(ERROR_SUCCESS);
780 return TRUE;
781}
782//******************************************************************************
783//******************************************************************************
784BOOL WIN32API VirtualUnlock(LPVOID lpAddress, DWORD dwSize)
785{
786 dprintf(("VirtualUnlock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
787 SetLastError(ERROR_SUCCESS);
788 return TRUE;
789}
790
791/*****************************************************************************
792 * Name : BOOL VirtualProtectEx
793 * Purpose : The VirtualProtectEx function changes the access protection on
794 * a region of committed pages in the virtual address space of a specified
795 * process. Note that this function differs from VirtualProtect,
796 * which changes the access protection on the calling process only.
797 * Parameters: HANDLE hProcess handle of process
798 * LPVOID lpvAddress address of region of committed pages
799 * DWORD cbSize size of region
800 * DWORD fdwNewProtect desired access protection
801 * PDWORD pfdwOldProtect address of variable to get old protection
802 * Variables :
803 * Result : size of target buffer
804 * Remark :
805 * Status : UNTESTED STUB
806 *
807 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
808 *****************************************************************************/
809
810BOOL WIN32API VirtualProtectEx(HANDLE hProcess,
811 LPVOID lpvAddress,
812 DWORD cbSize,
813 DWORD fdwNewProtect,
814 LPDWORD pfdwOldProtect)
815{
816 // only execute API, if this is the current process !
817 if (GetCurrentProcess() == hProcess)
818 return VirtualProtect(lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect);
819 else
820 {
821 SetLastError(ERROR_ACCESS_DENIED); // deny access to other processes
822 return FALSE;
823 }
824}
825
826
827/*****************************************************************************
828 * Name : DWORD VirtualQueryEx
829 * Purpose : The VirtualQueryEx function provides information about a range
830 * of pages within the virtual address space of a specified process.
831 * Parameters: HANDLE hProcess handle of process
832 * LPCVOID lpvAddress address of region
833 * LPMEMORY_BASIC_INFORMATION pmbiBuffer address of information buffer
834 * DWORD cbLength size of buffer
835 * Variables :
836 * Result : number of bytes returned in buffer
837 * Remark :
838 * Status : UNTESTED STUB
839 *
840 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
841 *****************************************************************************/
842
843DWORD WIN32API VirtualQueryEx(HANDLE hProcess,
844 LPCVOID lpvAddress,
845 LPMEMORY_BASIC_INFORMATION pmbiBuffer,
846 DWORD cbLength)
847{
848 // only execute API, if this is the current process !
849 if (GetCurrentProcess() == hProcess)
850 return VirtualQuery(lpvAddress, pmbiBuffer, cbLength);
851 else
852 {
853 SetLastError(ERROR_ACCESS_DENIED); // deny access to other processes
854 return FALSE;
855 }
856}
857
858//******************************************************************************
859// Private Odin api
860//******************************************************************************
861LPVOID VirtualAllocShared(DWORD cbSize, DWORD fdwAllocationType,
862 DWORD fdwProtect, LPSTR name)
863{
864 LPVOID Address;
865 ULONG flag = 0, base;
866 DWORD rc;
867
868 dprintf(("VirtualAllocShared: %x %x %x %s", cbSize, fdwAllocationType, fdwProtect, name));
869
870 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */
871 {
872 dprintf(("VirtualAllocShared: size too large"));
873 SetLastError( ERROR_OUTOFMEMORY );
874 return NULL;
875 }
876
877 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||
878 (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
879 {
880 dprintf(("VirtualAllocShared: Invalid parameter"));
881 SetLastError( ERROR_INVALID_PARAMETER );
882 return NULL;
883 }
884
885 //Translate windows page attributes (flag is reset to 0!!)
886 TranslateWinPageAttr(fdwProtect, &flag);
887
888 if(fdwAllocationType & MEM_COMMIT)
889 {
890 dprintf(("VirtualAllocShared: commit\n"));
891 flag |= PAG_COMMIT;
892 }
893
894 //just do this if other options are used
895 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0)
896 {
897 dprintf(("VirtualAllocShared: Unknown protection flags, default to read/write"));
898 flag |= PAG_READ | PAG_WRITE;
899 }
900
901 rc = OSLibDosAllocSharedMem(&Address, cbSize, flag, name);
902
903 if(rc)
904 {
905 dprintf(("DosAllocSharedMem returned %d\n", rc));
906 SetLastError( ERROR_OUTOFMEMORY );
907 return(NULL);
908 }
909
910 dprintf(("VirtualAllocShared returned %X\n", Address));
911 return(Address);
912}
913//******************************************************************************
914//******************************************************************************
Note: See TracBrowser for help on using the repository browser.