3 * Copyright (C) 2011-2012 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/mountmgr/device.c
22 * PURPOSE: Mount Manager - Device Control
23 * PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
26 /* INCLUDES *****************************************************************/
37 MountMgrChangeNotify(IN PDEVICE_EXTENSION DeviceExtension
,
42 PIO_STACK_LOCATION Stack
;
43 PMOUNTMGR_CHANGE_NOTIFY_INFO ChangeNotify
;
45 /* Get the I/O buffer */
46 Stack
= IoGetCurrentIrpStackLocation(Irp
);
47 ChangeNotify
= (PMOUNTMGR_CHANGE_NOTIFY_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
50 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO
) ||
51 Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO
))
53 return STATUS_INVALID_PARAMETER
;
56 /* If epic number doesn't match, just return now one */
57 if (DeviceExtension
->EpicNumber
!= ChangeNotify
->EpicNumber
)
59 ChangeNotify
->EpicNumber
= DeviceExtension
->EpicNumber
;
60 Irp
->IoStatus
.Information
= 0;
61 return STATUS_SUCCESS
;
64 /* If IRP is to be canceled, forget about that */
65 IoAcquireCancelSpinLock(&OldIrql
);
68 Status
= STATUS_CANCELLED
;
70 /* Otherwise queue the IRP to be notified with the next epic number change */
73 InsertTailList(&(DeviceExtension
->IrpListHead
), &(Irp
->Tail
.Overlay
.ListEntry
));
74 IoMarkIrpPending(Irp
);
75 IoSetCancelRoutine(Irp
, MountMgrCancel
);
76 Status
= STATUS_PENDING
;
78 IoReleaseCancelSpinLock(OldIrql
);
87 MountmgrWriteNoAutoMount(IN PDEVICE_EXTENSION DeviceExtension
)
89 ULONG Value
= DeviceExtension
->NoAutoMount
;
91 return RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
92 DeviceExtension
->RegistryPath
.Buffer
,
104 MountMgrSetAutoMount(IN PDEVICE_EXTENSION DeviceExtension
,
107 PIO_STACK_LOCATION Stack
;
108 PMOUNTMGR_SET_AUTO_MOUNT SetState
;
110 Stack
= IoGetCurrentIrpStackLocation(Irp
);
112 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_SET_AUTO_MOUNT
))
114 Irp
->IoStatus
.Information
= 0;
115 return STATUS_INVALID_PARAMETER
;
118 /* Only change if there's a real difference */
119 SetState
= (PMOUNTMGR_SET_AUTO_MOUNT
)Irp
->AssociatedIrp
.SystemBuffer
;
120 if (SetState
->NewState
== !DeviceExtension
->NoAutoMount
)
122 Irp
->IoStatus
.Information
= 0;
123 return STATUS_SUCCESS
;
126 /* Set new state; ! on purpose */
127 DeviceExtension
->NoAutoMount
= !SetState
->NewState
;
128 Irp
->IoStatus
.Information
= 0;
129 return MountmgrWriteNoAutoMount(DeviceExtension
);
136 MountMgrQueryAutoMount(IN PDEVICE_EXTENSION DeviceExtension
,
139 PIO_STACK_LOCATION Stack
;
140 PMOUNTMGR_QUERY_AUTO_MOUNT QueryState
;
142 Stack
= IoGetCurrentIrpStackLocation(Irp
);
144 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_QUERY_AUTO_MOUNT
))
146 Irp
->IoStatus
.Information
= 0;
147 return STATUS_INVALID_PARAMETER
;
150 QueryState
= (PMOUNTMGR_QUERY_AUTO_MOUNT
)Irp
->AssociatedIrp
.SystemBuffer
;
151 QueryState
->CurrentState
= !DeviceExtension
->NoAutoMount
;
152 Irp
->IoStatus
.Information
= sizeof(MOUNTMGR_QUERY_AUTO_MOUNT
);
154 return STATUS_SUCCESS
;
162 ScrubRegistryRoutine(IN PWSTR ValueName
,
165 IN ULONG ValueLength
,
167 IN PVOID EntryContext
)
170 PLIST_ENTRY NextEntry
;
171 PDEVICE_INFORMATION DeviceInfo
;
172 PBOOLEAN Continue
= EntryContext
;
173 PDEVICE_EXTENSION DeviceExtension
= Context
;
175 if (ValueType
!= REG_BINARY
)
177 return STATUS_SUCCESS
;
180 /* Delete values for devices that don't have the matching unique ID */
181 if (!IsListEmpty(&(DeviceExtension
->DeviceListHead
)))
183 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
184 NextEntry
!= &(DeviceExtension
->DeviceListHead
);
185 NextEntry
= NextEntry
->Flink
)
187 DeviceInfo
= CONTAINING_RECORD(NextEntry
,
191 if (!DeviceInfo
->UniqueId
|| DeviceInfo
->UniqueId
->UniqueIdLength
!= ValueLength
)
196 if (RtlCompareMemory(DeviceInfo
->UniqueId
->UniqueId
, ValueData
, ValueLength
) == ValueLength
)
198 return STATUS_SUCCESS
;
203 /* Wrong unique ID, scrub it */
204 Status
= RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
207 if (!NT_SUCCESS(Status
))
210 return STATUS_UNSUCCESSFUL
;
221 MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension
)
224 BOOLEAN Continue
= TRUE
;
225 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
229 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
230 QueryTable
[0].QueryRoutine
= ScrubRegistryRoutine
;
231 QueryTable
[0].EntryContext
= &Continue
;
234 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
248 MountMgrCreatePoint(IN PDEVICE_EXTENSION DeviceExtension
,
252 PIO_STACK_LOCATION Stack
;
253 PMOUNTMGR_CREATE_POINT_INPUT Point
;
254 UNICODE_STRING DeviceName
, SymbolicName
;
256 Stack
= IoGetCurrentIrpStackLocation(Irp
);
258 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_CREATE_POINT_INPUT
))
260 return STATUS_INVALID_PARAMETER
;
263 Point
= (PMOUNTMGR_CREATE_POINT_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
265 MaxLength
= MAX((Point
->DeviceNameOffset
+ Point
->DeviceNameLength
),
266 (Point
->SymbolicLinkNameLength
+ Point
->SymbolicLinkNameOffset
));
267 if (MaxLength
>= Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
269 return STATUS_INVALID_PARAMETER
;
272 /* Get all the strings and call the worker */
273 SymbolicName
.Length
= Point
->SymbolicLinkNameLength
;
274 SymbolicName
.MaximumLength
= Point
->SymbolicLinkNameLength
;
275 DeviceName
.Length
= Point
->DeviceNameLength
;
276 DeviceName
.MaximumLength
= Point
->DeviceNameLength
;
277 SymbolicName
.Buffer
= (PVOID
)((ULONG_PTR
)Point
+ Point
->SymbolicLinkNameOffset
);
278 DeviceName
.Buffer
= (PVOID
)((ULONG_PTR
)Point
+ Point
->DeviceNameOffset
);
280 return MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &DeviceName
);
287 MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension
,
290 PLIST_ENTRY NextEntry
;
291 PDEVICE_INFORMATION DeviceInformation
;
292 NTSTATUS ArrivalStatus
, Status
= STATUS_SUCCESS
;
294 /* No offline volumes, nothing more to do */
295 if (IsListEmpty(&(DeviceExtension
->OfflineDeviceListHead
)))
297 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
298 return STATUS_SUCCESS
;
301 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
303 /* Reactivate all the offline volumes */
304 while (!IsListEmpty(&(DeviceExtension
->OfflineDeviceListHead
)))
306 NextEntry
= RemoveHeadList(&(DeviceExtension
->OfflineDeviceListHead
));
307 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
309 ArrivalStatus
= MountMgrMountedDeviceArrival(DeviceExtension
,
310 &(DeviceInformation
->SymbolicName
),
311 DeviceInformation
->Volume
);
312 /* Then, remove them dead information */
313 MountMgrFreeDeadDeviceInfo(DeviceInformation
);
315 if (NT_SUCCESS(Status
))
317 Status
= ArrivalStatus
;
328 IsFtVolume(IN PUNICODE_STRING SymbolicName
)
333 PFILE_OBJECT FileObject
;
334 IO_STATUS_BLOCK IoStatusBlock
;
335 PARTITION_INFORMATION PartitionInfo
;
336 PDEVICE_OBJECT DeviceObject
, FileDeviceObject
;
338 /* Get device object */
339 Status
= IoGetDeviceObjectPointer(SymbolicName
,
340 FILE_READ_ATTRIBUTES
,
343 if (!NT_SUCCESS(Status
))
348 /* Get attached device */
349 FileDeviceObject
= FileObject
->DeviceObject
;
350 DeviceObject
= IoGetAttachedDeviceReference(FileDeviceObject
);
352 /* FT volume can't be removable */
353 if (FileDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
355 ObfDereferenceObject(DeviceObject
);
356 ObfDereferenceObject(FileObject
);
360 ObfDereferenceObject(FileObject
);
362 /* Get partition information */
363 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
364 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
369 sizeof(PartitionInfo
),
375 ObfDereferenceObject(DeviceObject
);
379 Status
= IofCallDriver(DeviceObject
, Irp
);
380 if (Status
== STATUS_PENDING
)
382 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
383 Status
= IoStatusBlock
.Status
;
386 ObfDereferenceObject(DeviceObject
);
387 if (!NT_SUCCESS(Status
))
392 /* Check if this is a FT volume */
393 return IsRecognizedPartition(PartitionInfo
.PartitionType
);
400 ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension
)
402 WCHAR NameBuffer
[DRIVE_LETTER_LENGTH
/ sizeof(WCHAR
)];
403 PLIST_ENTRY NextEntry
;
404 UNICODE_STRING SymbolicName
;
405 PDEVICE_INFORMATION DeviceInformation
;
407 /* No devices? Nothing to do! */
408 if (IsListEmpty(&(DeviceExtension
->DeviceListHead
)))
413 /* For all the devices */
414 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
415 NextEntry
!= &(DeviceExtension
->DeviceListHead
);
416 NextEntry
= NextEntry
->Flink
)
418 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
420 /* If no drive letter */
421 if (DeviceInformation
->SuggestedDriveLetter
== (UCHAR
)-1)
423 /* Ensure it has no entry yet */
424 if (!HasDriveLetter(DeviceInformation
) &&
425 !HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
428 CreateNoDriveLetterEntry(DeviceInformation
->UniqueId
);
431 DeviceInformation
->SuggestedDriveLetter
= 0;
433 /* Suggested letter & no entry */
434 else if (DeviceInformation
->SuggestedDriveLetter
&&
435 !HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
437 /* Just create a mount point */
438 SymbolicName
.Buffer
= NameBuffer
;
439 RtlCopyMemory(NameBuffer
, DosDevices
.Buffer
, DosDevices
.Length
);
440 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
441 NameBuffer
[COLON_POSITION
] = L
':';
442 SymbolicName
.Length
=
443 SymbolicName
.MaximumLength
= DRIVE_LETTER_LENGTH
;
445 MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &(DeviceInformation
->DeviceName
));
454 MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension
,
455 IN PUNICODE_STRING DeviceName
,
456 OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo
)
460 PLIST_ENTRY NextEntry
;
461 PMOUNTDEV_UNIQUE_ID UniqueId
;
462 BOOLEAN Removable
, GptDriveLetter
;
463 PDEVICE_INFORMATION DeviceInformation
;
464 WCHAR NameBuffer
[DRIVE_LETTER_LENGTH
];
465 PSYMLINK_INFORMATION SymlinkInformation
;
466 UNICODE_STRING TargetDeviceName
, SymbolicName
;
468 /* First, process suggested letters */
469 if (!DeviceExtension
->ProcessedSuggestions
)
471 ProcessSuggestedDriveLetters(DeviceExtension
);
472 DeviceExtension
->ProcessedSuggestions
= TRUE
;
475 /* Then, get information about the device */
476 Status
= QueryDeviceInformation(DeviceName
, &TargetDeviceName
, NULL
, &Removable
, &GptDriveLetter
, NULL
, NULL
, NULL
);
477 if (!NT_SUCCESS(Status
))
482 /* Ensure we have such device */
483 NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
484 while (NextEntry
!= &(DeviceExtension
->DeviceListHead
))
486 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
488 if (RtlCompareUnicodeString(&(DeviceInformation
->DeviceName
), &TargetDeviceName
, TRUE
) == 0)
493 NextEntry
= NextEntry
->Flink
;
496 if (NextEntry
== &(DeviceExtension
->DeviceListHead
))
498 FreePool(TargetDeviceName
.Buffer
);
499 return STATUS_OBJECT_NAME_NOT_FOUND
;
502 /* Now, mark we have assigned a letter (assumption) */
503 DeviceInformation
->LetterAssigned
=
504 DriveLetterInfo
->DriveLetterWasAssigned
= TRUE
;
506 /* Browse all the symlink to see if there's already a drive letter */
507 NextEntry
= DeviceInformation
->SymbolicLinksListHead
.Flink
;
508 while (NextEntry
!= &(DeviceInformation
->SymbolicLinksListHead
))
510 SymlinkInformation
= CONTAINING_RECORD(NextEntry
, SYMLINK_INFORMATION
, SymbolicLinksListEntry
);
512 /* This is a driver letter & online one, forget about new drive eltter */
513 if (IsDriveLetter(&(SymlinkInformation
->Name
)) && SymlinkInformation
->Online
)
515 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
516 DriveLetterInfo
->CurrentDriveLetter
= SymlinkInformation
->Name
.Buffer
[LETTER_POSITION
];
520 NextEntry
= NextEntry
->Flink
;
523 /* If we didn't find a drive letter online
524 * ensure there's no GPT drive letter nor no drive entry
526 if (NextEntry
== &(DeviceInformation
->SymbolicLinksListHead
))
528 if (GptDriveLetter
|| HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
530 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
531 DriveLetterInfo
->CurrentDriveLetter
= 0;
537 /* No, ensure that the device is not automonted nor removable */
538 if (!DeviceExtension
->NoAutoMount
&& !Removable
)
540 if (DriveLetterInfo
->DriveLetterWasAssigned
)
542 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
543 DriveLetterInfo
->CurrentDriveLetter
= 0;
549 if (!DriveLetterInfo
->DriveLetterWasAssigned
)
554 /* Now everything is fine, start processing */
555 if (RtlPrefixUnicodeString(&DeviceFloppy
, &TargetDeviceName
, TRUE
))
561 DriveLetter
= 'C' + RtlPrefixUnicodeString(&DeviceCdRom
, &TargetDeviceName
, TRUE
);
564 /* We cannot set NO drive letter */
565 ASSERT(DeviceInformation
->SuggestedDriveLetter
!= (UCHAR
)-1);
567 /* If we don't have suggested letter but it's a FT volume, fail */
568 if (!DeviceInformation
->SuggestedDriveLetter
&& IsFtVolume(&(DeviceInformation
->DeviceName
)))
570 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
571 DriveLetterInfo
->CurrentDriveLetter
= 0;
577 RtlCopyMemory(NameBuffer
, DosDevices
.Buffer
, DosDevices
.Length
);
578 NameBuffer
[COLON_POSITION
] = L
':';
579 SymbolicName
.Buffer
= NameBuffer
;
580 SymbolicName
.Length
=
581 SymbolicName
.MaximumLength
= DRIVE_LETTER_LENGTH
;
583 /* It's all prepared, create mount point */
584 if (DeviceInformation
->SuggestedDriveLetter
)
586 DriveLetterInfo
->CurrentDriveLetter
= DeviceInformation
->SuggestedDriveLetter
;
587 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
589 Status
= MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &TargetDeviceName
);
590 if (NT_SUCCESS(Status
))
596 /* It failed with this letter... Try another one! */
597 for (DriveLetterInfo
->CurrentDriveLetter
= DriveLetter
;
598 DriveLetterInfo
->CurrentDriveLetter
<= L
'Z';
599 DriveLetterInfo
->CurrentDriveLetter
++)
601 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
603 Status
= MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &TargetDeviceName
);
604 if (NT_SUCCESS(Status
))
610 /* We failed setting a letter */
611 if (DriveLetterInfo
->CurrentDriveLetter
> L
'Z')
613 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
614 DriveLetterInfo
->CurrentDriveLetter
= 0;
616 /* Try at least to add a no drive letter entry */
617 Status
= QueryDeviceInformation(&TargetDeviceName
, NULL
, &UniqueId
, NULL
, NULL
, NULL
, NULL
, NULL
);
618 if (NT_SUCCESS(Status
))
620 CreateNoDriveLetterEntry(UniqueId
);
626 FreePool(TargetDeviceName
.Buffer
);
628 return STATUS_SUCCESS
;
636 MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension
,
640 PIO_STACK_LOCATION Stack
;
641 UNICODE_STRING DeviceName
;
642 PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget
;
643 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation
;
645 Stack
= IoGetNextIrpStackLocation(Irp
);
648 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_DRIVE_LETTER_TARGET
) ||
649 Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION
))
651 return STATUS_INVALID_PARAMETER
;
654 DriveLetterTarget
= (PMOUNTMGR_DRIVE_LETTER_TARGET
)Irp
->AssociatedIrp
.SystemBuffer
;
655 if (DriveLetterTarget
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
657 return STATUS_INVALID_PARAMETER
;
660 /* Call the worker */
661 DeviceName
.Buffer
= DriveLetterTarget
->DeviceName
;
663 DeviceName
.MaximumLength
= DriveLetterTarget
->DeviceNameLength
;
665 Status
= MountMgrNextDriveLetterWorker(DeviceExtension
, &DeviceName
,
666 &DriveLetterInformation
);
667 if (NT_SUCCESS(Status
))
669 *(PMOUNTMGR_DRIVE_LETTER_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
=
670 DriveLetterInformation
;
671 Irp
->IoStatus
.Information
= sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION
);
682 MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName
,
685 IN ULONG ValueLength
,
687 IN PVOID EntryContext
)
689 UNICODE_STRING ValueString
;
690 PUNICODE_STRING SystemVolumeName
;
692 if (ValueType
!= REG_SZ
)
694 return STATUS_SUCCESS
;
697 RtlInitUnicodeString(&ValueString
, ValueData
);
698 SystemVolumeName
= Context
;
700 /* Return a string containing system volume name */
701 SystemVolumeName
->Length
= ValueString
.Length
;
702 SystemVolumeName
->MaximumLength
= ValueString
.Length
+ sizeof(WCHAR
);
703 SystemVolumeName
->Buffer
= AllocatePool(SystemVolumeName
->MaximumLength
);
704 if (SystemVolumeName
->Buffer
)
706 RtlCopyMemory(SystemVolumeName
->Buffer
, ValueData
, ValueString
.Length
);
707 SystemVolumeName
->Buffer
[ValueString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
710 return STATUS_SUCCESS
;
718 MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName
)
720 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
722 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
723 QueryTable
[0].QueryRoutine
= MountMgrQuerySystemVolumeNameQueryRoutine
;
724 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
725 QueryTable
[0].Name
= L
"SystemPartition";
727 SystemVolumeName
->Buffer
= NULL
;
729 RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
730 L
"\\Registry\\Machine\\System\\Setup",
735 if (SystemVolumeName
->Buffer
)
737 return STATUS_SUCCESS
;
740 return STATUS_UNSUCCESSFUL
;
747 MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension
)
750 PLIST_ENTRY NextEntry
;
751 UNICODE_STRING SystemVolumeName
;
752 PDEVICE_INFORMATION DeviceInformation
;
753 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation
;
755 /* First, get system volume name */
756 Status
= MountMgrQuerySystemVolumeName(&SystemVolumeName
);
758 /* If there are no device, it's all done */
759 if (IsListEmpty(&(DeviceExtension
->DeviceListHead
)))
761 if (NT_SUCCESS(Status
))
763 FreePool(SystemVolumeName
.Buffer
);
769 /* Now, for all the devices... */
770 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
771 NextEntry
!= &(DeviceExtension
->DeviceListHead
);
772 NextEntry
= NextEntry
->Flink
)
774 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
776 /* If the device doesn't have a letter assigned, do it! */
777 if (!DeviceInformation
->LetterAssigned
)
779 MountMgrNextDriveLetterWorker(DeviceExtension
,
780 &(DeviceInformation
->DeviceName
),
781 &DriveLetterInformation
);
784 /* If it was the system volume */
785 if (NT_SUCCESS(Status
) && RtlEqualUnicodeString(&SystemVolumeName
, &(DeviceInformation
->DeviceName
), TRUE
))
787 /* Keep track of it */
788 DeviceExtension
->DriveLetterData
= AllocatePool(DeviceInformation
->UniqueId
->UniqueIdLength
+
789 sizeof(MOUNTDEV_UNIQUE_ID
));
790 if (DeviceExtension
->DriveLetterData
)
792 RtlCopyMemory(DeviceExtension
->DriveLetterData
,
793 DeviceInformation
->UniqueId
,
794 DeviceInformation
->UniqueId
->UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
797 /* If it was not automount, ensure it gets mounted */
798 if (!DeviceExtension
->NoAutoMount
)
800 DeviceExtension
->NoAutoMount
= TRUE
;
802 MountMgrNextDriveLetterWorker(DeviceExtension
,
803 &(DeviceInformation
->DeviceName
),
804 &DriveLetterInformation
);
806 DeviceExtension
->NoAutoMount
= FALSE
;
811 if (NT_SUCCESS(Status
))
813 FreePool(SystemVolumeName
.Buffer
);
818 MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension
,
821 return STATUS_NOT_IMPLEMENTED
;
825 MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension
,
828 return STATUS_NOT_IMPLEMENTED
;
835 MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension
,
839 PIO_STACK_LOCATION Stack
;
840 UNICODE_STRING SymbolicName
;
841 PMOUNTMGR_TARGET_NAME Target
;
842 PDEVICE_INFORMATION DeviceInformation
;
844 Stack
= IoGetNextIrpStackLocation(Irp
);
847 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_TARGET_NAME
))
849 return STATUS_INVALID_PARAMETER
;
852 Target
= (PMOUNTMGR_TARGET_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
853 if (Target
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
855 return STATUS_INVALID_PARAMETER
;
858 SymbolicName
.Length
=
859 SymbolicName
.MaximumLength
= Target
->DeviceNameLength
;
860 SymbolicName
.Buffer
= Target
->DeviceName
;
862 /* Find the associated device */
863 Status
= FindDeviceInfo(DeviceExtension
, &SymbolicName
, FALSE
, &DeviceInformation
);
864 if (!NT_SUCCESS(Status
))
869 /* Mark we want to keep links */
870 DeviceInformation
->KeepLinks
= TRUE
;
872 return STATUS_SUCCESS
;
879 MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension
,
884 PIO_STACK_LOCATION Stack
;
885 UNICODE_STRING SymbolicName
;
886 PMOUNTMGR_TARGET_NAME Target
;
888 Stack
= IoGetNextIrpStackLocation(Irp
);
891 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_TARGET_NAME
))
893 return STATUS_INVALID_PARAMETER
;
896 Target
= (PMOUNTMGR_TARGET_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
897 if (Target
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
899 return STATUS_INVALID_PARAMETER
;
902 SymbolicName
.Length
=
903 SymbolicName
.MaximumLength
= Target
->DeviceNameLength
;
904 SymbolicName
.Buffer
= Target
->DeviceName
;
906 /* Disable hard errors */
907 OldState
= PsGetThreadHardErrorsAreDisabled(PsGetCurrentThread());
908 PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), TRUE
);
910 /* Call real worker */
911 Status
= MountMgrMountedDeviceArrival(DeviceExtension
, &SymbolicName
, TRUE
);
913 PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), OldState
);
922 MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension
,
926 PIO_STACK_LOCATION Stack
;
927 PMOUNTDEV_UNIQUE_ID UniqueId
;
928 PMOUNTMGR_MOUNT_POINT MountPoint
;
929 UNICODE_STRING SymbolicName
, DeviceName
;
931 Stack
= IoGetNextIrpStackLocation(Irp
);
933 /* Validate input... */
934 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINT
))
936 return STATUS_INVALID_PARAMETER
;
939 MountPoint
= (PMOUNTMGR_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
940 if (!MountPoint
->SymbolicLinkNameLength
)
942 MountPoint
->SymbolicLinkNameOffset
= 0;
945 if (!MountPoint
->UniqueIdLength
)
947 MountPoint
->UniqueIdOffset
= 0;
950 if (!MountPoint
->DeviceNameLength
)
952 MountPoint
->DeviceNameOffset
= 0;
955 /* Addresses can't be odd */
956 if ((MountPoint
->SymbolicLinkNameOffset
& 1) ||
957 (MountPoint
->SymbolicLinkNameLength
& 1))
959 return STATUS_INVALID_PARAMETER
;
962 if ((MountPoint
->UniqueIdOffset
& 1) ||
963 (MountPoint
->UniqueIdLength
& 1))
965 return STATUS_INVALID_PARAMETER
;
968 if ((MountPoint
->DeviceNameOffset
& 1) ||
969 (MountPoint
->DeviceNameLength
& 1))
971 return STATUS_INVALID_PARAMETER
;
974 /* We can't go beyond */
975 if (MountPoint
->SymbolicLinkNameLength
+ MountPoint
->UniqueIdLength
+
976 MountPoint
->DeviceNameLength
< Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
978 return STATUS_INVALID_PARAMETER
;
981 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINTS
))
983 return STATUS_INVALID_PARAMETER
;
986 /* If caller provided a Symlink, use it */
987 if (MountPoint
->SymbolicLinkNameLength
!= 0)
989 if (MountPoint
->SymbolicLinkNameLength
> MAXSHORT
)
991 return STATUS_INVALID_PARAMETER
;
994 SymbolicName
.Length
= MountPoint
->SymbolicLinkNameLength
;
995 SymbolicName
.MaximumLength
= MountPoint
->SymbolicLinkNameLength
+ sizeof(WCHAR
);
996 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
997 if (!SymbolicName
.Buffer
)
999 return STATUS_INSUFFICIENT_RESOURCES
;
1002 RtlCopyMemory(SymbolicName
.Buffer
,
1003 (PWSTR
)((ULONG_PTR
)MountPoint
+ MountPoint
->SymbolicLinkNameOffset
),
1004 SymbolicName
.Length
);
1005 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1007 /* Query links using it */
1008 Status
= QueryPointsFromSymbolicLinkName(DeviceExtension
, &SymbolicName
, Irp
);
1009 FreePool(SymbolicName
.Buffer
);
1011 /* If user provided an unique ID */
1012 else if (MountPoint
->UniqueIdLength
!= 0)
1014 UniqueId
= AllocatePool(MountPoint
->UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1017 return STATUS_INSUFFICIENT_RESOURCES
;
1020 UniqueId
->UniqueIdLength
= MountPoint
->UniqueIdLength
;
1021 RtlCopyMemory(UniqueId
->UniqueId
,
1022 (PVOID
)((ULONG_PTR
)MountPoint
+ MountPoint
->UniqueIdOffset
),
1023 MountPoint
->UniqueIdLength
);
1025 /* Query links using it */
1026 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, UniqueId
, NULL
);
1029 /* If caller provided a device name */
1030 else if (MountPoint
->DeviceNameLength
!= 0)
1032 if (MountPoint
->DeviceNameLength
> MAXSHORT
)
1034 return STATUS_INVALID_PARAMETER
;
1037 DeviceName
.Length
= MountPoint
->DeviceNameLength
;
1038 DeviceName
.MaximumLength
= MountPoint
->DeviceNameLength
+ sizeof(WCHAR
);
1039 DeviceName
.Buffer
= AllocatePool(DeviceName
.MaximumLength
);
1040 if (!DeviceName
.Buffer
)
1042 return STATUS_INSUFFICIENT_RESOURCES
;
1045 RtlCopyMemory(DeviceName
.Buffer
,
1046 (PWSTR
)((ULONG_PTR
)MountPoint
+ MountPoint
->DeviceNameOffset
),
1048 DeviceName
.Buffer
[DeviceName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1050 /* Query links using it */
1051 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, NULL
, &DeviceName
);
1052 FreePool(DeviceName
.Buffer
);
1056 /* Otherwise, query all links */
1057 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, NULL
, NULL
);
1067 MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension
,
1072 BOOLEAN CreateNoDrive
;
1073 PIO_STACK_LOCATION Stack
;
1074 PMOUNTDEV_UNIQUE_ID UniqueId
;
1075 PMOUNTMGR_MOUNT_POINT MountPoint
;
1076 PMOUNTMGR_MOUNT_POINTS MountPoints
;
1077 UNICODE_STRING SymbolicName
, DeviceName
;
1079 Stack
= IoGetNextIrpStackLocation(Irp
);
1081 /* Validate input */
1082 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINT
))
1084 return STATUS_INVALID_PARAMETER
;
1088 MountPoint
= (PMOUNTMGR_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
1089 CreateNoDrive
= (MountPoint
->SymbolicLinkNameOffset
&& MountPoint
->SymbolicLinkNameLength
);
1091 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1092 if (!NT_SUCCESS(Status
))
1097 /* For all the points matching the request */
1098 MountPoints
= (PMOUNTMGR_MOUNT_POINTS
)Irp
->AssociatedIrp
.SystemBuffer
;
1099 for (Link
= 0; Link
< MountPoints
->NumberOfMountPoints
; Link
++)
1101 SymbolicName
.Length
= MountPoints
->MountPoints
[Link
].SymbolicLinkNameLength
;
1102 SymbolicName
.MaximumLength
= SymbolicName
.Length
+ sizeof(WCHAR
);
1103 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
1104 if (!SymbolicName
.Buffer
)
1106 return STATUS_INSUFFICIENT_RESOURCES
;
1109 RtlCopyMemory(SymbolicName
.Buffer
,
1110 (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].SymbolicLinkNameOffset
),
1111 SymbolicName
.Length
);
1112 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1114 /* Create a no drive entry for the drive letters */
1115 if (CreateNoDrive
&& IsDriveLetter(&SymbolicName
))
1117 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1120 UniqueId
->UniqueIdLength
= MountPoints
->MountPoints
[Link
].UniqueIdLength
;
1121 RtlCopyMemory(UniqueId
->UniqueId
,
1122 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1123 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1125 CreateNoDriveLetterEntry(UniqueId
);
1130 /* If there are no link any more, and no need to create a no drive entry */
1131 if (Link
== 0 && !CreateNoDrive
)
1133 /* Then, delete everything */
1134 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1137 RtlCopyMemory(UniqueId
,
1138 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1139 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1141 DeleteNoDriveLetterEntry(UniqueId
);
1146 /* Delete all the information about the mount point */
1147 GlobalDeleteSymbolicLink(&SymbolicName
);
1148 DeleteSymbolicLinkNameFromMemory(DeviceExtension
, &SymbolicName
, FALSE
);
1149 RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE
, DatabasePath
, SymbolicName
.Buffer
);
1150 FreePool(SymbolicName
.Buffer
);
1152 /* Notify the change */
1153 DeviceName
.Length
= DeviceName
.MaximumLength
=
1154 MountPoints
->MountPoints
[Link
].DeviceNameLength
;
1155 DeviceName
.Buffer
= (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].DeviceNameOffset
);
1156 MountMgrNotifyNameChange(DeviceExtension
, &DeviceName
, TRUE
);
1159 MountMgrNotify(DeviceExtension
);
1168 MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension
,
1173 UNICODE_STRING SymbolicName
;
1174 PMOUNTDEV_UNIQUE_ID UniqueId
;
1175 PMOUNTMGR_MOUNT_POINTS MountPoints
;
1178 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1179 if (!NT_SUCCESS(Status
))
1184 MountPoints
= (PMOUNTMGR_MOUNT_POINTS
)Irp
->AssociatedIrp
.SystemBuffer
;
1185 if (MountPoints
->NumberOfMountPoints
== 0)
1190 /* For all the mount points */
1191 for (Link
= 0; Link
< MountPoints
->NumberOfMountPoints
; Link
++)
1193 SymbolicName
.Length
= MountPoints
->MountPoints
[Link
].SymbolicLinkNameLength
;
1194 SymbolicName
.MaximumLength
= SymbolicName
.Length
+ sizeof(WCHAR
);
1195 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
1196 if (!SymbolicName
.Buffer
)
1198 return STATUS_INSUFFICIENT_RESOURCES
;
1201 RtlCopyMemory(SymbolicName
.Buffer
,
1202 (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].SymbolicLinkNameOffset
),
1203 SymbolicName
.Length
);
1204 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1206 /* If the only mount point is a drive letter, then create a no letter drive entry */
1207 if (MountPoints
->NumberOfMountPoints
== 1 && IsDriveLetter(&SymbolicName
))
1209 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1212 UniqueId
->UniqueIdLength
= MountPoints
->MountPoints
[Link
].UniqueIdLength
;
1213 RtlCopyMemory(UniqueId
->UniqueId
,
1214 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1215 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1217 CreateNoDriveLetterEntry(UniqueId
);
1222 /* Simply delete mount point from DB */
1223 DeleteSymbolicLinkNameFromMemory(DeviceExtension
, &SymbolicName
, TRUE
);
1224 RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE
, DatabasePath
, SymbolicName
.Buffer
);
1225 FreePool(SymbolicName
.Buffer
);
1235 MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension
,
1237 IN NTSTATUS LockStatus
,
1238 OUT PUNICODE_STRING SourceDeviceName
,
1239 OUT PUNICODE_STRING SourceSymbolicName
,
1240 OUT PUNICODE_STRING TargetVolumeName
)
1244 PFILE_OBJECT FileObject
;
1245 PIO_STACK_LOCATION Stack
;
1246 ULONG Length
, SavedLength
;
1247 BOOLEAN FOReferenced
= FALSE
;
1248 IO_STATUS_BLOCK IoStatusBlock
;
1249 OBJECT_ATTRIBUTES ObjectAttributes
;
1250 PDEVICE_INFORMATION DeviceInformation
;
1251 OBJECT_NAME_INFORMATION ObjectNameInfo
;
1252 FILE_FS_DEVICE_INFORMATION FsDeviceInfo
;
1253 PFILE_NAME_INFORMATION FileNameInfo
= NULL
;
1254 PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint
;
1255 POBJECT_NAME_INFORMATION ObjectNameInfoPtr
= NULL
;
1256 UNICODE_STRING SourceVolumeName
, TargetDeviceName
;
1258 Stack
= IoGetNextIrpStackLocation(Irp
);
1260 /* Validate input */
1261 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_VOLUME_MOUNT_POINT
))
1263 return STATUS_INVALID_PARAMETER
;
1266 VolumeMountPoint
= (PMOUNTMGR_VOLUME_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
1268 if (VolumeMountPoint
->SourceVolumeNameLength
+ VolumeMountPoint
->TargetVolumeNameLength
<
1269 Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1271 return STATUS_INVALID_PARAMETER
;
1274 /* Get source volume name */
1275 SourceVolumeName
.Length
=
1276 SourceVolumeName
.MaximumLength
= VolumeMountPoint
->SourceVolumeNameLength
;
1277 SourceVolumeName
.Buffer
= (PWSTR
)((ULONG_PTR
)VolumeMountPoint
+ VolumeMountPoint
->SourceVolumeNameOffset
);
1279 InitializeObjectAttributes(&ObjectAttributes
,
1281 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
1286 Status
= ZwOpenFile(&Handle
,
1287 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
1290 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1291 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_REPARSE_POINT
);
1292 if (!NT_SUCCESS(Status
))
1297 TargetDeviceName
.Buffer
= NULL
;
1299 /* Query its attributes */
1300 Status
= ZwQueryVolumeInformationFile(Handle
,
1303 sizeof(FsDeviceInfo
),
1304 FileFsDeviceInformation
);
1305 if (!NT_SUCCESS(Status
))
1310 if (FsDeviceInfo
.DeviceType
!= FILE_DEVICE_DISK
&& FsDeviceInfo
.DeviceType
!= FILE_DEVICE_VIRTUAL_DISK
)
1315 if (FsDeviceInfo
.Characteristics
!= (FILE_REMOTE_DEVICE
| FILE_REMOVABLE_MEDIA
))
1321 Status
= ObReferenceObjectByHandle(Handle
, 0, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
1322 if (!NT_SUCCESS(Status
))
1326 FOReferenced
= TRUE
;
1329 FileNameInfo
= AllocatePool(sizeof(FILE_NAME_INFORMATION
));
1332 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1336 Status
= ZwQueryInformationFile(Handle
, &IoStatusBlock
, FileNameInfo
,
1337 sizeof(FILE_NAME_INFORMATION
),
1338 FileNameInformation
);
1339 if (Status
== STATUS_BUFFER_OVERFLOW
)
1341 /* Now we have real length, use it */
1342 Length
= FileNameInfo
->FileNameLength
;
1343 FreePool(FileNameInfo
);
1345 FileNameInfo
= AllocatePool(sizeof(FILE_NAME_INFORMATION
) + Length
);
1348 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1352 /* Really query file name */
1353 Status
= ZwQueryInformationFile(Handle
, &IoStatusBlock
, FileNameInfo
,
1354 sizeof(FILE_NAME_INFORMATION
) + Length
,
1355 FileNameInformation
);
1358 if (!NT_SUCCESS(Status
))
1363 /* Get symbolic name */
1364 ObjectNameInfoPtr
= &ObjectNameInfo
;
1365 SavedLength
= sizeof(OBJECT_NAME_INFORMATION
);
1366 Status
= ObQueryNameString(FileObject
->DeviceObject
, ObjectNameInfoPtr
, sizeof(OBJECT_NAME_INFORMATION
), &Length
);
1367 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
1369 /* Once again, with proper size, it works better */
1370 ObjectNameInfoPtr
= AllocatePool(Length
);
1371 if (!ObjectNameInfoPtr
)
1373 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1377 SavedLength
= Length
;
1378 Status
= ObQueryNameString(FileObject
->DeviceObject
, ObjectNameInfoPtr
, SavedLength
, &Length
);
1381 if (!NT_SUCCESS(Status
))
1386 /* Now, query the device name */
1387 Status
= QueryDeviceInformation(&ObjectNameInfoPtr
->Name
, SourceDeviceName
,
1388 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1389 if (!NT_SUCCESS(Status
))
1394 /* For target volume name, use input */
1395 TargetVolumeName
->Length
=
1396 TargetVolumeName
->MaximumLength
= VolumeMountPoint
->TargetVolumeNameLength
;
1397 TargetVolumeName
->Buffer
= (PWSTR
)((ULONG_PTR
)VolumeMountPoint
+ VolumeMountPoint
->TargetVolumeNameOffset
);
1399 /* Query its device name */
1400 Status
= QueryDeviceInformation(TargetVolumeName
, &TargetDeviceName
,
1401 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1402 if (!NT_SUCCESS(Status
))
1407 /* Return symbolic name */
1408 SourceSymbolicName
->Length
=
1409 SourceSymbolicName
->MaximumLength
= FileNameInfo
->FileNameLength
;
1410 SourceSymbolicName
->Buffer
= (PWSTR
)FileNameInfo
;
1411 /* memmove allows memory overlap */
1412 RtlMoveMemory(SourceSymbolicName
->Buffer
, FileNameInfo
->FileName
, SourceSymbolicName
->Length
);
1413 FileNameInfo
= NULL
;
1415 /* Notify the change */
1416 MountMgrNotify(DeviceExtension
);
1417 MountMgrNotifyNameChange(DeviceExtension
, &TargetDeviceName
, TRUE
);
1419 /* If we are locked, sync databases if possible */
1420 if (NT_SUCCESS(LockStatus
))
1422 Status
= FindDeviceInfo(DeviceExtension
, SourceDeviceName
, FALSE
, &DeviceInformation
);
1423 if (NT_SUCCESS(Status
))
1425 ReconcileThisDatabaseWithMaster(DeviceExtension
, DeviceInformation
);
1429 Status
= STATUS_PENDING
;
1434 if (TargetDeviceName
.Buffer
)
1436 FreePool(TargetDeviceName
.Buffer
);
1439 if (ObjectNameInfoPtr
&& ObjectNameInfoPtr
!= &ObjectNameInfo
)
1441 FreePool(ObjectNameInfoPtr
);
1446 FreePool(FileNameInfo
);
1451 ObfDereferenceObject(FileObject
);
1458 MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension
,
1460 IN NTSTATUS LockStatus
)
1462 return STATUS_NOT_IMPLEMENTED
;
1466 MountMgrVolumeMountPointDeleted(IN PDEVICE_EXTENSION DeviceExtension
,
1468 IN NTSTATUS LockStatus
)
1470 return STATUS_NOT_IMPLEMENTED
;
1478 MountMgrDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1481 PIO_STACK_LOCATION Stack
;
1482 NTSTATUS Status
, LockStatus
;
1483 PDEVICE_EXTENSION DeviceExtension
;
1485 Stack
= IoGetNextIrpStackLocation(Irp
);
1486 DeviceExtension
= DeviceObject
->DeviceExtension
;
1488 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1490 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
1492 case IOCTL_MOUNTMGR_CREATE_POINT
:
1493 Status
= MountMgrCreatePoint(DeviceExtension
, Irp
);
1496 case IOCTL_MOUNTMGR_DELETE_POINTS
:
1497 Status
= MountMgrDeletePoints(DeviceExtension
, Irp
);
1499 case IOCTL_MOUNTMGR_QUERY_POINTS
:
1500 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1503 case IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY
:
1504 Status
= MountMgrDeletePointsDbOnly(DeviceExtension
, Irp
);
1507 case IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
:
1508 Status
= MountMgrNextDriveLetter(DeviceExtension
, Irp
);
1511 case IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
:
1512 DeviceExtension
->AutomaticDriveLetter
= TRUE
;
1513 Status
= STATUS_SUCCESS
;
1515 MountMgrAssignDriveLetters(DeviceExtension
);
1516 ReconcileAllDatabasesWithMaster(DeviceExtension
);
1517 WaitForOnlinesToComplete(DeviceExtension
);
1520 case IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED
:
1521 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1523 LockStatus
= WaitForRemoteDatabaseSemaphore(DeviceExtension
);
1524 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1525 Status
= MountMgrVolumeMountPointCreated(DeviceExtension
, Irp
, LockStatus
);
1526 if (NT_SUCCESS(LockStatus
))
1528 ReleaseRemoteDatabaseSemaphore(DeviceExtension
);
1533 case IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED
:
1534 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1536 LockStatus
= WaitForRemoteDatabaseSemaphore(DeviceExtension
);
1537 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1538 Status
= MountMgrVolumeMountPointDeleted(DeviceExtension
, Irp
, LockStatus
);
1539 if (NT_SUCCESS(LockStatus
))
1541 ReleaseRemoteDatabaseSemaphore(DeviceExtension
);
1546 case IOCTL_MOUNTMGR_CHANGE_NOTIFY
:
1547 Status
= MountMgrChangeNotify(DeviceExtension
, Irp
);
1550 case IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE
:
1551 Status
= MountMgrKeepLinksWhenOffline(DeviceExtension
, Irp
);
1554 case IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES
:
1555 Status
= MountMgrCheckUnprocessedVolumes(DeviceExtension
, Irp
);
1558 case IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
:
1559 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1560 Status
= MountMgrVolumeArrivalNotification(DeviceExtension
, Irp
);
1563 case IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
:
1564 Status
= MountMgrQueryDosVolumePath(DeviceExtension
, Irp
);
1567 case IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
:
1568 Status
= MountMgrQueryDosVolumePaths(DeviceExtension
, Irp
);
1571 case IOCTL_MOUNTMGR_SCRUB_REGISTRY
:
1572 Status
= MountMgrScrubRegistry(DeviceExtension
);
1575 case IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT
:
1576 Status
= MountMgrQueryAutoMount(DeviceExtension
, Irp
);
1579 case IOCTL_MOUNTMGR_SET_AUTO_MOUNT
:
1580 Status
= MountMgrSetAutoMount(DeviceExtension
, Irp
);
1584 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1587 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1589 if (Status
!= STATUS_PENDING
)
1597 Irp
->IoStatus
.Status
= Status
;
1598 IofCompleteRequest(Irp
, IO_NO_INCREMENT
);