void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) { PFILE_OBJECT FileObject, mountmgrfo; PDEVICE_OBJECT devobj, mountmgr; NTSTATUS Status; STORAGE_DEVICE_NUMBER sdn; ULONG dlisize; DRIVE_LAYOUT_INFORMATION_EX* dli = NULL; IO_STATUS_BLOCK iosb; GET_LENGTH_INFORMATION gli; UNICODE_STRING mmdevpath; UNUSED(DriverObject); Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &FileObject, &devobj); if (!NT_SUCCESS(Status)) { ERR("IoGetDeviceObjectPointer returned %08x\n", Status); return; } RtlInitUnicodeString(&mmdevpath, MOUNTMGR_DEVICE_NAME); Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr); if (!NT_SUCCESS(Status)) { ERR("IoGetDeviceObjectPointer returned %08x\n", Status); ObDereferenceObject(FileObject); return; } dlisize = 0; do { dlisize += 1024; if (dli) ExFreePool(dli); dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG); if (!dli) { ERR("out of memory\n"); goto end; } Status = dev_ioctl(devobj, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, dli, dlisize, TRUE, &iosb); } while (Status == STATUS_BUFFER_TOO_SMALL); // only consider disk as a potential filesystem if it has no partitions if (NT_SUCCESS(Status) && dli->PartitionCount > 0) { ExFreePool(dli); goto end; } ExFreePool(dli); Status = dev_ioctl(devobj, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &gli, sizeof(gli), TRUE, NULL); if (!NT_SUCCESS(Status)) { ERR("error reading length information: %08x\n", Status); goto end; } Status = dev_ioctl(devobj, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(STORAGE_DEVICE_NUMBER), TRUE, NULL); if (!NT_SUCCESS(Status)) { TRACE("IOCTL_STORAGE_GET_DEVICE_NUMBER returned %08x\n", Status); sdn.DeviceNumber = 0xffffffff; sdn.PartitionNumber = 0; } else TRACE("DeviceType = %u, DeviceNumber = %u, PartitionNumber = %u\n", sdn.DeviceType, sdn.DeviceNumber, sdn.PartitionNumber); test_vol(mountmgr, devobj, devpath, sdn.DeviceNumber, sdn.PartitionNumber, gli.Length.QuadPart); end: ObDereferenceObject(FileObject); ObDereferenceObject(mountmgrfo); }
static NTSTATUS look_in_harddisk_dir(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmgr, PUNICODE_STRING name, LIST_ENTRY* volumes) { UNICODE_STRING path; OBJECT_ATTRIBUTES attr; NTSTATUS Status; HANDLE h; OBJECT_DIRECTORY_INFORMATION* odi; ULONG odisize, context; BOOL restart, has_part0 = FALSE, has_parts = FALSE; static const WCHAR partition[] = L"Partition"; static WCHAR partition0[] = L"Partition0"; path.Buffer = ExAllocatePoolWithTag(PagedPool, ((wcslen(devpath) + 1) * sizeof(WCHAR)) + name->Length, ALLOC_TAG); if (!path.Buffer) { ERR("out of memory\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(path.Buffer, devpath, wcslen(devpath) * sizeof(WCHAR)); path.Buffer[wcslen(devpath)] = '\\'; RtlCopyMemory(&path.Buffer[wcslen(devpath) + 1], name->Buffer, name->Length); path.Length = path.MaximumLength = ((wcslen(devpath) + 1) * sizeof(WCHAR)) + name->Length; attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.Attributes = OBJ_CASE_INSENSITIVE; attr.ObjectName = &path; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; Status = ZwOpenDirectoryObject(&h, DIRECTORY_TRAVERSE, &attr); if (!NT_SUCCESS(Status)) { ERR("ZwOpenDirectoryObject returned %08x\n", Status); goto end; } odisize = sizeof(OBJECT_DIRECTORY_INFORMATION) * 16; odi = ExAllocatePoolWithTag(PagedPool, odisize, ALLOC_TAG); if (!odi) { ERR("out of memory\n"); Status = STATUS_INSUFFICIENT_RESOURCES; ZwClose(h); goto end; } restart = TRUE; do { Status = ZwQueryDirectoryObject(h, odi, odisize, FALSE, restart, &context, NULL/*&retlen*/); restart = FALSE; if (!NT_SUCCESS(Status)) { if (Status != STATUS_NO_MORE_ENTRIES) ERR("ZwQueryDirectoryObject returned %08x\n", Status); } else { OBJECT_DIRECTORY_INFORMATION* odi2 = odi; while (odi2->Name.Buffer) { TRACE("%.*S, %.*S\n", odi2->TypeName.Length / sizeof(WCHAR), odi2->TypeName.Buffer, odi2->Name.Length / sizeof(WCHAR), odi2->Name.Buffer); if (odi2->Name.Length > wcslen(partition) * sizeof(WCHAR) && RtlCompareMemory(odi2->Name.Buffer, partition, wcslen(partition) * sizeof(WCHAR)) == wcslen(partition) * sizeof(WCHAR)) { if (odi2->Name.Length == (wcslen(partition) + 1) * sizeof(WCHAR) && odi2->Name.Buffer[(odi2->Name.Length / sizeof(WCHAR)) - 1] == '0') { // Partition0 refers to the whole disk has_part0 = TRUE; } else { has_parts = TRUE; test_vol(DriverObject, mountmgr, &path, &odi2->Name, FALSE, volumes); } } odi2 = &odi2[1]; } } } while (NT_SUCCESS(Status)); // If disk had no partitions, test the whole disk if (!has_parts && has_part0) { UNICODE_STRING part0us; part0us.Buffer = partition0; part0us.Length = part0us.MaximumLength = wcslen(partition0) * sizeof(WCHAR); test_vol(DriverObject, mountmgr, &path, &part0us, TRUE, volumes); } ZwClose(h); ExFreePool(odi); Status = STATUS_SUCCESS; end: ExFreePool(path.Buffer); return Status; }