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

📄 fsdserv.cpp

📁 WinCE5.0部分核心源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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:

    fsdserv.cpp

Abstract:

    This file contains the FSDMGR services provided to other FSDs.

--*/

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

#ifdef UNDER_CE
#include <windev.h>
#endif

#include <strsafe.h>

HANDLE g_hRootNotifyHandle = NULL; // Notification handle for the volume that has been mounted as ROOT "\"


/*  FSDMGR_GetDiskInfo - Called by an FSD to query disk info
 *
 *  ENTRY
 *      pDsk -> DSK passed to FSD_MountDisk
 *      pfdi -> FSD_DISK_INFO structure to be filled in
 *
 *  EXIT
 *      ERROR_SUCCESS if structure successfully filled in, or an error code.
 */

DWORD FSDMGR_GetDiskInfo(PDSK pDsk, FSD_DISK_INFO *pfdi)
{
    DWORD cb;

    PREFAST_ASSERT(
        VALIDSIG(pDsk, DSK_SIG) &&
        offsetof(FSD_DISK_INFO, cSectors)           == offsetof(DISK_INFO, di_total_sectors) &&
        offsetof(FSD_DISK_INFO, cbSector)           == offsetof(DISK_INFO, di_bytes_per_sect) &&
        offsetof(FSD_DISK_INFO, cCylinders)         == offsetof(DISK_INFO, di_cylinders) &&
        offsetof(FSD_DISK_INFO, cHeadsPerCylinder)  == offsetof(DISK_INFO, di_heads) &&
        offsetof(FSD_DISK_INFO, cSectorsPerTrack)   == offsetof(DISK_INFO, di_sectors) &&
        offsetof(FSD_DISK_INFO, dwFlags)            == offsetof(DISK_INFO, di_flags)
    );

    // Return cached information whenever possible

    if (pfdi != &pDsk->fdi && pDsk->fdi.cbSector != 0) {
        *pfdi = pDsk->fdi;
        return ERROR_SUCCESS;
    }
    
    if (FSDMGR_DiskIoControl(pDsk,
                        IOCTL_DISK_GETINFO,
                        NULL, 0,
                        pfdi, sizeof(*pfdi),
                        &cb, NULL)) {
        pDsk->dwFlags |= DSK_NEW_IOCTLS;
    }
    else
    if (FSDMGR_DiskIoControl(pDsk,
                        DISK_IOCTL_GETINFO,
                        pfdi, sizeof(*pfdi),
                        NULL, 0,
                        &cb, NULL)) {
        ASSERT(!(pDsk->dwFlags & DSK_NEW_IOCTLS));
    }
    else
    if (FSDMGR_DiskIoControl(pDsk,
                        IOCTL_DISK_GETINFO,
                        pfdi, sizeof(*pfdi),
                        NULL, 0,
                        &cb, NULL)) {
        pDsk->dwFlags |= DSK_NEW_IOCTLS;
    }
    else {
        DWORD status = GetLastError();
        DEBUGMSG(ZONE_ERRORS, (DBGTEXT("FSDMGR_GetDiskInfo: DISK_IOCTL_GETINFO failed (%d)\n"), status));
        pDsk->dwFlags |= DSK_NO_IOCTLS;
        return status;
    }

    DEBUGMSG(ZONE_DISKIO, (DBGTEXT("FSDMGR_GetDiskInfo: DISK_IOCTL_GETINFO returned %d bytes\n"), cb));

    DEBUGMSG(ZONE_DISKIO, (DBGTEXT("FSDMGR_GetDiskInfo: %d sectors, BPS=%d, CHS=%d:%d:%d\n"),
              pfdi->cSectors, pfdi->cSectors, pfdi->cbSector, pfdi->cCylinders, pfdi->cHeadsPerCylinder, pfdi->cSectorsPerTrack));

    DEBUGMSG(pfdi->dwFlags & ~(FDI_MBR | FDI_CHS_UNCERTAIN | FDI_UNFORMATTED | FDI_PAGEABLE), (DBGTEXT("FSDMGR_GetDiskInfo: DISK_IOCTL_GETINFO returned unknown flags (0x%08x)\n"), pfdi->dwFlags));

    pfdi->dwFlags &= (FDI_MBR | FDI_CHS_UNCERTAIN | FDI_UNFORMATTED | FDI_PAGEABLE);

    if (pDsk->dwFlags & DSK_READONLY)
        pfdi->dwFlags |= FDI_READONLY;

    return ERROR_SUCCESS;
}


/* process an I/O operation using ReadFile() or WriteFile() */
static DWORD PlainReadWrite(FSD_SCATTER_GATHER_INFO *sgi,
                            FSD_SCATTER_GATHER_RESULTS *sgr,
                            DWORD ioctl)
{
DWORD numBytes;
DWORD i;
PDSK  pDsk;
BOOL  ok;

    pDsk = (PDSK)sgi->idDsk;

    if (SetFilePointer(pDsk->hDsk, sgi->dwSector * pDsk->fdi.cbSector, NULL, FILE_BEGIN) == 0xFFFFFFFF)
        return GetLastError();

    for (i = 0; i < sgi->cfbi; i++)
    {
        if (ioctl == DISK_IOCTL_READ)
            ok = ReadFile(pDsk->hDsk, sgi->pfbi[i].pBuffer, sgi->pfbi[i].cbBuffer, &numBytes, NULL);
        else
            ok = WriteFile(pDsk->hDsk, sgi->pfbi[i].pBuffer, sgi->pfbi[i].cbBuffer, &numBytes, NULL);

        if (!ok)
            return GetLastError();

        if (numBytes != sgi->pfbi[i].cbBuffer)
            return ERROR_GEN_FAILURE;
    }

    return ERROR_SUCCESS;
}


/*  ReadWriteDiskEx - Read/write sectors from/to a disk to/from discontiguous buffers
 *
 *  ENTRY
 *      pfsgi -> FSD_SCATTER_GATHER_INFO
 *      pfsgr -> FSD_SCATTER_GATHER_RESULTS
 *      ioctl -> I/O op to perform
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, or an error code
 */

static DWORD ReadWriteDiskEx(FSD_SCATTER_GATHER_INFO *sgi,
                             FSD_SCATTER_GATHER_RESULTS *sgr,
                             DWORD ioctl)
{
    SG_REQ *psgreq = NULL;
    PDSK    pDsk;
    DWORD   result;
    DWORD   i;
    DWORD   dummy;

    pDsk = (PDSK)sgi->idDsk;
    PREFAST_ASSERT(VALIDSIG(pDsk, DSK_SIG) && pDsk->hDsk);

    // make sure the caller is not passing inappropriate flags
    if (sgi->dwFlags)
        return ERROR_INVALID_PARAMETER;

    //DEBUGMSGW(ZONE_DISKIO,(DBGTEXTW("ReadWriteDiskEd: %s sector %d (0x%08x), total %d)\n"), cmd == DISK_IOCTL_READ? TEXTW("READ") : TEXTW("WRITE"), dwSector, dwSector, cSectors));

    if (pDsk->hDsk == INVALID_HANDLE_VALUE)
    {
        DEBUGMSGW(ZONE_ERRORS,(DBGTEXTW("ReadWriteDiskEx: %s not open, returning error %d\n"), pDsk->wsDsk, ERROR_BAD_DEVICE));
        return ERROR_BAD_DEVICE;
    }

    if (pDsk->dwFlags & DSK_NO_IOCTLS)
    {
        result = PlainReadWrite(sgi, sgr, ioctl);
    }
    else
    {
        if (pDsk->dwFlags & DSK_NEW_IOCTLS)
        {
            if (ioctl == DISK_IOCTL_READ)
                ioctl = IOCTL_DISK_READ;
            else if (ioctl == DISK_IOCTL_WRITE)
                ioctl = IOCTL_DISK_WRITE;
        }

        psgreq              = (PSG_REQ)LocalAlloc(LPTR, (sizeof(SG_REQ) + sgi->cfbi * sizeof(SG_BUF) - sizeof(SG_BUF)));
        if (!psgreq) {
            return ERROR_OUTOFMEMORY;
        }
        psgreq->sr_start    = sgi->dwSector;
        psgreq->sr_num_sec  = sgi->cSectors;
        psgreq->sr_num_sg   = sgi->cfbi;
        psgreq->sr_status   = 0;
        psgreq->sr_callback = NULL;

        for (i = 0; i < sgi->cfbi; i++)
        {
            psgreq->sr_sglist[i].sb_buf = sgi->pfbi[i].pBuffer;
            psgreq->sr_sglist[i].sb_len = sgi->pfbi[i].cbBuffer;
        }
        
        if (!FSDMGR_DiskIoControl(pDsk, ioctl, psgreq, sizeof(SG_REQ) + sgi->cfbi * sizeof(SG_BUF) - sizeof(SG_BUF), NULL, 0, &dummy, NULL))
            result = GetLastError();
        else
            result = ERROR_SUCCESS;
        LocalFree( psgreq);
    }

    if (sgr)
    {
        sgr->dwFlags = 0;

        if (result == ERROR_SUCCESS)
            sgr->cSectorsTransferred = sgi->cSectors;
        else
            sgr->cSectorsTransferred = 0;
    }

    return result;
}


/*  FSDMGR_ReadDisk - Called by an FSD to read sector(s) from a disk
 *
 *  ENTRY
 *      pDsk -> DSK passed to FSD_MountDisk
 *      dwsector == starting sector #
 *      cSectors == number of sectors to read
 *      pBuffer -> buffer to read sectors into
 *      cbBuffer == size of buffer, in bytes
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, or an error code
 */

DWORD FSDMGR_ReadDisk(PDSK pDsk, DWORD dwSector, DWORD cSectors, PBYTE pBuffer, DWORD cbBuffer)
{
FSD_BUFFER_INFO         bi;
FSD_SCATTER_GATHER_INFO sgi;

    bi.pBuffer      = pBuffer;
    bi.cbBuffer     = cbBuffer;

    sgi.dwFlags     = 0;
    sgi.idDsk       = (DWORD)pDsk;
    sgi.dwSector    = dwSector;
    sgi.cSectors    = cSectors;
    sgi.pfdi        = NULL;
    sgi.cfbi        = 1;
    sgi.pfbi        = &bi;
    sgi.pfnCallBack = NULL;

    return ReadWriteDiskEx(&sgi, NULL, DISK_IOCTL_READ);
}


/*  FSDMGR_WriteDisk - Called by an FSD to write sector(s) to a disk
 *
 *  ENTRY
 *      pDsk -> DSK passed to FSD_MountDisk
 *      dwsector == starting sector #
 *      cSectors == number of sectors to write
 *      pBuffer -> buffer to write sectors from
 *      cbBuffer == size of buffer, in bytes
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, or an error code
 */

DWORD FSDMGR_WriteDisk(PDSK pDsk, DWORD dwSector, DWORD cSectors, PBYTE pBuffer, DWORD cbBuffer)
{
FSD_BUFFER_INFO         bi;
FSD_SCATTER_GATHER_INFO sgi;

    bi.pBuffer      = pBuffer;
    bi.cbBuffer     = cbBuffer;

    sgi.dwFlags     = 0;
    sgi.idDsk       = (DWORD)pDsk;
    sgi.dwSector    = dwSector;
    sgi.cSectors    = cSectors;
    sgi.pfdi        = NULL;
    sgi.cfbi        = 1;
    sgi.pfbi        = &bi;
    sgi.pfnCallBack = NULL;

    return ReadWriteDiskEx(&sgi, NULL, DISK_IOCTL_WRITE);
}


/*  FSDMGR_ReadDiskEx - Called by an FSD to read sectors from a disk into discontiguous buffers
 *
 *  ENTRY
 *      pfsgi -> FSD_SCATTER_GATHER_INFO
 *      pfsgr -> FSD_SCATTER_GATHER_RESULTS
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, or an error code
 */

DWORD FSDMGR_ReadDiskEx(FSD_SCATTER_GATHER_INFO *pfsgi, FSD_SCATTER_GATHER_RESULTS *pfsgr)
{
    return ReadWriteDiskEx(pfsgi, pfsgr, DISK_IOCTL_READ);
}


/*  FSDMGR_WriteDiskEx - Called by an FSD to write sectors to a disk from discontiguous buffers
 *
 *  ENTRY
 *      pfsgi -> FSD_SCATTER_GATHER_INFO
 *      pfsgr -> FSD_SCATTER_GATHER_RESULTS
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, or an error code
 */

DWORD FSDMGR_WriteDiskEx(FSD_SCATTER_GATHER_INFO *pfsgi, FSD_SCATTER_GATHER_RESULTS *pfsgr)
{
    return ReadWriteDiskEx(pfsgi, pfsgr, DISK_IOCTL_WRITE);
}


/*  FSDMGR_RegisterVolume - Called by an FSD to register a volume
 *
 *  ENTRY
 *      pDsk -> DSK passed to FSD_MountDisk
 *      pwsName -> desired volume name, NULL for default name (eg, "Storage Card")
 *      pVolume == FSD-defined volume-specific data
 *
 *  EXIT
 *      Volume identifier, NULL if none
 */

#ifdef UNDER_CE

PVOL FSDMGR_RegisterVolume(PDSK pDsk, PWSTR pwsName, PVOLUME pVolume)
{
    PVOL pVol;
    BOOL bSuccess = FALSE;

    PREFAST_ASSERT(VALIDSIG(pDsk, DSK_SIG));

    if (pDsk->pVol) {
        // the volume was previously registered; do not allow it to be 
        // registered a second time, just return the existing PVOL
        return pDsk->pVol;
    }

    LockFSDMgr();  
    
    pVol = AllocVolume(pDsk, (DWORD)pVolume);

    UnlockFSDMgr();

    if (pVol) {

        PFSD pFSD = pVol->pDsk->pFSD;

        if (pVol->iAFS == INVALID_AFS) {

            // Determine what AFS index to use.  We try to use OID_FIRST_AFS
            // first, because FILESYS.EXE pre-registers the name "Storage Card"
            // at that index (to prevent anyone from creating a folder or file
            // with that name).  However, if that fails, then we'll try to create
            // a unique derivation of whatever name FILESYS.EXE had reserved at
            // that index, register the new name, and use the resulting AFS index.

            
            int cch;
            int iAFS, iSuffix = 1;
            WCHAR wsAFS[128];

            cch = GetAFSName(OID_FIRST_AFS, wsAFS, ARRAY_SIZE(wsAFS));

            if ((pwsName == NULL) && cch) {

                // The FSD did not provide a name, and the default name is already in use,
                // so we should just try derivations of the default name.

                iSuffix = 2;
                pwsName = wsAFS;
            }

            if (((pwsName == NULL) || (wsAFS && (wcscmp(pwsName, wsAFS+1)==0))) && !cch){
                
                // The FSD did not provide a name, and the default name is NOT in use,
                // so we should be able to use the default name.

                if (RegisterAFSEx(OID_FIRST_AFS, hAFSAPI, (DWORD)pVol, AFS_VERSION, AFS_FROM_MOUNT_FLAGS(pDsk->dwFlags))) {
                    pVol->iAFS = OID_FIRST_AFS;
                    GetAFSName(pVol->iAFS, wsAFS, ARRAY_SIZE(wsAFS));
                    wcsncpy( pVol->wsVol, wsAFS, 63); // Size of wsVol = 63                    
                    pVol->wsVol[63] = 0;                    
                    LockFSDMgr();
                    pVol->hNotifyHandle = NotifyCreateVolume(wsAFS);
                    DEBUGMSGW(ZONE_EVENTS,(DBGTEXTW("FSDMGR_RegisterVolume: registered  volume as %s\n"), pVol->wsVol));
                    bSuccess = TRUE;
                    if (g_hRootNotifyHandle) {
                        NotifyPathChange(g_hRootNotifyHandle, pVol->wsVol, TRUE, FILE_ACTION_ADDED);
                    } else {
                        if (AFS_FROM_MOUNT_FLAGS(pDsk->dwFlags) & AFS_FLAG_ROOTFS) {
                            g_hRootNotifyHandle = pVol->hNotifyHandle;
                        }
                    }    
                    UnlockFSDMgr();
                }
            } 
            if (!bSuccess && pwsName) {

                // Either the FSD provided a name, or the default name is in use,
                // so we should try all the appropriate derivations.

                wcscpy(wsAFS, pwsName[0] == '\\'? pwsName+1 : pwsName);
                cch = wcslen(wsAFS);

                do {
                    if (iSuffix > 1) {
                        wsAFS[cch] = '0'+iSuffix;
                        wsAFS[cch+1] = 0;
                    }

                    

⌨️ 快捷键说明

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