📄 mapfile.c
字号:
/*
* NK Kernel loader code
*
* Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
*
* Module Name:
*
* mapfile.c
*
* Abstract:
*
* This file implements the NK kernel mapped file routines
*
*/
#include "kernel.h"
DWORD rbRes;
DWORD rbSubRes[NUM_MAPPER_SECTIONS];
extern CRITICAL_SECTION VAcs, PagerCS, MapCS, MapNameCS, WriterCS;
HANDLE hMapList;
BOOL SC_MapCloseHandle(HANDLE hMap);
BOOL ValidateFile(LPFSMAP lpm);
BOOL FlushMapBuffersLogged(LPFSMAP lpm, DWORD dwOffset, DWORD dwLength, DWORD dwFlags);
const PFNVOID MapMthds[] = {
(PFNVOID)SC_MapCloseHandle,
(PFNVOID)0,
(PFNVOID)SC_MapViewOfFile,
};
const CINFO cinfMap = {
"FMAP",
DISPATCH_KERNEL_PSL,
HT_FSMAP,
sizeof(MapMthds)/sizeof(MapMthds[0]),
MapMthds
};
#define SUB_MAPPER_INCR (MAPPER_INCR/32)
#define MapBits(n) ((n) == 0x1f ? 0xffffffff : (1<<((n)+1))-1)
// Restore flags used for map buffer logged flush
#define RESTORE_FLAG_NONE 0
#define RESTORE_FLAG_UNFLUSHED 1
#define RESTORE_FLAG_FLUSHED 2
// reserves a memory region of length len
LPVOID FSMapMemReserve(DWORD len)
{
DWORD secs;
DWORD first, curr, trav;
LPVOID retval = 0;
DEBUGCHK(len);
EnterCriticalSection(&VAcs);
if (len >= MAPPER_INCR) {
secs = (len + MAPPER_INCR - 1)/MAPPER_INCR;
first = 0;
for (curr = 0; curr <= NUM_MAPPER_SECTIONS - secs; curr++) {
if (rbRes & (1<<curr))
first = curr+1;
else if (curr - first + 1 == secs)
break;
}
if (curr > NUM_MAPPER_SECTIONS - secs)
goto exit;
for (trav = first; trav <= curr; trav++) {
if (!CreateMapperSection(FIRST_MAPPER_ADDRESS+(MAPPER_INCR*trav))) {
while (trav-- != first) {
DeleteMapperSection(FIRST_MAPPER_ADDRESS+(MAPPER_INCR*trav));
rbRes &= ~(1<<trav);
}
goto exit;
}
rbRes |= (1<<trav);
rbSubRes[trav] = (trav == curr
? MapBits(((len - 1)%MAPPER_INCR)/SUB_MAPPER_INCR)
: (DWORD)-1);
}
retval = (LPVOID)(FIRST_MAPPER_ADDRESS + (MAPPER_INCR*first));
} else {
secs = (len + SUB_MAPPER_INCR - 1) / SUB_MAPPER_INCR;
for (curr = 0; curr < NUM_MAPPER_SECTIONS; curr++) {
if (rbRes & (1<<curr)) {
first = 0;
for (trav = 0; trav <= 32-secs; trav++) {
if (rbSubRes[curr] & (1<<trav))
first = trav+1;
else if (trav - first == secs)
break;
}
if (trav <= 32-secs)
break;
}
}
if (curr == NUM_MAPPER_SECTIONS) {
for (curr = 0; curr < NUM_MAPPER_SECTIONS; curr++) {
if (!(rbRes & (1<<curr))) {
if (!CreateMapperSection(FIRST_MAPPER_ADDRESS + (MAPPER_INCR*curr)))
goto exit;
rbRes |= (1<<curr);
rbSubRes[curr] = MapBits(((len-1)/SUB_MAPPER_INCR));
retval = (LPVOID)(FIRST_MAPPER_ADDRESS + (MAPPER_INCR*curr));
break;
}
}
} else {
rbSubRes[curr] |= (MapBits(((len-1)/SUB_MAPPER_INCR)) << first);
retval = (LPVOID)(FIRST_MAPPER_ADDRESS + (MAPPER_INCR*curr)
+ (SUB_MAPPER_INCR*first));
}
}
exit:
LeaveCriticalSection(&VAcs);
return retval;
}
CLEANEVENT *pHugeCleanList;
LPVOID HugeVirtualReserve(DWORD dwSize)
{
LPCLEANEVENT lpce;
LPVOID pMem;
dwSize = PAGEALIGN_UP(dwSize);
if (!(lpce = AllocMem(HEAP_CLEANEVENT))) {
KSetLastError(pCurThread, ERROR_OUTOFMEMORY);
return 0;
}
if (!(pMem = FSMapMemReserve(dwSize))) {
FreeMem(lpce, HEAP_CLEANEVENT);
KSetLastError(pCurThread, ERROR_OUTOFMEMORY);
return 0;
}
lpce->base = pMem;
lpce->op = dwSize;
lpce->size = (DWORD)pCurProc;
EnterCriticalSection(&MapNameCS);
lpce->ceptr = pHugeCleanList;
pHugeCleanList = lpce;
LeaveCriticalSection(&MapNameCS);
return pMem;
}
BOOL FSMapMemFree(LPBYTE pBase, DWORD len, DWORD flags);
BOOL CloseHugeMemoryAreas(LPVOID pMem)
{
LPCLEANEVENT pce, pce2;
EnterCriticalSection(&MapNameCS);
pce = pHugeCleanList;
while (pce && (pce->size == (DWORD)pCurProc) && (!pMem || (pMem == pce->base))) {
pHugeCleanList = pce->ceptr;
VirtualFree(pce->base, pce->op, MEM_DECOMMIT);
FSMapMemFree(pce->base, pce->op, MEM_RELEASE);
FreeMem(pce, HEAP_CLEANEVENT);
pce = pHugeCleanList;
if (pMem) {
LeaveCriticalSection(&MapNameCS);
return TRUE;
}
}
if (pce) {
while (pce->ceptr) {
if ((pce->ceptr->size == (DWORD)pCurProc)
&& (!pMem || (pMem == pce->ceptr->base))) {
pce2 = pce->ceptr;
pce->ceptr = pce2->ceptr;
VirtualFree(pce2->base, pce2->op, MEM_DECOMMIT);
FSMapMemFree(pce2->base, pce2->op, MEM_RELEASE);
FreeMem(pce2, HEAP_CLEANEVENT);
if (pMem) {
LeaveCriticalSection(&MapNameCS);
return TRUE;
}
} else
pce = pce->ceptr;
}
}
LeaveCriticalSection(&MapNameCS);
return FALSE;
}
BOOL HugeVirtualRelease(LPVOID pMem)
{
if (!CloseHugeMemoryAreas(pMem)) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
void DecommitROPages(LPBYTE pBase, DWORD len)
{
MEMORY_BASIC_INFORMATION mbi;
EnterCriticalSection(&VAcs);
while (len) {
if (!VirtualQuery(pBase, &mbi, sizeof(mbi))) {
DEBUGCHK(0);
break;
}
if ((mbi.State == MEM_COMMIT) && (mbi.Protect == PAGE_READONLY))
VirtualFree(pBase, mbi.RegionSize, MEM_DECOMMIT);
pBase += mbi.RegionSize;
if (len < mbi.RegionSize)
break;
len -= mbi.RegionSize;
}
LeaveCriticalSection(&VAcs);
}
// Decommits or releases a MapMemReserve'd chunk of memory. Length must be passed in.
// Flags must be MEM_DECOMMIT *or* MEM_RELEASE, and to RELEASE the range must be
// decommitted already. pBase and len must be page aligned for DECOMMIT. pBase must be
// SUB_MAPPER_INCR aligned and len must be page aligned for RELEASE
BOOL FSMapMemFree(LPBYTE pBase, DWORD len, DWORD flags)
{
BOOL res, retval = FALSE;
LPBYTE pCurr = pBase;
DWORD curr, trav, currbytes, bytesleft = len;
DEBUGCHK((DWORD)pCurr == PAGEALIGN_UP((DWORD)pCurr));
DEBUGCHK(bytesleft == PAGEALIGN_UP(bytesleft));
EnterCriticalSection(&VAcs);
if (flags == MEM_DECOMMIT) {
while (bytesleft) {
currbytes = ((DWORD)(pCurr + MAPPER_INCR) & ~(MAPPER_INCR-1)) - (DWORD)pCurr;
if (currbytes > bytesleft)
currbytes = bytesleft;
DEBUGCHK((DWORD)pCurr == ((DWORD)pCurr & ~(PAGE_SIZE-1)));
DEBUGCHK(currbytes == PAGEALIGN_UP(currbytes));
res = VirtualFree(pCurr, currbytes, MEM_DECOMMIT);
DEBUGCHK(res);
pCurr += currbytes;
bytesleft -= currbytes;
}
retval = TRUE;
} else if (flags == MEM_RELEASE) {
do {
curr = ((DWORD)pCurr - FIRST_MAPPER_ADDRESS)/MAPPER_INCR;
trav = ((DWORD)pCurr/SUB_MAPPER_INCR)%32;
DEBUGCHK(rbSubRes[curr] & (1<<trav));
if (!(rbSubRes[curr] &= ~(1<<trav))) {
rbRes &= ~(1<<curr);
DeleteMapperSection(FIRST_MAPPER_ADDRESS+(MAPPER_INCR*curr));
}
pCurr += SUB_MAPPER_INCR;
} while (pCurr < pBase + len);
retval = TRUE;
}
LeaveCriticalSection(&VAcs);
return retval;
}
// pBase and len must be page-aligned
BOOL FSMapMemCommit(LPBYTE pBase, DWORD len, DWORD access)
{
BOOL retval = FALSE;
LPBYTE pFree, pCurr = pBase;
DWORD currbytes, bytesleft = len;
DEBUGCHK((DWORD)pCurr == PAGEALIGN_UP((DWORD)pCurr));
DEBUGCHK(bytesleft == PAGEALIGN_UP(bytesleft));
EnterCriticalSection(&VAcs);
while (bytesleft) {
currbytes = (((DWORD)pCurr + MAPPER_INCR) & ~(MAPPER_INCR-1)) - (DWORD)pCurr;
if (currbytes > bytesleft)
currbytes = bytesleft;
DEBUGCHK(currbytes == PAGEALIGN_UP(currbytes));
if (!VirtualAlloc(pCurr, currbytes, MEM_COMMIT, access)) {
pFree = pBase;
bytesleft = len;
while (pFree != pCurr) {
currbytes = (((DWORD)pCurr + MAPPER_INCR) & ~(MAPPER_INCR-1)) - (DWORD)pCurr;
if (currbytes > bytesleft)
currbytes = bytesleft;
VirtualFree(pFree, currbytes,MEM_DECOMMIT);
pFree += currbytes;
bytesleft -= currbytes;
}
goto exit;
}
pCurr += currbytes;
bytesleft -= currbytes;
}
retval = TRUE;
exit:
LeaveCriticalSection(&VAcs);
return retval;
}
// Provides r/w view if request r/o view of r/w map
LPVOID SC_MapViewOfFile(HANDLE hMap, DWORD fdwAccess, DWORD dwOffsetHigh,
DWORD dwOffsetLow, DWORD cbMap)
{
LPFSMAP lpm;
LPVOID lpret = 0;
DWORD length;
CLEANEVENT *lpce;
DEBUGMSG(ZONE_ENTRY,(L"SC_MapViewOfFile entry: %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx\r\n",
hMap, fdwAccess, dwOffsetHigh, dwOffsetLow, cbMap));
EnterCriticalSection(&MapNameCS);
//
// Check args
//
if (!(lpm = (bAllKMode ? HandleToMapPerm(hMap) : HandleToMap(hMap)))) {
KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
goto exit;
}
length = (cbMap ? cbMap : lpm->length - dwOffsetLow);
if ((fdwAccess == FILE_MAP_ALL_ACCESS)
|| (fdwAccess == (FILE_MAP_WRITE | FILE_MAP_READ)))
fdwAccess = FILE_MAP_WRITE;
if (dwOffsetHigh
|| ((fdwAccess == FILE_MAP_WRITE)
&& (lpm->hFile != INVALID_HANDLE_VALUE)
&& !lpm->pDirty)
|| (fdwAccess & ~(FILE_MAP_READ|FILE_MAP_WRITE))
|| ((dwOffsetLow + length) > lpm->length)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -