📄 memorybuffer.cpp
字号:
// MemoryBuffer.cpp: implementation of the CMemoryBuffer class.
//
//////////////////////////////////////////////////////////////////////
#include "includes.h"
#include "MemoryBuffer.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMemoryBuffer::CMemoryBuffer():
m_pChunks(NULL), // the physical addresses of the memory chunks
m_pVirtualAddress(NULL), // the virtual address
m_ulSize(0), // the size
m_nChunks(0)
{
FUNCMSG("+CMemoryBuffer::CMemoryBuffer()");
}
CMemoryBuffer::~CMemoryBuffer()
{
FUNCMSG("+CMemoryBuffer::~CMemoryBuffer()");
FreeBuffer();
}
bool CMemoryBuffer::ReservePhysicalMem(ULONG dwSize)
{
FUNCMSG1("+CMemoryBuffer::ReservePhysicalMem(%d)", dwSize);
FreeBuffer();
//
// Allocate a buffer
//
m_pVirtualAddress = (LPBYTE)VirtualAlloc(0, dwSize, MEM_COMMIT , PAGE_READWRITE | PAGE_NOCACHE);
if (!m_pVirtualAddress)
{
ERRMSG("CMemoryBuffer:ReservePhysicalMem:Allocate: Buffer Allocation Failed");
FreeBuffer();
return false;
}
// let's first find the maximum # of pages that could be locked
UINT cPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, dwSize);
//INFMSG1(" CMemoryBuffer::ReservePhysicalMem; needs %d pages", cPages);
// allocate an array for the maximum # of pages
ULONG *pPages = new ULONG[cPages];
if(!pPages)
{
ERRMSG("CMemoryBuffer:ReservePhysicalMem: Failed to allocate Pageframe array");
VirtualFree((VOID *)(m_pVirtualAddress), 0, MEM_RELEASE);
m_pVirtualAddress = NULL;
m_pChunks = NULL;
return false;
}
if (!LockPages((VOID *)(m_pVirtualAddress), dwSize, pPages, LOCKFLAG_WRITE))
{
ERRMSG("CMemoryBuffer:ReservePhysicalMem: LockPages Failed");
VirtualFree((VOID *)(m_pVirtualAddress), 0, MEM_RELEASE);
delete[] pPages;
m_pVirtualAddress = NULL;
return false;
}
//
// consolidate contiguous pages into chunks
//
// how many chunks?
m_nChunks = 1;
SYSTEM_INFO siSystemInfo;
//get page size
GetSystemInfo (&siSystemInfo);
for (UINT uCurrentPage=0; uCurrentPage < cPages-1; uCurrentPage++)
{
// LockPages fills pPages[] with the PFNs (Page Frame Numbers?) of the locked pages.
// We need to left-shift by a magic number to get the actual physical address.
// Note that as of this writing, the PB online help incorrectly states that we should right-shift.
if((pPages[uCurrentPage] << UserKInfo[KINX_PFN_SHIFT]) + siSystemInfo.dwPageSize != (pPages[uCurrentPage+1] << UserKInfo[KINX_PFN_SHIFT]) )
{
m_nChunks++;
}
}
//INFMSG1("CMemoryBuffer::ReservePhysicalMem: Number of chunks is %d", m_nChunks);
m_pChunks = new struct SMemoryChunk[m_nChunks];
if (!m_pChunks)
{
ERRMSG("CMemoryBuffer::ReservePhysicalMem: can't allocate chunks array");
delete[] pPages;
FreeBuffer();
return false;
}
// start filling the chunks array
UINT uCurrentChunk = 0;
DWORD dwRemainingSize = dwSize;
uCurrentPage = 0;
DWORD dwCurrentPageSize;
m_pChunks[uCurrentChunk].m_ulAddress = pPages[uCurrentPage] << UserKInfo[KINX_PFN_SHIFT];
m_pChunks[uCurrentChunk].m_ulSize = 0;
while (true)
{
// what's the size of the current page?
dwCurrentPageSize = (dwRemainingSize > siSystemInfo.dwPageSize)?siSystemInfo.dwPageSize:dwRemainingSize;
m_pChunks[uCurrentChunk].m_ulSize += dwCurrentPageSize;
dwRemainingSize -= dwCurrentPageSize;
//INFMSG2("m_pChunks[uCurrentChunk].m_ulSize is %d, dwRemainingSize is %d", m_pChunks[uCurrentChunk].m_ulSize, dwRemainingSize );
if (dwRemainingSize <= 0)
break;
// is the next page in the same chunk?
if((pPages[uCurrentPage] << UserKInfo[KINX_PFN_SHIFT]) + siSystemInfo.dwPageSize != (pPages[uCurrentPage+1] << UserKInfo[KINX_PFN_SHIFT]))
{
// no: go to next chunk
uCurrentChunk++;
m_pChunks[uCurrentChunk].m_ulSize = 0;
m_pChunks[uCurrentChunk].m_ulAddress = (pPages[uCurrentPage+1] << UserKInfo[KINX_PFN_SHIFT]);
}
uCurrentPage++;
}
#ifdef DEBUG
for (uCurrentChunk = 0; uCurrentChunk < m_nChunks; uCurrentChunk++)
{
INFMSG3("CMemoryBuffer::ReservePhysicalMem: chunk %d, addr 0x%8.8x, size %d",
uCurrentChunk, m_pChunks[uCurrentChunk].m_ulAddress, m_pChunks[uCurrentChunk].m_ulSize);
}
#endif
RETAILMSG((dwRemainingSize != 0)?ZONE_ERROR:0, (TEXT("CMemoryBuffer::ReservePhysicalMem: dwRemainingSize is %d\r\n"), dwRemainingSize));
delete[] pPages;
//INFMSG2("Call memset on 0x%8.8x, size %d", m_pVirtualAddress, dwSize);
memset((VOID *)(m_pVirtualAddress), 0, dwSize);
m_ulSize = dwSize;
return true;
}
void CMemoryBuffer::FreeBuffer()
{
FUNCMSG1("+CMemoryBuffer::FreeBuffer(): 0x%x", m_pVirtualAddress);
if(m_pVirtualAddress)
{
UnlockPages(m_pVirtualAddress, m_ulSize);
VirtualFree(m_pVirtualAddress, 0, MEM_RELEASE);
}
delete[] m_pChunks;
m_pChunks = NULL;
m_pVirtualAddress = NULL;
m_ulSize = m_nChunks = 0;
FUNCMSG("-CMemoryBuffer::FreeBuffer()");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -