📄 mapfile.c
字号:
{
LPVOID pMem = 0, pMemPage = 0;
BOOL retval, fPageUsed = TRUE;
WORD idxPgMem = INVALID_PG_INDEX;
DEBUGCHK (PagerCS.OwnerThread == hCurThread);
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE,
(L"MappedPageInHelper: Taking fault at 0x%08x (%s)\r\n", addr, bWrite ? L"write" : L"read"));
// cannot write to RO file
if (bWrite && (INVALID_HANDLE_VALUE != lpm->hFile) && !lpm->pDirty) {
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE, (L"MappedPageInHelper: Failed - Write on Read Only file\r\n"));
return PAGEIN_FAILURE;
}
// check if the memory is already paged-in by others.
if ((retval = MMQueryState (addr, bWrite)) != PAGEIN_RETRY) {
return retval;
}
// memory back'd file -- simply commit and return
if (INVALID_HANDLE_VALUE == lpm->hFile) {
if (!(pMem = VirtualAlloc((LPVOID)addr, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE))) {
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE, (L"MappedPageInHelper: PageIn failed COMMITING (%8.8lx)\r\n", addr));
return PAGEIN_FAILURE;
}
PagedInCount++;
return PAGEIN_SUCCESS;
}
//
// allocate memory for paging
//
if (!lpm->pDirty) {
// RO page, try to get it from paging pool
pMemPage = GetPagingPage (&lpm->pgqueue, 0, 0, &idxPgMem);
}
if (!pMemPage) {
// no paging pool, get a page from secure slot for paging
if (pMem = VirtualAlloc ((LPVOID)ProcArray[0].dwVMBase, 0x10000, MEM_RESERVE, PAGE_NOACCESS)) {
pMemPage = VirtualAlloc ((LPVOID)((DWORD)pMem + (addr & 0xffff)), PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE);
}
if (!pMemPage) {
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE, (L"MappedPageInHelper: PageIn failed on VirtualAlloc\r\n"));
// it's debatable whether we return PAGEIN_RETRY or PAGEIN_FAILURE when memory allocation failed.
// for now we're returning PAGEIN_RETRY
}
}
if (pMemPage) {
lpm->bRestart = 0;
LeaveCriticalSection(&PagerCS);
// page in the memory mapped file
retval = MappedPageInPage (lpm, bWrite, addr, pMemPage);
EnterCriticalSection(&PagerCS);
if (PAGEIN_SUCCESS == retval) {
if (!lpm->bRestart
&& ((retval = MMQueryState (addr, bWrite)) == PAGEIN_RETRY)) {
OEMCacheRangeFlush (pMemPage, PAGE_SIZE, CACHE_SYNC_WRITEBACK);
if (VirtualCopy ((LPVOID)addr, pMemPage, PAGE_SIZE, bWrite ? PAGE_READWRITE : PAGE_READONLY)) {
// note: if VirtualCopy Failed, we will return PAGEIN_RETRY since it might be someone
// else paged in the page for us
retval = PAGEIN_SUCCESS;
PagedInCount++;
}
} else {
// if we get here, the page we allocated for paging isn't used. Make sure we return it to
// the paging pool's free list.
fPageUsed = FALSE;
}
}
}
if (INVALID_PG_INDEX != idxPgMem) {
// if we're using paging pool, add the page to the memory mapped file's queue when succeeded,
// or return it to free list when failed
if ((PAGEIN_SUCCESS == retval) && fPageUsed) {
AddPageToQueue (&lpm->pgqueue, idxPgMem, addr, lpm);
} else {
AddPageToFreeList (idxPgMem);
}
} else {
if (pMemPage && !VirtualFree(pMemPage, PAGE_SIZE, MEM_DECOMMIT)) {
DEBUGMSG(1, (L"MappedPageInHelper: VirtualFree 1 failed during PageIn!\r\n"));
}
if (pMem && !VirtualFree(pMem, 0, MEM_RELEASE)) {
DEBUGMSG(1, (L"MappedPageInHelper: VirtualFree 2 failed during PageIn!\r\n"));
}
}
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE,
(L"MappedPageInHelper: PageIn exit, 0x%08x (%d) -> %u\r\n", addr, bWrite, retval));
return retval;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int MappedPageIn (BOOL bWrite, DWORD addr)
{
int retval;
HANDLE hm;
LPFSMAP lpm;
ACCESSKEY ulOldKey;
addr = PAGEALIGN_DOWN(addr);
if (!(hm = FindMap((LPBYTE)addr))) {
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE,
(L"MMFILE: PageIn failed on FindMap 0x%08x (%d)\r\n", addr, bWrite));
return PAGEIN_FAILURE;
}
if (!(lpm = HandleToMap(hm))) {
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE, (L"MMFILE: PageIn failed on bad hMap\r\n"));
DEBUGCHK(0);
return PAGEIN_FAILURE;
}
DEBUGCHK(!(lpm->bDirectROM)); // Should never have to page in ROM maps
EnterCriticalSection(&PagerCS);
SWITCHKEY(ulOldKey, 0xffffffff);
retval = MappedPageInHelper (lpm, bWrite, addr);
if ((PAGEIN_SUCCESS == retval) && bWrite && lpm->pDirty) {
DWORD page = (addr - (DWORD)lpm->pBase + PAGE_SIZE - 1)/PAGE_SIZE;
DEBUGMSG(lpm->pDirty[DIRTY_INDEX(page)] & DIRTY_MASK(page),
(TEXT("MappedPageIn: Pagein dirtying already-dirty page %u of map 0x%08x!\r\n"),
page, lpm));
lpm->pDirty[DIRTY_INDEX(page)] |= DIRTY_MASK(page);
lpm->dwDirty++;
}
SETCURKEY(ulOldKey);
LeaveCriticalSection(&PagerCS);
return retval;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
PageOutFile(void)
{
HANDLE hMap;
LPFSMAP lpm;
EnterCriticalSection(&MapNameCS);
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE,
(L"MMFILE: PageOut starting free count: %d\r\n", PageFreeCount));
for (hMap = hMapList; hMap; hMap = lpm->hNext) {
lpm = HandleToMap(hMap);
if (lpm) {
if (lpm->pDirty != (LPBYTE)1) {
FlushMapBuffers(lpm, 0, lpm->length,
FMB_DOFULLDISCARD | (lpm->bNoAutoFlush ? FMB_NOWRITEOUT : 0));
}
} else {
// No way to signal an error -- just continue
DEBUGCHK(0);
break;
}
}
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE,
(L"MMFILE: PageOut ending free count: %d\r\n", PageFreeCount));
LeaveCriticalSection(&MapNameCS);
}
CLEANEVENT *pCFMCleanup;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
TryCloseMappedHandle(
HANDLE h
)
{
BOOL retval;
CLEANEVENT *pce, *pce2;
EnterCriticalSection(&MapNameCS);
pce = pCFMCleanup;
if (pce) {
if ((pce->size == (DWORD)pCurProc) && (pce->base == h)) {
pCFMCleanup = pce->ceptr;
FreeMem(pce, HEAP_CLEANEVENT);
retval = KernelCloseHandle(h);
LeaveCriticalSection(&MapNameCS);
return retval;
}
while (pce->ceptr) {
if ((pce->ceptr->size == (DWORD)pCurProc) && (pce->ceptr->base == h)) {
pce2 = pce->ceptr;
pce->ceptr = pce2->ceptr;
FreeMem(pce2, HEAP_CLEANEVENT);
retval = KernelCloseHandle(h);
LeaveCriticalSection(&MapNameCS);
return retval;
}
pce = pce->ceptr;
}
}
LeaveCriticalSection(&MapNameCS);
KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
return FALSE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
CloseMappedFileHandles()
{
HANDLE hm;
LPFSMAP lpm;
CLEANEVENT *pce, *pce2;
CloseHugeMemoryAreas(0);
EnterCriticalSection(&MapNameCS);
pce = pCFMCleanup;
while (pce && (pce->size == (DWORD)pCurProc)) {
pCFMCleanup = pce->ceptr;
KernelCloseHandle(pce->base);
FreeMem(pce, HEAP_CLEANEVENT);
pce = pCFMCleanup;
}
if (pce) {
while (pce->ceptr) {
if (pce->ceptr->size == (DWORD)pCurProc) {
pce2 = pce->ceptr;
pce->ceptr = pce2->ceptr;
KernelCloseHandle(pce2->base);
FreeMem(pce2, HEAP_CLEANEVENT);
} else
pce = pce->ceptr;
}
}
EnterCriticalSection(&MapCS);
for (hm = hMapList; hm; hm = lpm->hNext) {
lpm = HandleToMap(hm);
if (lpm) {
while ((pce = lpm->lpmlist) && (pce->size == (DWORD)pCurProc)) {
lpm->lpmlist = pce->ceptr;
FreeMem(pce, HEAP_CLEANEVENT);
}
if (lpm->lpmlist) {
pce2 = lpm->lpmlist;
pce = pce2->ceptr;
while (pce) {
if (pce->size == (DWORD)pCurProc) {
pce2->ceptr = pce->ceptr;
FreeMem(pce, HEAP_CLEANEVENT);
pce = pce2->ceptr;
} else {
pce2 = pce;
pce = pce->ceptr;
}
}
}
} else {
// No way to signal an error -- just continue
DEBUGCHK(0);
break;
}
}
LeaveCriticalSection(&MapCS);
LeaveCriticalSection(&MapNameCS);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
HANDLE
SC_CreateFileForMapping(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
)
{
HANDLE hFile;
CALLBACKINFO cbi;
CLEANEVENT *pce;
DWORD dwFlags;
// Make sure the caller has access to this file
if ((SC_CeGetCallerTrust() != OEM_CERTIFY_TRUST)
&& (IsSystemFile(lpFileName) || (dwFlagsAndAttributes & FILE_ATTRIBUTE_SYSTEM))
&& (!g_fSysFileReadable || (dwDesiredAccess & GENERIC_WRITE))) {
ERRORMSG(1, (TEXT("CreateFileForMapping failed due to insufficient trust\r\n")));
KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
return INVALID_HANDLE_VALUE;
}
pce = AllocMem(HEAP_CLEANEVENT);
if (!pce) {
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
return INVALID_HANDLE_VALUE;
}
// Prepare to create the file
cbi.hProc = ProcArray[0].hProc;
cbi.pfn = (FARPROC)CreateFile;
cbi.pvArg0 = MapPtr(lpFileName);
if (dwShareMode & FILE_SHARE_WRITE_OVERRIDE) {
dwFlags = FILE_SHARE_WRITE | FILE_SHARE_READ;
} else {
dwFlags = (dwDesiredAccess == GENERIC_READ) ? FILE_SHARE_READ : 0;
}
// Create the file
hFile = (HANDLE)PerformCallBack(&cbi, dwDesiredAccess, dwFlags, lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes | FILE_FLAG_WRITE_THROUGH,
hTemplateFile);
if (hFile != INVALID_HANDLE_VALUE) {
// Add to mapper cleanup list
EnterCriticalSection(&MapNameCS);
pce->base = hFile;
pce->size = (DWORD)pCurProc;
pce->ceptr = pCFMCleanup;
pCFMCleanup = pce;
LeaveCriticalSection(&MapNameCS);
} else
FreeMem(pce, HEAP_CLEANEVENT);
return hFile;
}
//------------------------------------------------------------------------------
// flProtect can only combine PAGE_READONLY, PAGE_READWRITE, and SEC_COMMIT
// lpsa ignored
//------------------------------------------------------------------------------
HANDLE
SC_CreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpsa,
DWORD flProtect,
DWORD dwMaxSizeHigh,
DWORD dwMaxSizeLow,
LPCTSTR lpName
)
{
HANDLE hMap = 0;
LPFSMAP lpm = 0;
BYTE testbyte;
BOOL bPage = TRUE;
DWORD len, dwFileLen, dwMapLen;
LPBYTE pData = 0;
BOOL bNoAutoFlush;
BOOL bDirectROM = FALSE;
BY_HANDLE_FILE_INFORMATION info;
DEBUGMSG(ZONE_ENTRY, (L"SC_CreateFileMapping entry: %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx\r\n",
hFile, lpsa, flProtect, dwMaxSizeHigh, dwMaxSizeLow, lpName));
SetNKCallOut (pCurThread);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -