📄 dirctl.c
字号:
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlCopyMemory(
Ccb->DirectorySearchPattern.Buffer,
L"*\0", 2);
}
if (!IndexSpecified)
{
if (RestartScan || FirstQuery)
{
FileIndex = Fcb->Ext2Mcb->DeOffset = 0;
}
else
{
FileIndex = Ccb->CurrentByteOffset;
}
}
Inode = (PEXT2_INODE) ExAllocatePool(
PagedPool,
sizeof(EXT2_INODE));
if (Inode == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(Buffer, Length);
if (Fcb->ext2_inode->i_size <= FileIndex)
{
Status = STATUS_NO_MORE_FILES;
__leave;
}
pDir = ExAllocatePool(PagedPool,
sizeof(EXT2_DIR_ENTRY2));
if (!pDir)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
dwBytes = 0;
dwSize = Fcb->ext2_inode->i_size - FileIndex - (sizeof(EXT2_DIR_ENTRY2) - EXT2_NAME_LEN + 1);
ByteOffset = FileIndex;
dwTemp = 0;
while (bRun && UsedLength < Length && dwBytes < dwSize)
{
RtlZeroMemory(pDir, sizeof(EXT2_DIR_ENTRY2));
Status = Ext2ReadInode(
NULL,
Vcb,
Fcb->ext2_inode,
ByteOffset,
(PVOID)pDir,
sizeof(EXT2_DIR_ENTRY2),
&dwReturn);
if (!NT_SUCCESS(Status))
{
__leave;
}
if (!pDir->inode)
{
bRun = FALSE;
break;
}
InodeFileNameLength = pDir->name_len & 0xff;
InodeFileName.Length = InodeFileName.MaximumLength =
InodeFileNameLength * 2;
if (InodeFileName.Length <= 0)
break;
InodeFileName.Buffer = ExAllocatePool(
PagedPool,
InodeFileNameLength * 2 + 2);
if (!InodeFileName.Buffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(InodeFileName.Buffer, InodeFileNameLength * 2 + 2);
Ext2CharToWchar(
InodeFileName.Buffer,
pDir->name,
InodeFileNameLength );
if (FsRtlDoesNameContainWildCards(&(Ccb->DirectorySearchPattern)) ?
FsRtlIsNameInExpression(
&(Ccb->DirectorySearchPattern),
&InodeFileName,
TRUE,
NULL) :
!RtlCompareUnicodeString(
&(Ccb->DirectorySearchPattern),
&InodeFileName,
TRUE) )
{
dwReturn = Ext2ProcessDirEntry(
Vcb, FileInformationClass,
pDir->inode, Buffer, UsedLength, Length - UsedLength,
dwBytes, &InodeFileName,
ReturnSingleEntry );
if (dwReturn <= 0)
{
bRun = FALSE;
}
else
{
dwTemp = UsedLength;
UsedLength += dwReturn;
}
}
if (InodeFileName.Buffer != NULL)
{
ExFreePool(InodeFileName.Buffer);
InodeFileName.Buffer = NULL;
}
if (bRun)
{
dwBytes +=pDir->rec_len;
Ccb->CurrentByteOffset = FileIndex + dwBytes;
}
if (UsedLength && ReturnSingleEntry)
{
Status = STATUS_SUCCESS;
__leave;
}
ByteOffset = FileIndex + dwBytes;
}
FileIndex += dwBytes;
((PULONG)((PUCHAR)Buffer + dwTemp)) [0] = 0;
if (!UsedLength)
{
if (FirstQuery)
{
Status = STATUS_NO_SUCH_FILE;
}
else
{
Status = STATUS_NO_MORE_FILES;
}
}
else
{
Status = STATUS_SUCCESS;
}
}
__finally
{
if (FcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread() );
}
if (Inode != NULL)
{
ExFreePool(Inode);
}
if (pDir != NULL)
{
ExFreePool(pDir);
pDir = NULL;
}
if (InodeFileName.Buffer != NULL)
{
ExFreePool(InodeFileName.Buffer);
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
Status = Ext2LockUserBuffer(
IrpContext->Irp,
Length,
IoWriteAccess );
if (NT_SUCCESS(Status))
{
Status = Ext2QueueRequest(IrpContext);
}
else
{
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
Ext2FreeIrpContext(IrpContext);
}
}
else
{
IrpContext->Irp->IoStatus.Information = UsedLength;
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
Ext2FreeIrpContext(IrpContext);
}
}
}
return Status;
}
NTSTATUS
Ext2NotifyChangeDirectory (
IN PEXT2_IRP_CONTEXT IrpContext
)
{
PDEVICE_OBJECT DeviceObject;
BOOLEAN CompleteRequest;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_VCB Vcb;
PFILE_OBJECT FileObject;
PEXT2_FCB Fcb;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
ULONG CompletionFilter;
BOOLEAN WatchTree;
__try
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
//
// Always set the wait flag in the Irp context for the original request.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == gExt2Global->DeviceObject)
{
CompleteRequest = TRUE;
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
FileObject = IrpContext->FileObject;
Fcb = (PEXT2_FCB) FileObject->FsContext;
ASSERT(Fcb);
if (Fcb->Identifier.Type == EXT2VCB)
{
CompleteRequest = TRUE;
Status = STATUS_INVALID_PARAMETER;
__leave;
}
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
if (!FlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
CompleteRequest = TRUE;
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
#ifndef _GNU_NTIFS_
CompletionFilter =
IrpSp->Parameters.NotifyDirectory.CompletionFilter;
#else // _GNU_NTIFS_
CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION)
IrpSp)->Parameters.NotifyDirectory.CompletionFilter;
#endif // _GNU_NTIFS_
WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE);
CompleteRequest = FALSE;
Status = STATUS_PENDING;
{
UNICODE_STRING FullFileName;
if (Ext2GetFullFileName(Fcb->Ext2Mcb, &FullFileName))
{
FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
&Vcb->NotifyList,
FileObject->FsContext2,
(PSTRING)&FullFileName,
WatchTree,
FALSE,
CompletionFilter,
Irp,
NULL,
NULL );
ExFreePool(FullFileName.Buffer);
}
}
/*
Currently the driver is read-only but here is an example on how to use the
FsRtl-functions to report a change:
ANSI_STRING TestString;
USHORT FileNamePartLength;
RtlInitAnsiString(&TestString, "\\ntifs.h");
FileNamePartLength = 7;
FsRtlNotifyReportChange(
Vcb->NotifySync, // PNOTIFY_SYNC NotifySync
&Vcb->NotifyList, // PLIST_ENTRY NotifyList
&TestString, // PSTRING FullTargetName
&FileNamePartLength, // PUSHORT FileNamePartLength
FILE_NOTIFY_CHANGE_NAME // ULONG FilterMatch
);
or
ANSI_STRING TestString;
RtlInitAnsiString(&TestString, "\\ntifs.h");
FsRtlNotifyFullReportChange(
Vcb->NotifySync, // PNOTIFY_SYNC NotifySync
&Vcb->NotifyList, // PLIST_ENTRY NotifyList
&TestString, // PSTRING FullTargetName
1, // USHORT TargetNameOffset
NULL, // PSTRING StreamName OPTIONAL
NULL, // PSTRING NormalizedParentName OPTIONAL
FILE_NOTIFY_CHANGE_NAME, // ULONG FilterMatch
0, // ULONG Action
NULL // PVOID TargetContext
);
*/
}
__finally
{
if (!IrpContext->ExceptionInProgress)
{
if (CompleteRequest)
{
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
);
}
Ext2FreeIrpContext(IrpContext);
}
}
return Status;
}
NTSTATUS
Ext2DirectoryControl (IN PEXT2_IRP_CONTEXT IrpContext)
{
NTSTATUS Status;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
switch (IrpContext->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
Status = Ext2QueryDirectory(IrpContext);
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
Status = Ext2NotifyChangeDirectory(IrpContext);
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
Ext2FreeIrpContext(IrpContext);
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -