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

📄 ea.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 4 页
字号:

            DebugTrace(0, Dbg, "FatCommonSetEa:  Next Ea name -> %Z\n",
                       &EaName);

            //
            //  Make sure the ea name is valid
            //

            if (!FatIsEaNameValid( IrpContext,EaName )) {

                Irp->IoStatus.Information = (PUCHAR)FullEa - Buffer;
                Status = STATUS_INVALID_EA_NAME;
                try_return( Status );
            }

            //
            //  Check that no invalid ea flags are set.
            //

            //
            //  TEMPCODE  We are returning STATUS_INVALID_EA_NAME
            //  until a more appropriate error code exists.
            //

            if (FullEa->Flags != 0
                && FullEa->Flags != FILE_NEED_EA) {

                Irp->IoStatus.Information = (PUCHAR)FullEa - (PUCHAR)Buffer;
                try_return( Status = STATUS_INVALID_EA_NAME );
            }

            //
            //  See if we can locate the ea name in the ea set
            //

            if (FatLocateEaByName( IrpContext,
                                   (PPACKED_EA) EaSetHeader->PackedEas,
                                   PackedEasLength,
                                   &EaName,
                                   &Offset )) {

                DebugTrace(0, Dbg, "FatCommonSetEa:  Found Ea name\n", 0);

                //
                //  We found the ea name so now delete the current entry,
                //  and if the new ea value length is not zero then we
                //  replace if with the new ea
                //

                FatDeletePackedEa( IrpContext,
                                   EaSetHeader,
                                   &PackedEasLength,
                                   Offset );
            }

            if (FullEa->EaValueLength != 0) {

                FatAppendPackedEa( IrpContext,
                                   &EaSetHeader,
                                   &PackedEasLength,
                                   &AllocationLength,
                                   FullEa,
                                   BytesPerCluster );
            }
        }

        //
        //  If there are any ea's not removed, we
        //  call 'AddEaSet' to insert them into the Fat chain.
        //

        if (PackedEasLength != 0) {

            LARGE_INTEGER EaOffset;

            EaOffset.HighPart = 0;

            //
            //  If the packed eas length (plus 4 bytes) is greater
            //  than the maximum allowed ea size, we return an error.
            //

            if (PackedEasLength + 4 > MAXIMUM_EA_SIZE) {

                DebugTrace( 0, Dbg, "Ea length is greater than maximum\n", 0 );

                try_return( Status = STATUS_EA_TOO_LARGE );
            }

            //
            //  We need to now read the ea file if we haven't already.
            //

            if (EaDirent == NULL) {

                FatGetEaFile( IrpContext,
                              Vcb,
                              &EaDirent,
                              &EaBcb,
                              TRUE,
                              TRUE );

                AcquiredEaFcb = TRUE;
            }

            FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );

            RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));

            FatAddEaSet( IrpContext,
                         Vcb,
                         PackedEasLength + SIZE_OF_EA_SET_HEADER,
                         EaBcb,
                         EaDirent,
                         &EaHandle,
                         &EaSetRange );

            NewEaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;

            DebugTrace(0, Dbg, "FatCommonSetEa:  Adding an ea set\n", 0);

            //
            //  Store the length of the new Ea's into the EaSetHeader.
            //  This is the PackedEasLength + 4.
            //

            PackedEasLength += 4;

            CopyU4char( EaSetHeader->cbList, &PackedEasLength );

            //
            //  Copy all but the first four bytes of EaSetHeader into
            //  NewEaSetHeader.  The signature and index fields have
            //  already been filled in.
            //

            RtlCopyMemory( &NewEaSetHeader->NeedEaCount,
                           &EaSetHeader->NeedEaCount,
                           PackedEasLength + SIZE_OF_EA_SET_HEADER - 8 );

            FatMarkEaRangeDirty( IrpContext, Vcb->VirtualEaFile, &EaSetRange );
            FatUnpinEaRange( IrpContext, &EaSetRange );

            CcFlushCache( Vcb->VirtualEaFile->SectionObjectPointer, NULL, 0, NULL );

        } else {

            FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );

            EaHandle = 0;
        }

        //
        //  Now we do a wholesale replacement of the ea for the file
        //

        if (PreviousEas) {

            FatDeleteEaSet( IrpContext,
                            Vcb,
                            EaBcb,
                            EaDirent,
                            ExtendedAttributes,
                            &Fcb->ShortName.Name.Oem );

            CcFlushCache( Vcb->VirtualEaFile->SectionObjectPointer, NULL, 0, NULL );
        }

        if (PackedEasLength != 0 ) {

            Fcb->EaModificationCount++;
        }

        //
        //  Mark the dirent with the new ea's
        //

        Dirent->ExtendedAttributes = EaHandle;

        FatSetDirtyBcb( IrpContext, Bcb, Vcb, TRUE );

        //
        //  We call the notify package to report that the ea's were
        //  modified.
        //

        FatNotifyReportChange( IrpContext,
                               Vcb,
                               Fcb,
                               FILE_NOTIFY_CHANGE_EA,
                               FILE_ACTION_MODIFIED );

        Irp->IoStatus.Information = 0;
        Status = STATUS_SUCCESS;

    try_exit: NOTHING;

        //
        //  Unpin the dirents for the Fcb and EaFcb if necessary.
        //

        FatUnpinBcb( IrpContext, Bcb );
        FatUnpinBcb( IrpContext, EaBcb );

        FatUnpinRepinnedBcbs( IrpContext );

    } finally {

        DebugUnwind( FatCommonSetEa );

        //
        //  If this is an abnormal termination, we need to clean up
        //  any locked resources.
        //

        if (AbnormalTermination()) {

            //
            //  Unpin the dirents for the Fcb, EaFcb and EaSetFcb if necessary.
            //

            FatUnpinBcb( IrpContext, Bcb );
            FatUnpinBcb( IrpContext, EaBcb );

            FatUnpinEaRange( IrpContext, &EaSetRange );
        }

        //
        //  Release the Fcbs/Vcb acquired.
        //

        if (AcquiredEaFcb) {
            FatReleaseFcb( IrpContext, Vcb->EaFcb );
        }

        if (AcquiredFcb) {
            FatReleaseFcb( IrpContext, Fcb );
        }

        if (AcquiredParentDcb) {
            FatReleaseFcb( IrpContext, Fcb->ParentDcb );
        }

        if (AcquiredRootDcb) {
            FatReleaseFcb( IrpContext, Fcb->Vcb->RootDcb );
        }

        if (AcquiredVcb) {
            FatReleaseVcb( IrpContext, Fcb->Vcb );
        }

        //
        //  Deallocate our Ea buffer.
        //

        if (EaSetHeader != NULL) {

            ExFreePool( EaSetHeader );
        }

        //
        //  Complete the irp.
        //

        if (!AbnormalTermination()) {

            FatCompleteRequest( IrpContext, Irp, Status );
        }

        DebugTrace(-1, Dbg, "FatCommonSetEa -> %08lx\n", Status);
    }

    //
    //  And return to our caller
    //

    return Status;
#endif
}


#if 0

//
//  Local Support Routine
//

IO_STATUS_BLOCK
FatQueryEaUserEaList (
    IN PIRP_CONTEXT IrpContext,
    OUT PCCB Ccb,
    IN PPACKED_EA FirstPackedEa,
    IN ULONG PackedEasLength,
    OUT PUCHAR UserBuffer,
    IN ULONG  UserBufferLength,
    IN PUCHAR UserEaList,
    IN ULONG  UserEaListLength,
    IN BOOLEAN ReturnSingleEntry
    )

/*++

Routine Description:

    This routine is the work routine for querying EAs given an ea index

Arguments:

    Ccb - Supplies the Ccb for the query

    FirstPackedEa - Supplies the first ea for the file being queried

    PackedEasLength - Supplies the length of the ea data

    UserBuffer - Supplies the buffer to receive the full eas

    UserBufferLength - Supplies the length, in bytes, of the user buffer

    UserEaList - Supplies the user specified ea name list

    UserEaListLength - Supplies the length, in bytes, of the user ea list

    ReturnSingleEntry - Indicates if we are to return a single entry or not

Return Value:

    IO_STATUS_BLOCK - Receives the completion status for the operation

--*/

{
    IO_STATUS_BLOCK Iosb;

    ULONG Offset;
    ULONG RemainingUserBufferLength;

    PPACKED_EA PackedEa;
    ULONG PackedEaSize;

    PFILE_FULL_EA_INFORMATION LastFullEa = NULL;
    ULONG LastFullEaSize;
    PFILE_FULL_EA_INFORMATION NextFullEa;

    PFILE_GET_EA_INFORMATION GetEa;

    BOOLEAN Overflow;

    DebugTrace(+1, Dbg, "FatQueryEaUserEaList...\n", 0);

    LastFullEa = NULL;
    NextFullEa = (PFILE_FULL_EA_INFORMATION) UserBuffer;
    RemainingUserBufferLength = UserBufferLength;

    Overflow = FALSE;

    for (GetEa = (PFILE_GET_EA_INFORMATION) &UserEaList[0];
         GetEa < (PFILE_GET_EA_INFORMATION) ((PUCHAR) UserEaList
                                             + UserEaListLength);
         GetEa = (GetEa->NextEntryOffset == 0
                  ? (PFILE_GET_EA_INFORMATION) MAXUINT_PTR
                  : (PFILE_GET_EA_INFORMATION) ((PUCHAR) GetEa
                                                + GetEa->NextEntryOffset))) {

        OEM_STRING Str;
        OEM_STRING OutputEaName;

        DebugTrace(0, Dbg, "Top of loop, GetEa = %08lx\n", GetEa);
        DebugTrace(0, Dbg, "LastFullEa = %08lx\n", LastFullEa);
        DebugTrace(0, Dbg, "NextFullEa = %08lx\n", NextFullEa);
        DebugTrace(0, Dbg, "RemainingUserBufferLength = %08lx\n", RemainingUserBufferLength);

        //
        //  Make a string reference to the GetEa and see if we can
        //  locate the ea by name
        //

        Str.MaximumLength = Str.Length = GetEa->EaNameLength;
        Str.Buffer = &GetEa->EaName[0];

        //
        //  Check for a valid name.
        //

        if (!FatIsEaNameValid( IrpContext, Str )) {

            DebugTrace(-1, Dbg,
                       "FatQueryEaUserEaList:  Invalid Ea Name -> %Z\n",
                       &Str);

            Iosb.Information = (PUCHAR)GetEa - UserEaList;
            Iosb.Status = STATUS_INVALID_EA_NAME;
            return Iosb;
        }

        //
        //  If this is a duplicate name, we skip to the next.
        //

        if (FatIsDuplicateEaName( IrpContext, GetEa, UserEaList )) {

            DebugTrace(0, Dbg, "FatQueryEaUserEaList:  Duplicate name\n", 0);
            continue;
        }

        if (!FatLocateEaByName( IrpContext,
                                FirstPackedEa,
                                PackedEasLength,
                                &Str,
                                &Offset )) {

            Offset = 0xffffffff;

            DebugTrace(0, Dbg, "Need to dummy up an ea\n", 0);

            //
            //  We were not able to locate the name therefore we must
            //  dummy up a entry for the query.  The needed Ea size is
            //  the size of the name + 4 (next entry offset) + 1 (flags)
            //  + 1 (name length) + 2 (value length) + the name length +
            //  1 (null byte).
            //

            if ((ULONG)(4+1+1+2+GetEa->EaNameLength+1)
                > RemainingUserBufferLength) {

                Overflow = TRUE;
                break;
            }

            //
            //  Everything is going to work fine, so copy over the name,
            //  set the name length and zero out the rest of the ea.
            //

            NextFullEa->NextEntryOffset = 0;
            NextFullEa->Flags = 0;
            NextFullEa->EaNameLength = GetEa->EaNameLength;
            NextFullEa->EaValueLength = 0;
            RtlCopyMemory( &NextFullEa->EaName[0],
                           &GetEa->EaName[0],
                           GetEa->EaNameLength );

            //
            //  Upcase the name in the buffer.
            //

            OutputEaName.MaximumLength = OutputEaName.Length = Str.Length;
            OutputEaName.Buffer = NextFullEa->EaName;

            FatUpcaseEaName( IrpContext, &OutputEaName, &OutputEaName );

            NextFullEa->EaName[GetEa->EaNameLength] = 0;

        } else {

            DebugTrace(0, Dbg, "Located the ea, Offset = %08lx\n", Offset);

            //
            //  We were able to locate the packed ea
            //  Reference the packed ea
            //

            PackedEa = (PPACKED_EA) ((PUCHAR) FirstPackedEa + Offset);
            SizeOfPackedEa( PackedEa, &PackedEaSize );

            DebugTrace(0, Dbg, "PackedEaSize = %08lx\n", PackedEaSize);

            //
            //  We know that the packed ea is 4 bytes smaller than its
            //  equivalent full ea so we need to check the remaining
            //  user buffer length against the computed full ea size.
            //

            if (PackedEaSize + 4 > RemainingUserBufferLength) {

                Overflow = TRUE;
                break;
            }

            //
            //  Everything is going to work fine, so copy over the packed
            //  ea to the full ea and zero out the next entry offset field.
            //

            RtlCopyMemory( &NextFullEa->Flags,
                           &PackedEa->Flags,
                           PackedEaSize );

            NextFullEa->NextEntryOffset = 0;
        }

        //
        //  At this point we've copied a new full ea into the next full ea
        //  location.  So now go back and set the set full eas entry offset
        //  field to be the difference between out two pointers.
        //

        if (LastFullEa != NULL) {

            LastFullEa->NextEntryOffset = (ULONG)((PUCHAR) NextFullEa
                                          - (PUCHAR) LastFullEa);
        }

        //
        //  Set the last full ea to the next full ea, compute
        //  where the next full should be, and decrement the remaining user
        //  buffer length appropriately

⌨️ 快捷键说明

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