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

Last change on this file since 21302 was 21302, checked in by ydario, 16 years ago

Kernel32 updates.

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