📄 dirctrl.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
DirCtrl.c
Abstract:
This module implements the File Directory Control routines for Fat called
by the dispatch driver.
--*/
#include "FatProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (FAT_BUG_CHECK_DIRCTRL)
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_DIRCTRL)
WCHAR Fat8QMdot3QM[12] = { DOS_QM, DOS_QM, DOS_QM, DOS_QM, DOS_QM, DOS_QM, DOS_QM, DOS_QM,
L'.', DOS_QM, DOS_QM, DOS_QM};
//
// Local procedure prototypes
//
NTSTATUS
FatQueryDirectory (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
VOID
FatGetDirTimes(
PIRP_CONTEXT IrpContext,
PDIRENT Dirent,
PFILE_DIRECTORY_INFORMATION DirInfo
);
NTSTATUS
FatNotifyChangeDirectory (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatCommonDirectoryControl)
#pragma alloc_text(PAGE, FatFsdDirectoryControl)
#pragma alloc_text(PAGE, FatNotifyChangeDirectory)
#pragma alloc_text(PAGE, FatQueryDirectory)
#pragma alloc_text(PAGE, FatGetDirTimes)
#endif
NTSTATUS
FatFsdDirectoryControl (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the FSD part of directory control
Arguments:
VolumeDeviceObject - Supplies the volume device object where the
file exists
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The FSD status for the IRP
--*/
{
NTSTATUS Status;
PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
DebugTrace(+1, Dbg, "FatFsdDirectoryControl\n", 0);
//
// Call the common directory Control routine, with blocking allowed if
// synchronous
//
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
try {
IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
Status = FatCommonDirectoryControl( IrpContext, Irp );
} 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, "FatFsdDirectoryControl -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;
}
NTSTATUS
FatCommonDirectoryControl (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for doing directory 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;
//
// Get a pointer to the current Irp stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatCommonDirectoryControl\n", 0);
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction );
//
// We know this is a directory control so we'll case on the
// minor function, and call a internal worker routine to complete
// the irp.
//
switch ( IrpSp->MinorFunction ) {
case IRP_MN_QUERY_DIRECTORY:
Status = FatQueryDirectory( IrpContext, Irp );
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
Status = FatNotifyChangeDirectory( IrpContext, Irp );
break;
default:
DebugTrace(0, Dbg, "Invalid Directory Control Minor Function %08lx\n", IrpSp->MinorFunction);
FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
DebugTrace(-1, Dbg, "FatCommonDirectoryControl -> %08lx\n", Status);
return Status;
}
//
// Local Support Routine
//
NTSTATUS
FatQueryDirectory (
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;
//
// 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 = 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;
}
//
// 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 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -