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

Last change on this file since 21339 was 21339, checked in by vladest, 16 years ago
  1. Attempt to add support for DosAllocMem at specific address
  2. Fixed crashes in Handle manager when its tries to access non initialized pointer
File size: 30.9 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 dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d, REMOVING ERROR!\n",
725 lpBase, cbLength, rc));
726 SetLastError(0);
727 return 0;
728 }
729 if(rc)
730 {
731 dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n",
732 lpBase, cbLength, rc));
733 SetLastError(ERROR_INVALID_PARAMETER);
734 return 0;
735 }
736
737 memset(pmbiBuffer, 0, sizeof(MEMORY_BASIC_INFORMATION));
738
739 pmbiBuffer->BaseAddress = lpBase;
740 //round to next page boundary
741 pmbiBuffer->RegionSize = (cbRangeSize + 0xFFF) & 0xFFFFF000;
742
743 TranslateOS2PageAttr(dAttr, &pmbiBuffer->Protect, &pmbiBuffer->State, &pmbiBuffer->Type);
744
745 //TODO: This is not correct: AllocationProtect should contain the protection
746 // flags used in the initial call to VirtualAlloc
747 pmbiBuffer->AllocationProtect = pmbiBuffer->Protect;
748 pmbiBuffer->AllocationBase = OSLibDosFindMemBase(lpBase, &dAttr);
749 if(dAttr) {
750 TranslateOS2PageAttr(dAttr, &pmbiBuffer->AllocationProtect, NULL, NULL);
751 }
752 dprintf(("Memory region alloc base 0x%08x", pmbiBuffer->AllocationBase));
753 dprintf(("Memory region alloc protect flags %x", pmbiBuffer->AllocationProtect));
754 dprintf(("Memory region base 0x%08x", pmbiBuffer->BaseAddress));
755 dprintf(("Memory region protect flags %x", pmbiBuffer->Protect));
756 dprintf(("Memory region region size 0x%08x", pmbiBuffer->RegionSize));
757 dprintf(("Memory region state 0x%08x", pmbiBuffer->State));
758 dprintf(("Memory region type 0x%08x", pmbiBuffer->Type));
759 return sizeof(MEMORY_BASIC_INFORMATION);
760}
761//******************************************************************************
762//******************************************************************************
763BOOL WIN32API VirtualLock(LPVOID lpAddress, DWORD dwSize)
764{
765 dprintf(("VirtualLock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
766 SetLastError(ERROR_SUCCESS);
767 return TRUE;
768}
769//******************************************************************************
770//******************************************************************************
771BOOL WIN32API VirtualUnlock(LPVOID lpAddress, DWORD dwSize)
772{
773 dprintf(("VirtualUnlock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
774 SetLastError(ERROR_SUCCESS);
775 return TRUE;
776}
777
778/*****************************************************************************
779 * Name : BOOL VirtualProtectEx
780 * Purpose : The VirtualProtectEx function changes the access protection on
781 * a region of committed pages in the virtual address space of a specified
782 * process. Note that this function differs from VirtualProtect,
783 * which changes the access protection on the calling process only.
784 * Parameters: HANDLE hProcess handle of process
785 * LPVOID lpvAddress address of region of committed pages
786 * DWORD cbSize size of region
787 * DWORD fdwNewProtect desired access protection
788 * PDWORD pfdwOldProtect address of variable to get old protection
789 * Variables :
790 * Result : size of target buffer
791 * Remark :
792 * Status : UNTESTED STUB
793 *
794 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
795 *****************************************************************************/
796
797BOOL WIN32API VirtualProtectEx(HANDLE hProcess,
798 LPVOID lpvAddress,
799 DWORD cbSize,
800 DWORD fdwNewProtect,
801 LPDWORD pfdwOldProtect)
802{
803 // only execute API, if this is the current process !
804 if (GetCurrentProcess() == hProcess)
805 return VirtualProtect(lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect);
806 else
807 {
808 SetLastError(ERROR_ACCESS_DENIED); // deny access to other processes
809 return FALSE;
810 }
811}
812
813
814/*****************************************************************************
815 * Name : DWORD VirtualQueryEx
816 * Purpose : The VirtualQueryEx function provides information about a range
817 * of pages within the virtual address space of a specified process.
818 * Parameters: HANDLE hProcess handle of process
819 * LPCVOID lpvAddress address of region
820 * LPMEMORY_BASIC_INFORMATION pmbiBuffer address of information buffer
821 * DWORD cbLength size of buffer
822 * Variables :
823 * Result : number of bytes returned in buffer
824 * Remark :
825 * Status : UNTESTED STUB
826 *
827 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
828 *****************************************************************************/
829
830DWORD WIN32API VirtualQueryEx(HANDLE hProcess,
831 LPCVOID lpvAddress,
832 LPMEMORY_BASIC_INFORMATION pmbiBuffer,
833 DWORD cbLength)
834{
835 // only execute API, if this is the current process !
836 if (GetCurrentProcess() == hProcess)
837 return VirtualQuery(lpvAddress, pmbiBuffer, cbLength);
838 else
839 {
840 SetLastError(ERROR_ACCESS_DENIED); // deny access to other processes
841 return FALSE;
842 }
843}
844
845//******************************************************************************
846// Private Odin api
847//******************************************************************************
848LPVOID VirtualAllocShared(DWORD cbSize, DWORD fdwAllocationType,
849 DWORD fdwProtect, LPSTR name)
850{
851 LPVOID Address;
852 ULONG flag = 0, base;
853 DWORD rc;
854
855 dprintf(("VirtualAllocShared: %x %x %x %s", cbSize, fdwAllocationType, fdwProtect, name));
856
857 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */
858 {
859 dprintf(("VirtualAllocShared: size too large"));
860 SetLastError( ERROR_OUTOFMEMORY );
861 return NULL;
862 }
863
864 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||
865 (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
866 {
867 dprintf(("VirtualAllocShared: Invalid parameter"));
868 SetLastError( ERROR_INVALID_PARAMETER );
869 return NULL;
870 }
871
872 //Translate windows page attributes (flag is reset to 0!!)
873 TranslateWinPageAttr(fdwProtect, &flag);
874
875 if(fdwAllocationType & MEM_COMMIT)
876 {
877 dprintf(("VirtualAllocShared: commit\n"));
878 flag |= PAG_COMMIT;
879 }
880
881 //just do this if other options are used
882 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0)
883 {
884 dprintf(("VirtualAllocShared: Unknown protection flags, default to read/write"));
885 flag |= PAG_READ | PAG_WRITE;
886 }
887
888 rc = OSLibDosAllocSharedMem(&Address, cbSize, flag, name);
889
890 if(rc)
891 {
892 dprintf(("DosAllocSharedMem returned %d\n", rc));
893 SetLastError( ERROR_OUTOFMEMORY );
894 return(NULL);
895 }
896
897 dprintf(("VirtualAllocShared returned %X\n", Address));
898 return(Address);
899}
900//******************************************************************************
901//******************************************************************************
Note: See TracBrowser for help on using the repository browser.