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

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

Fix: header file cleanup (win32type.h)

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