Author: pschweitzer Date: Tue Jan 31 18:18:46 2012 New Revision: 55354
URL: http://svn.reactos.org/svn/reactos?rev=55354&view=rev Log: [NTOSKRNL] Implement IoVolumeDeviceToDosName(), taking advantage of newcomer in the branch, MountMgr :-). This implementation will in fact don't work as MountMgr doesn't implement that part... But the day it's ready, this function will be!
Modified: branches/usb-bringup-trunk/ntoskrnl/include/ntoskrnl.h branches/usb-bringup-trunk/ntoskrnl/io/iomgr/volume.c
Modified: branches/usb-bringup-trunk/ntoskrnl/include/ntoskrnl.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/ntoskrnl/inclu... ============================================================================== --- branches/usb-bringup-trunk/ntoskrnl/include/ntoskrnl.h [iso-8859-1] (original) +++ branches/usb-bringup-trunk/ntoskrnl/include/ntoskrnl.h [iso-8859-1] Tue Jan 31 18:18:46 2012 @@ -31,6 +31,7 @@ #include <ntifs.h> #include <wdmguid.h> #include <arc/arc.h> +#include <mountmgr.h> #undef NTHALAPI #define NTHALAPI __declspec(dllimport) #include <ndk/asm.h>
Modified: branches/usb-bringup-trunk/ntoskrnl/io/iomgr/volume.c URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/ntoskrnl/io/io... ============================================================================== --- branches/usb-bringup-trunk/ntoskrnl/io/iomgr/volume.c [iso-8859-1] (original) +++ branches/usb-bringup-trunk/ntoskrnl/io/iomgr/volume.c [iso-8859-1] Tue Jan 31 18:18:46 2012 @@ -1269,15 +1269,165 @@ }
/* - * @unimplemented + * @implemented */ NTSTATUS NTAPI IoVolumeDeviceToDosName(IN PVOID VolumeDeviceObject, OUT PUNICODE_STRING DosName) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIRP Irp; + ULONG Length; + KEVENT Event; + NTSTATUS Status; + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING MountMgrDevice; + MOUNTMGR_VOLUME_PATHS VolumePath; + PMOUNTMGR_VOLUME_PATHS VolumePathPtr; + /* + * This variable with be required to query device name. + * It's based on MOUNTDEV_NAME (mountmgr.h). + * Doing it that way will prevent dyn memory allocation. + * Device name won't be longer. + */ + struct + { + USHORT NameLength; + WCHAR DeviceName[256]; + } DeviceName; + + PAGED_CODE(); + + /* First step, getting device name */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, + VolumeDeviceObject, NULL, 0, + &DeviceName, sizeof(DeviceName), + FALSE, &Event, &IoStatusBlock); + if (!Irp) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = IoCallDriver(VolumeDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Now that we have the device name, we can query the MountMgr + * So, get its device object first. + */ + RtlInitUnicodeString(&MountMgrDevice, MOUNTMGR_DEVICE_NAME); + Status = IoGetDeviceObjectPointer(&MountMgrDevice, FILE_READ_ATTRIBUTES, + &FileObject, &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Then, use the proper IOCTL to query the DOS name */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, + DeviceObject, &DeviceName, sizeof(DeviceName), + &VolumePath, sizeof(VolumePath), + FALSE, &Event, &IoStatusBlock); + if (!Irp) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto DereferenceFO; + } + + Status = IoCallDriver(VolumeDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + + /* Only tolerated failure here is buffer too small, which is + * expected. + */ + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) + { + goto DereferenceFO; + } + + /* Compute needed size to store DOS name. + * Even if MOUNTMGR_VOLUME_PATHS allows bigger + * name lengths than MAXUSHORT, we can't use + * them, because we have to return this in an UNICODE_STRING + * that stores length on USHORT. + */ + Length = VolumePath.MultiSzLength + sizeof(VolumePath); + if (Length > MAXUSHORT) + { + Status = STATUS_INVALID_BUFFER_SIZE; + goto DereferenceFO; + } + + /* Reallocate memory, even in case of success, because + * that's the buffer that will be returned to caller + */ + VolumePathPtr = ExAllocatePoolWithTag(PagedPool, Length, 'D2d '); + if (!VolumePathPtr) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto DereferenceFO; + } + + /* Requery DOS path with proper size */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, + DeviceObject, &DeviceName, sizeof(DeviceName), + VolumePathPtr, Length, + FALSE, &Event, &IoStatusBlock); + if (!Irp) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ReleaseMemory; + } + + Status = IoCallDriver(VolumeDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + + if (!NT_SUCCESS(Status)) + { + goto ReleaseMemory; + } + + /* Set output string */ + DosName->Length = VolumePathPtr->MultiSzLength; + DosName->MaximumLength = VolumePathPtr->MultiSzLength + sizeof(UNICODE_NULL); + /* Our MOUNTMGR_VOLUME_PATHS will be used as output buffer */ + DosName->Buffer = (PWSTR)VolumePathPtr; + /* Move name at the begin, RtlMoveMemory is OK with overlapping */ + RtlMoveMemory(DosName->Buffer, VolumePathPtr->MultiSz, VolumePathPtr->MultiSzLength); + DosName->Buffer[DosName->Length / sizeof(WCHAR)] = UNICODE_NULL; + + /* DON'T release buffer, just dereference FO, and return success */ + Status = STATUS_SUCCESS; + goto DereferenceFO; + +ReleaseMemory: + ExFreePoolWithTag(VolumePathPtr, 'D2d '); + +DereferenceFO: + ObDereferenceObject(FileObject); + + return Status; }
/* EOF */