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 + -
显示快捷键?