Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
5.3 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. dev2dos.c
  5. Abstract:
  6. This module implements the device object to DOS name routine.
  7. Author:
  8. Norbert Kusters (norbertk) 21-Oct-1998
  9. Nar Ganapathy (narg) 1-April-2000 - Moved the code to IO manager
  10. Environment:
  11. Kernel Mode.
  12. Revision History:
  13. --*/
  14. #include <iomgr.h>
  15. #include <mountdev.h>
  16. #ifdef POOL_TAGGING
  17. #undef ExAllocatePool
  18. #undef ExAllocatePoolWithQuota
  19. #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,' d2D')
  20. #define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,' d2D')
  21. #endif
  22. NTSTATUS
  23. IoVolumeDeviceToDosName(
  24. IN PVOID VolumeDeviceObject,
  25. OUT PUNICODE_STRING DosName
  26. );
  27. #if defined(ALLOC_PRAGMA)
  28. #pragma alloc_text(PAGE,IoVolumeDeviceToDosName)
  29. #endif
  30. NTSTATUS
  31. IoVolumeDeviceToDosName(
  32. IN PVOID VolumeDeviceObject,
  33. OUT PUNICODE_STRING DosName
  34. )
  35. /*++
  36. Routine Description:
  37. This routine returns a valid DOS path for the given device object.
  38. This caller of this routine must call ExFreePool on DosName->Buffer
  39. when it is no longer needed.
  40. Arguments:
  41. VolumeDeviceObject - Supplies the volume device object.
  42. DosName - Returns the DOS name for the volume
  43. Return Value:
  44. NTSTATUS
  45. --*/
  46. {
  47. PDEVICE_OBJECT volumeDeviceObject = VolumeDeviceObject;
  48. PMOUNTDEV_NAME name;
  49. CHAR output[512], out[sizeof(MOUNTMGR_VOLUME_PATHS)];
  50. KEVENT event;
  51. PIRP irp;
  52. IO_STATUS_BLOCK ioStatus;
  53. NTSTATUS status;
  54. UNICODE_STRING mountmgrName;
  55. PFILE_OBJECT fileObject;
  56. PDEVICE_OBJECT deviceObject;
  57. PMOUNTMGR_VOLUME_PATHS paths;
  58. ULONG len;
  59. //
  60. // We are using a stack event and so must be at passive.
  61. //
  62. ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  63. name = (PMOUNTDEV_NAME) output;
  64. KeInitializeEvent(&event, NotificationEvent, FALSE);
  65. irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
  66. volumeDeviceObject, NULL, 0, name, 512,
  67. FALSE, &event, &ioStatus);
  68. if (!irp) {
  69. return STATUS_INSUFFICIENT_RESOURCES;
  70. }
  71. status = IoCallDriver(volumeDeviceObject, irp);
  72. if (status == STATUS_PENDING) {
  73. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  74. status = ioStatus.Status;
  75. }
  76. if (!NT_SUCCESS(status)) {
  77. return status;
  78. }
  79. RtlInitUnicodeString(&mountmgrName, MOUNTMGR_DEVICE_NAME);
  80. status = IoGetDeviceObjectPointer(&mountmgrName, FILE_READ_ATTRIBUTES,
  81. &fileObject, &deviceObject);
  82. if (!NT_SUCCESS(status)) {
  83. return status;
  84. }
  85. paths = (PMOUNTMGR_VOLUME_PATHS) out;
  86. KeInitializeEvent(&event, NotificationEvent, FALSE);
  87. irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
  88. deviceObject, name, 512,
  89. paths, sizeof(MOUNTMGR_VOLUME_PATHS),
  90. FALSE, &event, &ioStatus);
  91. if (!irp) {
  92. ObDereferenceObject(fileObject);
  93. return STATUS_INSUFFICIENT_RESOURCES;
  94. }
  95. status = IoCallDriver(deviceObject, irp);
  96. if (status == STATUS_PENDING) {
  97. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  98. status = ioStatus.Status;
  99. }
  100. if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) {
  101. ObDereferenceObject(fileObject);
  102. return status;
  103. }
  104. len = sizeof(MOUNTMGR_VOLUME_PATHS) + paths->MultiSzLength;
  105. //
  106. // Ensure that there is no overflow.
  107. //
  108. if (len > MAXUSHORT) {
  109. ObDereferenceObject(fileObject);
  110. return STATUS_INVALID_BUFFER_SIZE;
  111. }
  112. paths = ExAllocatePool(PagedPool, len);
  113. if (!paths) {
  114. ObDereferenceObject(fileObject);
  115. return STATUS_INSUFFICIENT_RESOURCES;
  116. }
  117. KeInitializeEvent(&event, NotificationEvent, FALSE);
  118. irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
  119. deviceObject, name, 512,
  120. paths, len, FALSE, &event, &ioStatus);
  121. if (!irp) {
  122. ExFreePool(paths);
  123. ObDereferenceObject(fileObject);
  124. return STATUS_INSUFFICIENT_RESOURCES;
  125. }
  126. status = IoCallDriver(deviceObject, irp);
  127. if (status == STATUS_PENDING) {
  128. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  129. status = ioStatus.Status;
  130. }
  131. if (!NT_SUCCESS(status)) {
  132. ExFreePool(paths);
  133. ObDereferenceObject(fileObject);
  134. return status;
  135. }
  136. DosName->Length = (USHORT) paths->MultiSzLength - 2*sizeof(WCHAR);
  137. DosName->MaximumLength = DosName->Length + sizeof(WCHAR);
  138. DosName->Buffer = (PWCHAR) paths;
  139. RtlCopyMemory(paths, paths->MultiSz, DosName->Length);
  140. DosName->Buffer[DosName->Length/sizeof(WCHAR)] = 0;
  141. ObDereferenceObject(fileObject);
  142. return STATUS_SUCCESS;
  143. }