Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
static VOID DokanControl(PDOKAN_CONTROL Control)
{
	PMOUNT_ENTRY	mountEntry;

	Control->Status = DOKAN_CONTROL_FAIL;

	switch (Control->Type)
	{
	case DOKAN_CONTROL_MOUNT:

		DbgPrintW(L"DokanControl Mount\n");

		if (DokanControlMount(Control->MountPoint, Control->DeviceName)) {
			Control->Status = DOKAN_CONTROL_SUCCESS;
			InsertMountEntry(Control);
		} else {
			Control->Status = DOKAN_CONTROL_FAIL;
		}
		break;

	case DOKAN_CONTROL_UNMOUNT:

		DbgPrintW(L"DokanControl Unmount\n");

		mountEntry = FindMountEntry(Control);
		if (mountEntry == NULL) {
			if (!wcslen(Control->MountPoint))
				FindMountPoint(Control);
			DbgPrintW(L"DokanControl MountEntry not found. Try unmount '%s' force: %d\n", Control->MountPoint, Control->Option);
			if (Control->Option == DOKAN_CONTROL_OPTION_FORCE_UNMOUNT &&
				DokanControlUnmount(Control->MountPoint)) {
				Control->Status = DOKAN_CONTROL_SUCCESS;
				break;
			}
			Control->Status = DOKAN_CONTROL_FAIL;
			break;	
		}

		if (DokanControlUnmount(mountEntry->MountControl.MountPoint)) {
			Control->Status = DOKAN_CONTROL_SUCCESS;
			if (Control->DeviceName[0] == L'\0') {
				wcscpy_s(Control->DeviceName, sizeof(Control->DeviceName) / sizeof(WCHAR),
						mountEntry->MountControl.DeviceName);
			}
			RemoveMountEntry(mountEntry);
		} else {
			mountEntry->MountControl.Status = DOKAN_CONTROL_FAIL;
			Control->Status = DOKAN_CONTROL_FAIL;
		}

		break;

	case DOKAN_CONTROL_CHECK:
		{
			DbgPrint("DokanControl Check\n");
			Control->Status = 0;
		}
		break;

	case DOKAN_CONTROL_FIND:
		{
			DbgPrintW(L"DokanControl Find\n");
			DokanControlFind(Control);
		}
		break;

	case DOKAN_CONTROL_LIST:
		{
			DbgPrintW(L"DokanControl List\n");
			DokanControlList(Control);
		}
		break;

	default:
		DbgPrintW(L"DokanControl UnknownType %u\n", Control->Type);
	}

	return;
}
Ejemplo n.º 3
0
Archivo: mounter.c Proyecto: ulteo/ovd
static VOID DokanControl(PDOKAN_CONTROL Control)
{
	PMOUNT_ENTRY	mountEntry;
	ULONG	index = 0;
	DWORD written = 0;

	Control->Status = DOKAN_CONTROL_FAIL;

	switch (Control->Type)
	{
	case DOKAN_CONTROL_MOUNT:

		DbgPrintW(L"DokanControl Mount\n");

//		if (DokanControlMount(Control->MountPoint, Control->DeviceName)) {
			Control->Status = DOKAN_CONTROL_SUCCESS;
			InsertMountEntry(Control);
			DbgPrintW(L"DriveLetter: %c, DeviceName %s\n", Control->MountPoint[0], Control->DeviceName);

//		} else {
//			Control->Status = DOKAN_CONTROL_FAIL;
//		}
		break;

	case DOKAN_CONTROL_UNMOUNT:

		DbgPrintW(L"DokanControl Unmount\n");

		mountEntry = FindMountEntry(Control);
		if (mountEntry == NULL) {
			if (Control->Option == DOKAN_CONTROL_OPTION_FORCE_UNMOUNT ) {
				Control->Status = DOKAN_CONTROL_SUCCESS;
				break;
			}
			Control->Status = DOKAN_CONTROL_FAIL;
			break;	
		}

//		if (DokanControlUnmount(mountEntry->MountControl.MountPoint)) {
			Control->Status = DOKAN_CONTROL_SUCCESS;
			if (wcslen(Control->DeviceName) == 0) {
				wcscpy_s(Control->DeviceName, sizeof(Control->DeviceName) / sizeof(WCHAR),
						mountEntry->MountControl.DeviceName);
			}
			RemoveMountEntry(mountEntry);
//		} else {
//			mountEntry->MountControl.Status = DOKAN_CONTROL_FAIL;
//			Control->Status = DOKAN_CONTROL_FAIL;
//		}

		break;

	case DOKAN_CONTROL_CHECK:
		{
			DbgPrint("DokanControl Check\n");
			Control->Status = 0;
		}
		break;

	case DOKAN_CONTROL_FIND:
		{
			DbgPrintW(L"DokanControl Find\n");
			DokanControlFind(Control);
		}
		break;

	case DOKAN_CONTROL_LIST:
		{
			DbgPrintW(L"DokanControl List\n");
			DokanControlList(Control);
		}
		break;

	default:
		DbgPrintW(L"DokanControl UnknownType %u\n", Control->Type);
	}

	return;
}