source: trunk/src/kernel32/os2native.cpp@ 657

Last change on this file since 657 was 657, checked in by sandervl, 26 years ago

VirtualQuery implemented + preliminary memory mapped code

File size: 15.1 KB
Line 
1/* $Id: os2native.cpp,v 1.6 1999-08-24 12:23:24 sandervl Exp $ */
2
3/*
4 * Misc procedures
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Knut St. Osmundsen
8 * Copyright 1998 Peter FitzSimmons
9 *
10 *
11 * TODO: VirtualProtectEx/VirtualQueryEx don't work for different processes!
12 * TODO: SetLastError should be called!
13 * TODO: WRITECOPY type not properly supported (never return as flag when queried)
14 *
15 * Project Odin Software License can be found in LICENSE.TXT
16 *
17 */
18#define INCL_BASE
19#define INCL_DOSEXCEPTIONS
20#define INCL_DOSMEMMGR
21#define INCL_DOSPROCESS
22#include <os2wrap.h> //Odin32 OS/2 api wrappers
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#ifdef __IBMC__
27#include <builtin.h>
28#endif
29#include <win32type.h>
30#include "misc.h"
31#include "exceptions.h"
32
33#define PAGE_NOACCESS 0x01
34#define PAGE_READONLY 0x02
35#define PAGE_READWRITE 0x04
36#define PAGE_WRITECOPY 0x08
37#define PAGE_EXECUTE 0x10
38#define PAGE_EXECUTE_READ 0x20
39#define PAGE_EXECUTE_READWRITE 0x40
40#define PAGE_EXECUTE_WRITECOPY 0x80
41#define PAGE_GUARD 0x100
42#define PAGE_NOCACHE 0x200
43
44#define MEM_COMMIT 0x00001000
45#define MEM_RESERVE 0x00002000
46#define MEM_DECOMMIT 0x00004000
47#define MEM_RELEASE 0x00008000
48#define MEM_FREE 0x00010000
49#define MEM_PRIVATE 0x00020000
50#define MEM_MAPPED 0x00040000
51#define MEM_TOP_DOWN 0x00100000
52
53#define SEC_FILE 0x00800000
54#define SEC_IMAGE 0x01000000
55#define SEC_RESERVE 0x04000000
56#define SEC_COMMIT 0x08000000
57#define SEC_NOCACHE 0x10000000
58
59#ifndef PAGE_SIZE
60#define PAGE_SIZE 4096
61#endif
62
63extern ULONG flAllocMem; /* Tue 03.03.1998: knut */
64
65#ifdef DEBUG
66ULONG commit = 0, reserve = 0;
67#endif
68
69//******************************************************************************
70//******************************************************************************
71LPVOID WIN32API VirtualAlloc(LPVOID lpvAddress, DWORD cbSize, DWORD fdwAllocationType,
72 DWORD fdwProtect)
73{
74 PVOID Address = lpvAddress;
75 ULONG flag = 0, base;
76 APIRET rc;
77
78 dprintf(("VirtualAlloc at %X; %d bytes, fAlloc %d, fProtect %d\n", (int)lpvAddress, cbSize, fdwAllocationType, fdwProtect));
79
80 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */
81 {
82 dprintf(("VirtualAlloc: size too large"));
83// SetLastError( ERROR_OUTOFMEMORY );
84 return NULL;
85 }
86
87 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||
88 (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE)))
89 {
90 dprintf(("VirtualAlloc: Invalid parameter"));
91// SetLastError( ERROR_INVALID_PARAMETER );
92 return NULL;
93 }
94
95 if(fdwAllocationType & MEM_COMMIT) {
96 dprintf(("VirtualAlloc: commit\n"));
97 flag = PAG_COMMIT;
98 }
99 if(fdwProtect & PAGE_READONLY) flag |= PAG_READ;
100 if(fdwProtect & PAGE_READWRITE) flag |= (PAG_READ | PAG_WRITE);
101 if(fdwProtect & PAGE_WRITECOPY) flag |= (PAG_READ | PAG_WRITE);
102
103 if(fdwProtect & PAGE_EXECUTE_READWRITE) flag |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
104 if(fdwProtect & PAGE_EXECUTE_READ) flag |= (PAG_EXECUTE | PAG_READ);
105 if(fdwProtect & PAGE_EXECUTE) flag |= PAG_EXECUTE;
106
107 if(fdwProtect & PAGE_GUARD) flag |= PAG_GUARD;
108
109 //just do this if other options are used
110 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0) {
111 dprintf(("VirtualAlloc: Unknown protection flags, default to read/write"));
112 flag |= PAG_READ | PAG_WRITE;
113 }
114
115 if(fdwAllocationType & MEM_COMMIT && lpvAddress != NULL) {
116 Address = lpvAddress;
117
118 rc = DosSetMem(lpvAddress, cbSize, flag);
119 //might try to commit larger part with same base address
120 if(rc == ERROR_ACCESS_DENIED && cbSize > 4096 ) {//knut: AND more than one page
121 char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page!
122 ULONG size, os2flags;
123
124 while(newbase >= (char *)lpvAddress) { //knut: should check first page to!!
125 size = 4096;
126 os2flags = 0;
127 rc = DosQueryMem(newbase, &size, &os2flags);
128 if(rc) break;
129 if(os2flags & PAG_COMMIT) {
130 newbase += 4096;
131 break;
132 }
133 newbase -= 4096;
134 }
135 if(rc == 0) {
136 //In case it wants to commit bytes that fall into the last
137 //page of the previous commit command
138 if(cbSize > ((int)newbase - (int)lpvAddress)) {
139 rc = DosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag);
140 }
141 }
142 else return(NULL);
143 }
144 else
145 {
146 if(rc == ERROR_INVALID_ADDRESS)
147 {
148 rc = DosAllocMem(&Address, cbSize, flag | flAllocMem );
149 }
150 else
151 if(rc) dprintf(("Unexpected DosSetMem error %x", rc));
152 }
153 }
154 else {
155 /*knut: flAllocMem */
156 rc = DosAllocMem(&Address, cbSize, flag | flAllocMem );
157 }
158
159 //TODO: Set last error in case rc != 0
160 if(rc) {
161 dprintf(("DosSetMem returned %d\n", rc));
162// SetLastError( ERROR_OUTOFMEMORY );
163 return(NULL);
164 }
165
166 dprintf(("VirtualAlloc returned %X\n", Address));
167 return(Address);
168}
169//******************************************************************************
170//******************************************************************************
171BOOL WIN32API VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD FreeType)
172{
173 APIRET rc;
174
175 dprintf(("VirtualFree at %d; %d bytes, freetype %d\n", (int)lpvAddress, cbSize, FreeType));
176
177 if(FreeType & MEM_DECOMMIT) {
178 rc = DosSetMem(lpvAddress, cbSize, PAG_DECOMMIT);
179 }
180 else rc = DosFreeMem(lpvAddress); //MEM_RELEASE, cbSize == 0 (or should be)
181
182//TODO: Set last error in case rc != 0
183 if(rc) return(FALSE);
184 return(TRUE);
185}
186//******************************************************************************
187//LPVOID lpvAddress; /* address of region of committed pages */
188//DWORD cbSize; /* size of the region */
189//DWORD fdwNewProtect; /* desired access protection */
190//PDWORD pfdwOldProtect; /* address of variable to get old protection */
191//TODO: Not 100% complete
192//TODO: SetLastError on failure
193//******************************************************************************
194BOOL WIN32API VirtualProtect(LPVOID lpvAddress, DWORD cbSize, DWORD fdwNewProtect,
195 DWORD *pfdwOldProtect)
196{
197 APIRET rc;
198 ULONG pageFlags = 0;
199 int npages;
200
201 dprintf(("VirtualProtect %X; %d bytes, new flags %X (%X)\n", (int)lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect));
202// _interrupt(3);
203 if(pfdwOldProtect == NULL)
204 return(FALSE);
205
206 rc = DosQueryMem(lpvAddress, &cbSize, &pageFlags);
207 if(rc) {
208 dprintf(("DosQueryMem returned %d\n", rc));
209 return(FALSE);
210 }
211 dprintf(("Old memory flags %X\n", pageFlags));
212 *pfdwOldProtect = 0;
213 if(pageFlags & PAG_READ && !(pageFlags & PAG_WRITE))
214 *pfdwOldProtect |= PAGE_READONLY;
215 if(pageFlags & (PAG_WRITE))
216 *pfdwOldProtect |= PAGE_READWRITE;
217
218 if(pageFlags & (PAG_WRITE | PAG_EXECUTE))
219 *pfdwOldProtect |= PAGE_EXECUTE_READWRITE;
220 else
221 if(pageFlags & PAG_EXECUTE)
222 *pfdwOldProtect |= PAGE_EXECUTE_READ;
223
224 if(pageFlags & PAG_GUARD)
225 *pfdwOldProtect |= PAGE_GUARD;
226 pageFlags = 0;
227
228 if(fdwNewProtect & PAGE_READONLY) pageFlags |= PAG_READ;
229 if(fdwNewProtect & PAGE_READWRITE) pageFlags |= (PAG_READ | PAG_WRITE);
230 if(fdwNewProtect & PAGE_WRITECOPY) pageFlags |= (PAG_READ | PAG_WRITE);
231 if(fdwNewProtect & PAGE_EXECUTE_READ) pageFlags |= (PAG_EXECUTE | PAG_READ);
232 if(fdwNewProtect & PAGE_EXECUTE_READWRITE)
233 pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
234 if(fdwNewProtect & PAGE_EXECUTE_WRITECOPY)
235 pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
236 if(fdwNewProtect & PAGE_GUARD) pageFlags |= PAG_GUARD;
237//Not supported in OS/2??
238// if(fdwNewProtect & PAGE_NOACCESS)
239
240 dprintf(("New memory flags %X\n", pageFlags));
241 if(pageFlags == 0) {
242 dprintf(("pageFlags == 0\n"));
243 return(TRUE); //nothing to do
244 }
245 npages = ((int)lpvAddress + cbSize >> 12) - ((int)lpvAddress >> 12) + 1;
246
247 lpvAddress = (LPVOID)((int)lpvAddress & ~0xFFF);
248 cbSize = npages*4096;
249 dprintf(("lpvAddress = %X, cbSize = %d\n", lpvAddress, cbSize));
250
251 rc = DosSetMem(lpvAddress, cbSize, pageFlags);
252 if(rc) {
253 dprintf(("DosSetMem returned %d\n", rc));
254 return(FALSE);
255 }
256 return(TRUE);
257}
258//******************************************************************************
259//******************************************************************************
260DWORD WIN32API VirtualQuery(LPVOID lpvAddress, PMEMORY_BASIC_INFORMATION pmbiBuffer,
261 DWORD cbLength)
262{
263 ULONG cbRangeSize, dAttr;
264 APIRET rc;
265
266 if(lpvAddress == NULL || pmbiBuffer == NULL || cbLength == 0) {
267 return 0;
268 }
269 cbRangeSize = cbLength;
270 rc = DosQueryMem(lpvAddress, &cbRangeSize, &dAttr);
271 if(rc) {
272 dprintf(("VirtualQuery - DosQueryMem %x %x returned %d\n", lpvAddress, cbLength, rc));
273 return 0;
274 }
275 memset(pmbiBuffer, 0, sizeof(MEMORY_BASIC_INFORMATION));
276 pmbiBuffer->BaseAddress = lpvAddress;
277 pmbiBuffer->RegionSize = cbRangeSize;
278 if(dAttr & PAG_READ && !(dAttr & PAG_WRITE))
279 pmbiBuffer->Protect |= PAGE_READONLY;
280 if(dAttr & PAG_WRITE)
281 pmbiBuffer->Protect |= PAGE_READWRITE;
282
283 if(dAttr & (PAG_WRITE | PAG_EXECUTE))
284 pmbiBuffer->Protect |= PAGE_EXECUTE_READWRITE;
285 else
286 if(dAttr & PAG_EXECUTE)
287 pmbiBuffer->Protect |= PAGE_EXECUTE_READ;
288
289 if(dAttr & PAG_GUARD)
290 pmbiBuffer->Protect |= PAGE_GUARD;
291
292 if(dAttr & PAG_FREE)
293 pmbiBuffer->State = MEM_FREE;
294 else
295 if(dAttr & PAG_COMMIT)
296 pmbiBuffer->State = MEM_COMMIT;
297 else pmbiBuffer->State = MEM_RESERVE;
298
299 if(!(dAttr & PAG_SHARED))
300 pmbiBuffer->Type = MEM_PRIVATE;
301
302 //TODO: This is not correct: AllocationProtect should contain the protection
303 // flags used in the initial call to VirtualAlloc
304 pmbiBuffer->AllocationProtect = pmbiBuffer->Protect;
305 if(dAttr & PAG_BASE) {
306 pmbiBuffer->AllocationBase = lpvAddress;
307 }
308 else {
309 while(lpvAddress > 0) {
310 rc = DosQueryMem(lpvAddress, &cbRangeSize, &dAttr);
311 if(rc) {
312 dprintf(("VirtualQuery - DosQueryMem %x %x returned %d\n", lpvAddress, cbLength, rc));
313 break;
314 }
315 if(dAttr & PAG_BASE) {
316 pmbiBuffer->AllocationBase = lpvAddress;
317 break;
318 }
319 lpvAddress = (LPVOID)((ULONG)lpvAddress - PAGE_SIZE);
320 }
321 }
322 return sizeof(MEMORY_BASIC_INFORMATION);
323}
324//******************************************************************************
325//******************************************************************************
326#ifdef __WATCOMC__ /*PLF Sat 97-06-21 17:12:36*/
327 extern void interrupt3( void );
328 #pragma aux interrupt3= \
329 "int 3"
330#endif
331void WIN32API DebugBreak()
332{
333 dprintf(("DebugBreak\n"));
334#ifdef __WATCOMC__
335 interrupt3();
336#else
337 _interrupt(3);
338#endif
339}
340//******************************************************************************
341//TODO: Implement this??
342//******************************************************************************
343BOOL WIN32API GetThreadContext(HANDLE hThread, LPWINCONTEXT lpContext)
344{
345 dprintf(("GetThreadContext NOT IMPLEMENTED!! (TRUE)\n"));
346 memset(lpContext, 0, sizeof(WINCONTEXT));
347 return TRUE;
348}
349//******************************************************************************
350//TODO: Implement this??
351//******************************************************************************
352BOOL WIN32API SetThreadContext(HANDLE hThread, LPWINCONTEXT lpContext)
353{
354 dprintf(("SetThreadContext NOT IMPLEMENTED!!\n"));
355
356 return FALSE;
357}
358//******************************************************************************
359//******************************************************************************
360BOOL WIN32API VirtualLock( LPVOID lpAddress, DWORD dwSize )
361{
362 dprintf(("VirtualLock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
363 return TRUE;
364}
365
366//******************************************************************************
367BOOL WIN32API VirtualUnlock( LPVOID lpAddress, DWORD dwSize )
368{
369 dprintf(("VirtualUnlock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
370 return TRUE;
371}
372
373
374/*****************************************************************************
375 * Name : BOOL VirtualProtectEx
376 * Purpose : The VirtualProtectEx function changes the access protection on
377 * a region of committed pages in the virtual address space of a specified
378 * process. Note that this function differs from VirtualProtect,
379 * which changes the access protection on the calling process only.
380 * Parameters: HANDLE hProcess handle of process
381 * LPVOID lpvAddress address of region of committed pages
382 * DWORD cbSize size of region
383 * DWORD fdwNewProtect desired access protection
384 * PDWORD pfdwOldProtect address of variable to get old protection
385 * Variables :
386 * Result : size of target buffer
387 * Remark :
388 * Status : UNTESTED STUB
389 *
390 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
391 *****************************************************************************/
392
393BOOL WIN32API VirtualProtectEx(HANDLE hProcess,
394 LPVOID lpvAddress,
395 DWORD cbSize,
396 DWORD fdwNewProtect,
397 LPDWORD pfdwOldProtect)
398{
399 dprintf(("KERNEL32: VirtualProtectEx(%08x,%08xh,%08xh,%08xh,%08xh) not implemented for different processes.\n",
400 hProcess,
401 lpvAddress,
402 cbSize,
403 fdwNewProtect,
404 pfdwOldProtect));
405
406 return VirtualProtect(lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect);
407}
408
409
410/*****************************************************************************
411 * Name : DWORD VirtualQueryEx
412 * Purpose : The VirtualQueryEx function provides information about a range
413 * of pages within the virtual address space of a specified process.
414 * Parameters: HANDLE hProcess handle of process
415 * LPCVOID lpvAddress address of region
416 * PMEMORY_BASIC_INFORMATION pmbiBuffer address of information buffer
417 * DWORD cbLength size of buffer
418 * Variables :
419 * Result : number of bytes returned in buffer
420 * Remark :
421 * Status : UNTESTED STUB
422 *
423 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
424 *****************************************************************************/
425
426DWORD WIN32API VirtualQueryEx(HANDLE hProcess,
427 LPVOID lpvAddress,
428 PMEMORY_BASIC_INFORMATION pmbiBuffer,
429 DWORD cbLength)
430{
431 dprintf(("KERNEL32: VirtualQueryEx(%08x,%08xh,%08xh,%08xh) not implemented for different processes.\n",
432 hProcess,
433 lpvAddress,
434 pmbiBuffer,
435 cbLength));
436
437 return VirtualQuery(lpvAddress, pmbiBuffer, cbLength);
438}
439
Note: See TracBrowser for help on using the repository browser.