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

📄 fsdapis.cpp

📁 WinCE5.0部分核心源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++


Module Name:

    fsdapis.cpp

Abstract:

    This file contains the FSDMGR entry points for all supported file
    system APIs.

--*/

#define KEEP_SYSCALLS           // for kernel.h only
#define NO_DEFINE_KCALL         // for kernel.h only

#include "fsdmgrp.h"
#include "fsnotify.h"
#include "storemain.h"
#include "cdioctl.h"

#ifdef UNDER_CE
#include "fsioctl.h"
#endif

inline BOOL IsValidVolume(PVOL pVol) 
{
    PREFAST_ASSERT(OWNCRITICALSECTION(&csFSD));
    
    // walk the global vol list to verify pVol has not been deregistered
    PVOL pVolNext = dlVOLList.pVolNext;
    while (pVolNext != (PVOL)&dlVOLList) {
        if (pVol == pVolNext) {
            return TRUE;
        }
        pVolNext = pVolNext->dlVol.pVolNext;
    }
    return FALSE;
}


void inline MarkVolume( PVOL pVol, DWORD dwFlags) 
{
    LockFSDMgr();
    __try {
        if (IsValidVolume(pVol)) {
            pVol->dwFlags  |= dwFlags;
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        ASSERT(0);
    }
    UnlockFSDMgr();
}    


void inline UnmarkVolume( PVOL pVol, DWORD dwFlags) 
{
    LockFSDMgr();
    __try {
        if (IsValidVolume(pVol)) {
            pVol->dwFlags  &= ~dwFlags;
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        ASSERT(0);
    }
    UnlockFSDMgr();
}    

void inline WaitForVolume(PVOL pVol)
{
    DWORD dwDelay = 0;
    extern DWORD g_dwWaitIODelay;    
    
    LockFSDMgr();
    __try {
        if (IsValidVolume(pVol) && !(VOL_DEINIT & pVol->dwFlags)) {
            ASSERT(VALIDSIG(pVol, VOL_SIG));
            // if the volume is currently unavailable, stall
            if (VOL_UNAVAILABLE & pVol->dwFlags) {
                dwDelay = g_dwWaitIODelay;
                DEBUGMSG(ZONE_POWER, (TEXT("FSDMGR!WaitForVolume: blocking file i/o for %u ms on unavailable volume %s\r\n"), dwDelay, pVol->wsVol));
            }
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        ASSERT(0);
    }
    UnlockFSDMgr();
    
    if (dwDelay) {
        // stall in case the device could come back online
        Sleep(dwDelay);
    }   
}

void inline WaitForHandle(PHDL pHdl)
{
    DWORD dwDelay = 0;
    extern DWORD g_dwWaitIODelay;    
    
    LockFSDMgr();
    __try {
        if (!(pHdl->dwFlags & HDL_INVALID) && pHdl->pVol) {
            ASSERT(VALIDSIG(pHdl->pVol, VOL_SIG));
            // if the volume is currently unavailable, stall
            if (VOL_UNAVAILABLE & pHdl->pVol->dwFlags) {
                dwDelay = g_dwWaitIODelay;
                DEBUGMSG(ZONE_POWER, (TEXT("FSDMGR!WaitForHandle: blocking file i/o for %u ms on unavailable volume %s\r\n"), dwDelay, pHdl->pVol->wsVol));
            }
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        ASSERT(0);
    }
    UnlockFSDMgr();
    
    if (dwDelay) {
        // stall in case the device could come back online
        Sleep(dwDelay);
    }   
}

/*  TryEnterVolume - Tracks threads entering an FSD volume API
 *
 *  ENTRY
 *      pVol -> VOL structure
 *
 *  EXIT
 *      Returns TRUE if the volume can be entered, FALSE if the volume
 *      is not available.
 *
 *  NOTES
 *      We track threads on a per-volume basis so that we will block
 *      volume deinitialization until all threads have stopped accessing
 *      the volume.
 */

BOOL TryEnterVolume(PVOL pVol)
{
    BOOL bRet = FALSE;
    HANDLE hActivityEvent = NULL;
    LockFSDMgr();
    __try {
        // check to see that the volume is available
        if (IsValidVolume(pVol) && 
            !(pVol->dwFlags & VOL_UNAVAILABLE) &&
            !(pVol->dwFlags & VOL_DEINIT)) {
            
            ASSERT(VALIDSIG(pVol, VOL_SIG));
            hActivityEvent = pVol->pDsk->hActivityEvent;

            // indicate that a new thread has entered the volume
            pVol->cThreads++;
            bRet = TRUE;
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        ASSERT(0);
    }
    UnlockFSDMgr();
    
    if (hActivityEvent) {
        // Set the Activity timer every time a volume is entered 
        // so that Power Manager will know this device is being used
        SetEvent(hActivityEvent);
    }

    if (!bRet) {
        // Indicate to the caller that the device is not available
        SetLastError(ERROR_DEVICE_NOT_AVAILABLE);
    }    
    
    return bRet;
}    

/*  TryEnterHandle - Tracks threads entering an FSD handle API
 *
 *  ENTRY
 *      pHdl -> PHDL structure
 *
 *  EXIT
 *      Returns TRUE if the volume can be entered and the handle is
 *      valid, FALSE if the volume is not available.
 *
 *  NOTES
 *      We track threads on a per-volume basis so that we will block
 *      volume deinitialization until all threads have stopped accessing
 *      the volume.
 */

BOOL TryEnterHandle(PHDL pHdl)
{
    BOOL bRet = FALSE;
    HANDLE hActivityEvent = NULL;

    LockFSDMgr();
    __try {
        // check to see that the handle is valid and the volume is available
        if (!(pHdl->dwFlags & HDL_INVALID) 
            // we don't need to call IsValidVolume here because it will have 
            // been set to NULL (and the handle will have been flagged INVALID)
            // during cleanup if the volume went away
            && pHdl->pVol
            && !(pHdl->pVol->dwFlags & VOL_UNAVAILABLE)
            && !(pHdl->pVol->dwFlags & VOL_DEINIT)) {
            
            ASSERT(VALIDSIG(pHdl->pVol, VOL_SIG));
            hActivityEvent = pHdl->pVol->pDsk->hActivityEvent;

            // indicate that a new thread has entered the volume
            pHdl->pVol->cThreads++;
            bRet = TRUE;
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        ASSERT(0);
    }
    UnlockFSDMgr();
    
    if (bRet && hActivityEvent) {
        // set the Activity timer every time a volume is entered 
        // so that Power Manager will know this device is being used
        SetEvent(hActivityEvent);
    }
    
    if (!bRet) {
        // Indicate to the caller that the device is not available
        SetLastError(ERROR_DEVICE_NOT_AVAILABLE);
    }
    
    return bRet;
}    


/*  ExitVolume - Tracks threads leaving an FSD (and can signal when the last one leaves)
 *
 *  ENTRY
 *      pVol -> VOL structure
 *
 *  EXIT
 *      None
 *
 *  NOTES
 *      See TryEnterVolume for notes.
 */

void ExitVolume(PVOL pVol)
{
    ASSERT(VALIDSIG(pVol, VOL_SIG));

    LockFSDMgr();
    __try {
        pVol->cThreads--;

        if ((VOL_DEINIT & pVol->dwFlags) && (pVol->cThreads == 0)) {
            // this is the last thread leaving a de-allocated volume, so signal 
            // the final thread exit event so that volume cleanup will complete
            ASSERT(pVol->hThreadExitEvent != NULL);
            SetEvent(pVol->hThreadExitEvent);
        } 
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        ASSERT(0);
    }
    UnlockFSDMgr();
}

/*  ExitHandle - Tracks threads leaving an FSD handle call
 *
 *  ENTRY
 *      pHdl -> PHDL structure
 *
 *  EXIT
 *      None
 *
 *  NOTES
 *      See TryEnterHandle for notes.
 */

inline void ExitHandle(PHDL pHdl)
{
    // just exit the volume, there is no special exit code for handles
    return ExitVolume(pHdl->pVol);
}


#ifdef UNDER_CE
BOOL MapSgBuffers(PSG_REQ pSgReq ,DWORD InBufLen)
{
    if  (pSgReq && InBufLen >= (sizeof(SG_REQ) + sizeof(SG_BUF) * (pSgReq->sr_num_sg - 1))) {
        DWORD dwIndex;
        for (dwIndex=0; dwIndex < pSgReq -> sr_num_sg; dwIndex++) {
            pSgReq->sr_sglist[dwIndex].sb_buf = 
                (PUCHAR)MapCallerPtr((LPVOID)pSgReq->sr_sglist[dwIndex].sb_buf,pSgReq->sr_sglist[dwIndex].sb_len);
        }
    }
    else // Parameter Wrong.
        return FALSE;
    
    return TRUE;
}
BOOL MapSgBuffers(PCDROM_READ pCdrom ,DWORD InBufLen)
{
    if  (pCdrom && InBufLen >= (sizeof(CDROM_READ) + sizeof(SGX_BUF) * (pCdrom->sgcount - 1))) {
        DWORD dwIndex;
        for (dwIndex=0; dwIndex < pCdrom-> sgcount; dwIndex++) {
            pCdrom->sglist[dwIndex].sb_buf = 
                (PUCHAR)MapCallerPtr((LPVOID)pCdrom->sglist[dwIndex].sb_buf,pCdrom->sglist[dwIndex].sb_len);
        }
    }
    else // Parameter Wrong.
        return FALSE;
    return TRUE;
}
#else
// NT stub
BOOL MapSgBuffers(PSG_REQ pSgReq ,DWORD InBufLen)
{
    return TRUE;
}

// NT stub
BOOL MapSgBuffers(PCDROM_READ pCdrom ,DWORD InBufLen)
{
    return TRUE;
}
#endif // UNDER_CE

BOOL ReadWriteFileSg (DWORD dwIoControlCode, PHDL pHdl, FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytes, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
{
    PFSD pFSD = pHdl->pVol->pDsk->pFSD;
    BOOL bRet = FALSE;
    
    if (!aSegmentArray) {
        SetLastError (ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    if ((dwIoControlCode == IOCTL_FILE_READ_SCATTER && !pFSD->pReadFileScatter) || 
        (dwIoControlCode == IOCTL_FILE_WRITE_GATHER && !pFSD->pWriteFileGather))
    {
        SetLastError(ERROR_NOT_SUPPORTED);
        return FALSE;
    }
    
    SYSTEM_INFO SystemInfo;
    GetSystemInfo (&SystemInfo);
    DWORD dwNumPages = nNumberOfBytes / SystemInfo.dwPageSize;

#ifdef UNDER_CE
    aSegmentArray = (FILE_SEGMENT_ELEMENT*)MapCallerPtr (aSegmentArray, SystemInfo.dwPageSize);

    if (aSegmentArray) {
        for (DWORD i = 0; i < dwNumPages; i++) {
            aSegmentArray[i].Buffer = MapCallerPtr (aSegmentArray[i].Buffer, SystemInfo.dwPageSize);
        }
    }
    lpReserved = (LPDWORD)MapCallerPtr (lpReserved, SystemInfo.dwPageSize);
#endif

    if (dwIoControlCode == IOCTL_FILE_READ_SCATTER) {
        __try {
            bRet = pFSD->pReadFileScatter(pHdl->dwHdlData, aSegmentArray, nNumberOfBytes, lpReserved, lpOverlapped);
        } __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
            bRet = FALSE;
        }
    } else {
        __try {
            bRet = pFSD->pWriteFileGather(pHdl->dwHdlData, aSegmentArray, nNumberOfBytes, lpReserved, lpOverlapped);
        } __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
            bRet = FALSE;
        }
    }  
    return bRet;
}

/*  FSDMGR_CloseVolume - Called when a volume is being deregistered
 *
 *  ENTRY
 *      pVol -> VOL structure
 *
 *  EXIT
 *      Always returns TRUE (that's what OUR stub always does, and it's
 *      expected that that's what FSDs will do too, if they even care to hook
 *      this entry point).
 */
BOOL FSDMGR_CloseVolume(PVOL pVol)
{
    // FSD_CloseVolume export is called from DeinitEx()
    return TRUE;
}


/*  FSDMGR_CreateDirectoryW - Create a new subdirectory

⌨️ 快捷键说明

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