VOID NtfsReleaseVolumeFromClose ( IN PVOID OpaqueVcb ) /*++ Routine Description: The address of this routine is specified when creating a CacheMap for a file. It is subsequently called by the Lazy Writer after its performing closes on the file. Arguments: Vcb - The Vcb which was specified as a close context parameter for this routine. Return Value: None --*/ { PVCB Vcb = (PVCB)OpaqueVcb; ASSERT_VCB(Vcb); PAGED_CODE(); NtfsReleaseVcb( NULL, Vcb ); return; }
BOOLEAN NtfsAcquireVolumeForClose ( IN PVOID OpaqueVcb, IN BOOLEAN Wait ) /*++ Routine Description: The address of this routine is specified when creating a CacheMap for a file. It is subsequently called by the Lazy Writer prior to its performing closes to the file. This callback is necessary to avoid deadlocks with the Lazy Writer. (Note that normal closes acquire the Vcb, and then call the Cache Manager, who must acquire some of his internal structures. If the Lazy Writer could not call this routine first, and were to issue a write after locking Caching data structures, then a deadlock could occur.) Arguments: Vcb - The Vcb which was specified as a close context parameter for this routine. Wait - TRUE if the caller is willing to block. Return Value: FALSE - if Wait was specified as FALSE and blocking would have been required. The Fcb is not acquired. TRUE - if the Vcb has been acquired --*/ { PVCB Vcb = (PVCB)OpaqueVcb; ASSERT_VCB(Vcb); PAGED_CODE(); // // Do the code of acquire exclusive Vcb but without the IrpContext // if (ExAcquireResourceExclusive( &Vcb->Resource, Wait )) { return TRUE; } return FALSE; }
NTSTATUS XixFsWriteFileInfoFromFcb( IN PXIFS_FCB pFCB, IN BOOLEAN Waitable, IN uint8 * Buffer, IN uint32 BufferSize ) { NTSTATUS RC = STATUS_SUCCESS; uint64 FileId = 0; PXIFS_VCB pVCB = NULL; PAGED_CODE(); ASSERT_FCB(pFCB); pVCB = pFCB->PtrVCB; ASSERT_VCB(pVCB); ASSERT(Waitable == TRUE); ASSERT(BufferSize >= XIDISK_FILE_HEADER_LOT_SIZE); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Enter XixFsWriteFileInfoFromFcb\n")); try{ RC = XixFsRawWriteLotAndFileHeader( pVCB->TargetDeviceObject, pVCB->LotSize, pFCB->LotNumber, Buffer, XIDISK_FILE_HEADER_LOT_SIZE, pVCB->SectorSize ); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("Fail Write File Data(%I64d).\n", pFCB->LotNumber)); try_return (RC); } }finally{ } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Exit XixFsWriteFileInfoFromFcb Status(0x%x)\n", RC)); return RC; }
BOOLEAN NtfsAcquireSharedVcb ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN RaiseOnCantWait ) /*++ Routine Description: This routine acquires shared access to the Vcb. This routine will raise if it cannot acquire the resource and wait in the IrpContext is false. Arguments: Vcb - Supplies the Vcb to acquire RaiseOnCantWait - Indicates if we should raise on an acquisition error or simply return a BOOLEAN indicating that we couldn't get the resource. Return Value: None. --*/ { ASSERT_IRP_CONTEXT(IrpContext); ASSERT_VCB(Vcb); PAGED_CODE(); if (ExAcquireResourceShared( &Vcb->Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) { return TRUE; } if (RaiseOnCantWait) { NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } else { return FALSE; } }
ULONG UdfLookupPsnOfExtent ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN USHORT Reference, IN ULONG Lbn, IN ULONG Len ) /*++ Routine Description: This routine maps the input logical block extent on a given partition to a starting physical sector. It doubles as a bounds checker - if the routine does not raise, the caller is guaranteed that the extent lies within the partition. Arguments: Vcb - Vcb of logical volume Reference - Partition reference to use in the mapping Lbn - Logical block number Len - Length of extent in bytes Return Value: ULONG physical sector number --*/ { PPCB Pcb = Vcb->Pcb; ULONG Psn; PBCB Bcb; LARGE_INTEGER Offset; PULONG MappedLbn; PAGED_CODE(); // // Check inputs // ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_VCB( Vcb ); ASSERT_PCB( Pcb ); DebugTrace(( +1, Dbg, "UdfLookupPsnOfExtent, [%04x/%08x, +%08x)\n", Reference, Lbn, Len )); if (Reference < Pcb->Partitions) { while (TRUE) { switch (Pcb->Partition[Reference].Type) { case Physical: // // Check that the input extent lies inside the partition. Calculate the // Lbn of the last block and see that it is interior. // if (SectorsFromBlocks( Vcb, Lbn ) + SectorsFromBytes( Vcb, Len ) > Pcb->Partition[Reference].Physical.Length) { goto NoGood; } Psn = Pcb->Partition[Reference].Physical.Start + SectorsFromBlocks( Vcb, Lbn ); DebugTrace(( -1, Dbg, "UdfLookupPsnOfExtent -> %08x\n", Psn )); return Psn; case Virtual: // // Bounds check. Per UDF 2.00 2.3.10 and implied in UDF 1.50, virtual // extent lengths cannot be greater than one block in size. // if (Lbn + BlocksFromBytes( Vcb, Len ) > Pcb->Partition[Reference].Virtual.Length || Len > BlockSize( Vcb )) { goto NoGood; } try { // // Calculate the location of the mapping element in the VAT // and retrieve. // Offset.QuadPart = Lbn * sizeof(ULONG); CcMapData( Vcb->VatFcb->FileObject, &Offset, sizeof(ULONG), TRUE, &Bcb, &MappedLbn ); // // Now rewrite the inputs in terms of the virtual mapping. We // will reloop to perform the logical -> physical mapping. // DebugTrace(( 0, Dbg, "UdfLookupPsnOfExtent, Mapping V %04x/%08x -> L %04x/%08x\n", Reference, Lbn, Pcb->Partition[Reference].Virtual.RelatedReference, *MappedLbn )); Lbn = *MappedLbn; Reference = Pcb->Partition[Reference].Virtual.RelatedReference; } finally { DebugUnwind( UdfLookupPsnOfExtent ); UdfUnpinData( IrpContext, &Bcb ); } // // An Lbn of ~0 in the VAT is defined to indicate that the sector is unused, // so we should never see such a thing. // if (Lbn == ~0) { goto NoGood; } break; default: ASSERT(FALSE); break; } } } NoGood: // // Some people have misinterpreted a partition number to equal a // partition reference, or perhaps this is just corrupt media. // UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR ); }
NTSTATUS NtfsQueryFsSizeInfo ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_FS_SIZE_INFORMATION Buffer, IN OUT PULONG Length ) /*++ Routine Description: This routine implements the query size information call Arguments: Vcb - Supplies the Vcb being queried Buffer - Supplies a pointer to the output buffer where the information is to be returned Length - Supplies the length of the buffer in byte. This variable upon return recieves the remaining bytes free in the buffer Return Value: NTSTATUS - Returns the status for the query --*/ { ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_VCB( Vcb ); PAGED_CODE(); DebugTrace( 0, Dbg, ("NtfsQueryFsSizeInfo...\n") ); // // Make sure the buffer is large enough and zero it out // if (*Length < sizeof(FILE_FS_SIZE_INFORMATION)) { return STATUS_BUFFER_OVERFLOW; } RtlZeroMemory( Buffer, sizeof(FILE_FS_SIZE_INFORMATION) ); // // Check if we need to rescan the bitmap. Don't try this // if we have started to teardown the volume. // if (FlagOn( Vcb->VcbState, VCB_STATE_RELOAD_FREE_CLUSTERS ) && FlagOn( Vcb->VcbState, VCB_STATE_VOLUME_MOUNTED )) { // // Acquire the volume bitmap shared to rescan the bitmap. // NtfsAcquireExclusiveScb( IrpContext, Vcb->BitmapScb ); try { NtfsScanEntireBitmap( IrpContext, Vcb, FALSE ); } finally { NtfsReleaseScb( IrpContext, Vcb->BitmapScb ); } }
NTSTATUS NtfsQueryFsVolumeInfo ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_FS_VOLUME_INFORMATION Buffer, IN OUT PULONG Length ) /*++ Routine Description: This routine implements the query volume info call Arguments: Vcb - Supplies the Vcb being queried Buffer - Supplies a pointer to the output buffer where the information is to be returned Length - Supplies the length of the buffer in byte. This variable upon return recieves the remaining bytes free in the buffer Return Value: NTSTATUS - Returns the status for the query --*/ { NTSTATUS Status; ULONG BytesToCopy; ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_VCB( Vcb ); PAGED_CODE(); DebugTrace( 0, Dbg, ("NtfsQueryFsVolumeInfo...\n") ); // // Get the volume creation time from the Vcb. // Buffer->VolumeCreationTime.QuadPart = Vcb->VolumeCreationTime; // // Fill in the serial number and indicate that we support objects // Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber; Buffer->SupportsObjects = TRUE; Buffer->VolumeLabelLength = Vcb->Vpb->VolumeLabelLength; // // Update the length field with how much we have filled in so far. // *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]); // // See how many bytes of volume label we can copy // if (*Length >= (ULONG)Vcb->Vpb->VolumeLabelLength) { Status = STATUS_SUCCESS; BytesToCopy = Vcb->Vpb->VolumeLabelLength; } else { Status = STATUS_BUFFER_OVERFLOW; BytesToCopy = *Length; } // // Copy over the volume label (if there is one). // RtlCopyMemory( &Buffer->VolumeLabel[0], &Vcb->Vpb->VolumeLabel[0], BytesToCopy); // // Update the buffer length by the amount we copied. // *Length -= BytesToCopy; return Status; }
NTSTATUS xixfs_CommonClose( IN PXIXFS_IRPCONTEXT pIrpContext ) { NTSTATUS RC = STATUS_SUCCESS; PXIXFS_FCB pFCB = NULL; PXIXFS_CCB pCCB = NULL; PXIXFS_VCB pVCB = NULL; PFILE_OBJECT pFileObject = NULL; PIRP pIrp = NULL; PIO_STACK_LOCATION pIrpSp = NULL; BOOLEAN OpenVCB = FALSE; BOOLEAN PotentialVCBUnmount = FALSE; BOOLEAN CanWait = FALSE; BOOLEAN ForceDismount = FALSE; BOOLEAN bUserReference = FALSE; TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject; BOOLEAN bVcbAcq = FALSE; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CLOSE| DEBUG_TARGET_IRPCONTEXT), ("Enter xixfs_CommonClose IrpContext(%p)\n", pIrpContext)); ASSERT_IRPCONTEXT(pIrpContext); pIrp = pIrpContext->Irp; ASSERT(pIrp); // check if open request is releated to file system CDO { PDEVICE_OBJECT DeviceObject = pIrpContext->TargetDeviceObject; ASSERT(DeviceObject); if (DeviceObject == XiGlobalData.XifsControlDeviceObject) { RC = STATUS_SUCCESS; DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLOSE| DEBUG_TARGET_IRPCONTEXT), ("CDO Device Close DevObj(%p).\n", DeviceObject)); xixfs_CompleteRequest(pIrpContext,RC,0); return(RC); } } if(pIrpContext->VCB == NULL) { DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_CLOSE, ("pIrpContext->VCB == NULL.\n")); RC = STATUS_SUCCESS; xixfs_CompleteRequest(pIrpContext, RC, 0); return RC; } CanWait = XIXCORE_TEST_FLAGS(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT); pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp); pFileObject = pIrpSp->FileObject; ASSERT(pFileObject); TypeOfOpen = xixfs_DecodeFileObject(pFileObject, &pFCB, &pCCB); if(TypeOfOpen == UnopenedFileObject) { DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLOSE| DEBUG_TARGET_IRPCONTEXT), ("TypeOfOpen <= StreamFileOpen.\n")); xixfs_CompleteRequest(pIrpContext, STATUS_SUCCESS, 0); return STATUS_SUCCESS; } if(TypeOfOpen == UserVolumeOpen) { ForceDismount = XIXCORE_TEST_FLAGS( pCCB->CCBFlags, XIXFSD_CCB_DISMOUNT_ON_CLOSE); if(ForceDismount) { if(!CanWait) { DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLOSE| DEBUG_TARGET_IRPCONTEXT), ("Force Dismount with Non Waitable Context.\n")); RC = xixfs_PostRequest(pIrpContext, pIrp); return RC; } } } DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, ("!!!!Close pCCB(%p) FileObject(%p)\n", pCCB, pFileObject)); ASSERT_FCB(pFCB); pVCB = pFCB->PtrVCB; ASSERT_VCB(pVCB); if( (pVCB->VCBCleanup == 0) && (pVCB->VCBState != XIFSD_VCB_STATE_VOLUME_MOUNTED) ) { if(!CanWait) { DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLOSE| DEBUG_TARGET_IRPCONTEXT), ("Force Dismount with Non Waitable Context.\n")); RC = xixfs_PostRequest(pIrpContext, pIrp); return RC; } } // // Clean up any CCB associated with this open. // try { if( ((TypeOfOpen == UserDirectoryOpen) || (TypeOfOpen == UserFileOpen) || (TypeOfOpen == UserVolumeOpen)) && (pCCB != NULL) ) { bUserReference = TRUE; DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_CCB), ("XifsdCommonClose Delete CCB (%x)\n", pCCB)); // Test //XifsdLockFcb(NULL, pFCB); //RemoveEntryList(&pCCB->LinkToFCB); //XifsdUnlockFcb(NULL, pFCB); xixfs_FreeCCB( pCCB ); } DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_REFCOUNT|DEBUG_TARGET_FCB|DEBUG_TARGET_VCB), ("XifsdCommonClose GenINFO Fcb LotNumber(%I64d) TypeOfOpen (%ld) Fcb %d/%d Vcb %d/%d \n", pFCB->XixcoreFcb.LotNumber, TypeOfOpen, pFCB->FCBReference, pFCB->FCBUserReference, pVCB->VCBReference, pVCB->VCBUserReference)); /* if(CanWait){ if(TypeOfOpen == UserFileOpen){ if(pFCB->FCBCleanup == 0){ if(pFCB->SectionObject.DataSectionObject != NULL) { CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL); CcPurgeCacheSection( &(pFCB->SectionObject), NULL, 0, FALSE ); } if(XIXCORE_TEST_FLAGS(pFCB->FCBFlags,XIXCORE_FCB_MODIFIED_FILE)){ xixfs_LastUpdateFileFromFCB(pFCB); } } } } */ if((pVCB->VCBState == XIFSD_VCB_STATE_VOLUME_MOUNTED) && ((TypeOfOpen == UserFileOpen) || (TypeOfOpen == UserDirectoryOpen)) && (pFCB != pVCB->RootDirFCB)) { DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_FCB), ("XifsdCommonClose Destroy FCB (%x)\n", pFCB)); DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_REFCOUNT|DEBUG_TARGET_FCB|DEBUG_TARGET_VCB), ("XifsdCommonClose, Fcb %08x Vcb %d/%d Fcb %d/%d\n", pFCB, pVCB->VCBReference, pVCB->VCBUserReference, pFCB->FCBReference, pFCB->FCBUserReference )); xixfs_TryClose(CanWait, bUserReference, pFCB); RC = STATUS_SUCCESS; try_return(RC); } else { if( ((pVCB->VCBCleanup == 0) || ForceDismount) && (pVCB->VCBState != XIFSD_VCB_STATE_VOLUME_MOUNTED)) { if(ForceDismount) { FsRtlNotifyVolumeEvent(pFileObject, FSRTL_VOLUME_DISMOUNT); } if( ((pVCB->VCBCleanup == 0) || ForceDismount) && (pVCB->VCBState != XIFSD_VCB_STATE_VOLUME_MOUNTED)) { PotentialVCBUnmount = TRUE; if(bVcbAcq)XifsdReleaseVcb(TRUE,pVCB); XifsdAcquireGData(pIrpContext); DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLOSE| DEBUG_TARGET_RESOURCE), ("XifsdCommonClose Acquire exclusive GData(%p)\n", &XiGlobalData.DataResource)); bVcbAcq = XifsdAcquireVcbExclusive(TRUE,pVCB, FALSE); DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLOSE| DEBUG_TARGET_VCB|DEBUG_TARGET_RESOURCE), ("XifsdCommonClose Acquire exclusive VCBResource(%p)\n", pVCB->VCBResource)); } } if(PotentialVCBUnmount && bVcbAcq) { if(!xixfs_CheckForDismount(pIrpContext, pVCB, TRUE)) { bVcbAcq = FALSE; RC = STATUS_SUCCESS; try_return(RC); } } RC = xixfs_TryClose(CanWait, bUserReference, pFCB); if(NT_SUCCESS(RC)) { if(PotentialVCBUnmount && bVcbAcq) { if(!xixfs_CheckForDismount(pIrpContext, pVCB, FALSE)) { bVcbAcq = FALSE; RC = STATUS_SUCCESS; try_return(RC); } } } RC = STATUS_SUCCESS; } ; } finally{ if(bVcbAcq) { XifsdReleaseVcb(TRUE, pVCB); } if(PotentialVCBUnmount) { XifsdReleaseGData(pIrpContext); PotentialVCBUnmount = FALSE; } } xixfs_CompleteRequest(pIrpContext, RC, 0); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CLOSE| DEBUG_TARGET_IRPCONTEXT), ("Exit xixfs_CommonClose \n")); return RC; }
NTSTATUS XixFsdCommonCleanUp( IN PXIFS_IRPCONTEXT pIrpContext ) { NTSTATUS RC = STATUS_SUCCESS; PXIFS_FCB pFCB = NULL; PXIFS_CCB pCCB = NULL; PXIFS_VCB pVCB = NULL; PFILE_OBJECT pFileObject = NULL; TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject; PIRP pIrp = NULL; PIO_STACK_LOCATION pIrpSp = NULL; KIRQL SavedIrql; PXIFS_LCB pLCB = NULL; PXIFS_FCB pParentFCB = NULL; BOOLEAN Wait = FALSE; BOOLEAN VCBAcquired = FALSE; BOOLEAN ParentFCBAcquired = FALSE; BOOLEAN CanWait = FALSE; BOOLEAN AttemptTeardown = FALSE; BOOLEAN SendUnlockNotification = FALSE; PAGED_CODE(); DebugTrace((DEBUG_LEVEL_TRACE), (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT), ("Enter XifsdCommonCleanUp pIrpContext(%p)\n", pIrpContext)); ASSERT_IRPCONTEXT(pIrpContext); pIrp = pIrpContext->Irp; ASSERT(pIrp); // check if open request is releated to file system CDO { PDEVICE_OBJECT DeviceObject = pIrpContext->TargetDeviceObject; ASSERT(DeviceObject); if (DeviceObject == XiGlobalData.XifsControlDeviceObject) { RC = STATUS_SUCCESS; DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CLEANUP), ("CDO Device TargetDevide(%p).\n", DeviceObject)); XixFsdCompleteRequest(pIrpContext,RC,0); return(RC); } } if(pIrpContext->VCB == NULL){ DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_CLEANUP, ("pIrpContext->VCB == NULL.\n")); RC = STATUS_SUCCESS; XixFsdCompleteRequest(pIrpContext, RC, 0); return RC; } pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp); pFileObject = pIrpSp->FileObject; ASSERT(pFileObject); TypeOfOpen = XixFsdDecodeFileObject(pFileObject, &pFCB, &pCCB); if(TypeOfOpen <= StreamFileOpen){ DebugTrace((DEBUG_LEVEL_TRACE|DEBUG_LEVEL_INFO), DEBUG_TARGET_CLEANUP, ("TypeOfOpen <= StreamFileOpen.\n")); XixFsdCompleteRequest(pIrpContext, STATUS_SUCCESS, 0); return STATUS_SUCCESS; } CanWait = XifsdCheckFlagBoolean(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT); if(CanWait == FALSE){ DebugTrace((DEBUG_LEVEL_TRACE|DEBUG_LEVEL_INFO), (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_IRPCONTEXT), ("PostRequest IrpCxt(%p) Irp(%p)\n", pIrpContext, pIrp)); RC = XixFsdPostRequest(pIrpContext, pIrp); return RC; } ASSERT_FCB(pFCB); pVCB = pFCB->PtrVCB; ASSERT_VCB(pVCB); DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE|DEBUG_TARGET_VCB), ("Acquire exclusive pVCB(%p) VCBResource(%p).\n", pVCB, &pVCB->VCBResource)); if((TypeOfOpen == UserVolumeOpen) && XifsdCheckFlagBoolean(pFileObject->Flags, FO_FILE_MODIFIED)) { XifsdAcquireVcbExclusive(CanWait, pVCB, FALSE); VCBAcquired = TRUE; } XifsdAcquireFcbExclusive(CanWait, pFCB, FALSE); DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB), ("Acquire exclusive FCB(%p) FCBResource(%p).\n", pFCB, pFCB->FCBResource)); XifsdSetFlag(pFileObject->Flags, FO_CLEANUP_COMPLETE); DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB), ("Set File Object Flags(0x%x)\n", pFileObject->Flags)); //IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess ); try{ switch(TypeOfOpen){ case UserDirectoryOpen: if(XifsdCheckFlagBoolean(pCCB->CCBFlags, XIFSD_CCB_FLAG_NOFITY_SET)) { DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, ("CompletionFilter Notify CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB)); FsRtlNotifyCleanup(pVCB->NotifyIRPSync, &pVCB->NextNotifyIRP, pCCB); //DbgPrint("Notify CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB); } //DbgPrint("CleanUp (%wZ) pCCB(%p) pCCB->CCBFlags(%x)\n", &pFCB->FCBName, pCCB, pCCB->CCBFlags); DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, ("!!!!CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB)); IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess ); break; case UserFileOpen: // // Coordinate the cleanup operation with the oplock state. // Oplock cleanup operations can always cleanup immediately so no // need to check for STATUS_PENDING. // FsRtlCheckOplock( &pFCB->FCBOplock, pIrp, pIrpContext, NULL, NULL ); // // Unlock all outstanding file locks. // if (pFCB->FCBFileLock != NULL) { FsRtlFastUnlockAll( pFCB->FCBFileLock, pFileObject, IoGetRequestorProcess( pIrp ), NULL ); } // // Check the fast io state. // XifsdLockFcb( pIrpContext, pFCB ); pFCB->IsFastIoPossible = XixFsdCheckFastIoPossible( pFCB ); XifsdUnlockFcb( pIrpContext, pFCB ); /* if((pFCB->HasLock != FCB_FILE_LOCK_HAS) && (!XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_OPEN_WRITE)) && XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED) && (pFCB->FCBCleanup == 1) ){ if(pFCB->SectionObject.DataSectionObject != NULL) { CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL); ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE); ExReleaseResourceLite( pFCB->PagingIoResource ); CcPurgeCacheSection( &(pFCB->SectionObject), NULL, 0, FALSE ); } } */ if( XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED) && (pFCB->FcbNonCachedOpenCount > 1) && ((pFCB->FcbNonCachedOpenCount + 1) == pFCB->FCBCleanup) ) { if(pFCB->SectionObject.DataSectionObject != NULL) { // changed by ILGU HONG for readonly 09052006 if(!pFCB->PtrVCB->IsVolumeWriteProctected) CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL); // changed by ILGU HONG for readonly end //DbgPrint("CcFlush 1 File(%wZ)\n", &pFCB->FCBFullPath); ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE); ExReleaseResourceLite( pFCB->PagingIoResource ); CcPurgeCacheSection( &(pFCB->SectionObject), NULL, 0, FALSE ); } } /* else if(pFCB->FCBCleanup == 1 ){ if(XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED)){ if(pFCB->SectionObject.DataSectionObject != NULL) { CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL); ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE); ExReleaseResourceLite( pFCB->PagingIoResource ); CcPurgeCacheSection( &(pFCB->SectionObject), NULL, 0, FALSE ); } } if(XifsdCheckFlagBoolean(pFCB->FCBFlags,XIFSD_FCB_MODIFIED_FILE)){ XixFsdUpdateFCB(pFCB); } } */ IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess ); // // Cleanup the cache map. // CcUninitializeCacheMap( pFileObject, NULL, NULL ); break; case UserVolumeOpen: break; default: break; } if((TypeOfOpen == UserDirectoryOpen) || (TypeOfOpen == UserFileOpen)){ if(pFCB->FCBCleanup == 1 ){ if(XifsdCheckFlagBoolean(pFCB->FCBFlags,XIFSD_FCB_MODIFIED_FILE)){ // changed by ILGU HONG for readonly 09052006 if(!pFCB->PtrVCB->IsVolumeWriteProctected){ XixFsdUpdateFCB(pFCB); if(pFCB->WriteStartOffset != -1){ //DbgPrint("Set Update Information!!!\n"); XixFsdSendFileChangeRC( TRUE, pVCB->HostMac, pFCB->LotNumber, pVCB->DiskId, pVCB->PartitionId, pFCB->FileSize.QuadPart, pFCB->RealAllocationSize, pFCB->WriteStartOffset ); pFCB->WriteStartOffset = -1; } } // changed by ILGU HONG for readonly end } } if(XifsdCheckFlagBoolean(pCCB->CCBFlags, XIFSD_CCB_FLAGS_DELETE_ON_CLOSE)){ if(pFCB == pFCB->PtrVCB->RootDirFCB){ XifsdClearFlag(pCCB->CCBFlags, XIFSD_CCB_FLAGS_DELETE_ON_CLOSE); XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE); }else{ XifsdSetFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE); } } // changed by ILGU HONG for readonly 09082006 if(XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE) && (!pFCB->PtrVCB->IsVolumeWriteProctected) ){ // changed by ILGU HONG for readonly end if(pFCB->FCBCleanup == 1){ //DbgPrint(" !!!Delete Entry From table (%wZ) .\n", &pFCB->FCBFullPath); ASSERT_CCB(pCCB); pLCB = pCCB->PtrLCB; ASSERT_LCB(pLCB); pParentFCB = pLCB->ParentFcb; ASSERT_FCB(pParentFCB); pFCB->FileSize.QuadPart = 0; pFCB->ValidDataLength.QuadPart = 0; if(pFCB->FCBType == FCB_TYPE_FILE){ XifsdReleaseFcb(TRUE, pFCB); XifsdAcquireFcbExclusive(TRUE, pParentFCB, FALSE); ParentFCBAcquired = TRUE; XifsdAcquireFcbExclusive(TRUE, pFCB, FALSE); RC = DeleteParentChild(pIrpContext, pParentFCB, &pLCB->FileName); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName)); //XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE); RC = STATUS_SUCCESS; goto pass_through; } XifsdClearFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_DELETE_ON_CLOSE); XifsdSetFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_LINK_IS_GONE); XixFsdRemovePrefix(TRUE, pLCB); // // Now Decrement the reference counts for the parent and drop the Vcb. // XifsdLockVcb(pIrpContext,pVCB); DebugTrace( DEBUG_LEVEL_INFO, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT), ("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", pParentFCB->LotNumber, pVCB->VCBReference, pVCB->VCBUserReference, pParentFCB->FCBReference, pParentFCB->FCBUserReference )); XifsdDecRefCount( pParentFCB, 1, 1 ); DebugTrace( DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT), ("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", pParentFCB->LotNumber, pVCB->VCBReference, pVCB->VCBUserReference, pParentFCB->FCBReference, pParentFCB->FCBUserReference )); XifsdUnlockVcb( pIrpContext, pVCB ); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName)); XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE); RC = STATUS_SUCCESS; goto pass_through; } }else { RC = XixFsReLoadFileFromFcb(pFCB); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("Fail XixFsReLoadFileFromFcb (%wZ)\n", &pFCB->FCBName)); XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE); RC = STATUS_SUCCESS; goto pass_through; } if(pFCB->ChildCount != 0){ XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE); RC = STATUS_SUCCESS; goto pass_through; } XifsdReleaseFcb(TRUE, pFCB); XifsdAcquireFcbExclusive(TRUE, pParentFCB, FALSE); ParentFCBAcquired = TRUE; XifsdAcquireFcbExclusive(TRUE, pFCB, FALSE); RC = DeleteParentChild(pIrpContext, pParentFCB, &pLCB->FileName); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName)); //ifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE); RC = STATUS_SUCCESS; goto pass_through; } XifsdClearFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_DELETE_ON_CLOSE); XifsdSetFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_LINK_IS_GONE); XixFsdRemovePrefix(TRUE, pLCB); // // Now Decrement the reference counts for the parent and drop the Vcb. // XifsdLockVcb(pIrpContext,pVCB); DebugTrace( DEBUG_LEVEL_INFO, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT), ("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", pParentFCB->LotNumber, pVCB->VCBReference, pVCB->VCBUserReference, pParentFCB->FCBReference, pParentFCB->FCBUserReference )); XifsdDecRefCount( pParentFCB, 1, 1 ); DebugTrace( DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT), ("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", pParentFCB->LotNumber, pVCB->VCBReference, pVCB->VCBUserReference, pParentFCB->FCBReference, pParentFCB->FCBUserReference )); XifsdUnlockVcb( pIrpContext, pVCB ); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName)); XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE); RC = STATUS_SUCCESS; goto pass_through; } } //XixFsdDeleteUpdateFCB(pFCB); XixFsdSendRenameLinkBC( TRUE, XIFS_SUBTYPE_FILE_DEL, pVCB->HostMac, pFCB->LotNumber, pVCB->DiskId, pVCB->PartitionId, pFCB->ParentLotNumber, 0 ); } } } pass_through: XifsdLockVcb(pIrpContext, pVCB); if(XifsdCheckFlagBoolean(pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) { ASSERT(pFCB->FcbNonCachedOpenCount > 0); pFCB->FcbNonCachedOpenCount --; } XifsdDecrementClenupCount(pFCB); DebugTrace(DEBUG_LEVEL_ALL, DEBUG_TARGET_ALL, ("Cleanup Name(%wZ) FCBLotNumber(%I64d) FCBCleanUp(%ld) VCBCleanup(%ld) pCCB(%p) FileObject(%p)\n", &pFCB->FCBName, pFCB->LotNumber, pFCB->FCBCleanup, pVCB->VCBCleanup, pCCB, pFileObject )); XifsdUnlockVcb( pIrpContext, pVCB ); AttemptTeardown = (pVCB->VCBCleanup == 0 && pVCB->VCBState == XIFSD_VCB_STATE_VOLUME_DISMOUNTED ); if(pFileObject == pVCB->LockVolumeFileObject){ ASSERT(XifsdCheckFlagBoolean(pVCB->VCBFlags, XIFSD_VCB_FLAGS_VOLUME_LOCKED)); IoAcquireVpbSpinLock(&SavedIrql); XifsdClearFlag(pVCB->PtrVPB->Flags, VPB_LOCKED); IoReleaseVpbSpinLock( SavedIrql ); XifsdClearFlag(pVCB->VCBFlags, XIFSD_VCB_FLAGS_VOLUME_LOCKED); pVCB->LockVolumeFileObject = NULL; SendUnlockNotification = TRUE; } /* if( (pFCB->FCBCleanup == 0) && (!XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE)) ){ DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT| DEBUG_TARGET_ALL), ("CleanUp Release Lot Lock LotNumber(%ld)\n", pFCB->LotNumber)); XifsdLotUnLock(pVCB, pVCB->TargetDeviceObject, pFCB->LotNumber); pFCB->HasLock = FCB_FILE_LOCK_INVALID; } */ // // We must clean up the share access at this time, since we may not // get a Close call for awhile if the file was mapped through this // File Object. // }finally{ XifsdReleaseFcb(pIrpContext, pFCB); if(ParentFCBAcquired) { XifsdReleaseFcb(TRUE,pParentFCB); } if (SendUnlockNotification) { FsRtlNotifyVolumeEvent( pFileObject, FSRTL_VOLUME_UNLOCK ); } if (VCBAcquired) { XifsdReleaseVcb( pIrpContext, pVCB); } } if (AttemptTeardown) { XifsdAcquireVcbExclusive( CanWait, pVCB, FALSE ); try { XixFsdPurgeVolume( pIrpContext, pVCB, FALSE ); } finally { XifsdReleaseVcb( pIrpContext, pVCB ); } } // // If this is a normal termination then complete the request // DebugTrace((DEBUG_LEVEL_TRACE), (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT), ("Exit XifsdCommonCleanUp pIrpContext(%p)\n", pIrpContext)); XixFsdCompleteRequest( pIrpContext, STATUS_SUCCESS, 0 ); return STATUS_SUCCESS; }
NTSTATUS UdfCompletePcb ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PPCB Pcb ) /*++ Routine Description: This routine completes initialization of a Pcb which has been filled in with partition descriptors. Initialization-time data such as the physical partition descriptors will be returned to the system. Arguments: Vcb - Vcb of the volume the Pcb describes Pcb - Pcb being completed Return Value: NTSTATUS according to whether intialization completion was succesful --*/ { ULONG Reference; NTSTATUS Status; PAGED_CODE(); // // Check inputs // ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_VCB( Vcb ); ASSERT_PCB( Pcb ); DebugTrace(( +1, Dbg, "UdfCompletePcb, Vcb %08x Pcb %08x\n", Vcb, Pcb )); // // Complete intialization all physical partitions // for (Reference = 0; Reference < Pcb->Partitions; Reference++) { DebugTrace(( 0, Dbg, "UdfCompletePcb, Examining Ref %u (type %u)!\n", Reference, Pcb->Partition[Reference].Type)); switch (Pcb->Partition[Reference].Type) { case Physical: if (Pcb->Partition[Reference].Physical.PartitionDescriptor == NULL) { DebugTrace(( 0, Dbg, "UdfCompletePcb, ... but didn't find Partition# %u!\n", Pcb->Partition[Reference].Physical.PartitionNumber )); DebugTrace(( -1, Dbg, "UdfCompletePcb -> STATUS_DISK_CORRUPT_ERROR\n" )); return STATUS_DISK_CORRUPT_ERROR; } Pcb->Partition[Reference].Physical.Start = Pcb->Partition[Reference].Physical.PartitionDescriptor->Start; Pcb->Partition[Reference].Physical.Length = Pcb->Partition[Reference].Physical.PartitionDescriptor->Length; // // Retrieve the sparing information at this point if appropriate. // We have to do this when we can map logical -> physical blocks. // if (Pcb->Partition[Reference].Physical.SparingMap) { Status = UdfLoadSparingTables( IrpContext, Vcb, Pcb, Reference ); if (!NT_SUCCESS( Status )) { DebugTrace(( -1, Dbg, "UdfCompletePcb -> %08x\n", Status )); return Status; } } // // We will not need the descriptor or sparing map anymore, so drop them. // UdfFreePool( &Pcb->Partition[Reference].Physical.PartitionDescriptor ); UdfFreePool( &Pcb->Partition[Reference].Physical.SparingMap ); break; case Virtual: break; default: ASSERT(FALSE); break; } } DebugTrace(( -1, Dbg, "UdfCompletePcb -> STATUS_SUCCESS\n" )); return STATUS_SUCCESS; }
NTSTATUS XixFsReadFileInfoFromFcb( IN PXIFS_FCB pFCB, IN BOOLEAN Waitable, IN uint8 * Buffer, IN uint32 BufferSize ) { NTSTATUS RC = STATUS_SUCCESS; uint64 FileId = 0; PXIFS_VCB pVCB = NULL; PXIDISK_FILE_HEADER_LOT pFileHeader = NULL; uint32 LotType = LOT_INFO_TYPE_INVALID; uint32 Reason = 0; PAGED_CODE(); ASSERT_FCB(pFCB); pVCB = pFCB->PtrVCB; ASSERT_VCB(pVCB); ASSERT(Waitable == TRUE); ASSERT(BufferSize >= XIDISK_FILE_HEADER_LOT_SIZE); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Enter XixFsReadFileInfoFromFcb\n")); try{ RC = XixFsRawReadLotAndFileHeader( pVCB->TargetDeviceObject, pVCB->LotSize, pFCB->LotNumber, Buffer, XIDISK_FILE_HEADER_LOT_SIZE, pVCB->SectorSize ); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ALL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Fail Read File Data(%I64d).\n", pFCB->LotNumber)); try_return (RC); } pFileHeader = (PXIDISK_FILE_HEADER_LOT)Buffer; // Check Header if(pFCB->FCBType == FCB_TYPE_DIR){ LotType = LOT_INFO_TYPE_DIRECTORY; }else{ LotType = LOT_INFO_TYPE_FILE; } RC = XixFsCheckLotInfo( &pFileHeader->LotHeader.LotInfo, pVCB->VolumeLotSignature, pFCB->LotNumber, LotType, LOT_FLAG_BEGIN, &Reason ); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("XixFsReadFileInfoFromFcb : XixFsCheckLotInfo (%I64d).\n", pFCB->LotNumber)); RC = STATUS_FILE_CORRUPT_ERROR; try_return(RC); } }finally{ } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Exit XixFsReadFileInfoFromFcb Status(0x%x)\n", RC)); return RC; }
NTSTATUS XixFsReadFileInfoFromContext( BOOLEAN Waitable, PXIFS_FILE_EMUL_CONTEXT FileContext ) { NTSTATUS RC = STATUS_SUCCESS; PXIDISK_FILE_HEADER_LOT pFileHeader = NULL; PXIFS_VCB pVCB = NULL; LARGE_INTEGER Offset; uint32 BlockSize; uint32 LotType = LOT_INFO_TYPE_INVALID; uint32 Reason = 0; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Enter XixFsReadFileInfoFromContext.\n")); ASSERT(Waitable == TRUE); ASSERT(FileContext); pVCB = FileContext->pVCB; ASSERT_VCB(pVCB); DebugTrace( DEBUG_LEVEL_INFO, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("FileContext Searched LotNumber(%I64d) FileType(%ld)\n", FileContext->LotNumber, FileContext->FileType )); FileContext->pSearchedFCB = NULL; try{ if(FileContext->Buffer == NULL){ FileContext->Buffer = ExAllocatePoolWithTag(NonPagedPool,XIDISK_FILE_HEADER_LOT_SIZE, TAG_BUFFER); } }finally{ if(AbnormalTermination()){ RC = STATUS_INSUFFICIENT_RESOURCES; } } if(!NT_SUCCESS(RC)){ return RC; } try{ RC = XixFsRawReadLotAndFileHeader( pVCB->TargetDeviceObject, pVCB->LotSize, FileContext->LotNumber, FileContext->Buffer, XIDISK_FILE_HEADER_LOT_SIZE, pVCB->SectorSize ); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_ALL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Fail Read File Data(%I64d).\n", FileContext->LotNumber)); try_return (RC); } pFileHeader = (PXIDISK_FILE_HEADER_LOT)FileContext->Buffer; // Check Header if(FileContext->FileType == FCB_TYPE_DIR){ LotType = LOT_INFO_TYPE_DIRECTORY; }else{ LotType = LOT_INFO_TYPE_FILE; } RC = XixFsCheckLotInfo( &pFileHeader->LotHeader.LotInfo, pVCB->VolumeLotSignature, FileContext->LotNumber, LotType, LOT_FLAG_BEGIN, &Reason ); if(!NT_SUCCESS(RC)){ RC = STATUS_FILE_CORRUPT_ERROR; try_return(RC); } }finally{ } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Exit XixFsReadFileInfoFromContext Status (0x%x).\n", RC)); return RC; }
VOID xixfs_CleanupFlushVCB( IN PXIXFS_IRPCONTEXT pIrpContext, IN PXIXFS_VCB pVCB, IN BOOLEAN DisMountVCB ) { //PAGED_CODE(); ASSERT_IRPCONTEXT( pIrpContext ); ASSERT_VCB( pVCB ); ASSERT_EXCLUSIVE_XIFS_GDATA; ASSERT_EXCLUSIVE_VCB(pVCB); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("xixfs_CleanupFlushVCB Status(%ld).\n", pVCB->VCBState)); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("11 Current VCB->PtrVPB->ReferenceCount %d \n", pVCB->PtrVPB->ReferenceCount)); XifsdLockVcb( pIrpContext, pVCB ); XIXCORE_SET_FLAGS(pVCB->VCBFlags, XIFSD_VCB_FLAGS_DEFERED_CLOSE); if(DisMountVCB){ if(pVCB->VolumeDasdFCB != NULL){ pVCB->VolumeDasdFCB->FCBReference -= 1; pVCB->VolumeDasdFCB->FCBUserReference -= 1; } if(pVCB->MetaFCB != NULL){ pVCB->MetaFCB->FCBReference -=1; pVCB->MetaFCB->FCBUserReference -= 1; } if(pVCB->RootDirFCB != NULL){ pVCB->RootDirFCB->FCBReference -=1; pVCB->RootDirFCB->FCBUserReference -= 1; } } XifsdUnlockVcb(pIrpContext, pVCB); xixfs_PurgeVolume(pIrpContext, pVCB, DisMountVCB); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("22 Current VCB->PtrVPB->ReferenceCount %d \n", pVCB->PtrVPB->ReferenceCount)); if(DisMountVCB){ // Added by ILGU HONG XifsdReleaseVcb(TRUE, pVCB); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_FSCTL|DEBUG_TARGET_VOLINFO ), ("VCB %d/%d \n", pVCB->VCBReference, pVCB->VCBUserReference)); CcWaitForCurrentLazyWriterActivity(); XifsdAcquireVcbExclusive(TRUE, pVCB, FALSE); xixfs_RealCloseFCB((PVOID)pVCB); } XifsdLockVcb( pIrpContext, pVCB ); XIXCORE_CLEAR_FLAGS(pVCB->VCBFlags, XIFSD_VCB_FLAGS_DEFERED_CLOSE); XifsdUnlockVcb(pIrpContext, pVCB); // Added by ILGU HONG END if(DisMountVCB){ // changed by ILGU HONG for readonly 09052006 if(!pVCB->XixcoreVcb.IsVolumeWriteProtected){ LARGE_INTEGER TimeOut; // // Stop Meta Update process // KeSetEvent(&pVCB->VCBUmountEvent, 0, FALSE); TimeOut.QuadPart = - DEFAULT_XIFS_UMOUNTWAIT; KeWaitForSingleObject(&pVCB->VCBStopOkEvent, Executive, KernelMode, FALSE, &TimeOut); xixcore_DeregisterHost(&pVCB->XixcoreVcb); // Added by ILGU HONG for 08312006 if(pVCB->NdasVolBacl_Id){ xixfs_RemoveUserBacl(pVCB->TargetDeviceObject, pVCB->NdasVolBacl_Id); } // Added by ILGU HONG End } // changed by ILGU HONG for readonly end } return; }
VOID NtfsReleaseVcbCheckDelete ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN UCHAR MajorCode, IN PFILE_OBJECT FileObject OPTIONAL ) /*++ Routine Description: This routine will release the Vcb. We will also test here whether we should teardown the Vcb at this point. If this is the last open queued to a dismounted volume or the last close from a failed mount or the failed mount then we will want to test the Vcb for a teardown. Arguments: Vcb - Supplies the Vcb to acquire MajorCode - Indicates what type of operation we were called from. FileObject - Optionally supplies the file object whose VPB pointer we need to zero out Return Value: None. --*/ { ASSERT_IRP_CONTEXT(IrpContext); ASSERT_VCB(Vcb); if (FlagOn( Vcb->VcbState, VCB_STATE_PERFORMED_DISMOUNT ) && (Vcb->CloseCount == 0)) { ULONG ReferenceCount; ULONG ResidualCount; KIRQL SavedIrql; BOOLEAN DeleteVcb = FALSE; ASSERT_EXCLUSIVE_RESOURCE( &Vcb->Resource ); // // The volume has gone through dismount. Now we need to decide if this // release of the Vcb is the last reference for this volume. If so we // can tear the volume down. // // We compare the reference count in the Vpb with the state of the volume // and the type of operation. We also need to check if there is a // referenced log file object. // IoAcquireVpbSpinLock( &SavedIrql ); ReferenceCount = Vcb->Vpb->ReferenceCount; IoReleaseVpbSpinLock( SavedIrql ); ResidualCount = 0; if (Vcb->LogFileObject != NULL) { ResidualCount = 1; } if (MajorCode == IRP_MJ_CREATE) { ResidualCount += 1; } // // If the residual count is the same as the count in the Vpb then we // can delete the Vpb. // if (ResidualCount == ReferenceCount) { SetFlag( Vcb->VcbState, VCB_STATE_DELETE_UNDERWAY ); ExReleaseResource( &Vcb->Resource ); // // Never delete the Vcb unless this is the last release of // this Vcb. // if (!ExIsResourceAcquiredExclusive( &Vcb->Resource ) && (ExIsResourceAcquiredShared( &Vcb->Resource ) == 0)) { if (ARGUMENT_PRESENT(FileObject)) { FileObject->Vpb = NULL; } // // If this is a create then the IO system will handle the // Vpb. // if (MajorCode == IRP_MJ_CREATE) { ClearFlag( Vcb->VcbState, VCB_STATE_TEMP_VPB ); } // // Use the global resource to synchronize the DeleteVcb process. // (VOID) ExAcquireResourceExclusive( &NtfsData.Resource, TRUE ); RemoveEntryList( &Vcb->VcbLinks ); ExReleaseResource( &NtfsData.Resource ); NtfsDeleteVcb( IrpContext, &Vcb ); } else { ClearFlag( Vcb->VcbState, VCB_STATE_DELETE_UNDERWAY ); } } else { ExReleaseResource( &Vcb->Resource ); } } else { ExReleaseResource( &Vcb->Resource ); } }
ULONG UdfLookupMetaVsnOfExtent ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN USHORT Reference, IN ULONG Lbn, IN ULONG Len, IN BOOLEAN ExactEnd ) /*++ Routine Description: This routine maps the input logical block extent on a given partition to a starting virtual block in the metadata stream. If a mapping does not exist, one will be created and the metadata stream extended. Arguments: Vcb - Vcb of logical volume Reference - Partition reference to use in the mapping Lbn - Logical block number Len - Length of extent in bytes ExactEnd - Indicates the extension policy if these blocks are not mapped. Return Value: ULONG virtual sector number Raised status if the Lbn extent is split across multiple Vbn extents. --*/ { ULONG Vsn; ULONG Psn; ULONG SectorCount; BOOLEAN Result; BOOLEAN UnwindExtension = FALSE; LONGLONG UnwindAllocationSize; PFCB Fcb = NULL; // // Check inputs // ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_VCB( Vcb ); // // The extent must be an integral number of logical blocks in length. // if (Len == 0 || BlockOffset( Vcb, Len )) { UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR ); } // // Get the physical mapping of the extent. The Mcb package operates on ULONG/ULONG // keys and values so we must render our 48bit address into 32. We can do this since // this is a single surface implementation, and it is guaranteed that a surface cannot // contain more than MAXULONG physical sectors. // Psn = UdfLookupPsnOfExtent( IrpContext, Vcb, Reference, Lbn, Len ); // // Use try-finally for cleanup // try { // // We must safely establish a mapping and extend the metadata stream so that cached // reads can occur on this new extent. // Fcb = Vcb->MetadataFcb; UdfLockFcb( IrpContext, Fcb ); Result = UdfVmcbLbnToVbn( &Vcb->Vmcb, Psn, &Vsn, &SectorCount ); if (Result) { // // If the mapping covers the extent, we can give this back. // if (BlocksFromSectors( Vcb, SectorCount ) >= BlocksFromBytes( Vcb, Len )) { try_leave( NOTHING ); } // // It is a fatal error if the extent we are mapping is not wholly contained // by an extent of Vsns in the Vmcb. This will indicate that some structure // is trying to overlap another. // UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR ); } // // Add the new mapping. We know that it is being added to the end of the stream. // UdfAddVmcbMapping( &Vcb->Vmcb, Psn, SectorsFromBytes( Vcb, Len ), ExactEnd, &Vsn, &SectorCount ); UnwindAllocationSize = Fcb->AllocationSize.QuadPart; UnwindExtension = TRUE; Fcb->AllocationSize.QuadPart = Fcb->FileSize.QuadPart = Fcb->ValidDataLength.QuadPart = LlBytesFromSectors( Vcb, Vsn + SectorCount); CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize ); UnwindExtension = FALSE; // // We do not need to purge the cache maps since the Vmcb will always be // page aligned, and thus any reads will have filled it with valid data. // } finally { if (UnwindExtension) { ULONG FirstZappedVsn; // // Strip off the additional mappings we made. // Fcb->AllocationSize.QuadPart = Fcb->FileSize.QuadPart = Fcb->ValidDataLength.QuadPart = UnwindAllocationSize; FirstZappedVsn = SectorsFromBytes( Vcb, UnwindAllocationSize ); UdfRemoveVmcbMapping( &Vcb->Vmcb, FirstZappedVsn, Vsn + SectorCount - FirstZappedVsn ); CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize ); } if (Fcb) { UdfUnlockFcb( IrpContext, Fcb ); } } return Vsn; }
NTSTATUS XixFsInitializeFCBInfo( IN PXIFS_FCB pFCB, IN BOOLEAN Waitable ) { NTSTATUS RC = STATUS_UNSUCCESSFUL; PXIFS_VCB pVCB = NULL; PXIDISK_FILE_HEADER pFileHeader = NULL; PXIDISK_DIR_HEADER pDirHeader = NULL; LARGE_INTEGER Offset; uint32 LotCount; uint32 BufferSize = 0; uint8 *Buffer = NULL; uint64 FileId = 0; uint32 LotType = LOT_INFO_TYPE_INVALID; uint8 *NameBuffer = NULL; uint8 *ChildBuffer = NULL; uint32 Reason; uint32 AddLotSize = 0; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Enter XixFsInitializeFCBInfo\n")); ASSERT_FCB(pFCB); pVCB = pFCB->PtrVCB; ASSERT_VCB(pVCB); ASSERT(Waitable == TRUE); FileId = pFCB->LotNumber; BufferSize = XIDISK_FILE_HEADER_LOT_SIZE; Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, TAG_BUFFER ); if(!Buffer){ return STATUS_INSUFFICIENT_RESOURCES; } try{ RC = XixFsReadFileInfoFromFcb( pFCB, Waitable, Buffer, BufferSize ); if(!NT_SUCCESS(RC)){ try_return(RC); } pFileHeader = (PXIDISK_FILE_HEADER)Buffer; if(pFCB->FCBType == FCB_TYPE_DIR){ pDirHeader = (PXIDISK_DIR_HEADER)Buffer; pFCB->LastAccessTime = pDirHeader->DirInfo.Access_time; pFCB->LastWriteTime = pDirHeader->DirInfo.Modified_time; pFCB->CreationTime = pDirHeader->DirInfo.Create_time; if(pDirHeader->DirInfo.NameSize != 0){ uint16 Size = (uint16)pDirHeader->DirInfo.NameSize; if(Size > XIFS_MAX_NAME_LEN){ Size = XIFS_MAX_NAME_LEN; } if(pFCB->FCBName.Buffer){ ExFreePool(pFCB->FCBName.Buffer); pFCB->FCBName.Buffer = NULL; } pFCB->FCBName.MaximumLength = SECTORALIGNSIZE_512(Size); pFCB->FCBName.Length = Size; NameBuffer =ExAllocatePoolWithTag(PagedPool, SECTORALIGNSIZE_512(Size),TAG_FILE_NAME); pFCB->FCBName.Buffer = (PWSTR)NameBuffer; if(!pFCB->FCBName.Buffer){ RC = STATUS_INSUFFICIENT_RESOURCES; try_return(RC); } RtlCopyMemory( pFCB->FCBName.Buffer, pDirHeader->DirInfo.Name, pFCB->FCBName.Length); } pFCB->RealFileSize = pDirHeader->DirInfo.FileSize; pFCB->RealAllocationSize = pDirHeader->DirInfo.AllocationSize; pFCB->ValidDataLength.QuadPart = pFCB->FileSize.QuadPart = pDirHeader->DirInfo.FileSize; pFCB->AllocationSize.QuadPart = pDirHeader->DirInfo.AllocationSize; pFCB->FileAttribute = pDirHeader->DirInfo.FileAttribute; pFCB->LinkCount = pDirHeader->DirInfo.LinkCount; pFCB->Type = pDirHeader->DirInfo.Type; if(pVCB->RootDirectoryLotIndex == FileId) { XifsdSetFlag(pFCB->Type, (XIFS_FD_TYPE_ROOT_DIRECTORY|XIFS_FD_TYPE_DIRECTORY)); } pFCB->LotNumber = pDirHeader->DirInfo.LotIndex; pFCB->FileId = (FCB_TYPE_DIR_INDICATOR|(FCB_ADDRESS_MASK & pFCB->LotNumber)); pFCB->ParentLotNumber = pDirHeader->DirInfo.ParentDirLotIndex; pFCB->AddrLotNumber = pDirHeader->DirInfo.AddressMapIndex; pFCB->ChildCount= pDirHeader->DirInfo.childCount; pFCB->ChildCount = (uint32)XixFsfindSetBitMapCount(1024, pDirHeader->DirInfo.ChildMap); pFCB->AddrStartSecIndex = 0; }else{ pFCB->LastAccessTime = pFileHeader->FileInfo.Access_time; pFCB->LastWriteTime = pFileHeader->FileInfo.Modified_time; pFCB->CreationTime = pFileHeader->FileInfo.Create_time; if(pFileHeader->FileInfo.NameSize != 0){ uint16 Size = (uint16)pFileHeader->FileInfo.NameSize; if(Size > XIFS_MAX_NAME_LEN){ Size = XIFS_MAX_NAME_LEN; } if(pFCB->FCBName.Buffer){ ExFreePool(pFCB->FCBName.Buffer); pFCB->FCBName.Buffer = NULL; } pFCB->FCBName.MaximumLength = SECTORALIGNSIZE_512(Size); pFCB->FCBName.Length = Size; NameBuffer = ExAllocatePool(NonPagedPool, SECTORALIGNSIZE_512(Size)); pFCB->FCBName.Buffer = (PWSTR)NameBuffer; if(!pFCB->FCBName.Buffer){ RC = STATUS_INSUFFICIENT_RESOURCES; try_return(RC); } RtlCopyMemory( pFCB->FCBName.Buffer, pFileHeader->FileInfo.Name, pFCB->FCBName.Length); } pFCB->RealFileSize = pFileHeader->FileInfo.FileSize; pFCB->RealAllocationSize = pFileHeader->FileInfo.AllocationSize; pFCB->ValidDataLength.QuadPart = pFCB->FileSize.QuadPart = pFileHeader->FileInfo.FileSize; pFCB->AllocationSize.QuadPart = pFileHeader->FileInfo.AllocationSize; pFCB->FileAttribute = pFileHeader->FileInfo.FileAttribute; pFCB->LinkCount = pFileHeader->FileInfo.LinkCount; pFCB->Type = pFileHeader->FileInfo.Type; pFCB->LotNumber = pFileHeader->FileInfo.LotIndex; pFCB->FileId = (FCB_TYPE_FILE_INDICATOR|(FCB_ADDRESS_MASK & pFCB->LotNumber)); pFCB->ParentLotNumber = pFileHeader->FileInfo.ParentDirLotIndex; pFCB->AddrLotNumber = pFileHeader->FileInfo.AddressMapIndex; pFCB->AddrStartSecIndex = 0; AddLotSize = pVCB->SectorSize; pFCB->AddrLot = ExAllocatePoolWithTag(NonPagedPool, AddLotSize, TAG_BUFFER); if(!pFCB->AddrLot){ RC = STATUS_INSUFFICIENT_RESOURCES; try_return(RC); } pFCB->AddrLotSize = AddLotSize; RC = XixFsRawReadAddressOfFile( pVCB->TargetDeviceObject, pVCB->LotSize, pFCB->LotNumber, pFCB->AddrLotNumber, (uint8 *)pFCB->AddrLot, pFCB->AddrLotSize, &(pFCB->AddrStartSecIndex), 0, pVCB->SectorSize); if(!NT_SUCCESS(RC)){ try_return(RC); } } if(pFCB->LastAccessTime == 0){ pFCB->LastAccessTime = XixGetSystemTime().QuadPart; DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Initialize pFCB->LastAccessTime(%I64d).\n", pFCB->LastAccessTime)); } if(pFCB->LastWriteTime == 0) { pFCB->LastWriteTime = XixGetSystemTime().QuadPart; DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Initialize pFCB->LastWriteTime(%I64d).\n",pFCB->LastWriteTime)); } if(pFCB->CreationTime == 0) { pFCB->CreationTime = XixGetSystemTime().QuadPart; DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Initialize pFCB->CreationTime(%I64d).\n", pFCB->CreationTime)); } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Add to FCB File LotNumber(%I64d).\n", FileId)); }finally{ if(Buffer) { ExFreePool(Buffer); } } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), ("Exit XixFsInitializeFCBInfo\n")); return RC; }
NTSTATUS UdfLoadSparingTables( PIRP_CONTEXT IrpContext, PVCB Vcb, PPCB Pcb, ULONG Reference ) /*++ Routine Description: This routine reads the sparing tables for a partition and fills in the sparing Mcb. Arguments: Vcb - the volume hosting the spared partition Pcb - the partion block corresponding to the volume Reference - the partition reference being pulled in Return Value: NTSTATUS according to whether the sparing tables were loaded --*/ { NTSTATUS Status; ULONG SparingTable; PULONG SectorBuffer; ULONG Psn; ULONG RemainingBytes; ULONG ByteOffset; ULONG TotalBytes; BOOLEAN Complete; PSPARING_TABLE_HEADER Header; PSPARING_TABLE_ENTRY Entry; PPARTITION Partition = &Pcb->Partition[Reference]; PPARTMAP_SPARABLE Map = Partition->Physical.SparingMap; ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_VCB( Vcb ); ASSERT( Map != NULL ); DebugTrace(( +1, Dbg, "UdfLoadSparingTables, Vcb %08x, PcbPartition %08x, Map @ %08x\n", Vcb, Partition, Map )); DebugTrace(( 0, Dbg, "UdfLoadSparingTables, Map sez: PacketLen %u, NTables %u, TableSize %u\n", Map->PacketLength, Map->NumSparingTables, Map->TableSize)); // // Check that the sparale map appears sane. If there are no sparing tables that // is pretty OK, and it'll wind up looking like a regular physical partition. // if (Map->NumSparingTables == 0) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, no sparing tables claimed!\n" )); DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_SUCCESS\n" )); return STATUS_SUCCESS; } if (Map->NumSparingTables > sizeof(Map->TableLocation)/sizeof(ULONG)) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, too many claimed tables to fit! (max %u)\n", sizeof(Map->TableLocation)/sizeof(ULONG))); DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); return STATUS_DISK_CORRUPT_ERROR; } if (Map->PacketLength != UDF_SPARING_PACKET_LENGTH) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, packet size is %u (not %u!\n", Map->PacketLength, UDF_SPARING_PACKET_LENGTH )); DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); return STATUS_DISK_CORRUPT_ERROR; } if (Map->TableSize < sizeof(SPARING_TABLE_HEADER) || (Map->TableSize - sizeof(SPARING_TABLE_HEADER)) % sizeof(SPARING_TABLE_ENTRY) != 0) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table size is too small or unaligned!\n" )); DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); return STATUS_DISK_CORRUPT_ERROR; } #ifdef UDF_SANITY DebugTrace(( 0, Dbg, "UdfLoadSparingTables" )); for (SparingTable = 0; SparingTable < Map->NumSparingTables; SparingTable++) { DebugTrace(( 0, Dbg, ", Table %u @ %x", SparingTable, Map->TableLocation[SparingTable] )); } DebugTrace(( 0, Dbg, "\n" )); #endif // // If a sparing mcb doesn't exist, manufacture one. // if (Pcb->SparingMcb == NULL) { Pcb->SparingMcb = FsRtlAllocatePoolWithTag( PagedPool, sizeof(LARGE_MCB), TAG_SPARING_MCB ); FsRtlInitializeLargeMcb( Pcb->SparingMcb, PagedPool ); } SectorBuffer = FsRtlAllocatePoolWithTag( PagedPool, PAGE_SIZE, TAG_NSR_FSD ); // // Now loop across the sparing tables and pull the data in. // try { for (Complete = FALSE, SparingTable = 0; SparingTable < Map->NumSparingTables; SparingTable++) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, loading sparing table %u!\n", SparingTable )); ByteOffset = 0; TotalBytes = 0; RemainingBytes = 0; do { if (RemainingBytes == 0) { (VOID) UdfReadSectors( IrpContext, BytesFromSectors( Vcb, Map->TableLocation[SparingTable] ) + ByteOffset, SectorSize( Vcb ), FALSE, SectorBuffer, Vcb->TargetDeviceObject ); // // Verify the descriptor at the head of the sparing table. If it is not // valid, we just break out for a chance at the next table, if any. // if (ByteOffset == 0) { Header = (PSPARING_TABLE_HEADER) SectorBuffer; if (!UdfVerifyDescriptor( IrpContext, &Header->Destag, 0, SectorSize( Vcb ), Header->Destag.Lbn, TRUE )) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table %u didn't verify destag!\n", SparingTable )); break; } if (!UdfUdfIdentifierContained( &Header->RegID, &UdfSparingTableIdentifier, UDF_VERSION_150, UDF_VERSION_RECOGNIZED, OSCLASS_INVALID, OSIDENTIFIER_INVALID)) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table %u didn't verify regid!\n", SparingTable )); break; } // // Calculate the total number bytes this map spans and check it against what // we were told the sparing table sizes are. // DebugTrace(( 0, Dbg, "UdfLoadSparingTables, Sparing table %u has %u entries\n", SparingTable, Header->TableEntries )); TotalBytes = sizeof(SPARING_TABLE_HEADER) + Header->TableEntries * sizeof(SPARING_TABLE_ENTRY); if (Map->TableSize < TotalBytes) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table #ents %u overflows allocation!\n", Header->TableEntries )); break; } // // So far so good, advance past the header. // ByteOffset = sizeof(SPARING_TABLE_HEADER); Entry = Add2Ptr( SectorBuffer, sizeof(SPARING_TABLE_HEADER), PSPARING_TABLE_ENTRY ); } else { // // Pick up in the new sector. // Entry = (PSPARING_TABLE_ENTRY) SectorBuffer; } RemainingBytes = Min( SectorSize( Vcb ), TotalBytes - ByteOffset ); } // // Add the mapping. Since sparing tables are an Lbn->Psn mapping, // very odd, and I want to simplify things by putting the sparing // in right at IO dispatch, translate this to a Psn->Psn mapping. // if (Entry->Original != UDF_SPARING_AVALIABLE && Entry->Original != UDF_SPARING_DEFECTIVE) { Psn = Partition->Physical.Start + SectorsFromBlocks( Vcb, Entry->Original ); DebugTrace(( 0, Dbg, "UdfLoadSparingTables, mapping from Psn %x (Lbn %x) -> Psn %x\n", Psn, Entry->Original, Entry->Mapped )); FsRtlAddLargeMcbEntry( Pcb->SparingMcb, Psn, Entry->Mapped, UDF_SPARING_PACKET_LENGTH ); } // // Advance to the next, and drop out if we've hit the end. // ByteOffset += sizeof(SPARING_TABLE_ENTRY); RemainingBytes -= sizeof(SPARING_TABLE_ENTRY); Entry++; } while ( ByteOffset < TotalBytes ); } } finally { DebugUnwind( UdfLoadSparingTables ); UdfFreePool( &SectorBuffer ); } DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_SUCCESS\n" )); return STATUS_SUCCESS; }
NTSTATUS XixFsdCommonLockControl( IN PXIFS_IRPCONTEXT pIrpContext ) { NTSTATUS RC = STATUS_SUCCESS; PIRP pIrp = NULL; PIO_STACK_LOCATION pIrpSp = NULL; PFILE_OBJECT pFileObject = NULL; PXIFS_FCB pFCB = NULL; PXIFS_CCB pCCB = NULL; PXIFS_VCB pVCB = NULL; TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, ("!!!!Enter XixFsdCommonLockControl \n")); DebugTrace(DEBUG_LEVEL_TRACE,(DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB), ("Enter XixFsdCommonLockControl\n")); ASSERT(pIrpContext); pIrp = pIrpContext->Irp; ASSERT(pIrp); pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp); pFileObject = pIrpSp->FileObject; ASSERT(pFileObject); TypeOfOpen = XixFsdDecodeFileObject(pFileObject, &pFCB, &pCCB); ASSERT_FCB(pFCB); if(TypeOfOpen != UserFileOpen){ RC = STATUS_INVALID_PARAMETER; XixFsdCompleteRequest(pIrpContext, RC, 0); return RC; } if(pFCB->FCBType != FCB_TYPE_FILE) { RC = STATUS_INVALID_PARAMETER; XixFsdCompleteRequest(pIrpContext, RC, 0); return RC; } if(pFCB->HasLock != FCB_FILE_LOCK_HAS){ RC = STATUS_ACCESS_DENIED; XixFsdCompleteRequest(pIrpContext, RC, 0); return RC; } pVCB = pFCB->PtrVCB; ASSERT_VCB(pVCB); DebugTrace(DEBUG_LEVEL_TRACE|DEBUG_LEVEL_ALL,(DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB), ("CALL FsRtlCheckOplock : XixFsdCommonLockControl\n")); RC = FsRtlCheckOplock(&pFCB->FCBOplock, pIrp, pIrpContext, XixFsdOplockComplete, NULL); if(!NT_SUCCESS(RC)){ DebugTrace(DEBUG_LEVEL_TRACE|DEBUG_LEVEL_ALL,(DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB), ("return PENDING FsRtlCheckOplock : XixFsdCommonLockControl\n")); return RC; } if(!XixFsdVerifyFcbOperation(pIrpContext, pFCB)){ RC = STATUS_INVALID_PARAMETER; XixFsdCompleteRequest(pIrpContext, RC, 0); return RC; } try{ if(pFCB->FCBFileLock == NULL){ pFCB->FCBFileLock = FsRtlAllocateFileLock(NULL, NULL); if(!pFCB->FCBFileLock){ RC = STATUS_INSUFFICIENT_RESOURCES; try_return(RC); } } RC = FsRtlProcessFileLock(pFCB->FCBFileLock, pIrp, NULL); XifsdLockFcb(pIrpContext, pFCB); pFCB->IsFastIoPossible = XixFsdCheckFastIoPossible(pFCB); XifsdUnlockFcb(pIrpContext, pFCB); }finally{ } XixFsdCompleteRequest(pIrpContext, RC, 0); DebugTrace(DEBUG_LEVEL_TRACE|DEBUG_LEVEL_ALL,(DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB), ("Exit XixFsdCommonLockControl\n")); return RC; }
NTSTATUS xixfs_CommonQueryVolumeInformation( IN PXIXFS_IRPCONTEXT pIrpContext ) { NTSTATUS RC = STATUS_SUCCESS; PIRP pIrp = NULL; PIO_STACK_LOCATION pIrpSp = NULL; PXIXFS_VCB pVCB = NULL; PXIXFS_FCB pFCB = NULL; PXIXFS_CCB pCCB = NULL; PFILE_OBJECT pFileObject = NULL; BOOLEAN Wait = FALSE; uint32 BytesToReturn = 0; uint32 Length = 0; TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_VOLINFO|DEBUG_TARGET_IRPCONTEXT), ("Enter xixfs_CommonQueryVolumeInformation \n")); ASSERT(pIrpContext); pIrp = pIrpContext->Irp; ASSERT(pIrp); pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrp); pFileObject = pIrpSp->FileObject; ASSERT(pFileObject); TypeOfOpen = xixfs_DecodeFileObject( pFileObject, &pFCB, &pCCB ); if (TypeOfOpen == UnopenedFileObject) { RC = STATUS_INVALID_PARAMETER; xixfs_CompleteRequest( pIrpContext, STATUS_INVALID_PARAMETER, 0 ); return RC; } DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, ("!!!!VolumeInformation pCCB(%p)\n", pCCB)); pVCB = pFCB->PtrVCB; ASSERT_VCB(pVCB); Wait = XIXCORE_TEST_FLAGS(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT); if(!ExAcquireResourceSharedLite(&(pVCB->VCBResource), Wait)){ DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_VOLINFO|DEBUG_TARGET_IRPCONTEXT), ("PostRequest IrpContext(%p) Irp(%p)\n", pIrpContext, pIrp)); RC = xixfs_PostRequest(pIrpContext, pIrp); return RC; } try{ Length = pIrpSp->Parameters.QueryVolume.Length ; DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_VOLINFO|DEBUG_TARGET_IRPCONTEXT), ("pIrpSp->Parameters.QueryVolume.FsInformationClass (0x%x)\n", pIrpSp->Parameters.QueryVolume.FsInformationClass)); switch (pIrpSp->Parameters.QueryVolume.FsInformationClass) { case FileFsSizeInformation: { RC = xixfs_QueryFsSizeInfo( pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn ); xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn); break; } case FileFsVolumeInformation: { RC = xixfs_QueryFsVolumeInfo( pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn ); xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn); break; } case FileFsDeviceInformation: { RC = xixfs_QueryFsDeviceInfo( pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn ); xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn); break; } case FileFsAttributeInformation: { RC = xixfs_QueryFsAttributeInfo( pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn ); xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn); break; } case FileFsFullSizeInformation: { RC = xixfs_QueryFsFullSizeInfo(pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn); xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn); break; } default: DebugTrace( DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("default Not supported Volume Info %ld\n",pIrpSp->Parameters.QueryVolume.FsInformationClass)); RC = STATUS_INVALID_PARAMETER; xixfs_CompleteRequest(pIrpContext, RC, 0); break; } }finally{ ExReleaseResourceLite(&(pVCB->VCBResource)); } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_VOLINFO|DEBUG_TARGET_IRPCONTEXT), ("Exit xixfs_CommonQueryVolumeInformation \n")); return RC; }
NTSTATUS XixFsdCommonPNP( IN PXIFS_IRPCONTEXT pIrpContext ) { NTSTATUS RC = STATUS_SUCCESS; PIRP pIrp = NULL; PIO_STACK_LOCATION pIrpSp = NULL; PXI_VOLUME_DEVICE_OBJECT pVolumeDeviceObject = NULL; PXIFS_VCB pVCB = NULL; uint32 PrevLevel = 0; uint32 PrevTarget = 0; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("Enter XixFsdCommonPNP \n")); ASSERT(pIrpContext); pIrp = pIrpContext->Irp; ASSERT(pIrp); pIrpSp = IoGetCurrentIrpStackLocation(pIrp); pVolumeDeviceObject = (PXI_VOLUME_DEVICE_OBJECT)pIrpSp->DeviceObject; if(pVolumeDeviceObject->DeviceObject.Size != sizeof(XI_VOLUME_DEVICE_OBJECT) || (pVolumeDeviceObject->VCB.NodeTypeCode != XIFS_NODE_VCB)) { DebugTrace( DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("XixFsdCommonPNP Invalid Parameter\n")); RC = STATUS_INVALID_PARAMETER; XixFsdCompleteRequest(pIrpContext, RC, 0); return RC; } if(!XifsdCheckFlagBoolean(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT)){ RC = STATUS_PENDING; DebugTrace(DEBUG_LEVEL_ERROR, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("XifsdPostRequest IrpContext(%p) Irp(%p)\n", pIrpContext, pIrp )); XixFsdPostRequest(pIrpContext, pIrp); return RC; } PrevLevel = XifsdDebugLevel; PrevTarget = XifsdDebugTarget; XifsdDebugLevel = DEBUG_LEVEL_ALL; XifsdDebugTarget = DEBUG_TARGET_REFCOUNT; pVCB = &(pVolumeDeviceObject->VCB); ASSERT_VCB(pVCB); switch ( pIrpSp->MinorFunction ) { case IRP_MN_QUERY_REMOVE_DEVICE: RC = XixFsdPnpQueryRemove( pIrpContext, pIrp, pVCB ); break; case IRP_MN_SURPRISE_REMOVAL: RC = XixFsdPnpSurpriseRemove( pIrpContext, pIrp, pVCB ); break; case IRP_MN_REMOVE_DEVICE: RC = XixFsdPnpRemove( pIrpContext, pIrp, pVCB ); break; case IRP_MN_CANCEL_REMOVE_DEVICE: RC = XixFsdPnpCancelRemove( pIrpContext, pIrp, pVCB ); break; default: IoSkipCurrentIrpStackLocation( pIrp ); RC = IoCallDriver(pVCB->TargetDeviceObject, pIrp); XixFsdReleaseIrpContext(pIrpContext); break; } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("Exit XixFsdCommonPNP \n")); XifsdDebugLevel = PrevLevel; XifsdDebugTarget = PrevTarget; return RC; }
BOOLEAN CdCheckForDismount ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN Force ) /*++ Routine Description: This routine is called to check if a volume is ready for dismount. This occurs when only file system references are left on the volume. If the dismount is not currently underway and the user reference count has gone to zero then we can begin the dismount. If the dismount is in progress and there are no references left on the volume (we check the Vpb for outstanding references as well to catch any create calls dispatched to the file system) then we can delete the Vcb. Arguments: Vcb - Vcb for the volume to try to dismount. Force - Whether we will force this volume to be dismounted. Return Value: BOOLEAN - True if the Vcb was not gone by the time this function finished, False if it was deleted. This is only a trustworthy indication to the caller if it had the vcb exclusive itself. --*/ { BOOLEAN UnlockVcb = TRUE; BOOLEAN VcbPresent = TRUE; KIRQL SavedIrql; ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_VCB( Vcb ); ASSERT_EXCLUSIVE_CDDATA; // // Acquire and lock this Vcb to check the dismount state. // CdAcquireVcbExclusive( IrpContext, Vcb, FALSE ); // // Lets get rid of any pending closes for this volume. // CdFspClose( Vcb ); CdLockVcb( IrpContext, Vcb ); // // If the dismount is not already underway then check if the // user reference count has gone to zero or we are being forced // to disconnect. If so start the teardown on the Vcb. // if (Vcb->VcbCondition != VcbDismountInProgress) { if (Vcb->VcbUserReference <= CDFS_RESIDUAL_USER_REFERENCE || Force) { CdUnlockVcb( IrpContext, Vcb ); UnlockVcb = FALSE; VcbPresent = CdDismountVcb( IrpContext, Vcb ); } // // If the teardown is underway and there are absolutely no references // remaining then delete the Vcb. References here include the // references in the Vcb and Vpb. // } else if (Vcb->VcbReference == 0) { IoAcquireVpbSpinLock( &SavedIrql ); // // If there are no file objects and no reference counts in the // Vpb we can delete the Vcb. Don't forget that we have the // last reference in the Vpb. // if (Vcb->Vpb->ReferenceCount == 1) { IoReleaseVpbSpinLock( SavedIrql ); CdUnlockVcb( IrpContext, Vcb ); UnlockVcb = FALSE; CdDeleteVcb( IrpContext, Vcb ); VcbPresent = FALSE; } else { IoReleaseVpbSpinLock( SavedIrql ); } } // // Unlock the Vcb if still held. // if (UnlockVcb) { CdUnlockVcb( IrpContext, Vcb ); } // // Release any resources still acquired. // if (VcbPresent) { CdReleaseVcb( IrpContext, Vcb ); } return VcbPresent; }
NTSTATUS XixFsdPnpQueryRemove ( PXIFS_IRPCONTEXT pIrpContext, PIRP pIrp, PXIFS_VCB pVCB ) { NTSTATUS RC = STATUS_SUCCESS; KEVENT Event; BOOLEAN IsPresentVCB = FALSE; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("Enter XixFsdPnpQueryRemove \n")); ASSERT_IRPCONTEXT(pIrpContext); ASSERT(pIrp); ASSERT_VCB(pVCB); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("1 VCB->PtrVPB->ReferenceCount %d \n", pVCB->PtrVPB->ReferenceCount)); XifsdAcquireGData(pIrpContext); XifsdAcquireVcbExclusive(TRUE, pVCB, FALSE); XifsdLockVcb(pIrpContext, pVCB); XifsdSetFlag(pVCB->VCBFlags, XIFSD_VCB_FLAGS_PROCESSING_PNP); XifsdUnlockVcb(pIrpContext, pVCB); IsPresentVCB = TRUE; RC = XixFsdLockVolumeInternal(pIrpContext, pVCB, NULL); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("2 VCB->PtrVPB->ReferenceCount %d \n", pVCB->PtrVPB->ReferenceCount)); if(NT_SUCCESS(RC)){ // // Release System Resource // XixFsdCleanupFlushVCB(pIrpContext, pVCB, TRUE); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("XixFsdPnpQueryRemove Forward IRP to low stack .\n")); IoCopyCurrentIrpStackLocationToNext( pIrp ); KeInitializeEvent( &Event, NotificationEvent, FALSE ); IoSetCompletionRoutine( pIrp, XixFsdPnpCompletionRoutine, &Event, TRUE, TRUE, TRUE ); // // Send the request and wait. // RC = IoCallDriver(pVCB->TargetDeviceObject, pIrp); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("XixFsdPnpQueryRemove Forward IRP's result(0x%x) .\n", RC)); if (RC == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); RC = pIrp->IoStatus.Status; } if(NT_SUCCESS(RC)){ IsPresentVCB = XixFsdCheckForDismount(pIrpContext, pVCB, TRUE); ASSERT(!IsPresentVCB || (pVCB->VCBState == XIFSD_VCB_STATE_VOLUME_DISMOUNT_PROGRESS)); } } ASSERT( !(NT_SUCCESS(RC) && IsPresentVCB && pVCB->VCBReference != 0) ); if(IsPresentVCB){ XifsdLockVcb(pIrpContext, pVCB); XifsdClearFlag(pVCB->VCBFlags, XIFSD_VCB_FLAGS_PROCESSING_PNP); XifsdUnlockVcb(pIrpContext, pVCB); XifsdReleaseVcb(TRUE, pVCB); } XifsdReleaseGData(pIrpContext); XixFsdCompleteRequest(pIrpContext, RC, 0); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_PNP| DEBUG_TARGET_VCB| DEBUG_TARGET_IRPCONTEXT), ("Exit XifsdPnpQueryRemove \n")); return RC; }
NTSTATUS xixfs_TryClose( IN BOOLEAN CanWait, IN BOOLEAN bUserReference, IN PXIXFS_FCB pFCB ) { PXIXFS_VCB pVCB = NULL; NTSTATUS RC = STATUS_SUCCESS; uint32 UserReference = 0; PAGED_CODE(); ASSERT_FCB(pFCB); pVCB = pFCB->PtrVCB; ASSERT_VCB(pVCB); if(bUserReference) { UserReference = 1; } else { UserReference = 0; } XifsdDecCloseCount(pFCB); if(!CanWait) { if(bUserReference) { XifsdLockVcb(TRUE, pVCB); DebugTrace(DEBUG_LEVEL_CRITICAL|DEBUG_LEVEL_ALL, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_REFCOUNT|DEBUG_TARGET_FCB|DEBUG_TARGET_VCB|DEBUG_TARGET_REFCOUNT), ("XifsdCloseFCB, Fcb %08x Vcb %d/%d Fcb %d/%d\n", pFCB, pVCB->VCBReference, pVCB->VCBUserReference, pFCB->FCBReference, pFCB->FCBUserReference )); XifsdDecRefCount(pFCB, 0, 1); /* DbgPrint("dec CCB user ref Count CCB with VCB (%d/%d) (%d/%d)\n", pVCB->VCBReference, pVCB->VCBUserReference, pFCB->FCBReference, pFCB->FCBUserReference); */ DebugTrace(DEBUG_LEVEL_CRITICAL|DEBUG_LEVEL_ALL, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_REFCOUNT|DEBUG_TARGET_FCB|DEBUG_TARGET_VCB|DEBUG_TARGET_REFCOUNT), ("XifsdCloseFCB, Fcb %08x Vcb %d/%d Fcb %d/%d\n", pFCB, pVCB->VCBReference, pVCB->VCBUserReference, pFCB->FCBReference, pFCB->FCBUserReference )); XifsdUnlockVcb(TRUE, pVCB); } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_FCB), ("XifsdCloseFCB Fail Insert delete queue FCB Lotnumber(%I64d)\n", pFCB->XixcoreFcb.LotNumber)); xixfs_InsertCloseQueue(pFCB); RC = STATUS_UNSUCCESSFUL; } else { if(!xixfs_CloseFCB(CanWait, pVCB, pFCB, UserReference)) { if(bUserReference) { XifsdLockVcb(TRUE, pVCB); DebugTrace(DEBUG_LEVEL_CRITICAL|DEBUG_LEVEL_ALL, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_REFCOUNT|DEBUG_TARGET_FCB|DEBUG_TARGET_VCB|DEBUG_TARGET_REFCOUNT), ("XifsdCloseFCB, Fcb %08x Vcb %d/%d Fcb %d/%d\n", pFCB, pVCB->VCBReference, pVCB->VCBUserReference, pFCB->FCBReference, pFCB->FCBUserReference )); XifsdDecRefCount(pFCB, 0, 1); /* DbgPrint("dec CCB user ref Count CCB with VCB (%d/%d) (%d/%d)\n", pVCB->VCBReference, pVCB->VCBUserReference, pFCB->FCBReference, pFCB->FCBUserReference); */ DebugTrace(DEBUG_LEVEL_CRITICAL|DEBUG_LEVEL_ALL, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_REFCOUNT|DEBUG_TARGET_FCB|DEBUG_TARGET_VCB|DEBUG_TARGET_REFCOUNT), ("XifsdCloseFCB, Fcb %08x Vcb %d/%d Fcb %d/%d\n", pFCB, pVCB->VCBReference, pVCB->VCBUserReference, pFCB->FCBReference, pFCB->FCBUserReference )); XifsdUnlockVcb(TRUE, pVCB); } DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_FCB), ("XifsdCloseFCB Fail Insert delete queue FCB Lotnumber(%I64d)\n", pFCB->XixcoreFcb.LotNumber)); xixfs_InsertCloseQueue(pFCB); RC = STATUS_UNSUCCESSFUL; } DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLOSE|DEBUG_TARGET_REFCOUNT|DEBUG_TARGET_FCB|DEBUG_TARGET_VCB), ("XifsdCommonFCB, Fcb %08x Vcb %d/%d Fcb %d/%d\n", pFCB, pVCB->VCBReference, pVCB->VCBUserReference, pFCB->FCBReference, pFCB->FCBUserReference )); } return RC; }
NTSTATUS XixFsdCommonDeviceControl( IN PXIFS_IRPCONTEXT pIrpContext ) { NTSTATUS RC = STATUS_SUCCESS; PIRP pIrp = NULL; PIO_STACK_LOCATION pIrpSp= NULL; PIO_STACK_LOCATION pNextIrpSp = NULL; PFILE_OBJECT PtrFileObject = NULL; PXIFS_FCB pFCB = NULL; PXIFS_CCB pCCB = NULL; PXIFS_VCB pVCB = NULL; BOOLEAN CompleteIrp = FALSE; ULONG IoControlCode = 0; void *BufferPointer = NULL; BOOLEAN Wait = FALSE; BOOLEAN PostRequest = FALSE; TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject; KEVENT WaitEvent; PVOID CompletionContext = NULL; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_DEVCTL, ("Enter XixFsdCommonDeviceControl .\n")); DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, ("!!!!Enter XixFsdCommonDeviceControl \n")); ASSERT(pIrpContext); ASSERT(pIrpContext->Irp); pIrp = pIrpContext->Irp; try { Wait = XifsdCheckFlagBoolean(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT); if(!Wait){ PostRequest = TRUE; try_return(RC = STATUS_PENDING); } // First, get a pointer to the current I/O stack location pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp); PtrFileObject = pIrpSp->FileObject; ASSERT(PtrFileObject); DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_DEVCTL, (" Decode File Object\n")); TypeOfOpen = XixFsdDecodeFileObject( PtrFileObject, &pFCB, &pCCB ); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DEVCTL|DEBUG_TARGET_IRPCONTEXT), ("pIrpSp->Parameters.DeviceIoControl.IoControlCode(0x%02x) .\n", pIrpSp->Parameters.DeviceIoControl.IoControlCode)); if (TypeOfOpen == UserVolumeOpen) { pVCB = (PXIFS_VCB)(pFCB ->PtrVCB); ASSERT_VCB(pVCB); } else { DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("User Volume Open Not supported!!.\n")); RC = STATUS_INVALID_PARAMETER; XixFsdCompleteRequest(pIrpContext, RC, 0); try_return(RC); } switch(pIrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES: //DbgPrint("!!! IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES\n"); XifsdAcquireVcbExclusive(TRUE, pVCB, FALSE); XixFsdFlusVolume(pIrpContext, pVCB); KeInitializeEvent( &WaitEvent, NotificationEvent, FALSE ); CompletionContext = &WaitEvent; IoCopyCurrentIrpStackLocationToNext(pIrp ); IoSetCompletionRoutine(pIrp, XixFsdDevFlushAndHoldWriteCompletionRoutine, CompletionContext, TRUE, TRUE, TRUE ); break; default: IoSkipCurrentIrpStackLocation( pIrp ); /* IoCopyCurrentIrpStackLocationToNext(pIrp ); // Set a completion routine. IoSetCompletionRoutine(pIrp, XixFsdDevIoctlCompletion, NULL, TRUE, TRUE, TRUE); */ break; } // Send the request. RC = IoCallDriver(pVCB->TargetDeviceObject, pIrp); if(RC == STATUS_PENDING && CompletionContext){ //DbgPrint("!!! IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES2\n"); KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL); RC = pIrp->IoStatus.Status; } if(CompletionContext) { /* DbgPrint("!!! IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES RC(0x%x) Status(0x%x) Information(%ld) \n", RC, pIrp->IoStatus.Status, pIrp->IoStatus.Information); */ XifsdReleaseVcb(TRUE, pVCB); XixFsdCompleteRequest(pIrpContext, RC, (uint32)pIrp->IoStatus.Information); }else{ XixFsdReleaseIrpContext(pIrpContext); } } finally { if (!(pIrpContext->IrpContextFlags & XIFSD_IRP_CONTEXT_EXCEPTION)) { ; } if(PostRequest ){ DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DEVCTL|DEBUG_TARGET_IRPCONTEXT), ("PostRequest pIrpCotnext(0x%x) pIrp(0x%x)\n", pIrpContext, pIrp)); RC = XixFsdPostRequest(pIrpContext, pIrp); } } DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_DEVCTL, ("Exit XixFsdCommonDeviceControl .\n")); return(RC); }