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

📄 disk.c

📁 从大量的wince源代码中剥离出的fat文件系统源代码。移植性非常高。 微软的代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
        else {
            csecGap = ppi->pi_secAbsolute - secStart;
            ASSERT((int)csecGap >= 0);
            if (csecGap >= pps->ps_csecDesired ||
                csecGap >= pps->ps_csecMinimum && csecGap > pps->ps_csecFound) {
                pps->ps_pdlFound = pdlPartInfo;
                pps->ps_ppiFound = ppi;
                pps->ps_csecFound = csecGap;
            }
            pps->ps_csecTotalFound += csecGap;
            if (csecGap >= pps->ps_csecDesired)
                return TRUE;
        }
        secStart = ppi->pi_secAbsolute + ppi->pi_PartEntry.Part_TotalSectors;
        ppi = ppi->pi_dlPartitions.ppiNext;
    }

    // Check for any gap past the end of the list...

    csecGap = secEnd - secStart;
    ASSERT((int)csecGap >= 0);
    if (csecGap >= pps->ps_csecDesired ||
        csecGap >= pps->ps_csecMinimum && csecGap > pps->ps_csecFound) {
        pps->ps_pdlFound = pdlPartInfo;
        pps->ps_ppiFound = ppi;
        pps->ps_csecFound = csecGap;
    }
    pps->ps_csecTotalFound += csecGap;
    if (csecGap >= pps->ps_csecDesired)
        return TRUE;

    return FALSE;
}


/*  RefreshPartitionInfo
 *
 *  ENTRY
 *      pdsk -> DSK structure
 *
 *  EXIT
 *      Partition information cached in the DSK structure is updated
 *      (eg, d_csec_Unused, d_csecTotalUnused).  Total unused sectors
 *      could be updated on the fly as we create/destroy PARTINFO structures,
 *      but the largest unused chunk cannot be determined until all partition
 *      mounting is complete.
 */

void RefreshPartitionInfo(PDSK pdsk)
{
    PARTSRCH ps;

    memset(&ps, 0, sizeof(ps));
    ps.ps_csecMinimum = ps.ps_csecDesired = 0xffffffff;
    WalkPartitionInfo(&pdsk->d_dlPartitions, 0, pdsk->d_diActive.di_total_sectors, &ps);

    pdsk->d_csecUnused = ps.ps_csecFound;
    pdsk->d_csecTotalUnused = ps.ps_csecTotalFound;
}


/*  FreePartitionInfo - Free all PARTINFO structures associated with a DSK structure
 *
 *  ENTRY
 *      pdlPartInfo -> head of a partition list
 *
 *  EXIT
 *      None
 */

void FreePartitionInfo(PPI_DLINK pdlPartInfo)
{
    PPARTINFO ppi = pdlPartInfo->ppiNext;

    while (ppi != (PPARTINFO)pdlPartInfo) {

        FreePartitionInfo(&ppi->pi_dlChildren);
        RemoveItem((PDLINK)&ppi->pi_dlPartitions);

        // If this partition info is associated with a volume, kill that association now

        if (ppi->pi_pvol) {
            ppi->pi_pvol->v_ppi = NULL;
          //ppi->pi_pvol = NULL;
        }

        NamePartitionInfo(ppi, NULL);   // free the name, if any
        ppi->pi_dwSig = 0;              // zap the signature, to avoid being spoofed elsewhere

        DEBUGFREE(sizeof(PARTINFO));
        VERIFYNULL(LocalFree((HLOCAL)ppi));

        ppi = pdlPartInfo->ppiNext;
        continue;
    }
}




PDSK FindDisk(HANDLE hdsk, PCWSTR pwsDisk, PDISK_INFO pdi)
{
    DWORD cwDisk;
    PDSK pdsk = dlDisks.pdskNext;

    ASSERT(OWNCRITICALSECTION(&csFATFS));

    cwDisk = 0;
    if (pwsDisk)
        cwDisk = wcslen(pwsDisk)+1;

    while (pdsk && (pdsk != (PDSK)&dlDisks)) {

        if (pdsk->d_hdsk == hdsk) {
            if (pdi)
                ASSERT(memcmp(&pdsk->d_diActive, pdi, sizeof(*pdi)) == 0);
            goto exit;
        }

        if (pdi && (pdsk->d_flags & DSKF_FROZEN)) {

            if (memcmp(&pdsk->d_diActive, pdi, sizeof(*pdi)) == 0) {
                pdsk->d_flags |= DSKF_REMOUNTED;
                DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!FindDisk: remounting frozen disk...\n")));
                goto init2;
            }
        }
        pdsk = pdsk->d_dlOpenDisks.pdskNext;
    }

    if (!pdi) {
        pdsk = NULL;
        goto exit;
    }    

    pdsk = (PDSK)LocalAlloc(LPTR, sizeof(DSK)-sizeof(pdsk->d_wsName) + cwDisk*sizeof(pwsDisk[0]));
    if (!pdsk)
        DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!FindDisk: out of memory!\n")));
    else {
        DEBUGALLOC(sizeof(DSK)-sizeof(pdsk->d_wsName) + cwDisk*sizeof(pwsDisk[0]));
        AddItem((PDLINK)&dlDisks, (PDLINK)&pdsk->d_dlOpenDisks);
        InitList((PDLINK)&pdsk->d_dlPartitions);
        pdsk->d_diActive = *pdi;
init2:
        pdsk->d_cwName = cwDisk;
        wcsncpy(pdsk->d_wsName, pwsDisk, cwDisk);
    }

exit:
    return pdsk;
}


/*  MountDisk - Find and mount all volumes on specified disk
 *
 *  ENTRY
 *      hdsk - handle to disk device containing one or more FAT volumes
 *      pwsDisk -> name of disk device, NULL if unknown
 *      flVol - initial volume flags (currently, only VOLF_READONLY is copied)
 *
 *  EXIT
 *      Pointer to DSK structure, NULL if error (eg, out of memory,
 *      unusable disk, etc)
 *
 *  NOTES
 *      In the 1.0 release, if the disk appeared to be a hard disk, I mounted
 *      only the active DOS partition, and if there was *no* active partition,
 *      then I mounted only the *first* DOS partition.  In the current release,
 *      I mount *all* DOS partitions, including "Extended DOS Partitions".
 */

PDSK MountDisk(HANDLE hdsk, PCWSTR pwsDisk, DWORD flVol)
{
    DWORD dwError;
    DISK_INFO di;
    PBYTE pbSector;
    PDSK pdsk = NULL;

   
    if (GetDiskInfo(hdsk, &di) != ERROR_SUCCESS || di.di_bytes_per_sect == 0) {

        DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!MountDisk: no valid disk info (%d)\n"), GetLastError()));

        di.di_total_sectors = SetFilePointer(hdsk, 0, NULL, FILE_END);
        if (di.di_total_sectors == 0xFFFFFFFF || di.di_total_sectors < DEFAULT_SECTOR_SIZE)
            return NULL;

        di.di_total_sectors /= DEFAULT_SECTOR_SIZE;
        di.di_bytes_per_sect = DEFAULT_SECTOR_SIZE;
        di.di_cylinders = 1;
        di.di_heads = 1;
        di.di_sectors = di.di_total_sectors;
        di.di_flags = DISK_INFO_FLAG_CHS_UNCERTAIN | DISK_INFO_FLAGS_FATFS_SIMULATED;
    }
    else {
        // Make sure our special "simulated" flag is never set by the driver
        DEBUGMSG((di.di_flags & DISK_INFO_FLAGS_FATFS_SIMULATED),(DBGTEXT("FATFS!MountDisk: driver is setting reserved bit(s)!\n")));
        di.di_flags &= ~DISK_INFO_FLAGS_FATFS_SIMULATED;
    }
    if (di.di_total_sectors < 16) {
        return NULL;
    }    

    // We ZEROINIT the memory so that if the ReadWriteDisk call fails
    // (perhaps because the media is completely unreadable/unusable at this
    // point), MountVolume won't be spoofed by bogus data in the sector buffer;
    // even though MountVolume won't actually mount anything in that case, it
    // will at least register a volume name that can be subsequently used in
    // format requests.

    pbSector = (PBYTE)LocalAlloc(LPTR, di.di_bytes_per_sect);
    if (!pbSector) {
        DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!MountDisk: out of memory, aborting mount\n")));
        return NULL;
    }
    DEBUGALLOC(di.di_bytes_per_sect);

    dwError = ReadWriteDisk(NULL, hdsk, DISK_IOCTL_READ, &di, 0, 1, pbSector);
    DEBUGMSG(ZONE_ERRORS && dwError,(DBGTEXT("FATFS!MountDisk: error reading MBR (%d)\n"), dwError));

    EnterCriticalSection(&csFATFS);

    // This is a logical point to assume that we're actually going
    // to succeed in mounting one or more volumes, so let's allocate
    // and initialize a DSK structure for the entire disk (which may
    // contain 0 or more volumes).

    pdsk = FindDisk(hdsk, pwsDisk, &di);
    if (!pdsk)
        goto exit;

    pdsk->d_hdsk = hdsk;
    pdsk->d_flags &= ~DSKF_FROZEN;


    // Since we're mounting non-partitioned media, HiddenSectors should be zero

    if (((PBIGFATBOOTSEC)pbSector)->bgbsBPB.oldBPB.BPB_HiddenSectors != 0) {
        DEBUGMSGW(ZONE_ERRORS,(DBGTEXTW("FATFS!MountDisk: BPB_HiddenSectors(%d) != 0\n"), ((PBIGFATBOOTSEC)pbSector)->bgbsBPB.oldBPB.BPB_HiddenSectors));
        ((PBIGFATBOOTSEC)pbSector)->bgbsBPB.oldBPB.BPB_HiddenSectors = 0;
    }
    pdsk->pVol = MountVolume(pdsk, (PBIGFATBOOTSEC *)&pbSector, NULL, flVol);

    // If we allocated a DSK structure but we never allocated any VOLUMEs
    // to go along with it, then free the DSK structure, using UnmountDisk.

  exit:
    if (pdsk && !(pdsk->d_flags & (DSKF_REMOUNTED | DSKF_RECYCLED)) && !pdsk->pVol) {

        pdsk->d_hdsk = INVALID_HANDLE_VALUE;    // prevent UnmountDisk from trying to close the disk
        UnmountDisk(pdsk, FALSE);
        pdsk = NULL;
    }

    if (pdsk)
        RefreshPartitionInfo(pdsk);

    LeaveCriticalSection(&csFATFS);

    DEBUGFREE(di.di_bytes_per_sect);
    VERIFYNULL(LocalFree((HLOCAL)pbSector));
    return pdsk;
}




/*  UnmountDisk - Unmount all volumes on specified disk
 *
 *  ENTRY
 *      pdsk -> DSK structure
 *      fFrozen == TRUE to unmount frozen volumes only;
 *      this is used when we're notified that all file system devices
 *      are ON, so we no longer want to retain frozen volumes that no
 *      longer have any open files or dirty data.
 *
 *  EXIT
 *      TRUE if all volumes on disk were unmounted, FALSE if not;  if all
 *      VOLUMEs are automatically freed, then the DSK is freed as well.
 */

BOOL UnmountDisk(PDSK pdsk, BOOL fFrozen)
{
    PVOLUME pvol=pdsk->pVol;
    BOOL fSuccess = TRUE;

    DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!UnmountDisk: unmounting %s volumes on disk %s\n"), fFrozen? TEXTW("frozen") : TEXTW("all"), pdsk->d_wsName));

    EnterCriticalSection(&csFATFS);

    if (pvol) {

        ASSERT(pvol->v_pdsk == pdsk);

        fSuccess = UnmountVolume(pvol, fFrozen);
    }

    // If we're going to free the DSK structure, or the disk
    // is going away anyway, then close the disk handle as well.

    if (fSuccess || !fFrozen) {
        if (pdsk->d_hdsk != INVALID_HANDLE_VALUE) {
            DEBUGFREE(DEBUGALLOC_HANDLE);
            CloseHandle(pdsk->d_hdsk);
            pdsk->d_hdsk = INVALID_HANDLE_VALUE;
        }
        pdsk->d_flags |= DSKF_FROZEN;
        pdsk->d_flags &= ~(DSKF_REMOUNTED | DSKF_RECYCLED);
    }

    if (fSuccess) {
        FreePartitionInfo(&pdsk->d_dlPartitions);
        RemoveItem((PDLINK)&pdsk->d_dlOpenDisks);
        DEBUGFREE(sizeof(DSK)-sizeof(pdsk->d_wsName) + pdsk->d_cwName*sizeof(pdsk->d_wsName[0]));
        VERIFYNULL(LocalFree((HLOCAL)pdsk));
    }

    LeaveCriticalSection(&csFATFS);

    DEBUGMSG(ZONE_APIS,(DBGTEXT("FATFS!UnmountDisk returned %d\n"), fSuccess));
    return fSuccess;
}


/*  UnmountAllDisks - Unmount all disks
 *
 *  ENTRY
 *      fFrozen == TRUE to unmount frozen volumes only;  this is used when
 *      we are notified that all file system devices are ON, so we no longer
 *      want to retain frozen volumes that no longer have any open files or
 *      dirty data.
 *
 *  EXIT
 *      The number of disk devices actually unmounted.
 */

DWORD UnmountAllDisks(BOOL fFrozen)
{
    DWORD cDisks = 0;

    if (dlDisks.pdskNext != (PDSK)&dlDisks) {

        PDSK pdsk;
        EnterCriticalSection(&csFATFS);
        pdsk = dlDisks.pdskNext;

        while (pdsk != (PDSK)&dlDisks) {

            if (UnmountDisk(pdsk, fFrozen)) {

                cDisks++;

                // Since UnmountDisk was successful, the DSK was
                // removed from the list and freed, so start at the top
                // of the list again.

                pdsk = dlDisks.pdskNext;
                continue;
            }
            pdsk = pdsk->d_dlOpenDisks.pdskNext;
        }
        LeaveCriticalSection(&csFATFS);
    }
    return cDisks;
}

⌨️ 快捷键说明

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