_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); }
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"); }
// 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; }
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; }
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); }
// 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; }
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 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; }
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; }
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; } }
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; }
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; }
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; }
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); }