mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
984 lines
35 KiB
984 lines
35 KiB
/****************************************************************************
|
|
MEMORY.C
|
|
|
|
$Log: S:\products\wangview\oiwh\display\memory.c_v $
|
|
*
|
|
* Rev 1.14 22 Apr 1996 07:46:40 BEG06016
|
|
* Cleaned up error checking.
|
|
*
|
|
* Rev 1.13 12 Apr 1996 11:21:48 BEG06016
|
|
* Fixed various memory manager bugs.
|
|
*
|
|
* Rev 1.12 05 Apr 1996 11:27:38 BEG06016
|
|
* Fixed misc memory manager bugs..
|
|
*
|
|
* Rev 1.11 03 Apr 1996 13:28:26 BEG06016
|
|
* Modified memory manager to speed up performance after display of large image.
|
|
*
|
|
* Rev 1.10 23 Feb 1996 18:22:36 RC
|
|
* Long aligned memory allocation
|
|
*
|
|
* Rev 1.9 22 Feb 1996 14:59:08 BEG06016
|
|
* Removed unused code.
|
|
*
|
|
* Rev 1.8 09 Feb 1996 08:23:34 BLJ
|
|
* Changed the memory styructure to accomodate NT memory change.
|
|
*
|
|
* Rev 1.7 06 Feb 1996 11:04:34 BLJ
|
|
* Added ability to #define the memory to not free the image memory.
|
|
*
|
|
* Rev 1.6 04 Jan 1996 14:28:40 BLJ
|
|
* Fixed a memory manager bug.
|
|
*
|
|
* Rev 1.5 02 Jan 1996 10:00:18 BLJ
|
|
* Changed alot of UINTs to ints.
|
|
* Changed IMG structure to include the image data.
|
|
* Changed lp prefix to p.
|
|
*
|
|
* Rev 1.4 22 Dec 1995 11:47:02 BLJ
|
|
* Added a parameter for zero init'ing to some memory manager calls.
|
|
*
|
|
* Rev 1.2 22 Dec 1995 11:12:00 BLJ
|
|
* Added a parameter for zero init'ing to some memory manager calls.
|
|
*
|
|
* Rev 1.1 18 Dec 1995 10:52:42 BLJ
|
|
* Fixed memory manager bug in the hashing algorithm.
|
|
*
|
|
* Rev 1.0 12 Dec 1995 10:03:36 BLJ
|
|
* Initial entry
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "privdisp.h"
|
|
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: AllocateMemory
|
|
|
|
PURPOSE: This routine allocates the memory requested and returns a
|
|
pointer to it.
|
|
|
|
INPUTS: nSize - The size of the block to be allocated.
|
|
ppBlock - The pointer to where the pointer is to be returned.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI AllocateMemory(int nSize, PPSTR ppBlock, BOOL bZeroInit){
|
|
|
|
int nStatus = 0;
|
|
|
|
PSUB_SEG_MEMORY_BLOCK pssBlock;
|
|
SUB_SEG_MEMORY_BLOCK ssBlock1;
|
|
SUB_SEG_MEMORY_BLOCK ssBlock2;
|
|
int nCommitSize;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockLo;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockHi;
|
|
int nMemBlockSize;
|
|
int nBlockIndex;
|
|
|
|
|
|
// nSize += 2000;
|
|
nSize = (nSize + 3) & ~3 ; // long align
|
|
*ppBlock = 0;
|
|
if (!nSize){
|
|
goto Exit; // Nothing to allocate, so return *ppBlock = 0;
|
|
}
|
|
nMemBlockSize = pSubSegMemory->nMemBlockSize;
|
|
|
|
if (nSize < LO_MEMORY_MAX_BLOCK_SIZE){
|
|
// Allocate memory in the small memory range.
|
|
// Find a block big enough to hold this block.
|
|
pBlockLo = pSubSegMemory->pBlockLo;
|
|
for (nBlockIndex = 0;; nBlockIndex++){
|
|
if (pBlockLo[nBlockIndex].bUsed){
|
|
continue;
|
|
}
|
|
if (!pBlockLo[nBlockIndex].nSize){
|
|
// Need more memory committed.
|
|
if (!pBlockLo[nBlockIndex - 1].bUsed){
|
|
nBlockIndex--;
|
|
}
|
|
nCommitSize = nSize - pBlockLo[nBlockIndex].nSize;
|
|
CheckError2( CommitMoreMemoryLo(nCommitSize, nBlockIndex));
|
|
}
|
|
|
|
if (pBlockLo[nBlockIndex].nSize >= nSize){
|
|
// Return this pointer.
|
|
*ppBlock = pBlockLo[nBlockIndex].pAddress;
|
|
pBlockLo[nBlockIndex].bUsed = TRUE;
|
|
|
|
ssBlock1.bUsed = FALSE;
|
|
ssBlock1.nSize = pBlockLo[nBlockIndex].nSize - nSize;
|
|
ssBlock1.pAddress = pBlockLo[nBlockIndex].pAddress + nSize;
|
|
pBlockLo[nBlockIndex].nSize = nSize;
|
|
|
|
// Break this block up into 2 blocks if possible.
|
|
while(ssBlock1.nSize){
|
|
nBlockIndex++;
|
|
if (!ssBlock1.bUsed && !pBlockLo[nBlockIndex].bUsed){
|
|
pBlockLo[nBlockIndex].nSize += ssBlock1.nSize;
|
|
pBlockLo[nBlockIndex].pAddress = ssBlock1.pAddress;
|
|
break;
|
|
}
|
|
ssBlock2 = pBlockLo[nBlockIndex];
|
|
pBlockLo[nBlockIndex] = ssBlock1;
|
|
ssBlock1 = ssBlock2;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pBlockLo[pSubSegMemory->nNumberOfMemoryBlocksLo - 2].nSize
|
|
&& !pSubSegMemory->bMemoryBlocksChangingLo){
|
|
pSubSegMemory->bMemoryBlocksChangingLo = TRUE;
|
|
// Allocate more memory for the block structures.
|
|
if (ReAllocateMemory((pSubSegMemory->nNumberOfMemoryBlocksLo + 256) * sizeof(SUB_SEG_MEMORY_BLOCK),
|
|
(PPSTR) &pSubSegMemory->pBlockLo, ZERO_INIT)){
|
|
nStatus = Error(DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
pSubSegMemory->nNumberOfMemoryBlocksLo += 256;
|
|
pSubSegMemory->bMemoryBlocksChangingLo = FALSE;
|
|
}
|
|
}else if (nSize < HI_MEMORY_MAX_BLOCK_SIZE){
|
|
// Allocate memory in the large memory range.
|
|
// This memory range commits and decommitts in whole page amounts only.
|
|
// Find a block big enough to hold this block.
|
|
pBlockHi = pSubSegMemory->pBlockHi;
|
|
nCommitSize = (nSize + nMemBlockSize) & -nMemBlockSize;
|
|
for (nBlockIndex = 0;; nBlockIndex++){
|
|
pssBlock = &pBlockHi[nBlockIndex];
|
|
if (pssBlock->bUsed){
|
|
continue;
|
|
}
|
|
if (!pssBlock->nSize){
|
|
// Need a new block committed.
|
|
if (((pBlockHi[nBlockIndex - 1].pAddress + pBlockHi[nBlockIndex - 1].nSize + nCommitSize)
|
|
- ((PSTR) pSubSegMemory->pBlockHi)) > HI_MEMORY_AMOUNT){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
|
|
pssBlock->bUsed = FALSE;
|
|
pssBlock->pAddress = pBlockHi[nBlockIndex - 1].pAddress + pBlockHi[nBlockIndex - 1].nSize;
|
|
pssBlock->nSize = nCommitSize;
|
|
|
|
if (!(VirtualAlloc(pssBlock->pAddress, nCommitSize, MEM_COMMIT, PAGE_READWRITE))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (!pssBlock->bUsed && pssBlock->nSize >= nCommitSize){
|
|
// Return this pointer.
|
|
ssBlock1.bUsed = FALSE;
|
|
ssBlock1.nSize = pssBlock->nSize - nCommitSize;
|
|
ssBlock1.pAddress = pssBlock->pAddress + nCommitSize;
|
|
|
|
*ppBlock = pssBlock->pAddress;
|
|
pssBlock->bUsed = TRUE;
|
|
pssBlock->nSize = nCommitSize;
|
|
|
|
// Break this block up into 2 blocks if possible.
|
|
while(ssBlock1.nSize){
|
|
nBlockIndex++;
|
|
if (!ssBlock1.bUsed && !pBlockHi[nBlockIndex].bUsed){
|
|
pBlockHi[nBlockIndex].nSize += ssBlock1.nSize;
|
|
pBlockHi[nBlockIndex].pAddress = pBlockHi[nBlockIndex - 1].pAddress + pBlockHi[nBlockIndex - 1].nSize;
|
|
break;
|
|
}
|
|
ssBlock2 = pBlockHi[nBlockIndex];
|
|
pBlockHi[nBlockIndex] = ssBlock1;
|
|
ssBlock1 = ssBlock2;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (bZeroInit){
|
|
memset((PBYTE) *ppBlock, 0, nCommitSize);
|
|
}
|
|
|
|
if (pBlockHi[pSubSegMemory->nNumberOfMemoryBlocksHi - 2].nSize
|
|
&& !pSubSegMemory->bMemoryBlocksChangingHi){
|
|
// If we get here, we have some major problems (4096 allocs greater than 64k).
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
|
|
}else{
|
|
// Have the system allocate the memory.
|
|
// This memory range allocs and frees in whole alloc amounts only.
|
|
if (nSysMemoryAddresses >= (nMaxSysMemoryAddresses - 2)
|
|
&& !bMemoryBlocksChangingSys){
|
|
bMemoryBlocksChangingSys = TRUE;
|
|
nMaxSysMemoryAddresses += 10;
|
|
CheckError2( ReAllocateMemory(sizeof(SUB_SEG_MEMORY_BLOCK) * nMaxSysMemoryAddresses, (PPSTR) &pSysMemoryTable, TRUE));
|
|
bMemoryBlocksChangingSys = FALSE;
|
|
}
|
|
if (!(*ppBlock = VirtualAlloc(NULL, nSize, MEM_COMMIT, PAGE_READWRITE))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
pSysMemoryTable[nSysMemoryAddresses].pAddress = *ppBlock;
|
|
pSysMemoryTable[nSysMemoryAddresses].nSize = nSize;
|
|
nSysMemoryAddresses++;
|
|
}
|
|
|
|
|
|
Exit:
|
|
if (nStatus){
|
|
*ppBlock = 0;
|
|
}
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: ReAllocateMemory
|
|
|
|
PURPOSE: This routine allocates the memory requested and returns a
|
|
pointer to it.
|
|
|
|
INPUTS: nSize - The new size of the block to be allocated.
|
|
ppBlock - The pointer to where the pointer is (and to be returned).
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI ReAllocateMemory(int nSize, PPSTR ppBlock, BOOL bZeroInit){
|
|
|
|
int nStatus = 0;
|
|
|
|
PSTR pBlock;
|
|
PSTR pBuff;
|
|
SUB_SEG_MEMORY_BLOCK ssBlock1;
|
|
SUB_SEG_MEMORY_BLOCK ssBlock2;
|
|
int nOldSize;
|
|
int nLowerBound;
|
|
int nUpperBound;
|
|
int nBlockIndex;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockLo;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockHi;
|
|
int nCommitSize;
|
|
int nDiffSize;
|
|
int nMemBlockSize;
|
|
int nLastError;
|
|
MEMORY_BASIC_INFORMATION MemoryBasicInfo;
|
|
BOOL bDone;
|
|
int nLoop;
|
|
|
|
|
|
nSize = (nSize + 3) & ~3 ; // long align
|
|
if (!(pBlock = *ppBlock)){
|
|
CheckError2( AllocateMemory(nSize, ppBlock, bZeroInit));
|
|
goto Exit;
|
|
}
|
|
if (!nSize){
|
|
CheckError2( FreeMemory(ppBlock));
|
|
goto Exit;
|
|
}
|
|
nMemBlockSize = pSubSegMemory->nMemBlockSize;
|
|
|
|
if (pBlock >= (PSTR) pSubSegMemory && pBlock < ((PSTR) pSubSegMemory) + LO_MEMORY_AMOUNT){
|
|
// Use low memory.
|
|
nLowerBound = 0;
|
|
pBlockLo = pSubSegMemory->pBlockLo;
|
|
if (!pBlockLo[16].nSize){
|
|
nUpperBound = 15;
|
|
}else if (!pBlockLo[32].nSize){
|
|
nUpperBound = 31;
|
|
}else if (!pBlockLo[64].nSize){
|
|
nUpperBound = 63;
|
|
}else if (!pBlockLo[128].nSize){
|
|
nUpperBound = 127;
|
|
}else if (!pBlockLo[256].nSize){
|
|
nUpperBound = 255;
|
|
}else{
|
|
nUpperBound = pSubSegMemory->nNumberOfMemoryBlocksLo - 1;
|
|
}
|
|
|
|
while(1){
|
|
nBlockIndex = (nUpperBound + nLowerBound) >> 1;
|
|
if (pBlock != pBlockLo[nBlockIndex].pAddress){
|
|
if (nLowerBound >= nUpperBound){
|
|
// Bad pointer
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if ((pBlock < pBlockLo[nBlockIndex].pAddress)
|
|
|| !pBlockLo[nBlockIndex].nSize){
|
|
nUpperBound = nBlockIndex - 1;
|
|
continue;
|
|
}
|
|
nLowerBound = nBlockIndex + 1;
|
|
continue;
|
|
}
|
|
|
|
// This is the block.
|
|
nOldSize = pBlockLo[nBlockIndex].nSize;
|
|
nDiffSize = nSize - nOldSize;
|
|
if (nDiffSize < 0){
|
|
nDiffSize = -nDiffSize;
|
|
memset((PBYTE) pBlockLo[nBlockIndex].pAddress + nSize, 0, nDiffSize);
|
|
pBlockLo[nBlockIndex].nSize -= nDiffSize;
|
|
if (!pBlockLo[nBlockIndex + 1].bUsed){
|
|
// Add the free bytes to the next block.
|
|
pBlockLo[nBlockIndex + 1].nSize += nDiffSize;
|
|
(PBYTE) pBlockLo[nBlockIndex + 1].pAddress = pBlockLo[nBlockIndex].pAddress + nSize;
|
|
}else{
|
|
// make a new block for the free memory.
|
|
ssBlock1.bUsed = FALSE;
|
|
ssBlock1.nSize = nDiffSize;
|
|
ssBlock1.pAddress = (PBYTE) pBlockLo[nBlockIndex].pAddress + nSize;
|
|
while(1){
|
|
nBlockIndex++;
|
|
ssBlock2 = pBlockLo[nBlockIndex];
|
|
pBlockLo[nBlockIndex] = ssBlock1;
|
|
ssBlock1 = ssBlock2;
|
|
if (!ssBlock1.nSize){
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}else if (!pBlockLo[nBlockIndex + 1].bUsed && nSize < LO_MEMORY_MAX_BLOCK_SIZE){
|
|
if (nDiffSize > pBlockLo[nBlockIndex + 1].nSize){
|
|
if (!pBlockLo[nBlockIndex + 2].nSize){
|
|
// Need more memory committed.
|
|
nCommitSize = nDiffSize - pBlockLo[nBlockIndex + 1].nSize;
|
|
CheckError2( CommitMoreMemoryLo(nCommitSize, nBlockIndex + 1));
|
|
}
|
|
}
|
|
|
|
|
|
if (nDiffSize <= pBlockLo[nBlockIndex + 1].nSize){
|
|
pBlockLo[nBlockIndex].nSize += nDiffSize;
|
|
nBlockIndex++;
|
|
pBlockLo[nBlockIndex].nSize -= nDiffSize;
|
|
(PBYTE) pBlockLo[nBlockIndex].pAddress += nDiffSize;
|
|
|
|
// Compress the list is nSize becomes 0.
|
|
if (!pBlockLo[nBlockIndex].nSize){
|
|
// Move the rest of the blocks intact down.
|
|
do{
|
|
pBlockLo[nBlockIndex] = pBlockLo[nBlockIndex + 1];
|
|
nBlockIndex++;
|
|
}while(pBlockLo[nBlockIndex].nSize);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
// It must be reallocated manually.
|
|
// AllocateMemory may move the Block structure. Therefore get the info now.
|
|
nOldSize = pBlockLo[nBlockIndex].nSize;
|
|
CheckError2( AllocateMemory(nSize, &pBuff, bZeroInit));
|
|
memcpy(pBuff, pBlock, min(nSize, nOldSize));
|
|
CheckError2( FreeMemory(ppBlock));
|
|
*ppBlock = pBuff;
|
|
break;
|
|
}
|
|
|
|
if (pBlockLo[pSubSegMemory->nNumberOfMemoryBlocksLo - 2].nSize
|
|
&& !pSubSegMemory->bMemoryBlocksChangingLo){
|
|
pSubSegMemory->bMemoryBlocksChangingLo = TRUE;
|
|
// Allocate more memory for the block structures.
|
|
CheckError2( ReAllocateMemory((pSubSegMemory->nNumberOfMemoryBlocksLo + 256) * sizeof(SUB_SEG_MEMORY_BLOCK),
|
|
(PPSTR) &pSubSegMemory->pBlockLo, ZERO_INIT));
|
|
pSubSegMemory->nNumberOfMemoryBlocksLo += 256;
|
|
pSubSegMemory->bMemoryBlocksChangingLo = FALSE;
|
|
}
|
|
}else if (pBlock >= (PSTR) pSubSegMemory && pBlock < ((PSTR) pSubSegMemory) + MAX_SIZE_OF_MEMORY){
|
|
// Use hi memory.
|
|
nLowerBound = 0;
|
|
pBlockHi = pSubSegMemory->pBlockHi;
|
|
if (!pBlockHi[8].nSize){
|
|
nUpperBound = 7;
|
|
}else if (!pBlockHi[16].nSize){
|
|
nUpperBound = 15;
|
|
}else if (!pBlockHi[32].nSize){
|
|
nUpperBound = 31;
|
|
}else if (!pBlockHi[64].nSize){
|
|
nUpperBound = 63;
|
|
}else if (!pBlockHi[128].nSize){
|
|
nUpperBound = 127;
|
|
}else if (!pBlockHi[256].nSize){
|
|
nUpperBound = 255;
|
|
}else{
|
|
nUpperBound = pSubSegMemory->nNumberOfMemoryBlocksHi - 1;
|
|
}
|
|
|
|
while(1){
|
|
nBlockIndex = (nUpperBound + nLowerBound) >> 1;
|
|
if (pBlock != pSubSegMemory->pBlockHi[nBlockIndex].pAddress){
|
|
if (nLowerBound >= nUpperBound){
|
|
// Bad pointer
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if ((pBlock < pSubSegMemory->pBlockHi[nBlockIndex].pAddress)
|
|
|| !pSubSegMemory->pBlockHi[nBlockIndex].nSize){
|
|
nUpperBound = nBlockIndex - 1;
|
|
continue;
|
|
}
|
|
nLowerBound = nBlockIndex + 1;
|
|
continue;
|
|
}
|
|
|
|
// This is the block.
|
|
nCommitSize = (nSize + pSubSegMemory->nMemBlockSize) & -pSubSegMemory->nMemBlockSize;
|
|
nDiffSize = nCommitSize - pBlockHi[nBlockIndex].nSize;
|
|
if (nDiffSize < 0 && nSize > LO_MEMORY_MAX_BLOCK_SIZE){
|
|
nDiffSize = 0 - nDiffSize;
|
|
VirtualQuery(pBlockHi[nBlockIndex].pAddress + pBlockHi[nBlockIndex].nSize
|
|
- nDiffSize, &MemoryBasicInfo, sizeof(MemoryBasicInfo));
|
|
|
|
if (!VirtualFree(pBlockHi[nBlockIndex].pAddress + pBlockHi[nBlockIndex].nSize
|
|
- nDiffSize, nDiffSize, MEM_DECOMMIT)){
|
|
nStatus = Error(DISPLAY_CANTFREE);
|
|
nLastError = GetLastError();
|
|
goto Exit;
|
|
}
|
|
pBlockHi[nBlockIndex].nSize -= nDiffSize;
|
|
if (!pBlockHi[nBlockIndex + 1].bUsed){
|
|
// Add the free bytes to the next block.
|
|
pBlockHi[nBlockIndex + 1].nSize += nDiffSize;
|
|
(PBYTE) pBlockHi[nBlockIndex + 1].pAddress -= nDiffSize;
|
|
}else{
|
|
// make a new block for the free memory.
|
|
ssBlock1.bUsed = FALSE;
|
|
ssBlock1.nSize = nDiffSize;
|
|
ssBlock1.pAddress = (PBYTE) pBlockHi[nBlockIndex].pAddress + nSize;
|
|
while(1){
|
|
nBlockIndex++;
|
|
ssBlock2 = pBlockHi[nBlockIndex];
|
|
pBlockHi[nBlockIndex] = ssBlock1;
|
|
ssBlock1 = ssBlock2;
|
|
if (!ssBlock1.nSize){
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
}else if (!pBlockHi[nBlockIndex + 1].bUsed && nSize > LO_MEMORY_MAX_BLOCK_SIZE){
|
|
if (nDiffSize < pBlockHi[nBlockIndex + 1].nSize){
|
|
if (bZeroInit){
|
|
memset((PBYTE) pSubSegMemory->pBlockHi[nBlockIndex].pAddress + nSize, 0, nDiffSize);
|
|
}
|
|
pBlockHi[nBlockIndex].nSize += nDiffSize;
|
|
pBlockHi[nBlockIndex + 1].nSize -= nDiffSize;
|
|
(PBYTE) pBlockHi[nBlockIndex + 1].pAddress += nDiffSize;
|
|
break;
|
|
}
|
|
}
|
|
// It must be reallocated manually.
|
|
// AllocateMemory may move the Block structure. Therefore get the info now.
|
|
nOldSize = pBlockHi[nBlockIndex].nSize;
|
|
CheckError2( AllocateMemory(nSize, &pBuff, bZeroInit));
|
|
memcpy(pBuff, pBlock, min(nSize, nOldSize));
|
|
CheckError2( FreeMemory(ppBlock));
|
|
*ppBlock = pBuff;
|
|
break;
|
|
}
|
|
|
|
if (pBlockHi[pSubSegMemory->nNumberOfMemoryBlocksHi - 2].nSize
|
|
&& !pSubSegMemory->bMemoryBlocksChangingHi){
|
|
// If we get here, we have some major problems (4096 allocs greater than 64k).
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
}else{
|
|
// Use system memory.
|
|
// Find the address in the table;
|
|
bDone = FALSE;
|
|
for (nLoop = 0; nLoop < nSysMemoryAddresses; nLoop++){
|
|
if (pSysMemoryTable[nLoop].pAddress == *ppBlock){
|
|
// This is the address, Realloc it manually.
|
|
if (!(pBuff = VirtualAlloc(NULL, nSize, MEM_COMMIT, PAGE_READWRITE))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
memcpy(pBuff, *ppBlock, min(nSize, pSysMemoryTable[nLoop].nSize));
|
|
|
|
if (!VirtualFree(*ppBlock, 0, MEM_RELEASE)){
|
|
nStatus = Error(DISPLAY_CANTFREE);
|
|
goto Exit;
|
|
}
|
|
*ppBlock = pBuff;
|
|
pSysMemoryTable[nLoop].pAddress = *ppBlock;
|
|
pSysMemoryTable[nLoop].nSize = nSize;
|
|
bDone = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!bDone){
|
|
// Unknown address.
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
if (nStatus){
|
|
// Force a crash and burn if caller doesn't check status.
|
|
*ppBlock = NULL;
|
|
}
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: ReduceMemory
|
|
|
|
PURPOSE: This routine is equivalent to ReAlloacteMemory except that it
|
|
assumes that the extra memory is unmodified.
|
|
This routine reduces the amount of allocated memory.
|
|
The pointer will remain unchanged.
|
|
The unused portion of memory will already be zero inited (unmodified).
|
|
|
|
INPUTS: nSize - The new size of the block to be allocated.
|
|
ppBlock - The pointer to where the pointer is (and to be returned).
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI ReduceMemory(long nSize, PPSTR ppBlock){
|
|
|
|
return(ReAllocateMemory(nSize, ppBlock, NO_INIT));
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: FreeMemory
|
|
|
|
PURPOSE: This routine frees the memory requested.
|
|
|
|
INPUTS: ppBlock - The pointer to where the pointer is.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI FreeMemory(PPSTR ppBlock){
|
|
|
|
int nStatus = 0;
|
|
|
|
PSTR pBlock;
|
|
int nLowerBound;
|
|
int nUpperBound;
|
|
int nBlockIndex;
|
|
int nBlockIndex2;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockLo;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockHi;
|
|
int nLastError;
|
|
BOOL bDone;
|
|
int nLoop;
|
|
|
|
|
|
if (!ppBlock){
|
|
goto Exit;
|
|
}
|
|
|
|
if (!(pBlock = *ppBlock)){
|
|
goto Exit;
|
|
}
|
|
|
|
if (pBlock >= (PSTR) pSubSegMemory && pBlock < ((PSTR) pSubSegMemory) + LO_MEMORY_AMOUNT){
|
|
// Use low memory.
|
|
nLowerBound = 0;
|
|
pBlockLo = pSubSegMemory->pBlockLo;
|
|
if (!pBlockLo[16].nSize){
|
|
nUpperBound = 15;
|
|
}else if (!pBlockLo[32].nSize){
|
|
nUpperBound = 31;
|
|
}else if (!pBlockLo[64].nSize){
|
|
nUpperBound = 63;
|
|
}else if (!pBlockLo[128].nSize){
|
|
nUpperBound = 127;
|
|
}else if (!pBlockLo[256].nSize){
|
|
nUpperBound = 255;
|
|
}else{
|
|
nUpperBound = pSubSegMemory->nNumberOfMemoryBlocksLo - 1;
|
|
}
|
|
|
|
while(1){
|
|
nBlockIndex = (nUpperBound + nLowerBound) >> 1;
|
|
if (pBlock != pBlockLo[nBlockIndex].pAddress){
|
|
if (nLowerBound >= nUpperBound){
|
|
// Bad pointer
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if ((pBlock < pBlockLo[nBlockIndex].pAddress)
|
|
|| !pBlockLo[nBlockIndex].nSize){
|
|
nUpperBound = nBlockIndex - 1;
|
|
continue;
|
|
}
|
|
nLowerBound = nBlockIndex + 1;
|
|
continue;
|
|
}
|
|
|
|
// This is the block.
|
|
memset(pBlock, 0, pBlockLo[nBlockIndex].nSize);
|
|
pBlockLo[nBlockIndex].bUsed = FALSE;
|
|
|
|
// Condense the list.
|
|
nBlockIndex2 = nBlockIndex;
|
|
if (nBlockIndex && !pBlockLo[nBlockIndex - 1].bUsed){
|
|
nBlockIndex--;
|
|
}else if (!pBlockLo[nBlockIndex + 1].bUsed){
|
|
nBlockIndex2++;
|
|
}else{
|
|
break;
|
|
}
|
|
|
|
// Condense the unused blocks into 1.
|
|
pBlockLo[nBlockIndex].nSize += pBlockLo[nBlockIndex2].nSize;
|
|
pBlockLo[nBlockIndex2].nSize = 0;
|
|
pBlockLo[nBlockIndex2].pAddress = 0;
|
|
nBlockIndex2++;
|
|
if (!pBlockLo[nBlockIndex2].bUsed && pBlockLo[nBlockIndex2].nSize){
|
|
pBlockLo[nBlockIndex].nSize += pBlockLo[nBlockIndex2].nSize;
|
|
pBlockLo[nBlockIndex2].nSize = 0;
|
|
pBlockLo[nBlockIndex2].pAddress = 0;
|
|
nBlockIndex2++;
|
|
}
|
|
nBlockIndex++;
|
|
|
|
// Move the rest of the blocks intact down.
|
|
while(pBlockLo[nBlockIndex2].nSize){
|
|
pBlockLo[nBlockIndex++] = pBlockLo[nBlockIndex2++];
|
|
}
|
|
|
|
// Zero out the abandoned blocks.
|
|
while(nBlockIndex != nBlockIndex2){
|
|
pBlockLo[nBlockIndex].bUsed = FALSE;
|
|
pBlockLo[nBlockIndex].nSize = 0;
|
|
pBlockLo[nBlockIndex].pAddress = 0;
|
|
nBlockIndex++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (pBlockLo[pSubSegMemory->nNumberOfMemoryBlocksLo - 2].nSize
|
|
&& !pSubSegMemory->bMemoryBlocksChangingLo){
|
|
pSubSegMemory->bMemoryBlocksChangingLo = TRUE;
|
|
// Allocate more memory for the block structures.
|
|
if (ReAllocateMemory((pSubSegMemory->nNumberOfMemoryBlocksLo + 256) * sizeof(SUB_SEG_MEMORY_BLOCK),
|
|
(PPSTR) &pSubSegMemory->pBlockLo, ZERO_INIT)){
|
|
goto Exit;
|
|
}
|
|
pSubSegMemory->nNumberOfMemoryBlocksLo += 256;
|
|
pSubSegMemory->bMemoryBlocksChangingLo = FALSE;
|
|
}
|
|
}else if (pBlock >= (PSTR) pSubSegMemory && pBlock < ((PSTR) pSubSegMemory) + MAX_SIZE_OF_MEMORY){
|
|
// Use high memory.
|
|
nLowerBound = 0;
|
|
pBlockHi = pSubSegMemory->pBlockHi;
|
|
if (!pBlockHi[4].nSize){
|
|
nUpperBound = 3;
|
|
}else if (!pBlockHi[8].nSize){
|
|
nUpperBound = 7;
|
|
}else if (!pBlockHi[16].nSize){
|
|
nUpperBound = 15;
|
|
}else if (!pBlockHi[32].nSize){
|
|
nUpperBound = 31;
|
|
}else if (!pBlockHi[64].nSize){
|
|
nUpperBound = 63;
|
|
}else if (!pBlockHi[128].nSize){
|
|
nUpperBound = 127;
|
|
}else if (!pBlockHi[256].nSize){
|
|
nUpperBound = 255;
|
|
}else{
|
|
nUpperBound = pSubSegMemory->nNumberOfMemoryBlocksHi - 1;
|
|
}
|
|
|
|
while(1){
|
|
nBlockIndex = (nUpperBound + nLowerBound) >> 1;
|
|
if (pBlock != pSubSegMemory->pBlockHi[nBlockIndex].pAddress){
|
|
if (nLowerBound >= nUpperBound){
|
|
// Bad pointer
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if ((pBlock < pSubSegMemory->pBlockHi[nBlockIndex].pAddress)
|
|
|| !pSubSegMemory->pBlockHi[nBlockIndex].nSize){
|
|
nUpperBound = nBlockIndex - 1;
|
|
continue;
|
|
}
|
|
nLowerBound = nBlockIndex + 1;
|
|
continue;
|
|
}
|
|
|
|
// This is the block.
|
|
if (!VirtualFree(pBlockHi[nBlockIndex].pAddress, pBlockHi[nBlockIndex].nSize, MEM_DECOMMIT)){
|
|
nStatus = Error(DISPLAY_CANTFREE);
|
|
nLastError = GetLastError();
|
|
goto Exit;
|
|
}
|
|
pBlockHi[nBlockIndex].bUsed = FALSE;
|
|
|
|
// Condense the list.
|
|
nBlockIndex2 = nBlockIndex;
|
|
if (nBlockIndex && !pSubSegMemory->pBlockHi[nBlockIndex - 1].bUsed){
|
|
nBlockIndex--;
|
|
}else if (!pSubSegMemory->pBlockHi[nBlockIndex2 + 1].bUsed){
|
|
nBlockIndex2++;
|
|
}else{
|
|
break;
|
|
}
|
|
// Condense the unused blocks into 1.
|
|
pSubSegMemory->pBlockHi[nBlockIndex].nSize += pSubSegMemory->pBlockHi[nBlockIndex2].nSize;
|
|
pSubSegMemory->pBlockHi[nBlockIndex2].nSize = 0;
|
|
pSubSegMemory->pBlockHi[nBlockIndex2].pAddress = 0;
|
|
nBlockIndex2++;
|
|
if (!pSubSegMemory->pBlockHi[nBlockIndex2].bUsed){
|
|
pSubSegMemory->pBlockHi[nBlockIndex].nSize += pSubSegMemory->pBlockHi[nBlockIndex2].nSize;
|
|
pSubSegMemory->pBlockHi[nBlockIndex2].nSize = 0;
|
|
pSubSegMemory->pBlockHi[nBlockIndex2].pAddress = 0;
|
|
nBlockIndex2++;
|
|
}
|
|
nBlockIndex++;
|
|
|
|
// Move the rest of the blocks in tact down.
|
|
while(pSubSegMemory->pBlockHi[nBlockIndex2].nSize){
|
|
pSubSegMemory->pBlockHi[nBlockIndex++] = pSubSegMemory->pBlockHi[nBlockIndex2++];
|
|
}
|
|
|
|
// Zero out the abandoned blocks.
|
|
while(nBlockIndex != nBlockIndex2){
|
|
pSubSegMemory->pBlockHi[nBlockIndex].bUsed = FALSE;
|
|
pSubSegMemory->pBlockHi[nBlockIndex].nSize = 0;
|
|
pSubSegMemory->pBlockHi[nBlockIndex].pAddress = 0;
|
|
nBlockIndex++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (pBlockHi[pSubSegMemory->nNumberOfMemoryBlocksHi - 2].nSize
|
|
&& !pSubSegMemory->bMemoryBlocksChangingHi){
|
|
// If we get here, we have some major problems (4096 allocs greater than 64k).
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
|
|
}else{
|
|
// Use system memory.
|
|
// Find the address in the table;
|
|
bDone = FALSE;
|
|
for (nLoop = 0; nLoop < nSysMemoryAddresses; nLoop++){
|
|
if (pSysMemoryTable[nLoop].pAddress == *ppBlock){
|
|
// This is the address, free it.
|
|
if (!VirtualFree(*ppBlock, 0, MEM_RELEASE)){
|
|
nStatus = Error(DISPLAY_CANTFREE);
|
|
goto Exit;
|
|
}
|
|
for (; nLoop < (nSysMemoryAddresses - 1); nLoop++){
|
|
pSysMemoryTable[nLoop] = pSysMemoryTable[nLoop + 1];
|
|
}
|
|
memset(&pSysMemoryTable[nSysMemoryAddresses], 0, sizeof(SUB_SEG_MEMORY_BLOCK));
|
|
nSysMemoryAddresses--;
|
|
*ppBlock = 0;
|
|
bDone = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!bDone){
|
|
// Unknown address.
|
|
nStatus = Error(DISPLAY_CANTFREE);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
if (!nStatus && ppBlock){
|
|
*ppBlock = 0;
|
|
}
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: CommitMoreMemoryLo
|
|
|
|
PURPOSE: This routine commits more Lo memory.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI CommitMoreMemoryLo(int nCommitSize, int nLastBlockIndex){
|
|
|
|
int nStatus = 0;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockLo;
|
|
int nMemBlockSize;
|
|
|
|
|
|
nMemBlockSize = pSubSegMemory->nMemBlockSize;
|
|
|
|
pBlockLo = pSubSegMemory->pBlockLo;
|
|
if (!pBlockLo[nLastBlockIndex].nSize){
|
|
if (!pBlockLo[nLastBlockIndex - 1].bUsed){
|
|
nLastBlockIndex--;
|
|
}else{
|
|
pBlockLo[nLastBlockIndex].pAddress
|
|
= pBlockLo[nLastBlockIndex - 1].pAddress + pBlockLo[nLastBlockIndex - 1].nSize;
|
|
}
|
|
}
|
|
nCommitSize = (nCommitSize + nMemBlockSize) & -nMemBlockSize;
|
|
|
|
if (pSubSegMemory->nCommittedLo + nCommitSize > LO_MEMORY_AMOUNT){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if (!(VirtualAlloc(((PBYTE) pSubSegMemory) + pSubSegMemory->nCommittedLo,
|
|
nCommitSize, MEM_COMMIT, PAGE_READWRITE))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
pBlockLo[nLastBlockIndex].nSize += nCommitSize;
|
|
memset(((PBYTE) pSubSegMemory) + pSubSegMemory->nCommittedLo, 0, nCommitSize);
|
|
pSubSegMemory->nCommittedLo += nCommitSize;
|
|
|
|
|
|
Exit:
|
|
return(nStatus);
|
|
}
|
|
#ifdef old
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: GetSizeOfMemory
|
|
|
|
PURPOSE: This routine returns the size of the memory requested.
|
|
|
|
INPUTS: ppBlock - The pointer to where the pointer is.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI GetSizeOfMemory(PPSTR ppBlock, PINT pnSize){
|
|
|
|
int nStatus = 0;
|
|
|
|
PSTR pBlock;
|
|
int nLowerBound;
|
|
int nUpperBound;
|
|
int nBlockIndex;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockLo;
|
|
PSUB_SEG_MEMORY_BLOCK pBlockHi;
|
|
BOOL bDone;
|
|
int nLoop;
|
|
MEMORY_BASIC_INFORMATION MemoryBasicInfo;
|
|
|
|
|
|
if (!(pBlock = *ppBlock)){
|
|
goto Exit;
|
|
}
|
|
|
|
if (pBlock >= (PSTR) pSubSegMemory && pBlock < ((PSTR) pSubSegMemory) + LO_MEMORY_AMOUNT){
|
|
// Use low memory.
|
|
nLowerBound = 0;
|
|
pBlockLo = pSubSegMemory->pBlockLo;
|
|
if (!pBlockLo[16].nSize){
|
|
nUpperBound = 15;
|
|
}else if (!pBlockLo[32].nSize){
|
|
nUpperBound = 31;
|
|
}else if (!pBlockLo[64].nSize){
|
|
nUpperBound = 63;
|
|
}else if (!pBlockLo[128].nSize){
|
|
nUpperBound = 127;
|
|
}else if (!pBlockLo[256].nSize){
|
|
nUpperBound = 255;
|
|
}else{
|
|
nUpperBound = pSubSegMemory->nNumberOfMemoryBlocksLo - 1;
|
|
}
|
|
|
|
while(1){
|
|
nBlockIndex = (nUpperBound + nLowerBound) >> 1;
|
|
if (pBlock != pBlockLo[nBlockIndex].pAddress){
|
|
if (nLowerBound >= nUpperBound){
|
|
// Bad pointer
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if ((pBlock < pBlockLo[nBlockIndex].pAddress)
|
|
|| !pBlockLo[nBlockIndex].nSize){
|
|
nUpperBound = nBlockIndex - 1;
|
|
continue;
|
|
}
|
|
nLowerBound = nBlockIndex + 1;
|
|
continue;
|
|
}
|
|
|
|
// This is the block.
|
|
*pnSize = pBlockLo[nBlockIndex].nSize;
|
|
break;
|
|
}
|
|
}else if (pBlock >= (PSTR) pSubSegMemory && pBlock < ((PSTR) pSubSegMemory) + MAX_SIZE_OF_MEMORY){
|
|
// Use high memory.
|
|
nLowerBound = 0;
|
|
pBlockHi = pSubSegMemory->pBlockHi;
|
|
if (!pBlockHi[4].nSize){
|
|
nUpperBound = 3;
|
|
}else if (!pBlockHi[8].nSize){
|
|
nUpperBound = 7;
|
|
}else if (!pBlockHi[16].nSize){
|
|
nUpperBound = 15;
|
|
}else if (!pBlockHi[32].nSize){
|
|
nUpperBound = 31;
|
|
}else if (!pBlockHi[64].nSize){
|
|
nUpperBound = 63;
|
|
}else if (!pBlockHi[128].nSize){
|
|
nUpperBound = 127;
|
|
}else if (!pBlockHi[256].nSize){
|
|
nUpperBound = 255;
|
|
}else{
|
|
nUpperBound = pSubSegMemory->nNumberOfMemoryBlocksHi - 1;
|
|
}
|
|
|
|
while(1){
|
|
nBlockIndex = (nUpperBound + nLowerBound) >> 1;
|
|
if (pBlock != pSubSegMemory->pBlockHi[nBlockIndex].pAddress){
|
|
if (nLowerBound >= nUpperBound){
|
|
// Bad pointer
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if ((pBlock < pSubSegMemory->pBlockHi[nBlockIndex].pAddress)
|
|
|| !pSubSegMemory->pBlockHi[nBlockIndex].nSize){
|
|
nUpperBound = nBlockIndex - 1;
|
|
continue;
|
|
}
|
|
nLowerBound = nBlockIndex + 1;
|
|
continue;
|
|
}
|
|
|
|
// This is the block.
|
|
*pnSize = pBlockHi[nBlockIndex].nSize;
|
|
break;
|
|
}
|
|
}else{
|
|
// Use system memory.
|
|
// Find the address in the table;
|
|
bDone = FALSE;
|
|
for (nLoop = 0; nLoop < nSysMemoryAddresses; nLoop++){
|
|
if (pSysMemoryTable[nLoop].pAddress == *ppBlock){
|
|
// This is the address.
|
|
VirtualQuery(pBlockHi[nBlockIndex].pAddress, &MemoryBasicInfo, sizeof(MemoryBasicInfo));
|
|
*pnSize = MemoryBasicInfo.RegionSize;
|
|
bDone = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!bDone){
|
|
// Unknown address.
|
|
nStatus = Error(DISPLAY_CANTFREE);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
if (!nStatus){
|
|
*ppBlock = 0;
|
|
}
|
|
return(nStatus);
|
|
}
|
|
#endif
|