_Use_decl_annotations_
NTSTATUS
SimBattSetBatteryString (
    PCWSTR String,
    PWCHAR Destination
    )

/*++

Routine Description:

    Set one of the simulated battery strings.

Arguments:

    String - Supplies the new string value to set.

    Destination - Supplies a pointer to the buffer to store the new string.

Return Value:

   NTSTATUS

--*/

{

    PAGED_CODE();

    return RtlStringCchCopyW(Destination, MAX_BATTERY_STRING_SIZE, String);
}
Beispiel #2
0
VOID DokanUnmount(__in PDokanDCB Dcb) {
  ULONG eventLength;
  PEVENT_CONTEXT eventContext;
  PDRIVER_EVENT_CONTEXT driverEventContext;
  PKEVENT completedEvent;
  LARGE_INTEGER timeout;
  PDokanVCB vcb = Dcb->Vcb;
  ULONG deviceNamePos;

  DDbgPrint("==> DokanUnmount\n");

  eventLength = sizeof(EVENT_CONTEXT);
  eventContext = AllocateEventContextRaw(eventLength);

  if (eventContext == NULL) {
    ; // STATUS_INSUFFICIENT_RESOURCES;
    DDbgPrint(" Not able to allocate eventContext.\n");
    if (vcb) {
      DokanEventRelease(vcb->DeviceObject);
    }
    return;
  }

  driverEventContext =
      CONTAINING_RECORD(eventContext, DRIVER_EVENT_CONTEXT, EventContext);
  completedEvent = ExAllocatePool(sizeof(KEVENT));
  if (completedEvent) {
    KeInitializeEvent(completedEvent, NotificationEvent, FALSE);
    driverEventContext->Completed = completedEvent;
  }

  deviceNamePos = Dcb->SymbolicLinkName->Length / sizeof(WCHAR) - 1;
  for (; Dcb->SymbolicLinkName->Buffer[deviceNamePos] != L'\\'; --deviceNamePos)
    ;
  RtlStringCchCopyW(eventContext->Operation.Unmount.DeviceName,
                    sizeof(eventContext->Operation.Unmount.DeviceName) /
                        sizeof(WCHAR),
                    &(Dcb->SymbolicLinkName->Buffer[deviceNamePos]));

  DDbgPrint("  Send Unmount to Service : %ws\n",
            eventContext->Operation.Unmount.DeviceName);

  DokanEventNotification(&Dcb->Global->NotifyService, eventContext);

  if (completedEvent) {
    timeout.QuadPart = -1 * 10 * 1000 * 10; // 10 sec
    KeWaitForSingleObject(completedEvent, Executive, KernelMode, FALSE,
                          &timeout);
  }

  if (vcb) {
    DokanEventRelease(vcb->DeviceObject);
  }

  if (completedEvent) {
    ExFreePool(completedEvent);
  }

  DDbgPrint("<== DokanUnmount\n");
}
Beispiel #3
0
// Initialize a log file related code such as a flushing thread.
_Use_decl_annotations_ static NTSTATUS LogpInitializeBufferInfo(
    const wchar_t *log_file_path, LogBufferInfo *info) {
  PAGED_CODE();
  NT_ASSERT(log_file_path);
  NT_ASSERT(info);

  KeInitializeSpinLock(&info->spin_lock);

  auto status = RtlStringCchCopyW(
      info->log_file_path, RTL_NUMBER_OF_FIELD(LogBufferInfo, log_file_path),
      log_file_path);
  if (!NT_SUCCESS(status)) {
    return status;
  }

  status = ExInitializeResourceLite(&info->resource);
  if (!NT_SUCCESS(status)) {
    return status;
  }
  info->resource_initialized = true;

  // Allocate two log buffers on NonPagedPool.
  info->log_buffer1 = reinterpret_cast<char *>(
      ExAllocatePoolWithTag(NonPagedPoolNx, kLogpBufferSize, kLogpPoolTag));
  if (!info->log_buffer1) {
    LogpFinalizeBufferInfo(info);
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  info->log_buffer2 = reinterpret_cast<char *>(
      ExAllocatePoolWithTag(NonPagedPoolNx, kLogpBufferSize, kLogpPoolTag));
  if (!info->log_buffer2) {
    LogpFinalizeBufferInfo(info);
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  // Initialize these buffers
  RtlFillMemory(info->log_buffer1, kLogpBufferSize, 0xff);  // for diagnostic
  info->log_buffer1[0] = '\0';
  info->log_buffer1[kLogpBufferSize - 1] = '\0';  // at the end

  RtlFillMemory(info->log_buffer2, kLogpBufferSize, 0xff);  // for diagnostic
  info->log_buffer2[0] = '\0';
  info->log_buffer2[kLogpBufferSize - 1] = '\0';  // at the end

  // Buffer should be used is log_buffer1, and location should be written logs
  // is the head of the buffer.
  info->log_buffer_head = info->log_buffer1;
  info->log_buffer_tail = info->log_buffer1;

  status = LogpInitializeLogFile(info);
  if (status == STATUS_OBJECT_PATH_NOT_FOUND) {
    HYPERPLATFORM_LOG_INFO("The log file needs to be activated later.");
    status = STATUS_REINITIALIZATION_NEEDED;
  } else if (!NT_SUCCESS(status)) {
    LogpFinalizeBufferInfo(info);
  }
  return status;
}
Beispiel #4
0
NTSTATUS
IOCTL_GetStatus(
	PIRP pIrp, 
	PULONG pulSize
	)
/*++

Routine Description:

	This routine is called when received IOCTL_DRBDLOCK_GET_STATUS and returns status of drbdlock.

Arguments:

	pIrp - Pointer to the irp of device control.
	pulSize - The size to be retrieved to caller.

Return Value:

	NtStatus values.

--*/
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);	
	PDEVICE_OBJECT pDevice = NULL;
	DRBDLOCK_VOLUME Vol = { 0, };
	PVOID pBuf = pIrp->AssociatedIrp.SystemBuffer;

	if (pBuf == NULL ||
		pIrpStack->Parameters.DeviceIoControl.InputBufferLength < (2 * sizeof(WCHAR)) ||
		pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(BOOLEAN))
	{
		drbdlock_print_log("invalid buffer length, input(%u), output(%u)\n",
			pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
			pIrpStack->Parameters.DeviceIoControl.OutputBufferLength);
		return STATUS_INVALID_PARAMETER;
	}

	Vol.volumeType = VOLUME_TYPE_DEVICE_NAME;
	status = RtlStringCchCopyW(Vol.volumeID.volumeName, DRBDLOCK_VOLUMENAME_MAX_LEN, pBuf);

	if (!NT_SUCCESS(status))
		return status;

	status = ConvertVolume(&Vol, &pDevice);

	if (NT_SUCCESS(status))
	{
		BOOLEAN r = isProtectedVolume(pDevice);

		RtlCopyMemory(pBuf, &r, sizeof(BOOLEAN));

		*pulSize = sizeof(BOOLEAN);
	}

	return status;
}
Beispiel #5
0
NTSTATUS DokanGlobalEventRelease(__in PDEVICE_OBJECT DeviceObject,
                                 __in PIRP Irp) {
  PDOKAN_GLOBAL dokanGlobal;
  PIO_STACK_LOCATION irpSp;
  PDOKAN_UNICODE_STRING_INTERMEDIATE szMountPoint;
  DOKAN_CONTROL dokanControl;
  PMOUNT_ENTRY mountEntry;

  dokanGlobal = DeviceObject->DeviceExtension;
  if (GetIdentifierType(dokanGlobal) != DGL) {
    return STATUS_INVALID_PARAMETER;
  }

  irpSp = IoGetCurrentIrpStackLocation(Irp);

  if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
      sizeof(DOKAN_UNICODE_STRING_INTERMEDIATE)) {
    DDbgPrint(
        "Input buffer is too small (< DOKAN_UNICODE_STRING_INTERMEDIATE)\n");
    return STATUS_BUFFER_TOO_SMALL;
  }
  szMountPoint =
      (PDOKAN_UNICODE_STRING_INTERMEDIATE)Irp->AssociatedIrp.SystemBuffer;
  if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
      sizeof(DOKAN_UNICODE_STRING_INTERMEDIATE) + szMountPoint->MaximumLength) {
    DDbgPrint("Input buffer is too small\n");
    return STATUS_BUFFER_TOO_SMALL;
  }

  RtlZeroMemory(&dokanControl, sizeof(dokanControl));
  RtlStringCchCopyW(dokanControl.MountPoint, MAXIMUM_FILENAME_LENGTH,
                    L"\\DosDevices\\");
  if ((szMountPoint->Length / sizeof(WCHAR)) < 4) {
    dokanControl.MountPoint[12] = towupper(szMountPoint->Buffer[0]);
    dokanControl.MountPoint[13] = L':';
    dokanControl.MountPoint[14] = L'\0';
  } else {
    RtlCopyMemory(&dokanControl.MountPoint[12], szMountPoint->Buffer,
                  szMountPoint->Length);
  }
  mountEntry = FindMountEntry(dokanGlobal, &dokanControl);
  if (mountEntry == NULL) {
    DDbgPrint("Cannot found device associated to mount point %ws\n",
              dokanControl.MountPoint);
    return STATUS_BUFFER_TOO_SMALL;
  }

  return DokanEventRelease(mountEntry->MountControl.DeviceObject);
}
Beispiel #6
0
// start event dispatching
NTSTATUS
DokanEventStart(
    __in PDEVICE_OBJECT DeviceObject,
    __in PIRP Irp
   )
{
	ULONG				outBufferLen;
	ULONG				inBufferLen;
	PVOID				buffer;
	PIO_STACK_LOCATION	irpSp;
	EVENT_START			eventStart;
	PEVENT_DRIVER_INFO	driverInfo;
	PDOKAN_GLOBAL		dokanGlobal;
	PDokanDCB			dcb;
	NTSTATUS			status;
	DEVICE_TYPE			deviceType;
	ULONG				deviceCharacteristics;
	WCHAR				baseGuidString[64];
	GUID				baseGuid = DOKAN_BASE_GUID;
	UNICODE_STRING		unicodeGuid;
	ULONG				deviceNamePos;
	

	DDbgPrint("==> DokanEventStart\n");

	dokanGlobal = DeviceObject->DeviceExtension;
	if (GetIdentifierType(dokanGlobal) != DGL) {
		return STATUS_INVALID_PARAMETER;
	}

	irpSp = IoGetCurrentIrpStackLocation(Irp);

	outBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
	inBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;

	if (outBufferLen != sizeof(EVENT_DRIVER_INFO) ||
		inBufferLen != sizeof(EVENT_START)) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	RtlCopyMemory(&eventStart, Irp->AssociatedIrp.SystemBuffer, sizeof(EVENT_START));
	driverInfo = Irp->AssociatedIrp.SystemBuffer;

	if (eventStart.UserVersion != DOKAN_DRIVER_VERSION) {
		driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;
		driverInfo->Status = DOKAN_START_FAILED;
		Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);
		return STATUS_SUCCESS;
	}

	deviceCharacteristics = FILE_DEVICE_IS_MOUNTED;

	switch (eventStart.DeviceType) {
	case DOKAN_DISK_FILE_SYSTEM:
		deviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
		break;
	case DOKAN_NETWORK_FILE_SYSTEM:
		deviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
		deviceCharacteristics |= FILE_REMOTE_DEVICE;
		break;
	default:
		DDbgPrint("  Unknown device type: %d\n", eventStart.DeviceType);
		deviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
	}

	if (eventStart.Flags & DOKAN_EVENT_REMOVABLE) {
		DDbgPrint("  DeviceCharacteristics |= FILE_REMOVABLE_MEDIA\n");
		deviceCharacteristics |= FILE_REMOVABLE_MEDIA;
	}

	baseGuid.Data2 = (USHORT)(dokanGlobal->MountId & 0xFFFF) ^ baseGuid.Data2;
	baseGuid.Data3 = (USHORT)(dokanGlobal->MountId >> 16) ^ baseGuid.Data3;

	status = RtlStringFromGUID(&baseGuid, &unicodeGuid);
	if (!NT_SUCCESS(status)) {
		return status;
	}
	RtlZeroMemory(baseGuidString, sizeof(baseGuidString));
	RtlStringCchCopyW(baseGuidString, sizeof(baseGuidString) / sizeof(WCHAR), unicodeGuid.Buffer);
	RtlFreeUnicodeString(&unicodeGuid);

	InterlockedIncrement(&dokanGlobal->MountId);

	KeEnterCriticalRegion();
	ExAcquireResourceExclusiveLite(&dokanGlobal->Resource, TRUE);

	status = DokanCreateDiskDevice(
				DeviceObject->DriverObject,
				dokanGlobal->MountId,
				baseGuidString,
				dokanGlobal,
				deviceType,
				deviceCharacteristics,
				&dcb);

	if (!NT_SUCCESS(status)) {
		ExReleaseResourceLite(&dokanGlobal->Resource);
		KeLeaveCriticalRegion();
		return status;
	}

	DDbgPrint("  MountId:%d\n", dcb->MountId);
	driverInfo->DeviceNumber = dokanGlobal->MountId;
	driverInfo->MountId = dokanGlobal->MountId;
	driverInfo->Status = DOKAN_MOUNTED;
	driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;

	// SymbolicName is \\DosDevices\\Global\\Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9}
	// Finds the last '\' and copy into DeviceName.
	// DeviceName is \Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9}
	deviceNamePos = dcb->SymbolicLinkName->Length / sizeof(WCHAR) - 1;
	for (; dcb->SymbolicLinkName->Buffer[deviceNamePos] != L'\\'; --deviceNamePos)
		;
	RtlStringCchCopyW(driverInfo->DeviceName,
			sizeof(driverInfo->DeviceName) / sizeof(WCHAR),
			&(dcb->SymbolicLinkName->Buffer[deviceNamePos]));

	DDbgPrint("  DeviceName:%ws\n", driverInfo->DeviceName);
	DokanUpdateTimeout(&dcb->TickCount, DOKAN_KEEPALIVE_TIMEOUT);

	dcb->UseAltStream = 0;
	if (eventStart.Flags & DOKAN_EVENT_ALTERNATIVE_STREAM_ON) {
		DDbgPrint("  ALT_STREAM_ON\n");
		dcb->UseAltStream = 1;
	}
	dcb->UseKeepAlive = 0;
	if (eventStart.Flags & DOKAN_EVENT_KEEP_ALIVE_ON) {
		DDbgPrint("  KEEP_ALIVE_ON\n");
		dcb->UseKeepAlive = 1;
	}
	dcb->Mounted = 1;

	DokanStartEventNotificationThread(dcb);
	DokanStartCheckThread(dcb);

	ExReleaseResourceLite(&dokanGlobal->Resource);
	KeLeaveCriticalRegion();

	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);

	DDbgPrint("<== DokanEventStart\n");

	return Irp->IoStatus.Status;
}
Beispiel #7
0
NTSTATUS
DiskDeviceControl(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {
  PIO_STACK_LOCATION irpSp;
  PDokanDCB dcb;
  PDokanVCB vcb;
  NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  ULONG outputLength = 0;
  ULONG inputLength = 0;

  DDbgPrint("   => DokanDiskDeviceControl\n");
  irpSp = IoGetCurrentIrpStackLocation(Irp);
  dcb = DeviceObject->DeviceExtension;
  outputLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  inputLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;

  if (GetIdentifierType(dcb) != DCB) {
    PrintIdType(dcb);
    DDbgPrint("   Device is not dcb so go out here\n");
    return STATUS_INVALID_PARAMETER;
  }

  if (IsDeletePending(DeviceObject)) {
    DDbgPrint("   Device object is pending for delete valid anymore\n");
    return STATUS_DEVICE_REMOVED;
  }

  vcb = dcb->Vcb;
  if (IsUnmountPendingVcb(vcb)) {
    DDbgPrint("   Volume is unmounted so ignore dcb requests\n");
    return STATUS_NO_SUCH_DEVICE;
  }

  DDbgPrint("   DiskDeviceControl Device name %wZ \n", dcb->DiskDeviceName);

  switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
    PDISK_GEOMETRY diskGeometry;

    DDbgPrint("  IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
    if (outputLength < sizeof(DISK_GEOMETRY)) {
      Irp->IoStatus.Information = 0;
      status = STATUS_BUFFER_TOO_SMALL;
      break;
    }

    diskGeometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(diskGeometry != NULL);

    DokanPopulateDiskGeometry(diskGeometry);

    Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
    status = STATUS_SUCCESS;
  } break;

  case IOCTL_DISK_GET_LENGTH_INFO: {
    PGET_LENGTH_INFORMATION getLengthInfo;

    DDbgPrint("  IOCTL_DISK_GET_LENGTH_INFO\n");

    if (outputLength < sizeof(GET_LENGTH_INFORMATION)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }

    getLengthInfo = (PGET_LENGTH_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(getLengthInfo != NULL);

    getLengthInfo->Length.QuadPart = 1024 * 1024 * 500;
    status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
  } break;

  case IOCTL_DISK_GET_DRIVE_LAYOUT:
  case IOCTL_DISK_GET_DRIVE_LAYOUT_EX:
  case IOCTL_DISK_GET_PARTITION_INFO:
  case IOCTL_DISK_GET_PARTITION_INFO_EX: {
    // Fake drive layout/partition information

    VOID *outputBuffer = Irp->AssociatedIrp.SystemBuffer;
    ULONG ioctl = irpSp->Parameters.DeviceIoControl.IoControlCode;

    switch (ioctl) {
    case IOCTL_DISK_GET_DRIVE_LAYOUT:
      DDbgPrint("  IOCTL_DISK_GET_DRIVE_LAYOUT\n");
      Irp->IoStatus.Information =
          FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]);
      break;
    case IOCTL_DISK_GET_DRIVE_LAYOUT_EX:
      DDbgPrint("  IOCTL_DISK_GET_DRIVE_LAYOUT_EX\n");
      Irp->IoStatus.Information =
          FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]);
      break;
    case IOCTL_DISK_GET_PARTITION_INFO:
      DDbgPrint("  IOCTL_DISK_GET_PARTITION_INFO\n");
      Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
      break;
    case IOCTL_DISK_GET_PARTITION_INFO_EX:
      DDbgPrint("  IOCTL_DISK_GET_PARTITION_INFO_EX\n");
      Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX);
      break;
    default:
      DDbgPrint("  unknown ioctl %d\n", ioctl);
      break;
    }

    if (outputLength < Irp->IoStatus.Information) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }
    RtlZeroMemory(outputBuffer, Irp->IoStatus.Information);

    // if we are getting the drive layout, then we need to start by
    // adding some of the non-partition stuff that says we have
    // exactly one partition available.
    if (ioctl == IOCTL_DISK_GET_DRIVE_LAYOUT) {
      PDRIVE_LAYOUT_INFORMATION layout;
      layout = (PDRIVE_LAYOUT_INFORMATION)outputBuffer;
      layout->PartitionCount = 1;
      layout->Signature = 1;
      outputBuffer = (PVOID)(layout->PartitionEntry);
      ioctl = IOCTL_DISK_GET_PARTITION_INFO;
    } else if (ioctl == IOCTL_DISK_GET_DRIVE_LAYOUT_EX) {
      PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
      layoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)outputBuffer;
      layoutEx->PartitionStyle = PARTITION_STYLE_MBR;
      layoutEx->PartitionCount = 1;
      layoutEx->Mbr.Signature = 1;
      outputBuffer = (PVOID)(layoutEx->PartitionEntry);
      ioctl = IOCTL_DISK_GET_PARTITION_INFO_EX;
    }

    // NOTE: the local var 'ioctl' is now modified to either EX or
    // non-EX version. the local var 'systemBuffer' is now pointing
    // to the partition information structure.
    if (ioctl == IOCTL_DISK_GET_PARTITION_INFO) {
      PPARTITION_INFORMATION partitionInfo;
      partitionInfo = (PPARTITION_INFORMATION)outputBuffer;
      partitionInfo->RewritePartition = FALSE;
      partitionInfo->RecognizedPartition = FALSE;
      partitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
      partitionInfo->BootIndicator = FALSE;
      partitionInfo->HiddenSectors = 0;
      partitionInfo->StartingOffset.QuadPart = 0;
      partitionInfo->PartitionLength.QuadPart =
          DOKAN_DEFAULT_DISK_SIZE; // Partition size equels disk size here
      partitionInfo->PartitionNumber = 0;
    } else {
      PPARTITION_INFORMATION_EX partitionInfo;
      partitionInfo = (PPARTITION_INFORMATION_EX)outputBuffer;
      partitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
      partitionInfo->RewritePartition = FALSE;
      partitionInfo->Mbr.RecognizedPartition = FALSE;
      partitionInfo->Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
      partitionInfo->Mbr.BootIndicator = FALSE;
      partitionInfo->Mbr.HiddenSectors = 0;
      partitionInfo->StartingOffset.QuadPart = 0;
      partitionInfo->PartitionLength.QuadPart =
          DOKAN_DEFAULT_DISK_SIZE; // Partition size equels disk size here
      partitionInfo->PartitionNumber = 0;
    }

    status = STATUS_SUCCESS;
  } break;

  case IOCTL_DISK_IS_WRITABLE:
    DDbgPrint("  IOCTL_DISK_IS_WRITABLE\n");
    status = IS_DEVICE_READ_ONLY(DeviceObject) ? STATUS_MEDIA_WRITE_PROTECTED
                                               : STATUS_SUCCESS;
    break;

  case IOCTL_DISK_MEDIA_REMOVAL:
    DDbgPrint("  IOCTL_DISK_MEDIA_REMOVAL\n");
    status = STATUS_SUCCESS;
    break;

  case IOCTL_STORAGE_MEDIA_REMOVAL:
    DDbgPrint("  IOCTL_STORAGE_MEDIA_REMOVAL\n");
    status = STATUS_SUCCESS;
    break;

  case IOCTL_DISK_SET_PARTITION_INFO:
    DDbgPrint("  IOCTL_DISK_SET_PARTITION_INFO\n");
    break;

  case IOCTL_DISK_VERIFY:
    DDbgPrint("  IOCTL_DISK_VERIFY\n");
    break;

  case IOCTL_STORAGE_GET_HOTPLUG_INFO: {
    PSTORAGE_HOTPLUG_INFO hotplugInfo;
    DDbgPrint("  IOCTL_STORAGE_GET_HOTPLUG_INFO\n");
    if (outputLength < sizeof(STORAGE_HOTPLUG_INFO)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }
    hotplugInfo = Irp->AssociatedIrp.SystemBuffer;
    hotplugInfo->Size = sizeof(STORAGE_HOTPLUG_INFO);
    hotplugInfo->MediaRemovable = 1;
    hotplugInfo->MediaHotplug = 1;
    hotplugInfo->DeviceHotplug = 1;
    hotplugInfo->WriteCacheEnableOverride = 0;
    status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO);
  } break;

  case IOCTL_VOLUME_GET_GPT_ATTRIBUTES: {
    DDbgPrint("   IOCTL_VOLUME_GET_GPT_ATTRIBUTES\n");
    PVOLUME_GET_GPT_ATTRIBUTES_INFORMATION gptAttrInfo;
    if (outputLength < sizeof(VOLUME_GET_GPT_ATTRIBUTES_INFORMATION)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }
    // Set GPT read-only flag if device is not writable
    gptAttrInfo = Irp->AssociatedIrp.SystemBuffer;
    if (IS_DEVICE_READ_ONLY(DeviceObject))
      gptAttrInfo->GptAttributes = GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY;
    Irp->IoStatus.Information = sizeof(VOLUME_GET_GPT_ATTRIBUTES_INFORMATION);
    status = STATUS_SUCCESS;
  } break;

  case IOCTL_STORAGE_CHECK_VERIFY:
  case IOCTL_DISK_CHECK_VERIFY:
    DDbgPrint("  IOCTL_STORAGE_CHECK_VERIFY\n");
    status = STATUS_SUCCESS;
    break;

  case IOCTL_STORAGE_CHECK_VERIFY2:
    DDbgPrint("  IOCTL_STORAGE_CHECK_VERIFY2\n");
    status = STATUS_SUCCESS;
    break;
  case IOCTL_STORAGE_QUERY_PROPERTY:
    DDbgPrint("  IOCTL_STORAGE_QUERY_PROPERTY\n");
    PSTORAGE_PROPERTY_QUERY query = NULL;
    query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(query != NULL);
    if (query->QueryType == PropertyExistsQuery) {
      if (query->PropertyId == StorageDeviceUniqueIdProperty) {
        PSTORAGE_DEVICE_UNIQUE_IDENTIFIER storage;
        DDbgPrint("    PropertyExistsQuery StorageDeviceUniqueIdProperty\n");
        if (outputLength < sizeof(STORAGE_DEVICE_UNIQUE_IDENTIFIER)) {
          status = STATUS_BUFFER_TOO_SMALL;
          Irp->IoStatus.Information = 0;
          break;
        }
        storage = Irp->AssociatedIrp.SystemBuffer;

        status = STATUS_SUCCESS;
      } else if (query->PropertyId == StorageDeviceWriteCacheProperty) {
        DDbgPrint("    PropertyExistsQuery StorageDeviceWriteCacheProperty\n");
        status = STATUS_NOT_IMPLEMENTED;
      } else {
        DDbgPrint("    PropertyExistsQuery Unknown %d\n", query->PropertyId);
        status = STATUS_NOT_IMPLEMENTED;
      }
    } else if (query->QueryType == PropertyStandardQuery) {
      if (query->PropertyId == StorageDeviceProperty) {
        PSTORAGE_DEVICE_DESCRIPTOR storage;
        DDbgPrint("    PropertyStandardQuery StorageDeviceProperty\n");
        if (outputLength < sizeof(STORAGE_DEVICE_DESCRIPTOR)) {
          status = STATUS_BUFFER_TOO_SMALL;
          Irp->IoStatus.Information = 0;
          break;
        }
        storage = Irp->AssociatedIrp.SystemBuffer;

        status = STATUS_SUCCESS;
      } else if (query->PropertyId == StorageAdapterProperty) {
        DDbgPrint("    PropertyStandardQuery StorageAdapterProperty\n");
        status = STATUS_NOT_IMPLEMENTED;
      } else {
        DDbgPrint("    PropertyStandardQuery Unknown %d\n", query->PropertyId);
        status = STATUS_ACCESS_DENIED;
      }
    } else {
      DDbgPrint("    Unknown query type %d\n", query->QueryType);
      status = STATUS_ACCESS_DENIED;
    }
    break;
  case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: {
    PMOUNTDEV_NAME mountdevName;
    PUNICODE_STRING deviceName = dcb->DiskDeviceName;

    DDbgPrint("   IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n");

    if (outputLength < sizeof(MOUNTDEV_NAME)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
      break;
    }

    mountdevName = (PMOUNTDEV_NAME)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(mountdevName != NULL);
    /* NOTE: When Windows API GetVolumeNameForVolumeMountPoint is called, this
       IO control is called.
       Even if status = STATUS_SUCCESS, GetVolumeNameForVolumeMountPoint can
       returns error
       if it doesn't match cached data from mount manager (looks like).
    */
    RtlZeroMemory(mountdevName, outputLength);
    mountdevName->NameLength = deviceName->Length;

    if (sizeof(USHORT) + mountdevName->NameLength <= outputLength) {
      RtlCopyMemory((PCHAR)mountdevName->Name, deviceName->Buffer,
                    mountdevName->NameLength);
      Irp->IoStatus.Information = sizeof(USHORT) + mountdevName->NameLength;
      status = STATUS_SUCCESS;
      DDbgPrint("  DeviceName %wZ\n", deviceName);
    } else {
      Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
      status = STATUS_BUFFER_OVERFLOW;
    }
  } break;
  case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: {
    PMOUNTDEV_UNIQUE_ID uniqueId;

    DDbgPrint("   IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n");
    if (outputLength < sizeof(MOUNTDEV_UNIQUE_ID)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
      break;
    }

    uniqueId = (PMOUNTDEV_UNIQUE_ID)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(uniqueId != NULL);

    uniqueId->UniqueIdLength = dcb->DiskDeviceName->Length;

    if (sizeof(USHORT) + uniqueId->UniqueIdLength <= outputLength) {
      RtlCopyMemory((PCHAR)uniqueId->UniqueId, dcb->DiskDeviceName->Buffer,
                    uniqueId->UniqueIdLength);
      Irp->IoStatus.Information =
          FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId[0]) +
          uniqueId->UniqueIdLength;
      status = STATUS_SUCCESS;
      DDbgPrint("  UniqueName %wZ\n", dcb->DiskDeviceName);
      break;
    } else {
      Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
      status = STATUS_BUFFER_OVERFLOW;
    }
  } break;
  case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: {
    PMOUNTDEV_SUGGESTED_LINK_NAME linkName;
    DDbgPrint("   IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME\n");

    if (outputLength < sizeof(MOUNTDEV_SUGGESTED_LINK_NAME)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
      break;
    }

    linkName = (PMOUNTDEV_SUGGESTED_LINK_NAME)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(linkName != NULL);

    if (dcb->MountPoint != NULL && dcb->MountPoint->Length > 0) {
      if (IsMountPointDriveLetter(dcb->MountPoint) == STATUS_SUCCESS) {
        linkName->UseOnlyIfThereAreNoOtherLinks = FALSE;
        linkName->NameLength = dcb->MountPoint->Length;

        if (sizeof(USHORT) + linkName->NameLength <= outputLength) {
          RtlCopyMemory((PCHAR)linkName->Name, dcb->MountPoint->Buffer,
                        linkName->NameLength);
          Irp->IoStatus.Information =
              FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME, Name[0]) +
              linkName->NameLength;
          status = STATUS_SUCCESS;
          DDbgPrint("  LinkName %wZ (%d)\n", dcb->MountPoint,
                    dcb->MountPoint->Length);
          break;
        } else {
          Irp->IoStatus.Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
          status = STATUS_BUFFER_OVERFLOW;
        }
      } else {
        DDbgPrint("   MountPoint %wZ is not a drive\n", dcb->MountPoint);
        status = STATUS_NOT_FOUND;
      }
    } else {
      DDbgPrint("   MountPoint is NULL or undefined\n");
      status = STATUS_NOT_FOUND;
    }
  } break;
  case IOCTL_MOUNTDEV_LINK_CREATED: {
    PMOUNTDEV_NAME mountdevName = Irp->AssociatedIrp.SystemBuffer;
    DDbgPrint("   IOCTL_MOUNTDEV_LINK_CREATED\n");

    status = STATUS_SUCCESS;
    if (!IsUnmountPending(DeviceObject) && mountdevName != NULL &&
        mountdevName->NameLength > 0) {
      WCHAR *symbolicLinkNameBuf =
          ExAllocatePool((mountdevName->NameLength + 1) * sizeof(WCHAR));
      if (symbolicLinkNameBuf == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        break;
      }

      RtlZeroMemory(symbolicLinkNameBuf,
                    (mountdevName->NameLength + 1) * sizeof(WCHAR));
      RtlCopyMemory(symbolicLinkNameBuf, mountdevName->Name,
                    mountdevName->NameLength);
      DDbgPrint("   MountDev Name: %ws\n", symbolicLinkNameBuf);

      if (wcsncmp(symbolicLinkNameBuf, L"\\DosDevices\\", 12) == 0) {
        if (dcb->MountPoint != NULL && dcb->MountPoint->Length == 0) {
          ExFreePool(dcb->MountPoint);
          dcb->MountPoint = NULL;
        }

        if (!dcb->MountPoint ||
            ((dcb->MountPoint->Length != mountdevName->NameLength ||
              RtlCompareMemory(mountdevName->Name, dcb->MountPoint->Buffer,
                               mountdevName->NameLength) !=
                  mountdevName->NameLength))) {

          DDbgPrint("   Update mount Point by %ws\n", symbolicLinkNameBuf);
          ExFreePool(dcb->MountPoint);

          dcb->MountPoint = DokanAllocateUnicodeString(symbolicLinkNameBuf);
          if (dcb->DiskDeviceName != NULL) {
            PMOUNT_ENTRY mountEntry;
            PDOKAN_CONTROL dokanControl = ExAllocatePool(sizeof(DOKAN_CONTROL));
            if (dokanControl == NULL) {
              ExFreePool(symbolicLinkNameBuf);
              status = STATUS_INSUFFICIENT_RESOURCES;
              break;
            }
            RtlZeroMemory(dokanControl, sizeof(*dokanControl));
            RtlCopyMemory(dokanControl->DeviceName, dcb->DiskDeviceName->Buffer,
                          dcb->DiskDeviceName->Length);
            if (dcb->UNCName->Buffer != NULL && dcb->UNCName->Length > 0) {
              RtlCopyMemory(dokanControl->UNCName, dcb->UNCName->Buffer,
                            dcb->UNCName->Length);
            }
            mountEntry = FindMountEntry(dcb->Global, dokanControl, TRUE);
            ExFreePool(dokanControl);
            if (mountEntry != NULL) {
              RtlStringCchCopyW(mountEntry->MountControl.MountPoint,
                                MAXIMUM_FILENAME_LENGTH, symbolicLinkNameBuf);
            } else {
              DDbgPrint("   Cannot found associated MountEntry.\n");
            }
          } else {
            DDbgPrint(
                "   DiskDeviceName is null. Is device currently unmounted?\n");
          }
        } else {
          DDbgPrint("   Mount Point match, no need to update it.\n");
        }
      } else {
        DDbgPrint("   Mount Point is not DosDevices, ignored.\n");
      }
      ExFreePool(symbolicLinkNameBuf);
    } else {
      DDbgPrint("   MountDev Name is undefined or unmounting in progress.\n");
    }
  } break;
  case IOCTL_MOUNTDEV_LINK_DELETED: {
    PMOUNTDEV_NAME mountdevName = Irp->AssociatedIrp.SystemBuffer;
    DDbgPrint("   IOCTL_MOUNTDEV_LINK_DELETED\n");
    status = STATUS_SUCCESS;
    if (dcb->UseMountManager) {
      if (mountdevName != NULL && mountdevName->NameLength > 0) {
        WCHAR *symbolicLinkNameBuf =
            ExAllocatePool((mountdevName->NameLength + 1) * sizeof(WCHAR));
        if (symbolicLinkNameBuf == NULL) {
          status = STATUS_INSUFFICIENT_RESOURCES;
          break;
        }

        RtlZeroMemory(symbolicLinkNameBuf,
                      (mountdevName->NameLength + 1) * sizeof(WCHAR));
        RtlCopyMemory(symbolicLinkNameBuf, mountdevName->Name,
                      mountdevName->NameLength);
        DDbgPrint("   MountDev Name: %ws\n", symbolicLinkNameBuf);

        if (dcb->MountPoint != NULL && dcb->MountPoint->Length > 0) {
          // If deleted mount point match user requested mount point, release
          // devices
          if (dcb->MountPoint->Length == mountdevName->NameLength &&
              RtlCompareMemory(mountdevName->Name, dcb->MountPoint->Buffer,
                               mountdevName->NameLength) ==
                  mountdevName->NameLength) {
            status = DokanEventRelease(vcb->DeviceObject, Irp);
          } else {
            DDbgPrint("   Deleted Mount Point doesn't match device excepted "
                      "mount point.\n");
          }
        }
        // Or, if no requested mount point, we assume the first deleted one
        // release devices
        else {
          status = DokanEventRelease(vcb->DeviceObject, Irp);
        }
        ExFreePool(symbolicLinkNameBuf);
      } else {
        DDbgPrint("   MountDev Name is undefined.\n");
      }
    } else {
      DDbgPrint("   Mount Manager is not enabled for this device. Ignored.\n");
    }
  } break;
  // case IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY:
  //    DDbgPrint("   IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY\n");
  //    break;
  case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
    DDbgPrint("   IOCTL_MOUNTDEV_QUERY_STABLE_GUID\n");
    break;
  case IOCTL_VOLUME_ONLINE:
    DDbgPrint("   IOCTL_VOLUME_ONLINE\n");
    status = STATUS_SUCCESS;
    break;
  case IOCTL_VOLUME_OFFLINE:
    DDbgPrint("   IOCTL_VOLUME_OFFLINE\n");
    status = STATUS_SUCCESS;
    break;
  case IOCTL_VOLUME_READ_PLEX:
    DDbgPrint("   IOCTL_VOLUME_READ_PLEX\n");
    break;
  case IOCTL_VOLUME_PHYSICAL_TO_LOGICAL:
    DDbgPrint("   IOCTL_VOLUME_PHYSICAL_TO_LOGICAL\n");
    break;
  case IOCTL_VOLUME_IS_CLUSTERED:
    DDbgPrint("   IOCTL_VOLUME_IS_CLUSTERED\n");
    break;
  case IOCTL_VOLUME_PREPARE_FOR_CRITICAL_IO:
    DDbgPrint("   IOCTL_VOLUME_PREPARE_FOR_CRITICAL_IO\n");
    break;
  case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: {
    PVOLUME_DISK_EXTENTS volume;
    ULONG bufferLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

    DDbgPrint("   IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS\n");
    if (bufferLength < sizeof(VOLUME_DISK_EXTENTS)) {
      status = STATUS_INVALID_PARAMETER;
      Irp->IoStatus.Information = 0;
      break;
    }
    volume = Irp->AssociatedIrp.SystemBuffer;
    RtlZeroMemory(volume, sizeof(VOLUME_DISK_EXTENTS));
    volume->NumberOfDiskExtents = 1;
    Irp->IoStatus.Information = sizeof(VOLUME_DISK_EXTENTS);
    status = STATUS_SUCCESS;
  } break;
  case IOCTL_STORAGE_EJECT_MEDIA: {
    DDbgPrint("   IOCTL_STORAGE_EJECT_MEDIA\n");
    DokanUnmount(dcb);
    status = STATUS_SUCCESS;
  } break;
  case IOCTL_REDIR_QUERY_PATH_EX:
  case IOCTL_REDIR_QUERY_PATH: {
    PQUERY_PATH_RESPONSE pathResp;
    BOOLEAN prefixOk = FALSE;

    if (dcb->UNCName != NULL && dcb->UNCName->Length > 0) {
      if (Irp->RequestorMode != KernelMode) {
        break;
      }

      WCHAR *lpPath = NULL;
      ULONG ulPath = 0;

      if (irpSp->Parameters.DeviceIoControl.IoControlCode ==
          IOCTL_REDIR_QUERY_PATH) {
        PQUERY_PATH_REQUEST pathReq;
        DDbgPrint("  IOCTL_REDIR_QUERY_PATH\n");

        if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
            sizeof(QUERY_PATH_REQUEST)) {
          status = STATUS_BUFFER_OVERFLOW;
          break;
        }

        // Always a METHOD_NEITHER IOCTL
        pathReq = (PQUERY_PATH_REQUEST)
                      irpSp->Parameters.DeviceIoControl.Type3InputBuffer;

        DDbgPrint("   PathNameLength = %d\n", pathReq->PathNameLength);
        DDbgPrint("   SecurityContext = %p\n", pathReq->SecurityContext);
        DDbgPrint("   FilePathName = %.*ls\n",
                  (unsigned int)(pathReq->PathNameLength / sizeof(WCHAR)),
                  pathReq->FilePathName);

        lpPath = pathReq->FilePathName;
        ulPath = pathReq->PathNameLength / sizeof(WCHAR);

        if (pathReq->PathNameLength >= dcb->UNCName->Length / sizeof(WCHAR)) {
          prefixOk = (_wcsnicmp(pathReq->FilePathName, dcb->UNCName->Buffer,
                                dcb->UNCName->Length / sizeof(WCHAR)) == 0);
        }
      } else {
        PQUERY_PATH_REQUEST_EX pathReqEx;
        DDbgPrint("  IOCTL_REDIR_QUERY_PATH_EX\n");

        if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
            sizeof(QUERY_PATH_REQUEST_EX)) {
          status = STATUS_BUFFER_OVERFLOW;
          break;
        }

        // Always a METHOD_NEITHER IOCTL
        pathReqEx = (PQUERY_PATH_REQUEST_EX)
                        irpSp->Parameters.DeviceIoControl.Type3InputBuffer;

        DDbgPrint("   pSecurityContext = %p\n", pathReqEx->pSecurityContext);
        DDbgPrint("   EaLength = %d\n", pathReqEx->EaLength);
        DDbgPrint("   pEaBuffer = %p\n", pathReqEx->pEaBuffer);
        DDbgPrint("   PathNameLength = %d\n", pathReqEx->PathName.Length);
        DDbgPrint("   FilePathName = %*ls\n",
                  (unsigned int)(pathReqEx->PathName.Length / sizeof(WCHAR)),
                  pathReqEx->PathName.Buffer);

        lpPath = pathReqEx->PathName.Buffer;
        ulPath = pathReqEx->PathName.Length / sizeof(WCHAR);

        if (pathReqEx->PathName.Length >= dcb->UNCName->Length) {
          prefixOk =
              (_wcsnicmp(pathReqEx->PathName.Buffer, dcb->UNCName->Buffer,
                         dcb->UNCName->Length / sizeof(WCHAR)) == 0);
        }
      }

      unsigned int i = 1;
      for (;
           i < ulPath && i * sizeof(WCHAR) < dcb->UNCName->Length && !prefixOk;
           ++i) {
        if (_wcsnicmp(&lpPath[i], &dcb->UNCName->Buffer[i], 1) != 0) {
          break;
        }

        if ((i + 1) * sizeof(WCHAR) < dcb->UNCName->Length) {
          prefixOk = (dcb->UNCName->Buffer[i + 1] == L'\\');
        }
      }

      if (!prefixOk) {
        status = STATUS_BAD_NETWORK_PATH;
        break;
      }

      for (; i < ulPath && i * sizeof(WCHAR) < dcb->UNCName->Length && prefixOk;
           ++i) {
        if (_wcsnicmp(&lpPath[i], &dcb->UNCName->Buffer[i], 1) != 0) {
          prefixOk = FALSE;
        }
      }

      if (!prefixOk) {
        status = STATUS_BAD_NETWORK_NAME;
        break;
      }

      pathResp = (PQUERY_PATH_RESPONSE)Irp->UserBuffer;
      pathResp->LengthAccepted = dcb->UNCName->Length;
      status = STATUS_SUCCESS;
    }
  } break;
  case IOCTL_STORAGE_GET_MEDIA_TYPES_EX: {
    PGET_MEDIA_TYPES mediaTypes = NULL;
    PDEVICE_MEDIA_INFO mediaInfo = NULL; //&mediaTypes->MediaInfo[0];

    // We alway return only one media type
    DDbgPrint("  IOCTL_STORAGE_GET_MEDIA_TYPES_EX\n");
    if (outputLength < sizeof(GET_MEDIA_TYPES)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = 0;
      break;
    }

    mediaTypes = (PGET_MEDIA_TYPES)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(mediaTypes != NULL);

    mediaInfo = &mediaTypes->MediaInfo[0];

    mediaTypes->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
    mediaTypes->MediaInfoCount = 1;

    PDISK_GEOMETRY diskGeometry = ExAllocatePool(sizeof(DISK_GEOMETRY));
    if (diskGeometry == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      break;
    }
    RtlZeroMemory(diskGeometry, sizeof(*diskGeometry));
    DokanPopulateDiskGeometry(diskGeometry);
    mediaInfo->DeviceSpecific.DiskInfo.MediaType = diskGeometry->MediaType;
    mediaInfo->DeviceSpecific.DiskInfo.NumberMediaSides = 1;
    mediaInfo->DeviceSpecific.DiskInfo.MediaCharacteristics =
        (MEDIA_CURRENTLY_MOUNTED | MEDIA_READ_WRITE);
    mediaInfo->DeviceSpecific.DiskInfo.Cylinders.QuadPart =
        diskGeometry->Cylinders.QuadPart;
    mediaInfo->DeviceSpecific.DiskInfo.TracksPerCylinder =
        diskGeometry->TracksPerCylinder;
    mediaInfo->DeviceSpecific.DiskInfo.SectorsPerTrack =
        diskGeometry->SectorsPerTrack;
    mediaInfo->DeviceSpecific.DiskInfo.BytesPerSector =
        diskGeometry->BytesPerSector;
    ExFreePool(diskGeometry);

    status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(GET_MEDIA_TYPES);
  } break;
  case IOCTL_STORAGE_GET_DEVICE_NUMBER: {
    PSTORAGE_DEVICE_NUMBER deviceNumber;

    DDbgPrint("  IOCTL_STORAGE_GET_DEVICE_NUMBER\n");

    if (outputLength < sizeof(STORAGE_DEVICE_NUMBER)) {
      status = STATUS_BUFFER_TOO_SMALL;
      Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
      break;
    }

    deviceNumber = (PSTORAGE_DEVICE_NUMBER)Irp->AssociatedIrp.SystemBuffer;
    ASSERT(deviceNumber != NULL);

    deviceNumber->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
    if (vcb) {
      deviceNumber->DeviceType = vcb->DeviceObject->DeviceType;
    }

    deviceNumber->DeviceNumber = 0; // Always one volume only per disk device
    deviceNumber->PartitionNumber = (ULONG)-1; // Not partitionable

    Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
    status = STATUS_SUCCESS;
  } break;

  default:
    PrintUnknownDeviceIoctlCode(
        irpSp->Parameters.DeviceIoControl.IoControlCode);
    status = STATUS_INVALID_DEVICE_REQUEST;
    break;
  }
  DDbgPrint("   <= DokanDiskDeviceControl\n");
  return status;
}
Beispiel #8
0
// start event dispatching
NTSTATUS
DokanEventStart(__in PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) {
  ULONG outBufferLen;
  ULONG inBufferLen;
  PIO_STACK_LOCATION irpSp = NULL;
  PEVENT_START eventStart = NULL;
  PEVENT_DRIVER_INFO driverInfo = NULL;
  PDOKAN_GLOBAL dokanGlobal = NULL;
  PDokanDCB dcb = NULL;
  NTSTATUS status;
  DEVICE_TYPE deviceType;
  ULONG deviceCharacteristics = 0;
  WCHAR *baseGuidString;
  GUID baseGuid = DOKAN_BASE_GUID;
  UNICODE_STRING unicodeGuid;
  ULONG deviceNamePos;
  BOOLEAN useMountManager = FALSE;
  BOOLEAN mountGlobally = TRUE;
  BOOLEAN fileLockUserMode = FALSE;

  DDbgPrint("==> DokanEventStart\n");

  dokanGlobal = DeviceObject->DeviceExtension;
  if (GetIdentifierType(dokanGlobal) != DGL) {
    return STATUS_INVALID_PARAMETER;
  }

  irpSp = IoGetCurrentIrpStackLocation(Irp);

  outBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  inBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;

  eventStart = ExAllocatePool(sizeof(EVENT_START));
  baseGuidString = ExAllocatePool(64 * sizeof(WCHAR));

  if (outBufferLen != sizeof(EVENT_DRIVER_INFO) ||
      inBufferLen != sizeof(EVENT_START) || eventStart == NULL ||
      baseGuidString == NULL) {
    if (eventStart)
      ExFreePool(eventStart);
    if (baseGuidString)
      ExFreePool(baseGuidString);
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  RtlCopyMemory(eventStart, Irp->AssociatedIrp.SystemBuffer,
                sizeof(EVENT_START));
  driverInfo = Irp->AssociatedIrp.SystemBuffer;

  if (eventStart->UserVersion != DOKAN_DRIVER_VERSION) {
    driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;
    driverInfo->Status = DOKAN_START_FAILED;
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);
    ExFreePool(eventStart);
    ExFreePool(baseGuidString);
    return STATUS_SUCCESS;
  }

  switch (eventStart->DeviceType) {
  case DOKAN_DISK_FILE_SYSTEM:
    deviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
    break;
  case DOKAN_NETWORK_FILE_SYSTEM:
    deviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
    deviceCharacteristics |= FILE_REMOTE_DEVICE;
    break;
  default:
    DDbgPrint("  Unknown device type: %d\n", eventStart->DeviceType);
    deviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
  }

  if (eventStart->Flags & DOKAN_EVENT_REMOVABLE) {
    DDbgPrint("  DeviceCharacteristics |= FILE_REMOVABLE_MEDIA\n");
    deviceCharacteristics |= FILE_REMOVABLE_MEDIA;
  }

  if (eventStart->Flags & DOKAN_EVENT_WRITE_PROTECT) {
    DDbgPrint("  DeviceCharacteristics |= FILE_READ_ONLY_DEVICE\n");
    deviceCharacteristics |= FILE_READ_ONLY_DEVICE;
  }

  if (eventStart->Flags & DOKAN_EVENT_MOUNT_MANAGER) {
    DDbgPrint("  Using Mount Manager\n");
    useMountManager = TRUE;
  }

  if (eventStart->Flags & DOKAN_EVENT_CURRENT_SESSION) {
    DDbgPrint("  Mounting on current session only\n");
    mountGlobally = FALSE;
  }

  if (eventStart->Flags & DOKAN_EVENT_FILELOCK_USER_MODE) {
    DDbgPrint("  FileLock in User Mode\n");
    fileLockUserMode = TRUE;
  }

  KeEnterCriticalRegion();
  ExAcquireResourceExclusiveLite(&dokanGlobal->Resource, TRUE);

  DOKAN_CONTROL dokanControl;
  RtlZeroMemory(&dokanControl, sizeof(dokanControl));
  RtlStringCchCopyW(dokanControl.MountPoint, MAXIMUM_FILENAME_LENGTH,
                    L"\\DosDevices\\");
  if (wcslen(eventStart->MountPoint) == 1) {
    dokanControl.MountPoint[12] = towupper(eventStart->MountPoint[0]);
    dokanControl.MountPoint[13] = L':';
    dokanControl.MountPoint[14] = L'\0';
  } else {
    RtlStringCchCatW(dokanControl.MountPoint, MAXIMUM_FILENAME_LENGTH,
                     eventStart->MountPoint);
  }

  DDbgPrint("  Checking for MountPoint %ls \n", dokanControl.MountPoint);
  PMOUNT_ENTRY foundEntry = FindMountEntry(dokanGlobal, &dokanControl, FALSE);
  if (foundEntry != NULL) {
    DDbgPrint("  MountPoint exists already %ls \n", dokanControl.MountPoint);
    driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;
    driverInfo->Status = DOKAN_START_FAILED;
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);
    ExReleaseResourceLite(&dokanGlobal->Resource);
    KeLeaveCriticalRegion();
    ExFreePool(eventStart);
    ExFreePool(baseGuidString);
    return STATUS_SUCCESS;
  }

  baseGuid.Data2 = (USHORT)(dokanGlobal->MountId & 0xFFFF) ^ baseGuid.Data2;
  baseGuid.Data3 = (USHORT)(dokanGlobal->MountId >> 16) ^ baseGuid.Data3;

  status = RtlStringFromGUID(&baseGuid, &unicodeGuid);
  if (!NT_SUCCESS(status)) {
    ExReleaseResourceLite(&dokanGlobal->Resource);
    KeLeaveCriticalRegion();
    ExFreePool(eventStart);
    ExFreePool(baseGuidString);
    return status;
  }
  RtlZeroMemory(baseGuidString, 64 * sizeof(WCHAR));
  RtlStringCchCopyW(baseGuidString, 64,
                    unicodeGuid.Buffer);
  RtlFreeUnicodeString(&unicodeGuid);

  InterlockedIncrement((LONG *)&dokanGlobal->MountId);

  status = DokanCreateDiskDevice(
      DeviceObject->DriverObject, dokanGlobal->MountId, eventStart->MountPoint,
      eventStart->UNCName, baseGuidString, dokanGlobal, deviceType,
      deviceCharacteristics, mountGlobally, useMountManager, &dcb);

  if (!NT_SUCCESS(status)) {
    ExReleaseResourceLite(&dokanGlobal->Resource);
    KeLeaveCriticalRegion();
    ExFreePool(eventStart);
    ExFreePool(baseGuidString);
    return status;
  }

  dcb->FileLockInUserMode = fileLockUserMode;

  DDbgPrint("  MountId:%d\n", dcb->MountId);
  driverInfo->DeviceNumber = dokanGlobal->MountId;
  driverInfo->MountId = dokanGlobal->MountId;
  driverInfo->Status = DOKAN_MOUNTED;
  driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;

  // SymbolicName is
  // \\DosDevices\\Global\\Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9}
  // Finds the last '\' and copy into DeviceName.
  // DeviceName is \Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9}
  deviceNamePos = dcb->SymbolicLinkName->Length / sizeof(WCHAR) - 1;
  for (; dcb->SymbolicLinkName->Buffer[deviceNamePos] != L'\\'; --deviceNamePos)
    ;
  RtlStringCchCopyW(driverInfo->DeviceName,
                    sizeof(driverInfo->DeviceName) / sizeof(WCHAR),
                    &(dcb->SymbolicLinkName->Buffer[deviceNamePos]));

  // Set the irp timeout in milliseconds
  // If the IrpTimeout is 0, we assume that the value was not changed
  dcb->IrpTimeout = DOKAN_IRP_PENDING_TIMEOUT;
  if (eventStart->IrpTimeout > 0) {
    if (eventStart->IrpTimeout > DOKAN_IRP_PENDING_TIMEOUT_RESET_MAX) {
      eventStart->IrpTimeout = DOKAN_IRP_PENDING_TIMEOUT_RESET_MAX;
    }

    if (eventStart->IrpTimeout < DOKAN_IRP_PENDING_TIMEOUT) {
      eventStart->IrpTimeout = DOKAN_IRP_PENDING_TIMEOUT;
    }
    dcb->IrpTimeout = eventStart->IrpTimeout;
  }

  DDbgPrint("  DeviceName:%ws\n", driverInfo->DeviceName);

  dcb->UseAltStream = 0;
  if (eventStart->Flags & DOKAN_EVENT_ALTERNATIVE_STREAM_ON) {
    DDbgPrint("  ALT_STREAM_ON\n");
    dcb->UseAltStream = 1;
  }

  DokanStartEventNotificationThread(dcb);

  ExReleaseResourceLite(&dokanGlobal->Resource);
  KeLeaveCriticalRegion();

  IoVerifyVolume(dcb->DeviceObject, FALSE);

  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);

  ExFreePool(eventStart);
  ExFreePool(baseGuidString);

  DDbgPrint("<== DokanEventStart\n");

  return Irp->IoStatus.Status;
}
Beispiel #9
0
static PNTOS_INSTALLATION
AddNTOSInstallation(
    IN PGENERIC_LIST List,
    IN PCWSTR InstallationName,
    IN USHORT Machine,
    IN PCWSTR VendorName,
    IN PCWSTR SystemRootArcPath,
    IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
    IN PCWSTR PathComponent,    // Pointer inside SystemRootNtPath buffer
    IN ULONG DiskNumber,
    IN ULONG PartitionNumber,
    IN PPARTENTRY PartEntry OPTIONAL)
{
    PNTOS_INSTALLATION NtOsInstall;
    SIZE_T ArcPathLength, NtPathLength;

    /* Is there already any installation with these settings? */
    NtOsInstall = FindExistingNTOSInstall(List, SystemRootArcPath, SystemRootNtPath);
    if (NtOsInstall)
    {
        DPRINT1("An NTOS installation with name \"%S\" from vendor \"%S\" already exists on disk #%d, partition #%d, in SystemRoot '%wZ'\n",
                NtOsInstall->InstallationName, NtOsInstall->VendorName,
                NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber, &NtOsInstall->SystemNtPath);
        //
        // NOTE: We may use its "IsDefault" attribute, and only keep the entries that have IsDefault == TRUE...
        // Setting IsDefault to TRUE would imply searching for the "Default" entry in the loader configuration file.
        //
        return NtOsInstall;
    }

    ArcPathLength = (wcslen(SystemRootArcPath) + 1) * sizeof(WCHAR);
    // NtPathLength  = ROUND_UP(SystemRootNtPath->Length + sizeof(UNICODE_NULL), sizeof(WCHAR));
    NtPathLength  = SystemRootNtPath->Length + sizeof(UNICODE_NULL);

    /* None was found, so add a new one */
    NtOsInstall = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY,
                                  sizeof(*NtOsInstall) +
                                  ArcPathLength + NtPathLength);
    if (!NtOsInstall)
        return NULL;

    NtOsInstall->DiskNumber = DiskNumber;
    NtOsInstall->PartitionNumber = PartitionNumber;
    NtOsInstall->PartEntry = PartEntry;

    NtOsInstall->Machine = Machine;

    RtlInitEmptyUnicodeString(&NtOsInstall->SystemArcPath,
                              (PWCHAR)(NtOsInstall + 1),
                              ArcPathLength);
    RtlCopyMemory(NtOsInstall->SystemArcPath.Buffer, SystemRootArcPath, ArcPathLength);
    NtOsInstall->SystemArcPath.Length = ArcPathLength - sizeof(UNICODE_NULL);

    RtlInitEmptyUnicodeString(&NtOsInstall->SystemNtPath,
                              (PWCHAR)((ULONG_PTR)(NtOsInstall + 1) + ArcPathLength),
                              NtPathLength);
    RtlCopyUnicodeString(&NtOsInstall->SystemNtPath, SystemRootNtPath);
    NtOsInstall->PathComponent = NtOsInstall->SystemNtPath.Buffer +
                                    (PathComponent - SystemRootNtPath->Buffer);

    RtlStringCchCopyW(NtOsInstall->InstallationName,
                      ARRAYSIZE(NtOsInstall->InstallationName),
                      InstallationName);

    RtlStringCchCopyW(NtOsInstall->VendorName,
                      ARRAYSIZE(NtOsInstall->VendorName),
                      VendorName);

    AppendGenericListEntry(List, NtOsInstall, FALSE);

    return NtOsInstall;
}
Beispiel #10
0
NTSTATUS
DokanCreateDiskDevice(__in PDRIVER_OBJECT DriverObject, __in ULONG MountId,
                      __in PWCHAR MountPoint, __in PWCHAR UNCName,
                      __in PWCHAR BaseGuid, __in PDOKAN_GLOBAL DokanGlobal,
                      __in DEVICE_TYPE DeviceType,
                      __in ULONG DeviceCharacteristics,
                      __in BOOLEAN UseMountManager, __out PDokanDCB *Dcb) {
  WCHAR diskDeviceNameBuf[MAXIMUM_FILENAME_LENGTH];
  WCHAR symbolicLinkNameBuf[MAXIMUM_FILENAME_LENGTH];
  WCHAR mountPointBuf[MAXIMUM_FILENAME_LENGTH];
  PDEVICE_OBJECT diskDeviceObject;
  PDEVICE_OBJECT volDeviceObject;
  PDokanDCB dcb;
  PDokanVCB vcb;
  UNICODE_STRING diskDeviceName;
  NTSTATUS status;
  BOOLEAN isNetworkFileSystem = (DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM);
  DOKAN_CONTROL dokanControl;

  // make DeviceName and SymboliLink
  if (isNetworkFileSystem) {
#ifdef DOKAN_NET_PROVIDER
    RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_NET_DEVICE_NAME);
    RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_NET_SYMBOLIC_LINK_NAME);
#else
    RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_NET_DEVICE_NAME);
    RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
    RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_NET_SYMBOLIC_LINK_NAME);
    RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
#endif

  } else {
    RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_DISK_DEVICE_NAME);
    RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
    RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_SYMBOLIC_LINK_NAME);
    RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
  }

  RtlInitUnicodeString(&diskDeviceName, diskDeviceNameBuf);

  //
  // Create DeviceObject for the Disk Device
  //
  if (!isNetworkFileSystem) {
    status =
        IoCreateDeviceSecure(DriverObject,          // DriverObject
                             sizeof(DokanDCB),      // DeviceExtensionSize
                             &diskDeviceName,       // DeviceName
                             FILE_DEVICE_DISK,      // DeviceType
                             DeviceCharacteristics, // DeviceCharacteristics
                             FALSE,                 // Not Exclusive
                             &sddl,                 // Default SDDL String
                             NULL,                  // Device Class GUID
                             &diskDeviceObject);    // DeviceObject
  } else {
    status = IoCreateDevice(DriverObject,          // DriverObject
                            sizeof(DokanDCB),      // DeviceExtensionSize
                            NULL,                  // DeviceName
                            FILE_DEVICE_UNKNOWN,   // DeviceType
                            DeviceCharacteristics, // DeviceCharacteristics
                            FALSE,                 // Not Exclusive
                            &diskDeviceObject);    // DeviceObject
  }

  if (!NT_SUCCESS(status)) {
    DDbgPrint("  %s failed: 0x%x\n",
              isNetworkFileSystem ? "IoCreateDevice(FILE_DEVICE_UNKNOWN)"
                                  : "IoCreateDeviceSecure(FILE_DEVICE_DISK)",
              status);
    return status;
  }

  //
  // Initialize the device extension.
  //
  dcb = diskDeviceObject->DeviceExtension;
  *Dcb = dcb;
  dcb->DeviceObject = diskDeviceObject;
  dcb->Global = DokanGlobal;

  dcb->Identifier.Type = DCB;
  dcb->Identifier.Size = sizeof(DokanDCB);

  dcb->MountId = MountId;
  dcb->DeviceType = FILE_DEVICE_DISK;
  dcb->DeviceCharacteristics = DeviceCharacteristics;
  KeInitializeEvent(&dcb->KillEvent, NotificationEvent, FALSE);

  //
  // Establish user-buffer access method.
  //
  diskDeviceObject->Flags |= DO_DIRECT_IO;

  // initialize Event and Event queue
  DokanInitIrpList(&dcb->PendingIrp);
  DokanInitIrpList(&dcb->PendingEvent);
  DokanInitIrpList(&dcb->NotifyEvent);

  KeInitializeEvent(&dcb->ReleaseEvent, NotificationEvent, FALSE);

  // "0" means not mounted
  dcb->Mounted = 0;

  ExInitializeResourceLite(&dcb->Resource);

  dcb->CacheManagerNoOpCallbacks.AcquireForLazyWrite = &DokanNoOpAcquire;
  dcb->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &DokanNoOpRelease;
  dcb->CacheManagerNoOpCallbacks.AcquireForReadAhead = &DokanNoOpAcquire;
  dcb->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &DokanNoOpRelease;

  dcb->UseMountManager = UseMountManager;
  if (wcscmp(MountPoint, L"") != 0) {
    RtlStringCchCopyW(mountPointBuf, MAXIMUM_FILENAME_LENGTH,
                      L"\\DosDevices\\");
    if (wcslen(MountPoint) < 4) {
      mountPointBuf[12] = towupper(MountPoint[0]);
      mountPointBuf[13] = L':';
      mountPointBuf[14] = L'\0';
      if (isNetworkFileSystem) {
        dcb->UseMountManager = FALSE;
      }
    } else {
      dcb->UseMountManager = FALSE;
      RtlStringCchCatW(mountPointBuf, MAXIMUM_FILENAME_LENGTH, MountPoint);
    }
  } else {
    RtlStringCchCopyW(mountPointBuf, MAXIMUM_FILENAME_LENGTH, L"");
  }

  dcb->DiskDeviceName = DokanAllocateUnicodeString(diskDeviceNameBuf);
  dcb->SymbolicLinkName = DokanAllocateUnicodeString(symbolicLinkNameBuf);
  dcb->MountPoint = DokanAllocateUnicodeString(mountPointBuf);
  if (UNCName != NULL) {
    dcb->UNCName = DokanAllocateUnicodeString(UNCName);
  }

  if (dcb->DiskDeviceName == NULL || dcb->SymbolicLinkName == NULL ||
      dcb->MountPoint == NULL || (dcb->UNCName == NULL && UNCName != NULL)) {
    DDbgPrint("  Failed to allocate memory for device naming");
    FreeDcbNames(dcb);
    ExDeleteResourceLite(&dcb->Resource);
    IoDeleteDevice(diskDeviceObject);
    return STATUS_INSUFFICIENT_RESOURCES;
  }
  DDbgPrint("DiskDeviceName: %wZ - SymbolicLinkName: %wZ - MountPoint: %wZ\n",
            dcb->DiskDeviceName, dcb->SymbolicLinkName, dcb->MountPoint);

  DDbgPrint("  IoCreateDevice DeviceType: %d\n", DeviceType);

  // Directly create volume device and init vcb here because it has strong
  // dependency with fs/disk
  // Otherwise we would have done this work when mounting the volume

  if (!isNetworkFileSystem) {
    status = IoCreateDevice(DriverObject,          // DriverObject
                            sizeof(DokanVCB),      // DeviceExtensionSize
                            NULL,                  // DeviceName
                            DeviceType,            // DeviceType
                            DeviceCharacteristics, // DeviceCharacteristics
                            FALSE,                 // Not Exclusive
                            &volDeviceObject);     // DeviceObject
  } else {
    status =
        IoCreateDeviceSecure(DriverObject,          // DriverObject
                             sizeof(DokanVCB),      // DeviceExtensionSize
                             &diskDeviceName,       // DeviceName
                             DeviceType,            // DeviceType
                             DeviceCharacteristics, // DeviceCharacteristics
                             FALSE,                 // Not Exclusive
                             &sddl,                 // Default SDDL String
                             NULL,                  // Device Class GUID
                             &volDeviceObject);     // DeviceObject
  }

  if (!NT_SUCCESS(status)) {
    DDbgPrint("  IoCreateDevice failed: 0x%x\n", status);
    ExDeleteResourceLite(&dcb->Resource);
    IoDeleteDevice(diskDeviceObject);
    FreeDcbNames(dcb);
    return status;
  }

  vcb = volDeviceObject->DeviceExtension;
  vcb->Identifier.Type = VCB;
  vcb->Identifier.Size = sizeof(DokanVCB);

  vcb->DeviceObject = volDeviceObject;
  vcb->Dcb = dcb;
  dcb->Vcb = vcb;

  InitializeListHead(&vcb->NextFCB);

  InitializeListHead(&vcb->DirNotifyList);
  FsRtlNotifyInitializeSync(&vcb->NotifySync);

  ExInitializeFastMutex(&vcb->AdvancedFCBHeaderMutex);

#if _WIN32_WINNT >= 0x0501
  FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader,
                           &vcb->AdvancedFCBHeaderMutex);
#else
  if (DokanFsRtlTeardownPerStreamContexts) {
    FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader,
                             &vcb->AdvancedFCBHeaderMutex);
  }
#endif

  //
  // Create a symbolic link for userapp to interact with the driver.
  //
  status = IoCreateSymbolicLink(dcb->SymbolicLinkName, dcb->DiskDeviceName);

  if (!NT_SUCCESS(status)) {
    ExDeleteResourceLite(&dcb->Resource);
    IoDeleteDevice(diskDeviceObject);
    FreeDcbNames(dcb);
    DDbgPrint("  IoCreateSymbolicLink returned 0x%x\n", status);
    return status;
  }
  DDbgPrint("SymbolicLink: %wZ -> %wZ created\n", dcb->SymbolicLinkName,
            dcb->DiskDeviceName);

  //
  // Establish user-buffer access method.
  //
  volDeviceObject->Flags |= DO_DIRECT_IO;

  DokanInitVpb(diskDeviceObject->Vpb, diskDeviceObject, volDeviceObject);

  // Mark devices as initialized
  diskDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  volDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

  ObReferenceObject(volDeviceObject);
  ObReferenceObject(diskDeviceObject);

  // DokanRegisterMountedDeviceInterface(diskDeviceObject, dcb);

  // Save to the global mounted list
  RtlZeroMemory(&dokanControl, sizeof(dokanControl));
  RtlStringCchCopyW(dokanControl.DeviceName,
                    sizeof(dokanControl.DeviceName) / sizeof(WCHAR),
                    diskDeviceNameBuf);
  RtlStringCchCopyW(dokanControl.MountPoint,
                    sizeof(dokanControl.MountPoint) / sizeof(WCHAR),
                    mountPointBuf);
  dokanControl.Type = DeviceType;
  dokanControl.DeviceObject = volDeviceObject;
  InsertMountEntry(DokanGlobal, &dokanControl);

  dcb->Mounted = 1;

  if (dcb->UseMountManager) {
    status = DokanSendVolumeArrivalNotification(dcb->DiskDeviceName);
    if (!NT_SUCCESS(status)) {
      DDbgPrint("  DokanSendVolumeArrivalNotification failed: 0x%x\n", status);
      if (diskDeviceObject->Vpb) {
        diskDeviceObject->Vpb->DeviceObject = NULL;
        diskDeviceObject->Vpb->RealDevice = NULL;
        diskDeviceObject->Vpb->Flags = 0;
      }
      ExDeleteResourceLite(&dcb->Resource);
      IoDeleteDevice(diskDeviceObject);
      FreeDcbNames(dcb);
      return status;
    }
  }

  DokanCreateMountPoint(dcb);

  if (isNetworkFileSystem) {
    // Run FsRtlRegisterUncProvider in System thread.
    HANDLE handle;
    PKTHREAD thread;
    OBJECT_ATTRIBUTES objectAttribs;

    InitializeObjectAttributes(&objectAttribs, NULL, OBJ_KERNEL_HANDLE, NULL,
                               NULL);
    status = PsCreateSystemThread(
        &handle, THREAD_ALL_ACCESS, &objectAttribs, NULL, NULL,
        (PKSTART_ROUTINE)DokanRegisterUncProvider, dcb);
    if (!NT_SUCCESS(status)) {
      DDbgPrint("PsCreateSystemThread failed: 0x%X\n", status);
    } else {
      ObReferenceObjectByHandle(handle, THREAD_ALL_ACCESS, NULL, KernelMode,
                                &thread, NULL);
      ZwClose(handle);
      KeWaitForSingleObject(thread, Executive, KernelMode, FALSE, NULL);
      ObDereferenceObject(thread);
    }
  }
  // DokanRegisterDeviceInterface(DriverObject, diskDeviceObject, dcb);

  return STATUS_SUCCESS;
}
Beispiel #11
0
NTSTATUS
FileDiskQueryPnpDeviceText(
    __in PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension,
    __in DEVICE_TEXT_TYPE DeviceTextType,
    __in LCID Locale,
    __in PWCHAR* DeviceText)
{
    NTSTATUS status;
    PFILEDISK_EXTENSION fileDiskExtension;
    size_t filePathLength;
    static CONST WCHAR FILEDISK_DEVICE_TEXT[] = L"NDAS Virtual File Disk";

    fileDiskExtension = FileDiskGetExtension(LogicalUnitExtension);

    switch (DeviceTextType)
    {
    case DeviceTextDescription:

        *DeviceText = (PWCHAR) ExAllocatePoolWithTag(
                          PagedPool,
                          sizeof(FILEDISK_DEVICE_TEXT),
                          FILEDISK_PNP_TAG);

        if (NULL == *DeviceText)
        {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        status = RtlStringCchCopyW(
                     *DeviceText,
                     countof(FILEDISK_DEVICE_TEXT),
                     FILEDISK_DEVICE_TEXT);

        ASSERT(NT_SUCCESS(status));
        return status;

    case DeviceTextLocationInformation:

        filePathLength = fileDiskExtension->FilePath.Length;
        filePathLength += sizeof(WCHAR); // additional NULL

        *DeviceText = ExAllocatePoolWithTag(
                          PagedPool,
                          filePathLength,
                          FILEDISK_PNP_TAG);

        if (NULL == *DeviceText)
        {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        status = RtlStringCbCopyW(
                     *DeviceText,
                     filePathLength,
                     fileDiskExtension->FilePath.Buffer);

        ASSERT(NT_SUCCESS(status));

        return status;
    default:
        return STATUS_NOT_SUPPORTED;
    }
}
Beispiel #12
0
NTSTATUS
DokanDispatchFileSystemControl(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)
{
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	PIO_STACK_LOCATION	irpSp;
	PDokanVCB			vcb;

	PAGED_CODE();

	__try {
		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanFileSystemControl\n");
		DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));

		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB) {
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		irpSp = IoGetCurrentIrpStackLocation(Irp);

		switch(irpSp->MinorFunction) {
		case IRP_MN_KERNEL_CALL:
			DDbgPrint("	 IRP_MN_KERNEL_CALL\n");
			break;

		case IRP_MN_LOAD_FILE_SYSTEM:
			DDbgPrint("	 IRP_MN_LOAD_FILE_SYSTEM\n");
			break;

		case IRP_MN_MOUNT_VOLUME:
			{
				PVPB vpb;
				DDbgPrint("	 IRP_MN_MOUNT_VOLUME\n");
				if (irpSp->Parameters.MountVolume.DeviceObject != vcb->Dcb->DeviceObject) {
					DDbgPrint("   Not DokanDiskDevice\n");
					status = STATUS_INVALID_PARAMETER;
				}
				vpb = irpSp->Parameters.MountVolume.Vpb;
				vpb->DeviceObject = vcb->DeviceObject;
				vpb->RealDevice = vcb->DeviceObject;
				vpb->Flags |= VPB_MOUNTED;
				vpb->VolumeLabelLength = wcslen(VOLUME_LABEL) * sizeof(WCHAR);
				RtlStringCchCopyW(vpb->VolumeLabel, sizeof(vpb->VolumeLabel) / sizeof(WCHAR), VOLUME_LABEL);
				vpb->SerialNumber = 0x19831116;
				status = STATUS_SUCCESS;
			}
			break;

		case IRP_MN_USER_FS_REQUEST:
			DDbgPrint("	 IRP_MN_USER_FS_REQUEST\n");
			status = DokanUserFsRequest(DeviceObject, Irp);
			break;

		case IRP_MN_VERIFY_VOLUME:
			DDbgPrint("	 IRP_MN_VERIFY_VOLUME\n");
			break;

		default:
			DDbgPrint("  unknown %d\n", irpSp->MinorFunction);
			status = STATUS_INVALID_PARAMETER;
			break;

		}

	} __finally {
		
		Irp->IoStatus.Status = status;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);

		DokanPrintNTStatus(status);
		DDbgPrint("<== DokanFileSystemControl\n");

		FsRtlExitFileSystem();
	}

	return status;
}
Beispiel #13
0
NTSTATUS
DokanCreateDiskDevice(
	__in PDRIVER_OBJECT DriverObject,
	__in ULONG			MountId,
	__in PWCHAR			BaseGuid,
	__in PDOKAN_GLOBAL	DokanGlobal,
	__in DEVICE_TYPE	DeviceType,
	__in ULONG			DeviceCharacteristics,
	__out PDokanDCB*	Dcb
	)
{
	WCHAR				diskDeviceNameBuf[MAXIMUM_FILENAME_LENGTH];
	WCHAR				fsDeviceNameBuf[MAXIMUM_FILENAME_LENGTH];
	WCHAR				symbolicLinkNameBuf[MAXIMUM_FILENAME_LENGTH];
	PDEVICE_OBJECT		diskDeviceObject;
	PDEVICE_OBJECT		fsDeviceObject;
	PDokanDCB			dcb;
	PDokanVCB			vcb;
	UNICODE_STRING		diskDeviceName;
	NTSTATUS			status;
	BOOLEAN				isNetworkFileSystem = (DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM);

	// make DeviceName and SymboliLink
	if (isNetworkFileSystem) {
#ifdef DOKAN_NET_PROVIDER
		RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME);
		RtlStringCchCopyW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME);
		RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_SYMBOLIC_LINK_NAME);
#else
		RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME);
		RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
		RtlStringCchCopyW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME);
		RtlStringCchCatW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
		RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_SYMBOLIC_LINK_NAME);
		RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
#endif

	} else {
		RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_DISK_DEVICE_NAME);
		RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
		RtlStringCchCopyW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_FS_DEVICE_NAME);
		RtlStringCchCatW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
		RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_SYMBOLIC_LINK_NAME);
		RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
	}
	
	RtlInitUnicodeString(&diskDeviceName, diskDeviceNameBuf);

	//
	// make a DeviceObject for Disk Device
	//
	if (!isNetworkFileSystem) {
		status = IoCreateDeviceSecure(
					DriverObject,		// DriverObject
					sizeof(DokanDCB),	// DeviceExtensionSize
					&diskDeviceName,	// DeviceName
					FILE_DEVICE_DISK,	// DeviceType
					DeviceCharacteristics,	// DeviceCharacteristics
					FALSE,				// Not Exclusive
					&sddl, // Default SDDL String
					NULL,				// Device Class GUID
					&diskDeviceObject); // DeviceObject
	} else {
		status = IoCreateDevice(
					DriverObject,			// DriverObject
					sizeof(DokanDCB),		// DeviceExtensionSize
					NULL,					// DeviceName
					FILE_DEVICE_UNKNOWN,	// DeviceType
					DeviceCharacteristics,	// DeviceCharacteristics
					FALSE,					// Not Exclusive
					&diskDeviceObject);		// DeviceObject
	}


	if (!NT_SUCCESS(status)) {
		DDbgPrint("  IoCreateDevice (DISK_DEVICE) failed: 0x%x\n", status);
		return status;
	}
	DDbgPrint("DokanDiskDevice: %wZ created\n", &diskDeviceName);

	//
	// Initialize the device extension.
	//
	dcb = diskDeviceObject->DeviceExtension;
	*Dcb = dcb;
	dcb->DeviceObject = diskDeviceObject;
	dcb->Global = DokanGlobal;

	dcb->Identifier.Type = DCB;
	dcb->Identifier.Size = sizeof(DokanDCB);

	dcb->MountId = MountId;
	dcb->DeviceType = FILE_DEVICE_DISK;
	dcb->DeviceCharacteristics = DeviceCharacteristics;
	KeInitializeEvent(&dcb->KillEvent, NotificationEvent, FALSE);

	//
	// Establish user-buffer access method.
	//
	diskDeviceObject->Flags |= DO_DIRECT_IO;

	// initialize Event and Event queue
	DokanInitIrpList(&dcb->PendingIrp);
	DokanInitIrpList(&dcb->PendingEvent);
	DokanInitIrpList(&dcb->NotifyEvent);

	KeInitializeEvent(&dcb->ReleaseEvent, NotificationEvent, FALSE);

	// "0" means not mounted
	dcb->Mounted = 0;

	ExInitializeResourceLite(&dcb->Resource);

	dcb->CacheManagerNoOpCallbacks.AcquireForLazyWrite  = &DokanNoOpAcquire;
	dcb->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &DokanNoOpRelease;
	dcb->CacheManagerNoOpCallbacks.AcquireForReadAhead  = &DokanNoOpAcquire;
	dcb->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &DokanNoOpRelease;

	dcb->SymbolicLinkName = AllocateUnicodeString(symbolicLinkNameBuf);
	dcb->DiskDeviceName =  AllocateUnicodeString(diskDeviceNameBuf);
	dcb->FileSystemDeviceName = AllocateUnicodeString(fsDeviceNameBuf);

	status = IoCreateDeviceSecure(
				DriverObject,		// DriverObject
				sizeof(DokanVCB),	// DeviceExtensionSize
				dcb->FileSystemDeviceName, // DeviceName
				DeviceType,			// DeviceType
				DeviceCharacteristics,	// DeviceCharacteristics
				FALSE,				// Not Exclusive
				&sddl, // Default SDDL String
				NULL,				// Device Class GUID
				&fsDeviceObject);	// DeviceObject

	if (!NT_SUCCESS(status)) {
		DDbgPrint("  IoCreateDevice (FILE_SYSTEM_DEVICE) failed: 0x%x\n", status);
		IoDeleteDevice(diskDeviceObject);
		return status;
	}
	DDbgPrint("DokanFileSystemDevice: %wZ created\n", dcb->FileSystemDeviceName);

	vcb = fsDeviceObject->DeviceExtension;

	vcb->Identifier.Type = VCB;
	vcb->Identifier.Size = sizeof(DokanVCB);

	vcb->DeviceObject = fsDeviceObject;
	vcb->Dcb = dcb;

	dcb->Vcb = vcb;
	
	InitializeListHead(&vcb->NextFCB);

	InitializeListHead(&vcb->DirNotifyList);
	FsRtlNotifyInitializeSync(&vcb->NotifySync);

	ExInitializeFastMutex(&vcb->AdvancedFCBHeaderMutex);
#if _WIN32_WINNT >= 0x0501
	FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader, &vcb->AdvancedFCBHeaderMutex);
#else
	if (DokanFsRtlTeardownPerStreamContexts) {
		FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader, &vcb->AdvancedFCBHeaderMutex);
	}
#endif


	//
	// Establish user-buffer access method.
	//
	fsDeviceObject->Flags |= DO_DIRECT_IO;

	if (diskDeviceObject->Vpb) {
		// NOTE: This can be done by IoRegisterFileSystem + IRP_MN_MOUNT_VOLUME,
		// however that causes BSOD inside filter manager on Vista x86 after mount
		// (mouse hover on file).
		// Probably FS_FILTER_CALLBACKS.PreAcquireForSectionSynchronization is
		// not correctly called in that case.
		diskDeviceObject->Vpb->DeviceObject = fsDeviceObject;
		diskDeviceObject->Vpb->RealDevice = fsDeviceObject;
		diskDeviceObject->Vpb->Flags |= VPB_MOUNTED;
		diskDeviceObject->Vpb->VolumeLabelLength = (USHORT)wcslen(VOLUME_LABEL) * sizeof(WCHAR);
		RtlStringCchCopyW(diskDeviceObject->Vpb->VolumeLabel,
						sizeof(diskDeviceObject->Vpb->VolumeLabel) / sizeof(WCHAR),
						VOLUME_LABEL);
		diskDeviceObject->Vpb->SerialNumber = 0x19831116;
	}

	ObReferenceObject(fsDeviceObject);
	ObReferenceObject(diskDeviceObject);

	//
	// Create a symbolic link for userapp to interact with the driver.
	//
	status = IoCreateSymbolicLink(dcb->SymbolicLinkName, dcb->DiskDeviceName);

	if (!NT_SUCCESS(status)) {
		if (diskDeviceObject->Vpb) {
			diskDeviceObject->Vpb->DeviceObject = NULL;
			diskDeviceObject->Vpb->RealDevice = NULL;
			diskDeviceObject->Vpb->Flags = 0;
		}
		IoDeleteDevice(diskDeviceObject);
		IoDeleteDevice(fsDeviceObject);
		DDbgPrint("  IoCreateSymbolicLink returned 0x%x\n", status);
		return status;
	}
	DDbgPrint("SymbolicLink: %wZ -> %wZ created\n", dcb->SymbolicLinkName, dcb->DiskDeviceName);

	// Mark devices as initialized
	diskDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
	fsDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

	//IoRegisterFileSystem(fsDeviceObject);

	if (isNetworkFileSystem) {
		// Run FsRtlRegisterUncProvider in System thread.
		HANDLE handle;
		PKTHREAD thread;
		OBJECT_ATTRIBUTES objectAttribs;

		InitializeObjectAttributes(
			&objectAttribs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
		status = PsCreateSystemThread(&handle, THREAD_ALL_ACCESS,
			&objectAttribs, NULL, NULL, (PKSTART_ROUTINE)DokanRegisterUncProvider, dcb);
		if (!NT_SUCCESS(status)) {
			DDbgPrint("PsCreateSystemThread failed: 0x%X\n", status);
		} else {
			ObReferenceObjectByHandle(handle, THREAD_ALL_ACCESS, NULL,
					KernelMode, &thread, NULL);
			ZwClose(handle);
			KeWaitForSingleObject(thread, Executive, KernelMode, FALSE, NULL);
			ObDereferenceObject(thread);
		}
	}

	//DokanRegisterMountedDeviceInterface(diskDeviceObject, dcb);
	
	dcb->Mounted = 1;

	//DokanSendVolumeArrivalNotification(&deviceName);
	//DokanRegisterDeviceInterface(DriverObject, diskDeviceObject, dcb);

	return STATUS_SUCCESS;
}
Beispiel #14
0
static NTSTATUS
V4vAddDevice(PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
{
    NTSTATUS          status = STATUS_SUCCESS;
    UNICODE_STRING    deviceName;
    PDEVICE_OBJECT    fdo = NULL;
    PXENV4V_EXTENSION pde = NULL;
    LONG              val;
    BOOLEAN           symlink = FALSE;
    LARGE_INTEGER     seed;
    WCHAR            *szSddl = NULL;
    UNICODE_STRING    sddlString;
    CHAR             *szFpath = NULL;

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    // We only allow one instance of this device type. If more than on pdo is created we need
    val = InterlockedCompareExchange(&g_deviceCreated, 1, 0);
    if (val != 0) {
        TraceWarning(("cannot instantiate more that one v4v device node.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    do {
        // Create our device
        RtlInitUnicodeString(&deviceName, V4V_DEVICE_NAME);
        szSddl = g_win5Sddl;
        RtlInitUnicodeString(&sddlString, szSddl);

        status = 
            IoCreateDeviceSecure(driverObject,
                                 sizeof(XENV4V_EXTENSION),
                                 &deviceName,
                                 FILE_DEVICE_UNKNOWN,
                                 FILE_DEVICE_SECURE_OPEN,
                                 FALSE,
                                 &sddlString,
                                 (LPCGUID)&GUID_SD_XENV4V_CONTROL_OBJECT,
                                 &fdo);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create device object - error: 0x%x\n", status));
            fdo = NULL;
            break;
        }

        pde = (PXENV4V_EXTENSION)fdo->DeviceExtension;
        RtlZeroMemory(pde, sizeof(XENV4V_EXTENSION));
        RtlStringCchCopyW(pde->symbolicLinkText, XENV4V_SYM_NAME_LEN, V4V_SYMBOLIC_NAME);
        RtlInitUnicodeString(&pde->symbolicLink, pde->symbolicLinkText);

        // Create our symbolic link
        status = IoCreateSymbolicLink(&pde->symbolicLink, &deviceName);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create symbolic - error: 0x%x\n", status));
            break;
        }
        symlink = TRUE;       

        // Get our xenstore path
        szFpath = xenbus_find_frontend(pdo);
        if (szFpath == NULL) {
            status = STATUS_NO_SUCH_DEVICE;
            TraceError(("failed to locate XenStore front end path\n"));
            break;
        }

        // Setup the extension
        pde->magic = XENV4V_MAGIC;
        pde->pdo = pdo;
        pde->fdo = fdo;
        IoInitializeRemoveLock(&pde->removeLock, 'v4vx', 0, 0);
        pde->frontendPath = szFpath;
        szFpath = NULL;
        pde->state = XENV4V_DEV_STOPPED; // wait for start
        pde->lastPoState = PowerSystemWorking;
        pde->virqPort = null_EVTCHN_PORT();
        KeInitializeDpc(&pde->virqDpc, V4vVirqNotifyDpc, fdo);
        KeInitializeSpinLock(&pde->virqLock);
        KeInitializeSpinLock(&pde->dpcLock);
        KeInitializeTimerEx(&pde->timer, NotificationTimer);
        KeInitializeDpc(&pde->timerDpc,
                        V4vConnectTimerDpc,
                        fdo);
        KeInitializeSpinLock(&pde->timerLock);
        pde->timerCounter = 0;
        InitializeListHead(&pde->contextList);
        KeInitializeSpinLock(&pde->contextLock);
        pde->contextCount = 0;
        InitializeListHead(&pde->ringList);
        KeInitializeSpinLock(&pde->ringLock);
        InitializeListHead(&pde->pendingIrpQueue);
        pde->pendingIrpCount = 0;
        KeInitializeSpinLock(&pde->queueLock);
        IoCsqInitializeEx(&pde->csqObject,
                          V4vCsqInsertIrpEx,
                          V4vCsqRemoveIrp,
                          V4vCsqPeekNextIrp,
                          V4vCsqAcquireLock,
                          V4vCsqReleaseLock,
                          V4vCsqCompleteCanceledIrp);
        InitializeListHead(&pde->destList);
        pde->destCount = 0;
        ExInitializeNPagedLookasideList(&pde->destLookasideList,
                                        NULL,
                                        NULL,
                                        0,
                                        sizeof(XENV4V_DESTINATION),
                                        XENV4V_TAG,
                                        0);
        KeQueryTickCount(&seed);
        pde->seed = seed.u.LowPart;

        // Now attach us to the stack
        pde->ldo = IoAttachDeviceToDeviceStack(fdo, pdo);
        if (pde->ldo == NULL) {
            TraceError(("failed to attach device to stack - error: 0x%x\n", status));
            status = STATUS_NO_SUCH_DEVICE;
            break;
        }

        // Use direct IO and let the IO manager directly map user buffers; clear the init flag
        fdo->Flags |= DO_DIRECT_IO;
        fdo->Flags &= ~DO_DEVICE_INITIALIZING;        

        // Made it here, go to connected state to be consistent
        xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CONNECTED);
    } while (FALSE);

    if (!NT_SUCCESS(status)) {
        if (fdo != NULL) {         
            if ((pde != NULL)&&(pde->ldo != NULL)) {
                IoDetachDevice(pde->ldo);
            }
            if (szFpath != NULL) {
                XmFreeMemory(szFpath);
            }
            if (symlink) {
                IoDeleteSymbolicLink(&pde->symbolicLink);
            }
            IoDeleteDevice(fdo);
        }
    }

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return status;
}
Beispiel #15
0
VOID
XenGfxReadRegistryValues(XENGFX_DEVICE_EXTENSION *pXenGfxExtension,
                         PUNICODE_STRING pDeviceRegistryPath)
{
#define _XENGFX_REGBUF_SPACE 240
    NTSTATUS Status;
    HANDLE   Key = NULL;
    ULONG    Len = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(WCHAR)*_XENGFX_REGBUF_SPACE; // room for 240 UNICODE chars
    ULONG    LenOut;
    UNICODE_STRING                 ValueName;
    OBJECT_ATTRIBUTES              ObjectAttrs;
    KEY_VALUE_PARTIAL_INFORMATION *pKvpi = NULL;
    PAGED_CODE();
	
    do {
        TraceVerbose(("%s Reading XENGFX device registry location: %.*ws\n",
                      __FUNCTION__, pDeviceRegistryPath->Length >> 1, pDeviceRegistryPath->Buffer));

        // Make a buffer for registry data
        pKvpi = (KEY_VALUE_PARTIAL_INFORMATION*)ExAllocatePoolWithTag(PagedPool, Len, XENGFX_TAG);
        if (pKvpi == NULL) {
            TraceError(("%s Failed to alloc registry read buffer!!\n", __FUNCTION__));
            break;
        }

        // Open the device key, it should be present.
        InitializeObjectAttributes(&ObjectAttrs, pDeviceRegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
        Status = ZwOpenKey(&Key, KEY_QUERY_VALUE, &ObjectAttrs);
        if (!NT_SUCCESS(Status)) {
            TraceError(("%s Failed to open registry key for driver - error: 0x%x\n", __FUNCTION__, Status));
            break;
        }

        // Get the ChildDeviceCount value - continue if it is not there.
        RtlInitUnicodeString(&ValueName, XENGFX_REG_CHILDDEVICECOUNT);
        RtlZeroMemory(pKvpi, Len);

        Status = ZwQueryValueKey(Key, &ValueName, KeyValuePartialInformation, pKvpi, Len, &LenOut);
        if ((!NT_SUCCESS(Status))||(pKvpi->Type != REG_DWORD)||(pKvpi->DataLength != sizeof(ULONG))) {
            TraceInfo(("%s Could not query ChildDeviceCount (may not be present) - type: %d length: 0x%x status: 0x%x\n", 
                       __FUNCTION__, pKvpi->Type, pKvpi->DataLength, Status));          
        }
        else
            pXenGfxExtension->VCrtcRegistryCount = *((ULONG*)pKvpi->Data);

        // Get the VidPnTracing value - continue if it is not there.
        RtlInitUnicodeString(&ValueName, XENGFX_REG_VIDPNTRACING);
        RtlZeroMemory(pKvpi, Len);

        Status = ZwQueryValueKey(Key, &ValueName, KeyValuePartialInformation, pKvpi, Len, &LenOut);
        if ((!NT_SUCCESS(Status))||(pKvpi->Type != REG_DWORD)||(pKvpi->DataLength != sizeof(ULONG))) {
            TraceInfo(("%s Could not query VidPnTracing (may not be present) - type: %d length: 0x%x status: 0x%x\n", 
                       __FUNCTION__, pKvpi->Type, pKvpi->DataLength, Status));
        }
        else
            pXenGfxExtension->VidPnTracing = (*((ULONG*)pKvpi->Data) != 0) ? TRUE : FALSE;

        // Get the VidPnTracing value - continue if it is not there.
        RtlInitUnicodeString(&ValueName, XENGFX_REG_DEBUGLOGNAME);
        RtlZeroMemory(pKvpi, Len);

        Status = ZwQueryValueKey(Key, &ValueName, KeyValuePartialInformation, pKvpi, Len, &LenOut);
        if ((!NT_SUCCESS(Status))||(pKvpi->Type != REG_SZ)||(pKvpi->DataLength > _XENGFX_REGBUF_SPACE*sizeof(WCHAR))) {
            TraceInfo(("%s Could not query DebugLogName (may not be present) - type: %d length: 0x%x status: 0x%x\n", 
                       __FUNCTION__, pKvpi->Type, pKvpi->DataLength, Status));
        }
        else {
            RtlStringCchCopyW(pXenGfxExtension->DebugLogName,
                              pKvpi->DataLength/sizeof(WCHAR),
                              (CONST WCHAR*)pKvpi->Data);
            TraceInfo(("%s DebugLogName: %S\n", __FUNCTION__, pXenGfxExtension->DebugLogName));
        }

    } while (FALSE);

    if (pKvpi != NULL)
        ExFreePoolWithTag(pKvpi, XENGFX_TAG);
}