⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mapfile.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 *              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 + -