NTSTATUS mvolQueryMountPoint(PVOLUME_EXTENSION pvext) { ULONG mplen = pvext->PhysicalDeviceNameLength + sizeof(MOUNTMGR_MOUNT_POINT); ULONG mpslen = 4096 * 2; PCHAR inbuf = kmalloc(mplen, 0, '56DW'); PCHAR otbuf = kmalloc(mpslen, 0, '56DW'); if (!inbuf || !otbuf) { return STATUS_MEMORY_NOT_ALLOCATED; } PMOUNTMGR_MOUNT_POINT pmp = (PMOUNTMGR_MOUNT_POINT)inbuf; PMOUNTMGR_MOUNT_POINTS pmps = (PMOUNTMGR_MOUNT_POINTS)otbuf; pmp->DeviceNameLength = pvext->PhysicalDeviceNameLength; pmp->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT); RtlCopyMemory(inbuf + pmp->DeviceNameOffset, pvext->PhysicalDeviceName, pvext->PhysicalDeviceNameLength); NTSTATUS status = QueryMountPoint(pmp, mplen, pmps, &mpslen); if (!NT_SUCCESS(status)) { goto cleanup; } for (int i = 0; i < pmps->NumberOfMountPoints; i++) { PMOUNTMGR_MOUNT_POINT p = pmps->MountPoints + i; PUNICODE_STRING link = NULL; UNICODE_STRING name = { .Length = p->SymbolicLinkNameLength, .MaximumLength = p->SymbolicLinkNameLength, .Buffer = (PWCH)(otbuf + p->SymbolicLinkNameOffset) }; if (MOUNTMGR_IS_DRIVE_LETTER(&name)) { name.Length = strlen(" :") * sizeof(WCHAR); name.Buffer += strlen("\\DosDevices\\"); pvext->VolIndex = name.Buffer[0] - 'C'; link = &pvext->MountPoint; FreeUnicodeString(link); } else if (MOUNTMGR_IS_VOLUME_NAME(&name)) { link = &pvext->VolumeGuid; } link && ucsdup(link, name.Buffer, name.Length); } cleanup: kfree(inbuf); kfree(otbuf); return status; } #ifdef _WIN32_GetDiskPerf NTSTATUS mvolGetDiskPerf(PDEVICE_OBJECT TargetDeviceObject, PDISK_PERFORMANCE pDiskPerf) { NTSTATUS status; KEVENT event; IO_STATUS_BLOCK ioStatus; PIRP newIrp; KeInitializeEvent(&event, NotificationEvent, FALSE); newIrp = IoBuildDeviceIoControlRequest(IOCTL_DISK_PERFORMANCE, TargetDeviceObject, NULL, 0, pDiskPerf, sizeof(DISK_PERFORMANCE), FALSE, &event, &ioStatus); if (!newIrp) { return STATUS_INSUFFICIENT_RESOURCES; } status = IoCallDriver(TargetDeviceObject, newIrp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, (PLARGE_INTEGER) NULL); status = ioStatus.Status; } return status; }
/* * @implemented */ NTSTATUS MountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName) { NTSTATUS Status; PLIST_ENTRY DeviceEntry; PMOUNTDEV_UNIQUE_ID UniqueId; PSYMLINK_INFORMATION SymlinkInformation; UNICODE_STRING SymLink, TargetDeviceName; PDEVICE_INFORMATION DeviceInformation = NULL, DeviceInfo; /* Get device name */ Status = QueryDeviceInformation(SymbolicLinkName, &TargetDeviceName, NULL, NULL, NULL, NULL, NULL, NULL); if (!NT_SUCCESS(Status)) { return Status; } /* First of all, try to find device */ for (DeviceEntry = DeviceExtension->DeviceListHead.Flink; DeviceEntry != &(DeviceExtension->DeviceListHead); DeviceEntry = DeviceEntry->Flink) { DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry); if (RtlCompareUnicodeString(&TargetDeviceName, &(DeviceInformation->DeviceName), TRUE) == 0) { break; } } /* Copy symbolic link name and null terminate it */ SymLink.Buffer = AllocatePool(SymbolicLinkName->Length + sizeof(UNICODE_NULL)); if (!SymLink.Buffer) { FreePool(TargetDeviceName.Buffer); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(SymLink.Buffer, SymbolicLinkName->Buffer, SymbolicLinkName->Length); SymLink.Buffer[SymbolicLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL; SymLink.Length = SymbolicLinkName->Length; SymLink.MaximumLength = SymbolicLinkName->Length + sizeof(UNICODE_NULL); /* If we didn't find device */ if (DeviceEntry == &(DeviceExtension->DeviceListHead)) { /* Then, try with unique ID */ Status = QueryDeviceInformation(SymbolicLinkName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL); if (!NT_SUCCESS(Status)) { FreePool(TargetDeviceName.Buffer); FreePool(SymLink.Buffer); return Status; } /* Create a link to the device */ Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName); if (!NT_SUCCESS(Status)) { FreePool(UniqueId); FreePool(TargetDeviceName.Buffer); FreePool(SymLink.Buffer); return Status; } /* If caller provided driver letter, delete it */ if (IsDriveLetter(&SymLink)) { DeleteRegistryDriveLetter(UniqueId); } /* Device will be identified with its unique ID */ Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, DatabasePath, SymLink.Buffer, REG_BINARY, UniqueId->UniqueId, UniqueId->UniqueIdLength); FreePool(UniqueId); FreePool(TargetDeviceName.Buffer); FreePool(SymLink.Buffer); return Status; } /* If call provided a driver letter whereas device already has one * fail, this is not doable */ if (IsDriveLetter(&SymLink) && HasDriveLetter(DeviceInformation)) { FreePool(TargetDeviceName.Buffer); FreePool(SymLink.Buffer); return STATUS_INVALID_PARAMETER; } /* Now, create a link */ Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName); FreePool(TargetDeviceName.Buffer); if (!NT_SUCCESS(Status)) { FreePool(SymLink.Buffer); return Status; } /* Associate Unique ID <-> symbolic name */ UniqueId = DeviceInformation->UniqueId; Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, DatabasePath, SymLink.Buffer, REG_BINARY, UniqueId->UniqueId, UniqueId->UniqueIdLength); if (!NT_SUCCESS(Status)) { GlobalDeleteSymbolicLink(&SymLink); FreePool(SymLink.Buffer); return Status; } /* Now, prepare to save the link with the device */ SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION)); if (!SymlinkInformation) { Status = STATUS_INSUFFICIENT_RESOURCES; GlobalDeleteSymbolicLink(&SymLink); FreePool(SymLink.Buffer); return Status; } SymlinkInformation->Name.Length = SymLink.Length; SymlinkInformation->Name.MaximumLength = SymLink.Length + sizeof(UNICODE_NULL); SymlinkInformation->Name.Buffer = AllocatePool(SymlinkInformation->Name.MaximumLength); if (!SymlinkInformation->Name.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; FreePool(SymlinkInformation); GlobalDeleteSymbolicLink(&SymLink); FreePool(SymLink.Buffer); return Status; } /* Save the link and mark it online */ RtlCopyMemory(SymlinkInformation->Name.Buffer, SymLink.Buffer, SymlinkInformation->Name.Length); SymlinkInformation->Name.Buffer[SymlinkInformation->Name.Length / sizeof(WCHAR)] = UNICODE_NULL; SymlinkInformation->Online = TRUE; InsertTailList(&DeviceInformation->SymbolicLinksListHead, &SymlinkInformation->SymbolicLinksListEntry); SendLinkCreated(&(SymlinkInformation->Name)); /* If we have a drive letter */ if (IsDriveLetter(&SymLink)) { /* Then, delete the no drive letter entry */ DeleteNoDriveLetterEntry(UniqueId); /* And post online notification if asked */ if (!DeviceInformation->SkipNotifications) { PostOnlineNotification(DeviceExtension, &DeviceInformation->SymbolicName); } } /* If that's a volume with automatic drive letter, it's now time to resync databases */ if (MOUNTMGR_IS_VOLUME_NAME(&SymLink) && DeviceExtension->AutomaticDriveLetter) { for (DeviceEntry = DeviceExtension->DeviceListHead.Flink; DeviceEntry != &(DeviceExtension->DeviceListHead); DeviceEntry = DeviceEntry->Flink) { DeviceInfo = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry); /* If there's one, ofc! */ if (!DeviceInfo->NoDatabase) { ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInfo); } } } /* Notify & quit */ FreePool(SymLink.Buffer); MountMgrNotify(DeviceExtension); if (!DeviceInformation->Volume) { MountMgrNotifyNameChange(DeviceExtension, DeviceName, FALSE); } return Status; }