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

📄 mapfile.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//------------------------------------------------------------------------------
void
FreeMap(
    HANDLE  hMap
    )
{
    CLEANEVENT *lpce;
    LPFSMAP lpm, lpm2;
    HANDLE  hm;

    DEBUGCHK(MapNameCS.OwnerThread == pCurThread->hTh); // Must own MapNameCS

    lpm = HandleToMap(hMap);
    if (!lpm) {
        // No way to signal an error
        DEBUGCHK(0);
        return;
    }

    EnterCriticalSection(&MapCS);

    // Remove from the list of maps
    if (hMapList == hMap)
        hMapList = lpm->hNext;
    else {
        for (hm = hMapList; hm; hm = lpm2->hNext) {
            lpm2 = HandleToMap(hm);
            if (lpm2) {
                if (lpm2->hNext == hMap) {
                    lpm2->hNext = lpm->hNext;
                    break;
                }
            } else {
                // No way to signal an error -- just continue
                DEBUGCHK(0);
                break;
            }
        }
        DEBUGCHK(hm);
    }

    LeaveCriticalSection(&MapCS);

    // Flush all dirty pages back to the file
    if (lpm->bNoAutoFlush) {
        if (FlushMapBuffersLogged(lpm, 0, lpm->length, FMB_LEAVENAMECS)) {
            FlushSettings FlushStruct;
            DWORD         dwTemp;

            // Remove kernel logging area reserved at the end of the file.
            // This must ONLY be done if the flush completed successfully.
            // To avoid growing/shrinking/growing/shrinking repeatedly, it is
            // only done when the map is freed.
            if (ReadFileWithSeek(lpm->hFile, &FlushStruct, sizeof(FlushSettings),
                                 &dwTemp, 0, offsetof(fslog_t, dwRestoreFlags), 0)
                && (dwTemp == sizeof(FlushSettings))
                && (SetFilePointer(lpm->hFile, FlushStruct.dwRestoreStart, NULL,
                                   FILE_BEGIN) == FlushStruct.dwRestoreStart)) {
                DEBUGMSG(ZONE_MAPFILE, (TEXT("MMFILE: Removing logging area from flushed map 0x%08x at 0x%08x, old size 0x%08x\r\n"),
                                        lpm, FlushStruct.dwRestoreStart, GetFileSize(lpm->hFile, NULL)));
                SetEndOfFile(lpm->hFile);
            }
        }
    } 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;
    }

    {
        LPBYTE pBase = (LPBYTE) PAGEALIGN_DOWN((DWORD)lpm->pBase);
        DWORD  len = PAGEALIGN_UP((DWORD)lpm->pBase + lpm->reslen - (DWORD) pBase);
        FSMapMemFree(pBase, len, MEM_DECOMMIT);
        FreeAllPagesFromQ (&lpm->pgqueue);
        FSMapMemFree(pBase, len, 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);
        if (lpm) {
            if ((lpm->pBase == pMem) || ((lpm->pBase <  pMem) && (pMem < lpm->pBase + lpm->length)))
                break;
        } else {
            DEBUGCHK(0);
            hm = (HANDLE)0;
            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 {
        DEBUGCHK(!hm); // DEBUGCHK only if lpm assignment failed
        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))) {
        
        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 {
        DEBUGCHK(!hm); // DEBUGCHK only if lpm assignment failed
        LeaveCriticalSection(&MapNameCS);
    }
    
    DEBUGMSG(ZONE_ENTRY, (L"SC_FlushViewOfFile exit: %8.8lx %8.8lx -> %8.8lx\r\n",
                          lpBaseAddress, dwNumberOfBytesToFlush, retval));
    
    return retval;
}


//------------------------------------------------------------------------------
// Not exposed directly, but through IOCTL_KLIB_CHANGEMAPFLUSHING.  Changes the
// flush settings for the mapped view of a file starting at lpBaseAddress.
// The flush settings affect the entire mapping, so no range is given.  Flush
// changes are only supported on logged maps.  Suspending flushing should not
// be taken lightly: it can lead to data loss, OOM, or ballooned file sizes.
//------------------------------------------------------------------------------
BOOL 
ChangeMapFlushing(
    LPCVOID lpBaseAddress,
    DWORD   dwFlags
    )
{
    BOOL retval = FALSE;
    LPFSMAP lpm;
    HANDLE hm;

    if (SC_CeGetCallerTrust() != OEM_CERTIFY_TRUST) {
        KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
        return FALSE;
    }

    EnterCriticalSection(&MapNameCS);
    if ((hm = FindMap((LPBYTE)lpBaseAddress)) && (lpm = HandleToMap(hm))) {
        
        // Flush changes are only used for database volumes so they are only
        // supported on logged maps
        if (lpm->bNoAutoFlush) {
            DEBUGMSG(ZONE_MAPFILE, (TEXT("MMFILE: Changing map 0x%08x flush flags 0x%08x  (%u dirty)\r\n"),
                                    lpm, dwFlags, lpm->dwDirty));
            lpm->bFlushFlags = (BYTE)(dwFlags & FILEMAP_NOBACKGROUNDFLUSH); // Only one flag supported
            retval = TRUE;
        } else {
            KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
        }
    
    } else {
        KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
        DEBUGCHK(!hm); // DEBUGCHK only if lpm assignment failed
    }
    LeaveCriticalSection(&MapNameCS);
    
    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))) {

        if ((PageFreeCount >= MAYBE_LIMIT_MEMORY + PageOutTrigger)
            && (lpm->dwDirty < MAYBE_LIMIT_DIRTY)) {
            LeaveCriticalSection(&MapNameCS);
            retval = TRUE;

        } else if (lpm->bNoAutoFlush) {
            if (lpm->bFlushFlags & FILEMAP_NOBACKGROUNDFLUSH) {
                // Skip background flushing
                LeaveCriticalSection(&MapNameCS);
                retval = TRUE;
            } else {
                retval = FlushMapBuffersLogged(lpm, (LPBYTE)lpBaseAddress - lpm->pBase,
                                               dwNumberOfBytesToFlush, FMB_LEAVENAMECS);
            }
        
        } else {
            retval = FlushMapBuffers(lpm, (LPBYTE)lpBaseAddress-lpm->pBase,
                                     dwNumberOfBytesToFlush, FMB_LEAVENAMECS);
        }

    } else {
        DEBUGCHK(!hm); // DEBUGCHK only if lpm assignment failed
        LeaveCriticalSection(&MapNameCS);
    }

    DEBUGMSG(ZONE_ENTRY, (L"SC_FlushViewOfFileMaybe exit: %8.8lx %8.8lx -> %8.8lx\r\n",
                          lpBaseAddress, dwNumberOfBytesToFlush, retval));

    return retval;
}

int MappedPageInPage (LPFSMAP lpm, BOOL bWrite, DWORD addr, LPBYTE pMem)
{
    DWORD   cbRead, cbToRead;
    
    // Flush logged mapfiles if too many pages are dirty
    if (bWrite
        && lpm->bNoAutoFlush
        && (lpm->dwDirty >= MAYBE_LIMIT_DIRTY - 1)
        && !(lpm->bFlushFlags & FILEMAP_NOBACKGROUNDFLUSH)) {
                if (FlushMapBuffersLogged(lpm, 0, 0, 0)) {
            return PAGEIN_OTHERRETRY;
        }
        // Continue with pagein if the flush failed
        RETAILMSG(1, (TEXT("MMFILE: PageIn continuing after mapped flush failure\r\n")));
    }

    if ((cbToRead = (DWORD) lpm->pBase + lpm->filelen - addr) > PAGE_SIZE)
        cbToRead = PAGE_SIZE;

    if (!ReadFileWithSeek (lpm->hFile, pMem, cbToRead, &cbRead, 0, addr - (DWORD)lpm->pBase, 0)) {
        DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE,
                 (L"MappedPageInPage: PageIn failed on ReadFile (0x%08x of 0x%08x read, pos 0x%08x of 0x%08x)\r\n",
                  cbRead, cbToRead, addr - (DWORD)lpm->pBase, lpm->filelen));
        return (KGetLastError (pCurThread) != ERROR_DEVICE_REMOVED)?  PAGEIN_RETRY : PAGEIN_FAILURE;
    }

    // if the mapfile changed underneath, don't bother retrying
    return (cbRead == cbToRead)? PAGEIN_SUCCESS : PAGEIN_FAILURE;
}

int MMQueryState (DWORD addr, BOOL bWrite)
{
    MEMORY_BASIC_INFORMATION mbi;
    DWORD dwOldProtect;

    if (!VirtualQuery((LPVOID)addr, &mbi, sizeof(mbi))) {
        DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE, (L"MMQueryState: VirtualQuery failed\r\n"));
        return PAGEIN_FAILURE;
    }
    
    if (MEM_COMMIT == mbi.State) {
        // memory already commited, someone else beat us paging the page in.
        // Just check/update protection and return accordingly
        
        switch (mbi.Protect & ~(PAGE_NOCACHE|PAGE_GUARD)) {
        case PAGE_READWRITE:
        case PAGE_EXECUTE_READWRITE:
            return PAGEIN_SUCCESS;
            
        case PAGE_READONLY:
        case PAGE_EXECUTE_READ:
            if (!bWrite
                || VirtualProtect((LPVOID)addr, PAGE_SIZE, PAGE_READWRITE, &dwOldProtect)) {
                return PAGEIN_SUCCESS;
            }

            DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE, (L"MMQueryState: Failed: write on RO pages\r\n"));
            // fall through
        default:
            break;
        }
        return PAGEIN_FAILURE;
    }

    // return PAGEIN_RETRY if the memory is not commited (not yet paged in)
    return PAGEIN_RETRY;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int MappedPageInHelper (LPFSMAP lpm, BOOL bWrite, DWORD addr)

⌨️ 快捷键说明

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