[9945] | 1 | /* $Id: oslibmem.cpp,v 1.7 2003-03-27 14:00:53 sandervl Exp $ */
|
---|
[8864] | 2 | /*
|
---|
| 3 | * Wrappers for OS/2 Dos* API
|
---|
| 4 | *
|
---|
[8866] | 5 | * Copyright 1998-2002 Sander van Leeuwen (sandervl@xs4all.nl)
|
---|
[8864] | 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>
|
---|
[21916] | 33 | #include <win/winioctl.h>
|
---|
[21302] | 34 | #include <dbglog.h>
|
---|
| 35 | #include <vmutex.h>
|
---|
[8864] | 36 | #include "initterm.h"
|
---|
| 37 | #include "oslibdos.h"
|
---|
[8877] | 38 | #include "oslibmem.h"
|
---|
[8864] | 39 | #include "dosqss.h"
|
---|
| 40 | #include "win32k.h"
|
---|
[21302] | 41 | #include "exceptstackdump.h"
|
---|
[8864] | 42 |
|
---|
| 43 | #define DBG_LOCALLOG DBG_oslibmem
|
---|
| 44 | #include "dbglocal.h"
|
---|
| 45 |
|
---|
[21302] | 46 | #include <_ras.h>
|
---|
| 47 |
|
---|
| 48 | #ifdef RAS
|
---|
| 49 | RAS_TRACK_HANDLE rthVirtual = 0;
|
---|
| 50 |
|
---|
| 51 | void rasInitVirtual (void)
|
---|
| 52 | {
|
---|
| 53 | RasRegisterObjectTracking (&rthVirtual, "Virtual* memory allocation",
|
---|
| 54 | 0, RAS_TRACK_FLAG_MEMORY | RAS_TRACK_FLAG_LOG_OBJECTS_AT_EXIT,
|
---|
| 55 | NULL, NULL);
|
---|
| 56 | }
|
---|
| 57 | #endif
|
---|
| 58 |
|
---|
| 59 | typedef struct _VirtAllocRec {
|
---|
| 60 | ULONG baseaddr;
|
---|
| 61 | ULONG size;
|
---|
| 62 | ULONG attr;
|
---|
| 63 |
|
---|
| 64 | struct _VirtAllocRec *next;
|
---|
| 65 | } VirtAllocRec;
|
---|
| 66 |
|
---|
| 67 | static VirtAllocRec *allocrecords = NULL;
|
---|
| 68 | static CRITICAL_SECTION_OS2 alloccritsect = {0};
|
---|
| 69 |
|
---|
[8864] | 70 | //******************************************************************************
|
---|
[21302] | 71 | //******************************************************************************
|
---|
| 72 | void AddAllocRec(ULONG baseaddr, ULONG size, ULONG attr)
|
---|
| 73 | {
|
---|
| 74 | VirtAllocRec *rec, *tmp;
|
---|
| 75 |
|
---|
| 76 | rec = (VirtAllocRec *)malloc(sizeof(VirtAllocRec));
|
---|
| 77 | if(!rec) {
|
---|
| 78 | DebugInt3();
|
---|
| 79 | return;
|
---|
| 80 | }
|
---|
| 81 | rec->baseaddr = baseaddr;
|
---|
| 82 | rec->size = size;
|
---|
| 83 | rec->attr = attr;
|
---|
| 84 |
|
---|
| 85 | DosEnterCriticalSection(&alloccritsect);
|
---|
| 86 | if(!allocrecords || allocrecords->baseaddr > baseaddr) {
|
---|
| 87 | rec->next = allocrecords;
|
---|
| 88 | allocrecords = rec;
|
---|
| 89 | }
|
---|
| 90 | else {
|
---|
| 91 | tmp = allocrecords;
|
---|
| 92 | while(tmp->next) {
|
---|
[21916] | 93 | if(tmp->next->baseaddr > baseaddr) {
|
---|
[21302] | 94 | break;
|
---|
| 95 | }
|
---|
| 96 | tmp = tmp->next;
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | rec->next = tmp->next;
|
---|
| 100 | tmp->next = rec;
|
---|
| 101 | }
|
---|
| 102 | DosLeaveCriticalSection(&alloccritsect);
|
---|
| 103 | }
|
---|
| 104 | //******************************************************************************
|
---|
| 105 | //******************************************************************************
|
---|
| 106 | void FreeAllocRec(ULONG baseaddr)
|
---|
| 107 | {
|
---|
| 108 | VirtAllocRec *rec = NULL, *tmp;
|
---|
| 109 |
|
---|
| 110 | if(!allocrecords) {
|
---|
| 111 | DebugInt3();
|
---|
| 112 | return;
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | DosEnterCriticalSection(&alloccritsect);
|
---|
| 116 | if(allocrecords->baseaddr == baseaddr) {
|
---|
| 117 | rec = allocrecords;
|
---|
| 118 | allocrecords = allocrecords->next;
|
---|
| 119 | }
|
---|
| 120 | else {
|
---|
| 121 | tmp = allocrecords;
|
---|
| 122 | while(tmp->next) {
|
---|
[21916] | 123 | if(tmp->next->baseaddr == baseaddr) {
|
---|
[21302] | 124 | break;
|
---|
| 125 | }
|
---|
| 126 | tmp = tmp->next;
|
---|
| 127 | }
|
---|
| 128 | if(tmp->next) {
|
---|
| 129 | rec = tmp->next;
|
---|
| 130 | tmp->next = tmp->next->next;
|
---|
| 131 | }
|
---|
| 132 | else dprintf(("ERROR: FreeAllocRec: allocation not found!! (%x)", baseaddr));
|
---|
| 133 | }
|
---|
| 134 | DosLeaveCriticalSection(&alloccritsect);
|
---|
| 135 | if(rec) free(rec);
|
---|
| 136 | }
|
---|
| 137 | //******************************************************************************
|
---|
| 138 | //******************************************************************************
|
---|
| 139 | BOOL FindAllocRec(ULONG addr, ULONG *lpBase, ULONG *lpSize, ULONG *lpAttr)
|
---|
| 140 | {
|
---|
| 141 | VirtAllocRec *rec = NULL;
|
---|
| 142 |
|
---|
| 143 | DosEnterCriticalSection(&alloccritsect);
|
---|
| 144 | rec = allocrecords;
|
---|
| 145 | while(rec) {
|
---|
| 146 | if(rec->baseaddr <= addr && rec->baseaddr + rec->size > addr) {
|
---|
| 147 | *lpBase = rec->baseaddr;
|
---|
| 148 | *lpSize = rec->size;
|
---|
| 149 | *lpAttr = rec->attr;
|
---|
| 150 | break; //found it
|
---|
| 151 | }
|
---|
| 152 | if(rec->baseaddr > addr) {
|
---|
| 153 | //sorted list, so no need to search any further
|
---|
| 154 | rec = NULL;
|
---|
| 155 | break;
|
---|
| 156 | }
|
---|
| 157 | rec = rec->next;
|
---|
| 158 | }
|
---|
| 159 | DosLeaveCriticalSection(&alloccritsect);
|
---|
| 160 | return (rec != NULL);
|
---|
| 161 | }
|
---|
| 162 | //******************************************************************************
|
---|
[8864] | 163 | //TODO: Check if this works for code aliases...
|
---|
[9945] | 164 | //NOTE: DosAliasMem fails if the address isn't page aligned
|
---|
[8864] | 165 | //******************************************************************************
|
---|
| 166 | DWORD OSLibDosAliasMem(LPVOID pb, ULONG cb, LPVOID *ppbAlias, ULONG fl)
|
---|
| 167 | {
|
---|
[8866] | 168 | DWORD rc;
|
---|
| 169 | DWORD attr;
|
---|
| 170 | DWORD size = cb;
|
---|
[8864] | 171 |
|
---|
[8866] | 172 | cb = (cb-1) & ~0xfff;
|
---|
| 173 | cb+= PAGE_SIZE;
|
---|
[8864] | 174 |
|
---|
[8866] | 175 | rc = DosAliasMem(pb, cb, ppbAlias, 2);
|
---|
| 176 | if(rc) {
|
---|
[8877] | 177 | dprintf(("!ERROR!: OSLibDosAliasMem: DosAliasMem %x %x returned %d", pb, cb, rc));
|
---|
[8864] | 178 | return rc;
|
---|
[8866] | 179 | }
|
---|
[9911] | 180 | //Now try to change the protection flags of all pages in the aliased range
|
---|
| 181 | DWORD pAlias = (DWORD)*ppbAlias;
|
---|
| 182 |
|
---|
[21916] | 183 | while(pAlias < (DWORD)*ppbAlias + cb)
|
---|
[9911] | 184 | {
|
---|
| 185 | rc = DosQueryMem((PVOID)pAlias, &size, &attr);
|
---|
| 186 | if(rc != NO_ERROR) {
|
---|
| 187 | dprintf(("!ERROR!: OSLibDosAliasMem: DosQueryMem %x returned %d", pAlias, rc));
|
---|
| 188 | DebugInt3();
|
---|
[8866] | 189 | return rc;
|
---|
[8864] | 190 | }
|
---|
[21916] | 191 | //Don't bother if the pages are not committed. DosSetMem will return
|
---|
| 192 | //ERROR_ACCESS_DENIED.
|
---|
[9911] | 193 | if(attr & PAG_COMMIT) {
|
---|
| 194 | rc = DosSetMem((PVOID)pAlias, size, fl);
|
---|
| 195 | if(rc) {
|
---|
| 196 | dprintf(("!ERROR!: OSLibDosAliasMem: DosSetMem %x %x return %d", *ppbAlias, size, rc));
|
---|
| 197 | DebugInt3();
|
---|
| 198 | return rc;
|
---|
| 199 | }
|
---|
| 200 | }
|
---|
| 201 | pAlias += size;
|
---|
[8866] | 202 | }
|
---|
[21302] | 203 | AddAllocRec((ULONG)*ppbAlias, cb, fl);
|
---|
[8866] | 204 | return 0;
|
---|
[8864] | 205 | }
|
---|
[21339] | 206 |
|
---|
| 207 | //***************************************************************************
|
---|
| 208 | //Allocation memory at address helper
|
---|
| 209 | //***************************************************************************
|
---|
| 210 | #define OBJ_LOCSPECIFIC 0x00001000UL
|
---|
| 211 |
|
---|
| 212 | int allocAtAddress(void *pvReq, ULONG cbReq, ULONG fReq)
|
---|
| 213 | {
|
---|
| 214 | dprintf(("DosAllocMemEx pvReq=%p cbReq=%lu fReq=%#lx\n", pvReq, cbReq, fReq));
|
---|
| 215 | PVOID apvTmps[3000];
|
---|
| 216 | ULONG cbTmp;
|
---|
| 217 | ULONG fTmp;
|
---|
| 218 | int iTmp;
|
---|
| 219 | int rcRet = ERROR_NOT_ENOUGH_MEMORY;
|
---|
| 220 |
|
---|
| 221 | /*
|
---|
| 222 | * Adjust flags and size.
|
---|
| 223 | */
|
---|
| 224 | if ((ULONG)pvReq < 0x20000000 /*512MB*/)
|
---|
| 225 | fReq &= ~OBJ_ANY;
|
---|
| 226 | else
|
---|
| 227 | fReq |= OBJ_ANY;
|
---|
| 228 | cbReq = (cbReq + 0xfff) & ~0xfff;
|
---|
| 229 |
|
---|
| 230 | /*
|
---|
| 231 | * Allocation loop.
|
---|
| 232 | * This algorithm is not optimal!
|
---|
| 233 | */
|
---|
| 234 | fTmp = fReq & ~(PAG_COMMIT);
|
---|
| 235 | cbTmp = 1*1024*1024; /* 1MB*/
|
---|
| 236 | for (iTmp = 0; iTmp < sizeof(apvTmps) / sizeof(apvTmps[0]); iTmp++)
|
---|
| 237 | {
|
---|
| 238 | PVOID pvNew = NULL;
|
---|
| 239 | int rc;
|
---|
| 240 |
|
---|
| 241 | /* Allocate chunk. */
|
---|
| 242 | rc = DosAllocMem(&pvNew, cbReq, fReq);
|
---|
| 243 | apvTmps[iTmp] = pvNew;
|
---|
| 244 | if (rc)
|
---|
| 245 | break;
|
---|
| 246 |
|
---|
| 247 | /*
|
---|
| 248 | * Passed it?
|
---|
| 249 | * Then retry with the requested size.
|
---|
| 250 | */
|
---|
| 251 | if (pvNew > pvReq)
|
---|
| 252 | {
|
---|
| 253 | if (cbTmp <= cbReq)
|
---|
| 254 | break;
|
---|
| 255 | DosFreeMem(pvNew);
|
---|
| 256 | cbTmp = cbReq;
|
---|
| 257 | iTmp--;
|
---|
| 258 | continue;
|
---|
| 259 | }
|
---|
| 260 |
|
---|
| 261 | /*
|
---|
| 262 | * Does the allocated object touch into the requested one?
|
---|
| 263 | */
|
---|
| 264 | if ((char *)pvNew + cbTmp > (char *)pvReq)
|
---|
| 265 | {
|
---|
| 266 | /*
|
---|
| 267 | * Yes, we've found the requested address!
|
---|
| 268 | */
|
---|
| 269 | apvTmps[iTmp] = NULL;
|
---|
| 270 | DosFreeMem(pvNew);
|
---|
| 271 |
|
---|
| 272 | /*
|
---|
| 273 | * Adjust the allocation size to fill the gap between the
|
---|
| 274 | * one we just got and the requested one.
|
---|
| 275 | * If no gap we'll attempt the real allocation.
|
---|
| 276 | */
|
---|
| 277 | cbTmp = (ULONG)pvReq - (ULONG)pvNew;
|
---|
| 278 | if (cbTmp)
|
---|
| 279 | {
|
---|
| 280 | iTmp--;
|
---|
| 281 | continue;
|
---|
| 282 | }
|
---|
| 283 |
|
---|
| 284 | rc = DosAllocMem(&pvNew, cbReq, fReq);
|
---|
| 285 | if (rc || (char *)pvNew > (char *)pvReq)
|
---|
| 286 | break; /* we failed! */
|
---|
| 287 | if (pvNew == pvReq)
|
---|
| 288 | {
|
---|
| 289 | rcRet = 0;
|
---|
| 290 | break;
|
---|
| 291 | }
|
---|
| 292 |
|
---|
| 293 | /*
|
---|
| 294 | * We've got an object which start is below the one we
|
---|
| 295 | * requested. This is probably caused by the requested object
|
---|
| 296 | * fitting in somewhere our tmp objects didn't.
|
---|
| 297 | * So, we'll have loop and retry till all such holes are filled.
|
---|
| 298 | */
|
---|
| 299 | apvTmps[iTmp] = pvNew;
|
---|
| 300 | }
|
---|
| 301 | }
|
---|
| 302 |
|
---|
| 303 | /*
|
---|
| 304 | * Cleanup reserved memory and return.
|
---|
| 305 | */
|
---|
| 306 | while (iTmp-- > 0)
|
---|
| 307 | if (apvTmps[iTmp])
|
---|
| 308 | DosFreeMem(apvTmps[iTmp]);
|
---|
| 309 |
|
---|
| 310 | return rcRet;
|
---|
| 311 | }
|
---|
| 312 |
|
---|
[8864] | 313 | //******************************************************************************
|
---|
[8877] | 314 | //Allocate memory aligned at 64kb boundary
|
---|
[8864] | 315 | //******************************************************************************
|
---|
[8882] | 316 | DWORD OSLibDosAllocMem(LPVOID *lplpMemAddr, DWORD cbSize, DWORD flFlags, BOOL fLowMemory)
|
---|
[8864] | 317 | {
|
---|
| 318 | PVOID pvMemAddr;
|
---|
| 319 | DWORD offset;
|
---|
| 320 | APIRET rc;
|
---|
[8882] | 321 | BOOL fMemFlags = flAllocMem;
|
---|
[8864] | 322 |
|
---|
[8882] | 323 | //Override low/high memory flag if necessary
|
---|
| 324 | if(fLowMemory) {
|
---|
| 325 | fMemFlags = 0;
|
---|
| 326 | }
|
---|
[21916] | 327 |
|
---|
[8864] | 328 | /*
|
---|
| 329 | * Let's try use the extended DosAllocMem API of Win32k.sys.
|
---|
| 330 | */
|
---|
| 331 | if (libWin32kInstalled())
|
---|
| 332 | {
|
---|
[8882] | 333 | rc = DosAllocMemEx(lplpMemAddr, cbSize, flFlags | fMemFlags | OBJ_ALIGN64K);
|
---|
[21302] | 334 | #ifdef RAS
|
---|
| 335 | if (rc == NO_ERROR)
|
---|
| 336 | {
|
---|
| 337 | RasAddObject (rthVirtual, (ULONG)*lplpMemAddr, NULL, cbSize);
|
---|
| 338 | }
|
---|
| 339 | #endif
|
---|
[8864] | 340 | if (rc != ERROR_NOT_SUPPORTED) /* This call was stubbed until recently. */
|
---|
| 341 | return rc;
|
---|
| 342 | }
|
---|
| 343 |
|
---|
| 344 | /*
|
---|
| 345 | * If no or old Win32k fall back to old method.
|
---|
| 346 | */
|
---|
| 347 |
|
---|
[21339] | 348 | if (flFlags & OBJ_LOCSPECIFIC)
|
---|
| 349 | {
|
---|
| 350 | rc = allocAtAddress(&pvMemAddr, cbSize, (flFlags & ~OBJ_LOCSPECIFIC) | fMemFlags);
|
---|
| 351 | } else
|
---|
| 352 | {
|
---|
| 353 | rc = DosAllocMem(&pvMemAddr, cbSize, flFlags | fMemFlags);
|
---|
| 354 | }
|
---|
[8864] | 355 | if(rc) {
|
---|
[8877] | 356 | dprintf(("!ERROR!: DosAllocMem failed with rc %d", rc));
|
---|
[8864] | 357 | return rc;
|
---|
| 358 | }
|
---|
| 359 | // already 64k aligned ?
|
---|
[21916] | 360 | if((ULONG) pvMemAddr & 0xFFFF)
|
---|
[8866] | 361 | {
|
---|
[8877] | 362 | ULONG addr64kb;
|
---|
[8864] | 363 |
|
---|
[8877] | 364 | //free misaligned allocated memory
|
---|
| 365 | DosFreeMem(pvMemAddr);
|
---|
| 366 |
|
---|
[8866] | 367 | //Allocate 64kb more so we can round the address to a 64kb aligned value
|
---|
[8882] | 368 | rc = DosAllocMem((PPVOID)&addr64kb, cbSize + 64*1024, (flFlags & ~PAG_COMMIT) | fMemFlags);
|
---|
[8866] | 369 | if(rc) {
|
---|
[8877] | 370 | dprintf(("!ERROR!: DosAllocMem failed with rc %d", rc));
|
---|
[8866] | 371 | return rc;
|
---|
| 372 | }
|
---|
[21916] | 373 |
|
---|
[21302] | 374 | PVOID baseAddr = (PVOID)addr64kb; // sunlover20040613: save returned address for a possible Free on failure
|
---|
[21916] | 375 |
|
---|
[8877] | 376 | dprintf(("Allocate aligned memory %x -> %x", addr64kb, (addr64kb + 0xFFFF) & ~0xFFFF));
|
---|
| 377 |
|
---|
[8866] | 378 | if(addr64kb & 0xFFFF) {
|
---|
[8877] | 379 | addr64kb = (addr64kb + 0xFFFF) & ~0xFFFF;
|
---|
[8866] | 380 | }
|
---|
| 381 | pvMemAddr = (PVOID)addr64kb;
|
---|
| 382 |
|
---|
| 383 | //and set the correct page flags for the request range
|
---|
[8877] | 384 | if((flFlags & ~PAG_COMMIT) != flFlags) {
|
---|
| 385 | rc = DosSetMem(pvMemAddr, cbSize, flFlags);
|
---|
| 386 | if(rc) {
|
---|
| 387 | dprintf(("!ERROR!: DosSetMem failed with rc %d", rc));
|
---|
[21302] | 388 | DosFreeMem (baseAddr); // sunlover20040613: Free allocated memory
|
---|
[8877] | 389 | return rc;
|
---|
| 390 | }
|
---|
| 391 | }
|
---|
[8866] | 392 | }
|
---|
[8877] | 393 |
|
---|
[21302] | 394 | if(!rc) {
|
---|
[8864] | 395 | *lplpMemAddr = pvMemAddr;
|
---|
[21302] | 396 | AddAllocRec((ULONG)pvMemAddr, cbSize, flFlags);
|
---|
| 397 | RasAddObject (rthVirtual, (ULONG)*lplpMemAddr, NULL, cbSize);
|
---|
| 398 | }
|
---|
[8864] | 399 | return rc;
|
---|
| 400 | }
|
---|
| 401 | //******************************************************************************
|
---|
[8877] | 402 | //Locate the base page of a memory allocation (the page with the PAG_BASE attribute)
|
---|
[8864] | 403 | //******************************************************************************
|
---|
[21302] | 404 | PVOID OSLibDosFindMemBase(LPVOID lpMemAddr, DWORD *lpAttr)
|
---|
[8877] | 405 | {
|
---|
[21302] | 406 | ULONG ulAttr, ulSize, ulAddr, ulBase;
|
---|
[8877] | 407 | APIRET rc;
|
---|
[21302] | 408 | VirtAllocRec *allocrec;
|
---|
| 409 |
|
---|
| 410 | *lpAttr = 0;
|
---|
[21916] | 411 |
|
---|
[21302] | 412 | if(FindAllocRec((ULONG)lpMemAddr, &ulBase, &ulSize, lpAttr) == TRUE) {
|
---|
| 413 | return (PVOID)ulBase;
|
---|
| 414 | }
|
---|
[21916] | 415 |
|
---|
[21302] | 416 | ulSize = PAGE_SIZE;
|
---|
[8877] | 417 | rc = DosQueryMem(lpMemAddr, &ulSize, &ulAttr);
|
---|
| 418 | if(rc != NO_ERROR) {
|
---|
| 419 | dprintf(("!ERROR!: OSLibDosFindMemBase: DosQueryMem %x failed with rc %d", lpMemAddr, rc));
|
---|
| 420 | return lpMemAddr;
|
---|
| 421 | }
|
---|
| 422 | if(!(ulAttr & PAG_BASE)) {
|
---|
| 423 | //Not the base of the initial allocation (can happen due to alignment) or app
|
---|
| 424 | //passing address inside memory allocation range
|
---|
| 425 | ulAddr = (DWORD)lpMemAddr & ~0xFFF;
|
---|
| 426 | ulAddr -= PAGE_SIZE;
|
---|
| 427 |
|
---|
| 428 | while(ulAddr > 0)
|
---|
| 429 | {
|
---|
| 430 | rc = DosQueryMem((PVOID)ulAddr, &ulSize, &ulAttr);
|
---|
| 431 | if(rc) {
|
---|
| 432 | dprintf(("!ERROR!: OSLibDosFindMemBase: DosQueryMem %x failed with rc %d", lpMemAddr, rc));
|
---|
| 433 | DebugInt3();
|
---|
| 434 | return NULL;
|
---|
| 435 | }
|
---|
| 436 | if(ulAttr & PAG_BASE) {
|
---|
| 437 | //Memory below the 512 MB boundary is always aligned at 64kb and VirtualAlloc only
|
---|
| 438 | //returns high memory (if OS/2 version supports it)
|
---|
| 439 | //If it is above the 512 MB boundary, then we must make sure the right base address
|
---|
| 440 | //is returned. VirtualAlloc allocates extra memory to make sure it can return addresses
|
---|
| 441 | //aligned at 64kb. If extra pages are needed, then the allocation base is inside
|
---|
| 442 | //the filler region. In that case we must return the next 64kb address as base.
|
---|
| 443 | if(ulAddr > MEM_TILED_CEILING) {
|
---|
| 444 | ulAddr = (ulAddr + 0xFFFF) & ~0xFFFF;
|
---|
| 445 | }
|
---|
| 446 | lpMemAddr = (PVOID)ulAddr;
|
---|
| 447 | break;
|
---|
| 448 | }
|
---|
| 449 | ulAddr -= PAGE_SIZE;
|
---|
| 450 | }
|
---|
| 451 | }
|
---|
| 452 | return lpMemAddr;
|
---|
| 453 | }
|
---|
| 454 | //******************************************************************************
|
---|
| 455 | //******************************************************************************
|
---|
[8864] | 456 | DWORD OSLibDosFreeMem(LPVOID lpMemAddr)
|
---|
| 457 | {
|
---|
[8877] | 458 | ULONG ulAttr, ulSize, ulAddr;
|
---|
| 459 | APIRET rc;
|
---|
| 460 |
|
---|
[9292] | 461 | ulAddr = (DWORD)lpMemAddr & ~0xFFF;
|
---|
| 462 | ulSize = 0x1000;
|
---|
[8877] | 463 |
|
---|
| 464 | //Find base within previous 64kb (alignment can add filler pages)
|
---|
[21916] | 465 | int i;
|
---|
| 466 | for(i=0;i<16;i++) {
|
---|
[8877] | 467 | rc = DosQueryMem((PVOID)ulAddr, &ulSize, &ulAttr);
|
---|
| 468 | if(rc != NO_ERROR) {
|
---|
| 469 | dprintf(("!ERROR!: OSLibDosFreeMem: DosQueryMem %x failed with rc %d", lpMemAddr, rc));
|
---|
| 470 | i = 16; //fail
|
---|
| 471 | break;
|
---|
| 472 | }
|
---|
| 473 | if(ulAttr & PAG_BASE) {
|
---|
| 474 | break;
|
---|
| 475 | }
|
---|
| 476 | ulAddr -= PAGE_SIZE;
|
---|
| 477 | }
|
---|
| 478 | if(i == 16) {
|
---|
| 479 | //oh, oh. didn't find base; shouldn't happen!!
|
---|
| 480 | dprintf(("!ERROR!: OSLibDosFreeMem: Unable to find base of %x", lpMemAddr));
|
---|
| 481 | DebugInt3();
|
---|
[21302] | 482 | return ERROR_INVALID_PARAMETER;
|
---|
[8877] | 483 | }
|
---|
[21302] | 484 | FreeAllocRec((ULONG)lpMemAddr);
|
---|
[21916] | 485 |
|
---|
[21302] | 486 | RasRemoveObject (rthVirtual, (ULONG)lpMemAddr);
|
---|
| 487 |
|
---|
| 488 | return DosFreeMem((PVOID)ulAddr);
|
---|
[8864] | 489 | }
|
---|
| 490 | //******************************************************************************
|
---|
| 491 | //NOTE: If name == NULL, allocated gettable unnamed shared memory
|
---|
| 492 | //OS/2 returns error 123 (invalid name) if the shared memory name includes
|
---|
| 493 | //colons. We need to replace them with underscores.
|
---|
| 494 | //******************************************************************************
|
---|
| 495 | DWORD OSLibDosAllocSharedMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags, LPSTR name)
|
---|
| 496 | {
|
---|
[8866] | 497 | APIRET rc;
|
---|
| 498 | char *sharedmemname = NULL, *tmp;
|
---|
[8864] | 499 |
|
---|
[8866] | 500 | if(name) {
|
---|
| 501 | sharedmemname = (char *)malloc(strlen(name) + 16);
|
---|
| 502 | strcpy(sharedmemname, "\\SHAREMEM\\");
|
---|
| 503 | strcat(sharedmemname, name);
|
---|
| 504 | }
|
---|
| 505 | else flags |= OBJ_GETTABLE;
|
---|
[8864] | 506 |
|
---|
[8866] | 507 | //SvL: Colons are unacceptable in shared memory names (for whatever reason)
|
---|
| 508 | tmp = sharedmemname;
|
---|
| 509 | while(*tmp != 0) {
|
---|
[8864] | 510 | if(*tmp == ':') {
|
---|
| 511 | *tmp = '_';
|
---|
| 512 | }
|
---|
| 513 | tmp++;
|
---|
[8866] | 514 | }
|
---|
[8864] | 515 |
|
---|
[8866] | 516 | rc = DosAllocSharedMem(lplpMemAddr, sharedmemname, size, flags);
|
---|
| 517 | if(name) {
|
---|
[8864] | 518 | free(sharedmemname);
|
---|
[8866] | 519 | }
|
---|
| 520 | return rc;
|
---|
[8864] | 521 | }
|
---|
| 522 | //******************************************************************************
|
---|
| 523 | //NOTE: If name == NULL, assume gettable unnamed shared memory
|
---|
| 524 | //******************************************************************************
|
---|
| 525 | DWORD OSLibDosGetNamedSharedMem(LPVOID *lplpMemAddr, LPSTR name)
|
---|
| 526 | {
|
---|
[8866] | 527 | APIRET rc;
|
---|
| 528 | char *sharedmemname = NULL, *tmp;
|
---|
[8864] | 529 |
|
---|
[8866] | 530 | if(name) {
|
---|
[8864] | 531 | sharedmemname = (char *)malloc(strlen(name) + 16);
|
---|
| 532 | strcpy(sharedmemname, "\\SHAREMEM\\");
|
---|
| 533 | strcat(sharedmemname, name);
|
---|
| 534 |
|
---|
| 535 | //SvL: Colons are unacceptable in shared memory names (for whatever reason)
|
---|
| 536 | tmp = sharedmemname;
|
---|
| 537 | while(*tmp != 0) {
|
---|
| 538 | if(*tmp == ':') {
|
---|
| 539 | *tmp = '_';
|
---|
| 540 | }
|
---|
| 541 | tmp++;
|
---|
| 542 | }
|
---|
| 543 | rc = DosGetNamedSharedMem(lplpMemAddr, sharedmemname, PAG_READ|PAG_WRITE);
|
---|
| 544 | if(name) {
|
---|
| 545 | free(sharedmemname);
|
---|
| 546 | }
|
---|
[8866] | 547 | }
|
---|
| 548 | else rc = DosGetSharedMem((LPVOID)*(DWORD *)lplpMemAddr, PAG_READ|PAG_WRITE);
|
---|
[8864] | 549 |
|
---|
[8866] | 550 | return rc;
|
---|
[8864] | 551 | }
|
---|
| 552 | //******************************************************************************
|
---|
| 553 | //******************************************************************************
|
---|
| 554 | DWORD OSLibDosQueryMem(LPVOID lpMemAddr, DWORD *lpRangeSize, DWORD *lpAttr)
|
---|
| 555 | {
|
---|
[8866] | 556 | return DosQueryMem(lpMemAddr, lpRangeSize, lpAttr);
|
---|
[8864] | 557 | }
|
---|
| 558 | //******************************************************************************
|
---|
| 559 | //******************************************************************************
|
---|
| 560 | DWORD OSLibDosSetMem(LPVOID lpMemAddr, DWORD size, DWORD flags)
|
---|
| 561 | {
|
---|
[8866] | 562 | APIRET rc;
|
---|
[8864] | 563 |
|
---|
[8866] | 564 | rc = DosSetMem(lpMemAddr, size, flags);
|
---|
| 565 | switch(rc) {
|
---|
| 566 | case ERROR_INVALID_ADDRESS:
|
---|
| 567 | return OSLIB_ERROR_INVALID_ADDRESS;
|
---|
| 568 | case ERROR_ACCESS_DENIED:
|
---|
| 569 | return OSLIB_ERROR_ACCESS_DENIED;
|
---|
| 570 | default:
|
---|
| 571 | return rc;
|
---|
| 572 | }
|
---|
[8864] | 573 | }
|
---|
| 574 | //******************************************************************************
|
---|
| 575 | //******************************************************************************
|
---|