/*++ Copyright (c) 1989 Microsoft Corporation Module Name: dev2dos.c Abstract: This module implements the device object to DOS name routine. Author: Norbert Kusters (norbertk) 21-Oct-1998 Nar Ganapathy (narg) 1-April-2000 - Moved the code to IO manager Environment: Kernel Mode. Revision History: --*/ #include #include #ifdef POOL_TAGGING #undef ExAllocatePool #undef ExAllocatePoolWithQuota #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,' d2D') #define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,' d2D') #endif NTSTATUS IoVolumeDeviceToDosName( IN PVOID VolumeDeviceObject, OUT PUNICODE_STRING DosName ); #if defined(ALLOC_PRAGMA) #pragma alloc_text(PAGE,IoVolumeDeviceToDosName) #endif NTSTATUS IoVolumeDeviceToDosName( IN PVOID VolumeDeviceObject, OUT PUNICODE_STRING DosName ) /*++ Routine Description: This routine returns a valid DOS path for the given device object. This caller of this routine must call ExFreePool on DosName->Buffer when it is no longer needed. Arguments: VolumeDeviceObject - Supplies the volume device object. DosName - Returns the DOS name for the volume Return Value: NTSTATUS --*/ { PDEVICE_OBJECT volumeDeviceObject = VolumeDeviceObject; PMOUNTDEV_NAME name; CHAR output[512], out[sizeof(MOUNTMGR_VOLUME_PATHS)]; KEVENT event; PIRP irp; IO_STATUS_BLOCK ioStatus; NTSTATUS status; UNICODE_STRING mountmgrName; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; PMOUNTMGR_VOLUME_PATHS paths; ULONG len; // // We are using a stack event and so must be at passive. // ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); name = (PMOUNTDEV_NAME) output; KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, volumeDeviceObject, NULL, 0, name, 512, FALSE, &event, &ioStatus); if (!irp) { return STATUS_INSUFFICIENT_RESOURCES; } status = IoCallDriver(volumeDeviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = ioStatus.Status; } if (!NT_SUCCESS(status)) { return status; } RtlInitUnicodeString(&mountmgrName, MOUNTMGR_DEVICE_NAME); status = IoGetDeviceObjectPointer(&mountmgrName, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject); if (!NT_SUCCESS(status)) { return status; } paths = (PMOUNTMGR_VOLUME_PATHS) out; KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, deviceObject, name, 512, paths, sizeof(MOUNTMGR_VOLUME_PATHS), FALSE, &event, &ioStatus); if (!irp) { ObDereferenceObject(fileObject); return STATUS_INSUFFICIENT_RESOURCES; } status = IoCallDriver(deviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = ioStatus.Status; } if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) { ObDereferenceObject(fileObject); return status; } len = sizeof(MOUNTMGR_VOLUME_PATHS) + paths->MultiSzLength; // // Ensure that there is no overflow. // if (len > MAXUSHORT) { ObDereferenceObject(fileObject); return STATUS_INVALID_BUFFER_SIZE; } paths = ExAllocatePool(PagedPool, len); if (!paths) { ObDereferenceObject(fileObject); return STATUS_INSUFFICIENT_RESOURCES; } KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, deviceObject, name, 512, paths, len, FALSE, &event, &ioStatus); if (!irp) { ExFreePool(paths); ObDereferenceObject(fileObject); return STATUS_INSUFFICIENT_RESOURCES; } status = IoCallDriver(deviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = ioStatus.Status; } if (!NT_SUCCESS(status)) { ExFreePool(paths); ObDereferenceObject(fileObject); return status; } DosName->Length = (USHORT) paths->MultiSzLength - 2*sizeof(WCHAR); DosName->MaximumLength = DosName->Length + sizeof(WCHAR); DosName->Buffer = (PWCHAR) paths; RtlCopyMemory(paths, paths->MultiSz, DosName->Length); DosName->Buffer[DosName->Length/sizeof(WCHAR)] = 0; ObDereferenceObject(fileObject); return STATUS_SUCCESS; }