@@ -797,134 +797,162 @@ VOID DokanCompleteSetInformation(__in PREQUEST_CONTEXT RequestContext,
797797 __in PEVENT_INFORMATION EventInfo ) {
798798 PDokanCCB ccb ;
799799 PDokanFCB fcb = NULL ;
800+ UNICODE_STRING oldFileName ;
801+ BOOLEAN fcbLocked = FALSE;
802+ BOOLEAN vcbLocked = FALSE;
800803 FILE_INFORMATION_CLASS infoClass ;
801804
802- RequestContext -> Irp -> IoStatus .Information = EventInfo -> BufferLength ;
803- RequestContext -> Irp -> IoStatus .Status = EventInfo -> Status ;
805+ __try {
806+ RequestContext -> Irp -> IoStatus .Information = EventInfo -> BufferLength ;
807+ RequestContext -> Irp -> IoStatus .Status = EventInfo -> Status ;
804808
805- ccb = RequestContext -> IrpSp -> FileObject -> FsContext2 ;
806- ASSERT (ccb != NULL );
809+ ccb = RequestContext -> IrpSp -> FileObject -> FsContext2 ;
810+ ASSERT (ccb != NULL );
807811
808- infoClass = RequestContext -> IrpSp -> Parameters .SetFile .FileInformationClass ;
809- DOKAN_LOG_FINE_IRP (RequestContext , "FileObject=%p infoClass=%s" ,
810- RequestContext -> IrpSp -> FileObject ,
811- DokanGetFileInformationClassStr (infoClass ));
812+ fcb = ccb -> Fcb ;
813+ ASSERT (fcb != NULL );
812814
813- ccb -> UserContext = EventInfo -> Context ;
815+ infoClass = RequestContext -> IrpSp -> Parameters .SetFile .FileInformationClass ;
816+ DOKAN_LOG_FINE_IRP (RequestContext , "FileObject=%p infoClass=%s" ,
817+ RequestContext -> IrpSp -> FileObject ,
818+ DokanGetFileInformationClassStr (infoClass ));
814819
815- if (!NT_SUCCESS (RequestContext -> Irp -> IoStatus .Status )) {
816- return ;
817- }
820+ ccb -> UserContext = EventInfo -> Context ;
818821
819- fcb = ccb -> Fcb ;
820- ASSERT (fcb != NULL );
821-
822- switch (RequestContext -> IrpSp -> Parameters .SetFile .FileInformationClass ) {
823- case FileAllocationInformation :
824- DokanNotifyReportChange (RequestContext , fcb , FILE_NOTIFY_CHANGE_SIZE ,
825- FILE_ACTION_MODIFIED );
826- break ;
827- case FileBasicInformation :
828- DokanNotifyReportChange (
829- RequestContext , fcb ,
830- FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE |
831- FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION ,
832- FILE_ACTION_MODIFIED );
833- break ;
834- case FileDispositionInformation :
835- case FileDispositionInformationEx : {
836- if (EventInfo -> Operation .Delete .DeleteOnClose ) {
837- // Note that we do not acquire the resource for paging file
838- // operations in order to avoid deadlock with Mm
839- BOOLEAN fcbLocked = !(RequestContext -> Irp -> Flags & IRP_PAGING_IO );
840- if (fcbLocked ) {
841- DokanFCBLockRW (fcb );
822+ if (!NT_SUCCESS (RequestContext -> Irp -> IoStatus .Status )) {
823+ __leave;
824+ }
825+
826+ // Note that we do not acquire the resource for paging file
827+ // operations in order to avoid deadlock with Mm
828+ if (!(RequestContext -> Irp -> Flags & IRP_PAGING_IO )) {
829+ // If we are going to change the FileName on the FCB, then we want the VCB
830+ // locked so that we don't race with the loop in create.c that searches
831+ // currently open FCBs for a matching name. However, we need to lock that
832+ // before the FCB so that the lock order is consistent everywhere.
833+ if (NT_SUCCESS (RequestContext -> Irp -> IoStatus .Status ) &&
834+ infoClass == FileRenameInformation ) {
835+ DokanVCBLockRW (RequestContext -> Vcb );
836+ vcbLocked = TRUE;
842837 }
843- if (!MmFlushImageSection (& fcb -> SectionObjectPointers , MmFlushForDelete )) {
844- DOKAN_LOG_FINE_IRP (RequestContext , "Cannot delete user mapped image" );
845- RequestContext -> Irp -> IoStatus .Status = STATUS_CANNOT_DELETE ;
838+ DokanFCBLockRW (fcb );
839+ fcbLocked = TRUE;
840+ }
841+
842+ switch (infoClass ) {
843+ case FileDispositionInformation :
844+ case FileDispositionInformationEx : {
845+ if (EventInfo -> Operation .Delete .DeleteOnClose ) {
846+ if (!MmFlushImageSection (& fcb -> SectionObjectPointers ,
847+ MmFlushForDelete )) {
848+ DOKAN_LOG_FINE_IRP (RequestContext , "Cannot delete user mapped image" );
849+ RequestContext -> Irp -> IoStatus .Status = STATUS_CANNOT_DELETE ;
850+ } else {
851+ DokanCCBFlagsSetBit (ccb , DOKAN_DELETE_ON_CLOSE );
852+ DokanFCBFlagsSetBit (fcb , DOKAN_DELETE_ON_CLOSE );
853+ DOKAN_LOG_FINE_IRP (RequestContext ,
854+ "FileObject->DeletePending = TRUE" );
855+ RequestContext -> IrpSp -> FileObject -> DeletePending = TRUE;
856+ }
857+
846858 } else {
847- DokanCCBFlagsSetBit (ccb , DOKAN_DELETE_ON_CLOSE );
848- DokanFCBFlagsSetBit (fcb , DOKAN_DELETE_ON_CLOSE );
849- DOKAN_LOG_FINE_IRP (RequestContext , "FileObject->DeletePending = TRUE " );
850- RequestContext -> IrpSp -> FileObject -> DeletePending = TRUE ;
859+ DokanCCBFlagsClearBit (ccb , DOKAN_DELETE_ON_CLOSE );
860+ DokanFCBFlagsClearBit (fcb , DOKAN_DELETE_ON_CLOSE );
861+ DOKAN_LOG_FINE_IRP (RequestContext , "FileObject->DeletePending = FALSE " );
862+ RequestContext -> IrpSp -> FileObject -> DeletePending = FALSE ;
851863 }
852- if (fcbLocked ) {
853- DokanFCBUnlock (fcb );
864+ break ;
865+ }
866+ case FileRenameInformation :
867+ case FileRenameInformationEx : {
868+ // Process rename
869+ oldFileName =
870+ DokanWrapUnicodeString (fcb -> FileName .Buffer , fcb -> FileName .Length );
871+ // Copy new file name
872+ PVOID buffer = DokanAllocZero (EventInfo -> BufferLength + sizeof (WCHAR ));
873+ if (buffer == NULL ) {
874+ RequestContext -> Irp -> IoStatus .Status = STATUS_INSUFFICIENT_RESOURCES ;
875+ __leave;
854876 }
855- } else {
856- DokanCCBFlagsClearBit (ccb , DOKAN_DELETE_ON_CLOSE );
857- DokanFCBFlagsClearBit (fcb , DOKAN_DELETE_ON_CLOSE );
858- DOKAN_LOG_FINE_IRP (RequestContext , "FileObject->DeletePending = FALSE" );
859- RequestContext -> IrpSp -> FileObject -> DeletePending = FALSE;
877+ RtlCopyMemory (buffer , EventInfo -> Buffer , EventInfo -> BufferLength );
878+ DokanRenameFcb (RequestContext , fcb , buffer ,
879+ (USHORT )EventInfo -> BufferLength );
880+ DOKAN_LOG_FINE_IRP (RequestContext , "Fcb=%p renamed \"%wZ\"" , fcb ,
881+ & fcb -> FileName );
882+ break ;
883+ }
860884 }
861- if (RequestContext -> IrpSp -> FileObject -> DeletePending ) {
862- if (DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )) {
885+
886+ switch (infoClass ) {
887+ case FileAllocationInformation :
888+ DokanNotifyReportChange (RequestContext , fcb , FILE_NOTIFY_CHANGE_SIZE ,
889+ FILE_ACTION_MODIFIED );
890+ break ;
891+ case FileBasicInformation :
892+ DokanNotifyReportChange (
893+ RequestContext , fcb ,
894+ FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE |
895+ FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION ,
896+ FILE_ACTION_MODIFIED );
897+ break ;
898+ case FileDispositionInformation :
899+ case FileDispositionInformationEx :
900+ if (RequestContext -> IrpSp -> FileObject -> DeletePending ) {
901+ if (DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )) {
902+ DokanNotifyReportChange (RequestContext , fcb ,
903+ FILE_NOTIFY_CHANGE_DIR_NAME ,
904+ FILE_ACTION_REMOVED );
905+ } else {
906+ DokanNotifyReportChange (RequestContext , fcb ,
907+ FILE_NOTIFY_CHANGE_FILE_NAME ,
908+ FILE_ACTION_REMOVED );
909+ }
910+ }
911+ break ;
912+ case FileEndOfFileInformation :
913+ DokanNotifyReportChange (RequestContext , fcb , FILE_NOTIFY_CHANGE_SIZE ,
914+ FILE_ACTION_MODIFIED );
915+ break ;
916+ case FileRenameInformation :
917+ case FileRenameInformationEx : {
918+ if (IsInSameDirectory (& oldFileName , & fcb -> FileName )) {
919+ DokanNotifyReportChange0 (RequestContext , fcb , & oldFileName ,
920+ DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )
921+ ? FILE_NOTIFY_CHANGE_DIR_NAME
922+ : FILE_NOTIFY_CHANGE_FILE_NAME ,
923+ FILE_ACTION_RENAMED_OLD_NAME );
863924 DokanNotifyReportChange (RequestContext , fcb ,
864- FILE_NOTIFY_CHANGE_DIR_NAME ,
865- FILE_ACTION_REMOVED );
925+ DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )
926+ ? FILE_NOTIFY_CHANGE_DIR_NAME
927+ : FILE_NOTIFY_CHANGE_FILE_NAME ,
928+ FILE_ACTION_RENAMED_NEW_NAME );
866929 } else {
930+ DokanNotifyReportChange0 (RequestContext , fcb , & oldFileName ,
931+ DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )
932+ ? FILE_NOTIFY_CHANGE_DIR_NAME
933+ : FILE_NOTIFY_CHANGE_FILE_NAME ,
934+ FILE_ACTION_REMOVED );
867935 DokanNotifyReportChange (RequestContext , fcb ,
868- FILE_NOTIFY_CHANGE_FILE_NAME ,
869- FILE_ACTION_REMOVED );
936+ DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )
937+ ? FILE_NOTIFY_CHANGE_DIR_NAME
938+ : FILE_NOTIFY_CHANGE_FILE_NAME ,
939+ FILE_ACTION_ADDED );
870940 }
941+ // free old file name
942+ ExFreePool (oldFileName .Buffer );
943+ } break ;
944+ case FileValidDataLengthInformation :
945+ DokanNotifyReportChange (RequestContext , fcb , FILE_NOTIFY_CHANGE_SIZE ,
946+ FILE_ACTION_MODIFIED );
947+ break ;
871948 }
872- } break ;
873- case FileEndOfFileInformation :
874- DokanNotifyReportChange (RequestContext , fcb , FILE_NOTIFY_CHANGE_SIZE ,
875- FILE_ACTION_MODIFIED );
876- break ;
877- case FileRenameInformationEx :
878- case FileRenameInformation : {
879- DokanFCBLockRW (fcb );
880- // Process rename
881- UNICODE_STRING oldFileName =
882- DokanWrapUnicodeString (fcb -> FileName .Buffer , fcb -> FileName .Length );
883- // Copy new file name
884- PVOID buffer = DokanAllocZero (EventInfo -> BufferLength + sizeof (WCHAR ));
885- if (buffer == NULL ) {
886- RequestContext -> Irp -> IoStatus .Status = STATUS_INSUFFICIENT_RESOURCES ;
949+
950+ } __finally {
951+ if (fcbLocked ) {
887952 DokanFCBUnlock (fcb );
888- return ;
889953 }
890- RtlCopyMemory (buffer , EventInfo -> Buffer , EventInfo -> BufferLength );
891- DokanVCBLockRW (RequestContext -> Vcb );
892- DokanRenameFcb (RequestContext , fcb , buffer ,
893- (USHORT )EventInfo -> BufferLength );
894- DokanVCBUnlock (RequestContext -> Vcb );
895- DOKAN_LOG_FINE_IRP (RequestContext , "Fcb=%p renamed \"%wZ\"" , fcb ,
896- & fcb -> FileName );
897- DokanFCBUnlock (fcb );
898- // Notify rename
899- if (IsInSameDirectory (& oldFileName , & fcb -> FileName )) {
900- DokanNotifyReportChange0 (RequestContext , fcb , & oldFileName ,
901- DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )
902- ? FILE_NOTIFY_CHANGE_DIR_NAME
903- : FILE_NOTIFY_CHANGE_FILE_NAME ,
904- FILE_ACTION_RENAMED_OLD_NAME );
905- DokanNotifyReportChange (RequestContext , fcb ,
906- DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )
907- ? FILE_NOTIFY_CHANGE_DIR_NAME
908- : FILE_NOTIFY_CHANGE_FILE_NAME ,
909- FILE_ACTION_RENAMED_NEW_NAME );
910- } else {
911- DokanNotifyReportChange0 (RequestContext , fcb , & oldFileName ,
912- DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )
913- ? FILE_NOTIFY_CHANGE_DIR_NAME
914- : FILE_NOTIFY_CHANGE_FILE_NAME ,
915- FILE_ACTION_REMOVED );
916- DokanNotifyReportChange (RequestContext , fcb ,
917- DokanFCBFlagsIsSet (fcb , DOKAN_FILE_DIRECTORY )
918- ? FILE_NOTIFY_CHANGE_DIR_NAME
919- : FILE_NOTIFY_CHANGE_FILE_NAME ,
920- FILE_ACTION_ADDED );
954+ if (vcbLocked ) {
955+ DokanVCBUnlock (RequestContext -> Vcb );
921956 }
922- // free old file name
923- ExFreePool (oldFileName .Buffer );
924- } break ;
925- case FileValidDataLengthInformation :
926- DokanNotifyReportChange (RequestContext , fcb , FILE_NOTIFY_CHANGE_SIZE ,
927- FILE_ACTION_MODIFIED );
928- break ;
929957 }
930- }
958+ }
0 commit comments