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

📄 path.c

📁 Windows操作系统中文件系统过滤驱动和设备驱动之间的相似
💻 C
📖 第 1 页 / 共 4 页
字号:
    // Failed allocation means that optimization is not used
    pvol->v_clusterListSize = (pvol->v_clusMax + CLUSTERS_PER_LIST_ENTRY - 1) / CLUSTERS_PER_LIST_ENTRY;
    pvol->v_clusterListSize = (pvol->v_clusterListSize + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1);
    pvol->v_pFreeClusterList = (LPBYTE)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, pvol->v_clusterListSize);

    dwSectorsRead = dwBufferSize >> pvol->v_log2cbSec;
    if (ReadVolume (pvol, 0, dwSectorsRead, pFATBuffer) != ERROR_SUCCESS) {
        goto exit;
    }

    // Start looking at the DATA_CLUSTER
    // 偏移到真正的数据区开始位置,偏移量为cbFATEntry * DATA_CLUSTER,这些数据都在fat表中
    pCurEntry = pFATBuffer + cbFATEntry * DATA_CLUSTER;

    pvol->v_cclusFree = 0;

    for (dwClus = DATA_CLUSTER; dwClus <= pvol->v_clusMax;  dwClus++) {

        if ((DWORD)(pCurEntry - pFATBuffer) >= dwBufferSize) {

            // We've reached the end of the buffer, read the next chunk of data
            DWORD dwSectorsToRead = min (pvol->v_csecFAT - dwSectorsRead, (DWORD)MAX_FREE_SPACE_CHUNK_SIZE >> pvol->v_log2cbSec);

            if (ReadVolume (pvol, dwSectorsRead, dwSectorsToRead, pFATBuffer) != ERROR_SUCCESS) {
                goto exit;
            }            
            pCurEntry = pFATBuffer;  
            dwSectorsRead += dwSectorsToRead;
        }

        if (fFAT16) {
            if ((*(PWORD)pCurEntry) == FREE_CLUSTER) {
                IncrementFreeClusterCount(pvol, dwClus);
            }
        } else {
            if ((*(PDWORD)pCurEntry) == FREE_CLUSTER) {
                IncrementFreeClusterCount(pvol, dwClus);
            }
        }

        pCurEntry += cbFATEntry;
    }

    fRet = TRUE;

exit:    
    if (pFATBuffer) {
        VirtualFree (pFATBuffer, 0, MEM_RELEASE);
    }
    return fRet;
}

DWORD CalculateFreeClustersFromBuffers(PVOLUME pvol)
{
    DWORD dwClus, dwData;
    DWORD dwError = ERROR_SUCCESS;

    pvol->v_cclusFree = 0;
    for (dwClus=DATA_CLUSTER; dwClus <= pvol->v_clusMax;  dwClus++) {
        dwError = UNPACK(pvol, dwClus, &dwData);
        if (dwError)
            break;
        if (dwData == FREE_CLUSTER)
            pvol->v_cclusFree++;
    }

    return dwError;
}

BOOL FAT_GetDiskFreeSpaceW(
PVOLUME pvol,
PCWSTR pwsPathName,
PDWORD pSectorsPerCluster,
PDWORD pBytesPerSector,
PDWORD pFreeClusters,
PDWORD pClusters)
{
    BOOL fSuccess = FALSE;
    DWORD dwError = ERROR_SUCCESS;

    
    DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_GetDiskFreeSpace(%s)\r\n"), pwsPathName? pwsPathName : TEXTW("")));

    LockFAT(pvol);

    if (pvol->v_flags & (VOLF_INVALID | VOLF_UNMOUNTED | VOLF_FROZEN | VOLF_WRITELOCKED)) {
        dwError = ERROR_ACCESS_DENIED;
        goto exit;
    }

    // We enter the FAT's critical section even though we're just reading
    // the FAT, because in process of reading, we could alter the FAT stream's
    // current buffer, and that could mess up someone else accessing the FAT.

    if (pvol->v_cclusFree == UNKNOWN_CLUSTER) {

        // We currently call FATEnter/FATExit just at this point,
        // because it's the only path in this call that might generate any I/O.

        if (!FATEnter(NULL, LOGID_NONE))
            goto exit;
    
        if (!CalculateFreeClustersInRAM(pvol)) {
            // If we couldn't do it in RAM, try it through the FAT buffers.
            dwError = CalculateFreeClustersFromBuffers(pvol);
        }
        
        FATExit(pvol, LOGID_NONE);
    }

    __try {
        if (!dwError) {
            if (pSectorsPerCluster)
                *pSectorsPerCluster = (1 << pvol->v_log2csecClus);
            if (pBytesPerSector)
                *pBytesPerSector = (1 << pvol->v_log2cbSec);
            if (pFreeClusters)
                *pFreeClusters = pvol->v_cclusFree;            
            if (pClusters)
                *pClusters = pvol->v_clusMax-1;
            fSuccess = TRUE;
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        dwError = ERROR_INVALID_PARAMETER;
    }

  exit:

    UnlockFAT(pvol);

    DEBUGMSG(ZONE_APIS || ZONE_CLUSTERS || ZONE_ERRORS && !fSuccess,(DBGTEXT("FATFS!FAT_GetDiskFreeSpace returned 0x%x (%d), 0x%x clusters free\r\n"), fSuccess, dwError, pvol->v_cclusFree));

    if (dwError)
        SetLastError(dwError);

    return fSuccess;
}



/*  GetSIDInfo - Get file information by SID (worker for FAT_OidGetInfo)
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *      psid - pointer to SID of interest
 *      poi - pointer to OID information to return
 *
 *  EXIT
 *      Error code (ERROR_SUCCESS if none).  This code was removed from FAT_OidGetInfo
 *      and put into this worker function, because we cannot tolerate FAT_* entry points
 *      calling other FAT_* entry points (like FAT_OidGetInfo!), because then we can
 *      get into situations where an outer call is blocked by an inner call that is in
 *      turn blocked in FATEnter (because power just went off or something....)
 *
 *      That particular case wasn't a problem in v1.0, because the shell notification
 *      mechanism was SHELL_MESSAGE_NOTIFICATION, not SHELL_CALLBACK_NOTIFICATION;  the latter
 *      now requires us to provide information while we're still inside the FAT APIs.
 */

DWORD GetSIDInfo(PVOLUME pvol, PDSID psid, CEOIDINFO *poi)
{
    SHANDLE sh;
    PWSTR pwsCur;
    DWORD len, dwError;
    BYTE fSearch;
    DWORD dwSearch;
    DWORD dwNext;
    DWORD oidParent;
    DWORD clusParent;
    DIRINFO di;
    WIN32_FIND_DATAW fd;

    fSearch = SHF_BYORD;
    dwSearch = psid->sid_ordDir;
    oidParent = 0;
    clusParent = psid->sid_clusDir;

    // Assume the OID is valid
    dwError = ERROR_SUCCESS;

    if (psid->sid_clusDir == UNKNOWN_CLUSTER)
        dwError = ERROR_INVALID_PARAMETER;

    // Find/create a stream for the object's directory

    // NOTE: this form of OpenStream doesn't initialize the stream's name,
    // attr, size, parent OID, or path length.  However, lower level functions
    // we call, like FindNext (which calls ReadStream), don't depend on that
    // information, and since we're creating the stream as a PRIVATE stream, no
    // one else will either.

    while (!dwError && clusParent && (sh.sh_pstm = OpenStream(pvol, clusParent, NULL, NULL, NULL, OPENSTREAM_CREATE|OPENSTREAM_PRIVATE))) {

        __try {

            dwNext = clusParent;
            dwError = ERROR_SUCCESS;

            // Prepare to build the full name from the top down

            // Find the object's DIRENTRY within that stream now.
            // But first, since the directory's "." and ".." entries
            // should appear first, let's look for them first.  This
            // will reduce the amount of oscillation within the stream.

            if (!ISROOTDIR(sh.sh_pstm)) {

                sh.sh_pos = 0;
                sh.sh_flags = SHF_BYNAME | SHF_DOTDOT;
                sh.sh_cwPattern = ARRAYSIZE(szDotDot)-1;
                memcpy(sh.sh_awcPattern, szDotDot, sizeof(szDotDot));

                dwError = FindNext(&sh, &di, &fd);
                if (!dwError) {

                    // Because we supplied a DIRINFO to FindNext,
                    // the stream buffer did NOT automatically get unheld.

                    ReleaseStreamBuffer(sh.sh_pstm, FALSE);

                    clusParent = di.di_clusEntry;

                    // The absence of a cluster (on non-FAT32 volumes anyway)
                    // means that this directory's parent is the ROOT.

                    if (di.di_clusEntry == UNKNOWN_CLUSTER)
                        clusParent = pvol->v_pstmRoot->s_clusFirst;
                }
                else {
                    DEBUGMSG(ZONE_ERRORS,(TEXT("FATFS!GetSIDInfo: FindNext(%x) for clusParent 0x%x returned %d\r\n"), sh.sh_flags, dwNext, dwError));

                    // FindNext already set dwError to something, so let's pass it on;
                    // this is more important for "driver errors", like ERROR_GEN_FAILURE,
                    // because those errors will insure that any lengthy scan in-progress
                    // will get cancelled instead of continuing (see ScanDirectory in scan.c)

                    // dwError = ERROR_INVALID_PARAMETER;
                    goto close;
                }
            }
            else
                clusParent = NO_CLUSTER;

            // OK, now we can go look for the object's DIRENTRY

            sh.sh_pos = 0;
            sh.sh_flags = fSearch;
            sh.sh_h = (HANDLE)dwSearch;

            dwError = FindNext(&sh, NULL, &fd);
            if (!dwError) {

                // The first DIRENTRY search is BYORD because that's
                // all the OID tells us.  Subsequent DIRENTRY searches are
                // BYCLUS because that's all the ".." entries tell us.

                // The first (BYORD) search is also the one that gives us
                // the attribute, size, etc info we need, so record that now.

                if (fSearch == SHF_BYORD) {
                    poi->infFile.dwAttributes = fd.dwFileAttributes;
                    poi->infFile.ftLastChanged = fd.ftLastWriteTime;
                    if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                        poi->wObjType = OBJTYPE_DIRECTORY;
                    else {
                        poi->wObjType = OBJTYPE_FILE;
                        poi->infFile.dwLength = fd.nFileSizeLow;
                    }
                    pwsCur = &poi->infFile.szFileName[MAX_PATH-1];
                    *pwsCur = 0;
                }

                // If this is the first BYCLUS search (ie, if oidParent
                // is still zero), then record this object as the parent.

                else if (oidParent == 0)
#ifdef UNDER_CE
                    // NT does not have OID defined                            
                    oidParent = fd.dwOID;
#endif

                // fd.cFileName has the name from the object's DIRENTRY
                // Ignore the hidden root directory.
                if (wcscmp(fd.cFileName, HIDDEN_TFAT_ROOT_DIR) != 0) {
                    len = wcslen(fd.cFileName);
                    pwsCur -= len;
                }

                if (pwsCur > poi->infFile.szFileName) {

                    if (wcscmp(fd.cFileName, HIDDEN_TFAT_ROOT_DIR) != 0) {
                        memcpy(pwsCur, fd.cFileName, len*sizeof(WCHAR));
                        *--pwsCur = TEXTW('\\');
                    }
                    if (clusParent) {
                        // Get ready for next search, since this one is done now
                        fSearch = SHF_BYCLUS;
                        dwSearch = dwNext;
                    }
                    else if (pvol->v_pwsHostRoot) {
                        pwsCur -= pvol->v_cwsHostRoot;
                        if (pwsCur >= poi->infFile.szFileName)
                            memcpy(pwsCur, pvol->v_pwsHostRoot, pvol->v_cwsHostRoot*sizeof(WCHAR));
                        else
                            dwError = ERROR_BUFFER_OVERFLOW;
                    }
                }
                else
                    dwError = ERROR_BUFFER_OVERFLOW;
            }
            else {
                DEBUGMSG(ZONE_ERRORS,(TEXT("FATFS!GetSIDInfo: FindNext(%x) for clusParent 0x%x returned %d\r\n"), sh.sh_flags, dwNext, dwError));
                dwError = ERROR_INVALID_PARAMETER;
            }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            dwError = ERROR_INVALID_PARAMETER;
        }

      close:
        CloseStream(sh.sh_pstm);

        if (dwError)
            break;
    }

    if (!dwError && !sh.sh_pstm) {
        dwError = ERROR_BAD_UNIT;  // device must have been removed
    }

    if (!dwError) {

        if (oidParent == 0)
            oidParent = OIDFROMSID(pvol, NULL);

        __try {
            poi->infFile.oidParent = oidParent;

            // Slide the completed filename down (if it isn't already)

            if (pwsCur != poi->infFile.szFileName)
                memcpy(poi->infFile.szFileName, pwsCur, (wcslen(pwsCur)+1)*sizeof(WCHAR));
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            dwError = ERROR_INVALID_PARAMETER;
        }
    }
    return dwError;
}


#ifdef SHELL_MESSAGE_NOTIFICATION

#ifndef DEBUG
void PostFileSystemMessage(PVOLUME pvol, UINT uMsg, PDSID psid, PDSID psidParent)
#else
void PostFileSystemMessage(PVOLUME pvol, UINT uMsg, PDSID psid, PDSID psidParent, PWSTR pwsCaller)
#endif
{
    if (hwndShellNotify && ZONE_SHELLMSGS) {
        PostMessage(hwndShellNotify, uMsg, OIDFROMSID(pvol,psid), OIDFROMSID(pvol,psidParent));
        DEBUGMSGW(ZONE_MSGS,(DBGTEXTW("FATFS!%s posted(0x%08x,0x%08x,0x%08x)\r\n"), pwsCaller, uMsg, OIDFROMSID(pvol,psid), OIDFROMSID(pvol,psidParent)));
    }
}

#endif  // SHELL_MESSAGE_NOTIFICATION


#ifdef SHELL_CALLBACK_NOTIFICATION

#ifndef DEBUG
void CallFileSystemFunction(PVOLUME pvol, DWORD dwSHCNE, PDSID psid, PDSID psidOld, CEOIDINFO *poiOld)
#else
void CallFileSystemFunction(PVOLUME pvol, DWORD dwSHCNE, PDSID psid, PDSID psidOld, CEOIDINFO *poiOld, PWSTR pwsCaller)
#endif
{
    if (pfnShell && ZONE_SHELLMSGS) {

        DWORD dwError;
        CEOIDINFO oi;
        FILECHANGEINFO fci;

        memset(&oi, 0, sizeof(oi));

        DEBUGMSG(ZONE_ERRORS && psid == NULL && psidOld == NULL,(DBGTEXT("FATFS!CallFileSystemFunction(0x%08x,0x%08x): called with invalid PDSIDs\r\n"), pvol, dwSHCNE));

        if (psid && (dwError = GetSIDInfo(pvol, psid, &oi))) {
            DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!CallFileSystemFunction(0x%08x,0x%08x): GetSIDInfo unexpectedly failed (%d)\r\n"), pvol, dwSHCNE, dwError));
            return;
        }

        fci.cbSize = sizeof(fci);
        fci.wEventId = dwSHCNE;
        fci.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT;
        fci.dwItem1 = psid? (DWORD)&oi.infFile.szFileName : 0;
        fci.dwItem2 = 0;
        fci.dwAttributes = oi.infFile.dwAttributes;
        fci.ftModified = oi.infFile.ftLastChanged;
        fci.nFileSize = oi.infFile.dwLength;
        if (poiOld) {
            fci.dwItem2 = fci.dwItem1;
            fci.dwItem1 = psidOld? (DWORD)&poiOld->infFile.szFileName : 0;
        }

        __try {
            (*pfnShell)(&fci);
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!CallFileSystemFunction(0x%08x,0x%08x): 0x%08x blew up\r\n"), pvol, dwSHCNE, pfnShell));
            return;
        }

        DEBUGMSGW(ZONE_MSGS,(DBGTEXTW("FATFS!%s notified function 0x%08x(0x%08x,\"%s\",\"%s\")\r\n"), pwsCaller, pfnShell, dwSHCNE, fci.dwItem1, fci.dwItem2));
    }
}

#endif  // SHELL_CALLBACK_NOTIFICATION

⌨️ 快捷键说明

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