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

📄 find.c

📁 Windows操作系统中文件系统过滤驱动和设备驱动之间的相似
💻 C
📖 第 1 页 / 共 5 页
字号:
                        }
                        
                        // CloneDirCluster succeeded
                        ASSERT( blkNew == pstmDir->s_pbufCur->b_blk );
    			}
                    
                    /* NOTE: blkNew will now be the blk of the current buffer,
                     * so this loop should only come again if there is
                     * another change in blocks (which there shouldn't be)
                     */
                }
            }
#endif            
            do {
                if( !ISLFNDIRENTRY( pde ))
                    goto lfndone;
                if(( dwError = ModifyStreamBuffer( pstmDir, pde, sizeof( DIRENTRY ))) != ERROR_SUCCESS )
                    goto lfndone;
                pde->de_name[ 0 ] = DIRFREE;

                // TEST_BREAK
                PWR_BREAK_NOTIFY(24);            
                
            } while( pdi->di_posLFN += sizeof( DIRENTRY ), ++pde < pdeEnd );
        }
       lfndone:
        ;
    }


    dwError = WriteAndReleaseStreamBuffers(pstmDir);

#ifdef TFAT
    // WriteAndReleaseStreamBuffers may not commit buffer if file is not write-through
    if (pvol->v_fTfat) {
        CommitStreamBuffers (pstmDir);
    }
#endif

    // Now kill all the cluster entries associated with this file.
    // We enter the FAT's critical section even though we're just freeing
    // clusters, because in the process, we could alter the FAT stream's
    // current buffer, and that could mess up someone else accessing the FAT.

    if (dwError == ERROR_SUCCESS && pdi->di_clusEntry != UNKNOWN_CLUSTER) {
        DWORD dwData = FREE_CLUSTER;

#ifdef DEBUG
#ifdef FATUI
        if (ZONE_PROMPTS) {
            int i;
            FATUIDATA fui;
            fui.dwSize = sizeof(fui);
            fui.dwFlags = FATUI_YES | FATUI_NO | FATUI_CANCEL | FATUI_DEBUGMESSAGE;
            fui.idsEvent = (UINT)TEXTW("Preparing to delete clusters for '%1!.11hs!'.\r\n\r\nSelect Yes to delete, No to mark bad, or Cancel to leave allocated.");
            fui.idsEventCaption = IDS_FATUI_WARNING;
            fui.cuiParams = 1;
            fui.auiParams[0].dwType = UIPARAM_VALUE;
            fui.auiParams[0].dwValue = (DWORD)achName;

            i = FATUIEvent(hFATFS, pvol->v_pwsHostRoot+1, &fui);
            if (i == FATUI_CANCEL)
                goto exit;
            if (i == FATUI_NO)
                dwData = FAT32_BAD;
        }
#endif                
#endif

#ifdef TFAT
        if (!pvol->v_fTfat)
#endif                
        {
            while (pdi->di_clusEntry >= DATA_CLUSTER && !ISEOF(pvol, pdi->di_clusEntry)) {
                FreeClustersOnDisk(pvol, pdi->di_clusEntry, 1);
                if (dwError = PACK(pvol, pdi->di_clusEntry, dwData, &pdi->di_clusEntry))
                    break;
            }
        }
#ifdef TFAT
        if (pvol->v_fTfat)
        // TFAT - don't delete the cluster, freeze it instead
        {
            DWORD clusFirst = NO_CLUSTER, clusNext = pdi->di_clusEntry, clusEnd;

            // Get the last cluster in the chain
            dwError = ERROR_SUCCESS;
            while (!dwError && clusNext >= DATA_CLUSTER && !ISEOF(pvol, clusNext)) 
            {
                if (NO_CLUSTER == clusFirst)
                    clusFirst = clusNext;

                clusEnd = clusNext;

                // get next cluster
                dwError = UNPACK( pvol, clusNext, &clusNext);
            }

            if (NO_CLUSTER != clusFirst){
                FreezeClusters (pvol, clusFirst, clusEnd);
            }
        }
#endif

        WriteAndReleaseStreamBuffers(pvol->v_pstmFAT);
        
    }

exit:
    UnlockFAT(pvol);    
    return dwError;
}


/*  FindFirst - find the directory stream containing the specified file
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *      pwsPath - pointer to pathname
 *      psh - pointer to SHANDLE (required)
 *      pdi - pointer to DIRINFO (optional, NULL if not needed)
 *      pfd - pointer to WIN32_FIND_DATAW structure (required)
 *      flName - zero or more NAME_* flags (eg, NAME_FILE, NAME_DIR)
 *      clusFail - cluster of stream not allowed in path
 *      (normally, this is UNKNOWN_CLUSTER, to perform unrestricted opens)
 *
 *      Additionally, psh->sh_flags must be set appropriately.  At a minimum,
 *      it must contain SHF_BYNAME, but can also contain SHF_WILD, SHF_DOTDOT,
 *      and SHF_CREATE.
 *
 *  EXIT
 *      If successful, it will return the attributes of the file from
 *      the file's DIRENTRY, and if a pdi was supplied, it will be filled
 *      in and current stream buffer left held.
 *
 *      If not successful, the attributes will be set to INVALID_ATTR,
 *      and the current stream buffer will not held.
 *
 *      Finally, if the stream didn't exist, or no pdi was supplied, no
 *      stream will be returned.  Otherwise, the directory stream containing
 *      the specified file will be returned.
 */

PDSTREAM FindFirst(PVOLUME pvol, PCWSTR pwsPath, PSHANDLE psh, PDIRINFO pdi, PWIN32_FIND_DATAW pfd, int flName, DWORD clusFail)
{
    PWSTR pwsName;
    DWORD len;
    DWORD dwError = ERROR_SUCCESS;

    psh->sh_pstm = NULL;

    __try {
        pfd->dwFileAttributes = INVALID_ATTR;

        psh->sh_pstm = OpenPath(pvol, pwsPath, &pwsName, &len, flName, clusFail);
        if (psh->sh_pstm == NULL) {
            if (ERROR_ALREADY_EXISTS == GetLastError()) {
                SetLastError(ERROR_PATH_NOT_FOUND);
            }
            goto exit;
        }

        if (len == 0) {

            // The caller must be trying to find '\\'.  That's normally
            // a no-no.  FAT_FindFirstFileW makes an exception, but it makes
            // no sense internally, because the root is never contained by
            // another directory stream.

            dwError = ERROR_FILE_NOT_FOUND;
            goto exit;
        }

        psh->sh_pos = 0;
        psh->sh_cwPattern = (WORD)len;
        memcpy(psh->sh_awcPattern, pwsName, len*sizeof(WCHAR));
        psh->sh_awcPattern[len] = 0;
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        dwError = ERROR_INVALID_PARAMETER;
        goto exit;
    }

    dwError = FindNext(psh, pdi, pfd);

  exit:
    if (dwError == ERROR_FILE_NOT_FOUND && (flName & (NAME_FILE|NAME_DIR)) == NAME_DIR)
        dwError = ERROR_PATH_NOT_FOUND;

    if (dwError)
        SetLastError(dwError);

    if (!pdi) {
        if (psh->sh_pstm) {
            CloseStream(psh->sh_pstm);
            psh->sh_pstm = NULL;
        }
    }
    return psh->sh_pstm;
}


/*  MatchNext - worker for FindNext
 *
 *  ENTRY
 *      psh - pointer to SHANDLE structure
 *      len - length of current name
 *      pws - pointer to current name
 *      pde - pointer to DIRENTRY to read from if match
 *
 *  EXIT
 *      TRUE if (another) file was found, FALSE if not
 */

__inline BOOL MatchNext(PSHANDLE psh, PWSTR pws, int len, PDIRENTRY pde)
{
    int fMask = psh->sh_flags & SHF_BYMASK;

    // Check the match criteria, and then check for that kind of match

    ASSERT(fMask);              // make sure flags are set to something

    if (psh->sh_pstm->s_cwPath + max(3,psh->sh_pstm->s_pvol->v_cwsHostRoot) + len + 2 > MAX_PATH)
        return FALSE;

    if (len > MAX_PATH)
        return FALSE;

    return(
        fMask == SHF_BYNAME &&
        MatchesWildcardMask(psh->sh_cwPattern, psh->sh_awcPattern, len, pws)
      ||
        fMask == SHF_BYORD &&
        (DWORD)(psh->sh_h) == psh->sh_pos/sizeof(DIRENTRY)
      ||
        fMask == SHF_BYCLUS &&
        (DWORD)(psh->sh_h) == GETDIRENTRYCLUSTER(psh->sh_pstm->s_pvol, pde)
    );
}


/*  CopyTimes - worker for FindNext
 *
 *  ENTRY
 *      pfd - pointer to WIN32_FIND_DATAW structure
 *      pde - pointer to DIRENTRY containing timestamps to transfer
 *
 *  EXIT
 *      None
 */

__inline void CopyTimes(PWIN32_FIND_DATAW pfd, PDIRENTRY pde)
{
    // DOSTimeToFileTime can fail because it doesn't range-check any of
    // the date/time values in the directory entry;  it just pulls them apart
    // and calls SystemTimeToFileTime, which won't initialize the FILETIME
    // structure if there's an error.  So we preset all the FILETIMEs to zero,
    // because that's what the Win32 API dictates when a time is unknown/not
    // supported.

    memset(&pfd->ftCreationTime, 0, sizeof(pfd->ftCreationTime) +
                                    sizeof(pfd->ftLastAccessTime) +
                                    sizeof(pfd->ftLastWriteTime));

    DOSTimeToFileTime(pde->de_createdDate,
                      pde->de_createdTime,
                      pde->de_createdTimeMsec, &pfd->ftCreationTime);

    DOSTimeToFileTime(pde->de_date, pde->de_time, 0, &pfd->ftLastWriteTime);

    DOSTimeToFileTime(pde->de_lastAccessDate, 0, 0, &pfd->ftLastAccessTime);
}


/*  FindNext - worker for FindFirstFileW, FindNextFileW, etc.
 *
 *  Callers need to supply a WIN32_FIND_DATAW structure even if they're
 *  not interested in "find data".  This is because the search may involve
 *  comparisons against LFN directory entries, which have to be built a piece
 *  at a time, and a wildcard comparison cannot be performed until the entire
 *  name has been built.  NON-wildcard searches can perform their comparisons
 *  a piece at a time, and don't necessarily need the MAX_PATH buffer that
 *  WIN32_FIND_DATAW provides us, but using the same buffer strategy in both
 *  cases yields better code.
 *
 *  ENTRY
 *      psh - pointer to SHANDLE structure
 *      pdi - pointer to DIRINFO (optional, NULL if not needed)
 *      pfd - pointer to user's WIN32_FIND_DATAW structure (required)
 *
 *  EXIT
 *      0 if successful, error code if not
 *
 *  On success, most of the fields in the WIN32_FIND_DATAW structure are filled
 *  in (eg, dwFileAttributes, nFileSizeHigh, nFileSizeLow, cFileName, and some
 *  CE-specific fields like dwOID).  Some are only filled in depending on the
 *  type of search however, like all the FILETIME fields (eg, ftCreationTime,
 *  ftLastAccessTime, ftLastWriteTime).  For example, SHF_BYCLUS searches, which
 *  are only used and supported internally, don't care about those fields, so we
 *  don't waste time filling them in.
 */

DWORD FindNext(PSHANDLE psh, PDIRINFO pdi, PWIN32_FIND_DATAW pfd)
{

    PDIRENTRY pdeEnd;           // ptr to ending directory entry
    BYTE chksum;                // LFN entry checksum of 8.3 name
    int seqLFN = -1;            // next LFN DIRENTRY seq # expected
    PCWSTR pwsComp;
    PWSTR pwsBuff;
    BOOL fComp = FALSE;
    DIRINFO di;
    DWORD dwError = ERROR_SUCCESS;
    PDSTREAM pstmDir = psh->sh_pstm;
    PDWORD pdwShortNameBitArray = NULL;

    ERRFALSE(sizeof(pfd->cFileName) >= sizeof(WCHAR [LDE_NAME_LEN*LN_MAX_ORD_NUM]));
    ASSERT(pstmDir);
    ASSERT(psh->sh_flags);      // make sure flags are set to something

    ASSERT(OWNCRITICALSECTION(&pstmDir->s_cs));

    memset(&di, 0, sizeof(DIRINFO));

    di.di_pos = psh->sh_pos;
    di.di_posLFN = INVALID_POS;
    di.di_clusEntry = UNKNOWN_CLUSTER;
    di.di_cdeNeed = -1;

    if (psh->sh_pos == INVALID_POS) {
        dwError = ERROR_FILE_NOT_FOUND;
        goto norelease;
    }

    if ((psh->sh_flags & SHF_BYMASK) == SHF_BYNAME) {

        di.di_cdeNeed = UniToOEMName(psh->sh_pstm->s_pvol, di.di_achOEM, psh->sh_awcPattern, psh->sh_cwPattern, psh->sh_pstm->s_pvol->v_nCodePage);

        // If the name is invalid (-2), or contains wildcards when wildcards
        // are not allowed, fail immediately.

        if (di.di_cdeNeed == -2 || di.di_cdeNeed == -1 && !(psh->sh_flags & SHF_WILD)) {
            dwError = ERROR_INVALID_NAME;
            goto norelease;
        }

        // If the name is OEM, then force the CREATE flag off.  Otherwise,
        // we'll leave the flag on if the caller turned it on (meaning he
        // wants us to check every normal DIRENTRY for a collision with the
        // short name in achOEM and set it to some name that doesn't conflict).

        if (di.di_cdeNeed >= 1) {

            di.di_flags |= DIRINFO_OEM;
            di.di_chksum = ChkSumName(di.di_achOEM);

            if (di.di_cdeNeed == 1) {
                psh->sh_flags &= ~SHF_CREATE;
            }

            // If the name fits in achOEM but contains lower-case, then cdeNeed
            // is already correct (2), but cwTail and pwsTail still need to be set.

            else if (di.di_cdeNeed == 2) {
                di.di_cwTail = psh->sh_cwPattern;
                di.di_pwsTail = psh->sh_awcPattern;
            }

            // If there's some uncertainty about the charset mapping, then revert to

⌨️ 快捷键说明

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