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); }
VOID DokanControlFind(PDOKAN_CONTROL Control) { PMOUNT_ENTRY mountEntry; mountEntry = FindMountEntry(Control); if (mountEntry == NULL) { Control->Status = DOKAN_CONTROL_FAIL; } else { wcscpy_s(Control->DeviceName, sizeof(Control->DeviceName) / sizeof(WCHAR), mountEntry->MountControl.DeviceName); wcscpy_s(Control->MountPoint, sizeof(Control->MountPoint) / sizeof(WCHAR), mountEntry->MountControl.MountPoint); Control->Status = DOKAN_CONTROL_SUCCESS; } }
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; }
// 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; }
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; }
VOID DokanDeleteDeviceObject(__in PDokanDCB Dcb) { PDokanVCB vcb; DOKAN_CONTROL dokanControl; PMOUNT_ENTRY mountEntry = NULL; ASSERT(GetIdentifierType(Dcb) == DCB); vcb = Dcb->Vcb; if (Dcb->SymbolicLinkName == NULL) { DDbgPrint(" Symbolic Name already deleted, so go out here\n"); return; } RtlZeroMemory(&dokanControl, sizeof(dokanControl)); RtlCopyMemory(dokanControl.DeviceName, Dcb->DiskDeviceName->Buffer, Dcb->DiskDeviceName->Length); mountEntry = FindMountEntry(Dcb->Global, &dokanControl); if (mountEntry != NULL) { if (mountEntry->MountControl.Type == FILE_DEVICE_NETWORK_FILE_SYSTEM) { // Run FsRtlDeregisterUncProvider in System thread. HANDLE handle; PKTHREAD thread; OBJECT_ATTRIBUTES objectAttribs; NTSTATUS status; InitializeObjectAttributes(&objectAttribs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); status = PsCreateSystemThread( &handle, THREAD_ALL_ACCESS, &objectAttribs, NULL, NULL, (PKSTART_ROUTINE)DokanDeregisterUncProvider, 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); } } RemoveMountEntry(Dcb->Global, mountEntry); } else { DDbgPrint(" Cannot found associated mount entry.\n"); } DDbgPrint(" Delete Symbolic Name: %wZ\n", Dcb->SymbolicLinkName); IoDeleteSymbolicLink(Dcb->SymbolicLinkName); if (Dcb->MountedDeviceInterfaceName.Buffer != NULL) { IoSetDeviceInterfaceState(&Dcb->MountedDeviceInterfaceName, FALSE); RtlFreeUnicodeString(&Dcb->MountedDeviceInterfaceName); RtlInitUnicodeString(&Dcb->MountedDeviceInterfaceName, NULL); } if (Dcb->DiskDeviceInterfaceName.Buffer != NULL) { IoSetDeviceInterfaceState(&Dcb->DiskDeviceInterfaceName, FALSE); RtlFreeUnicodeString(&Dcb->DiskDeviceInterfaceName); RtlInitUnicodeString(&Dcb->DiskDeviceInterfaceName, NULL); } FreeDcbNames(Dcb); if (Dcb->DeviceObject->Vpb) { Dcb->DeviceObject->Vpb->DeviceObject = NULL; Dcb->DeviceObject->Vpb->RealDevice = NULL; Dcb->DeviceObject->Vpb->Flags = 0; } if (vcb != NULL) { DDbgPrint(" FCB allocated: %d\n", vcb->FcbAllocated); DDbgPrint(" FCB freed: %d\n", vcb->FcbFreed); DDbgPrint(" CCB allocated: %d\n", vcb->CcbAllocated); DDbgPrint(" CCB freed: %d\n", vcb->CcbFreed); // delete volDeviceObject DDbgPrint(" Delete Volume DeviceObject\n"); IoDeleteDevice(vcb->DeviceObject); } // delete diskDeviceObject DDbgPrint(" Delete Disk DeviceObject\n"); IoDeleteDevice(Dcb->DeviceObject); }
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; }