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

📄 find.c

📁 Windows操作系统中文件系统过滤驱动和设备驱动之间的相似
💻 C
📖 第 1 页 / 共 5 页
字号:
            // the UNICODE case.

            else {
                ASSERT(di.di_cdeNeed == 3);
                di.di_cdeNeed = 0;
            }
        }

        // If the name is UNICODE (0), then cdeNeed needs to be recomputed,
        // based on the length of the UNICODE name.  Furthermore, unlike the
        // wildcard case, we will be able to compare it piece by piece.
        // pwsTail points to the end-most piece to compare, and cwTail is its
        // length.

        if (di.di_cdeNeed == 0) {
            fComp = TRUE;
            di.di_pwsTail = psh->sh_awcPattern + psh->sh_cwPattern;
            di.di_cdeNeed = ((psh->sh_cwPattern+LDE_NAME_LEN-1)/LDE_NAME_LEN) + 1;
            if ((di.di_cwTail = psh->sh_cwPattern % LDE_NAME_LEN) == 0)
                di.di_cwTail = LDE_NAME_LEN;
            di.di_pwsTail -= di.di_cwTail;
        }

        // Also record the complete length of the name.  If we actually
        // find a match, we will update this field again (since the match
        // might have been based on a short name and we always return
        // long names), but if we don't find a match, this still needs to
        // be set in case the caller wants to create it (via CreateName).

        di.di_cwName = psh->sh_cwPattern;
    }

    // Create a short name conflict bit array if the caller may need
    // to create a new LFN entry.  We must add 1 to MAX_SHORT_NAMES because
    // the set of addressible bits in the array starts with bit 0.

    if (psh->sh_flags & SHF_CREATE) {
        DWORD cb = (((MAX_SHORT_NAMES+1)+31)/32 + 2)*sizeof(DWORD);     
        InitNumericTail(&di);
        // CreateBitArray(pdwShortNameBitArray, MAX_SHORT_NAMES+1);
        if (cb > 2*sizeof(DWORD)) {                         
            pdwShortNameBitArray = (PDWORD)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, cb);
        }                                                   
        if (pdwShortNameBitArray) {                                  
            pdwShortNameBitArray[0] = MAX_SHORT_NAMES+1;                       
        }                                                   
        
    }

    while (!dwError) {

        dwError = ReadStream(pstmDir, di.di_pos, &di.di_pde, &pdeEnd);
        if (dwError) {
            if (dwError == ERROR_HANDLE_EOF) {
                if (di.di_pos == 0) {
                    DEBUGMSG(ZONE_ERRORS,(TEXT("FATFS!FindNext: 0-length directory???\r\n")));
                    dwError = ERROR_INVALID_DATA;
                }
                else
                    dwError = ERROR_FILE_NOT_FOUND;
            }
            else
                DEBUGMSG(ZONE_ERRORS,(TEXT("FATFS!FindNext: unexpected error (%d)\r\n"), dwError));
            di.di_posLFN = INVALID_POS;
            break;
        }

        // Let's do a little more error-checking before we dive in;  in particular,
        // if this is not a root directory, then it must have "dot" and "dotdot" entries
        // at the top, else the directory is corrupt.

        if (!ISROOTDIR(pstmDir) && di.di_pos == 0 && di.di_pde+1 < pdeEnd) {

            DWORD dwClus;

            if (*(PDWORD)di.di_pde->de_name != 0x2020202e ||
                *(PDWORD)(di.di_pde+1)->de_name != 0x20202e2e) {
                DEBUGMSG(ZONE_ERRORS,(TEXT("FATFS!FindNext: bogus directory!\r\n")));
                dwError = ERROR_INVALID_DATA;
                break;
            }

            // NOTE: I'm reserving ERROR_FILE_CORRUPT to indicate "correctable" directory
            // errors.  All the caller has to do is plug in correct cluster values.  See the
            // code in SCAN.C for more details.

            dwClus = GETDIRENTRYCLUSTER(pstmDir->s_pvol, di.di_pde);
            if (dwClus != pstmDir->s_clusFirst) {
                DEBUGMSG(ZONE_ERRORS,(TEXT("FATFS!FindNext: bogus '.' cluster (0x%08x instead of 0x%08x)\r\n"), dwClus, pstmDir->s_clusFirst));
                dwError = ERROR_FILE_CORRUPT;
                break;
            }

            dwClus = GETDIRENTRYCLUSTER(pstmDir->s_pvol, di.di_pde+1);
            if (!ISPARENTROOTDIR(pstmDir) || dwClus != NO_CLUSTER) {
                if (pstmDir->s_sid.sid_clusDir >= DATA_CLUSTER &&
                    pstmDir->s_sid.sid_clusDir != UNKNOWN_CLUSTER && dwClus != pstmDir->s_sid.sid_clusDir) {
                    DEBUGMSG(ZONE_ERRORS,(TEXT("FATFS!FindNext: bogus '..' cluster (0x%08x instead of 0x%08x)\r\n"), dwClus, pstmDir->s_sid.sid_clusDir));
                    dwError = ERROR_FILE_CORRUPT;
                    break;
                }
            }
        }

      __try {

        do {
            // Check for a deleted entry.

            if (di.di_pde->de_name[0] == DIRFREE) {

                // Deleted file entry.  If this is the first one,
                // remember its location.

                if (di.di_cdeFree < di.di_cdeNeed && di.di_cdeFree++ == 0)
                    di.di_posFree = di.di_pos;

                // Reset LFN sequence/position info
                goto resetlfn;
            }

            // Check for an ending entry.

            if (di.di_pde->de_name[0] == DIREND) {

                // Empty file entry.  If this is the first one,
                // remember its location.

                if (di.di_cdeFree < di.di_cdeNeed && di.di_cdeFree++ == 0)
                    di.di_posFree = di.di_pos;

                di.di_posLFN = INVALID_POS;
                dwError = ERROR_FILE_NOT_FOUND;
                goto release;
            }

            // Check for an LFN entry.

            if (ISLFNDIRENTRY(di.di_pde)) {

                int cwComp = LDE_NAME_LEN;
                PLFNDIRENTRY plde = (PLFNDIRENTRY)di.di_pde;
                int cbName3 = sizeof(plde->lde_name3);

                // If lde_flags is not zero, our assumption must be that
                // this is some new kind of LFN entry that we don't fully
                // understand, and must therefore ignore....

                if (plde->lde_flags != 0)
                    goto resetall;

                // Initialization code for initial LFN entry

                if (plde->lde_ord & LN_ORD_LAST_MASK) {

                    seqLFN = plde->lde_ord & ~LN_ORD_LAST_MASK;

                    if (seqLFN > LN_MAX_ORD_NUM) {

                        // This LFN sequence has TOO MANY entries, which also
                        // means it won't fit in a MAX_PATH buffer.  We could
                        // treat the sequence like orphaned LFN entries, but
                        // that seems a rather risky proposition, since we may be
                        // talking directory corruption here.  Safer to just ignore
                        // them and rely on SCANDSKW to fix things up. -JTP
                        goto resetall;
                    }

                    if (!(di.di_flags & DIRINFO_OEM) && di.di_cdeNeed > 1 && seqLFN != di.di_cdeNeed-1) {

                        // Optimization: this LFN sequence does not have the requisite
                        // number of entries, so it can't possibly be a match.
                        goto resetall;
                    }

                    chksum = plde->lde_chksum;

                    // If this LFN sequence has the wrong OEM chksum, it might simply
                    // be due to charset differences between the system where the OEM name
                    // was originally created and the current system, so unlike previous
                    // releases, we will no longer bail out and 'goto resetall';  we will
                    // instead continue to collect all the LFN chunks and do the full name
                    // comparison.  In other words, we are no longer dependent on the
                    // accuracy of the OEM version of the name (as computed by UniToOEMName). -JTP

                    DEBUGMSGW(di.di_cdeNeed == 1 && chksum != di.di_chksum && ZONE_APIS && ZONE_ERRORS,(DBGTEXTW("FATFS!FindNext: lfn chksum (%x) doesn't match OEM chksum (%x) for '%.11hs'\r\n"), chksum, di.di_chksum, di.di_achOEM));

                    // Remember this LFN's starting position
                    di.di_posLFN = di.di_pos;

                    cwComp = di.di_cwTail;
                    pwsComp = di.di_pwsTail;
                    pwsBuff = &pfd->cFileName[LDE_NAME_LEN*LN_MAX_ORD_NUM];
                    *--pwsBuff = 0;     // guarantee a NULL-terminator

                    // If this LFN contains the max number of LFNDIRENTRYs,
                    // we have to scoot pwsBuff up one WCHAR and reduce the
                    // amount of the final memcpy (of lde_name3) by one WCHAR,
                    // to insure that the NULL-terminator above is preserved.

                    if (seqLFN == LN_MAX_ORD_NUM) {
                        pwsBuff++;
                        cbName3 -= sizeof(WCHAR);
                    }
                }

                // Skip LFN entries we're not interested in

                else if (seqLFN == -1) {
                    goto resetall;
                }

                // Recover LFN entries that are inconsistent

                else if (seqLFN != plde->lde_ord || chksum != plde->lde_chksum) {

                    // All preceding LFN entries are deemed bogus/recoverable.
                    // If they can be merged with the free count, do it, otherwise
                    // leave them recorded as unrecoverable.

                    DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!FindNext: LFN sequence (0x%x vs. 0x%x) or LFN chksum (0x%x vs. 0x%x) error\n"), seqLFN, plde->lde_ord, chksum, plde->lde_chksum));

                    di.di_posOrphan = di.di_posLFN;
                    di.di_cdeOrphan = (di.di_pos - di.di_posLFN)/sizeof(LFNDIRENTRY);

                    if (di.di_posFree + di.di_cdeFree * sizeof(LFNDIRENTRY) == di.di_posLFN) {
                        di.di_cdeFree += di.di_cdeOrphan;
                        di.di_cdeOrphan = 0;
                    }
                    goto resetall;
                }

                if (di.di_cdeFree < di.di_cdeNeed)
                    di.di_cdeFree = 0;

                // LFN directory entry in sequence. Copy the name entry by
                // entry into a scratch buffer to be matched when all of the
                // entries in the name have been processed.

                pwsBuff -= LDE_NAME_LEN;
                memcpy(pwsBuff, plde->lde_name1, sizeof(plde->lde_name1));
                memcpy(pwsBuff+LDE_LEN1, plde->lde_name2, sizeof(plde->lde_name2));
                memcpy(pwsBuff+LDE_LEN1+LDE_LEN2, plde->lde_name3, cbName3);

                // If we can compare individual pieces, do it now

                if (fComp) {

                    // We perform a quick comparison on the first
                    // character past the end of the LFN (if one exists)
                    // and if that character isn't a NULL, then this
                    // entry isn't a match;  otherwise, compare entire piece.

                    if (cwComp != LDE_NAME_LEN && pwsBuff[cwComp] != 0 ||
                        _wcsnicmp(pwsBuff, pwsComp, cwComp) != 0) {
                        goto resetlfn;
                    }
                    pwsComp -= LDE_NAME_LEN;
                }

                --seqLFN;
                continue;
            }

#ifdef TFAT
            // As an optimization for TFAT, if the first cluster in the directory contains
            // a volume label, then we can skip this cluster because the entire cluster is
            // filled with volume labels.
            
            if (pstmDir->s_pvol->v_fTfat && ((di.di_pde->de_attr & ATTR_DIR_MASK) == ATTR_VOLUME_ID) && 
                (di.di_pos < pstmDir->s_pvol->v_cbClus) && (di.di_cdeFree == 0) && (di.di_posLFN == INVALID_POS))
            {
                // Set the position a cluster into the directory and ReadStream again.
                di.di_pos = pstmDir->s_pvol->v_cbClus;
                break;
            }
#endif

            // Check for a "normal" directory entry.

            if ((di.di_pde->de_attr & ATTR_DIR_MASK) != ATTR_VOLUME_ID) {

                int len;

                
                if (!(psh->sh_flags & SHF_DOTDOT) &&
                    (*(PDWORD)di.di_pde->de_name == 0x2020202e ||
                     *(PDWORD)di.di_pde->de_name == 0x20202e2e)) {
                    goto resetall;
                }

                // Normal directory entry.  If preceeding LFN
                // directory entries matched, handle this entry
                // as a match.  Otherwise, if the name is 8.3
                // compatible, then try to match the 8.3 OEM name
                // contained in this entry.

                if (seqLFN == 0) {

                    if (chksum == ChkSumName(di.di_pde->de_name)) {

                        len = wcslen(pwsBuff);

                        // We processed all the LFN chunks for the current entry,
                        // (since seqLFN is now 0), so if fComp is TRUE, that means
                        // we compared every chunk as we went, and they must have
                        // all matched, so let's just 'goto match'

                        if (fComp)
                            goto match;

                        // If cdeNeed == -1, we're dealing with wildcards *or* a
                        // a non-name-based search, so we have to explicitly check
                        // for a match.

                        if (di.di_cdeNeed == -1)
                            goto checkmatch;

                        // Well, we must be performing a name-based search, and since
                        // we didn't compare the LFN chunks as we went, we did at least
                        // collect them all in pwsBuff, so let's see if the full LFN
                        // matches....
                        //
                        // Note: we didn't *always* used to do this, which meant that we
                        // always fell into the "normal directory entry" case below, which
                        // which only compared the OEM forms of the filenames;  normally,
                        // that was sufficient, but in cases where the OEM name was created
                        // on a system with different charset mappings, that comparison could
                        // fail.  We should rely on the 8.3 OEM name IFF there are no LFN
                        // entries -- and in this case, there *is*.... -JTP

                        if (len == psh->sh_cwPattern && _wcsnicmp(pwsBuff, psh->sh_awcPattern, len) == 0)
                            goto match;
                    }
                    else {

                        // All preceding LFN entries are deemed bogus/recoverable.
                        // If they can be merged with the free count, do it, otherwise
                        // leave them recorded as unrecoverable.

                        DEBUGMSG(ZONE_ERRORS,(DBGTEXT("FATFS!FindNext: LFN chksum (0x%x vs. 0x%x) error\n"), chksum, ChkSumName(di.di_pde->de_name)));

                        di.di_posOrphan = di.di_posLFN;
                        di.di_cdeOrphan = (di.di_pos - di.di_posLFN)/sizeof(LFNDIRENTRY);

                        if (di.di_posFree + di.di_cdeFree * sizeof(LFNDIRENTRY) != di.di_posLFN) {
                            di.di_cdeFree = 0;
                        } else {
                            di.di_cdeFree += di.di_cdeOrphan;
                            di.di_cdeOrphan = 0;
                        }

                        // We used to bail at this point (goto checkshort), but the right
                        // thing to do is just treat the current DIRENTRY as a short-name only.
                        seqLFN = -1;
                    }
                }

                // Normal directory entry, and either there were no preceding LFN
                // entries, or there were but we couldn't make use of them.

                if (di.di_cdeNeed == -1 ||
                    (di.di_flags & DIRINFO_OEM) &&
                    memcmp(di.di_pde->de_name,
                           di.di_achOEM,
                           sizeof(di.di_pde

⌨️ 快捷键说明

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