dirctl.c
来自「一个类似windows」· C语言 代码 · 共 792 行 · 第 1/2 页
C
792 行
CdfsGetDirectoryInformation(PFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_DIRECTORY_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
DPRINT("CdfsGetDirectoryInformation() called\n");
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength)
return(STATUS_BUFFER_OVERFLOW);
Info->FileNameLength = Length;
Info->NextEntryOffset =
ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, 4);
memcpy(Info->FileName, Fcb->ObjectName, Length);
/* Convert file times */
CdfsDateTimeToSystemTime(Fcb,
&Info->CreationTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->LastAccessTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->LastWriteTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->ChangeTime);
/* Convert file flags */
CdfsFileFlagsToAttributes(Fcb,
&Info->FileAttributes);
if (CdfsFCBIsDirectory(Fcb))
{
Info->EndOfFile.QuadPart = 0LL;
Info->AllocationSize.QuadPart = 0LL;
}
else
{
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
/* Make AllocSize a rounded up multiple of the sector size */
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
}
// Info->FileIndex=;
return(STATUS_SUCCESS);
}
static NTSTATUS
CdfsGetFullDirectoryInformation(PFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_FULL_DIR_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
DPRINT("CdfsGetFullDirectoryInformation() called\n");
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength)
return(STATUS_BUFFER_OVERFLOW);
Info->FileNameLength = Length;
Info->NextEntryOffset =
ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, 4);
memcpy(Info->FileName, Fcb->ObjectName, Length);
/* Convert file times */
CdfsDateTimeToSystemTime(Fcb,
&Info->CreationTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->LastAccessTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->LastWriteTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->ChangeTime);
/* Convert file flags */
CdfsFileFlagsToAttributes(Fcb,
&Info->FileAttributes);
if (CdfsFCBIsDirectory(Fcb))
{
Info->EndOfFile.QuadPart = 0LL;
Info->AllocationSize.QuadPart = 0LL;
}
else
{
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
/* Make AllocSize a rounded up multiple of the sector size */
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
}
// Info->FileIndex=;
Info->EaSize = 0;
return(STATUS_SUCCESS);
}
static NTSTATUS
CdfsGetBothDirectoryInformation(PFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_BOTH_DIR_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
DPRINT("CdfsGetBothDirectoryInformation() called\n");
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength)
return(STATUS_BUFFER_OVERFLOW);
Info->FileNameLength = Length;
Info->NextEntryOffset =
ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, 4);
memcpy(Info->FileName, Fcb->ObjectName, Length);
/* Convert file times */
CdfsDateTimeToSystemTime(Fcb,
&Info->CreationTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->LastAccessTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->LastWriteTime);
CdfsDateTimeToSystemTime(Fcb,
&Info->ChangeTime);
/* Convert file flags */
CdfsFileFlagsToAttributes(Fcb,
&Info->FileAttributes);
if (CdfsFCBIsDirectory(Fcb))
{
Info->EndOfFile.QuadPart = 0LL;
Info->AllocationSize.QuadPart = 0LL;
}
else
{
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
/* Make AllocSize a rounded up multiple of the sector size */
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
}
// Info->FileIndex=;
Info->EaSize = 0;
/* Copy short name */
Info->ShortNameLength = Fcb->ShortNameU.Length;
memcpy(Info->ShortName, Fcb->ShortNameU.Buffer, Fcb->ShortNameU.Length);
return(STATUS_SUCCESS);
}
static NTSTATUS
CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
LONG BufferLength = 0;
PUNICODE_STRING SearchPattern = NULL;
FILE_INFORMATION_CLASS FileInformationClass;
ULONG FileIndex = 0;
PUCHAR Buffer = NULL;
PFILE_NAMES_INFORMATION Buffer0 = NULL;
PFCB Fcb;
PCCB Ccb;
FCB TempFcb;
BOOLEAN First = FALSE;
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("CdfsQueryDirectory() called\n");
DeviceExtension = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
FileObject = Stack->FileObject;
Ccb = (PCCB)FileObject->FsContext2;
Fcb = (PFCB)FileObject->FsContext;
/* Obtain the callers parameters */
BufferLength = Stack->Parameters.QueryDirectory.Length;
SearchPattern = Stack->Parameters.QueryDirectory.FileName;
FileInformationClass =
Stack->Parameters.QueryDirectory.FileInformationClass;
FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
if (SearchPattern != NULL)
{
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
First = TRUE;
Ccb->DirectorySearchPattern.Buffer =
ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR));
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Ccb->DirectorySearchPattern.Length = SearchPattern->Length;
Ccb->DirectorySearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
memcpy(Ccb->DirectorySearchPattern.Buffer,
SearchPattern->Buffer,
SearchPattern->Length);
Ccb->DirectorySearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0;
}
}
else if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
First = TRUE;
Ccb->DirectorySearchPattern.Buffer = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Ccb->DirectorySearchPattern.Length = sizeof(WCHAR);
Ccb->DirectorySearchPattern.MaximumLength = 2 * sizeof(WCHAR);
Ccb->DirectorySearchPattern.Buffer[0] = L'*';
Ccb->DirectorySearchPattern.Buffer[1] = 0;
}
DPRINT("Search pattern '%wZ'\n", &Ccb->DirectorySearchPattern);
/* Determine directory index */
if (Stack->Flags & SL_INDEX_SPECIFIED)
{
Ccb->Entry = Ccb->CurrentByteOffset.u.LowPart;
Ccb->Offset = 0;
}
else if (First || (Stack->Flags & SL_RESTART_SCAN))
{
Ccb->Entry = 0;
Ccb->Offset = 0;
}
/* Determine Buffer for result */
if (Irp->MdlAddress)
{
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
}
else
{
Buffer = Irp->UserBuffer;
}
DPRINT("Buffer = %p tofind = %wZ\n", Buffer, &Ccb->DirectorySearchPattern);
TempFcb.ObjectName = TempFcb.PathName;
while (Status == STATUS_SUCCESS && BufferLength > 0)
{
Status = CdfsFindFile(DeviceExtension,
&TempFcb,
Fcb,
&Ccb->DirectorySearchPattern,
&Ccb->Entry,
&Ccb->Offset);
DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry);
if (NT_SUCCESS(Status))
{
switch (FileInformationClass)
{
case FileNameInformation:
Status = CdfsGetNameInformation(&TempFcb,
DeviceExtension,
(PFILE_NAMES_INFORMATION)Buffer,
BufferLength);
break;
case FileDirectoryInformation:
Status = CdfsGetDirectoryInformation(&TempFcb,
DeviceExtension,
(PFILE_DIRECTORY_INFORMATION)Buffer,
BufferLength);
break;
case FileFullDirectoryInformation:
Status = CdfsGetFullDirectoryInformation(&TempFcb,
DeviceExtension,
(PFILE_FULL_DIR_INFORMATION)Buffer,
BufferLength);
break;
case FileBothDirectoryInformation:
Status = CdfsGetBothDirectoryInformation(&TempFcb,
DeviceExtension,
(PFILE_BOTH_DIR_INFORMATION)Buffer,
BufferLength);
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
}
if (Status == STATUS_BUFFER_OVERFLOW)
{
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
}
break;
}
}
else
{
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
}
if (First)
{
Status = STATUS_NO_SUCH_FILE;
}
else
{
Status = STATUS_NO_MORE_FILES;
}
break;
}
Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
Buffer0->FileIndex = FileIndex++;
Ccb->Entry++;
if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
{
break;
}
BufferLength -= Buffer0->NextEntryOffset;
Buffer += Buffer0->NextEntryOffset;
}
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
}
if (FileIndex > 0)
{
Status = STATUS_SUCCESS;
}
return(Status);
}
NTSTATUS STDCALL
CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION Stack;
NTSTATUS Status;
DPRINT("CdfsDirectoryControl() called\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
switch (Stack->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
Status = CdfsQueryDirectory(DeviceObject,
Irp);
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
DPRINT1("CDFS: MinorFunction %d\n", Stack->MinorFunction);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?