Changeset 8877 for trunk/src/kernel32/virtual.cpp
- Timestamp:
- Jul 15, 2002, 4:28:53 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/virtual.cpp
r8866 r8877 1 /* $Id: virtual.cpp,v 1.4 7 2002-07-13 16:30:40sandervl Exp $ */1 /* $Id: virtual.cpp,v 1.48 2002-07-15 14:28:52 sandervl Exp $ */ 2 2 3 3 /* … … 28 28 #include "mmap.h" 29 29 #include "oslibdos.h" 30 #include "oslibmem.h" 30 31 31 32 #define DBG_LOCALLOG DBG_virtual … … 270 271 DWORD fdwProtect) 271 272 { 272 PVOID Address = lpvAddress;273 ULONG flag = 0, base;274 DWORD rc;275 276 SetLastError(ERROR_SUCCESS);277 278 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */279 {280 dprintf(("VirtualAlloc: size too large"));273 PVOID Address = lpvAddress; 274 ULONG flag = 0, base; 275 DWORD rc; 276 277 SetLastError(ERROR_SUCCESS); 278 279 if (cbSize > 0x7fc00000) /* 2Gb - 4Mb */ 280 { 281 dprintf(("VirtualAlloc: size too large")); 281 282 SetLastError( ERROR_OUTOFMEMORY ); 282 283 return NULL; 283 }284 285 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) ||284 } 285 286 if (!(fdwAllocationType & (MEM_COMMIT | MEM_RESERVE)) || 286 287 (fdwAllocationType & ~(MEM_COMMIT | MEM_RESERVE))) 287 {288 { 288 289 dprintf(("VirtualAlloc: Invalid parameter")); 289 290 SetLastError( ERROR_INVALID_PARAMETER ); 290 291 return NULL; 291 }292 293 if(fdwAllocationType & MEM_COMMIT)294 {292 } 293 294 if(fdwAllocationType & MEM_COMMIT) 295 { 295 296 dprintf(("VirtualAlloc: commit\n")); 296 297 flag = PAG_COMMIT; 297 }298 299 if(fdwAllocationType & MEM_RESERVE) {300 //SvL: DosRead crashes if memory is initially reserved with write298 } 299 300 if(fdwAllocationType & MEM_RESERVE) { 301 //SvL: DosRead crashes if memory is initially reserved with write 301 302 // access disabled (OS/2 bug) even if the commit sets the page 302 303 // flags to read/write: 303 // DosSetMem does not alter the 16 bit selectors so if you change memory304 // attributes and then access the memory with a 16 bit API (such as DosRead),305 // it will have the old (alloc time) attributes306 flag |= PAG_READ|PAG_WRITE;307 }308 if(fdwProtect & PAGE_READONLY) flag |= PAG_READ;309 if(fdwProtect & PAGE_NOACCESS) flag |= PAG_READ; //can't do this in OS/2310 if(fdwProtect & PAGE_READWRITE) flag |= (PAG_READ | PAG_WRITE);311 if(fdwProtect & PAGE_WRITECOPY) flag |= (PAG_READ | PAG_WRITE);312 313 if(fdwProtect & PAGE_EXECUTE_READWRITE) flag |= (PAG_EXECUTE | PAG_WRITE | PAG_READ);314 if(fdwProtect & PAGE_EXECUTE_READ) flag |= (PAG_EXECUTE | PAG_READ);315 if(fdwProtect & PAGE_EXECUTE) flag |= PAG_EXECUTE;316 317 if(fdwProtect & PAGE_GUARD) {304 // DosSetMem does not alter the 16 bit selectors so if you change memory 305 // attributes and then access the memory with a 16 bit API (such as DosRead), 306 // it will have the old (alloc time) attributes 307 flag |= PAG_READ|PAG_WRITE; 308 } 309 if(fdwProtect & PAGE_READONLY) flag |= PAG_READ; 310 if(fdwProtect & PAGE_NOACCESS) flag |= PAG_READ; //can't do this in OS/2 311 if(fdwProtect & PAGE_READWRITE) flag |= (PAG_READ | PAG_WRITE); 312 if(fdwProtect & PAGE_WRITECOPY) flag |= (PAG_READ | PAG_WRITE); 313 314 if(fdwProtect & PAGE_EXECUTE_READWRITE) flag |= (PAG_EXECUTE | PAG_WRITE | PAG_READ); 315 if(fdwProtect & PAGE_EXECUTE_READ) flag |= (PAG_EXECUTE | PAG_READ); 316 if(fdwProtect & PAGE_EXECUTE) flag |= PAG_EXECUTE; 317 318 if(fdwProtect & PAGE_GUARD) { 318 319 dprintf(("ERROR: PAGE_GUARD bit set for VirtualAlloc -> we don't support this right now!")); 319 320 flag |= PAG_GUARD; 320 } 321 322 //just do this if other options are used 323 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0) 324 { 325 dprintf(("VirtualAlloc: Unknown protection flags, default to read/write")); 326 flag |= PAG_READ | PAG_WRITE; 327 } 328 329 if(lpvAddress) 330 { 331 Win32MemMap *map; 332 ULONG offset, nrpages, accessflags = 0; 321 } 333 322 334 nrpages = cbSize >> PAGE_SHIFT; 335 if(cbSize & 0xFFF) 336 nrpages++; 337 338 if(flag & PAG_READ) { 339 accessflags |= MEMMAP_ACCESS_READ; 340 } 341 if(flag & PAG_WRITE) { 342 accessflags |= MEMMAP_ACCESS_WRITE; 343 } 344 if(flag & PAG_EXECUTE) { 345 accessflags |= MEMMAP_ACCESS_EXECUTE; 346 } 347 map = Win32MemMapView::findMapByView((ULONG)lpvAddress, &offset, accessflags); 348 if(map) { 349 //TODO: We don't allow protection flag changes for mmaped files now 350 map->commitPage(offset, FALSE, nrpages); 351 return lpvAddress; 352 } 353 } 354 355 // commit memory 356 if(fdwAllocationType & MEM_COMMIT) 357 { 358 Address = lpvAddress; 359 360 rc = OSLibDosSetMem(lpvAddress, cbSize, flag); 361 362 //might try to commit larger part with same base address 363 if(rc == OSLIB_ERROR_ACCESS_DENIED && cbSize > 4096 ) 364 { //knut: AND more than one page 365 char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page! 366 ULONG size, os2flags; 367 368 while(newbase >= (char *)lpvAddress) 369 { //knut: should check first page to!! 370 size = 4096; 371 os2flags = 0; 372 rc = OSLibDosQueryMem(newbase, &size, &os2flags); 373 if(rc) 374 break; 375 376 if(os2flags & PAG_COMMIT) 323 //just do this if other options are used 324 if(!(flag & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) || flag == 0) 325 { 326 dprintf(("VirtualAlloc: Unknown protection flags, default to read/write")); 327 flag |= PAG_READ | PAG_WRITE; 328 } 329 330 if(lpvAddress) 331 { 332 Win32MemMap *map; 333 ULONG offset, nrpages, accessflags = 0; 334 335 nrpages = cbSize >> PAGE_SHIFT; 336 if(cbSize & 0xFFF) 337 nrpages++; 338 339 if(flag & PAG_READ) { 340 accessflags |= MEMMAP_ACCESS_READ; 341 } 342 if(flag & PAG_WRITE) { 343 accessflags |= MEMMAP_ACCESS_WRITE; 344 } 345 if(flag & PAG_EXECUTE) { 346 accessflags |= MEMMAP_ACCESS_EXECUTE; 347 } 348 map = Win32MemMapView::findMapByView((ULONG)lpvAddress, &offset, accessflags); 349 if(map) { 350 //TODO: We don't allow protection flag changes for mmaped files now 351 map->commitPage(offset, FALSE, nrpages); 352 return lpvAddress; 353 } 354 } 355 356 // commit memory 357 if(fdwAllocationType & MEM_COMMIT) 358 { 359 Address = lpvAddress; 360 361 rc = OSLibDosSetMem(lpvAddress, cbSize, flag); 362 363 //might try to commit larger part with same base address 364 if(rc == OSLIB_ERROR_ACCESS_DENIED && cbSize > 4096 ) 365 { //knut: AND more than one page 366 char *newbase = (char *)lpvAddress + ((cbSize-1) & 0xFFFFF000); //knut: lets not start after the last page! 367 ULONG size, os2flags; 368 369 while(newbase >= (char *)lpvAddress) 370 { //knut: should check first page to!! 371 size = 4096; 372 os2flags = 0; 373 rc = OSLibDosQueryMem(newbase, &size, &os2flags); 374 if(rc) 375 break; 376 377 if(os2flags & PAG_COMMIT) 378 { 379 newbase += 4096; 380 break; 381 } 382 newbase -= 4096; 383 } 384 385 if(rc == 0) 377 386 { 378 newbase += 4096; 379 break; 387 //In case it wants to commit bytes that fall into the last 388 //page of the previous commit command 389 if(cbSize > ((int)newbase - (int)lpvAddress)) 390 rc = OSLibDosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag); 380 391 } 381 newbase -= 4096; 382 } 383 384 if(rc == 0) 392 else return(NULL); 393 } 394 else 385 395 { 386 //In case it wants to commit bytes that fall into the last 387 //page of the previous commit command 388 if(cbSize > ((int)newbase - (int)lpvAddress)) 389 rc = OSLibDosSetMem(newbase, cbSize - ((int)newbase - (int)lpvAddress), flag); 390 } 391 else return(NULL); 392 393 } 394 else 395 { 396 if(rc == OSLIB_ERROR_INVALID_ADDRESS) { 397 rc = OSLibDosAllocMem(&Address, cbSize, flag ); 398 } 399 else { 400 if(rc) { 401 //check if the app tries to commit an already commited part of memory or change the protection flags 402 ULONG size = cbSize, os2flags, newrc; 403 newrc = OSLibDosQueryMem(lpvAddress, &size, &os2flags); 404 if(newrc == 0) { 405 if(size >= cbSize && (os2flags & PAG_COMMIT)) { 406 dprintf(("VirtualAlloc: commit on committed memory")); 407 if((flag & (PAG_READ|PAG_WRITE|PAG_EXECUTE)) != (os2flags & (PAG_READ|PAG_WRITE|PAG_EXECUTE))) 408 { //change protection flags 409 DWORD tmp; 410 if(VirtualProtect(lpvAddress, cbSize, fdwProtect, &tmp) == TRUE) { 411 return lpvAddress; 396 if(rc == OSLIB_ERROR_INVALID_ADDRESS) { 397 rc = OSLibDosAllocMem(&Address, cbSize, flag ); 398 } 399 else { 400 if(rc) { 401 //check if the app tries to commit an already commited part of memory or change the protection flags 402 ULONG size = cbSize, os2flags, newrc; 403 newrc = OSLibDosQueryMem(lpvAddress, &size, &os2flags); 404 if(newrc == 0) { 405 if(size >= cbSize && (os2flags & PAG_COMMIT)) { 406 dprintf(("VirtualAlloc: commit on committed memory")); 407 if((flag & (PAG_READ|PAG_WRITE|PAG_EXECUTE)) != (os2flags & (PAG_READ|PAG_WRITE|PAG_EXECUTE))) 408 { //change protection flags 409 DWORD tmp; 410 if(VirtualProtect(lpvAddress, cbSize, fdwProtect, &tmp) == TRUE) { 411 return lpvAddress; 412 } 413 dprintf(("ERROR: VirtualAlloc: commit on committed memory -> VirtualProtect failed!!")); 414 return NULL; 412 415 } 413 dprintf(("ERROR: VirtualAlloc: commit on committed memory -> VirtualProtect failed!!")); 414 return NULL; 415 } 416 //else everything ok 417 return lpvAddress; 416 //else everything ok 417 return lpvAddress; 418 } 419 else dprintf(("Unexpected DosSetMem error %x", rc)); 418 420 } 419 else dprintf(("Unexpected DosSetMem error %x", rc)); 420 } 421 else { 422 dprintf(("Unexpected DosQueryMem error %x", newrc)); 421 else { 422 dprintf(("Unexpected DosQueryMem error %x", newrc)); 423 } 423 424 } 424 425 } 425 426 } 426 427 } 427 } 428 else 429 { 430 rc = OSLibDosAllocMem(&Address, cbSize, flag); 431 } 432 433 if(rc) 434 { 435 dprintf(("DosSetMem returned %d\n", rc)); 436 SetLastError( ERROR_OUTOFMEMORY ); 437 return(NULL); 438 } 439 440 dprintf(("VirtualAlloc returned %X\n", Address)); 441 return(Address); 428 else 429 { 430 rc = OSLibDosAllocMem(&Address, cbSize, flag); 431 } 432 433 if(rc) 434 { 435 dprintf(("DosSetMem returned %d\n", rc)); 436 SetLastError( ERROR_OUTOFMEMORY ); 437 return(NULL); 438 } 439 440 dprintf(("VirtualAlloc returned %X\n", Address)); 441 return(Address); 442 442 } 443 443 //****************************************************************************** … … 665 665 // flags used in the initial call to VirtualAlloc 666 666 pmbiBuffer->AllocationProtect = pmbiBuffer->Protect; 667 if(dAttr & PAG_BASE) { 668 pmbiBuffer->AllocationBase = lpBase; 669 } 670 else 671 { 672 pmbiBuffer->AllocationBase = 0; 673 while(lpBase > 0) 674 { 675 rc = OSLibDosQueryMem(lpBase, &cbRangeSize, &dAttr); 676 if(rc) { 677 dprintf(("VirtualQuery - OSLibDosQueryMem %x %x returned %d\n", 678 lpBase, cbLength, rc)); 679 break; 680 } 681 if(dAttr & PAG_BASE) { 682 pmbiBuffer->AllocationBase = lpBase; 683 break; 684 } 685 lpBase = (LPVOID)((ULONG)lpBase - PAGE_SIZE); 686 } 687 } 688 #if 0 689 //TODO!!!!!!!!!!!! 690 //NOTE: !!!!!!!!!!!!!!!!!!!!!!! 691 //Allocation base is always aligned at 64kb 692 //the page with the PAG_BASE attribute might not be the real allocation base 693 //(due to extra alloc + rounding (see oslibmem.cpp) 694 //Only exception to this rule is the stack 695 TEB *teb = GetThreadTEB(); 696 if(teb) { 697 if(pmbiBuffer->AllocationBase >= teb->stack_low && pmbiBuffer->AllocationBase < teb->stack_top) { 698 pmbiBuffer->AllocationBase = pmbiBuffer->AllocationBase; 699 } 700 else pmbiBuffer->AllocationBase = (LPVOID)(((DWORD)pmbiBuffer->AllocationBase + 0xFFFF) & 0xFFFF); 701 } 702 else pmbiBuffer->AllocationBase = (LPVOID)(((DWORD)pmbiBuffer->AllocationBase + 0xFFFF) & 0xFFFF); 703 //END NOTE: !!!!!!!!!!!!!!!!!!! 704 #endif 667 pmbiBuffer->AllocationBase = OSLibDosFindMemBase(lpBase); 705 668 706 669 dprintf(("Memory region alloc base 0x%08x", pmbiBuffer->AllocationBase));
Note:
See TracChangeset
for help on using the changeset viewer.