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

📄 volume.c

📁 Windows操作系统中文件系统过滤驱动和设备驱动之间的相似
💻 C
📖 第 1 页 / 共 5 页
字号:
        pstm->s_flags &= ~STF_VISITED;
        pstm = pstm->s_dlOpenStreams.pstmNext;
    }

  restart:
    pstm = pvol->v_dlOpenStreams.pstmNext;
    while (pstm != pstmEnd) {

        if (pstm->s_flags & STF_VISITED) {
            pstm = pstm->s_dlOpenStreams.pstmNext;
            continue;
        }

        pstm->s_flags |= STF_VISITED;

        // Add a ref to insure that the stream can't go away once we
        // let go of the volume's critical section.

        pstm->s_refs++;

        LeaveCriticalSection(&pvol->v_csStms);
        EnterCriticalSection(&pstm->s_cs);

        // Try to commit the stream before we unmount it, because we may
        // never be able to remount this stream again, and CommitStream
        // will refuse to commit a stream that's unmounted (and rightly so).

        CommitStream(pstm, TRUE);

        pfh = pstm->s_dlOpenHandles.pfhNext;
        pfhEnd = (PFHANDLE)&pstm->s_dlOpenHandles;

        if (pfh == pfhEnd) {

            if (pstm->s_refs == 2) {
                if (pstm == pvol->v_pstmFAT) {
                    pstm->s_refs--;
                    pvol->v_pstmFAT = NULL;
                }
                else if (pstm == pvol->v_pstmRoot) {
                    pstm->s_refs--;
                    pvol->v_pstmRoot = NULL;
                }
            }
        }
        else {

            // An open handle exists, but free the volume anyway since 
            // this is most likely due to removing removable media

            // Note that we print # of refs less 1, because one of the
            // refs is temporary (ie, it has been added by this function).

            DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!CloseVolume: stream %.11hs still open (%d refs)\r\n"), pstm->s_achOEM, pstm->s_refs-1));

            // Since a stream's current buffer should be neither manipulated
            // nor held after the release of its critical section, and since we
            // own that critical section now, assert that the current buffer
            // is no longer held;  this means that the current buffer pointer
            // serves only as a "cache hint" now, and since we are about to call
            // FreeBufferPool, we need to invalidate that hint now, too.

            ASSERT(!(pstm->s_flags & STF_BUFCURHELD));
            pstm->s_pbufCur = NULL;

            while (pfh != pfhEnd) {
                pfh->fh_flags |= FHF_UNMOUNTED;
                pfh = pfh->fh_dlOpenHandles.pfhNext;
            }
        }

        pstm->s_flags |= STF_UNMOUNTED;

        CloseStream(pstm);
        EnterCriticalSection(&pvol->v_csStms);
        goto restart;
    }

    LeaveCriticalSection(&pvol->v_csStms);

    // Free any other memory associated with the volume.  The only
    // memory remaining (if ANY) should be the VOLUME structure and one
    // or more open streams hanging off it.  Also, before the registered name
    // of the volume goes away, save a copy if the caller wants it (like for
    // error reporting or something....)  We start at "+1" to avoid copying
    // the leading backslash.

    if (pwsVolName) {
        *pwsVolName = '\0';
        if (pvol->v_pwsHostRoot)
            wcscpy(pwsVolName, pvol->v_pwsHostRoot+1);
    }

    if (!(pvol->v_flags & VOLF_FORMATTING) && !(pvol->v_flags & VOLF_SCANNING))
        DeregisterVolume(pvol);

    if (!FreeBufferPool(pvol))
        fSuccess = FALSE;

    BufDeinit (pvol);

    if (pvol->v_pFreeClusterList) {
        HeapFree(hHeap, 0, pvol->v_pFreeClusterList);
    }

#ifdef TFAT
    if (pvol->v_fTfat) {
        // Free diry sector bit array
        if(pvol->v_DirtySectorsInFAT.lpBits)
        {
            HeapFree(hHeap, 0, pvol->v_DirtySectorsInFAT.lpBits);
            pvol->v_DirtySectorsInFAT.lpBits = NULL;
        }

        if(pvol->v_ClusBuf)
        {
            HeapFree(hHeap, 0, pvol->v_ClusBuf);
            pvol->v_ClusBuf = NULL;
        }

        if (pvol->v_pFrozenClusterList)
        {
            VirtualFree (pvol->v_pFrozenClusterList, 0, MEM_RELEASE);
            pvol->v_pFrozenClusterList = NULL;
        }

        if (pvol->v_pFATBuffer)
        {
            HeapFree (hHeap, 0 , pvol->v_pFATBuffer);
            pvol->v_pFATBuffer = NULL;
        }

        if (pvol->v_pBootSec)
        {
            HeapFree (hHeap, 0, pvol->v_pBootSec);
            pvol->v_pBootSec = NULL;
        }
        
    }
#endif    

    if (pvol->v_FATCacheId != INVALID_CACHE_ID)
        FSDMGR_DeleteCache (pvol->v_FATCacheId);
    
    if (pvol->v_DataCacheId != INVALID_CACHE_ID)
        FSDMGR_DeleteCache (pvol->v_DataCacheId);
    
    if (fSuccess) {

        // If we already tried once to close this volume and failed,
        // leave it allocated but frozen until the volume is remounted
        // or recycled, lest we mess up volume bookkeeping in
        // external components.  

        fSuccess =  !(pvol->v_flags & (VOLF_FROZEN | VOLF_RETAIN));

        if (fSuccess) {
#ifdef PATH_CACHING
            DEBUGFREE(DEBUGALLOC_CS);
            DeleteCriticalSection(&pvol->v_csCaches);
#endif
            DEBUGFREE(DEBUGALLOC_CS);
            DeleteCriticalSection(&pvol->v_csStms);
            DEBUGFREE(DEBUGALLOC_CS);
            LeaveCriticalSection(&pvol->v_cs);  // DeleteCriticalSection is picky about this...
            DeleteCriticalSection(&pvol->v_cs);
            DEBUGFREE(sizeof(VOLUME));
            VERIFYTRUE(HeapFree(hHeap, 0, (HLOCAL)pvol));
        }
        else {
            DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!CloseVolume: retaining volume 0x%08x (%s)\r\n"), pvol, pvol->v_flags & VOLF_FROZEN? TEXTW("previously frozen") : TEXTW("following power cycle")));
            if (!(pvol->v_flags & VOLF_FROZEN)) {
                pvol->v_bMediaDesc = MAX_VOLUMES;
                pvol->v_flags |= VOLF_FROZEN;
            }
        }
    }
    else {
        DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!CloseVolume: retaining volume 0x%08x (open files add/or dirty buffers)\r\n"), pvol));
        if (!(pvol->v_flags & VOLF_FROZEN)) {
            pvol->v_bMediaDesc = MAX_VOLUMES;   // overload bMediaDesc as a recycle skip count
            pvol->v_flags |= VOLF_FROZEN;
        }
    }
    DEBUGMSG(ZONE_APIS,(DBGTEXT("FATFS!CloseVolume returned 0x%x\r\n"), fSuccess));
    return fSuccess;
}


/*  QueryVolumeParameters - Query volume parameters
 *
 *  ENTRY
 *      pvol - pointer VOLUME structure
 *      pdevpb - pointer to DOS-style device parameter block
 *      fVolume - TRUE to return volume info, FALSE for device info
 *
 *  EXIT
 *      ERROR_SUCCESS if successful, error code if not
 */

void QueryVolumeParameters(PVOLUME pvol, PDEVPB pdevpb, BOOL fVolume)
{
    // Caller wants a DEVPB.  Give him a close approximation of one.

    memset(pdevpb, 0, sizeof(DEVPB));

#ifdef OLD_CODE
    // In order to allow invalid volumes inside valid partitions
    // to be reformatted, I'm going to leave fVolume alone now. -JTP

    if (pvol->v_flags & VOLF_INVALID)
        fVolume = FALSE;
#endif

    // We'll use this bMediaType field to tell the caller what
    // kind of disk this volume resides on.  Callers that want to
    // reformat volumes need to know that.

    if (pvol->v_pdsk->d_diActive.di_flags & DISK_INFO_FLAG_MBR) {
        pdevpb->DevPrm.OldDevPB.bMediaType = MEDIA_HD;
    }

    pdevpb->DevPrm.OldDevPB.BPB.BPB_BytesPerSector = (WORD)(pvol->v_pdsk->d_diActive.di_bytes_per_sect);

    if (fVolume) {
        pdevpb->DevPrm.OldDevPB.BPB.BPB_SectorsPerCluster   = (BYTE)(1 << (pvol->v_log2cblkClus - pvol->v_log2cblkSec));
        pdevpb->DevPrm.OldDevPB.BPB.BPB_HiddenSectors       = pvol->v_secVolBias;
        pdevpb->DevPrm.OldDevPB.BPB.BPB_ReservedSectors     = (WORD)(pvol->v_secBlkBias - pvol->v_secVolBias);
        if (pvol->v_csecFAT)
            pdevpb->DevPrm.OldDevPB.BPB.BPB_NumberOfFATs    = (BYTE)(pvol->v_secEndAllFATs / pvol->v_csecFAT);
        if (pvol->v_pstmRoot)
            pdevpb->DevPrm.OldDevPB.BPB.BPB_RootEntries     = (WORD)(pvol->v_pstmRoot->s_size / sizeof(DIRENTRY));
        pdevpb->DevPrm.OldDevPB.BPB.BPB_MediaDescriptor     = pvol->v_bMediaDesc;
        pdevpb->DevPrm.OldDevPB.BPB.BPB_SectorsPerFAT       = (WORD)pvol->v_csecFAT;
    }

    pdevpb->DevPrm.OldDevPB.BPB.BPB_SectorsPerTrack = (WORD)pvol->v_pdsk->d_diActive.di_sectors;
    pdevpb->DevPrm.OldDevPB.BPB.BPB_Heads = (WORD)pvol->v_pdsk->d_diActive.di_heads;
    pdevpb->DevPrm.OldDevPB.BPB.BPB_BigTotalSectors = fVolume? pvol->v_csecTotal + pdevpb->DevPrm.OldDevPB.BPB.BPB_ReservedSectors : pvol->v_pdsk->d_diActive.di_total_sectors;
}


/*  RegisterVolume - Register VOLUME in file system
 *
 *  ENTRY
 *      pvol -> VOLUME
 *
 *  EXIT
 *      TRUE if volume successfully registered, FALSE if not
 */

WCHAR awcFolder[] = TEXTW("Mounted Volume");

BOOL RegisterVolume(PVOLUME pvol)
{
    WCHAR szName[MAX_PATH];
    DWORD dwAvail;
    BOOL fSuccess = FALSE;
    DWORD dwValue;

    wcscpy( szName, L"");
    if (FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"MountLabel", &dwValue) && (dwValue == 1)) {
        FSDMGR_GetDiskName( (HDSK)pvol->v_pdsk->d_hdsk, szName);
    } 
    if (wcslen(szName) == 0) {
        if (!FSDMGR_DiskIoControl((HDSK)pvol->v_pdsk->d_hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL)) { 
            wcscpy( szName, awcFolder);
        }
    }    
    
    if (pvol->v_hVol = FSDMGR_RegisterVolume((HDSK)pvol->v_pdsk->d_hdsk, szName, (DWORD)pvol)) {
        pvol->v_volID = 1;
        if (!pvol->v_pwsHostRoot) {
            pvol->v_pwsHostRoot = (PWSTR)HeapAlloc(hHeap, 0, MAX_PATH * sizeof(WCHAR));
        }    
        if (pvol->v_pwsHostRoot) {
            FSDMGR_GetVolumeName(pvol->v_hVol, pvol->v_pwsHostRoot, MAX_PATH);
            pvol->v_cwsHostRoot = wcslen(pvol->v_pwsHostRoot);
        } else {
            pvol->v_cwsHostRoot = 0;
        }    
        fSuccess = TRUE;
    }    
    return fSuccess;
}


/*  DeregisterVolume - Deregister VOLUME in file system
 *
 *  ENTRY
 *      pvol -> VOLUME
 *
 *  EXIT
 *      None
 */

void DeregisterVolume(PVOLUME pvol)
{
    if (pvol->v_hVol && (pvol->v_volID != INVALID_AFS)) {
        FSDMGR_DeregisterVolume(pvol->v_hVol);
        pvol->v_hVol = 0;
        pvol->v_volID = INVALID_AFS;
    }    
    if (pvol->v_pwsHostRoot) {
        FSDMGR_AdvertiseInterface( &FATFS_MOUNT_GUID, pvol->v_pwsHostRoot, FALSE);
        HeapFree(hHeap, 0,  pvol->v_pwsHostRoot);
        pvol->v_pwsHostRoot = NULL;
    }
}

/*  MountVolume - Mount volume on specified disk
 *
 *  ENTRY
 *      pdsk -> DSK structure for disk
 *      pbSector -> BIGFATBOOTSEC structure (from disk)
 *      flVol == initial volume flags (currently, only VOLF_READONLY is copied)
 *
 *  EXIT
 *      Pointer to VOLUME structure, NULL if error (eg, out of memory,
 *      disk error, etc)
 */

PVOLUME MountVolume(PDSK pdsk, PBIGFATBOOTSEC *ppbgbs, DWORD flVol)
{
    PVOLUME pvol;

    ASSERT(OWNCRITICALSECTION(&csFATFS));

    if (pvol = OpenVolume(pdsk, ppbgbs, NULL)) {

        pvol->v_flags &= ~VOLF_READONLY;
        pvol->v_flags |= (flVol & VOLF_READONLY);

        // If this is a remounted volume, refresh as many of its open handles
        // as possible.  We do this even for INVALID volumes, because there
        // may still be VOLUME-based handles, which can always be refreshed.
        // Also, this has to be deferred until after AllocBufferPool, because we
        // can't verify what state the streams are in without buffers to work with.

        RefreshVolume(pvol);

        // We must not be holding the VOLUME's critical section around the FILESYS
        // calls made by RegisterVolume, because those calls take FILESYS' critical
        // section, and if another FILESYS thread issues a power-off notification
        // at the wrong time (whialso holds FILESYS's critical section),
        // our notification function (FAT_Notify) will hang attempting to take
        // the VOLUME's critical section in order to enumerate all the file handles
        // and flush them.

        // Since we're still holding onto csFATFS, and we haven't cleared the
        // volume's UNMOUNTED bit yet, it should be OK to let go of the VOLUME's
        // critical section now.

        LeaveCri

⌨️ 快捷键说明

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