📄 mapfile.c
字号:
// 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-1); // & (32-1) is faster than % 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 || ZONE_MAPFILE,
(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
//
lpm = HandleToMapPerm(hMap);
if (!lpm) {
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)
|| ((dwOffsetLow + length) < dwOffsetLow)
|| ((dwOffsetLow + length) < length)) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
goto exit;
}
//
// Prepare CleanEvent
//
lpce = AllocMem(HEAP_CLEANEVENT);
if (!lpce) {
KSetLastError(pCurThread, ERROR_OUTOFMEMORY);
goto exit;
}
IncRef(hMap, pCurProc);
lpret = lpm->pBase + dwOffsetLow;
lpce->base = lpret;
lpce->size = (DWORD)pCurProc;
lpce->ceptr = lpm->lpmlist;
lpm->lpmlist = lpce;
exit:
LeaveCriticalSection(&MapNameCS);
DEBUGMSG(ZONE_ENTRY || ZONE_MAPFILE,
(L"SC_MapViewOfFile exit: %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx -> %8.8lx\r\n",
hMap, fdwAccess, dwOffsetHigh, dwOffsetLow, cbMap, lpret));
return lpret;
}
#define FMB_LEAVENAMECS 0x1
#define FMB_DOFULLDISCARD 0x2
#define FMB_NOWRITEOUT 0x4
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
FlushMapBuffers(
LPFSMAP lpm,
DWORD dwOffset,
DWORD dwLength,
DWORD dwFlags
)
{
DWORD remain, page, end, dw1;
BOOL res, retval = FALSE;
HANDLE h;
LPBYTE pb;
ACCESSKEY ulOldKey;
// No pages to flush on ROM maps
if (lpm->bDirectROM) {
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
return TRUE;
}
SWITCHKEY(ulOldKey, 0xffffffff);
//
// Figure out where we're starting and stopping, page-aligned
//
if (!dwLength)
dwLength = lpm->length;
end = dwOffset + dwLength;
dwOffset = PAGEALIGN_DOWN(dwOffset);
end = PAGEALIGN_UP(end);
if (end > lpm->length)
end = lpm->length;
if (end < dwOffset) {
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
goto exit;
}
if (lpm->pDirty == (LPBYTE)1) {
//
// Old-style (non-transactionable) file system
//
h = lpm->hFile;
pb = lpm->pBase;
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
SetFilePointer(h, dwOffset, 0, FILE_BEGIN);
if (!FSWriteFile(h, pb, end - dwOffset, &remain) || (remain != end - dwOffset)) {
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE, (L"MMFILE: FlushMap failed on write 1\r\n"));
DEBUGCHK(0);
goto exit;
}
FlushFileBuffers(h);
retval = TRUE;
} else if (lpm->pDirty) {
//
// The file is read/write -- we may have dirty pages to flush
//
EnterCriticalSection(&WriterCS);
if (!(dwFlags & FMB_NOWRITEOUT)) {
DEBUGMSG(ZONE_MAPFILE, (L"MMFILE: FlushMap\r\n"));
EnterCriticalSection(&PagerCS);
//
// Now flush the pages in memory back to the file
//
for (page = dwOffset/PAGE_SIZE; (page+1)*PAGE_SIZE <= end; page++) {
// Flush the page only if it is dirty
if (lpm->pDirty[DIRTY_INDEX(page)] & DIRTY_MASK(page)) {
res = VirtualProtect(lpm->pBase + page*PAGE_SIZE, PAGE_SIZE,
PAGE_READONLY, &dw1);
DEBUGCHK(res);
LeaveCriticalSection(&PagerCS);
if (!WriteFileWithSeek(lpm->hFile, lpm->pBase + page*PAGE_SIZE, PAGE_SIZE,
&dw1, 0, page*PAGE_SIZE, 0) ||
(dw1 != PAGE_SIZE)) {
DEBUGMSG(ZONE_MAPFILE, (L"MMFILE: FlushMap failed on write 2\r\n"));
LeaveCriticalSection(&WriterCS);
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
DEBUGCHK(0);
goto exit;
}
EnterCriticalSection(&PagerCS);
lpm->bRestart = 1;
lpm->pDirty[DIRTY_INDEX(page)] &= ~DIRTY_MASK(page);
lpm->dwDirty--;
DEBUGCHK(!(lpm->dwDirty & 0x80000000));
}
}
// Flush the incomplete page at the end, if present
remain = end - (page*PAGE_SIZE);
if (remain && (lpm->pDirty[DIRTY_INDEX(page)] & DIRTY_MASK(page))) {
DEBUGCHK(remain <= PAGE_SIZE);
res = VirtualProtect(lpm->pBase + page*PAGE_SIZE, PAGE_SIZE,
PAGE_READONLY, &dw1);
DEBUGCHK(res);
LeaveCriticalSection(&PagerCS);
if (!WriteFileWithSeek(lpm->hFile, lpm->pBase + page*PAGE_SIZE, remain,
&dw1, 0, page*PAGE_SIZE, 0)
|| (dw1 != remain)) {
DEBUGMSG(ZONE_MAPFILE, (L"MMFILE: FlushMap failed on write 3\r\n"));
LeaveCriticalSection(&WriterCS);
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
DEBUGCHK(0);
goto exit;
}
EnterCriticalSection(&PagerCS);
lpm->bRestart = 1;
lpm->pDirty[DIRTY_INDEX(page)] &= ~DIRTY_MASK(page);
lpm->dwDirty--;
DEBUGCHK(!(lpm->dwDirty & 0x80000000));
}
LeaveCriticalSection(&PagerCS);
DEBUGMSG(ZONE_MAPFILE, (L"MMFILE: FlushMap succeeded\r\n"));
// Flush the dirty blocks in the cache back to the file
FlushFileBuffers(lpm->hFile);
}
DEBUGCHK (!lpm->bDirectROM);
if (dwFlags & FMB_DOFULLDISCARD)
DecommitROPages(lpm->pBase, lpm->reslen);
LeaveCriticalSection(&WriterCS);
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
} else {
//
// The file is read-only (no dirty pages to flush)
//
DEBUGCHK (!lpm->bDirectROM);
if ((lpm->hFile != INVALID_HANDLE_VALUE) && (dwFlags & FMB_DOFULLDISCARD)) {
FSMapMemFree(lpm->pBase, lpm->reslen, MEM_DECOMMIT);
FreeAllPagesFromQ (&lpm->pgqueue);
}
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
}
retval = TRUE;
exit:
SETCURKEY(ulOldKey);
return retval;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
KernelCloseHandle(
HANDLE hFile
)
{
CALLBACKINFO cbi;
cbi.hProc = ProcArray[0].hProc;
cbi.pfn = (FARPROC)CloseHandle;
cbi.pvArg0 = hFile;
return (BOOL)PerformCallBack4Int(&cbi);
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -