📄 dirctl.c
字号:
__leave;
}
RtlZeroMemory(
InodeFileName.Buffer,
InodeFileNameLength + 2);
Status = FFSOEMToUnicode(&InodeFileName,
&OemName);
if (!NT_SUCCESS(Status))
{
__leave;
}
if (FsRtlDoesNameContainWildCards(
&(Ccb->DirectorySearchPattern)) ?
FsRtlIsNameInExpression(
&(Ccb->DirectorySearchPattern),
&InodeFileName,
TRUE,
NULL) :
!RtlCompareUnicodeString(
&(Ccb->DirectorySearchPattern),
&InodeFileName,
TRUE))
{
dwReturn = FFSProcessDirEntry(
Vcb, FileInformationClass,
pDir->d_ino,
Buffer,
UsedLength,
Length - UsedLength,
(FileIndex + dwBytes),
&InodeFileName,
ReturnSingleEntry);
if (dwReturn <= 0)
{
bRun = FALSE;
}
else
{
dwTemp = UsedLength;
UsedLength += dwReturn;
}
}
if (InodeFileName.Buffer != NULL)
{
ExFreePool(InodeFileName.Buffer);
InodeFileName.Buffer = NULL;
}
ProcessNextEntryv1:
if (bRun)
{
dwBytes +=pDir->d_reclen;
Ccb->CurrentByteOffset = FileIndex + dwBytes;
}
if (UsedLength && ReturnSingleEntry)
{
Status = STATUS_SUCCESS;
__leave;
}
ByteOffset = FileIndex + dwBytes;
}
}
else
{
dwBytes = 0;
dwSize = (ULONG)Fcb->dinode2->di_size - FileIndex -
(sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1);
ByteOffset = FileIndex;
dwTemp = 0;
while (bRun && UsedLength < Length && dwBytes < dwSize)
{
OEM_STRING OemName;
RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));
Status = FFSv2ReadInode(
NULL,
Vcb,
Fcb->dinode2,
ByteOffset,
(PVOID)pDir,
sizeof(FFS_DIR_ENTRY),
&dwReturn);
if (!NT_SUCCESS(Status))
{
__leave;
}
if (!pDir->d_ino)
{
if (pDir->d_reclen == 0)
{
FFSBreakPoint();
__leave;
}
goto ProcessNextEntryv2;
}
OemName.Buffer = pDir->d_name;
OemName.Length = (pDir->d_namlen & 0xff);
OemName.MaximumLength = OemName.Length;
#if 0
/*
//
// We could not filter the files: "." and ".."
//
if ((OemName.Length >) 1 && OemName.Buffer[0] == '.')
{
if ( OemName.Length == 2 && OemName.Buffer[1] == '.')
{
}
else
{
goto ProcessNextEntry2;
}
}
*/
#endif
InodeFileNameLength = (USHORT)
RtlOemStringToUnicodeSize(&OemName);
InodeFileName.Length = 0;
InodeFileName.MaximumLength = InodeFileNameLength + 2;
if (InodeFileNameLength <= 0)
{
break;
}
InodeFileName.Buffer = ExAllocatePool(
PagedPool,
InodeFileNameLength + 2);
if (!InodeFileName.Buffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(
InodeFileName.Buffer,
InodeFileNameLength + 2);
Status = FFSOEMToUnicode(&InodeFileName,
&OemName);
if (!NT_SUCCESS(Status))
{
__leave;
}
if (FsRtlDoesNameContainWildCards(
&(Ccb->DirectorySearchPattern)) ?
FsRtlIsNameInExpression(
&(Ccb->DirectorySearchPattern),
&InodeFileName,
TRUE,
NULL) :
!RtlCompareUnicodeString(
&(Ccb->DirectorySearchPattern),
&InodeFileName,
TRUE))
{
dwReturn = FFSProcessDirEntry(
Vcb, FileInformationClass,
pDir->d_ino,
Buffer,
UsedLength,
Length - UsedLength,
(FileIndex + dwBytes),
&InodeFileName,
ReturnSingleEntry);
if (dwReturn <= 0)
{
bRun = FALSE;
}
else
{
dwTemp = UsedLength;
UsedLength += dwReturn;
}
}
if (InodeFileName.Buffer != NULL)
{
ExFreePool(InodeFileName.Buffer);
InodeFileName.Buffer = NULL;
}
ProcessNextEntryv2:
if (bRun)
{
dwBytes +=pDir->d_reclen;
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 (FS_VERSION == 1)
{
if (dinode1 != NULL)
{
ExFreePool(dinode1);
}
}
else
{
if (dinode2 != NULL)
{
ExFreePool(dinode2);
}
}
if (pDir != NULL)
{
ExFreePool(pDir);
pDir = NULL;
}
if (InodeFileName.Buffer != NULL)
{
ExFreePool(InodeFileName.Buffer);
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
Status = FFSLockUserBuffer(
IrpContext->Irp,
Length,
IoWriteAccess);
if (NT_SUCCESS(Status))
{
Status = FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
else
{
IrpContext->Irp->IoStatus.Information = UsedLength;
FFSCompleteIrpContext(IrpContext, Status);
}
}
}
return Status;
}
NTSTATUS
FFSNotifyChangeDirectory(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
BOOLEAN CompleteRequest;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_VCB Vcb;
PFILE_OBJECT FileObject;
PFFS_FCB Fcb;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
ULONG CompletionFilter;
BOOLEAN WatchTree;
BOOLEAN bFcbAcquired = FALSE;
PUNICODE_STRING FullName;
__try
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_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 == FFSGlobal->DeviceObject)
{
CompleteRequest = TRUE;
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
FileObject = IrpContext->FileObject;
Fcb = (PFFS_FCB)FileObject->FsContext;
ASSERT(Fcb);
if (Fcb->Identifier.Type == FFSVCB)
{
FFSBreakPoint();
CompleteRequest = TRUE;
Status = STATUS_INVALID_PARAMETER;
__leave;
}
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
if (!IsDirectory(Fcb))
{
FFSBreakPoint();
CompleteRequest = TRUE;
Status = STATUS_INVALID_PARAMETER;
__leave;
}
if (ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
TRUE))
{
bFcbAcquired = TRUE;
}
else
{
Status = STATUS_PENDING;
__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);
if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
{
Status = STATUS_DELETE_PENDING;
__leave;
}
FullName = &Fcb->LongName;
if (FullName->Buffer == NULL)
{
if (!FFSGetFullFileName(Fcb->FFSMcb, FullName))
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
}
FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
&Vcb->NotifyList,
FileObject->FsContext2,
(PSTRING)FullName,
WatchTree,
FALSE,
CompletionFilter,
Irp,
NULL,
NULL);
CompleteRequest = FALSE;
Status = STATUS_PENDING;
/*
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 (bFcbAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (!CompleteRequest)
{
IrpContext->Irp = NULL;
}
FFSCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
VOID
FFSNotifyReportChange(
IN PFFS_IRP_CONTEXT IrpContext,
IN PFFS_VCB Vcb,
IN PFFS_FCB Fcb,
IN ULONG Filter,
IN ULONG Action)
{
PUNICODE_STRING FullName;
USHORT Offset;
FullName = &Fcb->LongName;
// ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
if (FullName->Buffer == NULL)
{
if (!FFSGetFullFileName(Fcb->FFSMcb, FullName))
{
/*Status = STATUS_INSUFFICIENT_RESOURCES;*/
return;
}
}
Offset = (USHORT)(FullName->Length -
Fcb->FFSMcb->ShortName.Length);
FsRtlNotifyFullReportChange(Vcb->NotifySync,
&(Vcb->NotifyList),
(PSTRING)(FullName),
(USHORT)Offset,
(PSTRING)NULL,
(PSTRING)NULL,
(ULONG)Filter,
(ULONG)Action,
(PVOID)NULL);
// ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
}
NTSTATUS
FFSDirectoryControl(
IN PFFS_IRP_CONTEXT IrpContext)
{
NTSTATUS Status;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
switch (IrpContext->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
Status = FFSQueryDirectory(IrpContext);
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
Status = FFSNotifyChangeDirectory(IrpContext);
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
FFSCompleteIrpContext(IrpContext, Status);
}
return Status;
}
BOOLEAN
FFSIsDirectoryEmpty(
PFFS_VCB Vcb,
PFFS_FCB Dcb)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_DIR_ENTRY pTarget = NULL;
ULONG dwBytes = 0;
ULONG dwRet;
BOOLEAN bRet = TRUE;
if (!IsFlagOn(Dcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
return TRUE;
__try
{
pTarget = (PFFS_DIR_ENTRY)ExAllocatePool(PagedPool,
FFS_DIR_REC_LEN(FFS_NAME_LEN));
if (!pTarget)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
dwBytes = 0;
while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart)
{
RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));
if (FS_VERSION == 1)
{
Status = FFSv1ReadInode(
NULL,
Vcb,
Dcb->dinode1,
dwBytes,
(PVOID)pTarget,
FFS_DIR_REC_LEN(FFS_NAME_LEN),
&dwRet);
}
else
{
Status = FFSv2ReadInode(
NULL,
Vcb,
Dcb->dinode2,
dwBytes,
(PVOID)pTarget,
FFS_DIR_REC_LEN(FFS_NAME_LEN),
&dwRet);
}
if (!NT_SUCCESS(Status))
{
FFSPrint((DBG_ERROR, "FFSRemoveEntry: Reading Directory Content error.\n"));
__leave;
}
if (pTarget->d_ino)
{
if (pTarget->d_namlen == 1 && pTarget->d_name[0] == '.')
{
}
else if (pTarget->d_namlen == 2 && pTarget->d_name[0] == '.' &&
pTarget->d_name[1] == '.')
{
}
else
{
bRet = FALSE;
break;
}
}
else
{
break;
}
dwBytes += pTarget->d_reclen;
}
}
__finally
{
if (pTarget != NULL)
{
ExFreePool(pTarget);
}
}
return bRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -