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

Last change on this file since 1237 was 1237, checked in by phaller, 26 years ago

Fix: debug info

File size: 19.8 KB
Line 
1/* $Id: virtual.cpp,v 1.16 1999-10-09 22:28:59 phaller Exp $ */
2
3/*
4 * Win32 virtual memory functions
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Knut St. Osmundsen
8 * Copyright 1998 Peter FitzSimmons
9 *
10 * Parts (VIRTUAL_MapFileA/W) based on Wine code (memory\virtual.c):
11 *
12 * Copyright 1997 Alexandre Julliard
13 *
14 * Project Odin Software License can be found in LICENSE.TXT
15 *
16 */
17
18#include <odin.h>
19#include <odinwrap.h>
20
21#include <os2win.h>
22#include <stdlib.h>
23#include <string.h>
24#include <win\virtual.h>
25#include <heapstring.h>
26#include <handlemanager.h>
27#include "mmap.h"
28#include "oslibdos.h"
29
30
31ODINDEBUGCHANNEL(KERNEL32-VIRTUAL)
32
33
34/***********************************************************************
35 * CreateFileMapping32A (KERNEL32.46)
36 * Creates a named or unnamed file-mapping object for the specified file
37 *
38 * RETURNS
39 * Handle: Success
40 * 0: Mapping object does not exist
41 * NULL: Failure
42 */
43HANDLE WINAPI CreateFileMappingA(
44 HFILE hFile, /* [in] Handle of file to map */
45 SECURITY_ATTRIBUTES *sa, /* [in] Optional security attributes*/
46 DWORD protect, /* [in] Protection for mapping object */
47 DWORD size_high, /* [in] High-order 32 bits of object size */
48 DWORD size_low, /* [in] Low-order 32 bits of object size */
49 LPCSTR name /* [in] Name of file-mapping object */ )
50{
51 return HMCreateFileMapping(hFile, sa, protect, size_high, size_low, name);
52}
53
54
55/***********************************************************************
56 * CreateFileMapping32W (KERNEL32.47)
57 * See CreateFileMapping32A
58 */
59HANDLE WINAPI CreateFileMappingW( HFILE hFile, LPSECURITY_ATTRIBUTES attr,
60 DWORD protect, DWORD size_high,
61 DWORD size_low, LPCWSTR name )
62{
63 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
64 HANDLE ret = CreateFileMappingA( hFile, attr, protect,
65 size_high, size_low, nameA );
66 HeapFree( GetProcessHeap(), 0, nameA );
67 return ret;
68}
69
70
71/***********************************************************************
72 * OpenFileMapping32A (KERNEL32.397)
73 * Opens a named file-mapping object.
74 *
75 * RETURNS
76 * Handle: Success
77 * NULL: Failure
78 */
79HANDLE WINAPI OpenFileMappingA(
80 DWORD access, /* [in] Access mode */
81 BOOL inherit, /* [in] Inherit flag */
82 LPCSTR name ) /* [in] Name of file-mapping object */
83{
84 dprintf(("OpenFileMappingA: %x %d %s", access, inherit, name));
85 return HMOpenFileMapping(access, inherit, name);
86}
87
88
89/***********************************************************************
90 * OpenFileMapping32W (KERNEL32.398)
91 * See OpenFileMapping32A
92 */
93HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
94{
95 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
96 HANDLE ret = OpenFileMappingA( access, inherit, nameA );
97 HeapFree( GetProcessHeap(), 0, nameA );
98 return ret;
99}
100
101
102/***********************************************************************
103 * MapViewOfFile (KERNEL32.385)
104 * Maps a view of a file into the address space
105 *
106 * RETURNS
107 * Starting address of mapped view
108 * NULL: Failure
109 */
110LPVOID WINAPI MapViewOfFile(
111 HANDLE mapping, /* [in] File-mapping object to map */
112 DWORD access, /* [in] Access mode */
113 DWORD offset_high, /* [in] High-order 32 bits of file offset */
114 DWORD offset_low, /* [in] Low-order 32 bits of file offset */
115 DWORD count /* [in] Number of bytes to map */
116)
117{
118 return MapViewOfFileEx( mapping, access, offset_high,
119 offset_low, count, NULL );
120}
121
122
123/***********************************************************************
124 * MapViewOfFileEx (KERNEL32.386)
125 * Maps a view of a file into the address space
126 *
127 * RETURNS
128 * Starting address of mapped view
129 * NULL: Failure
130 */
131LPVOID WINAPI MapViewOfFileEx(
132 HANDLE handle, /* [in] File-mapping object to map */
133 DWORD access, /* [in] Access mode */
134 DWORD offset_high, /* [in] High-order 32 bits of file offset */
135 DWORD offset_low, /* [in] Low-order 32 bits of file offset */
136 DWORD count, /* [in] Number of bytes to map */
137 LPVOID addr /* [in] Suggested starting address for mapped view */
138)
139{
140 return HMMapViewOfFileEx(handle, access, offset_high, offset_low, count, addr);
141}
142
143
144/***********************************************************************
145 * FlushViewOfFile (KERNEL32.262)
146 * Writes to the disk a byte range within a mapped view of a file
147 *
148 * RETURNS
149 * TRUE: Success
150 * FALSE: Failure
151 */
152BOOL WINAPI FlushViewOfFile(
153 LPCVOID base, /* [in] Start address of byte range to flush */
154 DWORD cbFlush /* [in] Number of bytes in range */
155)
156{
157 Win32MemMap *map;
158 DWORD offset;
159
160 if (!base)
161 {
162 SetLastError( ERROR_INVALID_PARAMETER );
163 return FALSE;
164 }
165 map = Win32MemMapView::findMapByView((ULONG)base, &offset, MEMMAP_ACCESS_READ);
166 if(map == NULL) {
167 SetLastError( ERROR_FILE_NOT_FOUND );
168 return FALSE;
169 }
170 return map->flushView(offset, cbFlush);
171}
172
173
174/***********************************************************************
175 * UnmapViewOfFile (KERNEL32.540)
176 * Unmaps a mapped view of a file.
177 *
178 * NOTES
179 * Should addr be an LPCVOID?
180 *
181 * RETURNS
182 * TRUE: Success
183 * FALSE: Failure
184 */
185BOOL WINAPI UnmapViewOfFile(LPVOID addr /* [in] Address where mapped view begins */
186)
187{
188 Win32MemMap *map;
189 Win32MemMapView *view;
190
191 DWORD offset;
192
193 if (!addr)
194 {
195 SetLastError( ERROR_INVALID_PARAMETER );
196 return FALSE;
197 }
198 map = Win32MemMapView::findMapByView((ULONG)addr, &offset, MEMMAP_ACCESS_READ, &view);
199 if(map == NULL) {
200 SetLastError( ERROR_FILE_NOT_FOUND );
201 return FALSE;
202 }
203 return map->unmapViewOfFile(view);
204}
205
206/***********************************************************************
207 * VIRTUAL_MapFileW
208 *
209 * Helper function to map a file to memory:
210 * name - file name
211 * [RETURN] ptr - pointer to mapped file
212 */
213HANDLE WINAPI VIRTUAL_MapFileW( LPCWSTR name , LPVOID *lpMapping)
214{
215 HANDLE hFile, hMapping = -1;
216
217 hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
218 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);
219 if (hFile != INVALID_HANDLE_VALUE)
220 {
221 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
222 CloseHandle( hFile );
223 if (hMapping != INVALID_HANDLE_VALUE)
224 {
225 *lpMapping = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
226 }
227 }
228 return hMapping;
229}
230
231/***********************************************************************
232 * VIRTUAL_MapFileA
233 *
234 * Helper function to map a file to memory:
235 * name - file name
236 * [RETURN] ptr - pointer to mapped file
237 */
238HANDLE WINAPI VIRTUAL_MapFileA( LPCSTR name , LPVOID *lpMapping)
239{
240 HANDLE hFile, hMapping = -1;
241
242 hFile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL,
243 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);
244 if (hFile != INVALID_HANDLE_VALUE)
245 {
246 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
247 CloseHandle( hFile );
248 if (hMapping != INVALID_HANDLE_VALUE)
249 {
250 *lpMapping = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
251 }
252 }
253 return hMapping;
254}
255
256//******************************************************************************
257//******************************************************************************
258ODINFUNCTION4(LPVOID, VirtualAlloc, LPVOID, lpvAddress,
259 DWORD, cbSize,
260 DWORD, fdwAllocationType,
261 DWORD, fdwProtect)
262{
263 PVOID Address = lpvAddress;
264 ULONG flag = 0, base;
265 DWORD rc;
266
267 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */
268 {
269 dprintf(("VirtualAlloc: size too large"));
270 SetLastError( ERROR_OUTOFMEMORY );
271 return NULL;
272 }
273
274 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||
275 (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
276 {
277 dprintf(("VirtualAlloc: Invalid parameter"));
278 SetLastError( ERROR_INVALID_PARAMETER );
279 return NULL;
280 }
281
282 if(fdwAllocationType & MEM_COMMIT) {
283 dprintf(("VirtualAlloc: commit\n"));
284 flag = PAG_COMMIT;
285 }
286 if(fdwProtect & PAGE_READONLY) flag |= PAG_READ;
287 if(fdwProtect & PAGE_READWRITE) flag |= (PAG_READ | PAG_WRITE);
288 if(fdwProtect & PAGE_WRITECOPY) flag |= (PAG_READ | PAG_WRITE);
289
290 if(fdwProtect & PAGE_EXECUTE_READWRITE) flag |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
291 if(fdwProtect & PAGE_EXECUTE_READ) flag |= (PAG_EXECUTE | PAG_READ);
292 if(fdwProtect & PAGE_EXECUTE) flag |= PAG_EXECUTE;
293
294 if(fdwProtect & PAGE_GUARD) flag |= PAG_GUARD;
295
296 //just do this if other options are used
297 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0)
298 {
299 dprintf(("VirtualAlloc: Unknown protection flags, default to read/write"));
300 flag |= PAG_READ | PAG_WRITE;
301 }
302
303 if(fdwAllocationType & MEM_COMMIT && lpvAddress != NULL)
304 {
305 Address = lpvAddress;
306
307 rc = OSLibDosSetMem(lpvAddress, cbSize, flag);
308
309 //might try to commit larger part with same base address
310 if(rc == OSLIB_ERROR_ACCESS_DENIED && cbSize > 4096 )
311 { //knut: AND more than one page
312 char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page!
313 ULONG size, os2flags;
314
315 while(newbase >= (char *)lpvAddress)
316 { //knut: should check first page to!!
317 size = 4096;
318 os2flags = 0;
319 rc = OSLibDosQueryMem(newbase, &size, &os2flags);
320 if(rc)
321 break;
322
323 if(os2flags & PAG_COMMIT)
324 {
325 newbase += 4096;
326 break;
327 }
328 newbase -= 4096;
329 }
330
331 if(rc == 0)
332 {
333 //In case it wants to commit bytes that fall into the last
334 //page of the previous commit command
335 if(cbSize > ((int)newbase - (int)lpvAddress))
336 rc = OSLibDosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag);
337 }
338 else return(NULL);
339
340 }
341 else
342 {
343 if(rc == OSLIB_ERROR_INVALID_ADDRESS) {
344 rc = OSLibDosAllocMem(&Address, cbSize, flag );
345 }
346 else
347 if(rc) dprintf(("Unexpected DosSetMem error %x", rc));
348 }
349 }
350 else
351 {
352 rc = OSLibDosAllocMem(&Address, cbSize, flag);
353 }
354
355 if(rc)
356 {
357 dprintf(("DosSetMem returned %d\n", rc));
358 SetLastError( ERROR_OUTOFMEMORY );
359 return(NULL);
360 }
361
362 dprintf(("VirtualAlloc returned %X\n", Address));
363 return(Address);
364}
365//******************************************************************************
366//******************************************************************************
367ODINFUNCTION3(BOOL, VirtualFree, LPVOID, lpvAddress,
368 DWORD, cbSize,
369 DWORD, FreeType)
370{
371 DWORD rc;
372
373 // verify parameters
374 if ( (lpvAddress == NULL) ||
375 ( (FreeType & MEM_RELEASE) &&
376 (cbSize != 0) )
377 )
378 {
379 SetLastError(ERROR_INVALID_PARAMETER);
380 return(FALSE);
381 }
382
383 if(FreeType & MEM_DECOMMIT)
384 rc = OSLibDosSetMem(lpvAddress, cbSize, PAG_DECOMMIT);
385 else
386 rc = OSLibDosFreeMem(lpvAddress); //MEM_RELEASE, cbSize == 0 (or should be)
387
388 if(rc)
389 {
390 dprintf(("KERNEL32:VirtualFree rc = #%d\n",
391 rc));
392 SetLastError(ERROR_GEN_FAILURE);
393 return(FALSE);
394 }
395
396 return(TRUE);
397}
398//******************************************************************************
399//LPVOID lpvAddress; /* address of region of committed pages */
400//DWORD cbSize; /* size of the region */
401//DWORD fdwNewProtect; /* desired access protection */
402//PDWORD pfdwOldProtect; /* address of variable to get old protection */
403//TODO: Not 100% complete
404//TODO: SetLastError on failure
405//******************************************************************************
406
407ODINFUNCTION4(BOOL, VirtualProtect, LPVOID, lpvAddress,
408 DWORD, cbSize,
409 DWORD, fdwNewProtect,
410 DWORD*, pfdwOldProtect)
411{
412 DWORD rc;
413 ULONG pageFlags = 0;
414 int npages;
415
416 dprintf(("VirtualProtect %X; %d bytes, new flags %X (%X)\n", (int)lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect));
417 if(pfdwOldProtect == NULL)
418 return(FALSE);
419
420 rc = OSLibDosQueryMem(lpvAddress, &cbSize, &pageFlags);
421 if(rc) {
422 dprintf(("DosQueryMem returned %d\n", rc));
423 return(FALSE);
424 }
425 dprintf(("Old memory flags %X\n", pageFlags));
426 *pfdwOldProtect = 0;
427 if(pageFlags & PAG_READ && !(pageFlags & PAG_WRITE))
428 *pfdwOldProtect |= PAGE_READONLY;
429 if(pageFlags & (PAG_WRITE))
430 *pfdwOldProtect |= PAGE_READWRITE;
431
432 if((pageFlags & (PAG_WRITE | PAG_EXECUTE)) == (PAG_WRITE | PAG_EXECUTE))
433 *pfdwOldProtect |= PAGE_EXECUTE_READWRITE;
434 else
435 if(pageFlags & PAG_EXECUTE)
436 *pfdwOldProtect |= PAGE_EXECUTE_READ;
437
438 if(pageFlags & PAG_GUARD)
439 *pfdwOldProtect |= PAGE_GUARD;
440 pageFlags = 0;
441
442 if(fdwNewProtect & PAGE_READONLY) pageFlags |= PAG_READ;
443 if(fdwNewProtect & PAGE_READWRITE) pageFlags |= (PAG_READ | PAG_WRITE);
444 if(fdwNewProtect & PAGE_WRITECOPY) pageFlags |= (PAG_READ | PAG_WRITE);
445 if(fdwNewProtect & PAGE_EXECUTE_READ) pageFlags |= (PAG_EXECUTE | PAG_READ);
446 if(fdwNewProtect & PAGE_EXECUTE_READWRITE)
447 pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
448 if(fdwNewProtect & PAGE_EXECUTE_WRITECOPY)
449 pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
450 if(fdwNewProtect & PAGE_GUARD) pageFlags |= PAG_GUARD;
451//Not supported in OS/2??
452// if(fdwNewProtect & PAGE_NOACCESS)
453
454 dprintf(("New memory flags %X\n", pageFlags));
455 if(pageFlags == 0) {
456 dprintf(("pageFlags == 0\n"));
457 return(TRUE); //nothing to do
458 }
459 ULONG offset = ((ULONG)lpvAddress & 0xFFF);
460 npages = (cbSize >> 12);
461 if(cbSize & 0xFFF + offset) {
462 npages++;
463 }
464
465 lpvAddress = (LPVOID)((int)lpvAddress & ~0xFFF);
466 cbSize = npages*4096;
467 dprintf(("lpvAddress = %X, cbSize = %d\n", lpvAddress, cbSize));
468
469 rc = OSLibDosSetMem(lpvAddress, cbSize, pageFlags);
470 if(rc) {
471 dprintf(("DosSetMem returned %d\n", rc));
472 return(FALSE);
473 }
474 return(TRUE);
475}
476//******************************************************************************
477//******************************************************************************
478ODINFUNCTION3(DWORD, VirtualQuery, LPCVOID, lpvAddress,
479 LPMEMORY_BASIC_INFORMATION, pmbiBuffer,
480 DWORD, cbLength)
481{
482 ULONG cbRangeSize, dAttr;
483 DWORD rc;
484
485 if(lpvAddress == NULL || pmbiBuffer == NULL || cbLength == 0) {
486 return 0;
487 }
488
489 cbRangeSize = cbLength & ~0xFFF;
490 if(cbLength & 0xFFF) {
491 cbRangeSize += PAGE_SIZE;
492 }
493 rc = OSLibDosQueryMem((LPVOID)lpvAddress, &cbRangeSize, &dAttr);
494 if(rc) {
495 dprintf(("VirtualQuery - DosQueryMem %x %x returned %d\n", lpvAddress, cbLength, rc));
496 return 0;
497 }
498 memset(pmbiBuffer, 0, sizeof(MEMORY_BASIC_INFORMATION));
499 pmbiBuffer->BaseAddress = (LPVOID)lpvAddress;
500 pmbiBuffer->RegionSize = cbRangeSize;
501 if(dAttr & PAG_READ && !(dAttr & PAG_WRITE))
502 pmbiBuffer->Protect |= PAGE_READONLY;
503 if(dAttr & PAG_WRITE)
504 pmbiBuffer->Protect |= PAGE_READWRITE;
505
506 if((dAttr & (PAG_WRITE | PAG_EXECUTE)) == (PAG_WRITE | PAG_EXECUTE))
507 pmbiBuffer->Protect |= PAGE_EXECUTE_READWRITE;
508 else
509 if(dAttr & PAG_EXECUTE)
510 pmbiBuffer->Protect |= PAGE_EXECUTE_READ;
511
512 if(dAttr & PAG_GUARD)
513 pmbiBuffer->Protect |= PAGE_GUARD;
514
515 if(dAttr & PAG_FREE)
516 pmbiBuffer->State = MEM_FREE;
517 else
518 if(dAttr & PAG_COMMIT)
519 pmbiBuffer->State = MEM_COMMIT;
520 else pmbiBuffer->State = MEM_RESERVE;
521
522 if(!(dAttr & PAG_SHARED))
523 pmbiBuffer->Type = MEM_PRIVATE;
524
525 //TODO: This is not correct: AllocationProtect should contain the protection
526 // flags used in the initial call to VirtualAlloc
527 pmbiBuffer->AllocationProtect = pmbiBuffer->Protect;
528 if(dAttr & PAG_BASE) {
529 pmbiBuffer->AllocationBase = (LPVOID)lpvAddress;
530 }
531 else {
532 while(lpvAddress > 0) {
533 rc = OSLibDosQueryMem((LPVOID)lpvAddress, &cbRangeSize, &dAttr);
534 if(rc) {
535 dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n", lpvAddress, cbLength, rc));
536 break;
537 }
538 if(dAttr & PAG_BASE) {
539 pmbiBuffer->AllocationBase = (LPVOID)lpvAddress;
540 break;
541 }
542 lpvAddress = (LPVOID)((ULONG)lpvAddress - PAGE_SIZE);
543 }
544 }
545 return sizeof(MEMORY_BASIC_INFORMATION);
546}
547//******************************************************************************
548//******************************************************************************
549ODINFUNCTION2(BOOL, VirtualLock, LPVOID, lpAddress,
550 DWORD, dwSize)
551{
552 dprintf(("VirtualLock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
553 return TRUE;
554}
555
556//******************************************************************************
557ODINFUNCTION2(BOOL, VirtualUnlock, LPVOID, lpAddress,
558 DWORD, dwSize)
559{
560 dprintf(("VirtualUnlock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
561 return TRUE;
562}
563
564/*****************************************************************************
565 * Name : BOOL VirtualProtectEx
566 * Purpose : The VirtualProtectEx function changes the access protection on
567 * a region of committed pages in the virtual address space of a specified
568 * process. Note that this function differs from VirtualProtect,
569 * which changes the access protection on the calling process only.
570 * Parameters: HANDLE hProcess handle of process
571 * LPVOID lpvAddress address of region of committed pages
572 * DWORD cbSize size of region
573 * DWORD fdwNewProtect desired access protection
574 * PDWORD pfdwOldProtect address of variable to get old protection
575 * Variables :
576 * Result : size of target buffer
577 * Remark :
578 * Status : UNTESTED STUB
579 *
580 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
581 *****************************************************************************/
582
583ODINFUNCTION5(BOOL, VirtualProtectEx, HANDLE, hProcess,
584 LPVOID, lpvAddress,
585 DWORD, cbSize,
586 DWORD, fdwNewProtect,
587 LPDWORD, pfdwOldProtect)
588{
589 return VirtualProtect(lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect);
590}
591
592
593/*****************************************************************************
594 * Name : DWORD VirtualQueryEx
595 * Purpose : The VirtualQueryEx function provides information about a range
596 * of pages within the virtual address space of a specified process.
597 * Parameters: HANDLE hProcess handle of process
598 * LPCVOID lpvAddress address of region
599 * LPMEMORY_BASIC_INFORMATION pmbiBuffer address of information buffer
600 * DWORD cbLength size of buffer
601 * Variables :
602 * Result : number of bytes returned in buffer
603 * Remark :
604 * Status : UNTESTED STUB
605 *
606 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
607 *****************************************************************************/
608
609ODINFUNCTION4(DWORD, VirtualQueryEx, HANDLE, hProcess,
610 LPCVOID, lpvAddress,
611 LPMEMORY_BASIC_INFORMATION, pmbiBuffer,
612 DWORD, cbLength)
613{
614 return VirtualQuery(lpvAddress, pmbiBuffer, cbLength);
615}
Note: See TracBrowser for help on using the repository browser.