?? volume.c
字號:
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 + -