📄 volume.c
字号:
// 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;
}
/* GetAFSName - Query name of specified AFS
*
* ENTRY
* pvol -> VOLUME
* iAFS == AFS index
* poi -> CEOIDINFO
*
* EXIT
* Length of AFS name (in characters), 0 if error
*/
int GetAFSName(int iAFS, CEOIDINFO *poi)
{
if (!CeOidGetInfo(OIDFROMAFS(iAFS), poi))
return 0;
return wcslen(poi->infDirectory.szDirName);
}
// TODO: YG - Investigate - Neccesity of GetDeviceValue
int GetDeviceValue(PWSTR pwsDevName, PCWSTR pwsValueName, PWSTR pwsValue)
{
HKEY hKey;
DWORD ValType;
DWORD ValLen;
DWORD dwError;
WCHAR wsDriverKey[MAX_PATH];
WCHAR wsActiveKey[MAX_PATH];
ValLen = sizeof(wsDriverKey);
ValType = sizeof(wsActiveKey);
// Use GetDeviceKeys function (see COREDLL.DLL, winceos\drivers\serdev\devices.c)
dwError = GetDeviceKeys(pwsDevName, wsActiveKey, &ValType, wsDriverKey, &ValLen);
if (dwError) {
DEBUGMSGW(ZONE_INIT || ZONE_ERRORS,(DBGTEXTW("FATFS!GetDeviceValue: GetDeviceKeys(%s) failed (%d)\n"), pwsDevName, dwError));
return 0;
}
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!GetDeviceValue(%s): DriverKey='%s', ActiveKey='%s'\n"), pwsDevName, wsDriverKey, wsActiveKey));
#ifdef MAX_DEBUG
//
// Get the PCMCIA socket number from the active key
//
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wsActiveKey, 0, 0, &hKey);
if (dwError)
DEBUGMSGW(ZONE_INIT || ZONE_ERRORS,(DBGTEXTW("FATFS!GetDeviceValue(%s): RegOpenKeyEx(HKLM\\%s) failed (%d)\n"), pwsDevName, wsActiveKey, dwError));
else {
DWORD dwVal;
ValLen = sizeof(dwVal);
dwError = RegQueryValueEx(hKey,
DEVLOAD_SOCKET_VALNAME, // see devload.h
NULL,
&ValType,
(PUCHAR)&dwVal,
&ValLen);
if (dwError)
DEBUGMSGW(ZONE_INIT || ZONE_ERRORS,(DBGTEXTW("FATFS!GetDeviceValue(%s): RegQueryValueEx(%s\\%s) failed (%d)\n"), pwsDevName, wsActiveKey, DEVLOAD_SOCKET_VALNAME, dwError));
else {
//
// The socket number is in the low byte (the function number is in the next byte)
//
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!GetDeviceValue(%s): socket number is %d\n"), pwsDevName, dwVal & 0x000000ff));
}
RegCloseKey(hKey);
}
#endif // MAX_DEBUG
//
// Get the specified string value from the driver key
//
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wsDriverKey, 0, 0, &hKey);
if (dwError) {
DEBUGMSGW(ZONE_INIT || ZONE_ERRORS,(DBGTEXTW("FATFS!GetDeviceValue(%s): RegOpenKeyEx(HKLM\\%s) failed (%d)\n"), pwsDevName, wsDriverKey, dwError));
ValLen = 0;
}
else {
ValLen = MAX_PATH;
dwError = RegQueryValueEx(hKey, pwsValueName, NULL, &ValType, (PUCHAR)pwsValue, &ValLen);
if (dwError) {
DEBUGMSGW(ZONE_INIT || ZONE_ERRORS,(DBGTEXTW("FATFS!GetDeviceValue(%s): RegQueryValueEx(HKLM\\%s\\%s) failed (%d)\n"), pwsDevName, wsDriverKey, pwsValueName, dwError));
ValLen = 0;
}
else {
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!GetDeviceValue(%s): 'HKLM\\%s\\%s'='%s'\n"), pwsDevName, wsDriverKey, pwsValueName, pwsValue));
ASSERT(ValLen > sizeof(WCHAR) && !(ValLen & 0x1));
if (ValLen <= sizeof(WCHAR))
ValLen = 0; // invalid registry data
else
ValLen = ValLen/sizeof(WCHAR) - 1; // convert to # chars (not including terminating NULL)
}
RegCloseKey(hKey);
}
return (int)ValLen;
}
/* 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;
pvol->v_pwsHostRoot = LocalAlloc( LMEM_FIXED, MAX_PATH * sizeof(WCHAR));
FSDMGR_GetVolumeName(pvol->v_hVol, pvol->v_pwsHostRoot, MAX_PATH);
pvol->v_cwsHostRoot = wcslen(pvol->v_pwsHostRoot);
fSuccess = TRUE;
}
return fSuccess;
}
/* DeregisterVolume - Deregister VOLUME in file system
*
* ENTRY
* pvol -> VOLUME
*
* EXIT
* None
*/
void DeregisterVolume(PVOLUME pvol)
{
if (pvol->v_volID != INVALID_AFS) {
FSDMGR_DeregisterVolume(pvol->v_hVol);
pvol->v_volID = INVALID_AFS;
}
}
/* MountVolume - Mount volume on specified disk
*
* ENTRY
* pdsk -> DSK structure for disk
* pbSector -> BIGFATBOOTSEC structure (from disk)
* ppi -> PI structure containing partition information
* 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, PPARTINFO ppi, DWORD flVol)
{
PVOLUME pvol;
ASSERT(OWNCRITICALSECTION(&csFATFS));
if (pvol = OpenVolume(pdsk, ppi, ppbgbs, NULL)) {
pvol->v_flags &= ~VOLF_READONLY;
pvol->v_flags |= (flVol & VOLF_READONLY);
if ((pvol->v_flags & VOLF_INVALID) && ppi != NULL) {
// For invalid volumes, we still know something about the start
// and extent of the volume, based on the partition table. So we
// will record that info in the VOLUME structure for future reformats.
pvol->v_secVolBias = ppi->pi_secAbsolute;
pvol->v_csecTotal = ppi->pi_PartEntry.Part_TotalSectors;
pvol->v_secBlkBias = pvol->v_secVolBias;
}
#ifdef LATER
// Although we call FreeBufferPool inside CloseVolume, we call
// AllocBufferPool outside OpenVolume so that we can free the sector
// buffer first and avoid spiking the system's memory requirements
// any more than necessary.
DEBUGFREE(pvol->v_pdsk->d_diActive.di_bytes_per_sect);
VERIFYNULL(LocalFree((HLOCAL)pbSector));
#endif
if (AllocBufferPool(pvol)) {
// 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 (which also 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.
LeaveCriticalSection(&pvol->v_cs);
if ((pvol->v_flags & VOLF_FORMATTING) || RegisterVolume(pvol)) {
pvol->v_flags &= ~VOLF_UNMOUNTED;
// Make sure the following calls won't block if the current
// mount happens to occur immediately after a power cycle.
// The driver and volume should be more than ready by this point.
flFATFS &= ~FATFS_SHUTDOWN;
if (!(pvol->v_flags & VOLF_INITCOMPLETE)) {
BOOL fCompCheck = !(flFATFS & FATFS_DISABLE_COMPCHECK);
// We set VOLF_INITCOMPLETE a little prematurely in order
// to avoid a nested call to MountVolume redundantly taking
// this path. A nested call can occur in several ways; for
// example, if ScanVolume or CheckUnformattedVolume modified
// the volume, they would generate a remount as soon as they
// unlocked the volume.
pvol->v_flags |= VOLF_INITCOMPLETE;
// Do all the rest of our once-in-a-volume-lifetime bit
// twiddling before diving into the first sections of code
// that might care about them (some of them anyway). For
// example, turning on write verifies before we get to ScanVolume
// and any attempts it might make to repair a bad disk is probably
// a good idea....
if (flFATFS & FATFS_UPDATE_ACCESS)
pvol->v_flags |= VOLF_UPDATE_ACCESS;
if (!(flFATFS & FATFS_DISABLE_AUTOSCAN))
pvol->v_bVerifyCount = 3;
if (flFATFS & FATFS_VERIFY_WRITES)
pvol->v_bVerifyCount = 255; // set magic value that is never decremented
// Check for unformatted (or unsupported) volumes and volunteer to format them
if (!(flFATFS & FATFS_DISABLE_AUTOFORMAT))
if (CheckUnformattedVolume(pvol))
fCompCheck = FALSE; // no need to check for compressed volumes
// Check for errors in the volume's file system, now that
// we've taken care of any potential roll-backs.
if (!(flFATFS & FATFS_DISABLE_AUTOSCAN))
ScanVolume(pvol, SCANVOL_QUICK, ScanFixInteractive, NULL);
// Check for compressed volume files (which we don't support,
// a fact that we would like to advise the user of).
if (fCompCheck)
CheckCompressedVolume(pvol);
}
return pvol;
}
else
DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!MountVolume: unable to register file system (%d)\n"), GetLastError()));
}
else
DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!MountVolume: unable to allocate buffer pool\n")));
// Free the volume we just allocated if we can't allocate enough
// buffers or there's a problem registering with the host file system.
EnterCriticalSection(&pvol->v_cs);
VERIFYTRUE(CloseVolume(pvol, NULL));
}
return NULL;
}
/* UnmountVolume - Unmount the specified volume
*
* ENTRY
* pvol -> VOLUME structure
* fFrozen == TRUE to unmount frozen volumes only
*
* EXIT
* TRUE if volume was successfully unmounted, FALSE if not
*/
BOOL UnmountVolume(PVOLUME pvol, BOOL fFrozen)
{
BOOL fDirty = FALSE;
BOOL fSuccess = TRUE;
WCHAR wsVolName[MAX_PATH];
if (fFrozen && !(pvol->v_flags & VOLF_FROZEN)) {
fSuccess = FALSE;
goto exit;
}
EnterCriticalSection(&csFATFS);
EnterCriticalSection(&pvol->v_cs);
if (fFrozen) {
// Clear the FROZEN and RETAIN flags, so that CloseVolume
// retains the volume only if it must (ie, open files and/or
// dirty buffers).
pvol->v_flags &= ~(VOLF_FROZEN | VOLF_RETAIN);
}
else {
pvol->v_flags |= VOLF_UNMOUNTED;
pvol->v_flags &= ~(VOLF_REMOUNTED | VOLF_RECYCLED);
// If we're being detached, then we must *force* closure
if (cLoads == 0) {
DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!UnmountVolume: volume 0x%08x being forcibly closed!\n"), pvol));
FAT_CloseAllFiles(pvol, NULL);
// Clear the FROZEN and RETAIN flags, and set the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -