📄 dirctl.c
字号:
/*
This is a romfs file system driver for Windows NT/2000/XP.
Copyright (C) 1999, 2000, 2001, 2002 Bo Brant閚.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ntifs.h"
#include "fsd.h"
#include "rom_fs.h"
#include "border.h"
#pragma code_seg(FSD_PAGED_CODE)
NTSTATUS
FsdDirectoryControl (
IN PFSD_IRP_CONTEXT IrpContext
)
{
NTSTATUS Status;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == ICX) &&
(IrpContext->Identifier.Size == sizeof(FSD_IRP_CONTEXT)));
switch (IrpContext->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
Status = FsdQueryDirectory(IrpContext);
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
Status = FsdNotifyChangeDirectory(IrpContext);
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
IrpContext->Irp->IoStatus.Status = Status;
FsdCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
FsdFreeIrpContext(IrpContext);
}
return Status;
}
NTSTATUS
FsdQueryDirectory (
IN PFSD_IRP_CONTEXT IrpContext
)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFSD_VCB Vcb;
PFILE_OBJECT FileObject;
PFSD_FCB Fcb;
PFSD_CCB Ccb;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
FILE_INFORMATION_CLASS FileInformationClass;
ULONG Length;
PUNICODE_STRING FileName;
UNICODE_STRING UpcaseFileName;
ULONG FileIndex;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
PUCHAR UserBuffer;
BOOLEAN FirstQuery;
struct romfs_inode* Inode = NULL;
BOOLEAN FcbResourceAcquired = FALSE;
ULONG QueryBlockLength;
ULONG UsedLength = 0;
USHORT InodeFileNameLength;
UNICODE_STRING InodeFileName;
PULONG NextEntryOffset = NULL;
UpcaseFileName.Buffer = NULL;
InodeFileName.Buffer = NULL;
__try
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == ICX) &&
(IrpContext->Identifier.Size == sizeof(FSD_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == FsdGlobalData.DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PFSD_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == VCB) &&
(Vcb->Identifier.Size == sizeof(FSD_VCB)));
FileObject = IrpContext->FileObject;
Fcb = (PFSD_FCB) FileObject->FsContext;
ASSERT(Fcb);
if (Fcb->Identifier.Type == VCB)
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
ASSERT((Fcb->Identifier.Type == FCB) &&
(Fcb->Identifier.Size == sizeof(FSD_FCB)));
if (!FlagOn(Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Ccb = (PFSD_CCB) FileObject->FsContext2;
ASSERT(Ccb);
ASSERT((Ccb->Identifier.Type == CCB) &&
(Ccb->Identifier.Size == sizeof(FSD_CCB)));
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
#ifndef _GNU_NTIFS_
FileInformationClass =
IrpSp->Parameters.QueryDirectory.FileInformationClass;
Length = IrpSp->Parameters.QueryDirectory.Length;
FileName = IrpSp->Parameters.QueryDirectory.FileName;
FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;
#else // _GNU_NTIFS_
FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION)
IrpSp)->Parameters.QueryDirectory.FileInformationClass;
Length = ((PEXTENDED_IO_STACK_LOCATION)
IrpSp)->Parameters.QueryDirectory.Length;
FileName = ((PEXTENDED_IO_STACK_LOCATION)
IrpSp)->Parameters.QueryDirectory.FileName;
FileIndex = ((PEXTENDED_IO_STACK_LOCATION)
IrpSp)->Parameters.QueryDirectory.FileIndex;
#endif // _GNU_NTIFS_
RestartScan = FlagOn(IrpSp->Flags, SL_RESTART_SCAN);
ReturnSingleEntry = FlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
IndexSpecified = FlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED);
if (Irp->RequestorMode != KernelMode &&
!Irp->MdlAddress &&
Irp->UserBuffer)
{
ProbeForWrite(Irp->UserBuffer, Length, 1);
}
UserBuffer = FsdGetUserBuffer(Irp);
if (UserBuffer == NULL)
{
Status = STATUS_INVALID_USER_BUFFER;
__leave;
}
if (!IrpContext->IsSynchronous)
{
Status = STATUS_PENDING;
__leave;
}
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource,
IrpContext->IsSynchronous
))
{
Status = STATUS_PENDING;
__leave;
}
FcbResourceAcquired = TRUE;
if (FileName != NULL)
{
UpcaseFileName.Length = UpcaseFileName.MaximumLength =
FileName->Length;
UpcaseFileName.Buffer =
FsdAllocatePool(NonPagedPool, FileName->Length, '1iDR');
if (UpcaseFileName.Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlUpcaseUnicodeString(
&UpcaseFileName,
FileName,
FALSE
);
FileName = &UpcaseFileName;
if (Ccb->DirectorySearchPattern.Buffer != NULL)
{
FirstQuery = FALSE;
}
else
{
FirstQuery = TRUE;
Ccb->DirectorySearchPattern.Length =
Ccb->DirectorySearchPattern.MaximumLength =
FileName->Length;
Ccb->DirectorySearchPattern.Buffer =
FsdAllocatePool(NonPagedPool, FileName->Length, '2iDR');
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlCopyMemory(
Ccb->DirectorySearchPattern.Buffer,
FileName->Buffer,
FileName->Length
);
}
}
else if (Ccb->DirectorySearchPattern.Buffer != NULL)
{
FirstQuery = FALSE;
FileName = &Ccb->DirectorySearchPattern;
}
else
{
FirstQuery = TRUE;
Ccb->DirectorySearchPattern.Length = sizeof(WCHAR);
Ccb->DirectorySearchPattern.MaximumLength = sizeof(WCHAR);
Ccb->DirectorySearchPattern.Buffer =
FsdAllocatePool(NonPagedPool, sizeof(WCHAR), '3iDR');
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlCopyMemory(Ccb->DirectorySearchPattern.Buffer, L"*", sizeof(WCHAR));
FileName = &Ccb->DirectorySearchPattern;
}
if (!IndexSpecified)
{
if (RestartScan || FirstQuery)
{
FileIndex = Fcb->romfs_inode->spec;
}
else
{
FileIndex = Ccb->CurrentByteOffset;
}
}
if (!(be32_to_cpu(FileIndex) & ROMFH_MASK))
{
if (FirstQuery)
{
Status = STATUS_NO_SUCH_FILE;
}
else
{
Status = STATUS_NO_MORE_FILES;
}
__leave;
}
Inode = (struct romfs_inode*) FsdAllocatePool(
NonPagedPool,
sizeof(struct romfs_inode) + ROMFS_MAXFN,
'4iDR'
);
if (Inode == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(UserBuffer, Length);
switch (FileInformationClass)
{
case FileDirectoryInformation:
if (Length < sizeof(FILE_DIRECTORY_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
__leave;
}
QueryBlockLength = sizeof(FILE_DIRECTORY_INFORMATION);
break;
case FileFullDirectoryInformation:
if (Length < sizeof(FILE_FULL_DIR_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
__leave;
}
QueryBlockLength = sizeof(FILE_FULL_DIR_INFORMATION);
break;
case FileBothDirectoryInformation:
if (Length < sizeof(FILE_BOTH_DIR_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
__leave;
}
QueryBlockLength = sizeof(FILE_BOTH_DIR_INFORMATION);
break;
case FileNamesInformation:
if (Length < sizeof(FILE_NAMES_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
__leave;
}
QueryBlockLength = sizeof(FILE_NAMES_INFORMATION);
break;
#if (VER_PRODUCTBUILD >= 2600)
case FileIdFullDirectoryInformation:
if (Length < sizeof(FILE_ID_FULL_DIR_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
__leave;
}
QueryBlockLength = sizeof(FILE_ID_FULL_DIR_INFORMATION);
break;
case FileIdBothDirectoryInformation:
if (Length < sizeof(FILE_ID_BOTH_DIR_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
__leave;
}
QueryBlockLength = sizeof(FILE_ID_BOTH_DIR_INFORMATION);
break;
#endif // (VER_PRODUCTBUILD >= 2600)
default:
Status = STATUS_INVALID_PARAMETER;
__leave;
}
while (UsedLength < Length
&& (be32_to_cpu(FileIndex) & ROMFH_MASK))
{
Status = FsdReadInodeByIndex(
Vcb->TargetDeviceObject,
FileIndex,
Inode
);
if (!NT_SUCCESS(Status))
{
if (!UsedLength)
{
if (FirstQuery)
{
Status = STATUS_NO_SUCH_FILE;
}
else
{
Status = STATUS_NO_MORE_FILES;
}
}
else
{
Status = STATUS_SUCCESS;
}
__leave;
}
InodeFileNameLength = (USHORT) strnlen(Inode->name, ROMFS_MAXFN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -