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

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

Add: HMDeviceMemMapClass fixed

File size: 15.0 KB
Line 
1/* $Id: os2native.cpp,v 1.7 1999-08-25 08:57:14 phaller 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 {
112 dprintf(("VirtualAlloc: Unknown protection flags, default to read/write"));
113 flag |= PAG_READ | PAG_WRITE;
114 }
115
116 if(fdwAllocationType & MEM_COMMIT && lpvAddress != NULL)
117 {
118 Address = lpvAddress;
119
120 rc = DosSetMem(lpvAddress, cbSize, flag);
121 //might try to commit larger part with same base address
122 if(rc == ERROR_ACCESS_DENIED && cbSize > 4096 )
123 { //knut: AND more than one page
124 char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page!
125 ULONG size, os2flags;
126
127 while(newbase >= (char *)lpvAddress)
128 { //knut: should check first page to!!
129 size = 4096;
130 os2flags = 0;
131 rc = DosQueryMem(newbase, &size, &os2flags);
132 if(rc)
133 break;
134
135 if(os2flags & PAG_COMMIT)
136 {
137 newbase += 4096;
138 break;
139 }
140 newbase -= 4096;
141 }
142
143 if(rc == 0)
144 {
145 //In case it wants to commit bytes that fall into the last
146 //page of the previous commit command
147 if(cbSize > ((int)newbase - (int)lpvAddress))
148 rc = DosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag);
149 }
150 else
151 return(NULL);
152
153 }
154 else
155 {
156 if(rc == ERROR_INVALID_ADDRESS)
157 rc = DosAllocMem(&Address, cbSize, flag | flAllocMem );
158 else
159 if(rc)
160 dprintf(("Unexpected DosSetMem error %x", rc));
161 }
162 }
163 else
164 {
165 /*knut: flAllocMem */
166 rc = DosAllocMem(&Address, cbSize, flag | flAllocMem );
167 }
168
169 //TODO: Set last error in case rc != 0
170 if(rc)
171 {
172 dprintf(("DosSetMem returned %d\n", rc));
173// SetLastError( ERROR_OUTOFMEMORY );
174 return(NULL);
175 }
176
177 dprintf(("VirtualAlloc returned %X\n", Address));
178 return(Address);
179}
180//******************************************************************************
181//******************************************************************************
182BOOL WIN32API VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD FreeType)
183{
184 APIRET rc;
185
186 dprintf(("VirtualFree at %d; %d bytes, freetype %d\n", (int)lpvAddress, cbSize, FreeType));
187
188 if(FreeType & MEM_DECOMMIT) {
189 rc = DosSetMem(lpvAddress, cbSize, PAG_DECOMMIT);
190 }
191 else rc = DosFreeMem(lpvAddress); //MEM_RELEASE, cbSize == 0 (or should be)
192
193//TODO: Set last error in case rc != 0
194 if(rc) return(FALSE);
195 return(TRUE);
196}
197//******************************************************************************
198//LPVOID lpvAddress; /* address of region of committed pages */
199//DWORD cbSize; /* size of the region */
200//DWORD fdwNewProtect; /* desired access protection */
201//PDWORD pfdwOldProtect; /* address of variable to get old protection */
202//TODO: Not 100% complete
203//TODO: SetLastError on failure
204//******************************************************************************
205BOOL WIN32API VirtualProtect(LPVOID lpvAddress, DWORD cbSize, DWORD fdwNewProtect,
206 DWORD *pfdwOldProtect)
207{
208 APIRET rc;
209 ULONG pageFlags = 0;
210 int npages;
211
212 dprintf(("VirtualProtect %X; %d bytes, new flags %X (%X)\n", (int)lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect));
213// _interrupt(3);
214 if(pfdwOldProtect == NULL)
215 return(FALSE);
216
217 rc = DosQueryMem(lpvAddress, &cbSize, &pageFlags);
218 if(rc) {
219 dprintf(("DosQueryMem returned %d\n", rc));
220 return(FALSE);
221 }
222 dprintf(("Old memory flags %X\n", pageFlags));
223 *pfdwOldProtect = 0;
224 if(pageFlags & PAG_READ && !(pageFlags & PAG_WRITE))
225 *pfdwOldProtect |= PAGE_READONLY;
226 if(pageFlags & (PAG_WRITE))
227 *pfdwOldProtect |= PAGE_READWRITE;
228
229 if(pageFlags & (PAG_WRITE | PAG_EXECUTE))
230 *pfdwOldProtect |= PAGE_EXECUTE_READWRITE;
231 else
232 if(pageFlags & PAG_EXECUTE)
233 *pfdwOldProtect |= PAGE_EXECUTE_READ;
234
235 if(pageFlags & PAG_GUARD)
236 *pfdwOldProtect |= PAGE_GUARD;
237 pageFlags = 0;
238
239 if(fdwNewProtect & PAGE_READONLY) pageFlags |= PAG_READ;
240 if(fdwNewProtect & PAGE_READWRITE) pageFlags |= (PAG_READ | PAG_WRITE);
241 if(fdwNewProtect & PAGE_WRITECOPY) pageFlags |= (PAG_READ | PAG_WRITE);
242 if(fdwNewProtect & PAGE_EXECUTE_READ) pageFlags |= (PAG_EXECUTE | PAG_READ);
243 if(fdwNewProtect & PAGE_EXECUTE_READWRITE)
244 pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
245 if(fdwNewProtect & PAGE_EXECUTE_WRITECOPY)
246 pageFlags |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);
247 if(fdwNewProtect & PAGE_GUARD) pageFlags |= PAG_GUARD;
248//Not supported in OS/2??
249// if(fdwNewProtect & PAGE_NOACCESS)
250
251 dprintf(("New memory flags %X\n", pageFlags));
252 if(pageFlags == 0) {
253 dprintf(("pageFlags == 0\n"));
254 return(TRUE); //nothing to do
255 }
256 npages = ((int)lpvAddress + cbSize >> 12) - ((int)lpvAddress >> 12) + 1;
257
258 lpvAddress = (LPVOID)((int)lpvAddress & ~0xFFF);
259 cbSize = npages*4096;
260 dprintf(("lpvAddress = %X, cbSize = %d\n", lpvAddress, cbSize));
261
262 rc = DosSetMem(lpvAddress, cbSize, pageFlags);
263 if(rc) {
264 dprintf(("DosSetMem returned %d\n", rc));
265 return(FALSE);
266 }
267 return(TRUE);
268}
269//******************************************************************************
270//******************************************************************************
271DWORD WIN32API VirtualQuery(LPVOID lpvAddress, PMEMORY_BASIC_INFORMATION pmbiBuffer,
272 DWORD cbLength)
273{
274 ULONG cbRangeSize, dAttr;
275 APIRET rc;
276
277 if(lpvAddress == NULL || pmbiBuffer == NULL || cbLength == 0) {
278 return 0;
279 }
280 cbRangeSize = cbLength;
281 rc = DosQueryMem(lpvAddress, &cbRangeSize, &dAttr);
282 if(rc) {
283 dprintf(("VirtualQuery - DosQueryMem %x %x returned %d\n", lpvAddress, cbLength, rc));
284 return 0;
285 }
286 memset(pmbiBuffer, 0, sizeof(MEMORY_BASIC_INFORMATION));
287 pmbiBuffer->BaseAddress = lpvAddress;
288 pmbiBuffer->RegionSize = cbRangeSize;
289 if(dAttr & PAG_READ && !(dAttr & PAG_WRITE))
290 pmbiBuffer->Protect |= PAGE_READONLY;
291 if(dAttr & PAG_WRITE)
292 pmbiBuffer->Protect |= PAGE_READWRITE;
293
294 if(dAttr & (PAG_WRITE | PAG_EXECUTE))
295 pmbiBuffer->Protect |= PAGE_EXECUTE_READWRITE;
296 else
297 if(dAttr & PAG_EXECUTE)
298 pmbiBuffer->Protect |= PAGE_EXECUTE_READ;
299
300 if(dAttr & PAG_GUARD)
301 pmbiBuffer->Protect |= PAGE_GUARD;
302
303 if(dAttr & PAG_FREE)
304 pmbiBuffer->State = MEM_FREE;
305 else
306 if(dAttr & PAG_COMMIT)
307 pmbiBuffer->State = MEM_COMMIT;
308 else pmbiBuffer->State = MEM_RESERVE;
309
310 if(!(dAttr & PAG_SHARED))
311 pmbiBuffer->Type = MEM_PRIVATE;
312
313 //TODO: This is not correct: AllocationProtect should contain the protection
314 // flags used in the initial call to VirtualAlloc
315 pmbiBuffer->AllocationProtect = pmbiBuffer->Protect;
316 if(dAttr & PAG_BASE) {
317 pmbiBuffer->AllocationBase = lpvAddress;
318 }
319 else {
320 while(lpvAddress > 0) {
321 rc = DosQueryMem(lpvAddress, &cbRangeSize, &dAttr);
322 if(rc) {
323 dprintf(("VirtualQuery - DosQueryMem %x %x returned %d\n", lpvAddress, cbLength, rc));
324 break;
325 }
326 if(dAttr & PAG_BASE) {
327 pmbiBuffer->AllocationBase = lpvAddress;
328 break;
329 }
330 lpvAddress = (LPVOID)((ULONG)lpvAddress - PAGE_SIZE);
331 }
332 }
333 return sizeof(MEMORY_BASIC_INFORMATION);
334}
335//******************************************************************************
336//******************************************************************************
337#ifdef __WATCOMC__ /*PLF Sat 97-06-21 17:12:36*/
338 extern void interrupt3( void );
339 #pragma aux interrupt3= \
340 "int 3"
341#endif
342void WIN32API DebugBreak()
343{
344 dprintf(("DebugBreak\n"));
345#ifdef __WATCOMC__
346 interrupt3();
347#else
348 _interrupt(3);
349#endif
350}
351//******************************************************************************
352//TODO: Implement this??
353//******************************************************************************
354BOOL WIN32API GetThreadContext(HANDLE hThread, LPWINCONTEXT lpContext)
355{
356 dprintf(("GetThreadContext NOT IMPLEMENTED!! (TRUE)\n"));
357 memset(lpContext, 0, sizeof(WINCONTEXT));
358 return TRUE;
359}
360//******************************************************************************
361//TODO: Implement this??
362//******************************************************************************
363BOOL WIN32API SetThreadContext(HANDLE hThread, LPWINCONTEXT lpContext)
364{
365 dprintf(("SetThreadContext NOT IMPLEMENTED!!\n"));
366
367 return FALSE;
368}
369//******************************************************************************
370//******************************************************************************
371BOOL WIN32API VirtualLock( LPVOID lpAddress, DWORD dwSize )
372{
373 dprintf(("VirtualLock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
374 return TRUE;
375}
376
377//******************************************************************************
378BOOL WIN32API VirtualUnlock( LPVOID lpAddress, DWORD dwSize )
379{
380 dprintf(("VirtualUnlock at %d; %d bytes - stub (TRUE)\n", (int)lpAddress, dwSize));
381 return TRUE;
382}
383
384
385/*****************************************************************************
386 * Name : BOOL VirtualProtectEx
387 * Purpose : The VirtualProtectEx function changes the access protection on
388 * a region of committed pages in the virtual address space of a specified
389 * process. Note that this function differs from VirtualProtect,
390 * which changes the access protection on the calling process only.
391 * Parameters: HANDLE hProcess handle of process
392 * LPVOID lpvAddress address of region of committed pages
393 * DWORD cbSize size of region
394 * DWORD fdwNewProtect desired access protection
395 * PDWORD pfdwOldProtect address of variable to get old protection
396 * Variables :
397 * Result : size of target buffer
398 * Remark :
399 * Status : UNTESTED STUB
400 *
401 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
402 *****************************************************************************/
403
404BOOL WIN32API VirtualProtectEx(HANDLE hProcess,
405 LPVOID lpvAddress,
406 DWORD cbSize,
407 DWORD fdwNewProtect,
408 LPDWORD pfdwOldProtect)
409{
410 dprintf(("KERNEL32: VirtualProtectEx(%08x,%08xh,%08xh,%08xh,%08xh) not implemented for different processes.\n",
411 hProcess,
412 lpvAddress,
413 cbSize,
414 fdwNewProtect,
415 pfdwOldProtect));
416
417 return VirtualProtect(lpvAddress, cbSize, fdwNewProtect, pfdwOldProtect);
418}
419
420
421/*****************************************************************************
422 * Name : DWORD VirtualQueryEx
423 * Purpose : The VirtualQueryEx function provides information about a range
424 * of pages within the virtual address space of a specified process.
425 * Parameters: HANDLE hProcess handle of process
426 * LPCVOID lpvAddress address of region
427 * PMEMORY_BASIC_INFORMATION pmbiBuffer address of information buffer
428 * DWORD cbLength size of buffer
429 * Variables :
430 * Result : number of bytes returned in buffer
431 * Remark :
432 * Status : UNTESTED STUB
433 *
434 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
435 *****************************************************************************/
436
437DWORD WIN32API VirtualQueryEx(HANDLE hProcess,
438 LPVOID lpvAddress,
439 PMEMORY_BASIC_INFORMATION pmbiBuffer,
440 DWORD cbLength)
441{
442 dprintf(("KERNEL32: VirtualQueryEx(%08x,%08xh,%08xh,%08xh) not implemented for different processes.\n",
443 hProcess,
444 lpvAddress,
445 pmbiBuffer,
446 cbLength));
447
448 return VirtualQuery(lpvAddress, pmbiBuffer, cbLength);
449}
450
Note: See TracBrowser for help on using the repository browser.