📄 dirctrl.c
字号:
// 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 );
}
try_exit: NOTHING;
} finally {
DebugUnwind( FatQueryDirectory );
FatReleaseFcb( IrpContext, Dcb );
//
// Unpin data in cache if still held.
//
FatUnpinBcb( IrpContext, Bcb );
//
// Free any dynamically allocated string buffer
//
FatFreeStringBuffer( &LongFileName);
//
// Perform any cleanup. If this is the first query, then store
// the filename in the Ccb if successful. Also update the
// VBO index for the next search. This is done by transferring
// from shared access to exclusive access and copying the
// data from the local copies.
//
if (!AbnormalTermination()) {
if (UpdateCcb) {
//
// Store the most recent VBO to use as a starting point for
// the next search.
//
Ccb->OffsetToStartSearchFrom = CurrentVbo;
}
FatCompleteRequest( IrpContext, Irp, Status );
}
DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);
}
return Status;
}
//
// Local Support Routine
//
VOID
FatGetDirTimes(
PIRP_CONTEXT IrpContext,
PDIRENT Dirent,
PFILE_DIRECTORY_INFORMATION DirInfo
)
/*++
Routine Description:
This routine pulls the date/time information from a dirent and fills
in the DirInfo structure.
Arguments:
Dirent - Supplies the dirent
DirInfo - Supplies the target structure
Return Value:
VOID
--*/
{
//
// Start with the Last Write Time.
//
DirInfo->LastWriteTime =
FatFatTimeToNtTime( IrpContext,
Dirent->LastWriteTime,
0 );
//
// These fields are only non-zero when in Chicago mode.
//
if (FatData.ChicagoMode) {
//
// Do a quick check here for Creation and LastAccess
// times that are the same as the LastWriteTime.
//
if (*((UNALIGNED LONG *)&Dirent->CreationTime) ==
*((UNALIGNED LONG *)&Dirent->LastWriteTime)) {
DirInfo->CreationTime.QuadPart =
DirInfo->LastWriteTime.QuadPart +
Dirent->CreationMSec * 10 * 1000 * 10;
} else {
//
// Only do the really hard work if this field is non-zero.
//
if (((PUSHORT)Dirent)[8] != 0) {
DirInfo->CreationTime =
FatFatTimeToNtTime( IrpContext,
Dirent->CreationTime,
Dirent->CreationMSec );
} else {
ExLocalTimeToSystemTime( &FatJanOne1980,
&DirInfo->CreationTime );
}
}
//
// Do a quick check for LastAccessDate.
//
if (*((PUSHORT)&Dirent->LastAccessDate) ==
*((PUSHORT)&Dirent->LastWriteTime.Date)) {
PFAT_TIME WriteTime;
WriteTime = &Dirent->LastWriteTime.Time;
DirInfo->LastAccessTime.QuadPart =
DirInfo->LastWriteTime.QuadPart -
UInt32x32To64(((WriteTime->DoubleSeconds * 2) +
(WriteTime->Minute * 60) +
(WriteTime->Hour * 60 * 60)),
1000 * 1000 * 10);
} else {
//
// Only do the really hard work if this field is non-zero.
//
if (((PUSHORT)Dirent)[9] != 0) {
DirInfo->LastAccessTime =
FatFatDateToNtTime( IrpContext,
Dirent->LastAccessDate );
} else {
ExLocalTimeToSystemTime( &FatJanOne1980,
&DirInfo->LastAccessTime );
}
}
}
}
//
// Local Support Routine
//
NTSTATUS
FatNotifyChangeDirectory (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine performs the notify change 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;
ULONG CompletionFilter;
BOOLEAN WatchTree;
BOOLEAN CompleteRequest;
//
// Get the current Stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatNotifyChangeDirectory...\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, " ->CompletionFilter = %08lx\n", IrpSp->Parameters.NotifyDirectory.CompletionFilter);
//
// Always set the wait flag in the Irp context for the original request.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
//
// Assume we don't complete request.
//
CompleteRequest = FALSE;
//
// Check on the type of open. We return invalid parameter for all
// but UserDirectoryOpens.
//
if (FatDecodeFileObject( IrpSp->FileObject,
&Vcb,
&Dcb,
&Ccb ) != UserDirectoryOpen) {
FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
DebugTrace(-1, Dbg, "FatQueryDirectory -> STATUS_INVALID_PARAMETER\n", 0);
return STATUS_INVALID_PARAMETER;
}
//
// Reference our input parameter to make things easier
//
CompletionFilter = IrpSp->Parameters.NotifyDirectory.CompletionFilter;
WatchTree = BooleanFlagOn( IrpSp->Flags, SL_WATCH_TREE );
//
// Try to acquire exclusive access to the Dcb and enqueue the Irp to the
// Fsp if we didn't get access
//
if (!FatAcquireExclusiveFcb( IrpContext, Dcb )) {
DebugTrace(0, Dbg, "FatNotifyChangeDirectory -> Cannot Acquire Fcb\n", 0);
Status = FatFsdPostRequest( IrpContext, Irp );
DebugTrace(-1, Dbg, "FatNotifyChangeDirectory -> %08lx\n", Status);
return Status;
}
try {
//
// Make sure the Fcb is still good
//
FatVerifyFcb( IrpContext, Dcb );
//
// We need the full name.
//
FatSetFullFileNameInFcb( IrpContext, Dcb );
//
// If the file is marked as DELETE_PENDING then complete this
// request immediately.
//
if (FlagOn( Dcb->FcbState, FCB_STATE_DELETE_ON_CLOSE )) {
FatRaiseStatus( IrpContext, STATUS_DELETE_PENDING );
}
//
// Call the Fsrtl package to process the request.
//
FsRtlNotifyFullChangeDirectory( Vcb->NotifySync,
&Vcb->DirNotifyList,
Ccb,
(PSTRING)&Dcb->FullFileName,
WatchTree,
FALSE,
CompletionFilter,
Irp,
NULL,
NULL );
Status = STATUS_PENDING;
CompleteRequest = TRUE;
} finally {
DebugUnwind( FatNotifyChangeDirectory );
FatReleaseFcb( IrpContext, Dcb );
//
// If the dir notify package is holding the Irp, we discard the
// the IrpContext.
//
if (CompleteRequest) {
FatCompleteRequest( IrpContext, FatNull, 0 );
}
DebugTrace(-1, Dbg, "FatNotifyChangeDirectory -> %08lx\n", Status);
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -