fsctl.c

来自「一个类似windows」· C语言 代码 · 共 565 行 · 第 1/2 页

C
565
字号
	  case 255:
	    DPRINT("VolumeDescriptorSetTerminator found!\n");
	    break;

	  default:
	    DPRINT1("Unknown volume descriptor type %u found!\n", VdHeader->VdType);
	    break;
	}
    }

  ExFreePool(Buffer);

  return(STATUS_SUCCESS);
}


static NTSTATUS
CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
		PIRP Irp)
{
  PDEVICE_EXTENSION DeviceExt = NULL;
  PDEVICE_OBJECT NewDeviceObject = NULL;
  PDEVICE_OBJECT DeviceToMount;
  PIO_STACK_LOCATION Stack;
  PFCB Fcb = NULL;
  PCCB Ccb = NULL;
  PVPB Vpb;
  NTSTATUS Status;
  CDINFO CdInfo;

  DPRINT("CdfsMountVolume() called\n");

  if (DeviceObject != CdfsGlobalData->DeviceObject)
    {
      Status = STATUS_INVALID_DEVICE_REQUEST;
      goto ByeBye;
    }

  Stack = IoGetCurrentIrpStackLocation(Irp);
  DeviceToMount = Stack->Parameters.MountVolume.DeviceObject;
  Vpb = Stack->Parameters.MountVolume.Vpb;

  Status = CdfsGetVolumeData(DeviceToMount, &CdInfo);
  if (!NT_SUCCESS(Status))
    {
      goto ByeBye;
    }

  Status = IoCreateDevice(CdfsGlobalData->DriverObject,
			  sizeof(DEVICE_EXTENSION),
			  NULL,
			  FILE_DEVICE_FILE_SYSTEM,
//			  FILE_DEVICE_DISK_FILE_SYSTEM,
			  0,
			  FALSE,
			  &NewDeviceObject);
  if (!NT_SUCCESS(Status))
    goto ByeBye;

  NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO;
  NewDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
  DeviceExt = (PVOID)NewDeviceObject->DeviceExtension;
  RtlZeroMemory(DeviceExt,
		sizeof(DEVICE_EXTENSION));

  Vpb->SerialNumber = CdInfo.SerialNumber;
  Vpb->VolumeLabelLength = CdInfo.VolumeLabelLength;
  RtlCopyMemory(Vpb->VolumeLabel, CdInfo.VolumeLabel, CdInfo.VolumeLabelLength * sizeof(WCHAR));
  RtlCopyMemory(&DeviceExt->CdInfo, &CdInfo, sizeof(CDINFO));

  NewDeviceObject->Vpb = DeviceToMount->Vpb;

  DeviceExt->VolumeDevice = NewDeviceObject;
  DeviceExt->StorageDevice = DeviceToMount;
  DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject;
  DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
  DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
  DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
  DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

  DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL,
							 DeviceExt->StorageDevice);

  Fcb = CdfsCreateFCB(NULL);
  if (Fcb == NULL)
    {
      Status = STATUS_INSUFFICIENT_RESOURCES;
      goto ByeBye;
    }

  Ccb = ExAllocatePoolWithTag(NonPagedPool,
			      sizeof(CCB),
			      TAG_CCB);
  if (Ccb == NULL)
    {
      Status =  STATUS_INSUFFICIENT_RESOURCES;
      goto ByeBye;
    }
  RtlZeroMemory(Ccb,
		sizeof(CCB));

  DeviceExt->StreamFileObject->FsContext = Fcb;
  DeviceExt->StreamFileObject->FsContext2 = Ccb;
  DeviceExt->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
  DeviceExt->StreamFileObject->PrivateCacheMap = NULL;
  DeviceExt->StreamFileObject->Vpb = DeviceExt->Vpb;
  Ccb->PtrFileObject = DeviceExt->StreamFileObject;
  Fcb->FileObject = DeviceExt->StreamFileObject;
  Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice;

  Fcb->Flags = FCB_IS_VOLUME_STREAM;

  Fcb->RFCB.FileSize.QuadPart = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE;
  Fcb->RFCB.ValidDataLength = Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;

  Fcb->Entry.ExtentLocationL = 0;
  Fcb->Entry.DataLengthL = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE;
#ifdef USE_ROS_CC_AND_FS
  Status = CcRosInitializeFileCache(DeviceExt->StreamFileObject,
				    PAGE_SIZE);
  if (!NT_SUCCESS (Status))
    {
      DbgPrint("CcRosInitializeFileCache failed\n");
      goto ByeBye;
    }
#else
  CcInitializeCacheMap(DeviceExt->StreamFileObject,
                       (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
		       TRUE,
		       NULL,
		       NULL);
#endif
  ExInitializeResourceLite(&DeviceExt->VcbResource);
  ExInitializeResourceLite(&DeviceExt->DirResource);

  KeInitializeSpinLock(&DeviceExt->FcbListLock);
  InitializeListHead(&DeviceExt->FcbListHead);

  Status = STATUS_SUCCESS;

ByeBye:
  if (!NT_SUCCESS(Status))
    {
      /* Cleanup */
      if (DeviceExt && DeviceExt->StreamFileObject)
	ObDereferenceObject(DeviceExt->StreamFileObject);
      if (Fcb)
	ExFreePool(Fcb);
      if (Ccb)
	ExFreePool(Ccb);
      if (NewDeviceObject)
	IoDeleteDevice(NewDeviceObject);
    }

  DPRINT("CdfsMountVolume() done (Status: %lx)\n", Status);

  return(Status);
}


static NTSTATUS
CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
		 PIRP Irp)
{
  PDEVICE_EXTENSION DeviceExt;
  PDEVICE_OBJECT DeviceToVerify;
  PIO_STACK_LOCATION Stack;
  NTSTATUS Status;
  CDINFO CdInfo;

  PLIST_ENTRY Entry;
  PFCB Fcb;

  DPRINT1 ("CdfsVerifyVolume() called\n");

#if 0
  if (DeviceObject != CdfsGlobalData->DeviceObject)
    {
      DPRINT1("DeviceObject != CdfsGlobalData->DeviceObject\n");
      return(STATUS_INVALID_DEVICE_REQUEST);
    }
#endif

  DeviceExt = DeviceObject->DeviceExtension;

  Stack = IoGetCurrentIrpStackLocation (Irp);
  DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject;

  ExAcquireResourceExclusiveLite (&DeviceExt->VcbResource,
				  TRUE);

  if (!(DeviceToVerify->Flags & DO_VERIFY_VOLUME))
    {
      DPRINT1 ("Volume has been verified!\n");
      ExReleaseResourceLite (&DeviceExt->VcbResource);
      return STATUS_SUCCESS;
    }

  DPRINT1 ("Device object %p  Device to verify %p\n", DeviceObject, DeviceToVerify);

  Status = CdfsGetVolumeData (DeviceToVerify,
			      &CdInfo);
  if (NT_SUCCESS(Status) &&
      CdInfo.SerialNumber == DeviceToVerify->Vpb->SerialNumber &&
      CdInfo.VolumeLabelLength == DeviceToVerify->Vpb->VolumeLabelLength &&
      !wcsncmp (CdInfo.VolumeLabel, DeviceToVerify->Vpb->VolumeLabel, CdInfo.VolumeLabelLength))
    {
      DPRINT1 ("Same volume!\n");

      /* FIXME: Flush and purge metadata */

      Status = STATUS_SUCCESS;
    }
  else
    {
      DPRINT1 ("Different volume!\n");

      /* FIXME: force volume dismount */
      Entry = DeviceExt->FcbListHead.Flink;
      while (Entry != &DeviceExt->FcbListHead)
	{
	  Fcb = (PFCB)CONTAINING_RECORD(Entry, FCB, FcbListEntry);
	  DPRINT1("OpenFile %S  RefCount %ld\n", Fcb->PathName, Fcb->RefCount);

	  Entry = Entry->Flink;
	}

      Status = STATUS_WRONG_VOLUME;
    }

  DeviceToVerify->Flags &= ~DO_VERIFY_VOLUME;

  ExReleaseResourceLite (&DeviceExt->VcbResource);

  return Status;
}


NTSTATUS STDCALL
CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
		      PIRP Irp)
{
  PIO_STACK_LOCATION Stack;
  NTSTATUS Status;

  DPRINT("CdfsFileSystemControl() called\n");

  Stack = IoGetCurrentIrpStackLocation(Irp);

  switch (Stack->MinorFunction)
    {
      case IRP_MN_USER_FS_REQUEST:
	DPRINT1("CDFS: IRP_MN_USER_FS_REQUEST\n");
	Status = STATUS_INVALID_DEVICE_REQUEST;
	break;

      case IRP_MN_MOUNT_VOLUME:
	DPRINT("CDFS: IRP_MN_MOUNT_VOLUME\n");
	Status = CdfsMountVolume(DeviceObject, Irp);
	break;

      case IRP_MN_VERIFY_VOLUME:
	DPRINT1("CDFS: IRP_MN_VERIFY_VOLUME\n");
	Status = CdfsVerifyVolume(DeviceObject, Irp);
	break;

      default:
	DPRINT1("CDFS FSC: 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 + -
显示快捷键?