IO_STATUS_BLOCK MsCreateClientEnd ( IN PFCB Fcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE RequestorMode, IN PETHREAD UserThread ) /*++ Routine Description: This routine performs the operation for opening the client end of a mailslot. This routine does not complete the IRP, it performs the function and then returns a status. Arguments: Fcb - Supplies the FCB for the mailslot being accessed. FileObject - Supplies the file object associated with the client end. DesiredAccess - Supplies the caller's desired access. ShareAccess - Supplies the caller's share access. Return Value: IO_STATUS_BLOCK - Returns the appropriate status for the operation --*/ { IO_STATUS_BLOCK iosb; PCCB ccb; BOOLEAN accessGranted; ACCESS_MASK grantedAccess; UNICODE_STRING name; PPRIVILEGE_SET Privileges = NULL; BOOLEAN shareAccessUpdated = FALSE; PAGED_CODE(); DebugTrace(+1, Dbg, "MsCreateClientEnd\n", 0 ); try { // // First do an access check for the user against the Fcb // SeLockSubjectContext( &AccessState->SubjectSecurityContext ); accessGranted = SeAccessCheck( Fcb->SecurityDescriptor, &AccessState->SubjectSecurityContext, TRUE, // Tokens are locked DesiredAccess, 0, &Privileges, IoGetFileObjectGenericMapping(), RequestorMode, &grantedAccess, &iosb.Status ); if (Privileges != NULL) { (VOID) SeAppendPrivileges( AccessState, Privileges ); SeFreePrivileges( Privileges ); } if (accessGranted) { AccessState->PreviouslyGrantedAccess |= grantedAccess; AccessState->RemainingDesiredAccess &= ~grantedAccess; } RtlInitUnicodeString( &name, L"Mailslot" ); SeOpenObjectAuditAlarm( &name, NULL, &FileObject->FileName, Fcb->SecurityDescriptor, AccessState, FALSE, accessGranted, RequestorMode, &AccessState->GenerateOnClose ); SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); if (!accessGranted) { DebugTrace(0, Dbg, "Access Denied\n", 0 ); try_return( iosb.Status ); } // // Now make sure our share access is okay. // if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess, ShareAccess, FileObject, &Fcb->ShareAccess, TRUE ))) { DebugTrace(0, Dbg, "Sharing violation\n", 0); try_return( NOTHING ); } shareAccessUpdated = TRUE; // // Create a CCB for this client. // ccb = MsCreateCcb( Fcb ); // // Set the file object back pointers and our pointer to the // server file object. // MsSetFileObject( FileObject, ccb, NULL ); ccb->FileObject = FileObject; // // And set our return status // iosb.Status = STATUS_SUCCESS; iosb.Information = FILE_OPENED; try_exit: NOTHING; } finally { DebugTrace(-1, Dbg, "MsCreateClientEnd -> %08lx\n", iosb.Status); if (!NT_SUCCESS(iosb.Status) || AbnormalTermination()) { if (shareAccessUpdated) { IoRemoveShareAccess( FileObject, &Fcb->ShareAccess ); } } } return iosb; }
NTSTATUS AFSInitVolume( IN GUID *AuthGroup, IN AFSFileID *RootFid, OUT AFSVolumeCB **VolumeCB) { NTSTATUS ntStatus = STATUS_SUCCESS; IO_STATUS_BLOCK stIoStatus = {0,0}; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; AFSNonPagedVolumeCB *pNonPagedVcb = NULL; AFSVolumeCB *pVolumeCB = NULL; AFSNonPagedObjectInfoCB *pNonPagedObject = NULL; ULONGLONG ullIndex = 0; BOOLEAN bReleaseLocks = FALSE; AFSVolumeInfoCB stVolumeInformation; AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL; __Enter { // // Before grabbing any locks ask the service for the volume information // This may be a waste but we need to get this information prior to // taking any volume tree locks. Don't do this for any 'reserved' cell entries // if( RootFid->Cell != 0) { RtlZeroMemory( &stVolumeInformation, sizeof( AFSVolumeInfoCB)); ntStatus = AFSRetrieveVolumeInformation( AuthGroup, RootFid, &stVolumeInformation); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitVolume AFSRetrieveVolumeInformation(RootFid) failure %08lX\n", ntStatus); try_return( ntStatus); } // // Grab our tree locks and see if we raced with someone else // AFSAcquireExcl( pDeviceExt->Specific.RDR.VolumeTree.TreeLock, TRUE); AFSAcquireExcl( &pDeviceExt->Specific.RDR.VolumeListLock, TRUE); bReleaseLocks = TRUE; ullIndex = AFSCreateHighIndex( RootFid); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead, ullIndex, (AFSBTreeEntry **)&pVolumeCB); if( NT_SUCCESS( ntStatus) && pVolumeCB != NULL) { // // So we don't lock with an invalidation call ... // InterlockedIncrement( &pVolumeCB->VolumeReferenceCount); AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock); bReleaseLocks = FALSE; AFSAcquireExcl( pVolumeCB->VolumeLock, TRUE); InterlockedDecrement( &pVolumeCB->VolumeReferenceCount); *VolumeCB = pVolumeCB; try_return( ntStatus); } // // Revert our status from the above call back to success. // ntStatus = STATUS_SUCCESS; } // // For the global root we allocate out volume node and insert it // into the volume tree ... // pVolumeCB = (AFSVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSVolumeCB), AFS_VCB_ALLOCATION_TAG); if( pVolumeCB == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitVolume Failed to allocate the root volume cb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pVolumeCB, sizeof( AFSVolumeCB)); // // The non paged portion // pNonPagedVcb = (AFSNonPagedVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedVolumeCB), AFS_VCB_ALLOCATION_TAG); if( pNonPagedVcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitVolume Failed to allocate the root non paged volume cb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pNonPagedVcb, sizeof( AFSNonPagedVolumeCB)); ExInitializeResourceLite( &pNonPagedVcb->VolumeLock); ExInitializeResourceLite( &pNonPagedVcb->ObjectInfoTreeLock); pNonPagedObject = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedObjectInfoCB), AFS_VCB_ALLOCATION_TAG); if( pNonPagedObject == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitVolume Failed to allocate the root non paged object cb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pNonPagedObject, sizeof( AFSNonPagedObjectInfoCB)); ExInitializeResourceLite( &pNonPagedObject->DirectoryNodeHdrLock); pVolumeCB->NonPagedVcb = pNonPagedVcb; pVolumeCB->ObjectInformation.NonPagedInfo = pNonPagedObject; pVolumeCB->VolumeLock = &pNonPagedVcb->VolumeLock; pVolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock = &pNonPagedObject->DirectoryNodeHdrLock; pVolumeCB->ObjectInfoTree.TreeLock = &pNonPagedVcb->ObjectInfoTreeLock; // // Bias our reference by 1 // AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitVolume Initializing count (1) on volume %08lX\n", pVolumeCB); pVolumeCB->VolumeReferenceCount = 1; AFSAcquireExcl( pVolumeCB->VolumeLock, TRUE); pVolumeCB->DirectoryCB = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool, sizeof( AFSDirectoryCB) + sizeof( WCHAR), AFS_DIR_ENTRY_TAG); if( pVolumeCB->DirectoryCB == NULL) { try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedDirectoryCB), AFS_DIR_ENTRY_NP_TAG); if( pNonPagedDirEntry == NULL) { try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pVolumeCB->DirectoryCB, sizeof( AFSDirectoryCB) + sizeof( WCHAR)); RtlZeroMemory( pNonPagedDirEntry, sizeof( AFSNonPagedDirectoryCB)); ExInitializeResourceLite( &pNonPagedDirEntry->Lock); pVolumeCB->DirectoryCB->NonPaged = pNonPagedDirEntry; // // Initialize the non-paged portion of the directory entry // KeQuerySystemTime( &pVolumeCB->ObjectInformation.CreationTime); KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastWriteTime); KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastAccessTime); pVolumeCB->ObjectInformation.FileType = AFS_FILE_TYPE_DIRECTORY; SetFlag( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_ROOT_VOLUME); pVolumeCB->ObjectInformation.FileId.Cell = RootFid->Cell; pVolumeCB->ObjectInformation.FileId.Volume = RootFid->Volume; pVolumeCB->ObjectInformation.FileId.Vnode = RootFid->Vnode; pVolumeCB->ObjectInformation.FileId.Unique = RootFid->Unique; pVolumeCB->ObjectInformation.FileId.Hash = RootFid->Hash; pVolumeCB->ObjectInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY; pVolumeCB->DirectoryCB->NameInformation.FileName.Length = sizeof( WCHAR); pVolumeCB->DirectoryCB->NameInformation.FileName.MaximumLength = pVolumeCB->DirectoryCB->NameInformation.FileName.Length; pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer = (WCHAR *)((char *)pVolumeCB->DirectoryCB + sizeof( AFSDirectoryCB)); RtlCopyMemory( pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer, L"\\", sizeof( WCHAR)); // // Copy in the volume information retrieved above // RtlCopyMemory( &pVolumeCB->VolumeInformation, &stVolumeInformation, sizeof( AFSVolumeInfoCB)); // // Setup pointers // pVolumeCB->DirectoryCB->ObjectInformation = &pVolumeCB->ObjectInformation; pVolumeCB->DirectoryCB->ObjectInformation->VolumeCB = pVolumeCB; // // Insert the volume into our volume tree. Don't insert any reserved entries // if( RootFid->Cell != 0) { pVolumeCB->TreeEntry.HashIndex = ullIndex; if( pDeviceExt->Specific.RDR.VolumeTree.TreeHead == NULL) { pDeviceExt->Specific.RDR.VolumeTree.TreeHead = &pVolumeCB->TreeEntry; SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE); } else { if ( NT_SUCCESS( AFSInsertHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead, &pVolumeCB->TreeEntry))) { SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE); } } if( pDeviceExt->Specific.RDR.VolumeListHead == NULL) { pDeviceExt->Specific.RDR.VolumeListHead = pVolumeCB; } else { pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = (void *)pVolumeCB; pVolumeCB->ListEntry.bLink = pDeviceExt->Specific.RDR.VolumeListTail; } pDeviceExt->Specific.RDR.VolumeListTail = pVolumeCB; } *VolumeCB = pVolumeCB; try_exit: if( !NT_SUCCESS( ntStatus)) { if( pNonPagedVcb != NULL) { AFSReleaseResource( pVolumeCB->VolumeLock); ExDeleteResourceLite( &pNonPagedVcb->VolumeLock); ExDeleteResourceLite( &pNonPagedVcb->ObjectInfoTreeLock); AFSExFreePool( pNonPagedVcb); } if( pNonPagedObject != NULL) { ExDeleteResourceLite( &pNonPagedObject->DirectoryNodeHdrLock); AFSExFreePool( pNonPagedObject); } if( pVolumeCB != NULL) { if( pVolumeCB->DirectoryCB != NULL) { AFSExFreePool( pVolumeCB->DirectoryCB); } AFSExFreePool( pVolumeCB); } if( pNonPagedDirEntry != NULL) { ExDeleteResourceLite( &pNonPagedDirEntry->Lock); AFSExFreePool( pNonPagedDirEntry); } } if( bReleaseLocks) { AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock); } } return ntStatus; }
NTSTATUS AFSInitRootFcb( IN ULONGLONG ProcessID, IN AFSVolumeCB *VolumeCB) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSFcb *pFcb = NULL; AFSNonPagedFcb *pNPFcb = NULL; IO_STATUS_BLOCK stIoStatus = {0,0}; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; __Enter { // // Initialize the root fcb // pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool, sizeof( AFSFcb), AFS_FCB_ALLOCATION_TAG); if( pFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRootFcb Failed to allocate the root fcb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pFcb, sizeof( AFSFcb)); pFcb->Header.NodeByteSize = sizeof( AFSFcb); pFcb->Header.NodeTypeCode = AFS_ROOT_FCB; pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedFcb), AFS_FCB_NP_ALLOCATION_TAG); if( pNPFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRootFcb Failed to allocate the non-paged fcb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pNPFcb, sizeof( AFSNonPagedFcb)); pNPFcb->Size = sizeof( AFSNonPagedFcb); pNPFcb->Type = AFS_NON_PAGED_FCB; // // OK, initialize the entry // ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex); FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex); ExInitializeResourceLite( &pNPFcb->Resource); AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitRootFcb Acquiring Fcb lock %08lX EXCL %08lX\n", &pNPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pNPFcb->Resource, TRUE); ExInitializeResourceLite( &pNPFcb->PagingResource); ExInitializeResourceLite( &pNPFcb->CcbListLock); pFcb->Header.Resource = &pNPFcb->Resource; pFcb->Header.PagingIoResource = &pNPFcb->PagingResource; pFcb->NPFcb = pNPFcb; // // Initialize enumeration information // KeInitializeEvent( &pFcb->NPFcb->Specific.Directory.DirectoryEnumEvent, NotificationEvent, FALSE); // // Save the root Fcb in the VolumeCB // VolumeCB->ObjectInformation.Fcb = pFcb; VolumeCB->ObjectInformation.VolumeCB = VolumeCB; VolumeCB->RootFcb = pFcb; pFcb->ObjectInformation = &VolumeCB->ObjectInformation; try_exit: if( !NT_SUCCESS( ntStatus)) { if( pFcb != NULL) { AFSRemoveRootFcb( pFcb); } } } return ntStatus; }
BOOLEAN FatFastUnlockAllByKey ( IN PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast unlock all by key call. Arguments: FileObject - Supplies the file object used in this operation ProcessId - Supplies the process ID used in this operation Key - Supplies the key used in this operation Status - Receives the Status if this operation is successful Return Value: BOOLEAN - TRUE if this operation completed and FALSE if caller needs to take the long route. --*/ { BOOLEAN Results; PVCB Vcb; PFCB Fcb; PCCB Ccb; DebugTrace(+1, Dbg, "FatFastUnlockAllByKey\n", 0); IoStatus->Information = 0; // // Decode the type of file object we're being asked to process and make sure // it is only a user file open. // if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) { IoStatus->Status = STATUS_INVALID_PARAMETER; DebugTrace(-1, Dbg, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0); return TRUE; } // // Acquire exclusive access to the Fcb this operation can always wait // FsRtlEnterFileSystem(); (VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE ); try { // // We check whether we can proceed based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) { try_return( Results = FALSE ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request. The call will always succeed. // Results = TRUE; IoStatus->Status = FsRtlFastUnlockAllByKey( &Fcb->Specific.Fcb.FileLock, FileObject, ProcessId, Key, NULL ); // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb ); try_exit: NOTHING; } finally { DebugUnwind( FatFastUnlockAllByKey ); // // Release the Fcb, and return to our caller // ExReleaseResourceLite( (Fcb)->Header.Resource ); FsRtlExitFileSystem(); DebugTrace(-1, Dbg, "FatFastUnlockAllByKey -> %08lx\n", Results); } return Results; }
NTSTATUS FatFsdRead ( IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the driver entry to the common read routine for NtReadFile calls. For synchronous requests, the CommonRead is called with Wait == TRUE, which means the request will always be completed in the current thread, and never passed to the Fsp. If it is not a synchronous request, CommonRead is called with Wait == FALSE, which means the request will be passed to the Fsp only if there is a need to block. Arguments: VolumeDeviceObject - Supplies the volume device object where the file being Read exists Irp - Supplies the Irp being processed Return Value: NTSTATUS - The FSD status for the IRP --*/ { PFCB Fcb = NULL; NTSTATUS Status; PIRP_CONTEXT IrpContext = NULL; BOOLEAN TopLevel; DebugTrace(+1, Dbg, "FatFsdRead\n", 0); // // Call the common Read routine, with blocking allowed if synchronous // FsRtlEnterFileSystem(); // // We are first going to do a quick check for paging file IO. Since this // is a fast path, we must replicate the check for the fsdo. // if (!FatDeviceIsFatFsdo( IoGetCurrentIrpStackLocation(Irp)->DeviceObject)) { Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext); if ((NodeType(Fcb) == FAT_NTC_FCB) && FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE)) { // // Do the usual STATUS_PENDING things. // IoMarkIrpPending( Irp ); // // If there is not enough stack to do this read, then post this // read to the overflow queue. // if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) { KEVENT Event; PAGING_FILE_OVERFLOW_PACKET Packet; Packet.Irp = Irp; Packet.Fcb = Fcb; KeInitializeEvent( &Event, NotificationEvent, FALSE ); FsRtlPostPagingFileStackOverflow( &Packet, &Event, FatOverflowPagingFileRead ); // // And wait for the worker thread to complete the item // (VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); } else { // // Perform the actual IO, it will be completed when the io finishes. // FatPagingFileIo( Irp, Fcb ); } FsRtlExitFileSystem(); return STATUS_PENDING; } } try { TopLevel = FatIsIrpTopLevel( Irp ); IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) ); // // If this is an Mdl complete request, don't go through // common read. // if ( FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE) ) { DebugTrace(0, Dbg, "Calling FatCompleteMdl\n", 0 ); try_return( Status = FatCompleteMdl( IrpContext, Irp )); } // // Check if we have enough stack space to process this request. If there // isn't enough then we will pass the request off to the stack overflow thread. // if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) { DebugTrace(0, Dbg, "Passing StackOverflowRead off\n", 0 ); try_return( Status = FatPostStackOverflowRead( IrpContext, Irp, Fcb ) ); } Status = FatCommonRead( IrpContext, Irp ); try_exit: NOTHING; } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) { // // We had some trouble trying to perform the requested // operation, so we'll abort the I/O request with // the error status that we get back from the // execption code // Status = FatProcessException( IrpContext, Irp, GetExceptionCode() ); } if (TopLevel) { IoSetTopLevelIrp( NULL ); } FsRtlExitFileSystem(); // // And return to our caller // DebugTrace(-1, Dbg, "FatFsdRead -> %08lx\n", Status); UNREFERENCED_PARAMETER( VolumeDeviceObject ); return Status; }
NTSTATUS GenerateFileName(IN PFLT_INSTANCE Instance, IN PFILE_OBJECT FileObject, IN PFLT_CALLBACK_DATA CallbackData, IN FLT_FILE_NAME_OPTIONS NameOptions, OUT PBOOLEAN CacheFileNameInformation, OUT PFLT_NAME_CONTROL FileName ) //上层的minifilter过滤驱动的名字请求进行处理 { NTSTATUS Status = STATUS_UNSUCCESSFUL; PFILE_OBJECT StreamObject = FileObject; PFLT_FILE_NAME_INFORMATION FileNameInformation = NULL; BOOLEAN bEncryptResource = FALSE; PFCB Fcb = FileObject->FsContext; PCCB Ccb = FileObject->FsContext2; FsRtlEnterFileSystem(); try { if(IsMyFakeFcb(FileObject)) { ExAcquireResourceSharedLite(Fcb->EncryptResource,TRUE); bEncryptResource = TRUE; if(BooleanFlagOn(Fcb->FcbState,SCB_STATE_SHADOW_CLOSE) || Ccb->StreamFileInfo.StreamObject == NULL) { try_return (Status = STATUS_FILE_DELETED); } else { StreamObject = Ccb->StreamFileInfo.StreamObject; } } ClearFlag(NameOptions,FLT_FILE_NAME_REQUEST_FROM_CURRENT_PROVIDER); if(FlagOn(NameOptions,FLT_FILE_NAME_NORMALIZED)) { ClearFlag(NameOptions,FLT_FILE_NAME_NORMALIZED); SetFlag(NameOptions,FLT_FILE_NAME_OPENED); } if (CallbackData) { PFILE_OBJECT TemFileObject = CallbackData->Iopb->TargetFileObject; CallbackData->Iopb->TargetFileObject = StreamObject; FltSetCallbackDataDirty(CallbackData); Status = FltGetFileNameInformation(CallbackData,NameOptions, &FileNameInformation); CallbackData->Iopb->TargetFileObject = TemFileObject; FltClearCallbackDataDirty(CallbackData); } else { Status = FltGetFileNameInformationUnsafe(StreamObject,Instance, NameOptions, &FileNameInformation); } if(!NT_SUCCESS(Status)) { try_return (Status); } Status = FltCheckAndGrowNameControl(FileName, FileNameInformation->Name.Length); if(!NT_SUCCESS(Status)) { try_return (Status); } RtlCopyUnicodeString(&FileName->Name, &FileNameInformation->Name); if(FileNameInformation != NULL) { FltReleaseFileNameInformation(FileNameInformation); } Status = STATUS_SUCCESS; try_exit: NOTHING; } finally { if(bEncryptResource) { ExReleaseResourceLite( Fcb->EncryptResource ); } } FsRtlExitFileSystem(); return Status; }
/* Routine Description: This routine performs the verify volume operation. It is responsible for either completing of enqueuing the input Irp. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ NTSTATUS UDFVerifyVolume( IN PIRP Irp ) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PVPB Vpb = IrpSp->Parameters.VerifyVolume.Vpb; PVCB Vcb = (PVCB)IrpSp->Parameters.VerifyVolume.DeviceObject->DeviceExtension; PVCB NewVcb = NULL; IO_STATUS_BLOCK Iosb; ULONG MediaChangeCount = 0; NTSTATUS RC; ULONG Mode; BOOLEAN UnsafeIoctl = (Vcb->VCBFlags & UDF_VCB_FLAGS_UNSAFE_IOCTL) ? TRUE : FALSE; // Update the real device in the IrpContext from the Vpb. There was no available // file object when the IrpContext was created. // IrpContext->RealDevice = Vpb->RealDevice; KdPrint(("UDFVerifyVolume:\n")); // Acquire shared global access, the termination handler for the // following try statement will free the access. UDFAcquireResourceShared(&(UDFGlobalData.GlobalDataResource),TRUE); UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE); _SEH2_TRY { KdPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); // Check if the real device still needs to be verified. If it doesn't // then obviously someone beat us here and already did the work // so complete the verify irp with success. Otherwise reenable // the real device and get to work. if( !(Vpb->RealDevice->Flags & DO_VERIFY_VOLUME) && ((Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_LOCKED) && !UnsafeIoctl) ) { KdPrint(("UDFVerifyVolume: STATUS_SUCCESS (1)\n")); try_return(RC = STATUS_SUCCESS); } Vcb->VCBFlags &= ~UDF_VCB_FLAGS_UNSAFE_IOCTL; // Verify that there is a disk here. RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY, Vcb->TargetDeviceObject, NULL,0, &MediaChangeCount,sizeof(ULONG), TRUE,&Iosb ); if(!NT_SUCCESS( RC )) { // If we will allow a raw mount then return WRONG_VOLUME to // allow the volume to be mounted by raw. if(FlagOn( IrpSp->Flags, SL_ALLOW_RAW_MOUNT )) { KdPrint(("UDFVerifyVolume: STATUS_WRONG_VOLUME (1)\n")); RC = STATUS_WRONG_VOLUME; } if(UDFIsRawDevice(RC)) { KdPrint(("UDFVerifyVolume: STATUS_WRONG_VOLUME (2)\n")); RC = STATUS_WRONG_VOLUME; } try_return( RC ); } if(Iosb.Information != sizeof(ULONG)) { // Be safe about the count in case the driver didn't fill it in MediaChangeCount = 0; } KdPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); KdPrint(("UDFVerifyVolume: MediaChangeCount=%x, Vcb->MediaChangeCount=%x, UnsafeIoctl=%x\n", MediaChangeCount, Vcb->MediaChangeCount, UnsafeIoctl)); // Verify that the device actually saw a change. If the driver does not // support the MCC, then we must verify the volume in any case. if(MediaChangeCount == 0 || (Vcb->MediaChangeCount != MediaChangeCount) || UnsafeIoctl ) { KdPrint(("UDFVerifyVolume: compare\n")); NewVcb = (PVCB)MyAllocatePool__(NonPagedPool,sizeof(VCB)); if(!NewVcb) try_return(RC=STATUS_INSUFFICIENT_RESOURCES); RtlZeroMemory(NewVcb,sizeof(VCB)); NewVcb->TargetDeviceObject = Vcb->TargetDeviceObject; NewVcb->Vpb = Vpb; // Set the removable media flag based on the real device's // characteristics if(Vpb->RealDevice->Characteristics & FILE_REMOVABLE_MEDIA) { UDFSetFlag( NewVcb->VCBFlags, UDF_VCB_FLAGS_REMOVABLE_MEDIA ); } RC = UDFGetDiskInfo(NewVcb->TargetDeviceObject,NewVcb); if(!NT_SUCCESS(RC)) try_return(RC); // Prevent modification attempts durring Verify NewVcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY | UDF_VCB_FLAGS_MEDIA_READ_ONLY; // Compare physical parameters (phase 1) KdPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); RC = UDFCompareVcb(Vcb,NewVcb, TRUE); if(!NT_SUCCESS(RC)) try_return(RC); if((Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) && Vcb->MountPhErrorCount > MOUNT_ERR_THRESHOLD ) { KdPrint(("UDFVerifyVolume: it was very BAD volume. Do not perform Logical check\n")); goto skip_logical_check; } // Initialize internal cache // in *** READ ONLY *** mode Mode = WCACHE_MODE_ROM; RC = WCacheInit__(&(NewVcb->FastCache), UDFGlobalData.WCacheMaxFrames, UDFGlobalData.WCacheMaxBlocks, NewVcb->WriteBlockSize, 5, NewVcb->BlockSizeBits, UDFGlobalData.WCacheBlocksPerFrameSh, 0/*NewVcb->FirstLBA*/, NewVcb->LastPossibleLBA, Mode, /*WCACHE_CACHE_WHOLE_PACKET*/ 0 | (Vcb->DoNotCompareBeforeWrite ? WCACHE_DO_NOT_COMPARE : 0) | WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS, // speed up mount on bad disks UDFGlobalData.WCacheFramesToKeepFree, UDFTWrite, UDFTRead, #ifdef UDF_ASYNC_IO UDFTWriteAsync, UDFTReadAsync, #else //UDF_ASYNC_IO NULL, NULL, #endif //UDF_ASYNC_IO UDFIsBlockAllocated, UDFUpdateVAT, UDFWCacheErrorHandler); if(!NT_SUCCESS(RC)) try_return(RC); KdPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); RC = UDFGetDiskInfoAndVerify(NewVcb->TargetDeviceObject,NewVcb); KdPrint((" NewVcb->NSRDesc=%x\n", NewVcb->NSRDesc)); if(!NT_SUCCESS(RC)) { if((Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) && (NewVcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) && !(NewVcb->NSRDesc & VRS_ISO9660_FOUND)) { KdPrint(("UDFVerifyVolume: both are RAW -> remount\n", Vcb->Modified)); RC = STATUS_SUCCESS; goto skip_logical_check; } if(RC == STATUS_UNRECOGNIZED_VOLUME) { try_return(RC = STATUS_WRONG_VOLUME); } try_return(RC); } WCacheChFlags__(&(Vcb->FastCache), WCACHE_CACHE_WHOLE_PACKET, // enable cache whole packet WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS); // let user retry request on Bad Blocks NewVcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_MOUNTED; // Compare logical parameters (phase 2) KdPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); RC = UDFCompareVcb(Vcb,NewVcb, FALSE); if(!NT_SUCCESS(RC)) try_return(RC); // We have unitialized WCache, so it is better to // force MOUNT_VOLUME call if(!WCacheIsInitialized__(&(Vcb->FastCache))) try_return(RC = STATUS_WRONG_VOLUME); skip_logical_check:; } KdPrint(("UDFVerifyVolume: compared\n")); KdPrint(("UDFVerifyVolume: Modified=%d\n", Vcb->Modified)); if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED)) { KdPrint(("UDFVerifyVolume: set UDF_VCB_FLAGS_VOLUME_MOUNTED\n")); Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_MOUNTED; Vcb->SoftEjectReq = FALSE; } UDFClearFlag( Vpb->RealDevice->Flags, DO_VERIFY_VOLUME ); try_exit: NOTHING; } _SEH2_FINALLY { // Update the media change count to note that we have verified the volume // at this value Vcb->MediaChangeCount = MediaChangeCount; // If we got the wrong volume, mark the Vcb as not mounted. if(RC == STATUS_WRONG_VOLUME) { KdPrint(("UDFVerifyVolume: clear UDF_VCB_FLAGS_VOLUME_MOUNTED\n")); Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED; Vcb->WriteSecurity = FALSE; // ASSERT(!(Vcb->EjectWaiter)); if(Vcb->EjectWaiter) { UDFReleaseResource(&(Vcb->VCBResource)); UDFStopEjectWaiter(Vcb); UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE); } } else if(NT_SUCCESS(RC) && (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)){ BOOLEAN CacheInitialized = FALSE; KdPrint((" !!! VerifyVolume - QUICK REMOUNT !!!\n")); // Initialize internal cache CacheInitialized = WCacheIsInitialized__(&(Vcb->FastCache)); if(!CacheInitialized) { Mode = WCACHE_MODE_ROM; RC = WCacheInit__(&(Vcb->FastCache), Vcb->WCacheMaxFrames, Vcb->WCacheMaxBlocks, Vcb->WriteBlockSize, 5, Vcb->BlockSizeBits, Vcb->WCacheBlocksPerFrameSh, 0/*Vcb->FirstLBA*/, Vcb->LastPossibleLBA, Mode, /*WCACHE_CACHE_WHOLE_PACKET*/ 0 | (Vcb->DoNotCompareBeforeWrite ? WCACHE_DO_NOT_COMPARE : 0) | (Vcb->CacheChainedIo ? WCACHE_CHAINED_IO : 0), Vcb->WCacheFramesToKeepFree, // UDFTWrite, UDFTRead, UDFTWriteVerify, UDFTReadVerify, #ifdef UDF_ASYNC_IO UDFTWriteAsync, UDFTReadAsync, #else //UDF_ASYNC_IO NULL, NULL, #endif //UDF_ASYNC_IO UDFIsBlockAllocated, UDFUpdateVAT, UDFWCacheErrorHandler); } if(NT_SUCCESS(RC)) { if(!Vcb->VerifyCtx.VInited) { RC = UDFVInit(Vcb); } } if(NT_SUCCESS(RC)) { if(!CacheInitialized) { if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY)) { if(!Vcb->CDR_Mode) { if((Vcb->TargetDeviceObject->DeviceType == FILE_DEVICE_DISK) || CdrwMediaClassEx_IsRAM(Vcb->MediaClassEx)) { KdPrint(("UDFMountVolume: RAM mode\n")); Mode = WCACHE_MODE_RAM; } else { KdPrint(("UDFMountVolume: RW mode\n")); Mode = WCACHE_MODE_RW; } /* if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) { } else { Vcb->WriteSecurity = TRUE; }*/ } else { Mode = WCACHE_MODE_R; } } WCacheSetMode__(&(Vcb->FastCache), Mode); WCacheChFlags__(&(Vcb->FastCache), WCACHE_CACHE_WHOLE_PACKET, // enable cache whole packet WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS); // let user retry request on Bad Blocks } // we can't record ACL on old format disks if(!UDFNtAclSupported(Vcb)) { Vcb->WriteSecurity = FALSE; Vcb->UseExtendedFE = FALSE; } KdPrint(("UDFVerifyVolume: try start EjectWaiter\n")); RC = UDFStartEjectWaiter(Vcb); if(!NT_SUCCESS(RC)) { KdPrint(("UDFVerifyVolume: start EjectWaiter failed\n")); Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED; Vcb->WriteSecurity = FALSE; } } } if(NewVcb) { // Release internal cache KdPrint(("UDFVerifyVolume: delete NewVcb\n")); WCacheFlushAll__(&(NewVcb->FastCache),NewVcb); WCacheRelease__(&(NewVcb->FastCache)); ASSERT(!(NewVcb->EjectWaiter)); // Waiter thread should be already stopped // if MediaChangeCount have changed ASSERT(!(Vcb->EjectWaiter)); UDFCleanupVCB(NewVcb); MyFreePool__(NewVcb); } UDFReleaseResource(&(Vcb->VCBResource)); UDFReleaseResource(&(UDFGlobalData.GlobalDataResource)); } _SEH2_END; // Complete the request if no exception. Irp->IoStatus.Information = 0; Irp->IoStatus.Status = RC; IoCompleteRequest(Irp,IO_DISK_INCREMENT); KdPrint(("UDFVerifyVolume: RC = %x\n", RC)); return RC; } // end UDFVerifyVolume ()
BOOLEAN FatCheckFileAccess ( PIRP_CONTEXT IrpContext, IN UCHAR DirentAttributes, IN ULONG DesiredAccess ) /*++ Routine Description: This routine checks if a desired access is allowed to a file represented by the specified DirentAttriubutes. Arguments: DirentAttributes - Supplies the Dirent attributes to check access for DesiredAccess - Supplies the desired access mask that we are checking for Return Value: BOOLEAN - TRUE if access is allowed and FALSE otherwise --*/ { BOOLEAN Result; DebugTrace(+1, Dbg, "FatCheckFileAccess\n", 0); DebugTrace( 0, Dbg, "DirentAttributes = %8lx\n", DirentAttributes); DebugTrace( 0, Dbg, "DesiredAccess = %8lx\n", DesiredAccess); // // This procedures is programmed like a string of filters each // filter checks to see if some access is allowed, if it is not allowed // the filter return FALSE to the user without further checks otherwise // it moves on to the next filter. The filter check is to check for // desired access flags that are not allowed for a particular dirent // Result = TRUE; try { // // Check for Volume ID or Device Dirents, these are not allowed user // access at all // if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_VOLUME_ID) || FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DEVICE)) { DebugTrace(0, Dbg, "Cannot access volume id or device\n", 0); try_return( Result = FALSE ); } // // Check for a directory Dirent or non directory dirent // if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DIRECTORY)) { // // check the desired access for directory dirent // if (FlagOn(DesiredAccess, ~(DELETE | READ_CONTROL | WRITE_OWNER | WRITE_DAC | SYNCHRONIZE | ACCESS_SYSTEM_SECURITY | FILE_WRITE_DATA | FILE_READ_EA | FILE_WRITE_EA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_TRAVERSE | FILE_DELETE_CHILD | FILE_APPEND_DATA))) { DebugTrace(0, Dbg, "Cannot open directory\n", 0); try_return( Result = FALSE ); } } else { // // check the desired access for a non-directory dirent, we // blackball // FILE_LIST_DIRECTORY, FILE_ADD_FILE, FILE_TRAVERSE, // FILE_ADD_SUBDIRECTORY, and FILE_DELETE_CHILD // if (FlagOn(DesiredAccess, ~(DELETE | READ_CONTROL | WRITE_OWNER | WRITE_DAC | SYNCHRONIZE | ACCESS_SYSTEM_SECURITY | FILE_READ_DATA | FILE_WRITE_DATA | FILE_READ_EA | FILE_WRITE_EA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | FILE_EXECUTE | FILE_APPEND_DATA))) { DebugTrace(0, Dbg, "Cannot open file\n", 0); try_return( Result = FALSE ); } } // // Check for a read-only Dirent // if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) { // // Check the desired access for a read-only dirent, we blackball // WRITE, FILE_APPEND_DATA, FILE_ADD_FILE, // FILE_ADD_SUBDIRECTORY, and FILE_DELETE_CHILD // if (FlagOn(DesiredAccess, ~(DELETE | READ_CONTROL | WRITE_OWNER | WRITE_DAC | SYNCHRONIZE | ACCESS_SYSTEM_SECURITY | FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | FILE_EXECUTE | FILE_LIST_DIRECTORY | FILE_TRAVERSE))) { DebugTrace(0, Dbg, "Cannot open readonly\n", 0); try_return( Result = FALSE ); } } try_exit: NOTHING; } finally { DebugUnwind( FatCheckFileAccess ); DebugTrace(-1, Dbg, "FatCheckFileAccess -> %08lx\n", Result); } UNREFERENCED_PARAMETER( IrpContext ); return Result; }
BOOLEAN FatCheckFileAccess ( PIRP_CONTEXT IrpContext, IN UCHAR DirentAttributes, IN PACCESS_MASK DesiredAccess ) /*++ Routine Description: This routine checks if a desired access is allowed to a file represented by the specified DirentAttriubutes. Arguments: DirentAttributes - Supplies the Dirent attributes to check access for DesiredAccess - Supplies the desired access mask that we are checking for Return Value: BOOLEAN - TRUE if access is allowed and FALSE otherwise --*/ { BOOLEAN Result; DebugTrace(+1, Dbg, "FatCheckFileAccess\n", 0); DebugTrace( 0, Dbg, "DirentAttributes = %8lx\n", DirentAttributes); DebugTrace( 0, Dbg, "DesiredAccess = %8lx\n", *DesiredAccess); PAGED_CODE(); // // This procedures is programmed like a string of filters each // filter checks to see if some access is allowed, if it is not allowed // the filter return FALSE to the user without further checks otherwise // it moves on to the next filter. The filter check is to check for // desired access flags that are not allowed for a particular dirent // Result = TRUE; _SEH2_TRY { // // Check for Volume ID or Device Dirents, these are not allowed user // access at all // if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_VOLUME_ID) || FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DEVICE)) { DebugTrace(0, Dbg, "Cannot access volume id or device\n", 0); try_return( Result = FALSE ); } // // Check the desired access for the object - we only blackball that // we do not understand. The model of filesystems using ACLs is that // they do not type the ACL to the object the ACL is on. Permissions // are not checked for consistency vs. the object type - dir/file. // if (FlagOn(*DesiredAccess, ~(DELETE | READ_CONTROL | WRITE_OWNER | WRITE_DAC | SYNCHRONIZE | ACCESS_SYSTEM_SECURITY | FILE_WRITE_DATA | FILE_READ_EA | FILE_WRITE_EA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_TRAVERSE | FILE_DELETE_CHILD | FILE_APPEND_DATA | MAXIMUM_ALLOWED))) { DebugTrace(0, Dbg, "Cannot open object\n", 0); try_return( Result = FALSE ); } // // Check for a read-only Dirent // if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) { // // Check the desired access for a read-only dirent. AccessMask will contain // the flags we're going to allow. // ACCESS_MASK AccessMask = DELETE | READ_CONTROL | WRITE_OWNER | WRITE_DAC | SYNCHRONIZE | ACCESS_SYSTEM_SECURITY | FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | FILE_EXECUTE | FILE_LIST_DIRECTORY | FILE_TRAVERSE; // // If this is a subdirectory also allow add file/directory and delete. // if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DIRECTORY)) { AccessMask |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | FILE_DELETE_CHILD; } if (FlagOn(*DesiredAccess, ~AccessMask)) { DebugTrace(0, Dbg, "Cannot open readonly\n", 0); try_return( Result = FALSE ); } } try_exit: NOTHING; } _SEH2_FINALLY { DebugUnwind( FatCheckFileAccess ); DebugTrace(-1, Dbg, "FatCheckFileAccess -> %08lx\n", Result); } _SEH2_END; UNREFERENCED_PARAMETER( IrpContext ); return Result; }
NTSTATUS AFSFlushBuffers( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { UNREFERENCED_PARAMETER(LibDeviceObject); AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension; NTSTATUS ntStatus = STATUS_SUCCESS; IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); PFILE_OBJECT pFileObject = pIrpSp->FileObject; AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext; AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2; IO_STATUS_BLOCK iosb = {0}; BOOLEAN bReleaseSectionObject = FALSE; pIrpSp = IoGetCurrentIrpStackLocation( Irp); __Enter { if( pFcb == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSFlushBuffers Attempted access (%p) when pFcb == NULL\n", Irp)); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB || pFcb->Header.NodeTypeCode == AFS_ROOT_ALL ) { // // Once we support ADS's on directories we need to perform a flush ehre // try_return( ntStatus = STATUS_SUCCESS); } else if (pFcb->Header.NodeTypeCode != AFS_FILE_FCB) { // // Nothing to flush Everything but files are write through // try_return( ntStatus = STATUS_INVALID_PARAMETER); } AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT, AFS_TRACE_LEVEL_VERBOSE, "AFSFlushBuffers Acquiring Fcb SectionObject lock %p SHARED %08lX\n", &pFcb->NPFcb->SectionObjectResource, PsGetCurrentThread())); AFSAcquireShared( &pFcb->NPFcb->SectionObjectResource, TRUE); bReleaseSectionObject = TRUE; // // The flush consists of two parts. We firstly flush our // cache (if we have one), then we tell the service to write // to the remote server // __try { CcFlushCache( &pFcb->NPFcb->SectionObjectPointers, NULL, 0, &iosb); if (!NT_SUCCESS( iosb.Status )) { AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSFlushBuffers CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n", pFcb->ObjectInformation->FileId.Cell, pFcb->ObjectInformation->FileId.Volume, pFcb->ObjectInformation->FileId.Vnode, pFcb->ObjectInformation->FileId.Unique, iosb.Status, iosb.Information)); try_return( ntStatus = iosb.Status ); } } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation())) { try_return( ntStatus = GetExceptionCode()); } if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT, AFS_TRACE_LEVEL_VERBOSE, "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n", &pFcb->NPFcb->SectionObjectResource, PsGetCurrentThread())); AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource); bReleaseSectionObject = FALSE; // // Now, flush to the server - if there is stuff to do // ntStatus = AFSFlushExtents( pFcb, &pCcb->AuthGroup); if( !NT_SUCCESS( ntStatus)) { AFSReleaseExtentsWithFlush( pFcb, &pCcb->AuthGroup, TRUE); ntStatus = STATUS_SUCCESS; } } try_exit: if ( bReleaseSectionObject) { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT, AFS_TRACE_LEVEL_VERBOSE, "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n", &pFcb->NPFcb->SectionObjectResource, PsGetCurrentThread())); AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource); } AFSCompleteRequest( Irp, ntStatus); } return ntStatus; }
PXIXFS_LCB xixfs_FCBTLBFindPrefix ( IN PXIXFS_IRPCONTEXT IrpContext, IN OUT PXIXFS_FCB *CurrentFcb, IN OUT PUNICODE_STRING RemainingName, IN BOOLEAN bIgnoreCase ) { UNICODE_STRING LocalRemainingName; UNICODE_STRING FinalName; PXIXFS_LCB NameLink; PXIXFS_LCB CurrentLcb = NULL; BOOLEAN Waitable = FALSE; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CREATE|DEBUG_TARGET_CLOSE| DEBUG_TARGET_FCB), ("Enter xixfs_FCBTLBFindPrefix \n" )); // // Check inputs. // ASSERT_IRPCONTEXT( IrpContext ); ASSERT_FCB( *CurrentFcb ); ASSERT_EXCLUSIVE_FCB( *CurrentFcb ); Waitable = XIXCORE_TEST_FLAGS(IrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT); try{ // // Make a local copy of the input strings. // LocalRemainingName = *RemainingName; // // Loop until we find the longest matching prefix. // while (TRUE) { // // If there are no characters left or we are not at an IndexFcb then // return immediately. // if ((LocalRemainingName.Length == 0) || (XifsSafeNodeType( *CurrentFcb ) != XIFS_NODE_FCB)) { try_return(TRUE); // return CurrentLcb; } if((*CurrentFcb)->XixcoreFcb.FCBType != FCB_TYPE_DIR){ try_return(TRUE); //return CurrentLcb; } // // Split off the next component from the name. // FsRtlDissectName( LocalRemainingName, &FinalName, &LocalRemainingName); // // Check if this name is in the splay tree for this Fcb. // if(bIgnoreCase){ NameLink = xixfs_NLFindNameLinkIgnoreCase( IrpContext, &(*CurrentFcb)->IgnoreCaseRoot, &FinalName ); }else{ NameLink = xixfs_NLFindNameLink( IrpContext, &(*CurrentFcb)->Root, &FinalName ); } // // If we didn't find a match then exit. // if (NameLink == NULL) { break; } // // // //if ( XIXCORE_TEST_FLAGS(NameLink->LCBFlags, // (XIFSD_LCB_STATE_LINK_IS_GONE)) ) //{ // break; //} CurrentLcb = NameLink; // // Update the caller's remaining name string to reflect the fact that we found // a match. // *RemainingName = LocalRemainingName; // // Move down to the next component in the tree. Acquire without waiting. // If this fails then lock the Fcb to reference this Fcb and then drop // the parent and acquire the child. // ASSERT( NameLink->ParentFcb == *CurrentFcb ); if (!XifsdAcquireFcbExclusive( Waitable, NameLink->ChildFcb, FALSE )) { // // If we can't wait then raise CANT_WAIT. // if ( Waitable) { XifsdRaiseStatus( IrpContext, STATUS_CANT_WAIT ); } XifsdLockVcb( IrpContext, IrpContext->VCB ); NameLink->ChildFcb->FCBReference += 1; NameLink->Reference += 1; XifsdUnlockVcb( IrpContext, IrpContext->VCB ); XifsdReleaseFcb( IrpContext, *CurrentFcb ); XifsdAcquireFcbExclusive( Waitable, NameLink->ChildFcb, FALSE ); XifsdLockVcb( IrpContext, IrpContext->VCB ); NameLink->ChildFcb->FCBReference -= 1; NameLink->Reference -= 1; XifsdUnlockVcb( IrpContext, IrpContext->VCB ); } else { XifsdReleaseFcb( IrpContext, *CurrentFcb ); } *CurrentFcb = NameLink->ChildFcb; } }finally{ if(AbnormalTermination()){ ExRaiseStatus(STATUS_CANT_WAIT); } } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CREATE|DEBUG_TARGET_CLOSE| DEBUG_TARGET_FCB), ("Exit xixfs_FCBTLBFindPrefix \n" )); return CurrentLcb; }
NTSTATUS NdasFatSecondaryQueryDirectory ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This routine performs the query directory operation. It is responsible for either completing of enqueuing the input Irp. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; PVCB Vcb; PDCB Dcb; PCCB Ccb; PBCB Bcb; ULONG i; PUCHAR Buffer; CLONG UserBufferLength; PUNICODE_STRING UniArgFileName; WCHAR LongFileNameBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE]; UNICODE_STRING LongFileName; FILE_INFORMATION_CLASS FileInformationClass; ULONG FileIndex; BOOLEAN RestartScan; BOOLEAN ReturnSingleEntry; BOOLEAN IndexSpecified; BOOLEAN InitialQuery; VBO CurrentVbo; BOOLEAN UpdateCcb; PDIRENT Dirent; UCHAR Fat8Dot3Buffer[12]; OEM_STRING Fat8Dot3String; ULONG DiskAllocSize; ULONG NextEntry; ULONG LastEntry; PFILE_DIRECTORY_INFORMATION DirInfo; PFILE_FULL_DIR_INFORMATION FullDirInfo; PFILE_BOTH_DIR_INFORMATION BothDirInfo; PFILE_ID_FULL_DIR_INFORMATION IdFullDirInfo; PFILE_ID_BOTH_DIR_INFORMATION IdBothDirInfo; PFILE_NAMES_INFORMATION NamesInfo; #if 1 PVOLUME_DEVICE_OBJECT volDo; BOOLEAN secondarySessionResourceAcquired = FALSE; PSECONDARY_REQUEST secondaryRequest = NULL; PNDFS_REQUEST_HEADER ndfsRequestHeader; PNDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PNDFS_WINXP_REPLY_HEADER ndfsWinxpReplytHeader; _U8 *ndfsWinxpRequestData; LARGE_INTEGER timeOut; struct QueryDirectory queryDirectory; PVOID inputBuffer; ULONG inputBufferLength; ULONG returnedDataSize; #endif PAGED_CODE(); // // Get the current Stack location // IrpSp = IoGetCurrentIrpStackLocation( Irp ); // // Display the input values. // DebugTrace(+1, Dbg, "FatQueryDirectory...\n", 0); DebugTrace( 0, Dbg, " Wait = %08lx\n", FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp); DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.QueryDirectory.Length); DebugTrace( 0, Dbg, " ->FileName = %08lx\n", IrpSp->Parameters.QueryDirectory.FileName); DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.QueryDirectory.FileInformationClass); DebugTrace( 0, Dbg, " ->FileIndex = %08lx\n", IrpSp->Parameters.QueryDirectory.FileIndex); DebugTrace( 0, Dbg, " ->UserBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer); DebugTrace( 0, Dbg, " ->RestartScan = %08lx\n", FlagOn( IrpSp->Flags, SL_RESTART_SCAN )); DebugTrace( 0, Dbg, " ->ReturnSingleEntry = %08lx\n", FlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY )); DebugTrace( 0, Dbg, " ->IndexSpecified = %08lx\n", FlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED )); // // Reference our input parameters to make things easier // UserBufferLength = IrpSp->Parameters.QueryDirectory.Length; FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass; FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex; UniArgFileName = (PUNICODE_STRING) IrpSp->Parameters.QueryDirectory.FileName; RestartScan = BooleanFlagOn(IrpSp->Flags, SL_RESTART_SCAN); ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY); IndexSpecified = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED); // // Check on the type of open. We return invalid parameter for all // but UserDirectoryOpens. Also check that the filename is a valid // UNICODE string. // if (FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Dcb, &Ccb) != UserDirectoryOpen || (UniArgFileName && UniArgFileName->Length % sizeof(WCHAR))) { FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); DebugTrace(-1, Dbg, "FatQueryDirectory -> STATUS_INVALID_PARAMETER\n", 0); return STATUS_INVALID_PARAMETER; } #if 1 if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) { ASSERT( FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) ); FatCompleteRequest( IrpContext, Irp, STATUS_FILE_CORRUPT_ERROR ); DebugTrace2( -1, Dbg, ("NtfsCommonDirectoryControl -> STATUS_FILE_CORRUPT_ERROR\n") ); return STATUS_FILE_CORRUPT_ERROR; } #endif // // Initialize the local variables. // Bcb = NULL; UpdateCcb = TRUE; Dirent = NULL; Fat8Dot3String.MaximumLength = 12; Fat8Dot3String.Buffer = Fat8Dot3Buffer; LongFileName.Length = 0; LongFileName.MaximumLength = sizeof( LongFileNameBuffer); LongFileName.Buffer = LongFileNameBuffer; InitialQuery = (BOOLEAN)((Ccb->UnicodeQueryTemplate.Buffer == NULL) && !FlagOn(Ccb->Flags, CCB_FLAG_MATCH_ALL)); Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; DiskAllocSize = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster; // // If this is the initial query, then grab exclusive access in // order to update the search string in the Ccb. We may // discover that we are not the initial query once we grab the Fcb // and downgrade our status. // if (InitialQuery) { if (!FatAcquireExclusiveFcb( IrpContext, Dcb )) { DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0); Status = FatFsdPostRequest( IrpContext, Irp ); DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status); return Status; } if (Ccb->UnicodeQueryTemplate.Buffer != NULL) { InitialQuery = FALSE; FatConvertToSharedFcb( IrpContext, Dcb ); } } else { if (!FatAcquireSharedFcb( IrpContext, Dcb )) { DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0); Status = FatFsdPostRequest( IrpContext, Irp ); DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status); return Status; } } try { ULONG BaseLength; ULONG BytesConverted; // // If we are in the Fsp now because we had to wait earlier, // we must map the user buffer, otherwise we can use the // user's buffer directly. // Buffer = FatMapUserBuffer( IrpContext, Irp ); #if 1 volDo = CONTAINING_RECORD( Vcb, VOLUME_DEVICE_OBJECT, Vcb ); secondarySessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->SessionResource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) { NDASFAT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST ); FatRaiseStatus( IrpContext, STATUS_CANT_WAIT ); } queryDirectory.FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex; queryDirectory.FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass; queryDirectory.FileName = IrpSp->Parameters.QueryDirectory.FileName; queryDirectory.Length = IrpSp->Parameters.QueryDirectory.Length; inputBuffer = (queryDirectory.FileName) ? (queryDirectory.FileName->Buffer) : NULL; inputBufferLength = (queryDirectory.FileName) ? (queryDirectory.FileName->Length) : 0; if (queryDirectory.FileName) { DebugTrace2( 0, Dbg, ("NdNtfsSecondaryQueryDirectory: queryFileName = %wZ\n", queryDirectory.FileName) ); } ASSERT( inputBufferLength <= volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize ); ASSERT( UserBufferLength <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize ); secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, IRP_MJ_DIRECTORY_CONTROL, ((inputBufferLength > UserBufferLength) ? inputBufferLength : UserBufferLength) ); if (secondaryRequest == NULL) { try_return( Status = STATUS_INSUFFICIENT_RESOURCES ); } ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader; INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_DIRECTORY_CONTROL, inputBufferLength ); ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1); ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData ); INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, Irp, IrpSp, Ccb->PrimaryFileHandle ); ndfsWinxpRequestHeader->QueryDirectory.Length = UserBufferLength; ndfsWinxpRequestHeader->QueryDirectory.FileInformationClass = queryDirectory.FileInformationClass; ndfsWinxpRequestHeader->QueryDirectory.FileIndex = queryDirectory.FileIndex; ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1); if (inputBufferLength) RtlCopyMemory( ndfsWinxpRequestData, inputBuffer, inputBufferLength ); secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE; QueueingSecondaryRequest( volDo->Secondary, secondaryRequest ); timeOut.QuadPart = -NDASFAT_TIME_OUT; Status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut ); KeClearEvent( &secondaryRequest->CompleteEvent ); if (Status != STATUS_SUCCESS) { secondaryRequest = NULL; try_return( Status = STATUS_IO_DEVICE_ERROR ); } SecondaryReleaseResourceLite( IrpContext, &volDo->SessionResource ); secondarySessionResourceAcquired = FALSE; if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) { if (IrpContext->OriginatingIrp) PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp ); DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) ); NDASFAT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST ); FatRaiseStatus( IrpContext, STATUS_CANT_WAIT ); } ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData; Status = Irp->IoStatus.Status = ndfsWinxpReplytHeader->Status; Irp->IoStatus.Information = ndfsWinxpReplytHeader->Information; returnedDataSize = secondaryRequest->NdfsReplyHeader.MessageSize - sizeof(NDFS_REPLY_HEADER) - sizeof(NDFS_WINXP_REPLY_HEADER); if (returnedDataSize) { ASSERT( ndfsWinxpReplytHeader->Information != 0 ); ASSERT(returnedDataSize <= ADD_ALIGN8(queryDirectory.Length)); ASSERT( Buffer ); RtlCopyMemory( Buffer, (_U8 *)(ndfsWinxpReplytHeader+1), (returnedDataSize < queryDirectory.Length) ? returnedDataSize : queryDirectory.Length ); } #endif #if 0 // // Make sure the Dcb is still good. // FatVerifyFcb( IrpContext, Dcb ); // // Determine where to start the scan. Highest priority is given // to the file index. Lower priority is the restart flag. If // neither of these is specified, then the Vbo offset field in the // Ccb is used. // if (IndexSpecified) { CurrentVbo = FileIndex + sizeof( DIRENT ); } else if (RestartScan) { CurrentVbo = 0; } else { CurrentVbo = Ccb->OffsetToStartSearchFrom; } // // If this is the first try then allocate a buffer for the file // name. // if (InitialQuery) { // // If either: // // - No name was specified // - An empty name was specified // - We received a '*' // - The user specified the DOS equivolent of ????????.??? // // then match all names. // if ((UniArgFileName == NULL) || (UniArgFileName->Length == 0) || (UniArgFileName->Buffer == NULL) || ((UniArgFileName->Length == sizeof(WCHAR)) && (UniArgFileName->Buffer[0] == L'*')) || ((UniArgFileName->Length == 12*sizeof(WCHAR)) && (RtlEqualMemory( UniArgFileName->Buffer, Fat8QMdot3QM, 12*sizeof(WCHAR) )))) { Ccb->ContainsWildCards = TRUE; SetFlag( Ccb->Flags, CCB_FLAG_MATCH_ALL ); } else { BOOLEAN ExtendedName = FALSE; OEM_STRING LocalBestFit; // // First and formost, see if the name has wild cards. // Ccb->ContainsWildCards = FsRtlDoesNameContainWildCards( UniArgFileName ); // // Now check to see if the name contains any extended // characters // for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) { if (UniArgFileName->Buffer[i] >= 0x80) { ExtendedName = TRUE; break; } } // // OK, now do the conversions we need. // if (ExtendedName) { Status = RtlUpcaseUnicodeString( &Ccb->UnicodeQueryTemplate, UniArgFileName, TRUE ); if (!NT_SUCCESS(Status)) { try_return( Status ); } SetFlag( Ccb->Flags, CCB_FLAG_FREE_UNICODE ); // // Upcase the name and convert it to the Oem code page. // Status = RtlUpcaseUnicodeStringToCountedOemString( &LocalBestFit, UniArgFileName, TRUE ); // // If this conversion failed for any reason other than // an unmappable character fail the request. // if (!NT_SUCCESS(Status)) { if (Status == STATUS_UNMAPPABLE_CHARACTER) { SetFlag( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE ); } else { try_return( Status ); } } else { SetFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT ); } } else { PVOID Buffers; // // This case is optimized because I know I only have to // worry about a-z. // Buffers = FsRtlAllocatePoolWithTag( PagedPool, UniArgFileName->Length + UniArgFileName->Length / sizeof(WCHAR), TAG_FILENAME_BUFFER ); Ccb->UnicodeQueryTemplate.Buffer = Buffers; Ccb->UnicodeQueryTemplate.Length = UniArgFileName->Length; Ccb->UnicodeQueryTemplate.MaximumLength = UniArgFileName->Length; LocalBestFit.Buffer = (PUCHAR)Buffers + UniArgFileName->Length; LocalBestFit.Length = UniArgFileName->Length / sizeof(WCHAR); LocalBestFit.MaximumLength = LocalBestFit.Length; SetFlag( Ccb->Flags, CCB_FLAG_FREE_UNICODE ); for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) { WCHAR c = UniArgFileName->Buffer[i]; LocalBestFit.Buffer[i] = (UCHAR) (Ccb->UnicodeQueryTemplate.Buffer[i] = (c < 'a' ? c : c <= 'z' ? c - ('a' - 'A') : c)); } } // // At this point we now have the upcased unicode name, // and the two Oem names if they could be represented in // this code page. // // Now determine if the Oem names are legal for what we // going to try and do. Mark them as not usable is they // are not legal. Note that we can optimize extended names // since they are actually both the same string. // if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE ) && !FatIsNameShortOemValid( IrpContext, LocalBestFit, Ccb->ContainsWildCards, FALSE, FALSE )) { if (ExtendedName) { RtlFreeOemString( &LocalBestFit ); ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT ); } SetFlag( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE ); } // // OK, now both locals oem strings correctly reflect their // usability. Now we want to load up the Ccb structure. // // Now we will branch on two paths of wheather the name // is wild or not. // if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE )) { if (Ccb->ContainsWildCards) { Ccb->OemQueryTemplate.Wild = LocalBestFit; } else { FatStringTo8dot3( IrpContext, LocalBestFit, &Ccb->OemQueryTemplate.Constant ); if (FlagOn(Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT)) { RtlFreeOemString( &LocalBestFit ); ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT ); } } } } // // We convert to shared access. // FatConvertToSharedFcb( IrpContext, Dcb ); } LastEntry = 0; NextEntry = 0; switch (FileInformationClass) { case FileDirectoryInformation: BaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION, FileName[0] ); break; case FileFullDirectoryInformation: BaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION, FileName[0] ); break; case FileIdFullDirectoryInformation: BaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION, FileName[0] ); break; case FileNamesInformation: BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION, FileName[0] ); break; case FileBothDirectoryInformation: BaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, FileName[0] ); break; case FileIdBothDirectoryInformation: BaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION, FileName[0] ); break; default: try_return( Status = STATUS_INVALID_INFO_CLASS ); } // // At this point we are about to enter our query loop. We have // determined the index into the directory file to begin the // search. LastEntry and NextEntry are used to index into the user // buffer. LastEntry is the last entry we've added, NextEntry is // current one we're working on. If NextEntry is non-zero, then // at least one entry was added. // while ( TRUE ) { VBO NextVbo; ULONG FileNameLength; ULONG BytesRemainingInBuffer; DebugTrace(0, Dbg, "FatQueryDirectory -> Top of loop\n", 0); // // If the user had requested only a single match and we have // returned that, then we stop at this point. // if (ReturnSingleEntry && NextEntry != 0) { try_return( Status ); } // // We call FatLocateDirent to lock down the next matching dirent. // FatLocateDirent( IrpContext, Dcb, Ccb, CurrentVbo, &Dirent, &Bcb, &NextVbo, NULL, &LongFileName); // // If we didn't receive a dirent, then we are at the end of the // directory. If we have returned any files, we exit with // success, otherwise we return STATUS_NO_MORE_FILES. // if (!Dirent) { DebugTrace(0, Dbg, "FatQueryDirectory -> No dirent\n", 0); if (NextEntry == 0) { UpdateCcb = FALSE; if (InitialQuery) { Status = STATUS_NO_SUCH_FILE; } else { Status = STATUS_NO_MORE_FILES; } } try_return( Status ); } // // Protect access to the user buffer with an exception handler. // Since (at our request) IO doesn't buffer these requests, we have // to guard against a user messing with the page protection and other // such trickery. // try { if (LongFileName.Length == 0) { // // Now we have an entry to return to our caller. We'll convert // the name from the form in the dirent to a <name>.<ext> form. // We'll case on the type of information requested and fill up // the user buffer if everything fits. // Fat8dot3ToString( IrpContext, Dirent, TRUE, &Fat8Dot3String ); // // Determine the UNICODE length of the file name. // FileNameLength = RtlOemStringToCountedUnicodeSize(&Fat8Dot3String); // // Here are the rules concerning filling up the buffer: // // 1. The Io system garentees that there will always be // enough room for at least one base record. // // 2. If the full first record (including file name) cannot // fit, as much of the name as possible is copied and // STATUS_BUFFER_OVERFLOW is returned. // // 3. If a subsequent record cannot completely fit into the // buffer, none of it (as in 0 bytes) is copied, and // STATUS_SUCCESS is returned. A subsequent query will // pick up with this record. // BytesRemainingInBuffer = UserBufferLength - NextEntry; if ( (NextEntry != 0) && ( (BaseLength + FileNameLength > BytesRemainingInBuffer) || (UserBufferLength < NextEntry) ) ) { DebugTrace(0, Dbg, "Next entry won't fit\n", 0); try_return( Status = STATUS_SUCCESS ); } ASSERT( BytesRemainingInBuffer >= BaseLength ); // // Zero the base part of the structure. // RtlZeroMemory( &Buffer[NextEntry], BaseLength ); switch ( FileInformationClass ) { // // Now fill the base parts of the strucure that are applicable. // case FileBothDirectoryInformation: case FileFullDirectoryInformation: case FileIdBothDirectoryInformation: case FileIdFullDirectoryInformation: DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0); // // Get the Ea file length. // FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry]; // // If the EAs are corrupt, ignore the error. We don't want // to abort the directory query. // try { FatGetEaLength( IrpContext, Vcb, Dirent, &FullDirInfo->EaSize ); } except(EXCEPTION_EXECUTE_HANDLER) { FatResetExceptionState( IrpContext ); FullDirInfo->EaSize = 0; } case FileDirectoryInformation: DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry]; FatGetDirTimes( IrpContext, Dirent, DirInfo ); DirInfo->EndOfFile.QuadPart = Dirent->FileSize; if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) { DirInfo->AllocationSize.QuadPart = (((Dirent->FileSize + DiskAllocSize - 1) / DiskAllocSize) * DiskAllocSize ); } DirInfo->FileAttributes = Dirent->Attributes != 0 ? Dirent->Attributes : FILE_ATTRIBUTE_NORMAL; DirInfo->FileIndex = NextVbo; DirInfo->FileNameLength = FileNameLength; DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String); break; case FileNamesInformation: DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0); NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry]; NamesInfo->FileIndex = NextVbo; NamesInfo->FileNameLength = FileNameLength; DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String ); break; default: FatBugCheck( FileInformationClass, 0, 0 ); } BytesConverted = 0; Status = RtlOemToUnicodeN( (PWCH)&Buffer[NextEntry + BaseLength], BytesRemainingInBuffer - BaseLength, &BytesConverted, Fat8Dot3String.Buffer, Fat8Dot3String.Length ); // // Check for the case that a single entry doesn't fit. // This should only get this far on the first entry // if (BytesConverted < FileNameLength) { ASSERT( NextEntry == 0 ); Status = STATUS_BUFFER_OVERFLOW; } // // Set up the previous next entry offset // *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry; // // And indicate how much of the user buffer we have currently // used up. We must compute this value before we long align // ourselves for the next entry // Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) + BaseLength + BytesConverted; // // If something happened with the conversion, bail here. // if ( !NT_SUCCESS( Status ) ) { try_return( NOTHING ); } } else { ULONG ShortNameLength; FileNameLength = LongFileName.Length; // // Here are the rules concerning filling up the buffer: // // 1. The Io system garentees that there will always be // enough room for at least one base record. // // 2. If the full first record (including file name) cannot // fit, as much of the name as possible is copied and // STATUS_BUFFER_OVERFLOW is returned. // // 3. If a subsequent record cannot completely fit into the // buffer, none of it (as in 0 bytes) is copied, and // STATUS_SUCCESS is returned. A subsequent query will // pick up with this record. // BytesRemainingInBuffer = UserBufferLength - NextEntry; if ( (NextEntry != 0) && ( (BaseLength + FileNameLength > BytesRemainingInBuffer) || (UserBufferLength < NextEntry) ) ) { DebugTrace(0, Dbg, "Next entry won't fit\n", 0); try_return( Status = STATUS_SUCCESS ); } ASSERT( BytesRemainingInBuffer >= BaseLength ); // // Zero the base part of the structure. // RtlZeroMemory( &Buffer[NextEntry], BaseLength ); switch ( FileInformationClass ) { // // Now fill the base parts of the strucure that are applicable. // case FileBothDirectoryInformation: case FileIdBothDirectoryInformation: BothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&Buffer[NextEntry]; // // Now we have an entry to return to our caller. We'll convert // the name from the form in the dirent to a <name>.<ext> form. // We'll case on the type of information requested and fill up // the user buffer if everything fits. // Fat8dot3ToString( IrpContext, Dirent, FALSE, &Fat8Dot3String ); ASSERT( Fat8Dot3String.Length <= 12 ); Status = RtlOemToUnicodeN( &BothDirInfo->ShortName[0], 12*sizeof(WCHAR), &ShortNameLength, Fat8Dot3String.Buffer, Fat8Dot3String.Length ); ASSERT( Status != STATUS_BUFFER_OVERFLOW ); ASSERT( ShortNameLength <= 12*sizeof(WCHAR) ); // // Copy the length into the dirinfo structure. Note // that the LHS below is a USHORT, so it can not // be specificed as the OUT parameter above. // BothDirInfo->ShortNameLength = (UCHAR)ShortNameLength; // // If something happened with the conversion, bail here. // if ( !NT_SUCCESS( Status ) ) { try_return( NOTHING ); } case FileFullDirectoryInformation: case FileIdFullDirectoryInformation: DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0); // // Get the Ea file length. // FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry]; // // If the EAs are corrupt, ignore the error. We don't want // to abort the directory query. // try { FatGetEaLength( IrpContext, Vcb, Dirent, &FullDirInfo->EaSize ); } except(EXCEPTION_EXECUTE_HANDLER) { FatResetExceptionState( IrpContext ); FullDirInfo->EaSize = 0; } case FileDirectoryInformation: DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry]; FatGetDirTimes( IrpContext, Dirent, DirInfo ); DirInfo->EndOfFile.QuadPart = Dirent->FileSize; if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) { DirInfo->AllocationSize.QuadPart = ( (( Dirent->FileSize + DiskAllocSize - 1 ) / DiskAllocSize ) * DiskAllocSize ); } DirInfo->FileAttributes = Dirent->Attributes != 0 ? Dirent->Attributes : FILE_ATTRIBUTE_NORMAL; DirInfo->FileIndex = NextVbo; DirInfo->FileNameLength = FileNameLength; DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String); break; case FileNamesInformation: DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0); NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry]; NamesInfo->FileIndex = NextVbo; NamesInfo->FileNameLength = FileNameLength; DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String ); break; default: FatBugCheck( FileInformationClass, 0, 0 ); } BytesConverted = BytesRemainingInBuffer - BaseLength >= FileNameLength ? FileNameLength : BytesRemainingInBuffer - BaseLength; RtlCopyMemory( &Buffer[NextEntry + BaseLength], &LongFileName.Buffer[0], BytesConverted ); // // Set up the previous next entry offset // *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry; // // And indicate how much of the user buffer we have currently // used up. We must compute this value before we long align // ourselves for the next entry // Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) + BaseLength + BytesConverted; // // Check for the case that a single entry doesn't fit. // This should only get this far on the first entry. // if (BytesConverted < FileNameLength) { ASSERT( NextEntry == 0 ); try_return( Status = STATUS_BUFFER_OVERFLOW ); } } // // Finish up by filling in the FileId // switch ( FileInformationClass ) { case FileIdBothDirectoryInformation: IdBothDirInfo = (PFILE_ID_BOTH_DIR_INFORMATION)&Buffer[NextEntry]; IdBothDirInfo->FileId.QuadPart = FatGenerateFileIdFromDirentAndOffset( Dcb, Dirent, NextVbo ); break; case FileIdFullDirectoryInformation: IdFullDirInfo = (PFILE_ID_FULL_DIR_INFORMATION)&Buffer[NextEntry]; IdFullDirInfo->FileId.QuadPart = FatGenerateFileIdFromDirentAndOffset( Dcb, Dirent, NextVbo ); break; default: break; } } except (EXCEPTION_EXECUTE_HANDLER) { // // We had a problem filling in the user's buffer, so stop and // fail this request. This is the only reason any exception // would have occured at this level. // Irp->IoStatus.Information = 0; UpdateCcb = FALSE; try_return( Status = GetExceptionCode()); } // // Set ourselves up for the next iteration // LastEntry = NextEntry; NextEntry += (ULONG)QuadAlign(BaseLength + BytesConverted); CurrentVbo = NextVbo + sizeof( DIRENT ); } #endif try_exit: NOTHING; } finally {
IO_STATUS_BLOCK MsOpenMailslotRootDirectory( IN PROOT_DCB RootDcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess ) { IO_STATUS_BLOCK iosb; PAGED_CODE(); DebugTrace( +1, Dbg, "MsOpenMailslotRootDirectory, RootDcb = %08lx\n", (ULONG)RootDcb); try { // // Set the new share access. // if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess, ShareAccess, FileObject, &RootDcb->ShareAccess, TRUE ))) { DebugTrace(0, Dbg, "bad share access\n", 0); try_return( NOTHING ); } // // Supply the file object with a referenced pointer to the root DCB. // MsAcquireGlobalLock(); MsReferenceNode( &RootDcb->Header ); MsReleaseGlobalLock(); MsSetFileObject( FileObject, RootDcb, MsCreateRootDcbCcb() ); // // Set the return status. // iosb.Status = STATUS_SUCCESS; iosb.Information = FILE_OPENED; try_exit: NOTHING; } finally { DebugTrace(-1, Dbg, "MsOpenMailslotRootDirectory -> iosb.Status = %08lx\n", iosb.Status); } // // Return to the caller. // return iosb; }
IO_STATUS_BLOCK MsOpenMailslotFileSystem ( IN PVCB Vcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess ) { IO_STATUS_BLOCK iosb; PAGED_CODE(); DebugTrace(+1, Dbg, "MsOpenMailslotFileSystem, Vcb = %08lx\n", (ULONG)Vcb); try { // // Set the new share access // if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess, ShareAccess, FileObject, &Vcb->ShareAccess, TRUE ))) { DebugTrace(0, Dbg, "bad share access\n", 0); try_return( NOTHING ); } // // Supply the file object with a referenced pointer to the VCB. // MsAcquireGlobalLock(); MsReferenceNode( &Vcb->Header ); if (Vcb->Header.ReferenceCount == 2) { // // Set the driver paging back to normal // MmResetDriverPaging(MsOpenMailslotFileSystem); } MsReleaseGlobalLock(); MsSetFileObject( FileObject, Vcb, NULL ); // // Set the return status. // iosb.Status = STATUS_SUCCESS; iosb.Information = FILE_OPENED; try_exit: NOTHING; } finally { DebugTrace(-1, Dbg, "MsOpenMailslotFileSystem -> Iosb.Status = %08lx\n", iosb.Status); } // // Return to the caller. // return iosb; }
NTSTATUS NTAPI Ext2PassDownSingleReadWriteIRP( PtrExt2IrpContext PtrIrpContext, PIRP PtrIrp, PtrExt2VCB PtrVCB, LARGE_INTEGER ByteOffset, uint32 ReadWriteLength, BOOLEAN SynchronousIo) { NTSTATUS RC = STATUS_SUCCESS; PEXT2_IO_CONTEXT PtrIoContext = NULL; PKEVENT PtrSyncEvent = NULL; PIO_STACK_LOCATION PtrIrpNextSp = NULL; try { if( !PtrIrp->MdlAddress ) { Ext2LockCallersBuffer( PtrIrp, TRUE, ReadWriteLength ); } if( SynchronousIo ) { PtrSyncEvent = Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) ) ); if ( !PtrSyncEvent ) { RC = STATUS_INSUFFICIENT_RESOURCES; try_return(); } KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE ); } // // Allocate and initialize a completion context // PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) ) ); if ( !PtrIoContext ) { RC = STATUS_INSUFFICIENT_RESOURCES; try_return(); } RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) ); PtrIoContext->Count = 1; PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT; PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT ); PtrIoContext->PtrMasterIrp = NULL; PtrIoContext->PtrSyncEvent = PtrSyncEvent; PtrIoContext->ReadWriteLength = ReadWriteLength; IoSetCompletionRoutine( PtrIrp, SynchronousIo ? Ext2SingleSyncCompletionRoutine: Ext2SingleAsyncCompletionRoutine, PtrIoContext, TRUE, TRUE, TRUE ); // // Setup the next IRP stack location in the associated Irp for the disk // driver beneath us. // PtrIrpNextSp = IoGetNextIrpStackLocation( PtrIrp ); // // Setup the Stack location to do a read from the disk driver. // PtrIrpNextSp->MajorFunction = PtrIrpContext->MajorFunction; if( PtrIrpContext->MajorFunction == IRP_MJ_READ ) { PtrIrpNextSp->Parameters.Read.Length = ReadWriteLength; PtrIrpNextSp->Parameters.Read.ByteOffset = ByteOffset; } else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE ) { PtrIrpNextSp->Parameters.Write.Length = ReadWriteLength; PtrIrpNextSp->Parameters.Write.ByteOffset = ByteOffset; } // // Issue the read / write request // RC = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp); if( SynchronousIo ) { // // Wait for completion... // RC = KeWaitForSingleObject( &PtrIoContext->PtrSyncEvent, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL ); RC = STATUS_SUCCESS; } else { RC = STATUS_PENDING; } try_exit: NOTHING; } finally { if( PtrSyncEvent ) { DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrSyncEvent ); ExFreePool( PtrSyncEvent ); } if( PtrIoContext && !( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) ) { // // This means we are getting out of // this function without doing a read / write // due to an error, maybe... // DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrIoContext ); ExFreePool( PtrIoContext ); } } return RC; }
NTSTATUS AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo) { NTSTATUS ntStatus = STATUS_SUCCESS; LARGE_INTEGER cacheSizeBytes; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; OBJECT_ATTRIBUTES stObjectAttribs; IO_STATUS_BLOCK stIoStatus; UNICODE_STRING uniServiceName; __Enter { // // First this is to load the library // RtlInitUnicodeString( &uniServiceName, AFS_REDIR_LIBRARY_SERVICE_ENTRY); ntStatus = AFSLoadLibrary( 0, &uniServiceName); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n", ntStatus); try_return( ntStatus); } // // Save off the cache file information // pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize; pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount; pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength; cacheSizeBytes = RedirInitInfo->ExtentCount; cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize; AFSDumpFileLocation.Length = 0; AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR)); AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, AFSDumpFileLocation.MaximumLength, AFS_GENERIC_MEMORY_23_TAG); if( AFSDumpFileLocation.Buffer == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( AFSDumpFileLocation.Buffer, L"\\??\\", 4 * sizeof( WCHAR)); AFSDumpFileLocation.Length = 4 * sizeof( WCHAR); RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)], (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset), RedirInitInfo->DumpFileLocationLength); AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength; // // Be sure the shutdown flag is not set // ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN); // // Set up the Throttles. // // Max IO is 10% of the cache, or the value in the registry, // with a minimum of 5Mb (and a maximum of 50% cache size) // if( AFSMaxDirectIo) { // // collect what the user // pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo; pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204)) { pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204; } // // For small cache configurations ... // if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2) { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } // // Maximum Dirty is 50% of the cache, or the value in the // registry. No minimum, maximum of 90% of cache size. // if (AFSMaxDirtyFile) { pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile; pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2; } cacheSizeBytes.QuadPart *= 9; cacheSizeBytes.QuadPart = cacheSizeBytes.QuadPart / 10; if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart) { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart; } // // Store off any flags for the file system // if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES)) { // // Hide files which begin with . // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES); } if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 && RedirInitInfo->MemoryCacheLength.QuadPart != 0) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; #ifdef AMD64 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.QuadPart, RedirInitInfo->MemoryCacheLength.QuadPart); #else pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.LowPart, RedirInitInfo->MemoryCacheLength.LowPart); #endif if( pDevExt->Specific.RDR.CacheMdl != NULL) { __try { MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl, KernelMode, IoModifyAccess); pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl, NormalPagePriority); } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { IoFreeMdl( pDevExt->Specific.RDR.CacheMdl); pDevExt->Specific.RDR.CacheMdl = NULL; } if( pDevExt->Specific.RDR.CacheMdl != NULL) { pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength; ntStatus = STATUS_SUCCESS; } } }
/************************************************************************* * * Function: Ext2PassDownMultiReadWriteIRP() * * Description: * pass down multiple read IRPs as Associated IRPs * * Expected Interrupt Level (for execution) : * * ? * * Return Value: STATUS_SUCCESS / STATUS_PENDING / Error * *************************************************************************/ NTSTATUS NTAPI Ext2PassDownMultiReadWriteIRP( PEXT2_IO_RUN PtrIoRuns, UINT Count, ULONG TotalReadWriteLength, PtrExt2IrpContext PtrIrpContext, PtrExt2FCB PtrFCB, BOOLEAN SynchronousIo) { PIRP PtrMasterIrp; PIRP PtrAssociatedIrp; PIO_STACK_LOCATION PtrIrpSp; PMDL PtrMdl; PtrExt2VCB PtrVCB; UINT i; ULONG BufferOffset; PEXT2_IO_CONTEXT PtrIoContext = NULL; PKEVENT PtrSyncEvent = NULL; ULONG LogicalBlockSize; ULONG ReadWriteLength; NTSTATUS RC = STATUS_SUCCESS; PtrVCB = PtrFCB->PtrVCB; PtrMasterIrp = PtrIrpContext->Irp; LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; try { if( !SynchronousIo ) { IoMarkIrpPending( PtrIrpContext->Irp ); // We will be returning STATUS_PENDING... } if( !PtrMasterIrp->MdlAddress ) { Ext2LockCallersBuffer( PtrMasterIrp, TRUE, TotalReadWriteLength ); } if( SynchronousIo ) { PtrSyncEvent = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) ) ); if ( !PtrSyncEvent ) { RC = STATUS_INSUFFICIENT_RESOURCES; try_return(); } KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE ); } // // Allocate and initialize a completion context // PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) ) ); if ( !PtrIoContext ) { RC = STATUS_INSUFFICIENT_RESOURCES; try_return(); } RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) ); PtrIoContext->Count = Count; PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT; PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT ); PtrIoContext->PtrMasterIrp = PtrMasterIrp; PtrIoContext->PtrSyncEvent = PtrSyncEvent; PtrIoContext->ReadWriteLength = TotalReadWriteLength; for( ReadWriteLength = 0, BufferOffset = 0, i = 0; i < Count; i++, BufferOffset += ReadWriteLength ) { ReadWriteLength = PtrIoRuns[ i].EndOffset - PtrIoRuns[ i].StartOffset; // // Allocating an Associated IRP... // PtrAssociatedIrp = IoMakeAssociatedIrp( PtrMasterIrp, (CCHAR) (PtrVCB->TargetDeviceObject->StackSize + 1 ) ); PtrIoRuns[ i].PtrAssociatedIrp = PtrAssociatedIrp; ASSERT ( PtrAssociatedIrp ); PtrMasterIrp->AssociatedIrp.IrpCount ++; // // Allocating a Memory Descriptor List... // PtrMdl = IoAllocateMdl( (PCHAR) PtrMasterIrp->UserBuffer + BufferOffset, // Virtual Address ReadWriteLength, FALSE, FALSE, PtrAssociatedIrp ); // // and building a partial MDL... // IoBuildPartialMdl( PtrMasterIrp->MdlAddress, PtrMdl, (PCHAR)PtrMasterIrp->UserBuffer + BufferOffset, ReadWriteLength ); // // Create an Irp stack location for ourselves... // IoSetNextIrpStackLocation( PtrAssociatedIrp ); PtrIrpSp = IoGetCurrentIrpStackLocation( PtrAssociatedIrp ); // // Setup the Stack location to describe our read. // PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction; if( PtrIrpContext->MajorFunction == IRP_MJ_READ ) { PtrIrpSp->Parameters.Read.Length = ReadWriteLength; PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize ); } else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE ) { PtrIrpSp->Parameters.Write.Length = ReadWriteLength; PtrIrpSp->Parameters.Write.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize ); } // PtrIrpSp->Parameters.Read.Length = ReadWriteLength; // PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock; // // Setup a completion routine... // IoSetCompletionRoutine( PtrAssociatedIrp, SynchronousIo ? Ext2MultiSyncCompletionRoutine : Ext2MultiAsyncCompletionRoutine, PtrIoContext, TRUE, TRUE, TRUE ); // // Initialise the next stack location for the driver below us to use... // PtrIrpSp = IoGetNextIrpStackLocation( PtrAssociatedIrp ); PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction; if( PtrIrpContext->MajorFunction == IRP_MJ_READ ) { PtrIrpSp->Parameters.Read.Length = ReadWriteLength; PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize ); } else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE ) { PtrIrpSp->Parameters.Write.Length = ReadWriteLength; PtrIrpSp->Parameters.Write.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize ); } // PtrIrpSp->Parameters.Read.Length = ReadWriteLength; // PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = // PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize ); } for( i = 0; i < Count; i++ ) { // DbgPrint("PASSING DOWN IRP %d TO TARGET DEVICE\n", i); IoCallDriver( PtrVCB->TargetDeviceObject, PtrIoRuns[ i].PtrAssociatedIrp ); } if( SynchronousIo ) { // // Synchronous IO // Wait for the IO to complete... // DbgPrint("DEADLY WAIT (%d)\n", KeGetCurrentIrql()); KeWaitForSingleObject( PtrSyncEvent, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL ); DbgPrint("DEADLY WAIT DONE\n"); try_return(); } else { // Asynchronous IO... RC = STATUS_PENDING; try_return(); } try_exit: NOTHING; } finally { if( PtrSyncEvent ) { DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrSyncEvent ); ExFreePool( PtrSyncEvent ); } if( PtrIoContext && ! ( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) ) { // // This means we are getting out of // this function without doing a read // due to an error, maybe... // DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrIoContext); ExFreePool( PtrIoContext ); } } return(RC); }
NTSTATUS AFSInitRDRDevice() { NTSTATUS ntStatus = STATUS_SUCCESS; UNICODE_STRING uniDeviceName; ULONG ulIndex = 0; AFSDeviceExt *pDeviceExt = NULL; AFSFileID stRootFid; UNICODE_STRING uniFsRtlRegisterUncProviderEx; FsRtlRegisterUncProviderEx_t pFsRtlRegisterUncProviderEx = NULL; __Enter { RtlInitUnicodeString( &uniDeviceName, AFS_RDR_DEVICE_NAME); RtlInitUnicodeString( &uniFsRtlRegisterUncProviderEx, L"FsRtlRegisterUncProviderEx"); pFsRtlRegisterUncProviderEx = (FsRtlRegisterUncProviderEx_t)MmGetSystemRoutineAddress(&uniFsRtlRegisterUncProviderEx); ntStatus = IoCreateDevice( AFSDriverObject, sizeof( AFSDeviceExt), pFsRtlRegisterUncProviderEx ? NULL : &uniDeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE, FALSE, &AFSRDRDeviceObject); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRDRDevice IoCreateDevice failure %08lX\n", ntStatus); try_return( ntStatus); } pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; RtlZeroMemory( pDeviceExt, sizeof( AFSDeviceExt)); // // Initialize resources // pDeviceExt->Specific.RDR.VolumeTree.TreeLock = &pDeviceExt->Specific.RDR.VolumeTreeLock; ExInitializeResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); pDeviceExt->Specific.RDR.VolumeTree.TreeHead = NULL; ExInitializeResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock); pDeviceExt->Specific.RDR.VolumeListHead = NULL; pDeviceExt->Specific.RDR.VolumeListTail = NULL; KeInitializeEvent( &pDeviceExt->Specific.RDR.QueuedReleaseExtentEvent, NotificationEvent, TRUE); ExInitializeResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock); pDeviceExt->Specific.RDR.RootCellTree.TreeLock = &pDeviceExt->Specific.RDR.RootCellTreeLock; pDeviceExt->Specific.RDR.RootCellTree.TreeHead = NULL; ExInitializeResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock); // // Clear the initializing bit // AFSRDRDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; // // Register this device with MUP with FilterMgr if Vista or above // if( pFsRtlRegisterUncProviderEx) { ntStatus = pFsRtlRegisterUncProviderEx( &AFSMUPHandle, &uniDeviceName, AFSRDRDeviceObject, 0); if ( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n", ntStatus); } } else { ntStatus = FsRtlRegisterUncProvider( &AFSMUPHandle, &uniDeviceName, FALSE); if ( NT_SUCCESS( ntStatus)) { IoRegisterFileSystem( AFSRDRDeviceObject); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n", ntStatus); } } if( !NT_SUCCESS( ntStatus)) { // // Delete our device and bail // ExDeleteResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); ExDeleteResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock); ExDeleteResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock); ExDeleteResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock); IoDeleteDevice( AFSRDRDeviceObject); AFSRDRDeviceObject = NULL; try_return( ntStatus); } // // Good to go, all registered and ready to start receiving requests // try_exit: if( !NT_SUCCESS( ntStatus)) { } } return ntStatus; }
NTSTATUS AFSQueryEA( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_EAS_NOT_SUPPORTED; AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; __try { if( DeviceObject == AFSDeviceObject) { AFSCompleteRequest( Irp, ntStatus); try_return( ntStatus); } // // Check the state of the library // ntStatus = AFSCheckLibraryState( Irp); if( !NT_SUCCESS( ntStatus) || ntStatus == STATUS_PENDING) { if( ntStatus != STATUS_PENDING) { AFSCompleteRequest( Irp, ntStatus); } try_return( ntStatus); } IoSkipCurrentIrpStackLocation( Irp); ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, Irp); // // Indicate the library is done with the request // AFSClearLibraryRequest(); try_exit: NOTHING; } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSQueryEA\n"); AFSDumpTraceFilesFnc(); } return ntStatus; }
NTSTATUS AFSWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; __try { if( DeviceObject == AFSDeviceObject) { ntStatus = STATUS_INVALID_DEVICE_REQUEST; AFSCompleteRequest( Irp, ntStatus); try_return( ntStatus); } // // Check the state of the library // ntStatus = AFSCheckLibraryState( Irp); if( !NT_SUCCESS( ntStatus) || ntStatus == STATUS_PENDING) { if( ntStatus != STATUS_PENDING) { AFSCompleteRequest( Irp, ntStatus); } try_return( ntStatus); } // // Increment the outstanding IO count again - this time for the // completion routine. // ntStatus = AFSCheckLibraryState( Irp); if( !NT_SUCCESS( ntStatus) || ntStatus == STATUS_PENDING) { AFSClearLibraryRequest(); if( ntStatus != STATUS_PENDING) { AFSCompleteRequest( Irp, ntStatus); } try_return( ntStatus); } // // And send it down, but arrange to capture the comletion // so we can free our lock against unloading. // IoCopyCurrentIrpStackLocationToNext( Irp); AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "Setting AFSWriteComplete as IoCompletion Routine Irp %p\n", Irp)); IoSetCompletionRoutine( Irp, AFSWriteComplete, NULL, TRUE, TRUE, TRUE); ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, Irp); // // Indicate the library/thread pair is done with the request // AFSClearLibraryRequest(); try_exit: NOTHING; } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; AFSDumpTraceFilesFnc(); } return ntStatus; }
BOOLEAN FatFastLock ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast lock call. Arguments: FileObject - Supplies the file object used in this operation FileOffset - Supplies the file offset used in this operation Length - Supplies the length used in this operation ProcessId - Supplies the process ID used in this operation Key - Supplies the key used in this operation FailImmediately - Indicates if the request should fail immediately if the lock cannot be granted. ExclusiveLock - Indicates if this is a request for an exclusive or shared lock IoStatus - Receives the Status if this operation is successful Return Value: BOOLEAN - TRUE if this operation completed and FALSE if caller needs to take the long route. --*/ { BOOLEAN Results; PVCB Vcb; PFCB Fcb; PCCB Ccb; DebugTrace(+1, Dbg, "FatFastLock\n", 0); // // Decode the type of file object we're being asked to process and make // sure it is only a user file open. // if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) { IoStatus->Status = STATUS_INVALID_PARAMETER; IoStatus->Information = 0; DebugTrace(-1, Dbg, "FatFastLock -> TRUE (STATUS_INVALID_PARAMETER)\n", 0); return TRUE; } // // Acquire exclusive access to the Fcb this operation can always wait // FsRtlEnterFileSystem(); try { // // We check whether we can proceed // based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) { try_return( Results = FALSE ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request // if (Results = FsRtlFastLock( &Fcb->Specific.Fcb.FileLock, FileObject, FileOffset, Length, ProcessId, Key, FailImmediately, ExclusiveLock, IoStatus, NULL, FALSE )) { // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb ); } try_exit: NOTHING; } finally { DebugUnwind( FatFastLock ); // // Release the Fcb, and return to our caller // FsRtlExitFileSystem(); DebugTrace(-1, Dbg, "FatFastLock -> %08lx\n", Results); } return Results; }
NTSTATUS FatCommonClose ( IN PVCB Vcb, IN PFCB Fcb, IN PCCB Ccb, IN TYPE_OF_OPEN TypeOfOpen, IN BOOLEAN Wait, OUT PBOOLEAN VcbDeleted OPTIONAL ) /*++ Routine Description: This is the common routine for closing a file/directory called by both the fsd and fsp threads. Close is invoked whenever the last reference to a file object is deleted. Cleanup is invoked when the last handle to a file object is closed, and is called before close. The function of close is to completely tear down and remove the fcb/dcb/ccb structures associated with the file object. Arguments: Fcb - Supplies the file to process. Wait - If this is TRUE we are allowed to block for the Vcb, if FALSE then we must try to acquire the Vcb anyway. VcbDeleted - Returns whether the VCB was deleted by this call. Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PDCB ParentDcb; BOOLEAN RecursiveClose; BOOLEAN LocalVcbDeleted; IRP_CONTEXT IrpContext; #if __NDAS_FAT_SECONDARY__ BOOLEAN volDoResourceAcquired = FALSE; BOOLEAN send2Primary = FALSE; BOOLEAN volDoCcb = FALSE; _U64 primaryFileHandle; PVOLUME_DEVICE_OBJECT volDo = CONTAINING_RECORD( Vcb, VOLUME_DEVICE_OBJECT, Vcb ); BOOLEAN volDoSessionResourceAcquired = FALSE; PSECONDARY_REQUEST secondaryRequest = NULL; PNDFS_REQUEST_HEADER ndfsRequestHeader; PNDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PNDFS_WINXP_REPLY_HEADER ndfsWinxpReplytHeader; LARGE_INTEGER timeOut; #endif PAGED_CODE(); DebugTrace(+1, Dbg, "FatCommonClose...\n", 0); // // Initailize the callers variable, if needed. // LocalVcbDeleted = FALSE; if (ARGUMENT_PRESENT( VcbDeleted )) { *VcbDeleted = LocalVcbDeleted; } // // Special case the unopened file object // if (TypeOfOpen == UnopenedFileObject) { DebugTrace(0, Dbg, "Close unopened file object\n", 0); Status = STATUS_SUCCESS; DebugTrace(-1, Dbg, "FatCommonClose -> %08lx\n", Status); return Status; } // // Set up our stack IrpContext. // RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) ); IrpContext.NodeTypeCode = FAT_NTC_IRP_CONTEXT; IrpContext.NodeByteSize = sizeof( IrpContext ); IrpContext.MajorFunction = IRP_MJ_CLOSE; IrpContext.Vcb = Vcb; if (Wait) { SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT ); } #if __NDAS_FAT_SECONDARY__ if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) SetFlag( IrpContext.NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT ); if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) { if (!FlagOn(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT)) { return STATUS_PENDING; } volDoResourceAcquired = SecondaryAcquireResourceSharedStarveExclusiveLite( &IrpContext, &volDo->Resource, BooleanFlagOn(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT) ); if (volDoResourceAcquired == FALSE) { ASSERT( FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ); // It's not always garented continue; return STATUS_PENDING; } } if (volDo->NetdiskEnableMode == NETDISK_SECONDARY && !FlagOn(volDo->NetdiskPartitionInformation.Flags, NETDISK_PARTITION_INFORMATION_FLAG_INDIRECT)) { if (TypeOfOpen == VirtualVolumeFile || TypeOfOpen == DirectoryFile) { SetFlag( IrpContext.NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT ); } } #endif // // Acquire exclusive access to the Vcb and enqueue the irp if we didn't // get access. // #if __NDAS_FAT_SECONDARY__ if (!(FlagOn(IrpContext.NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT) ? ExAcquireResourceExclusiveLite( &Vcb->SecondaryResource, Wait ) : ExAcquireResourceExclusiveLite( &Vcb->Resource, Wait ))) { if (volDoResourceAcquired) { ASSERT( ExIsResourceAcquiredSharedLite(&volDo->Resource) ); SecondaryReleaseResourceLite( NULL, &volDo->Resource ); } return STATUS_PENDING; } #else if (!ExAcquireResourceExclusiveLite( &Vcb->Resource, Wait )) { return STATUS_PENDING; } #endif // // The following test makes sure that we don't blow away an Fcb if we // are trying to do a Supersede/Overwrite open above us. This test // does not apply for the EA file. // if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS) && Vcb->EaFcb != Fcb) { #if __NDAS_FAT_SECONDARY__ if (FlagOn(IrpContext.NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT)) ExReleaseResourceLite( &Vcb->SecondaryResource ); else ExReleaseResourceLite( &Vcb->Resource ); if (volDoResourceAcquired) { ASSERT( ExIsResourceAcquiredSharedLite(&volDo->Resource) ); SecondaryReleaseResourceLite( NULL, &volDo->Resource ); } #else ExReleaseResourceLite( &Vcb->Resource ); #endif return STATUS_PENDING; } // // Setting the following flag prevents recursive closes of directory file // objects, which are handled in a special case loop. // if ( FlagOn(Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS) ) { RecursiveClose = TRUE; } else { SetFlag(Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS); RecursiveClose = FALSE; // // Since we are at the top of the close chain, we need to add // a reference to the VCB. This will keep it from going away // on us until we are ready to check for a dismount below. // Vcb->OpenFileCount += 1; } try { // // Case on the type of open that we are trying to close. // switch (TypeOfOpen) { case VirtualVolumeFile: DebugTrace(0, Dbg, "Close VirtualVolumeFile\n", 0); // // Remove this internal, residual open from the count. // InterlockedDecrement( &(Vcb->InternalOpenCount) ); InterlockedDecrement( &(Vcb->ResidualOpenCount) ); try_return( Status = STATUS_SUCCESS ); break; case UserVolumeOpen: DebugTrace(0, Dbg, "Close UserVolumeOpen\n", 0); #if __NDAS_FAT_SECONDARY__ if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) { volDoCcb = TRUE; if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) { if ( FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) ) Fcb->CorruptedCcbCloseCount --; send2Primary = FALSE; } else send2Primary = TRUE; primaryFileHandle = Ccb->PrimaryFileHandle; ExAcquireFastMutex( &volDo->Secondary->RecoveryCcbQMutex ); RemoveEntryList( &Ccb->ListEntry ); ExReleaseFastMutex( &volDo->Secondary->RecoveryCcbQMutex ); InitializeListHead( &Ccb->ListEntry ); Ccb->FileObject = NULL; if (Ccb->Buffer) ExFreePool( Ccb->Buffer ); Ccb->FileObject = NULL; InterlockedDecrement( &Vcb->SecondaryOpenFileCount ); } else { Vcb->DirectAccessOpenCount -= 1; Vcb->OpenFileCount -= 1; if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; } } if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_OPEN_BY_PRIMARY_SESSION)) { InterlockedDecrement( &Vcb->PrimaryOpenFileCount ); } FatDeleteCcb( &IrpContext, &Ccb ); if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) { InterlockedDecrement( &Fcb->OpenCount ); if (Fcb->OpenCount == 0) { ExAcquireFastMutex( &volDo->Secondary->FcbQMutex ); RemoveEntryList( &Fcb->ListEntry ); InitializeListHead( &Fcb->ListEntry ); ExReleaseFastMutex( &volDo->Secondary->FcbQMutex ); Fcb->Header.NodeTypeCode = FAT_NTC_FCB; FatDeleteFcb( &IrpContext, &Fcb ); Secondary_Dereference( volDo->Secondary ); } } else { try_return( Status = STATUS_SUCCESS ); } #else Vcb->DirectAccessOpenCount -= 1; Vcb->OpenFileCount -= 1; if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; } FatDeleteCcb( &IrpContext, &Ccb ); try_return( Status = STATUS_SUCCESS ); #endif break; case EaFile: DebugTrace(0, Dbg, "Close EaFile\n", 0); // // Remove this internal, residual open from the count. // InterlockedDecrement( &(Vcb->InternalOpenCount) ); InterlockedDecrement( &(Vcb->ResidualOpenCount) ); try_return( Status = STATUS_SUCCESS ); break; case DirectoryFile: DebugTrace(0, Dbg, "Close DirectoryFile\n", 0); InterlockedDecrement( &Fcb->Specific.Dcb.DirectoryFileOpenCount ); // // Remove this internal open from the count. // InterlockedDecrement( &(Vcb->InternalOpenCount) ); // // If this is the root directory, it is a residual open // as well. // if (NodeType( Fcb ) == FAT_NTC_ROOT_DCB) { InterlockedDecrement( &(Vcb->ResidualOpenCount) ); } // // If this is a recursive close, just return here. // if ( RecursiveClose ) { try_return( Status = STATUS_SUCCESS ); } else { break; } case UserDirectoryOpen: case UserFileOpen: DebugTrace(0, Dbg, "Close UserFileOpen/UserDirectoryOpen\n", 0); // // Uninitialize the cache map if we no longer need to use it // if ((NodeType(Fcb) == FAT_NTC_DCB) && IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) && (Fcb->OpenCount == 1) && (Fcb->Specific.Dcb.DirectoryFile != NULL)) { PFILE_OBJECT DirectoryFileObject = Fcb->Specific.Dcb.DirectoryFile; DebugTrace(0, Dbg, "Uninitialize the stream file object\n", 0); CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL ); // // Dereference the directory file. This may cause a close // Irp to be processed, so we need to do this before we destory // the Fcb. // Fcb->Specific.Dcb.DirectoryFile = NULL; ObDereferenceObject( DirectoryFileObject ); } #if __NDAS_FAT__ if (TypeOfOpen == UserFileOpen) { ExAcquireFastMutex( &Fcb->NonPaged->CcbQMutex ); Ccb->FileObject = NULL; Ccb->Fcb = NULL; RemoveEntryList( &Ccb->FcbListEntry ); InitializeListHead( &Ccb->FcbListEntry ); ExReleaseFastMutex( &Fcb->NonPaged->CcbQMutex ); } #endif Fcb->OpenCount -= 1; #if __NDAS_FAT_SECONDARY__ if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) { volDoCcb = TRUE; if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) { if ( FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) ) Fcb->CorruptedCcbCloseCount --; send2Primary = FALSE; } else send2Primary = TRUE; primaryFileHandle = Ccb->PrimaryFileHandle; ExAcquireFastMutex( &volDo->Secondary->RecoveryCcbQMutex ); RemoveEntryList( &Ccb->ListEntry ); ExReleaseFastMutex( &volDo->Secondary->RecoveryCcbQMutex ); InitializeListHead( &Ccb->ListEntry ); Ccb->FileObject = NULL; if (Ccb->Buffer) ExFreePool( Ccb->Buffer ); InterlockedDecrement( &Vcb->SecondaryOpenFileCount ); Ccb->FileObject = NULL; } else { Vcb->OpenFileCount -= 1; if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; } } if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_OPEN_BY_PRIMARY_SESSION)) { InterlockedDecrement( &Vcb->PrimaryOpenFileCount ); } FatDeleteCcb( &IrpContext, &Ccb ); if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) { if (Fcb->OpenCount == 0) { ExAcquireFastMutex( &volDo->Secondary->FcbQMutex ); RemoveEntryList( &Fcb->ListEntry ); InitializeListHead( &Fcb->ListEntry ); ExReleaseFastMutex( &volDo->Secondary->FcbQMutex ); Fcb->Header.NodeTypeCode = FAT_NTC_FCB; FatDeleteFcb( &IrpContext, &Fcb ); Secondary_Dereference( volDo->Secondary ); } } #else Fcb->OpenCount -= 1; Vcb->OpenFileCount -= 1; if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; } FatDeleteCcb( &IrpContext, &Ccb ); #endif break; default: FatBugCheck( TypeOfOpen, 0, 0 ); } #if __NDAS_FAT_SECONDARY__ if (send2Primary) { Status = STATUS_SUCCESS; volDoSessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( &IrpContext, &volDo->SessionResource, BooleanFlagOn(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) || FlagOn(volDo->Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) { Status = STATUS_SUCCESS; leave; } secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, IRP_MJ_CLOSE, 0 ); if (secondaryRequest == NULL) { ASSERT( FALSE ); leave; } ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader; INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_CLOSE, 0 ); ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1); ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData ); //ndfsWinxpRequestHeader->IrpTag = (_U32)Fcb; ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_CLOSE; ndfsWinxpRequestHeader->IrpMinorFunction = 0; ndfsWinxpRequestHeader->FileHandle = primaryFileHandle; ndfsWinxpRequestHeader->IrpFlags = 0; ndfsWinxpRequestHeader->IrpSpFlags = 0; secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE; QueueingSecondaryRequest( volDo->Secondary, secondaryRequest ); timeOut.QuadPart = -NDASFAT_TIME_OUT; Status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut ); KeClearEvent( &secondaryRequest->CompleteEvent ); if (Status != STATUS_SUCCESS) { ASSERT( NDASFAT_BUG ); } if (secondaryRequest->ExecuteStatus == STATUS_SUCCESS) { ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData; ASSERT( ndfsWinxpReplytHeader->Status == STATUS_SUCCESS ); leave; } ASSERT( secondaryRequest->ExecuteStatus != STATUS_SUCCESS ); } if (volDoCcb == TRUE) { Status = STATUS_SUCCESS; leave; } #endif // // At this point we've cleaned up any on-disk structure that needs // to be done, and we can now update the in-memory structures. // Now if this is an unreferenced FCB or if it is // an unreferenced DCB (not the root) then we can remove // the fcb and set our ParentDcb to non null. // if (((NodeType(Fcb) == FAT_NTC_FCB) && (Fcb->OpenCount == 0)) || ((NodeType(Fcb) == FAT_NTC_DCB) && (IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue)) && (Fcb->OpenCount == 0) && (Fcb->Specific.Dcb.DirectoryFileOpenCount == 0))) { ParentDcb = Fcb->ParentDcb; SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB ); FatDeleteFcb( &IrpContext, &Fcb ); // // Uninitialize our parent's cache map if we no longer need // to use it. // while ((NodeType(ParentDcb) == FAT_NTC_DCB) && IsListEmpty(&ParentDcb->Specific.Dcb.ParentDcbQueue) && (ParentDcb->OpenCount == 0) && (ParentDcb->Specific.Dcb.DirectoryFile != NULL)) { PFILE_OBJECT DirectoryFileObject; DirectoryFileObject = ParentDcb->Specific.Dcb.DirectoryFile; DebugTrace(0, Dbg, "Uninitialize our parent Stream Cache Map\n", 0); CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL ); ParentDcb->Specific.Dcb.DirectoryFile = NULL; ObDereferenceObject( DirectoryFileObject ); // // Now, if the ObDereferenceObject() caused the final close // to come in, then blow away the Fcb and continue up, // otherwise wait for Mm to to dereference its file objects // and stop here.. // if ( ParentDcb->Specific.Dcb.DirectoryFileOpenCount == 0) { PDCB CurrentDcb; CurrentDcb = ParentDcb; ParentDcb = CurrentDcb->ParentDcb; SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB ); FatDeleteFcb( &IrpContext, &CurrentDcb ); } else { break; } } } Status = STATUS_SUCCESS; try_exit: NOTHING; } finally { DebugUnwind( FatCommonClose ); #if __NDAS_FAT_SECONDARY__ if (secondaryRequest) DereferenceSecondaryRequest( secondaryRequest ); if (volDoSessionResourceAcquired) { SecondaryReleaseResourceLite( &IrpContext, &volDo->SessionResource ); } if (volDoResourceAcquired) { ASSERT( ExIsResourceAcquiredSharedLite(&volDo->Resource) ); SecondaryReleaseResourceLite( NULL, &volDo->Resource ); } #endif // // We are done processing the close. If we are the top of the close // chain, see if the VCB can go away. We have biased the open count by // one, so we need to take that into account. // if (!RecursiveClose) { // // See if there is only one open left. If so, it is ours. We only want // to check for a dismount if a dismount is not already in progress. // We also only do this if the caller can handle the VCB going away. // This is determined by whether they passed in the VcbDeleted argument. // if (Vcb->OpenFileCount == 1 && !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS ) && ARGUMENT_PRESENT( VcbDeleted )) { // // We need the global lock, which must be acquired before the // VCB. Since we already have the VCB, we have to drop and // reaquire here. Note that we always want to wait from this // point on. Note that the VCB cannot go away, since we have // biased the open file count. // FatReleaseVcb( &IrpContext, Vcb ); SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT ); FatAcquireExclusiveGlobal( &IrpContext ); FatAcquireExclusiveVcb( &IrpContext, Vcb ); // // We have our locks in the correct order. Remove our // extra open and check for a dismount. Note that if // something changed while we dropped the lock, it will // not matter, since the dismount code does the correct // checks to make sure the volume can really go away. // Vcb->OpenFileCount -= 1; LocalVcbDeleted = FatCheckForDismount( &IrpContext, Vcb, FALSE ); FatReleaseGlobal( &IrpContext ); // // Let the caller know what happened, if they want this information. // if (ARGUMENT_PRESENT( VcbDeleted )) { *VcbDeleted = LocalVcbDeleted; } } else { // // The volume cannot go away now. Just remove our extra reference. // Vcb->OpenFileCount -= 1; } // // If the VCB is still around, clear our recursion flag. // if (!LocalVcbDeleted) { ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS ); } } // // Only release the VCB if it did not go away. // if (!LocalVcbDeleted) { FatReleaseVcb( &IrpContext, Vcb ); } DebugTrace(-1, Dbg, "FatCommonClose -> %08lx\n", Status); } return Status; }
NTSTATUS FatCommonLockControl ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for doing Lock control operations called by both the fsd and fsp threads Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; TYPE_OF_OPEN TypeOfOpen; PVCB Vcb; PFCB Fcb; PCCB Ccb; BOOLEAN OplockPostIrp = FALSE; // // Get a pointer to the current Irp stack location // IrpSp = IoGetCurrentIrpStackLocation( Irp ); DebugTrace(+1, Dbg, "FatCommonLockControl\n", 0); DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp); DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction); // // Decode the type of file object we're being asked to process // TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb ); // // If the file is not a user file open then we reject the request // as an invalid parameter // if (TypeOfOpen != UserFileOpen) { FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); DebugTrace(-1, Dbg, "FatCommonLockControl -> STATUS_INVALID_PARAMETER\n", 0); return STATUS_INVALID_PARAMETER; } // // Acquire exclusive access to the Fcb and enqueue the Irp if we didn't // get access // if (!FatAcquireSharedFcb( IrpContext, Fcb )) { Status = FatFsdPostRequest( IrpContext, Irp ); DebugTrace(-1, Dbg, "FatCommonLockControl -> %08lx\n", Status); return Status; } try { // // We check whether we can proceed // based on the state of the file oplocks. // Status = FsRtlCheckOplock( &Fcb->Specific.Fcb.Oplock, Irp, IrpContext, FatOplockComplete, NULL ); if (Status != STATUS_SUCCESS) { OplockPostIrp = TRUE; try_return( NOTHING ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request // Status = FsRtlProcessFileLock( &Fcb->Specific.Fcb.FileLock, Irp, NULL ); // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb ); try_exit: NOTHING; } finally { DebugUnwind( FatCommonLockControl ); // // Only if this is not an abnormal termination do we delete the // irp context // if (!AbnormalTermination() && !OplockPostIrp) { FatCompleteRequest( IrpContext, FatNull, 0 ); } // // Release the Fcb, and return to our caller // FatReleaseFcb( IrpContext, Fcb ); DebugTrace(-1, Dbg, "FatCommonLockControl -> %08lx\n", Status); } return Status; }
/************************************************************************* * * Function: Ext2MountVolume() * * Description: * This routine verifies and mounts the volume; * Called by FSCTRL IRP handler to attempt a * volume mount. * * Expected Interrupt Level (for execution) : * * IRQL_PASSIVE_LEVEL * * * Arguments: * * Irp - Supplies the Irp being processed * IrpSp - Irp Stack Location pointer * * Return Value: * * NTSTATUS - The Mount status * *************************************************************************/ NTSTATUS Ext2MountVolume ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { // Volume Parameter Block PVPB PtrVPB; // The target device object PDEVICE_OBJECT TargetDeviceObject = NULL; // The new volume device object (to be created if partition is Ext2) PDEVICE_OBJECT PtrVolumeDeviceObject = NULL; // Return Status NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME; // Number of bytes to read for Volume verification... unsigned long NumberOfBytesToRead = 0; // Starting Offset for 'read' LONGLONG StartingOffset = 0; // Boot Sector information... PPACKED_BOOT_SECTOR BootSector = NULL; // Ext2 Super Block information... PEXT2_SUPER_BLOCK SuperBlock = NULL; // Volume Control Block PtrExt2VCB PtrVCB = NULL; // The File Object for the root directory PFILE_OBJECT PtrRootFileObject = NULL; // Flag int WeClearedVerifyRequiredBit; // Used by a for loop... unsigned int i; // LARGE_INTEGER VolumeByteOffset; unsigned long LogicalBlockSize = 0; // Buffer Control Block PBCB PtrBCB = NULL; // Cache Buffer - used for pinned access of volume... PVOID PtrCacheBuffer = NULL; PEXT2_GROUP_DESCRIPTOR PtrGroupDescriptor = NULL; // Inititalising variables PtrVPB = IrpSp->Parameters.MountVolume.Vpb; TargetDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject; try { // // 1. Reading in Volume meta data // // Temporarily clear the DO_VERIFY_VOLUME Flag WeClearedVerifyRequiredBit = 0; if ( Ext2IsFlagOn( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME ) ) { Ext2ClearFlag( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME ); WeClearedVerifyRequiredBit = 1; } // Allocating memory for reading in Boot Sector... NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), TargetDeviceObject->SectorSize ); BootSector = Ext2AllocatePool( PagedPool, NumberOfBytesToRead ); RtlZeroMemory( BootSector, NumberOfBytesToRead ); // Reading in Boot Sector StartingOffset = 0L; Ext2PerformVerifyDiskRead ( TargetDeviceObject, BootSector, StartingOffset, NumberOfBytesToRead ); // Reject a volume that contains fat artifacts DebugTrace(DEBUG_TRACE_MOUNT, "OEM[%s]", BootSector->Oem); if (BootSector->Oem[0]) { try_return(); } // Allocating memory for reading in Super Block... SuperBlock = Ext2AllocatePool( PagedPool, NumberOfBytesToRead ); RtlZeroMemory( SuperBlock, NumberOfBytesToRead ); StartingOffset = 1024; // Reading in the Super Block... Ext2PerformVerifyDiskRead ( TargetDeviceObject, SuperBlock, StartingOffset, NumberOfBytesToRead ); // Resetting the DO_VERIFY_VOLUME Flag if( WeClearedVerifyRequiredBit ) { PtrVPB->RealDevice->Flags |= DO_VERIFY_VOLUME; } // Verifying the Super Block.. if( SuperBlock->s_magic == EXT2_SUPER_MAGIC ) { // // Found a valid super block. // No more tests for now. // Assuming that this is an ext2 partition... // Going ahead with mount. // DebugTrace(DEBUG_TRACE_MOUNT, "Valid Ext2 partition detected\nMounting %s...", SuperBlock->s_volume_name); // // 2. Creating a volume device object // if (!NT_SUCCESS( IoCreateDevice( Ext2GlobalData.Ext2DriverObject, // (This) Driver object Ext2QuadAlign( sizeof(Ext2VCB) ), // Device Extension NULL, // Device Name - no name ;) FILE_DEVICE_DISK_FILE_SYSTEM, // Disk File System 0, // DeviceCharacteristics FALSE, // Not an exclusive device (PDEVICE_OBJECT *)&PtrVolumeDeviceObject)) // The Volume Device Object ) { try_return(); } // // Our alignment requirement is the larger of the processor alignment requirement // already in the volume device object and that in the TargetDeviceObject // if (TargetDeviceObject->AlignmentRequirement > PtrVolumeDeviceObject->AlignmentRequirement) { PtrVolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement; } // // Clearing the Device Initialising Flag // Ext2ClearFlag( PtrVolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); // // Setting the Stack Size for the newly created Volume Device Object // PtrVolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1); // // 3. Creating the link between Target Device Object // and the Volume Device Object via the Volume Parameter Block // PtrVPB->DeviceObject = PtrVolumeDeviceObject; // Remembring the Volume parameters in the VPB bock for( i = 0; i < 16 ; i++ ) { PtrVPB->VolumeLabel[i] = SuperBlock->s_volume_name[i]; if( SuperBlock->s_volume_name[i] == 0 ) break; } PtrVPB->VolumeLabelLength = i * 2; PtrVPB->SerialNumber = ((ULONG*)SuperBlock->s_uuid)[0]; // // 4. Initialise the Volume Comtrol Block // { LARGE_INTEGER AllocationSize; AllocationSize .QuadPart = ( EXT2_MIN_BLOCK_SIZE << SuperBlock->s_log_block_size ) * SuperBlock->s_blocks_count; Ext2InitializeVCB( PtrVolumeDeviceObject, TargetDeviceObject, PtrVPB, &AllocationSize); PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension); ASSERT( PtrVCB ); } PtrVCB->InodesCount = SuperBlock->s_inodes_count; PtrVCB->BlocksCount = SuperBlock->s_blocks_count; PtrVCB->ReservedBlocksCount = SuperBlock->s_r_blocks_count; PtrVCB->FreeBlocksCount = SuperBlock->s_free_blocks_count; PtrVCB->FreeInodesCount = SuperBlock->s_free_inodes_count; PtrVCB->LogBlockSize = SuperBlock->s_log_block_size; PtrVCB->InodesPerGroup = SuperBlock->s_inodes_per_group; PtrVCB->BlocksPerGroup = SuperBlock->s_blocks_per_group; PtrVCB->NoOfGroups = ( SuperBlock->s_blocks_count - SuperBlock->s_first_data_block + SuperBlock->s_blocks_per_group - 1 ) / SuperBlock->s_blocks_per_group; if( SuperBlock->s_rev_level ) { PtrVCB->InodeSize = SuperBlock->s_inode_size; } else { PtrVCB->InodeSize = sizeof( EXT2_INODE ); } PtrVCB->PtrGroupDescriptors = Ext2AllocatePool( NonPagedPool, sizeof( Ext2GroupDescriptors ) * PtrVCB->NoOfGroups ); RtlZeroMemory( PtrVCB->PtrGroupDescriptors , sizeof( Ext2GroupDescriptors ) * PtrVCB->NoOfGroups ); // // Attempting to Read in some matadata from the Cache... // using pin access... // LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; // // Reading Group Descriptors... // if( PtrVCB->LogBlockSize ) { // First block contains the descriptors... VolumeByteOffset.QuadPart = LogicalBlockSize; } else { // Second block contains the descriptors... VolumeByteOffset.QuadPart = LogicalBlockSize * 2; } NumberOfBytesToRead = PtrVCB->NoOfGroups * sizeof( struct ext2_group_desc ); NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize ); if (!CcMapData( PtrVCB->PtrStreamFileObject, &VolumeByteOffset, NumberOfBytesToRead, TRUE, &PtrBCB, &PtrCacheBuffer )) { DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); try_return( Status = STATUS_INSUFFICIENT_RESOURCES ); } else { // // Saving up Often Used Group Descriptor Information in the VCB... // unsigned int DescIndex ; DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0); PtrGroupDescriptor = (PEXT2_GROUP_DESCRIPTOR )PtrCacheBuffer; for( DescIndex = 0; DescIndex < PtrVCB->NoOfGroups; DescIndex++ ) { PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeTablesBlock = PtrGroupDescriptor[ DescIndex ].bg_inode_table; PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeBitmapBlock = PtrGroupDescriptor[ DescIndex ].bg_inode_bitmap ; PtrVCB->PtrGroupDescriptors[ DescIndex ].BlockBitmapBlock = PtrGroupDescriptor[ DescIndex ].bg_block_bitmap ; PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeBlocksCount = PtrGroupDescriptor[ DescIndex ].bg_free_blocks_count; PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeInodesCount = PtrGroupDescriptor[ DescIndex ].bg_free_inodes_count; } CcUnpinData( PtrBCB ); PtrBCB = NULL; } // // 5. Creating a Root Directory FCB // PtrRootFileObject = IoCreateStreamFileObject(NULL, TargetDeviceObject ); if( !PtrRootFileObject ) { try_return(); } // // Associate the file stream with the Volume parameter block... // I do it now // PtrRootFileObject->Vpb = PtrVCB->PtrVPB; PtrRootFileObject->ReadAccess = TRUE; PtrRootFileObject->WriteAccess = TRUE; { PtrExt2ObjectName PtrObjectName; LARGE_INTEGER ZeroSize; PtrObjectName = Ext2AllocateObjectName(); RtlInitUnicodeString( &PtrObjectName->ObjectName, L"\\" ); Ext2CopyWideCharToUnicodeString( &PtrObjectName->ObjectName, L"\\" ); ZeroSize.QuadPart = 0; if ( !NT_SUCCESS( Ext2CreateNewFCB( &PtrVCB->PtrRootDirectoryFCB, // Root FCB ZeroSize, // AllocationSize, ZeroSize, // EndOfFile, PtrRootFileObject, // The Root Dircetory File Object PtrVCB, PtrObjectName ) ) ) { try_return(); } PtrVCB->PtrRootDirectoryFCB->FCBFlags |= EXT2_FCB_DIRECTORY | EXT2_FCB_ROOT_DIRECTORY; } PtrVCB->PtrRootDirectoryFCB->DcbFcb.Dcb.PtrDirFileObject = PtrRootFileObject; PtrVCB->PtrRootDirectoryFCB->INodeNo = EXT2_ROOT_INO; PtrRootFileObject->SectionObjectPointer = &(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.SectionObject); RtlInitUnicodeString( &PtrRootFileObject->FileName, L"\\" ); Ext2InitializeFCBInodeInfo( PtrVCB->PtrRootDirectoryFCB ); // // Initiating caching for root directory... // CcInitializeCacheMap(PtrRootFileObject, (PCC_FILE_SIZES)(&(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)), TRUE, // We will utilize pin access for directories &(Ext2GlobalData.CacheMgrCallBacks), // callbacks PtrVCB->PtrRootDirectoryFCB ); // The context used in callbacks // // 6. Update the VCB Flags // PtrVCB->VCBFlags |= EXT2_VCB_FLAGS_VOLUME_MOUNTED ; // | EXT2_VCB_FLAGS_VOLUME_READ_ONLY; // // 7. Mount Success // Status = STATUS_SUCCESS; { // // This block is for testing.... // To be removed... /* EXT2_INODE Inode ; Ext2ReadInode( PtrVCB, 100, &Inode ); DebugTrace( DEBUG_TRACE_MISC, "Inode size= %lX [FS Ctrl]", Inode.i_size ); Ext2DeallocInode( NULL, PtrVCB, 0xfb6 ); */ } // ObDereferenceObject( TargetDeviceObject ); } else { DebugTrace(DEBUG_TRACE_MOUNT, "Failing mount. Partition not Ext2...", 0); } try_exit: NOTHING; } finally { // Freeing Allocated Memory... if( SuperBlock != NULL ) { DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", SuperBlock ); ExFreePool( SuperBlock ); } if( BootSector != NULL ) { DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", BootSector); ExFreePool( BootSector ); } // start unwinding if we were unsuccessful if (!NT_SUCCESS( Status )) { } } return Status; }
VOID LfsTerminateLogQuery ( IN LFS_LOG_HANDLE LogHandle, IN LFS_LOG_CONTEXT Context ) /*++ Routine Description: This routine is called when a client has completed his query operation and wishes to deallocate any resources acquired by the Lfs to perform the log file query. Arguments: LogHandle - Pointer to private Lfs structure used to identify this client. Context - Supplies the address to store a pointer to the Lfs created context structure. Return Value: None --*/ { PLCH Lch; PLfsLCB Lcb; PLFCB Lfcb; PAGED_CODE(); LfsDebugTrace( +1, Dbg, "LfsTerminateLogQuery: Entered\n", 0 ); LfsDebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); LfsDebugTrace( 0, Dbg, "Context -> %08lx\n", Context ); Lch = (PLCH) LogHandle; Lcb = (PLfsLCB) Context; // // Check that the structure is a valid log handle structure. // LfsValidateLch( Lch ); // // Use a try-finally to facilitate cleanup. // try { // // Acquire the log file control block for this log file. // LfsAcquireLch( Lch ); Lfcb = Lch->Lfcb; // // If the Log file has been closed then refuse access. // if (Lfcb == NULL) { try_return( NOTHING ); } // // Check that the client Id is valid. // LfsValidateClientId( Lfcb, Lch ); // // Check that the context structure is valid. // LfsValidateLcb( Lcb, Lch ); // // Deallocate the context block. // LfsDeallocateLcb( Lcb ); try_exit: NOTHING; } finally { DebugUnwind( LfsTerminateLogQuery ); // // Release the Lfcb if acquired. // LfsReleaseLch( Lch ); LfsDebugTrace( -1, Dbg, "LfsTerminateLogQuery: Exit\n", 0 ); } return; }
NTSTATUS NdasFatSecondaryUserFsCtrl ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for implementing the user's requests made through NtFsControlFile. Arguments: Irp - Supplies the Irp being processed Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; ULONG FsControlCode; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PVOLUME_DEVICE_OBJECT volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb ); BOOLEAN secondarySessionResourceAcquired = FALSE; TYPE_OF_OPEN typeOfOpen; PVCB vcb; PFCB fcb; PCCB ccb; PSECONDARY_REQUEST secondaryRequest = NULL; PNDFS_REQUEST_HEADER ndfsRequestHeader; PNDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PNDFS_WINXP_REPLY_HEADER ndfsWinxpReplytHeader; UINT8 *ndfsWinxpRequestData; LARGE_INTEGER timeOut; struct FileSystemControl fileSystemControl; PVOID inputBuffer = NULL; ULONG inputBufferLength; PVOID outputBuffer = NULL; ULONG outputBufferLength; ULONG bufferLength; // // Save some references to make our life a little easier // FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode; DebugTrace(+1, Dbg,"FatUserFsCtrl...\n", 0); DebugTrace( 0, Dbg,"FsControlCode = %08lx\n", FsControlCode); // // Some of these Fs Controls use METHOD_NEITHER buffering. If the previous mode // of the caller was userspace and this is a METHOD_NEITHER, we have the choice // of realy buffering the request through so we can possibly post, or making the // request synchronous. Since the former was not done by design, do the latter. // if (Irp->RequestorMode != KernelMode && (FsControlCode & 3) == METHOD_NEITHER) { SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); } // // Case on the control code. // switch ( FsControlCode ) { case FSCTL_REQUEST_OPLOCK_LEVEL_1: case FSCTL_REQUEST_OPLOCK_LEVEL_2: case FSCTL_REQUEST_BATCH_OPLOCK: case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE: case FSCTL_OPBATCH_ACK_CLOSE_PENDING: case FSCTL_OPLOCK_BREAK_NOTIFY: case FSCTL_OPLOCK_BREAK_ACK_NO_2: case FSCTL_REQUEST_FILTER_OPLOCK : //ASSERT( FALSE ); //Status = STATUS_SUCCESS; //break; Status = FatOplockRequest( IrpContext, Irp ); return Status; case FSCTL_LOCK_VOLUME: FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace2( -1, Dbg, ("NdasFatSecondaryUserFsCtrl -> %08lx\n", Status) ); return Status; //Status = FatLockVolume( IrpContext, Irp ); break; case FSCTL_UNLOCK_VOLUME: FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace2( -1, Dbg, ("NdasFatSecondaryUserFsCtrl -> %08lx\n", Status) ); return Status; //Status = FatUnlockVolume( IrpContext, Irp ); break; case FSCTL_DISMOUNT_VOLUME: FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace2( -1, Dbg, ("NdasFatSecondaryUserFsCtrl -> %08lx\n", Status) ); return Status; //Status = FatDismountVolume( IrpContext, Irp ); break; case FSCTL_MARK_VOLUME_DIRTY: FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace2( -1, Dbg, ("NdasFatSecondaryUserFsCtrl -> %08lx\n", Status) ); return Status; //Status = FatDirtyVolume( IrpContext, Irp ); break; case FSCTL_IS_VOLUME_DIRTY: Status = FatIsVolumeDirty( IrpContext, Irp ); break; case FSCTL_IS_VOLUME_MOUNTED: Status = FatIsVolumeMounted( IrpContext, Irp ); DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; break; case FSCTL_IS_PATHNAME_VALID: Status = FatIsPathnameValid( IrpContext, Irp ); DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; break; case FSCTL_QUERY_RETRIEVAL_POINTERS: Status = FatQueryRetrievalPointers( IrpContext, Irp ); break; case FSCTL_QUERY_FAT_BPB: Status = FatQueryBpb( IrpContext, Irp ); DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; break; case FSCTL_FILESYSTEM_GET_STATISTICS: Status = FatGetStatistics( IrpContext, Irp ); break; case FSCTL_GET_VOLUME_BITMAP: Status = FatGetVolumeBitmap( IrpContext, Irp ); break; case FSCTL_GET_RETRIEVAL_POINTERS: Status = FatGetRetrievalPointers( IrpContext, Irp ); break; case FSCTL_MOVE_FILE: FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = FatMoveFile( IrpContext, Irp ); break; case FSCTL_ALLOW_EXTENDED_DASD_IO: Status = FatAllowExtendedDasdIo( IrpContext, Irp ); break; default : DebugTrace(0, Dbg, "Invalid control code -> %08lx\n", FsControlCode ); FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST ); Status = STATUS_INVALID_DEVICE_REQUEST; break; } ASSERT( !ExIsResourceAcquiredSharedLite(&volDo->Vcb.Resource) ); if (Status != STATUS_SUCCESS) { DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; } inputBuffer = IrpContext->InputBuffer; outputBuffer = IrpContext->outputBuffer; ASSERT( IrpSp->Parameters.FileSystemControl.InputBufferLength ? (inputBuffer != NULL) : (inputBuffer == NULL) ); ASSERT( IrpSp->Parameters.FileSystemControl.OutputBufferLength ? (outputBuffer != NULL) : (outputBuffer == NULL) ); ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { return FatFsdPostRequest( IrpContext, Irp ); } try { secondarySessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->SessionResource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) { PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp ); NDAS_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST ); FatRaiseStatus( IrpContext, STATUS_CANT_WAIT ); } ASSERT( IS_SECONDARY_FILEOBJECT(IrpSp->FileObject) ); typeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &vcb, &fcb, &ccb ); if (FlagOn(ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) { ASSERT( FlagOn(ccb->NdasFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) ); try_return( Status = STATUS_FILE_CORRUPT_ERROR ); } fileSystemControl.FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode; fileSystemControl.InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; fileSystemControl.OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; if (inputBuffer == NULL) fileSystemControl.InputBufferLength = 0; if (outputBuffer == NULL) fileSystemControl.OutputBufferLength = 0; outputBufferLength = fileSystemControl.OutputBufferLength; if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) { // 29 inputBufferLength = 0; } else if (fileSystemControl.FsControlCode == FSCTL_MARK_HANDLE) { // 63 inputBufferLength = 0; } else { inputBufferLength = fileSystemControl.InputBufferLength; } bufferLength = (inputBufferLength >= outputBufferLength) ? inputBufferLength : outputBufferLength; secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, IRP_MJ_FILE_SYSTEM_CONTROL, bufferLength ); if (secondaryRequest == NULL) { NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES ); Status = Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; try_return( Status ); } ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader; INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_FILE_SYSTEM_CONTROL, inputBufferLength ); ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1); ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData ); INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, Irp, IrpSp, ccb->PrimaryFileHandle ); ndfsWinxpRequestHeader->FileSystemControl.OutputBufferLength = fileSystemControl.OutputBufferLength; ndfsWinxpRequestHeader->FileSystemControl.InputBufferLength = fileSystemControl.InputBufferLength; ndfsWinxpRequestHeader->FileSystemControl.FsControlCode = fileSystemControl.FsControlCode; #if 0 if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) { // 29 PMOVE_FILE_DATA moveFileData = inputBuffer; PFILE_OBJECT moveFileObject; PCCB moveCcb; Status = ObReferenceObjectByHandle( moveFileData->FileHandle, FILE_READ_DATA, 0, KernelMode, &moveFileObject, NULL ); if (Status != STATUS_SUCCESS) { ASSERT( FALSE ); try_return( Status ); } ObDereferenceObject( moveFileObject ); moveCcb = moveFileObject->FsContext2; ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.FileHandle = moveCcb->PrimaryFileHandle; ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.StartingVcn = moveFileData->StartingVcn.QuadPart; ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.StartingLcn = moveFileData->StartingLcn.QuadPart; ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.ClusterCount = moveFileData->ClusterCount; } else #endif if (fileSystemControl.FsControlCode == FSCTL_MARK_HANDLE) { // 63 PMARK_HANDLE_INFO markHandleInfo = inputBuffer; PFILE_OBJECT volumeFileObject; PCCB volumeCcb; Status = ObReferenceObjectByHandle( markHandleInfo->VolumeHandle, FILE_READ_DATA, 0, KernelMode, &volumeFileObject, NULL ); if (Status != STATUS_SUCCESS) { try_return( Status ); } ObDereferenceObject( volumeFileObject ); volumeCcb = volumeFileObject->FsContext2; ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.UsnSourceInfo = markHandleInfo->UsnSourceInfo; ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.VolumeHandle = volumeCcb->PrimaryFileHandle; ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.HandleInfo = markHandleInfo->HandleInfo; } else { ndfsWinxpRequestData = (UINT8 *)(ndfsWinxpRequestHeader+1); if (inputBufferLength) RtlCopyMemory( ndfsWinxpRequestData, inputBuffer, inputBufferLength ); } ASSERT( !ExIsResourceAcquiredSharedLite(&IrpContext->Vcb->Resource) ); secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE; QueueingSecondaryRequest( volDo->Secondary, secondaryRequest ); timeOut.QuadPart = -NDASFAT_TIME_OUT; Status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut ); if (Status != STATUS_SUCCESS) { secondaryRequest = NULL; try_return( Status = STATUS_IO_DEVICE_ERROR ); } KeClearEvent( &secondaryRequest->CompleteEvent ); if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) { if (IrpContext->OriginatingIrp) PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp ); DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) ); NDAS_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST ); FatRaiseStatus( IrpContext, STATUS_CANT_WAIT ); } ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData; Status = Irp->IoStatus.Status = NTOHL(ndfsWinxpReplytHeader->Status4); Irp->IoStatus.Information = NTOHL(ndfsWinxpReplytHeader->Information32); if (FsControlCode == FSCTL_GET_NTFS_VOLUME_DATA && Status != STATUS_SUCCESS) DebugTrace2( 0, Dbg2, ("FSCTL_GET_NTFS_VOLUME_DATA: Status = %x, Irp->IoStatus.Information = %d\n", Status, Irp->IoStatus.Information) ); if (NTOHL(secondaryRequest->NdfsReplyHeader.MessageSize4) - sizeof(NDFS_REPLY_HEADER) - sizeof(NDFS_WINXP_REPLY_HEADER)) { ASSERT( Irp->IoStatus.Status == STATUS_SUCCESS || Irp->IoStatus.Status == STATUS_BUFFER_OVERFLOW ); ASSERT( Irp->IoStatus.Information ); ASSERT( Irp->IoStatus.Information <= outputBufferLength ); ASSERT( outputBuffer ); RtlCopyMemory( outputBuffer, (UINT8 *)(ndfsWinxpReplytHeader+1), Irp->IoStatus.Information ); } if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE && Status != STATUS_SUCCESS) DebugTrace2( 0, Dbg2, ("NtfsDefragFile: status = %x\n", Status) ); #if 0 if (Status == STATUS_SUCCESS && fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) { // 29 PMOVE_FILE_DATA moveFileData = inputBuffer; PFILE_OBJECT moveFileObject; TYPE_OF_OPEN typeOfOpen; PVCB vcb; PFCB moveFcb; PSCB moveScb; PCCB moveCcb; Status = ObReferenceObjectByHandle( moveFileData->FileHandle, FILE_READ_DATA, 0, KernelMode, &moveFileObject, NULL ); if (Status != STATUS_SUCCESS) { try_return( Status ); } ObDereferenceObject( moveFileObject ); typeOfOpen = NtfsDecodeFileObject( IrpContext, moveFileObject, &vcb, &moveFcb, &moveScb, &moveCcb, TRUE ); if (typeOfOpen == UserFileOpen && FlagOn(volDo->NdasFatFlags, ND_FAT_DEVICE_FLAG_DIRECT_RW) && ndfsWinxpReplytHeader->FileInformationSet && NTOHLL(ndfsWinxpReplytHeader->AllocationSize8)) { PNDFS_FAT_MCB_ENTRY mcbEntry; ULONG index; VCN testVcn; SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ACQUIRE_PAGING ); NtfsAcquireFcbWithPaging( IrpContext, moveFcb, 0 ); NtfsAcquireNtfsMcbMutex( &moveScb->Mcb ); mcbEntry = (PNDFS_FAT_MCB_ENTRY)( ndfsWinxpReplytHeader+1 ); if (moveScb->Header.AllocationSize.QuadPart) { NtfsRemoveNtfsMcbEntry( &moveScb->Mcb, 0, 0xFFFFFFFF ); } for (index=0, testVcn=0; index < NTOHL(ndfsWinxpReplytHeader->NumberOfMcbEntry4); index++) { ASSERT( mcbEntry[index].Vcn == testVcn ); testVcn += (LONGLONG)mcbEntry[index].ClusterCount; NtfsAddNtfsMcbEntry( &moveScb->Mcb, mcbEntry[index].Vcn, (mcbEntry[index].Lcn << vcb->AllocationSupport.LogOfBytesPerSector), (LONGLONG)mcbEntry[index].ClusterCount, TRUE ); } ASSERT( LlBytesFromClusters(vcb, testVcn) == NTOHLL(ndfsWinxpReplytHeader->AllocationSize8) ); if (moveScb->Header.AllocationSize.QuadPart != NTOHLL(ndfsWinxpReplytHeader->AllocationSize8)) SetFlag( moveScb->ScbState, SCB_STATE_TRUNCATE_ON_CLOSE ); moveScb->Header.FileSize.LowPart = NTOHLL(ndfsWinxpReplytHeader->FileSize8); moveScb->Header.AllocationSize.QuadPart = NTOHLL(ndfsWinxpReplytHeader->AllocationSize8); ASSERT( moveScb->Header.AllocationSize.QuadPart >= moveScb->Header.FileSize.LowPart ); if (moveFileObject->SectionObjectPointer->DataSectionObject != NULL && moveFileObject->PrivateCacheMap == NULL) { CcInitializeCacheMap( moveFileObject, (PCC_FILE_SIZES)&moveScb->Header.AllocationSize, FALSE, &NtfsData.CacheManagerCallbacks, moveScb ); //CcSetAdditionalCacheAttributes( fileObject, TRUE, TRUE ); } if (CcIsFileCached(moveFileObject)) { NtfsSetBothCacheSizes( moveFileObject, (PCC_FILE_SIZES)&scb->Header.AllocationSize, moveScb ); } NtfsReleaseNtfsMcbMutex( &moveScb->Mcb ); NtfsReleaseFcb( IrpContext, moveFcb ); } } #endif try_exit: NOTHING; } finally { if (secondarySessionResourceAcquired == TRUE) { SecondaryReleaseResourceLite( IrpContext, &volDo->SessionResource ); } if (secondaryRequest) DereferenceSecondaryRequest( secondaryRequest ); } FatCompleteRequest( IrpContext, Irp, Status ); DebugTrace(-1, Dbg, "FatUserFsCtrl -> %08lx\n", Status ); return Status; }
NTSTATUS AFSInitFcb( IN AFSDirectoryCB *DirEntry, IN OUT AFSFcb **Fcb) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; AFSFcb *pFcb = NULL; AFSNonPagedFcb *pNPFcb = NULL; IO_STATUS_BLOCK stIoSb = {0,0}; BOOLEAN bUninitFileLock = FALSE; USHORT usFcbLength = 0; ULONGLONG ullIndex = 0; AFSDirEnumEntry *pDirEnumCB = NULL; AFSObjectInfoCB *pObjectInfo = NULL, *pParentObjectInfo = NULL; AFSVolumeCB *pVolumeCB = NULL; __Enter { pObjectInfo = DirEntry->ObjectInformation; pParentObjectInfo = pObjectInfo->ParentObjectInformation; pVolumeCB = pObjectInfo->VolumeCB; // // Allocate the Fcb and the nonpaged portion of the Fcb. // AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSInitFcb Initializing fcb for %wZ FID %08lX-%08lX-%08lX-%08lX\n", &DirEntry->NameInformation.FileName, pObjectInfo->FileId.Cell, pObjectInfo->FileId.Volume, pObjectInfo->FileId.Vnode, pObjectInfo->FileId.Unique); usFcbLength = sizeof( AFSFcb); pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool, usFcbLength, AFS_FCB_ALLOCATION_TAG); if( pFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitFcb Failed to allocate fcb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pFcb, usFcbLength); pFcb->Header.NodeByteSize = usFcbLength; pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedFcb), AFS_FCB_NP_ALLOCATION_TAG); if( pNPFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitFcb Failed to allocate non-paged fcb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pNPFcb, sizeof( AFSNonPagedFcb)); pNPFcb->Size = sizeof( AFSNonPagedFcb); pNPFcb->Type = AFS_NON_PAGED_FCB; // // Initialize the advanced header // ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex); FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex); // // OK, initialize the entry // ExInitializeResourceLite( &pNPFcb->Resource); ExInitializeResourceLite( &pNPFcb->PagingResource); ExInitializeResourceLite( &pNPFcb->CcbListLock); pFcb->Header.Resource = &pNPFcb->Resource; pFcb->Header.PagingIoResource = &pNPFcb->PagingResource; // // Grab the Fcb for processing // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitFcb Acquiring Fcb lock %08lX EXCL %08lX\n", &pNPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pNPFcb->Resource, TRUE); pFcb->NPFcb = pNPFcb; // // Initialize some fields in the Fcb // pFcb->ObjectInformation = pObjectInfo; pObjectInfo->Fcb = pFcb; // // Set type specific information // if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY) { // // Reset the type to a directory type // pFcb->Header.NodeTypeCode = AFS_DIRECTORY_FCB; // // Initialize enumeration information // KeInitializeEvent( &pFcb->NPFcb->Specific.Directory.DirectoryEnumEvent, NotificationEvent, FALSE); } else if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE) { pFcb->Header.NodeTypeCode = AFS_FILE_FCB; // // Initialize the file specific information // FsRtlInitializeFileLock( &pFcb->Specific.File.FileLock, NULL, NULL); bUninitFileLock = TRUE; // // Initialize the header file sizes to our dir entry information // pFcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart; pFcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart; pFcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart; // // Initialize the Extents resources and so forth. The // quiescent state is that no one has the extents for // IO (do the extents are not busy) and there is no // extents request outstanding (and hence the "last // one" is complete). // ExInitializeResourceLite( &pNPFcb->Specific.File.ExtentsResource ); KeInitializeEvent( &pNPFcb->Specific.File.ExtentsRequestComplete, NotificationEvent, TRUE ); for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++) { InitializeListHead(&pFcb->Specific.File.ExtentsLists[i]); } pNPFcb->Specific.File.DirtyListHead = NULL; pNPFcb->Specific.File.DirtyListTail = NULL; ExInitializeResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock); KeInitializeEvent( &pNPFcb->Specific.File.FlushEvent, SynchronizationEvent, TRUE); KeInitializeEvent( &pNPFcb->Specific.File.QueuedFlushEvent, NotificationEvent, TRUE); } else if( pObjectInfo->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME) { pFcb->Header.NodeTypeCode = AFS_SPECIAL_SHARE_FCB; } else if( pObjectInfo->FileType == AFS_FILE_TYPE_PIOCTL) { pFcb->Header.NodeTypeCode = AFS_IOCTL_FCB; } else if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK) { pFcb->Header.NodeTypeCode = AFS_SYMBOLIC_LINK_FCB; } else if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT) { pFcb->Header.NodeTypeCode = AFS_MOUNT_POINT_FCB; } else if( pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK) { pFcb->Header.NodeTypeCode = AFS_DFS_LINK_FCB; } else { pFcb->Header.NodeTypeCode = AFS_INVALID_FCB; } // // And return the Fcb // *Fcb = pFcb; AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitFcb Initialized Fcb %08lX Name %wZ\n", pFcb, &DirEntry->NameInformation.FileName); try_exit: if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitFcb Failed to initialize fcb Status %08lX\n", ntStatus); if( pFcb != NULL) { if( bUninitFileLock) { FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock); } if( pNPFcb != NULL) { AFSReleaseResource( &pNPFcb->Resource); ExDeleteResourceLite( &pNPFcb->PagingResource); ExDeleteResourceLite( &pNPFcb->CcbListLock); ExDeleteResourceLite( &pNPFcb->Resource); } AFSExFreePool( pFcb); } if( pNPFcb != NULL) { AFSExFreePool( pNPFcb); } if( Fcb != NULL) { *Fcb = NULL; } } } return ntStatus; }
NTSTATUS AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt = NULL; IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); AFSFcb *pFcb = NULL; AFSCcb *pCcb = NULL; PFILE_OBJECT pFileObject = NULL; AFSFcb *pRootFcb = NULL; AFSDeviceExt *pControlDeviceExt = NULL; IO_STATUS_BLOCK stIoSB; AFSObjectInfoCB *pObjectInfo = NULL; AFSFileCleanupCB stFileCleanup; ULONG ulNotificationFlags = 0; __try { if( AFSRDRDeviceObject == NULL) { // // Let this through, it's a cleanup on the library control device // try_return( ntStatus); } pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension; // // Set some initial variables to make processing easier // pFileObject = pIrpSp->FileObject; pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext; pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2; if( pFcb == NULL) { try_return( ntStatus); } pObjectInfo = pFcb->ObjectInformation; pRootFcb = pObjectInfo->VolumeCB->RootFcb; RtlZeroMemory( &stFileCleanup, sizeof( AFSFileCleanupCB)); stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId(); stFileCleanup.Identifier = (ULONGLONG)pFileObject; // // Perform the cleanup functionality depending on the type of node it is // switch( pFcb->Header.NodeTypeCode) { case AFS_ROOT_ALL: { AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); AFSReleaseResource( &pFcb->NPFcb->Resource); FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync, &pControlDeviceExt->Specific.Control.DirNotifyList, pCcb); break; } case AFS_IOCTL_FCB: { AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL && pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0) { InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } // // This Fcb represents a file // case AFS_FILE_FCB: { // // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); // // If the handle has write permission ... // if( (pCcb->GrantedAccess & FILE_WRITE_DATA) && CcIsFileCached( pIrpSp->FileObject)) { __try { CcFlushCache( &pFcb->NPFcb->SectionObjectPointers, NULL, 0, &stIoSB); if( !NT_SUCCESS( stIoSB.Status)) { AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n", &pCcb->FullFileName, pObjectInfo->FileId.Cell, pObjectInfo->FileId.Volume, pObjectInfo->FileId.Vnode, pObjectInfo->FileId.Unique, stIoSB.Status, stIoSB.Information); ntStatus = stIoSB.Status; } } __except( EXCEPTION_EXECUTE_HANDLER) { ntStatus = GetExceptionCode(); } } // // Uninitialize the cache map. This call is unconditional. // AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n", pFcb, pFileObject); CcUninitializeCacheMap( pFileObject, NULL, NULL); // // Unlock all outstanding locks on the file, again, unconditionally // (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock, pFileObject, IoGetRequestorProcess( Irp), NULL); // // Tell the service to unlock all on the file // ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL; // // Perform some final common processing // ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); if( pFcb->ObjectInformation->ParentObjectInformation != NULL) { stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId; } stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { stFileCleanup.AllocationSize = pObjectInfo->EndOfFile; stFileCleanup.FileAttributes = pObjectInfo->FileAttributes; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME)) { stFileCleanup.CreateTime = pObjectInfo->CreationTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME)) { stFileCleanup.ChangeTime = pObjectInfo->ChangeTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME)) { stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME)) { stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME); } } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME)) { stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime; } // // If the count has dropped to zero and there is a pending delete // then delete the node // if( pFcb->OpenHandleCount == 0 && BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE)) { // // Stop anything possibly in process // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Specific.File.ExtentsResource, PsGetCurrentThread()); AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource, TRUE); pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED; KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete, 0, FALSE); AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Specific.File.ExtentsResource, PsGetCurrentThread()); AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource); // // Before telling the server about the deleted file, tear down all extents for // the file // AFSTearDownFcbExtents( pFcb, &pCcb->AuthGroup); ntStatus = STATUS_SUCCESS; ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED; // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; // // Push the request to the service // ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); if( !NT_SUCCESS( ntStatus) && ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n", &pCcb->FullFileName, ntStatus); ntStatus = STATUS_SUCCESS; ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE); } else { ntStatus = STATUS_SUCCESS; AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n", &pCcb->FullFileName, pCcb->DirectoryCB); SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED); ASSERT( pObjectInfo->ParentObjectInformation != NULL); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME, (ULONG)FILE_ACTION_REMOVED); // // Now that the service has the entry has deleted we need to remove it from the parent // tree so another lookup on the node will fail // if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE)) { AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock, TRUE); AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup DE %p for %wZ removing entry\n", pCcb->DirectoryCB, &pCcb->DirectoryCB->NameInformation.FileName); AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation, pCcb->DirectoryCB); AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n", pCcb->DirectoryCB, &pCcb->DirectoryCB->NameInformation.FileName); } } } else { if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { ULONG ulNotifyFilter = 0; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED); ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)ulNotifyFilter, (ULONG)FILE_ACTION_MODIFIED); } // // Attempt to flush any dirty extents to the server. This may be a little // aggressive, to flush whenever the handle is closed, but it ensures // coherency. // if( (pCcb->GrantedAccess & FILE_WRITE_DATA) && pFcb->Specific.File.ExtentsDirtyCount != 0) { AFSFlushExtents( pFcb, &pCcb->AuthGroup); } if( pFcb->OpenHandleCount == 0) { // // Wait for any outstanding queued flushes to complete // AFSWaitOnQueuedFlushes( pFcb); ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE; } // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; // // Push the request to the service // AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); } // // Remove the share access at this time since we may not get the close for sometime on this FO. // IoRemoveShareAccess( pFileObject, &pFcb->ShareAccess); // // We don't need the name array after the user closes the handle on the file // if( pCcb->NameArray != NULL) { AFSFreeNameArray( pCcb->NameArray); pCcb->NameArray = NULL; } // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL) { ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0); InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } // // Root or directory node // case AFS_ROOT_FCB: { // // Set the root Fcb to this node // pRootFcb = pFcb; // // Fall through to below // } case AFS_DIRECTORY_FCB: { // // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); // // Perform some final common processing // ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); if( pFcb->ObjectInformation->ParentObjectInformation != NULL) { stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId; } stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { stFileCleanup.FileAttributes = pObjectInfo->FileAttributes; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME)) { stFileCleanup.CreateTime = pObjectInfo->CreationTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME)) { stFileCleanup.ChangeTime = pObjectInfo->ChangeTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME)) { stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME); } } // // If the count has dropped to zero and there is a pending delete // then delete the node // if( pFcb->OpenHandleCount == 0 && BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE)) { // // Try to notify the service about the delete // ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED; // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; // // Push the request to the service // ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); if( !NT_SUCCESS( ntStatus) && ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n", &pCcb->FullFileName, ntStatus); ntStatus = STATUS_SUCCESS; ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE); } else { ntStatus = STATUS_SUCCESS; AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n", &pCcb->FullFileName, pCcb->DirectoryCB); SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED); ASSERT( pObjectInfo->ParentObjectInformation != NULL); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME, (ULONG)FILE_ACTION_REMOVED); // // Now that the service has the entry has deleted we need to remove it from the parent // tree so another lookup on the node will fail // if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE)) { AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock, TRUE); AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation, pCcb->DirectoryCB); AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n", pCcb->DirectoryCB, &pCcb->DirectoryCB->NameInformation.FileName); } } } // // If there have been any updates to the node then push it to // the service // else { if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { ULONG ulNotifyFilter = 0; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED); if( pObjectInfo->ParentObjectInformation != NULL) { ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)ulNotifyFilter, (ULONG)FILE_ACTION_MODIFIED); } } // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); } // // Release the notification for this directory if there is one // FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync, &pControlDeviceExt->Specific.Control.DirNotifyList, pCcb); // // Remove the share access at this time since we may not get the close for sometime on this FO. // IoRemoveShareAccess( pFileObject, &pFcb->ShareAccess); // // We don't need the name array after the user closes the handle on the file // if( pCcb->NameArray != NULL) { AFSFreeNameArray( pCcb->NameArray); pCcb->NameArray = NULL; } // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL) { ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0); InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } case AFS_SYMBOLIC_LINK_FCB: case AFS_MOUNT_POINT_FCB: case AFS_DFS_LINK_FCB: case AFS_INVALID_FCB: { // // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); // // Perform some final common processing // ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); if( pFcb->ObjectInformation->ParentObjectInformation != NULL) { stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId; } stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { stFileCleanup.FileAttributes = pObjectInfo->FileAttributes; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME)) { stFileCleanup.CreateTime = pObjectInfo->CreationTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME)) { stFileCleanup.ChangeTime = pObjectInfo->ChangeTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME)) { stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME); } } // // If the count has dropped to zero and there is a pending delete // then delete the node // if( pFcb->OpenHandleCount == 0 && BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE)) { // // Try to notify the service about the delete // ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED; // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; // // Push the request to the service // ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); if( !NT_SUCCESS( ntStatus) && ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n", &pCcb->FullFileName, ntStatus); ntStatus = STATUS_SUCCESS; ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE); } else { ntStatus = STATUS_SUCCESS; AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n", &pCcb->FullFileName, pCcb->DirectoryCB); SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED); ASSERT( pObjectInfo->ParentObjectInformation != NULL); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME, (ULONG)FILE_ACTION_REMOVED); // // Now that the service has the entry has deleted we need to remove it from the parent // tree so another lookup on the node will fail // if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE)) { AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock, TRUE); AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation, pCcb->DirectoryCB); AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n", pCcb->DirectoryCB, &pCcb->DirectoryCB->NameInformation.FileName); } } } // // If there have been any updates to the node then push it to // the service // else { if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { ULONG ulNotifyFilter = 0; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED); if( pObjectInfo->ParentObjectInformation != NULL) { ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)ulNotifyFilter, (ULONG)FILE_ACTION_MODIFIED); } } // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); } // // Remove the share access at this time since we may not get the close for sometime on this FO. // IoRemoveShareAccess( pFileObject, &pFcb->ShareAccess); // // We don't need the name array after the user closes the handle on the file // if( pCcb->NameArray != NULL) { AFSFreeNameArray( pCcb->NameArray); pCcb->NameArray = NULL; } // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL) { ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0); InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } case AFS_SPECIAL_SHARE_FCB: { AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL && pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0) { InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } default: AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSCleanup Processing unknown node type %d\n", pFcb->Header.NodeTypeCode); break; } try_exit: if( pFileObject != NULL) { // // Setup the fileobject flags to indicate cleanup is complete. // SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE); } // // Complete the request // AFSCompleteRequest( Irp, ntStatus); }
NTSTATUS NdNtfsSecondaryCommonSetQuota ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) { NTSTATUS status; PVOLUME_DEVICE_OBJECT volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb ); BOOLEAN secondarySessionResourceAcquired = FALSE; PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT fileObject = irpSp->FileObject; TYPE_OF_OPEN typeOfOpen; PVCB vcb; PFCB fcb; PSCB scb; PCCB ccb; PSECONDARY_REQUEST secondaryRequest = NULL; PNDFS_REQUEST_HEADER ndfsRequestHeader; PNDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PNDFS_WINXP_REPLY_HEADER ndfsWinxpReplytHeader; _U8 *ndfsWinxpRequestData; LARGE_INTEGER timeOut; struct SetQuota setQuota; PVOID inputBuffer; ULONG inputBufferLength; ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); if(volDo->Secondary == NULL) { status = Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; Irp->IoStatus.Information = 0; return status; } try { secondarySessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->Secondary->SessionResource, BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) { PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } typeOfOpen = NtfsDecodeFileObject( IrpContext, fileObject, &vcb, &fcb, &scb, &ccb, TRUE ); if(FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_UNOPENED)) { ASSERT( FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_CORRUPTED) ); try_return( status = STATUS_FILE_CORRUPT_ERROR ); } setQuota.Length = irpSp->Parameters.SetQuota.Length; inputBuffer = NtfsMapUserBuffer( Irp ); inputBufferLength = setQuota.Length; secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, IRP_MJ_SET_QUOTA, inputBufferLength ); if(secondaryRequest == NULL) { status = Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; try_return( status ); } ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader; INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_SET_QUOTA, inputBufferLength ); ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1); ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData ); INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, Irp, irpSp, ccb->PrimaryFileHandle ); ndfsWinxpRequestHeader->SetQuota.Length = inputBufferLength; ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1); RtlCopyMemory(ndfsWinxpRequestData, inputBuffer, inputBufferLength) ; secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE; QueueingSecondaryRequest( volDo->Secondary, secondaryRequest ); timeOut.QuadPart = -NDNTFS_TIME_OUT; status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut ); KeClearEvent( &secondaryRequest->CompleteEvent ); if(status != STATUS_SUCCESS) { secondaryRequest = NULL; try_return( status = STATUS_IO_DEVICE_ERROR ); } if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) { if (IrpContext->OriginatingIrp) PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp ); DebugTrace( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData; status = Irp->IoStatus.Status = ndfsWinxpReplytHeader->Status; Irp->IoStatus.Information = ndfsWinxpReplytHeader->Information; try_exit: NOTHING; } finally { if( secondarySessionResourceAcquired == TRUE ) { SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource ); } if(secondaryRequest) DereferenceSecondaryRequest( secondaryRequest ); } return status; }
NTSTATUS MsCommonCreate ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the common routine for creating/opening a file. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - the return status for the operation. --*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; PFILE_OBJECT relatedFileObject; UNICODE_STRING fileName; ACCESS_MASK desiredAccess; USHORT shareAccess; BOOLEAN caseInsensitive = TRUE; //**** Make all searches case insensitive PVCB vcb; PFCB fcb; UNICODE_STRING remainingPart; PAGED_CODE(); // // Make local copies of our input parameters to make things easier. // irpSp = IoGetCurrentIrpStackLocation( Irp ); fileObject = irpSp->FileObject; relatedFileObject = irpSp->FileObject->RelatedFileObject; fileName = *(PUNICODE_STRING)&irpSp->FileObject->FileName; desiredAccess = irpSp->Parameters.Create.SecurityContext->DesiredAccess; shareAccess = irpSp->Parameters.Create.ShareAccess; DebugTrace(+1, Dbg, "MsCommonCreate\n", 0 ); DebugTrace( 0, Dbg, "MsfsDeviceObject = %08lx\n", (ULONG)MsfsDeviceObject ); DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp ); DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG)fileObject ); DebugTrace( 0, Dbg, "relatedFileObject = %08lx\n", (ULONG)relatedFileObject ); DebugTrace( 0, Dbg, "FileName = %wZ\n", (ULONG)&fileName ); DebugTrace( 0, Dbg, "DesiredAccess = %08lx\n", desiredAccess ); DebugTrace( 0, Dbg, "ShareAccess = %08lx\n", shareAccess ); // // Get the VCB we are trying to access. // vcb = &MsfsDeviceObject->Vcb; // // Acquire exclusive access to the VCB. // MsAcquireExclusiveVcb( vcb ); try { // // Check if we are trying to open the mailslot file system // (i.e., the Vcb). // if ((fileName.Length == 0) && ((relatedFileObject == NULL) || ( NodeType(relatedFileObject->FsContext) == MSFS_NTC_VCB))) { DebugTrace(0, Dbg, "Open mailslot file system\n", 0); Irp->IoStatus = MsOpenMailslotFileSystem( vcb, fileObject, desiredAccess, shareAccess ); status = Irp->IoStatus.Status; MsCompleteRequest( Irp, status ); try_return( NOTHING ); } // // Check if we are trying to open the root directory. // if (((fileName.Length == sizeof(WCHAR)) && (fileName.Buffer[0] == L'\\') && (relatedFileObject == NULL)) || ((fileName.Length == 0) && (NodeType( relatedFileObject->FsContext) == MSFS_NTC_ROOT_DCB))) { DebugTrace(0, Dbg, "Open root directory system\n", 0); Irp->IoStatus = MsOpenMailslotRootDirectory( vcb->RootDcb, fileObject, desiredAccess, shareAccess ); status = Irp->IoStatus.Status; MsCompleteRequest( Irp, status ); try_return( NOTHING ); } // // If there is a related file object then this is a relative open // and it better be the root DCB. Both the then and the else clause // return an FCB. // if (relatedFileObject != NULL) { PDCB dcb; dcb = relatedFileObject->FsContext; if (NodeType(dcb) != MSFS_NTC_ROOT_DCB) { DebugTrace(0, Dbg, "Bad file name\n", 0); MsCompleteRequest( Irp, STATUS_OBJECT_NAME_INVALID ); try_return( status = STATUS_OBJECT_NAME_INVALID ); } fcb = MsFindRelativePrefix( dcb, &fileName, caseInsensitive, &remainingPart ); } else { // // The only nonrelative name we allow are of the form // "\mailslot-name". // if ((fileName.Length <= sizeof( WCHAR )) || (fileName.Buffer[0] != L'\\')) { DebugTrace(0, Dbg, "Bad file name\n", 0); MsCompleteRequest( Irp, STATUS_OBJECT_NAME_INVALID ); try_return( status = STATUS_OBJECT_NAME_INVALID ); } fcb = MsFindPrefix( vcb, &fileName, caseInsensitive, &remainingPart ); } // // If the remaining name is not empty then we have an error, either // we have an illegal name or a non-existent name. // if (remainingPart.Length != 0) { if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) { // // We were given a name such as "\mailslot-name\another-name" // DebugTrace(0, Dbg, "Illegal object name\n", 0); status = STATUS_OBJECT_NAME_INVALID; } else { // // We were given a non-existent name // DebugTrace(0, Dbg, "non-existent name\n", 0); status = STATUS_OBJECT_NAME_NOT_FOUND; } } else { // // The remaining name is empty so we better have an FCB otherwise // we have an invalid object name. // if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) { DebugTrace(0, Dbg, "Create client end mailslot, Fcb = %08lx\n", (ULONG)fcb ); Irp->IoStatus = MsCreateClientEnd( fcb, fileObject, desiredAccess, shareAccess, irpSp->Parameters.Create.SecurityContext->AccessState, Irp->RequestorMode, Irp->Tail.Overlay.Thread ); status = Irp->IoStatus.Status; } else { DebugTrace(0, Dbg, "Illegal object name\n", 0); status = STATUS_OBJECT_NAME_INVALID; } } // // Complete the IRP and return to the caller. // MsCompleteRequest( Irp, status ); try_exit: NOTHING; } finally { MsReleaseVcb( vcb ); DebugTrace(-1, Dbg, "MsCommonCreate -> %08lx\n", status); } return status; }