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

📄 mapfile.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 5 页
字号:
{
    HANDLE hm;
    LPFSMAP lpm;
    DWORD bread, len, len2, page;
    LPVOID pMem = 0, pMem2 = 0;
    BOOL bWritable, retval = 2;
    MEMORY_BASIC_INFORMATION mbi;
    ACCESSKEY ulOldKey;

    SWITCHKEY(ulOldKey,0xffffffff);
    addr = PAGEALIGN_DOWN(addr);

    EnterCriticalSection(&PagerCS);

    DEBUGMSG(ZONE_PAGING,(L"Taking Mapped PI fault: %8.8lx (%d)\r\n", addr, bWrite));

    VirtualQuery((LPVOID)addr, &mbi, sizeof(mbi));
    if (mbi.State == MEM_COMMIT) {
        if ((mbi.Protect == PAGE_READWRITE) || (mbi.Protect == PAGE_EXECUTE_READWRITE)
            || (!bWrite && ((mbi.Protect == PAGE_READONLY)
                            || (mbi.Protect == PAGE_EXECUTE_READ)))) {
            DEBUGMSG(ZONE_PAGING,(L"LPI: %8.8lx (%d) -> %d (1)\r\n", addr, bWrite, retval));
            LeaveCriticalSection(&PagerCS);
            return 1;
        }
    }

    if (!(hm = FindMap((LPBYTE)addr))) {
        DEBUGMSG(ZONE_PAGING,(L"LPI: %8.8lx (%d) -> 0 (4)\r\n",addr,bWrite));
        LeaveCriticalSection(&PagerCS);
        return 0;
    }

    lpm = HandleToMap(hm);
    DEBUGCHK(lpm);
    bWritable = ((lpm->hFile == INVALID_HANDLE_VALUE) || lpm->pDirty);
    if (lpm->hFile == INVALID_HANDLE_VALUE) {

        if (!(pMem = VirtualAlloc((LPVOID)addr, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE))) {
            DEBUGMSG(ZONE_PAGING, (L"    MPI: VA0 Failed!\r\n"));
            goto exit;
        }
        PagedInCount++;
        retval = 1;

    } else if (bWritable || !bWrite) {

        if (mbi.State == MEM_COMMIT) {
            if (!VirtualProtect((LPVOID)addr, PAGE_SIZE, PAGE_READWRITE, &bread)) {
                DEBUGMSG(ZONE_PAGING, (L"    MPI: VP1 Failed!\r\n"));
                goto exit;
            }

        } else {

            if (!(pMem = VirtualAlloc((LPVOID)ProcArray[0].dwVMBase, 0x10000,
                                      MEM_RESERVE, PAGE_NOACCESS))) {
                DEBUGMSG(ZONE_PAGING, (L"    MPI: VA1 Failed!\r\n"));
                goto exit;
            }

            pMem2 = (LPVOID)((DWORD)pMem + (addr&0xffff));
            if (!VirtualAlloc(pMem2, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE)) {
                DEBUGMSG(ZONE_PAGING, (L"    MPI: VA2 Failed!\r\n"));
                goto exit;
            }

            len = addr - (DWORD)lpm->pBase;
            lpm->bRestart = 0;

            LeaveCriticalSection(&PagerCS);

            // flush any logged mapfiles if too many pages are dirty
            if (bWrite && lpm->bNoAutoFlush && (lpm->dwDirty >= MAYBE_LIMIT_DIRTY - 1)) {
                FlushMapBuffersLogged(lpm, 0, 0, 0);
                retval = 3;
                goto exitnoleave;
            }

            len2 = ((DWORD)lpm->pBase + lpm->filelen - addr < PAGE_SIZE
                    ? (DWORD)lpm->pBase + lpm->filelen - addr
                    : PAGE_SIZE);
            if (!ReadFileWithSeek(lpm->hFile, pMem2, len2, &bread, 0, len, 0)
                || (bread != len2)) {
                DEBUGMSG(ZONE_PAGING,(L"    MPI: SFP Failed!\r\n"));
                retval = 3;
                goto exitnoleave;
            }

            EnterCriticalSection(&PagerCS);

            if (lpm->bRestart) {
                retval = 1;
                DEBUGMSG(ZONE_PAGING,(L"LPI: %8.8lx (%d) -> %d (restart)\r\n",
                                      addr, bWrite, retval));
                goto exit;
            }

            VirtualQuery((LPVOID)addr, &mbi, sizeof(mbi));
            if (mbi.State == MEM_COMMIT) {
                if ((mbi.Protect == PAGE_READWRITE) || (mbi.Protect == PAGE_EXECUTE_READWRITE)
                    || (!bWrite && ((mbi.Protect == PAGE_READONLY)
                                    || (mbi.Protect == PAGE_EXECUTE_READ))))
                    retval = 1;
                else
                    retval = 0;
                DEBUGMSG(ZONE_PAGING,(L"LPI: %8.8lx (%d) -> %d (1)\r\n",
                                      addr, bWrite, retval));
                goto exit;
            }

            if (!VirtualCopy((LPVOID)addr, pMem2, PAGE_SIZE,
                             bWrite ? PAGE_READWRITE : PAGE_READONLY)) {
                DEBUGMSG(ZONE_PAGING,(L"    MPI: VC Failed!\r\n"));
                goto exit;
            }

            PagedInCount++;
        }

        if (bWrite) {
            page = (addr - (DWORD)lpm->pBase + PAGE_SIZE - 1)/PAGE_SIZE;
            lpm->pDirty[page/8] |= (1<<(page%8));
            lpm->dwDirty++;
        }

        retval = 1;

    } else
        retval = 0;

exit:
    LeaveCriticalSection(&PagerCS);

exitnoleave:
    DEBUGMSG(ZONE_PAGING,(L"MappedPageIn exit: %8.8lx %8.8lx -> %8.8lx\r\n",
                          bWrite, addr, retval));

    if (pMem2)
        if (!VirtualFree(pMem2,PAGE_SIZE,MEM_DECOMMIT))
            DEBUGMSG(ZONE_PAGING,(L"  MapPage in failure in VF1!\r\n"));

    if (pMem)
        if (!VirtualFree(pMem,0,MEM_RELEASE))
            DEBUGMSG(ZONE_PAGING,(L"  MapPage in failure in VF2!\r\n"));

    SETCURKEY(ulOldKey);

    return retval;
}


void PageOutFile(void)
{
    HANDLE hMap;
    LPFSMAP lpm;
    EnterCriticalSection(&MapNameCS);
    DEBUGMSG(ZONE_PAGING,(L"MPO: Starting free count: %d\r\n",PageFreeCount));
    for (hMap = hMapList; hMap; hMap = lpm->hNext) {
        lpm = HandleToMap(hMap);
        DEBUGCHK(lpm);
        if (lpm->pDirty != (LPBYTE)1)
            FlushMapBuffers(lpm, 0, lpm->length,
                            FMB_DOFULLDISCARD | (lpm->bNoAutoFlush ? FMB_NOWRITEOUT : 0));
    }
    DEBUGMSG(ZONE_PAGING,(L"MPO: Ending page 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);
        DEBUGCHK(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;
                }           
            }
        }
    }

    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;

    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 = 1;
    DWORD len, realfilelen, reallen;
    PHDATA phd;
    LPBYTE pData = 0;
    BOOL bNoAutoFlush;

    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));

    bNoAutoFlush = (flProtect & PAGE_INTERNALDBMAPPING) ? 1 : 0;
    flProtect &= ~(SEC_COMMIT|PAGE_INTERNALDBMAPPING);

    // Remove from mapper cleanup list, if present
    if ((hFile != INVALID_HANDLE_VALUE) && !bNoAutoFlush) {
        CLEANEVENT *pce, *pce2;

        EnterCriticalSection(&MapNameCS);

        if (pce = pCFMCleanup) {
            if (pce->base == hFile) {
                pCFMCleanup = pce->ceptr;
                FreeMem(pce, HEAP_CLEANEVENT);
            } else {
                while (pce->ceptr && (pce->ceptr->base != hFile))
                    pce = pce->ceptr;
                if (pce2 = pce->ceptr) {
                    pce->ceptr = pce2->ceptr;
                    FreeMem(pce2, HEAP_CLEANEVENT);
                }
            }
        }

        LeaveCriticalSection(&MapNameCS);
    }

    // Reject if the file is empty (??)
    if ((hFile != INVALID_HANDLE_VALUE)
        && ((realfilelen = SetFilePointer(hFile, 0, 0, FILE_END)) == 0xffffffff)) {
        KernelCloseHandle(hFile);
        KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
        return 0;
    }

    // Determine the size the map should have
    if ((hFile == INVALID_HANDLE_VALUE) || dwMaxSizeLow)
        reallen = dwMaxSizeLow;
    else
        reallen = realfilelen;
    if (reallen & 0x80000000) {
        KernelCloseHandle(hFile);
        KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
        return 0;
    }

    // Clip the file to the new size, if necessary
    if ((hFile != INVALID_HANDLE_VALUE) && (realfilelen < reallen)) {
        if (!bNoAutoFlush && ((SetFilePointer(hFile, reallen, 0, FILE_BEGIN) != reallen)
                              || !SetEndOfFile(hFile))) {
            KernelCloseHandle(hFile);
            KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
            return 0;
        }

        realfilelen = reallen;
    }

    //
    // Make sure the mapping doesn't already exist
    //

    EnterCriticalSection(&MapNameCS);

    if (lpName) {
        // Check name
        if ((len = strlenW(lpName)) > MAX_PATH - 1) {
            KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
            goto errexit;
        }

        EnterCriticalSection(&MapCS);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -