📄 mapfile.c
字号:
|| ((dwOffsetLow + length) < dwOffsetLow)
|| ((dwOffsetLow + length) < length)) {
KSetLastError(pCurThread,ERROR_INVALID_PARAMETER);
goto exit;
}
//
// Prepare CleanEvent
//
if (!(lpce = AllocMem(HEAP_CLEANEVENT))) {
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,(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;
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);
return FALSE;
}
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 (!WriteFile(h,pb,end-dwOffset,&remain,0) || (remain != end-dwOffset)) {
DEBUGMSG(ZONE_PAGING,(L"FMB 5\r\n"));
DEBUGCHK(0);
goto exit;
}
FlushFileBuffers(h);
retval = TRUE;
} else if (lpm->pDirty) {
//
// We have dirty memory to flush
//
EnterCriticalSection(&WriterCS);
if (!(dwFlags & FMB_NOWRITEOUT)) {
DEBUGMSG(ZONE_PAGING,(L"FMB 1\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[page/8] & (1<<(page%8))) {
lpm->bRestart = 1;
lpm->pDirty[page/8] &= ~(1<<(page%8));
res = VirtualProtect(lpm->pBase+page*PAGE_SIZE, PAGE_SIZE,
PAGE_READONLY, &dw1);
DEBUGCHK(res);
lpm->dwDirty--;
DEBUGCHK(!(lpm->dwDirty & 0x80000000));
LeaveCriticalSection(&PagerCS);
if (!WriteFileWithSeek(lpm->hFile, lpm->pBase+page*PAGE_SIZE, PAGE_SIZE,
&dw1, 0, page*PAGE_SIZE, 0) ||
(dw1 != PAGE_SIZE)) {
DEBUGMSG(ZONE_PAGING,(L"FMB 2\r\n"));
LeaveCriticalSection(&WriterCS);
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
DEBUGCHK(0);
goto exit;
}
EnterCriticalSection(&PagerCS);
}
}
// Flush the incomplete page at the end, if present
remain = end - (page*PAGE_SIZE);
if (remain && (lpm->pDirty[page/8] & (1<<(page%8)))) {
DEBUGCHK(remain<=PAGE_SIZE);
lpm->bRestart = 1;
lpm->pDirty[page/8] &= ~(1<<(page%8));
res = VirtualProtect(lpm->pBase+page*PAGE_SIZE, PAGE_SIZE,
PAGE_READONLY, &dw1);
DEBUGCHK(res);
lpm->dwDirty--;
DEBUGCHK(!(lpm->dwDirty & 0x80000000));
LeaveCriticalSection(&PagerCS);
if (!WriteFileWithSeek(lpm->hFile, lpm->pBase+page*PAGE_SIZE, remain,
&dw1, 0, page*PAGE_SIZE, 0)
|| (dw1 != remain)) {
DEBUGMSG(ZONE_PAGING,(L"FMB 3\r\n"));
LeaveCriticalSection(&WriterCS);
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
DEBUGCHK(0);
goto exit;
}
} else
LeaveCriticalSection(&PagerCS);
DEBUGMSG(ZONE_PAGING,(L"FMB 4\r\n"));
// Flush the dirty blocks in the cache back to the file
FlushFileBuffers(lpm->hFile);
}
if (dwFlags & FMB_DOFULLDISCARD)
DecommitROPages(lpm->pBase,lpm->reslen);
LeaveCriticalSection(&WriterCS);
if (dwFlags & FMB_LEAVENAMECS)
LeaveCriticalSection(&MapNameCS);
} else {
//
// No dirty memory
//
if ((lpm->hFile != INVALID_HANDLE_VALUE) && (dwFlags & FMB_DOFULLDISCARD))
FSMapMemFree(lpm->pBase,lpm->reslen,MEM_DECOMMIT);
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);
}
void FreeMap(HANDLE hMap)
{
CLEANEVENT *lpce;
LPFSMAP lpm, lpm2;
HANDLE hm;
lpm = HandleToMap(hMap);
DEBUGCHK(lpm);
EnterCriticalSection(&MapCS);
// Remove from the list of maps
if (hMapList == hMap)
hMapList = HandleToMap(hMap)->hNext;
else {
for (hm = hMapList; hm; hm = lpm2->hNext) {
lpm2 = HandleToMap(hm);
DEBUGCHK(lpm2);
if (lpm2->hNext == hMap) {
lpm2->hNext = lpm->hNext;
break;
}
}
DEBUGCHK(hm);
}
LeaveCriticalSection(&MapCS);
// Flush all dirty pages back to the file
if (lpm->bNoAutoFlush)
FlushMapBuffersLogged(lpm, 0, lpm->length, FMB_LEAVENAMECS);
else
FlushMapBuffers(lpm, 0, lpm->length, FMB_LEAVENAMECS);
if ((lpm->hFile != INVALID_HANDLE_VALUE) && !lpm->bNoAutoFlush)
KernelCloseHandle(lpm->hFile);
if (lpm->name)
FreeName(lpm->name);
while (lpm->lpmlist) {
lpce = lpm->lpmlist->ceptr;
FreeMem(lpm->lpmlist, HEAP_CLEANEVENT);
lpm->lpmlist = lpce;
}
FSMapMemFree(lpm->pBase, lpm->reslen, MEM_DECOMMIT);
FSMapMemFree(lpm->pBase, lpm->reslen, MEM_RELEASE);
FreeMem(lpm, HEAP_FSMAP);
FreeHandle(hMap);
}
HANDLE FindMap(LPBYTE pMem)
{
HANDLE hm;
LPFSMAP lpm;
EnterCriticalSection(&MapCS);
for (hm = hMapList; hm; hm = lpm->hNext) {
lpm = HandleToMap(hm);
DEBUGCHK(lpm);
if ((lpm->pBase <= pMem) && (pMem < lpm->pBase + lpm->length))
break;
}
LeaveCriticalSection(&MapCS);
return hm;
}
BOOL SC_UnmapViewOfFile(LPVOID lpvAddr)
{
BOOL retval = FALSE;
HANDLE hm;
BOOL bLeft = 0;
LPFSMAP lpm;
CLEANEVENT *lpce, *lpce2;
DEBUGMSG(ZONE_ENTRY,(L"SC_UnmapViewOfFile entry: %8.8lx\r\n", lpvAddr));
EnterCriticalSection(&MapNameCS);
if (hm = FindMap(lpvAddr)) {
lpm = HandleToMap(hm);
lpce2 = NULL;
if (lpce = lpm->lpmlist) {
if ((lpce->base == lpvAddr) && (lpce->size == (DWORD)pCurProc))
lpm->lpmlist = lpce->ceptr;
else {
do {
lpce2 = lpce;
lpce = lpce->ceptr;
} while (lpce && ((lpce->base != lpvAddr)
|| (lpce->size != (DWORD)pCurProc)));
if (lpce)
lpce2->ceptr = lpce->ceptr;
}
}
if (lpce) {
FreeMem(lpce, HEAP_CLEANEVENT);
if (DecRef(hm, pCurProc, FALSE)) {
FreeMap(hm);
bLeft = 1;
}
retval = TRUE;
} else
KSetLastError(pCurThread, ERROR_INVALID_ADDRESS);
} else
KSetLastError(pCurThread, ERROR_INVALID_ADDRESS);
if (!bLeft)
LeaveCriticalSection(&MapNameCS);
DEBUGMSG(ZONE_ENTRY,(L"SC_UnmapViewOfFile exit: %8.8lx -> %8.8lx\r\n",
lpvAddr, retval));
return retval;
}
BOOL SC_FlushViewOfFile(LPCVOID lpBaseAddress, DWORD dwNumberOfBytesToFlush)
{
BOOL retval = FALSE;
LPFSMAP lpm;
HANDLE hm;
DEBUGMSG(ZONE_ENTRY,(L"SC_FlushViewOfFile entry: %8.8lx %8.8lx\r\n",
lpBaseAddress, dwNumberOfBytesToFlush));
EnterCriticalSection(&MapNameCS);
if (hm = FindMap((LPBYTE)lpBaseAddress)) {
lpm = HandleToMap(hm);
DEBUGCHK(lpm);
if (lpm->bNoAutoFlush) {
retval = FlushMapBuffersLogged(lpm, (LPBYTE)lpBaseAddress-lpm->pBase,
dwNumberOfBytesToFlush, FMB_LEAVENAMECS);
} else
retval = FlushMapBuffers(lpm, (LPBYTE)lpBaseAddress-lpm->pBase,
dwNumberOfBytesToFlush, FMB_LEAVENAMECS);
} else
LeaveCriticalSection(&MapNameCS);
DEBUGMSG(ZONE_ENTRY,(L"SC_FlushViewOfFile exit: %8.8lx %8.8lx -> %8.8lx\r\n",
lpBaseAddress, dwNumberOfBytesToFlush, retval));
return retval;
}
#if (PAGE_SIZE == 1024)
#define MAYBE_LIMIT_MEMORY 32
#define MAYBE_LIMIT_DIRTY 72
#else
#define MAYBE_LIMIT_MEMORY 10
#define MAYBE_LIMIT_DIRTY 18
#endif
BOOL SC_FlushViewOfFileMaybe(LPCVOID lpBaseAddress, DWORD dwNumberOfBytesToFlush)
{
extern long PageOutTrigger;
BOOL retval = FALSE;
LPFSMAP lpm;
HANDLE hm;
DEBUGMSG(ZONE_ENTRY,(L"SC_FlushViewOfFileMaybe entry: %8.8lx %8.8lx\r\n",
lpBaseAddress, dwNumberOfBytesToFlush));
EnterCriticalSection(&MapNameCS);
if (hm = FindMap((LPBYTE)lpBaseAddress)) {
lpm = HandleToMap(hm);
DEBUGCHK(lpm);
if ((PageFreeCount >= MAYBE_LIMIT_MEMORY + PageOutTrigger)
&& (lpm->dwDirty < MAYBE_LIMIT_DIRTY)) {
LeaveCriticalSection(&MapNameCS);
retval = TRUE;
} else if (lpm->bNoAutoFlush) {
retval = FlushMapBuffersLogged(lpm, (LPBYTE)lpBaseAddress-lpm->pBase,
dwNumberOfBytesToFlush, FMB_LEAVENAMECS);
} else {
retval = FlushMapBuffers(lpm, (LPBYTE)lpBaseAddress-lpm->pBase,
dwNumberOfBytesToFlush, FMB_LEAVENAMECS);
}
} else
LeaveCriticalSection(&MapNameCS);
DEBUGMSG(ZONE_ENTRY,(L"SC_FlushViewOfFileMaybe exit: %8.8lx %8.8lx -> %8.8lx\r\n",
lpBaseAddress, dwNumberOfBytesToFlush, retval));
return retval;
}
int MappedPageIn(BOOL bWrite, DWORD addr)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -