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

📄 volume.c

📁 从大量的wince源代码中剥离出的fat文件系统源代码。移植性非常高。 微软的代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    // 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 + -