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

📄 volume.c

📁 Windows操作系统中文件系统过滤驱动和设备驱动之间的相似
💻 C
📖 第 1 页 / 共 5 页
字号:
//对pdsk->pVol是否为null进行验证,如果为真,即未挂在分区,则分配并初始化相关的临界区变量
//条件为假则置flag为VOLF_REMOUNTED,表示某个分区被重新的mount
PVOLUME FindVolume(PDSK pdsk, PBIGFATBOOTSEC pbgbs)
{
    PBIGFATBPB pbpb = &pbgbs->bgbsBPB;
    PVOLUME pvol = pdsk->pVol;

    ASSERT(OWNCRITICALSECTION(&csFATFS));

    if (!pvol) {
        //为挂载任何分区
        pvol = (PVOLUME)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(VOLUME));

        if (pvol) {
            pvol->v_hVol = 0;
        }    

    } else {
        pvol->v_flags |= VOLF_REMOUNTED;
        return pvol;
    }
    if (!pvol)
        DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!FindVolume: out of memory!\r\n")));
    else {
        DEBUGALLOC(sizeof(VOLUME));

        InitializeCriticalSection(&pvol->v_cs);
        DEBUGALLOC(DEBUGALLOC_CS);
        InitializeCriticalSection(&pvol->v_csStms);
        DEBUGALLOC(DEBUGALLOC_CS);

#ifdef PATH_CACHING
        InitList((PDLINK)&pvol->v_dlCaches);
        InitializeCriticalSection(&pvol->v_csCaches);
        DEBUGALLOC(DEBUGALLOC_CS);
#endif
        InitList((PDLINK)&pvol->v_dlOpenStreams);
        pvol->v_pdsk = pdsk;
        pvol->v_volID = INVALID_AFS;
    }
    return pvol;
}


/*  TestVolume - Test a VOLUME's validity
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *      ppbgbs - pointer to address of PBR (partition boot record) for volume
 *
 *  EXIT
 *      ERROR_SUCCESS, else VOLUME's INVALID bit set if any errors encountered
 */

DWORD TestVolume(PVOLUME pvol, PBIGFATBOOTSEC *ppbgbs)
{
    DWORD cbSecOrig;
    DWORD dwError = ERROR_SUCCESS;
    PDSK pdsk = pvol->v_pdsk;
    PBIGFATBOOTSEC pbgbs = *ppbgbs;

    if (pvol->v_flags & VOLF_INVALID)
        return dwError;

    // Make sure other key BPB values are in sync with the driver (ie, sector
    // size), assuming driver info was provided.

    cbSecOrig = pdsk->d_diActive.di_bytes_per_sect;

    if (cbSecOrig != pbgbs->bgbsBPB.oldBPB.BPB_BytesPerSector) {

        DEBUGMSG(ZONE_INIT || ZONE_ERRORS,
                        (DBGTEXT("FATFS!TestVolume: forcing driver sector size (%d) to match BPB (%d)\r\n"),
                         cbSecOrig, pbgbs->bgbsBPB.oldBPB.BPB_BytesPerSector));

        pdsk->d_diActive.di_bytes_per_sect = pbgbs->bgbsBPB.oldBPB.BPB_BytesPerSector;

        if (SetDiskInfo(pdsk->d_hdsk, &pdsk->d_diActive) == ERROR_SUCCESS) {

            pvol->v_flags |= VOLF_MODDISKINFO;

            if (pdsk->d_diActive.di_bytes_per_sect > cbSecOrig) {
                PVOID pTemp;
                pTemp = LocalReAlloc((HLOCAL)pbgbs, pdsk->d_diActive.di_bytes_per_sect, LMEM_MOVEABLE);
                if (pTemp) {
                    pbgbs = pTemp;
                } else {
                    DEBUGCHK(0);
                    return ERROR_OUTOFMEMORY;
                }    
                if (pbgbs) {
                    DEBUGALLOC(pdsk->d_diActive.di_bytes_per_sect - cbSecOrig);
                    *ppbgbs = pbgbs;        // update the caller's buffer address, too
                }
                else {
                    dwError = GetLastError();
                    DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: out of memory, volume deemed invalid (%d)\r\n"), dwError));
                    pvol->v_flags |= (VOLF_INVALID|VOLF_UNCERTAIN);
                    goto exit;
                }
            }
        }
        else {

            // If SetDiskInfo returned an error, then revert to the
            // size originally reported, but continue trying to mount.

            pdsk->d_diActive.di_bytes_per_sect = cbSecOrig;
            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: SetDiskInfo call to driver failed (%d)\r\n"), GetLastError()));
        }
    }

    // Perform some trial reads now (first sector of first FAT, first
    // sector of second FAT if one exists, and anything else we think of).
    // We will clear VOLF_INVALID only on success.  NOTE that we can now reuse
    // the sector containing the BPB;  we've extracted everything we needed
    // from it.

#ifdef FAT32
    // 对dbr的相关内容进行 有效性验证
    if (pvol->v_flags & VOLF_32BIT_FAT) {

        PBIGFATBOOTFSINFO pFSInfo;

        dwError = ReadWriteDisk(pvol,
                                pdsk->d_hdsk,
                                READ_DISK_CMD,
                                &pdsk->d_diActive,
                                pvol->v_secVolBias + 1,
                                1,
                                pbgbs, 
                                TRUE);

        if (dwError != ERROR_SUCCESS) 
        {
            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: ReadWriteDisk failed on extended boot sector (%d)\r\n"), dwError));
            pvol->v_flags |= (VOLF_INVALID|VOLF_UNCERTAIN);
            goto exit;
        }

        if (*(PDWORD)((PBYTE)pbgbs + 0) != SECONDBOOTSECSIG
            ||
            *(PDWORD)((PBYTE)pbgbs + OFFSETTRLSIG) != BOOTSECTRAILSIG)
        {
            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error verifying extended boot sector, volume deemed invalid (%d)\r\n"), dwError));
            pvol->v_flags |= VOLF_INVALID;
            goto exit;
        }

        // If secFSInfo happens to be 1 (which is typical), then there's no need
        // to perform another read, since it's the same sector we just read (above).

        if (pvol->v_secFSInfo != 1) {
            dwError = ReadWriteDisk(pvol,
                                    pdsk->d_hdsk,
                                    READ_DISK_CMD,
                                    &pdsk->d_diActive,
                                    pvol->v_secVolBias + pvol->v_secFSInfo,
                                    1,
                                    pbgbs,
                                    TRUE);
        }

        if (dwError != ERROR_SUCCESS) 
        {
            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: ReadWriteDisk failed on FS info sector (%d)\r\n"), dwError));
            pvol->v_flags |= (VOLF_INVALID|VOLF_UNCERTAIN);
            goto exit;
        }

        if (*(PDWORD)((PBYTE)pbgbs + 0) != SECONDBOOTSECSIG
            ||
            *(PDWORD)((PBYTE)pbgbs + OFFSETTRLSIG) != BOOTSECTRAILSIG
            ||
            (pFSInfo = (PBIGFATBOOTFSINFO)((PBYTE)pbgbs + OFFSETFSINFOFRMSECSTRT))->bfFSInf_Sig != FSINFOSIG)
        {
            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error verifying FS info sector, volume deemed invalid (%d)\r\n"), dwError));
            pvol->v_flags |= VOLF_INVALID;
            goto exit;
        }

        // Don't use the FSInfo values since we will not update them (they are legacy from Win 9x).
#if 0
        if (pFSInfo->bfFSInf_free_clus_cnt < pvol->v_clusMax &&
            pFSInfo->bfFSInf_next_free_clus <= pvol->v_clusMax) {

            pvol->v_cclusFree = pFSInfo->bfFSInf_free_clus_cnt;
            pvol->v_clusAlloc = pFSInfo->bfFSInf_next_free_clus;
        }
        else {
            // Note that if the FSInfo fields are simply UNKNOWN_CLUSTER, then my assumption
            // is that they simply haven't been initialized yet (as opposed to being truly bogus).

            DEBUGMSG((ZONE_INIT || ZONE_ERRORS) &&
                     pFSInfo->bfFSInf_free_clus_cnt != UNKNOWN_CLUSTER &&
                     pFSInfo->bfFSInf_next_free_clus != UNKNOWN_CLUSTER, (DBGTEXT("FATFS!TestVolume: FS info data suspicious (%x,%x), ignoring...\r\n"), pFSInfo->bfFSInf_free_clus_cnt, pFSInfo->bfFSInf_next_free_clus));
        }
#endif        
    }
#endif  // FAT32

    dwError = ReadWriteDisk(pvol,
                            pdsk->d_hdsk,
                            READ_DISK_CMD,
                            &pdsk->d_diActive,
                            pvol->v_secBlkBias + 0,
                            1,
                            pbgbs,
                            FALSE);

    if (dwError != ERROR_SUCCESS) 
    {
        DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: ReadWriteDisk failed on first FAT (%d)\r\n"), dwError));
        pvol->v_flags |= (VOLF_INVALID|VOLF_UNCERTAIN);
        goto exit;
    }
    // 判断是否是有效的fat表
    if (!ValidateFATSector(pvol, pbgbs))
    {
        DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading first FAT, volume deemed invalid (%d)\r\n"), dwError));
        pvol->v_flags |= VOLF_INVALID;
        goto exit;
    }

    if (pvol->v_flags & VOLF_BACKUP_FAT) {

        dwError = ReadWriteDisk(pvol,
                pdsk->d_hdsk,
                READ_DISK_CMD,
                &pdsk->d_diActive,
                pvol->v_secBlkBias + pvol->v_csecFAT,
                1,
                pbgbs,
                FALSE);

        if (dwError != ERROR_SUCCESS) 
        {
            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: ReadWriteDisk failed on backup FAT (%d)\r\n"), dwError));
            pvol->v_flags |= (VOLF_INVALID|VOLF_UNCERTAIN);
            goto exit;
        }

        if (!ValidateFATSector(pvol, pbgbs))
        {
            DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading backup FAT, volume deemed invalid (%d)\r\n"), dwError));
            pvol->v_flags |= VOLF_INVALID;
            goto exit;
        }
    }

    // Verify we can read the last sector in the last cluster of the volume too...
#if 0
    dwError = ReadWriteDisk(pvol,
                            pdsk->d_hdsk,
                            READ_DISK_CMD,
                            &pdsk->d_diActive,
                            CLUSTERTOSECTOR(pvol, pvol->v_clusMax) +
                                (1 << pvol->v_log2csecClus) - 1,
                            1,
                            pbgbs);

    if (dwError != ERROR_SUCCESS)
    {
        DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!TestVolume: error reading last sector, volume deemed invalid (%d)\r\n"), dwError));
        pvol->v_flags |= VOLF_INVALID;
        goto exit;
    }
#endif

    // If we modified the drive parameters but the volume isn't valid anyway, restore the default parameters.

  exit:
    if ((pvol->v_flags & (VOLF_MODDISKINFO | VOLF_INVALID)) == (VOLF_MODDISKINFO | VOLF_INVALID)) {
        pvol->v_flags &= ~VOLF_MODDISKINFO;
        pdsk->d_diActive.di_bytes_per_sect = cbSecOrig;
        SetDiskInfo(pdsk->d_hdsk, &pdsk->d_diActive);
    }

    return dwError;
}


/*  RefreshVolume - Refresh a VOLUME's handles
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *
 *  EXIT
 *      Stream handles are restored, provided the volume is valid AND
 *      the streams appear to be in the same state we left them.
 */

void RefreshVolume(PVOLUME pvol)
{
    PDSTREAM pstm, pstmEnd;

    if (!(pvol->v_flags & (VOLF_REMOUNTED | VOLF_RECYCLED)))
        return;

    ASSERT(OWNCRITICALSECTION(&pvol->v_cs));

    // Walk the open stream list, regenerate each stream, then walk the
    // open handle list for each successfully regenerated stream, and clear
    // the unmounted bit for each open handle.

    // First, make sure the VISITED bit is clear in every stream currently
    // open on this volume.

    EnterCriticalSection(&pvol->v_csStms);

    pstm = pvol->v_dlOpenStreams.pstmNext;
    pstmEnd = (PDSTREAM)&pvol->v_dlOpenStreams;

    while (pstm != pstmEnd) {
        pstm->s_flags &= ~STF_VISITED;
        pstm = pstm->s_dlOpenStreams.pstmNext;
    }

    // Now find the next unvisited stream.  Note that every iteration of the
    // loop starts with the volume critical section held.

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

        // Find/read the block containing this stream's DIRENTRY, unless
        // it's a VOLUME-based stream, in which case we'll just automatically
        // remount it.

        ASSERT(pstm->s_pvol == pvol);

        // Volume handles are always remounted, regardless

        if (pstm->s_flags & STF_VOLUME)
            pstm->s_flags &= ~STF_UNMOUNTED;

        if ((pstm->s_flags & STF_UNMOUNTED) && !(pvol->v_flags & VOLF_INVALID)) {

            PBUF pbuf;

⌨️ 快捷键说明

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