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

📄 path.c

📁 Windows操作系统中文件系统过滤驱动和设备驱动之间的相似
💻 C
📖 第 1 页 / 共 4 页
字号:
 *  EXIT
 *      Attributes of file/subdirectory if it exists, 0xFFFFFFFF if it
 *      does not (call GetLastError for error code).
 */

DWORD FAT_GetFileAttributesW(PVOLUME pvol, PCWSTR pwsFileName)
{
    SHANDLE sh;
    WIN32_FIND_DATAW fd;
    WCHAR   wsFName[MAX_PATH+1];

    DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_GetFileAttributesW(%d chars: %s)\r\n"), wcslen(pwsFileName), pwsFileName));

    if (!FATEnter(NULL, LOGID_NONE))
        return INVALID_ATTR;

    if (pvol->v_flags & (VOLF_INVALID | VOLF_UNMOUNTED | VOLF_FROZEN | VOLF_WRITELOCKED)) {
        SetLastError(ERROR_ACCESS_DENIED);
        FATExit(pvol, LOGID_NONE);
        DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_GetFileAttributesW(%-.64s) returned 0x%x (%d)\r\n"), pwsFileName, INVALID_ATTR, ERROR_ACCESS_DENIED));
        return INVALID_ATTR;
    }

    // FindFirst will call SetLastError appropriately, so
    // all we have to do is bail if it doesn't return a stream.

    wcsncpy (wsFName, pwsFileName, MAX_PATH);
    wsFName[MAX_PATH] = TEXT('\0'); // Ensure null
    // Desktop will remove trailing '\' && '/'
    while (wcslen(wsFName) && ((wsFName[wcslen(wsFName)-1] == TEXT('\\')) ||
                               (wsFName[wcslen(wsFName)-1] == TEXT('/')))) {
        // Trim trailing slash
        wsFName[wcslen(wsFName)-1] = TEXT('\0');
    }

    sh.sh_flags = SHF_BYNAME;
    FindFirst(pvol, wsFName, &sh, NULL, &fd, NAME_FILE | NAME_DIR, UNKNOWN_CLUSTER);

    FATExit(pvol, LOGID_NONE);

    DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_GetFileAttributesW(%-.64s) returned 0x%x (%d)\r\n"), pwsFileName, fd.dwFileAttributes, fd.dwFileAttributes != INVALID_ATTR? 0 : GetLastError()));

    return fd.dwFileAttributes;
}


/*  FAT_SetFileAttributesW - Set file/subdirectory attributes
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *      pwsFileName - pointer to name of existing file/subdirectory
 *      dwAttributes - new attributes for file/subdirectory
 *
 *  EXIT
 *      TRUE if successful, FALSE if not (call GetLastError for error code)
 */

BOOL FAT_SetFileAttributesW(PVOLUME pvol, PCWSTR pwsFileName, DWORD dwAttributes)
{
    PDSTREAM pstmDir;
    SHANDLE sh;
    DIRINFO di;
    DWORD dw, dwError = ERROR_SUCCESS;
    WIN32_FIND_DATAW fd;
    DWORD dwSHCNE = 0;
    DSID sidParent;

    DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_SetFileAttributesW(0x%x,%d chars: %s)\r\n"), dwAttributes, wcslen(pwsFileName), pwsFileName));

    // NOTE: Even though this call modifies the volume, it never has any impact
    // on file system integrity, so we don't waste time logging it (ie, LOGID_NONE).

    if (!FATEnter(NULL, LOGID_NONE))
        return FALSE;

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

    if (pvol->v_flags & VOLF_READONLY) {
        dwError = ERROR_WRITE_PROTECT;
        goto error;
    }

    // FindFirst will call SetLastError appropriately, so
    // all we have to do is bail if it doesn't return a stream.

    sh.sh_flags = SHF_BYNAME;

    pstmDir = FindFirst(pvol, pwsFileName, &sh, &di, &fd, NAME_FILE | NAME_DIR, UNKNOWN_CLUSTER);
    if (!pstmDir) {
        FATExit(pvol, LOGID_NONE);
        DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_SetFileAttributesW(%-.64s) returned FALSE (%d)\r\n"), pwsFileName, GetLastError()));
        return FALSE;
    }

    // If FindFirst was successful...

    if (fd.dwFileAttributes != INVALID_ATTR) {

        // Clear any bits that are not changable
        dwAttributes &= ATTR_CHANGEABLE;

        // NOTE: We pass 0 for the size instead of sizeof(DIRENTRY) to disable logging
        // of this modification, since we are not logging these particular calls (by virtue
        // of LOGID_NONE above).

        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
            dwAttributes |= FILE_ATTRIBUTE_DIRECTORY;
        }

#ifdef TFAT
    if (pvol->v_fTfat && (pvol->v_flFATFS & FATFS_TFAT_NONATOMIC_SECTOR)) {
        // we need to clone the current buffer
        // before we make any modifications!
        LockFAT(pvol);
        
        if (CLONE_CLUSTER_COMPLETE == CloneDirCluster( pvol, pstmDir, pstmDir->s_pbufCur->b_blk, NULL ))
        {
            // The current buffer might be changed in CloneDirCluster
            // update plde to with the new buffer
            dwError = ReadStream( pstmDir, di.di_pos, &di.di_pde, NULL);
        }
    }
#endif

        if (!dwError)
            dwError = ModifyStreamBuffer(pstmDir, di.di_pde, 0);
        if (!dwError)
            di.di_pde->de_attr = (BYTE)dwAttributes;

        dwSHCNE = SHCNE_UPDATEITEM;
        memcpy (&sidParent, &pstmDir->s_sid, sizeof(DSID));

#ifdef TFAT
    if (pvol->v_fTfat && (pvol->v_flFATFS & FATFS_TFAT_NONATOMIC_SECTOR)) {
        if (!dwError)
            dwError = CommitStreamBuffers (pstmDir);
        if (!dwError)
            dwError = CommitTransactions (pvol);
        UnlockFAT(pvol);
    }
#endif
        
    }


    dw = CloseStream(pstmDir);
    if (!dwError)
        dwError = dw;

    if (dwSHCNE)
        FILESYSTEMNOTIFICATION(pvol, DB_CEOID_CHANGED, 0, dwSHCNE, &di.di_sid, &sidParent, NULL, NULL, NULL, DBGTEXTW("FAT_SetFileAttributesW"));


    if (dwError) {
      error:
        SetLastError(dwError);
    }

    FATExit(pvol, LOGID_NONE);

    DEBUGMSGW(ZONE_APIS || ZONE_ERRORS && dwError,(DBGTEXTW("FATFS!FAT_SetFileAttributesW(0x%x,%-.64s) returned 0x%x (%d)\r\n"), dwAttributes, pwsFileName, dwError == ERROR_SUCCESS, dwError));

    return dwError == ERROR_SUCCESS;
}


/*  FAT_DeleteFileW - Delete file
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *      pwsFileName - pointer to name of existing file
 *
 *  EXIT
 *      TRUE if successful, FALSE if not (call GetLastError for error code)
 *
 *  NOTES
 *      A file marked FILE_ATTRIBUTE_READONLY cannot be deleted.  You have to
 *      remove that attribute first, with SetFileAttributes.
 *
 *      An open file cannot be deleted.  All open handles must be closed first.
 *
 *      A subdirectory cannot be deleted with this call either.  You have to
 *      use RemoveDirectory instead.
 */

BOOL FAT_DeleteFileW(PVOLUME pvol, PCWSTR pwsFileName)
{
    PDSTREAM pstmDir;
    SHANDLE sh;
    DIRINFO di;
    WIN32_FIND_DATAW fd;
    DWORD dwError = ERROR_SUCCESS;
#ifdef SHELL_CALLBACK_NOTIFICATION
    CEOIDINFO oiOld;
#endif
    DSID sidParent;

    DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_DeleteFileW(%d chars: %s)\r\n"), wcslen(pwsFileName), pwsFileName));

    if (!FATEnter(pvol, LOGID_DELETEFILE))
        return FALSE;

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

    if (pvol->v_flags & VOLF_READONLY) {
        dwError = ERROR_WRITE_PROTECT;
        goto error;
    }

    // FindFirst will call SetLastError appropriately, so
    // all we have to do is bail if it doesn't return a stream.

    sh.sh_flags = SHF_BYNAME;
    pstmDir = FindFirst(pvol, pwsFileName, &sh, &di, &fd, NAME_FILE, UNKNOWN_CLUSTER);
    if (!pstmDir) {
        FATExit(pvol, LOGID_DELETEFILE);
        DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_DeleteFileW(%-.64s) returned FALSE (%d)\r\n"), pwsFileName, GetLastError()));
        return FALSE;
    }

    // If the source file doesn't exist, fail

    if (fd.dwFileAttributes == INVALID_ATTR) {
        CloseStream(pstmDir);
        FATExit(pvol, LOGID_DELETEFILE);
        DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_DeleteFileW(%-.64s) returned FALSE (%d)\r\n"), pwsFileName, GetLastError()));
        return FALSE;
    }

    // If the source file is R/O or a directory, fail
    //
    // NOTE: Win95 reports ERROR_FILE_NOT_FOUND if the name is an existing
    // directory, whereas NT reports ERROR_ACCESS_DENIED.  I find the latter
    // to be more sensible. -JTP

    if (fd.dwFileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY)) {
        dwError = ERROR_ACCESS_DENIED;
        goto exit;
    }

    // If the source file has any open handles, fail

    if (CheckStreamHandles(pstmDir->s_pvol, &di.di_sid)) {
        dwError = ERROR_SHARING_VIOLATION;
        goto exit;
    }

    // Retrieve the fully-qualified pathname of the source, in case we need
    // it for the FILESYSTEMNOTIFICATION at the end of the function.  We have to
    // do the wacky buffer holding/unholding because pstmDir's current buffer is
    // in a known state, and we can't tolerate GetSIDInfo mucking that state up.

#ifdef SHELL_CALLBACK_NOTIFICATION
    if (pfnShell && ZONE_SHELLMSGS) {
        PBUF pbuf = pstmDir->s_pbufCur;
        HoldBuffer(pbuf);
        GetSIDInfo(pvol, &di.di_sid, &oiOld);
        ReleaseStreamBuffer(pstmDir, FALSE);
        AssignStreamBuffer(pstmDir, pbuf, FALSE);
        UnholdBuffer(pbuf);
    }
#endif

    dwError = DestroyName(pstmDir, &di);
    // TEST_BREAK
    PWR_BREAK_NOTIFY(31);

    if (!dwError)
        memcpy (&sidParent, &pstmDir->s_sid, sizeof (DSID));

  exit:    
    CloseStream(pstmDir);
    
    if (!dwError)
        FILESYSTEMNOTIFICATION(pvol, 0, DB_CEOID_FILE_DELETED, SHCNE_DELETE, NULL, NULL, &di.di_sid, &sidParent, &oiOld, DBGTEXTW("FAT_DeleteFileW"));

    if (dwError) {
      error:
        SetLastError(dwError);
    }

#ifdef TFAT    
    else if (pvol->v_fTfat)
        dwError = CommitTransactions (pvol);
#endif

    FATExit(pvol, LOGID_DELETEFILE);

    DEBUGMSGW(ZONE_APIS || ZONE_ERRORS && dwError,(DBGTEXTW("FATFS!FAT_DeleteFileW(%-.64s) returned 0x%x (%d)\r\n"), pwsFileName, dwError == ERROR_SUCCESS, dwError));

    return dwError == ERROR_SUCCESS;
}


/*  FAT_MoveFileW
 *
 *  ENTRY
 *      pvol - pointer to VOLUME
 *      pwsOldFileName - pointer to name of existing file
 *      pwsNewFileName - pointer to new name for file
 *
 *  EXIT
 *      TRUE if successful, FALSE if not (call GetLastError for error code)
 *
 *  NOTES
 *      We call FindFirst once to obtain the source directory stream for the
 *      for the existing file, and if it really exists, we call FindFirst
 *      again to obtain the destination directory stream for the new file,
 *      verifying that the new name does NOT exist.  Then we create the new
 *      name and destroy the old.
 *
 *      When moving a directory, we must make sure that our traversal
 *      of the destination path does not cross the source directory, otherwise
 *      we will end up creating a circular directory chain.
 */

BOOL FAT_MoveFileW(PVOLUME pvol, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName)
{
    PBUF pbufSrc;
    BYTE bAttrSrc;
    WIN32_FIND_DATAW fd;
    SHANDLE shSrc, shDst;
    DIRINFO diSrc, diDst;
    PDSTREAM pstmSrc, pstmDst;
    DIRENTRY deClone, *pdeClone;
    DWORD dwError = ERROR_SUCCESS;
    DWORD clusFail = UNKNOWN_CLUSTER;
#ifdef SHELL_CALLBACK_NOTIFICATION
    CEOIDINFO oiOld;
#endif
    DSID sidSrcParent, sidDstParent;


    DEBUGONLY(pdeClone = INVALID_PTR);

    DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_MoveFileW(%d->%d chars: %s->%s)\r\n"), wcslen(pwsOldFileName), wcslen(pwsNewFileName), pwsOldFileName, pwsNewFileName));

    if (!FATEnter(pvol, LOGID_MOVEFILE))
        return FALSE;

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

    if (pvol->v_flags & VOLF_READONLY) {
        dwError = ERROR_WRITE_PROTECT;
        goto error;
    }

    // We add an explicit call to OpenRoot because this function performs
    // two path traversals starting at the root, with a lock on the source
    // directory while it traverses the destination.  So if another thread
    // tried to open a file in that source directory at the same time, it would
    // block waiting for MoveFile to finish, but MoveFile couldn't finish if
    // the other thread currently had a stream open in MoveFile's destination
    // path.  The explicit OpenRoot prevents all other path-based calls from
    // even starting down that path.

    OpenRoot(pvol);

    shSrc.sh_flags = SHF_BYNAME;
    pstmSrc = FindFirst(pvol, pwsOldFileName, &shSrc, &diSrc, &fd, NAME_FILE | NAME_DIR, UNKNOWN_CLUSTER);
    if (!pstmSrc) {
        CloseRoot(pvol);
        FATExit(pvol, LOGID_MOVEFILE);
        DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_MoveFileW(%s->%s) returned FALSE (%d)\r\n"), pwsOldFileName, pwsNewFileName, GetLastError()));
        return FALSE;
    }

    DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_MoveFileW.  Source (%s) located at cluster %d\r\n"), pwsOldFileName, diSrc.di_clusEntry));

    // If the source file doesn't exist, fail

    if (fd.dwFileAttributes == INVALID_ATTR) {
        CloseStream(pstmSrc);
        CloseRoot(pvol);
        FATExit(pvol, LOGID_MOVEFILE);
        DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_MoveFileW(%s->%s) returned FALSE (%d)\r\n"), pwsOldFileName, pwsNewFileName, GetLastError()));
        return FALSE;
    }


    // If the source file has any open handles, fail
    if (StreamOpenedForExclAccess(pstmSrc->s_pvol, &diSrc.di_sid)) {
        dwError = ERROR_SHARING_VIOLATION;
        goto exit3;
    }

    bAttrSrc = (BYTE)fd.dwFileAttributes;

#ifdef TFAT
    if (pvol->v_fTfat && (pvol->v_flFATFS & FATFS_TFAT_DISABLE_MOVEDIR) && (bAttrSrc & ATTR_DIRECTORY)) {
        // Moving a directory has been disabled on this volume
        dwError = ERROR_ACCESS_DENIED;
        goto exit3;
    }
#endif

    // Retrieve the fully-qualified pathname of the source, in case we need
    // it for the FILESYSTEMNOTIFICATION at the end of the function.  We have to
    // do the wacky buffer holding/unholding because pstmSrc's current buffer is
    // in a known state, and we can't tolerate GetSIDInfo mucking that state up.

#ifdef SHELL_CALLBACK_NOTIFICATION
    if (pfnShell && ZONE_SHELLMSGS) {
        PBUF pbuf = pstmSrc->s_pbufCur;
        HoldBuffer(pbuf);
        GetSIDInfo(pvol, &diSrc.di_sid, &oiOld);
        ReleaseStreamBuffer(pstmSrc, FALSE);
        AssignStreamBuffer(pstmSrc, pbuf, FALSE);
        UnholdBuffer(pbuf);
    }
#endif

    // We don't need the source pattern anymore, but we *might* need
    // the complete source filename (if we had to delete the source first,

⌨️ 快捷键说明

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