source: trunk/src/kernel32/oslibmem.cpp@ 9945

Last change on this file since 9945 was 9945, checked in by sandervl, 22 years ago

updates

File size: 10.5 KB
Line 
1/* $Id: oslibmem.cpp,v 1.7 2003-03-27 14:00:53 sandervl Exp $ */
2/*
3 * Wrappers for OS/2 Dos* API
4 *
5 * Copyright 1998-2002 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12
13
14/*******************************************************************************
15* Header Files *
16*******************************************************************************/
17#define INCL_BASE
18#define INCL_DOSEXCEPTIONS
19#define INCL_DOSMEMMGR
20#define INCL_DOSPROCESS
21#define INCL_DOSFILEMGR
22#define INCL_DOSERRORS
23#define INCL_DOSDEVIOCTL
24#define INCL_DOSDEVICES
25#define INCL_NPIPES
26#include <os2wrap.h> //Odin32 OS/2 api wrappers
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#include <ctype.h>
31#include <win32api.h>
32#include <winconst.h>
33#include <win\winioctl.h>
34#include <misc.h>
35#include "initterm.h"
36#include "oslibdos.h"
37#include "oslibmem.h"
38#include "dosqss.h"
39#include "win32k.h"
40
41#define DBG_LOCALLOG DBG_oslibmem
42#include "dbglocal.h"
43
44//******************************************************************************
45//TODO: Check if this works for code aliases...
46//NOTE: DosAliasMem fails if the address isn't page aligned
47//******************************************************************************
48DWORD OSLibDosAliasMem(LPVOID pb, ULONG cb, LPVOID *ppbAlias, ULONG fl)
49{
50 DWORD rc;
51 DWORD attr;
52 DWORD size = cb;
53
54 cb = (cb-1) & ~0xfff;
55 cb+= PAGE_SIZE;
56
57 rc = DosAliasMem(pb, cb, ppbAlias, 2);
58 if(rc) {
59 dprintf(("!ERROR!: OSLibDosAliasMem: DosAliasMem %x %x returned %d", pb, cb, rc));
60 return rc;
61 }
62 //Now try to change the protection flags of all pages in the aliased range
63 DWORD pAlias = (DWORD)*ppbAlias;
64
65 while(pAlias < (DWORD)*ppbAlias + cb)
66 {
67 rc = DosQueryMem((PVOID)pAlias, &size, &attr);
68 if(rc != NO_ERROR) {
69 dprintf(("!ERROR!: OSLibDosAliasMem: DosQueryMem %x returned %d", pAlias, rc));
70 DebugInt3();
71 return rc;
72 }
73 //Don't bother if the pages are not committed. DosSetMem will return
74 //ERROR_ACCESS_DENIED.
75 if(attr & PAG_COMMIT) {
76 rc = DosSetMem((PVOID)pAlias, size, fl);
77 if(rc) {
78 dprintf(("!ERROR!: OSLibDosAliasMem: DosSetMem %x %x return %d", *ppbAlias, size, rc));
79 DebugInt3();
80 return rc;
81 }
82 }
83 pAlias += size;
84 }
85 return 0;
86}
87//******************************************************************************
88//Allocate memory aligned at 64kb boundary
89//******************************************************************************
90DWORD OSLibDosAllocMem(LPVOID *lplpMemAddr, DWORD cbSize, DWORD flFlags, BOOL fLowMemory)
91{
92 PVOID pvMemAddr;
93 DWORD offset;
94 APIRET rc;
95 BOOL fMemFlags = flAllocMem;
96
97 //Override low/high memory flag if necessary
98 if(fLowMemory) {
99 fMemFlags = 0;
100 }
101 /*
102 * Let's try use the extended DosAllocMem API of Win32k.sys.
103 */
104 if (libWin32kInstalled())
105 {
106 rc = DosAllocMemEx(lplpMemAddr, cbSize, flFlags | fMemFlags | OBJ_ALIGN64K);
107 if (rc != ERROR_NOT_SUPPORTED) /* This call was stubbed until recently. */
108 return rc;
109 }
110
111 /*
112 * If no or old Win32k fall back to old method.
113 */
114
115 rc = DosAllocMem(&pvMemAddr, cbSize, flFlags | fMemFlags);
116 if(rc) {
117 dprintf(("!ERROR!: DosAllocMem failed with rc %d", rc));
118 return rc;
119 }
120 // already 64k aligned ?
121 if((ULONG) pvMemAddr & 0xFFFF)
122 {
123 ULONG addr64kb;
124
125 //free misaligned allocated memory
126 DosFreeMem(pvMemAddr);
127
128 //Allocate 64kb more so we can round the address to a 64kb aligned value
129 rc = DosAllocMem((PPVOID)&addr64kb, cbSize + 64*1024, (flFlags & ~PAG_COMMIT) | fMemFlags);
130 if(rc) {
131 dprintf(("!ERROR!: DosAllocMem failed with rc %d", rc));
132 return rc;
133 }
134 dprintf(("Allocate aligned memory %x -> %x", addr64kb, (addr64kb + 0xFFFF) & ~0xFFFF));
135
136 if(addr64kb & 0xFFFF) {
137 addr64kb = (addr64kb + 0xFFFF) & ~0xFFFF;
138 }
139 pvMemAddr = (PVOID)addr64kb;
140
141 //and set the correct page flags for the request range
142 if((flFlags & ~PAG_COMMIT) != flFlags) {
143 rc = DosSetMem(pvMemAddr, cbSize, flFlags);
144 if(rc) {
145 dprintf(("!ERROR!: DosSetMem failed with rc %d", rc));
146 return rc;
147 }
148 }
149 }
150
151 if(!rc)
152 *lplpMemAddr = pvMemAddr;
153
154 return rc;
155}
156//******************************************************************************
157//Locate the base page of a memory allocation (the page with the PAG_BASE attribute)
158//******************************************************************************
159PVOID OSLibDosFindMemBase(LPVOID lpMemAddr)
160{
161 ULONG ulAttr, ulSize, ulAddr;
162 APIRET rc;
163
164 rc = DosQueryMem(lpMemAddr, &ulSize, &ulAttr);
165 if(rc != NO_ERROR) {
166 dprintf(("!ERROR!: OSLibDosFindMemBase: DosQueryMem %x failed with rc %d", lpMemAddr, rc));
167 return lpMemAddr;
168 }
169 if(!(ulAttr & PAG_BASE)) {
170 //Not the base of the initial allocation (can happen due to alignment) or app
171 //passing address inside memory allocation range
172 ulAddr = (DWORD)lpMemAddr & ~0xFFF;
173 ulAddr -= PAGE_SIZE;
174
175 while(ulAddr > 0)
176 {
177 rc = DosQueryMem((PVOID)ulAddr, &ulSize, &ulAttr);
178 if(rc) {
179 dprintf(("!ERROR!: OSLibDosFindMemBase: DosQueryMem %x failed with rc %d", lpMemAddr, rc));
180 DebugInt3();
181 return NULL;
182 }
183 if(ulAttr & PAG_BASE) {
184 //Memory below the 512 MB boundary is always aligned at 64kb and VirtualAlloc only
185 //returns high memory (if OS/2 version supports it)
186 //If it is above the 512 MB boundary, then we must make sure the right base address
187 //is returned. VirtualAlloc allocates extra memory to make sure it can return addresses
188 //aligned at 64kb. If extra pages are needed, then the allocation base is inside
189 //the filler region. In that case we must return the next 64kb address as base.
190 if(ulAddr > MEM_TILED_CEILING) {
191 ulAddr = (ulAddr + 0xFFFF) & ~0xFFFF;
192 }
193 lpMemAddr = (PVOID)ulAddr;
194 break;
195 }
196 ulAddr -= PAGE_SIZE;
197 }
198 }
199 return lpMemAddr;
200}
201//******************************************************************************
202//******************************************************************************
203DWORD OSLibDosFreeMem(LPVOID lpMemAddr)
204{
205 ULONG ulAttr, ulSize, ulAddr;
206 APIRET rc;
207
208 ulAddr = (DWORD)lpMemAddr & ~0xFFF;
209 ulSize = 0x1000;
210
211 //Find base within previous 64kb (alignment can add filler pages)
212 for(int i=0;i<16;i++) {
213 rc = DosQueryMem((PVOID)ulAddr, &ulSize, &ulAttr);
214 if(rc != NO_ERROR) {
215 dprintf(("!ERROR!: OSLibDosFreeMem: DosQueryMem %x failed with rc %d", lpMemAddr, rc));
216 i = 16; //fail
217 break;
218 }
219 if(ulAttr & PAG_BASE) {
220 break;
221 }
222 ulAddr -= PAGE_SIZE;
223 }
224 if(i == 16) {
225 //oh, oh. didn't find base; shouldn't happen!!
226 dprintf(("!ERROR!: OSLibDosFreeMem: Unable to find base of %x", lpMemAddr));
227 DebugInt3();
228 }
229 else {
230 lpMemAddr = (PVOID)ulAddr;
231 }
232 return DosFreeMem(lpMemAddr);
233}
234//******************************************************************************
235//NOTE: If name == NULL, allocated gettable unnamed shared memory
236//OS/2 returns error 123 (invalid name) if the shared memory name includes
237//colons. We need to replace them with underscores.
238//******************************************************************************
239DWORD OSLibDosAllocSharedMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags, LPSTR name)
240{
241 APIRET rc;
242 char *sharedmemname = NULL, *tmp;
243
244 if(name) {
245 sharedmemname = (char *)malloc(strlen(name) + 16);
246 strcpy(sharedmemname, "\\SHAREMEM\\");
247 strcat(sharedmemname, name);
248 }
249 else flags |= OBJ_GETTABLE;
250
251 //SvL: Colons are unacceptable in shared memory names (for whatever reason)
252 tmp = sharedmemname;
253 while(*tmp != 0) {
254 if(*tmp == ':') {
255 *tmp = '_';
256 }
257 tmp++;
258 }
259
260 rc = DosAllocSharedMem(lplpMemAddr, sharedmemname, size, flags);
261 if(name) {
262 free(sharedmemname);
263 }
264 return rc;
265}
266//******************************************************************************
267//NOTE: If name == NULL, assume gettable unnamed shared memory
268//******************************************************************************
269DWORD OSLibDosGetNamedSharedMem(LPVOID *lplpMemAddr, LPSTR name)
270{
271 APIRET rc;
272 char *sharedmemname = NULL, *tmp;
273
274 if(name) {
275 sharedmemname = (char *)malloc(strlen(name) + 16);
276 strcpy(sharedmemname, "\\SHAREMEM\\");
277 strcat(sharedmemname, name);
278
279 //SvL: Colons are unacceptable in shared memory names (for whatever reason)
280 tmp = sharedmemname;
281 while(*tmp != 0) {
282 if(*tmp == ':') {
283 *tmp = '_';
284 }
285 tmp++;
286 }
287 rc = DosGetNamedSharedMem(lplpMemAddr, sharedmemname, PAG_READ|PAG_WRITE);
288 if(name) {
289 free(sharedmemname);
290 }
291 }
292 else rc = DosGetSharedMem((LPVOID)*(DWORD *)lplpMemAddr, PAG_READ|PAG_WRITE);
293
294 return rc;
295}
296//******************************************************************************
297//******************************************************************************
298DWORD OSLibDosQueryMem(LPVOID lpMemAddr, DWORD *lpRangeSize, DWORD *lpAttr)
299{
300 return DosQueryMem(lpMemAddr, lpRangeSize, lpAttr);
301}
302//******************************************************************************
303//******************************************************************************
304DWORD OSLibDosSetMem(LPVOID lpMemAddr, DWORD size, DWORD flags)
305{
306 APIRET rc;
307
308 rc = DosSetMem(lpMemAddr, size, flags);
309 switch(rc) {
310 case ERROR_INVALID_ADDRESS:
311 return OSLIB_ERROR_INVALID_ADDRESS;
312 case ERROR_ACCESS_DENIED:
313 return OSLIB_ERROR_ACCESS_DENIED;
314 default:
315 return rc;
316 }
317}
318//******************************************************************************
319//******************************************************************************
Note: See TracBrowser for help on using the repository browser.