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)
28 #define MAX_DEVICES 0x3E8 /* Matches 1000 devices */
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
)
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
,
249 MountMgrCreatePoint(IN PDEVICE_EXTENSION DeviceExtension
,
253 PIO_STACK_LOCATION Stack
;
254 PMOUNTMGR_CREATE_POINT_INPUT Point
;
255 UNICODE_STRING DeviceName
, SymbolicName
;
257 Stack
= IoGetCurrentIrpStackLocation(Irp
);
259 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_CREATE_POINT_INPUT
))
261 return STATUS_INVALID_PARAMETER
;
264 Point
= (PMOUNTMGR_CREATE_POINT_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
266 MaxLength
= MAX((Point
->DeviceNameOffset
+ Point
->DeviceNameLength
),
267 (Point
->SymbolicLinkNameLength
+ Point
->SymbolicLinkNameOffset
));
268 if (MaxLength
>= Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
270 return STATUS_INVALID_PARAMETER
;
273 /* Get all the strings and call the worker */
274 SymbolicName
.Length
= Point
->SymbolicLinkNameLength
;
275 SymbolicName
.MaximumLength
= Point
->SymbolicLinkNameLength
;
276 DeviceName
.Length
= Point
->DeviceNameLength
;
277 DeviceName
.MaximumLength
= Point
->DeviceNameLength
;
278 SymbolicName
.Buffer
= (PVOID
)((ULONG_PTR
)Point
+ Point
->SymbolicLinkNameOffset
);
279 DeviceName
.Buffer
= (PVOID
)((ULONG_PTR
)Point
+ Point
->DeviceNameOffset
);
281 return MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &DeviceName
);
288 MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension
,
291 PLIST_ENTRY NextEntry
;
292 PDEVICE_INFORMATION DeviceInformation
;
293 NTSTATUS ArrivalStatus
, Status
= STATUS_SUCCESS
;
295 UNREFERENCED_PARAMETER(Irp
);
297 /* No offline volumes, nothing more to do */
298 if (IsListEmpty(&(DeviceExtension
->OfflineDeviceListHead
)))
300 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
301 return STATUS_SUCCESS
;
304 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
306 /* Reactivate all the offline volumes */
307 while (!IsListEmpty(&(DeviceExtension
->OfflineDeviceListHead
)))
309 NextEntry
= RemoveHeadList(&(DeviceExtension
->OfflineDeviceListHead
));
310 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
312 ArrivalStatus
= MountMgrMountedDeviceArrival(DeviceExtension
,
313 &(DeviceInformation
->SymbolicName
),
314 DeviceInformation
->Volume
);
315 /* Then, remove them dead information */
316 MountMgrFreeDeadDeviceInfo(DeviceInformation
);
318 if (NT_SUCCESS(Status
))
320 Status
= ArrivalStatus
;
331 IsFtVolume(IN PUNICODE_STRING SymbolicName
)
336 PFILE_OBJECT FileObject
;
337 IO_STATUS_BLOCK IoStatusBlock
;
338 PARTITION_INFORMATION PartitionInfo
;
339 PDEVICE_OBJECT DeviceObject
, FileDeviceObject
;
341 /* Get device object */
342 Status
= IoGetDeviceObjectPointer(SymbolicName
,
343 FILE_READ_ATTRIBUTES
,
346 if (!NT_SUCCESS(Status
))
351 /* Get attached device */
352 FileDeviceObject
= FileObject
->DeviceObject
;
353 DeviceObject
= IoGetAttachedDeviceReference(FileDeviceObject
);
355 /* FT volume can't be removable */
356 if (FileDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
358 ObDereferenceObject(DeviceObject
);
359 ObDereferenceObject(FileObject
);
363 ObDereferenceObject(FileObject
);
365 /* Get partition information */
366 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
367 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
372 sizeof(PartitionInfo
),
378 ObDereferenceObject(DeviceObject
);
382 Status
= IoCallDriver(DeviceObject
, Irp
);
383 if (Status
== STATUS_PENDING
)
385 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
386 Status
= IoStatusBlock
.Status
;
389 ObDereferenceObject(DeviceObject
);
390 if (!NT_SUCCESS(Status
))
395 /* Check if this is a FT volume */
396 return IsRecognizedPartition(PartitionInfo
.PartitionType
);
403 ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension
)
405 WCHAR NameBuffer
[DRIVE_LETTER_LENGTH
/ sizeof(WCHAR
)];
406 PLIST_ENTRY NextEntry
;
407 UNICODE_STRING SymbolicName
;
408 PDEVICE_INFORMATION DeviceInformation
;
410 /* No devices? Nothing to do! */
411 if (IsListEmpty(&(DeviceExtension
->DeviceListHead
)))
416 /* For all the devices */
417 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
418 NextEntry
!= &(DeviceExtension
->DeviceListHead
);
419 NextEntry
= NextEntry
->Flink
)
421 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
423 /* If no drive letter */
424 if (DeviceInformation
->SuggestedDriveLetter
== (UCHAR
)-1)
426 /* Ensure it has no entry yet */
427 if (!HasDriveLetter(DeviceInformation
) &&
428 !HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
431 CreateNoDriveLetterEntry(DeviceInformation
->UniqueId
);
434 DeviceInformation
->SuggestedDriveLetter
= 0;
436 /* Suggested letter & no entry */
437 else if (DeviceInformation
->SuggestedDriveLetter
&&
438 !HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
440 /* Just create a mount point */
441 SymbolicName
.Buffer
= NameBuffer
;
442 RtlCopyMemory(NameBuffer
, DosDevices
.Buffer
, DosDevices
.Length
);
443 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
444 NameBuffer
[COLON_POSITION
] = L
':';
445 SymbolicName
.Length
=
446 SymbolicName
.MaximumLength
= DRIVE_LETTER_LENGTH
;
448 MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &(DeviceInformation
->DeviceName
));
457 MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension
,
458 IN PUNICODE_STRING DeviceName
,
459 OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo
)
463 PLIST_ENTRY NextEntry
;
464 PMOUNTDEV_UNIQUE_ID UniqueId
;
465 BOOLEAN Removable
, GptDriveLetter
;
466 PDEVICE_INFORMATION DeviceInformation
;
467 WCHAR NameBuffer
[DRIVE_LETTER_LENGTH
];
468 PSYMLINK_INFORMATION SymlinkInformation
;
469 UNICODE_STRING TargetDeviceName
, SymbolicName
;
471 /* First, process suggested letters */
472 if (!DeviceExtension
->ProcessedSuggestions
)
474 ProcessSuggestedDriveLetters(DeviceExtension
);
475 DeviceExtension
->ProcessedSuggestions
= TRUE
;
478 /* Then, get information about the device */
479 Status
= QueryDeviceInformation(DeviceName
, &TargetDeviceName
, NULL
, &Removable
, &GptDriveLetter
, NULL
, NULL
, NULL
);
480 if (!NT_SUCCESS(Status
))
485 /* Ensure we have such device */
486 NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
487 while (NextEntry
!= &(DeviceExtension
->DeviceListHead
))
489 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
491 if (RtlCompareUnicodeString(&(DeviceInformation
->DeviceName
), &TargetDeviceName
, TRUE
) == 0)
496 NextEntry
= NextEntry
->Flink
;
499 if (NextEntry
== &(DeviceExtension
->DeviceListHead
))
501 FreePool(TargetDeviceName
.Buffer
);
502 return STATUS_OBJECT_NAME_NOT_FOUND
;
505 /* Now, mark we have assigned a letter (assumption) */
506 DeviceInformation
->LetterAssigned
=
507 DriveLetterInfo
->DriveLetterWasAssigned
= TRUE
;
509 /* Browse all the symlink to see if there's already a drive letter */
510 NextEntry
= DeviceInformation
->SymbolicLinksListHead
.Flink
;
511 while (NextEntry
!= &(DeviceInformation
->SymbolicLinksListHead
))
513 SymlinkInformation
= CONTAINING_RECORD(NextEntry
, SYMLINK_INFORMATION
, SymbolicLinksListEntry
);
515 /* This is a driver letter & online one, forget about new drive eltter */
516 if (IsDriveLetter(&(SymlinkInformation
->Name
)) && SymlinkInformation
->Online
)
518 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
519 DriveLetterInfo
->CurrentDriveLetter
= (CHAR
)SymlinkInformation
->Name
.Buffer
[LETTER_POSITION
];
523 NextEntry
= NextEntry
->Flink
;
526 /* If we didn't find a drive letter online
527 * ensure there's no GPT drive letter nor no drive entry
529 if (NextEntry
== &(DeviceInformation
->SymbolicLinksListHead
))
531 if (GptDriveLetter
|| HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
533 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
534 DriveLetterInfo
->CurrentDriveLetter
= 0;
540 /* No, ensure that the device is not automonted nor removable */
541 if (!DeviceExtension
->NoAutoMount
&& !Removable
)
543 if (DriveLetterInfo
->DriveLetterWasAssigned
)
545 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
546 DriveLetterInfo
->CurrentDriveLetter
= 0;
552 if (!DriveLetterInfo
->DriveLetterWasAssigned
)
557 /* Now everything is fine, start processing */
559 if (RtlPrefixUnicodeString(&DeviceFloppy
, &TargetDeviceName
, TRUE
))
561 /* If the device is a floppy, start with letter A */
564 else if (RtlPrefixUnicodeString(&DeviceCdRom
, &TargetDeviceName
, TRUE
))
566 /* If the device is a CD-ROM, start with letter D */
571 /* Finally, if it's a disk, use C */
575 /* We cannot set NO drive letter */
576 ASSERT(DeviceInformation
->SuggestedDriveLetter
!= (UCHAR
)-1);
578 /* If we don't have suggested letter but it's a FT volume, fail */
579 if (!DeviceInformation
->SuggestedDriveLetter
&& IsFtVolume(&(DeviceInformation
->DeviceName
)))
581 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
582 DriveLetterInfo
->CurrentDriveLetter
= 0;
588 RtlCopyMemory(NameBuffer
, DosDevices
.Buffer
, DosDevices
.Length
);
589 NameBuffer
[COLON_POSITION
] = L
':';
590 SymbolicName
.Buffer
= NameBuffer
;
591 SymbolicName
.Length
=
592 SymbolicName
.MaximumLength
= DRIVE_LETTER_LENGTH
;
594 /* It's all prepared, create mount point */
595 if (DeviceInformation
->SuggestedDriveLetter
)
597 DriveLetterInfo
->CurrentDriveLetter
= DeviceInformation
->SuggestedDriveLetter
;
598 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
600 Status
= MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &TargetDeviceName
);
601 if (NT_SUCCESS(Status
))
607 /* It failed with this letter... Try another one! */
608 for (DriveLetterInfo
->CurrentDriveLetter
= DriveLetter
;
609 DriveLetterInfo
->CurrentDriveLetter
<= L
'Z';
610 DriveLetterInfo
->CurrentDriveLetter
++)
612 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
614 Status
= MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &TargetDeviceName
);
615 if (NT_SUCCESS(Status
))
621 /* We failed setting a letter */
622 if (DriveLetterInfo
->CurrentDriveLetter
> L
'Z')
624 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
625 DriveLetterInfo
->CurrentDriveLetter
= 0;
627 /* Try at least to add a no drive letter entry */
628 Status
= QueryDeviceInformation(&TargetDeviceName
, NULL
, &UniqueId
, NULL
, NULL
, NULL
, NULL
, NULL
);
629 if (NT_SUCCESS(Status
))
631 CreateNoDriveLetterEntry(UniqueId
);
637 FreePool(TargetDeviceName
.Buffer
);
639 return STATUS_SUCCESS
;
647 MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension
,
651 PIO_STACK_LOCATION Stack
;
652 UNICODE_STRING DeviceName
;
653 PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget
;
654 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation
;
656 Stack
= IoGetCurrentIrpStackLocation(Irp
);
659 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_DRIVE_LETTER_TARGET
) ||
660 Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION
))
662 return STATUS_INVALID_PARAMETER
;
665 DriveLetterTarget
= (PMOUNTMGR_DRIVE_LETTER_TARGET
)Irp
->AssociatedIrp
.SystemBuffer
;
666 if (DriveLetterTarget
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
668 return STATUS_INVALID_PARAMETER
;
671 /* Call the worker */
672 DeviceName
.Buffer
= DriveLetterTarget
->DeviceName
;
674 DeviceName
.MaximumLength
= DriveLetterTarget
->DeviceNameLength
;
676 Status
= MountMgrNextDriveLetterWorker(DeviceExtension
, &DeviceName
,
677 &DriveLetterInformation
);
678 if (NT_SUCCESS(Status
))
680 *(PMOUNTMGR_DRIVE_LETTER_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
=
681 DriveLetterInformation
;
682 Irp
->IoStatus
.Information
= sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION
);
693 MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName
,
696 IN ULONG ValueLength
,
698 IN PVOID EntryContext
)
700 UNICODE_STRING ValueString
;
701 PUNICODE_STRING SystemVolumeName
;
703 UNREFERENCED_PARAMETER(ValueName
);
704 UNREFERENCED_PARAMETER(ValueLength
);
705 UNREFERENCED_PARAMETER(EntryContext
);
707 if (ValueType
!= REG_SZ
)
709 return STATUS_SUCCESS
;
712 RtlInitUnicodeString(&ValueString
, ValueData
);
713 SystemVolumeName
= Context
;
715 /* Return a string containing system volume name */
716 SystemVolumeName
->Length
= ValueString
.Length
;
717 SystemVolumeName
->MaximumLength
= ValueString
.Length
+ sizeof(WCHAR
);
718 SystemVolumeName
->Buffer
= AllocatePool(SystemVolumeName
->MaximumLength
);
719 if (SystemVolumeName
->Buffer
)
721 RtlCopyMemory(SystemVolumeName
->Buffer
, ValueData
, ValueString
.Length
);
722 SystemVolumeName
->Buffer
[ValueString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
725 return STATUS_SUCCESS
;
733 MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName
)
735 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
737 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
738 QueryTable
[0].QueryRoutine
= MountMgrQuerySystemVolumeNameQueryRoutine
;
739 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
740 QueryTable
[0].Name
= L
"SystemPartition";
742 SystemVolumeName
->Buffer
= NULL
;
744 RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
745 L
"\\Registry\\Machine\\System\\Setup",
750 if (SystemVolumeName
->Buffer
)
752 return STATUS_SUCCESS
;
755 return STATUS_UNSUCCESSFUL
;
762 MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension
)
765 PLIST_ENTRY NextEntry
;
766 UNICODE_STRING SystemVolumeName
;
767 PDEVICE_INFORMATION DeviceInformation
;
768 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation
;
770 /* First, get system volume name */
771 Status
= MountMgrQuerySystemVolumeName(&SystemVolumeName
);
773 /* If there are no device, it's all done */
774 if (IsListEmpty(&(DeviceExtension
->DeviceListHead
)))
776 if (NT_SUCCESS(Status
))
778 FreePool(SystemVolumeName
.Buffer
);
784 /* Now, for all the devices... */
785 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
786 NextEntry
!= &(DeviceExtension
->DeviceListHead
);
787 NextEntry
= NextEntry
->Flink
)
789 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
791 /* If the device doesn't have a letter assigned, do it! */
792 if (!DeviceInformation
->LetterAssigned
)
794 MountMgrNextDriveLetterWorker(DeviceExtension
,
795 &(DeviceInformation
->DeviceName
),
796 &DriveLetterInformation
);
799 /* If it was the system volume */
800 if (NT_SUCCESS(Status
) && RtlEqualUnicodeString(&SystemVolumeName
, &(DeviceInformation
->DeviceName
), TRUE
))
802 /* Keep track of it */
803 DeviceExtension
->DriveLetterData
= AllocatePool(DeviceInformation
->UniqueId
->UniqueIdLength
+
804 sizeof(MOUNTDEV_UNIQUE_ID
));
805 if (DeviceExtension
->DriveLetterData
)
807 RtlCopyMemory(DeviceExtension
->DriveLetterData
,
808 DeviceInformation
->UniqueId
,
809 DeviceInformation
->UniqueId
->UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
812 /* If it was not automount, ensure it gets mounted */
813 if (!DeviceExtension
->NoAutoMount
)
815 DeviceExtension
->NoAutoMount
= TRUE
;
817 MountMgrNextDriveLetterWorker(DeviceExtension
,
818 &(DeviceInformation
->DeviceName
),
819 &DriveLetterInformation
);
821 DeviceExtension
->NoAutoMount
= FALSE
;
826 if (NT_SUCCESS(Status
))
828 FreePool(SystemVolumeName
.Buffer
);
833 MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension
,
838 PIO_STACK_LOCATION Stack
;
839 PLIST_ENTRY SymlinksEntry
;
840 UNICODE_STRING SymbolicName
;
841 PMOUNTMGR_TARGET_NAME Target
;
842 PWSTR DeviceString
, OldBuffer
;
843 USHORT DeviceLength
, OldLength
;
844 PDEVICE_INFORMATION DeviceInformation
;
845 PSYMLINK_INFORMATION SymlinkInformation
;
846 PASSOCIATED_DEVICE_ENTRY AssociatedDevice
;
848 Stack
= IoGetCurrentIrpStackLocation(Irp
);
850 /* Validate input size */
851 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_TARGET_NAME
))
853 return STATUS_INVALID_PARAMETER
;
856 /* Ensure we have received UNICODE_STRING */
857 Target
= (PMOUNTMGR_TARGET_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
858 if (Target
->DeviceNameLength
& 1)
860 return STATUS_INVALID_PARAMETER
;
863 /* Validate the entry structure size */
864 if (Target
->DeviceNameLength
+ sizeof(UNICODE_NULL
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
866 return STATUS_INVALID_PARAMETER
;
869 /* Ensure we can at least return needed size */
870 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
872 return STATUS_INVALID_PARAMETER
;
875 /* Construct string for query */
876 SymbolicName
.Length
= Target
->DeviceNameLength
;
877 SymbolicName
.MaximumLength
= Target
->DeviceNameLength
+ sizeof(UNICODE_NULL
);
878 SymbolicName
.Buffer
= Target
->DeviceName
;
880 /* Find device with our info */
881 Status
= FindDeviceInfo(DeviceExtension
, &SymbolicName
, FALSE
, &DeviceInformation
);
882 if (!NT_SUCCESS(Status
))
891 /* Try to find associated device info */
894 for (SymlinksEntry
= DeviceInformation
->SymbolicLinksListHead
.Flink
;
895 SymlinksEntry
!= &(DeviceInformation
->SymbolicLinksListHead
);
896 SymlinksEntry
= SymlinksEntry
->Flink
)
898 SymlinkInformation
= CONTAINING_RECORD(SymlinksEntry
, SYMLINK_INFORMATION
, SymbolicLinksListEntry
);
900 /* Try to find with drive letter */
901 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation
->Name
) && SymlinkInformation
->Online
)
907 /* We didn't find, break */
908 if (SymlinksEntry
== &(DeviceInformation
->SymbolicLinksListHead
))
913 /* It doesn't have associated device, go to fallback method */
914 if (IsListEmpty(&DeviceInformation
->AssociatedDevicesHead
))
916 goto TryWithVolumeName
;
919 /* Create a string with the information about the device */
920 AssociatedDevice
= CONTAINING_RECORD(&(DeviceInformation
->SymbolicLinksListHead
), ASSOCIATED_DEVICE_ENTRY
, AssociatedDevicesEntry
);
921 OldLength
= DeviceLength
;
922 OldBuffer
= DeviceString
;
923 DeviceLength
+= AssociatedDevice
->String
.Length
;
924 DeviceString
= AllocatePool(DeviceLength
);
932 return STATUS_INSUFFICIENT_RESOURCES
;
935 /* Store our info and previous if any */
936 RtlCopyMemory(DeviceString
, AssociatedDevice
->String
.Buffer
, AssociatedDevice
->String
.Length
);
939 RtlCopyMemory(&DeviceString
[AssociatedDevice
->String
.Length
/ sizeof(WCHAR
)], OldBuffer
, OldLength
);
943 /* Count and continue looking */
945 DeviceInformation
= AssociatedDevice
->DeviceInformation
;
947 /* If too many devices, try another way */
948 if (DevicesFound
> MAX_DEVICES
) /* 1000 */
950 goto TryWithVolumeName
;
954 /* Reallocate our string, so that we can prepend disk letter */
955 OldBuffer
= DeviceString
;
956 OldLength
= DeviceLength
;
957 DeviceLength
+= 2 * sizeof(WCHAR
);
958 DeviceString
= AllocatePool(DeviceLength
);
966 return STATUS_INSUFFICIENT_RESOURCES
;
970 DeviceString
[0] = SymlinkInformation
->Name
.Buffer
[12];
971 DeviceString
[1] = L
':';
973 /* And copy the rest */
976 RtlCopyMemory(&DeviceString
[2], OldBuffer
, OldLength
);
981 /* If we didn't find anything, try differently */
982 if (DeviceLength
< 2 * sizeof(WCHAR
) || DeviceString
[1] != L
':')
986 FreePool(DeviceString
);
990 /* Try to find a volume name matching */
991 for (SymlinksEntry
= DeviceInformation
->SymbolicLinksListHead
.Flink
;
992 SymlinksEntry
!= &(DeviceInformation
->SymbolicLinksListHead
);
993 SymlinksEntry
= SymlinksEntry
->Flink
)
995 SymlinkInformation
= CONTAINING_RECORD(SymlinksEntry
, SYMLINK_INFORMATION
, SymbolicLinksListEntry
);
997 if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation
->Name
))
1004 if (SymlinksEntry
!= &(DeviceInformation
->SymbolicLinksListHead
))
1006 DeviceLength
= SymlinkInformation
->Name
.Length
;
1007 DeviceString
= AllocatePool(DeviceLength
);
1010 return STATUS_INSUFFICIENT_RESOURCES
;
1013 RtlCopyMemory(DeviceString
, SymlinkInformation
->Name
.Buffer
, DeviceLength
);
1014 /* Ensure we are in the right namespace; [1] can be ? */
1015 DeviceString
[1] = L
'\\';
1019 /* If we found something */
1022 /* At least, we will return our length */
1023 ((PMOUNTMGR_VOLUME_PATHS
)Irp
->AssociatedIrp
.SystemBuffer
)->MultiSzLength
= DeviceLength
;
1024 /* MOUNTMGR_VOLUME_PATHS is a string + a ULONG */
1025 Irp
->IoStatus
.Information
= DeviceLength
+ sizeof(ULONG
);
1027 /* If we have enough room for copying the string */
1028 if (sizeof(ULONG
) + DeviceLength
<= Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
1033 RtlCopyMemory(((PMOUNTMGR_VOLUME_PATHS
)Irp
->AssociatedIrp
.SystemBuffer
)->MultiSz
, DeviceString
, DeviceLength
);
1036 /* And double zero at its end - this is needed in case of multiple paths which are separated by a single 0 */
1037 FreePool(DeviceString
);
1038 ((PMOUNTMGR_VOLUME_PATHS
)Irp
->AssociatedIrp
.SystemBuffer
)->MultiSz
[DeviceLength
/ sizeof(WCHAR
)] = 0;
1039 ((PMOUNTMGR_VOLUME_PATHS
)Irp
->AssociatedIrp
.SystemBuffer
)->MultiSz
[DeviceLength
/ sizeof(WCHAR
) + 1] = 0;
1041 return STATUS_SUCCESS
;
1045 /* Just return appropriate size and leave */
1046 FreePool(DeviceString
);
1047 Irp
->IoStatus
.Information
= sizeof(ULONG
);
1048 return STATUS_BUFFER_OVERFLOW
;
1053 return STATUS_NOT_FOUND
;
1057 MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension
,
1060 UNREFERENCED_PARAMETER(DeviceExtension
);
1061 UNREFERENCED_PARAMETER(Irp
);
1062 return STATUS_NOT_IMPLEMENTED
;
1069 MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension
,
1073 PIO_STACK_LOCATION Stack
;
1074 UNICODE_STRING SymbolicName
;
1075 PMOUNTMGR_TARGET_NAME Target
;
1076 PDEVICE_INFORMATION DeviceInformation
;
1078 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1080 /* Validate input */
1081 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_TARGET_NAME
))
1083 return STATUS_INVALID_PARAMETER
;
1086 Target
= (PMOUNTMGR_TARGET_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
1087 if (Target
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1089 return STATUS_INVALID_PARAMETER
;
1092 SymbolicName
.Length
=
1093 SymbolicName
.MaximumLength
= Target
->DeviceNameLength
;
1094 SymbolicName
.Buffer
= Target
->DeviceName
;
1096 /* Find the associated device */
1097 Status
= FindDeviceInfo(DeviceExtension
, &SymbolicName
, FALSE
, &DeviceInformation
);
1098 if (!NT_SUCCESS(Status
))
1103 /* Mark we want to keep links */
1104 DeviceInformation
->KeepLinks
= TRUE
;
1106 return STATUS_SUCCESS
;
1113 MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension
,
1118 PIO_STACK_LOCATION Stack
;
1119 UNICODE_STRING SymbolicName
;
1120 PMOUNTMGR_TARGET_NAME Target
;
1122 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1124 /* Validate input */
1125 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_TARGET_NAME
))
1127 return STATUS_INVALID_PARAMETER
;
1130 Target
= (PMOUNTMGR_TARGET_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
1131 if (Target
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1133 return STATUS_INVALID_PARAMETER
;
1136 SymbolicName
.Length
=
1137 SymbolicName
.MaximumLength
= Target
->DeviceNameLength
;
1138 SymbolicName
.Buffer
= Target
->DeviceName
;
1140 /* Disable hard errors */
1141 OldState
= PsGetThreadHardErrorsAreDisabled(PsGetCurrentThread());
1142 PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), TRUE
);
1144 /* Call real worker */
1145 Status
= MountMgrMountedDeviceArrival(DeviceExtension
, &SymbolicName
, TRUE
);
1147 PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), OldState
);
1156 MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension
,
1160 PIO_STACK_LOCATION Stack
;
1161 PMOUNTDEV_UNIQUE_ID UniqueId
;
1162 PMOUNTMGR_MOUNT_POINT MountPoint
;
1163 UNICODE_STRING SymbolicName
, DeviceName
;
1165 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1167 /* Validate input... */
1168 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINT
))
1170 return STATUS_INVALID_PARAMETER
;
1173 MountPoint
= (PMOUNTMGR_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
1174 if (!MountPoint
->SymbolicLinkNameLength
)
1176 MountPoint
->SymbolicLinkNameOffset
= 0;
1179 if (!MountPoint
->UniqueIdLength
)
1181 MountPoint
->UniqueIdOffset
= 0;
1184 if (!MountPoint
->DeviceNameLength
)
1186 MountPoint
->DeviceNameOffset
= 0;
1189 /* Addresses can't be odd */
1190 if ((MountPoint
->SymbolicLinkNameOffset
& 1) ||
1191 (MountPoint
->SymbolicLinkNameLength
& 1))
1193 return STATUS_INVALID_PARAMETER
;
1196 if ((MountPoint
->UniqueIdOffset
& 1) ||
1197 (MountPoint
->UniqueIdLength
& 1))
1199 return STATUS_INVALID_PARAMETER
;
1202 if ((MountPoint
->DeviceNameOffset
& 1) ||
1203 (MountPoint
->DeviceNameLength
& 1))
1205 return STATUS_INVALID_PARAMETER
;
1208 /* We can't go beyond */
1209 if (((ULONG
)MountPoint
->SymbolicLinkNameLength
+ MountPoint
->UniqueIdLength
+
1210 MountPoint
->DeviceNameLength
) < Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1212 return STATUS_INVALID_PARAMETER
;
1215 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINTS
))
1217 return STATUS_INVALID_PARAMETER
;
1220 /* If caller provided a Symlink, use it */
1221 if (MountPoint
->SymbolicLinkNameLength
!= 0)
1223 if (MountPoint
->SymbolicLinkNameLength
> MAXSHORT
)
1225 return STATUS_INVALID_PARAMETER
;
1228 SymbolicName
.Length
= MountPoint
->SymbolicLinkNameLength
;
1229 SymbolicName
.MaximumLength
= MountPoint
->SymbolicLinkNameLength
+ sizeof(WCHAR
);
1230 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
1231 if (!SymbolicName
.Buffer
)
1233 return STATUS_INSUFFICIENT_RESOURCES
;
1236 RtlCopyMemory(SymbolicName
.Buffer
,
1237 (PWSTR
)((ULONG_PTR
)MountPoint
+ MountPoint
->SymbolicLinkNameOffset
),
1238 SymbolicName
.Length
);
1239 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1241 /* Query links using it */
1242 Status
= QueryPointsFromSymbolicLinkName(DeviceExtension
, &SymbolicName
, Irp
);
1243 FreePool(SymbolicName
.Buffer
);
1245 /* If user provided an unique ID */
1246 else if (MountPoint
->UniqueIdLength
!= 0)
1248 UniqueId
= AllocatePool(MountPoint
->UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1251 return STATUS_INSUFFICIENT_RESOURCES
;
1254 UniqueId
->UniqueIdLength
= MountPoint
->UniqueIdLength
;
1255 RtlCopyMemory(UniqueId
->UniqueId
,
1256 (PVOID
)((ULONG_PTR
)MountPoint
+ MountPoint
->UniqueIdOffset
),
1257 MountPoint
->UniqueIdLength
);
1259 /* Query links using it */
1260 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, UniqueId
, NULL
);
1263 /* If caller provided a device name */
1264 else if (MountPoint
->DeviceNameLength
!= 0)
1266 if (MountPoint
->DeviceNameLength
> MAXSHORT
)
1268 return STATUS_INVALID_PARAMETER
;
1271 DeviceName
.Length
= MountPoint
->DeviceNameLength
;
1272 DeviceName
.MaximumLength
= MountPoint
->DeviceNameLength
+ sizeof(WCHAR
);
1273 DeviceName
.Buffer
= AllocatePool(DeviceName
.MaximumLength
);
1274 if (!DeviceName
.Buffer
)
1276 return STATUS_INSUFFICIENT_RESOURCES
;
1279 RtlCopyMemory(DeviceName
.Buffer
,
1280 (PWSTR
)((ULONG_PTR
)MountPoint
+ MountPoint
->DeviceNameOffset
),
1282 DeviceName
.Buffer
[DeviceName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1284 /* Query links using it */
1285 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, NULL
, &DeviceName
);
1286 FreePool(DeviceName
.Buffer
);
1290 /* Otherwise, query all links */
1291 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, NULL
, NULL
);
1301 MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension
,
1306 BOOLEAN CreateNoDrive
;
1307 PIO_STACK_LOCATION Stack
;
1308 PMOUNTDEV_UNIQUE_ID UniqueId
;
1309 PMOUNTMGR_MOUNT_POINT MountPoint
;
1310 PMOUNTMGR_MOUNT_POINTS MountPoints
;
1311 UNICODE_STRING SymbolicName
, DeviceName
;
1313 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1315 /* Validate input */
1316 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINT
))
1318 return STATUS_INVALID_PARAMETER
;
1322 MountPoint
= (PMOUNTMGR_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
1323 CreateNoDrive
= (MountPoint
->SymbolicLinkNameOffset
&& MountPoint
->SymbolicLinkNameLength
);
1325 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1326 if (!NT_SUCCESS(Status
))
1331 /* For all the points matching the request */
1332 MountPoints
= (PMOUNTMGR_MOUNT_POINTS
)Irp
->AssociatedIrp
.SystemBuffer
;
1333 for (Link
= 0; Link
< MountPoints
->NumberOfMountPoints
; Link
++)
1335 SymbolicName
.Length
= MountPoints
->MountPoints
[Link
].SymbolicLinkNameLength
;
1336 SymbolicName
.MaximumLength
= SymbolicName
.Length
+ sizeof(WCHAR
);
1337 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
1338 if (!SymbolicName
.Buffer
)
1340 return STATUS_INSUFFICIENT_RESOURCES
;
1343 RtlCopyMemory(SymbolicName
.Buffer
,
1344 (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].SymbolicLinkNameOffset
),
1345 SymbolicName
.Length
);
1346 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1348 /* Create a no drive entry for the drive letters */
1349 if (CreateNoDrive
&& IsDriveLetter(&SymbolicName
))
1351 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1354 UniqueId
->UniqueIdLength
= MountPoints
->MountPoints
[Link
].UniqueIdLength
;
1355 RtlCopyMemory(UniqueId
->UniqueId
,
1356 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1357 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1359 CreateNoDriveLetterEntry(UniqueId
);
1364 /* If there are no link any more, and no need to create a no drive entry */
1365 if (Link
== 0 && !CreateNoDrive
)
1367 /* Then, delete everything */
1368 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1371 RtlCopyMemory(UniqueId
,
1372 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1373 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1375 DeleteNoDriveLetterEntry(UniqueId
);
1380 /* Delete all the information about the mount point */
1381 GlobalDeleteSymbolicLink(&SymbolicName
);
1382 DeleteSymbolicLinkNameFromMemory(DeviceExtension
, &SymbolicName
, FALSE
);
1383 RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE
, DatabasePath
, SymbolicName
.Buffer
);
1384 FreePool(SymbolicName
.Buffer
);
1386 /* Notify the change */
1387 DeviceName
.Length
= DeviceName
.MaximumLength
=
1388 MountPoints
->MountPoints
[Link
].DeviceNameLength
;
1389 DeviceName
.Buffer
= (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].DeviceNameOffset
);
1390 MountMgrNotifyNameChange(DeviceExtension
, &DeviceName
, TRUE
);
1393 MountMgrNotify(DeviceExtension
);
1402 MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension
,
1407 UNICODE_STRING SymbolicName
;
1408 PMOUNTDEV_UNIQUE_ID UniqueId
;
1409 PMOUNTMGR_MOUNT_POINTS MountPoints
;
1412 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1413 if (!NT_SUCCESS(Status
))
1418 MountPoints
= (PMOUNTMGR_MOUNT_POINTS
)Irp
->AssociatedIrp
.SystemBuffer
;
1419 if (MountPoints
->NumberOfMountPoints
== 0)
1424 /* For all the mount points */
1425 for (Link
= 0; Link
< MountPoints
->NumberOfMountPoints
; Link
++)
1427 SymbolicName
.Length
= MountPoints
->MountPoints
[Link
].SymbolicLinkNameLength
;
1428 SymbolicName
.MaximumLength
= SymbolicName
.Length
+ sizeof(WCHAR
);
1429 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
1430 if (!SymbolicName
.Buffer
)
1432 return STATUS_INSUFFICIENT_RESOURCES
;
1435 RtlCopyMemory(SymbolicName
.Buffer
,
1436 (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].SymbolicLinkNameOffset
),
1437 SymbolicName
.Length
);
1438 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1440 /* If the only mount point is a drive letter, then create a no letter drive entry */
1441 if (MountPoints
->NumberOfMountPoints
== 1 && IsDriveLetter(&SymbolicName
))
1443 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1446 UniqueId
->UniqueIdLength
= MountPoints
->MountPoints
[Link
].UniqueIdLength
;
1447 RtlCopyMemory(UniqueId
->UniqueId
,
1448 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1449 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1451 CreateNoDriveLetterEntry(UniqueId
);
1456 /* Simply delete mount point from DB */
1457 DeleteSymbolicLinkNameFromMemory(DeviceExtension
, &SymbolicName
, TRUE
);
1458 RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE
, DatabasePath
, SymbolicName
.Buffer
);
1459 FreePool(SymbolicName
.Buffer
);
1469 MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension
,
1471 IN NTSTATUS LockStatus
,
1472 OUT PUNICODE_STRING SourceDeviceName
,
1473 OUT PUNICODE_STRING SourceSymbolicName
,
1474 OUT PUNICODE_STRING TargetVolumeName
)
1478 PFILE_OBJECT FileObject
;
1479 PIO_STACK_LOCATION Stack
;
1480 ULONG Length
, SavedLength
;
1481 BOOLEAN FOReferenced
= FALSE
;
1482 IO_STATUS_BLOCK IoStatusBlock
;
1483 OBJECT_ATTRIBUTES ObjectAttributes
;
1484 PDEVICE_INFORMATION DeviceInformation
;
1485 OBJECT_NAME_INFORMATION ObjectNameInfo
;
1486 FILE_FS_DEVICE_INFORMATION FsDeviceInfo
;
1487 PFILE_NAME_INFORMATION FileNameInfo
= NULL
;
1488 PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint
;
1489 POBJECT_NAME_INFORMATION ObjectNameInfoPtr
= NULL
;
1490 UNICODE_STRING SourceVolumeName
, TargetDeviceName
;
1492 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1494 /* Validate input */
1495 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_VOLUME_MOUNT_POINT
))
1497 return STATUS_INVALID_PARAMETER
;
1500 VolumeMountPoint
= (PMOUNTMGR_VOLUME_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
1502 if (((ULONG
)VolumeMountPoint
->SourceVolumeNameLength
+ VolumeMountPoint
->TargetVolumeNameLength
) <
1503 Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1505 return STATUS_INVALID_PARAMETER
;
1508 /* Get source volume name */
1509 SourceVolumeName
.Length
=
1510 SourceVolumeName
.MaximumLength
= VolumeMountPoint
->SourceVolumeNameLength
;
1511 SourceVolumeName
.Buffer
= (PWSTR
)((ULONG_PTR
)VolumeMountPoint
+ VolumeMountPoint
->SourceVolumeNameOffset
);
1513 InitializeObjectAttributes(&ObjectAttributes
,
1515 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
1520 Status
= ZwOpenFile(&Handle
,
1521 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
1524 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1525 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_REPARSE_POINT
);
1526 if (!NT_SUCCESS(Status
))
1531 TargetDeviceName
.Buffer
= NULL
;
1533 /* Query its attributes */
1534 Status
= ZwQueryVolumeInformationFile(Handle
,
1537 sizeof(FsDeviceInfo
),
1538 FileFsDeviceInformation
);
1539 if (!NT_SUCCESS(Status
))
1544 if (FsDeviceInfo
.DeviceType
!= FILE_DEVICE_DISK
&& FsDeviceInfo
.DeviceType
!= FILE_DEVICE_VIRTUAL_DISK
)
1549 if (FsDeviceInfo
.Characteristics
!= (FILE_REMOTE_DEVICE
| FILE_REMOVABLE_MEDIA
))
1555 Status
= ObReferenceObjectByHandle(Handle
, 0, *IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
1556 if (!NT_SUCCESS(Status
))
1560 FOReferenced
= TRUE
;
1563 FileNameInfo
= AllocatePool(sizeof(FILE_NAME_INFORMATION
));
1566 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1570 Status
= ZwQueryInformationFile(Handle
, &IoStatusBlock
, FileNameInfo
,
1571 sizeof(FILE_NAME_INFORMATION
),
1572 FileNameInformation
);
1573 if (Status
== STATUS_BUFFER_OVERFLOW
)
1575 /* Now we have real length, use it */
1576 Length
= FileNameInfo
->FileNameLength
;
1577 FreePool(FileNameInfo
);
1579 FileNameInfo
= AllocatePool(sizeof(FILE_NAME_INFORMATION
) + Length
);
1582 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1586 /* Really query file name */
1587 Status
= ZwQueryInformationFile(Handle
, &IoStatusBlock
, FileNameInfo
,
1588 sizeof(FILE_NAME_INFORMATION
) + Length
,
1589 FileNameInformation
);
1592 if (!NT_SUCCESS(Status
))
1597 /* Get symbolic name */
1598 ObjectNameInfoPtr
= &ObjectNameInfo
;
1599 SavedLength
= sizeof(OBJECT_NAME_INFORMATION
);
1600 Status
= ObQueryNameString(FileObject
->DeviceObject
, ObjectNameInfoPtr
, sizeof(OBJECT_NAME_INFORMATION
), &Length
);
1601 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
1603 /* Once again, with proper size, it works better */
1604 ObjectNameInfoPtr
= AllocatePool(Length
);
1605 if (!ObjectNameInfoPtr
)
1607 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1611 SavedLength
= Length
;
1612 Status
= ObQueryNameString(FileObject
->DeviceObject
, ObjectNameInfoPtr
, SavedLength
, &Length
);
1615 if (!NT_SUCCESS(Status
))
1620 /* Now, query the device name */
1621 Status
= QueryDeviceInformation(&ObjectNameInfoPtr
->Name
, SourceDeviceName
,
1622 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1623 if (!NT_SUCCESS(Status
))
1628 /* For target volume name, use input */
1629 TargetVolumeName
->Length
=
1630 TargetVolumeName
->MaximumLength
= VolumeMountPoint
->TargetVolumeNameLength
;
1631 TargetVolumeName
->Buffer
= (PWSTR
)((ULONG_PTR
)VolumeMountPoint
+ VolumeMountPoint
->TargetVolumeNameOffset
);
1633 /* Query its device name */
1634 Status
= QueryDeviceInformation(TargetVolumeName
, &TargetDeviceName
,
1635 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1636 if (!NT_SUCCESS(Status
))
1641 /* Return symbolic name */
1642 SourceSymbolicName
->Length
=
1643 SourceSymbolicName
->MaximumLength
= (USHORT
)FileNameInfo
->FileNameLength
;
1644 SourceSymbolicName
->Buffer
= (PWSTR
)FileNameInfo
;
1645 /* memmove allows memory overlap */
1646 RtlMoveMemory(SourceSymbolicName
->Buffer
, FileNameInfo
->FileName
, SourceSymbolicName
->Length
);
1647 FileNameInfo
= NULL
;
1649 /* Notify the change */
1650 MountMgrNotify(DeviceExtension
);
1651 MountMgrNotifyNameChange(DeviceExtension
, &TargetDeviceName
, TRUE
);
1653 /* If we are locked, sync databases if possible */
1654 if (NT_SUCCESS(LockStatus
))
1656 Status
= FindDeviceInfo(DeviceExtension
, SourceDeviceName
, FALSE
, &DeviceInformation
);
1657 if (NT_SUCCESS(Status
))
1659 ReconcileThisDatabaseWithMaster(DeviceExtension
, DeviceInformation
);
1663 Status
= STATUS_PENDING
;
1668 if (TargetDeviceName
.Buffer
)
1670 FreePool(TargetDeviceName
.Buffer
);
1673 if (ObjectNameInfoPtr
&& ObjectNameInfoPtr
!= &ObjectNameInfo
)
1675 FreePool(ObjectNameInfoPtr
);
1680 FreePool(FileNameInfo
);
1685 ObDereferenceObject(FileObject
);
1692 MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension
,
1694 IN NTSTATUS LockStatus
)
1696 UNREFERENCED_PARAMETER(DeviceExtension
);
1697 UNREFERENCED_PARAMETER(Irp
);
1698 UNREFERENCED_PARAMETER(LockStatus
);
1699 return STATUS_NOT_IMPLEMENTED
;
1703 MountMgrVolumeMountPointDeleted(IN PDEVICE_EXTENSION DeviceExtension
,
1705 IN NTSTATUS LockStatus
)
1707 UNREFERENCED_PARAMETER(DeviceExtension
);
1708 UNREFERENCED_PARAMETER(Irp
);
1709 UNREFERENCED_PARAMETER(LockStatus
);
1710 return STATUS_NOT_IMPLEMENTED
;
1718 MountMgrDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1721 PIO_STACK_LOCATION Stack
;
1722 NTSTATUS Status
, LockStatus
;
1723 PDEVICE_EXTENSION DeviceExtension
;
1725 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1726 DeviceExtension
= DeviceObject
->DeviceExtension
;
1728 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1730 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
1732 case IOCTL_MOUNTMGR_CREATE_POINT
:
1733 Status
= MountMgrCreatePoint(DeviceExtension
, Irp
);
1736 case IOCTL_MOUNTMGR_DELETE_POINTS
:
1737 Status
= MountMgrDeletePoints(DeviceExtension
, Irp
);
1740 case IOCTL_MOUNTMGR_QUERY_POINTS
:
1741 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1744 case IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY
:
1745 Status
= MountMgrDeletePointsDbOnly(DeviceExtension
, Irp
);
1748 case IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
:
1749 Status
= MountMgrNextDriveLetter(DeviceExtension
, Irp
);
1752 case IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
:
1753 DeviceExtension
->AutomaticDriveLetter
= TRUE
;
1754 Status
= STATUS_SUCCESS
;
1756 MountMgrAssignDriveLetters(DeviceExtension
);
1757 ReconcileAllDatabasesWithMaster(DeviceExtension
);
1758 WaitForOnlinesToComplete(DeviceExtension
);
1761 case IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED
:
1762 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1764 LockStatus
= WaitForRemoteDatabaseSemaphore(DeviceExtension
);
1765 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1766 Status
= MountMgrVolumeMountPointCreated(DeviceExtension
, Irp
, LockStatus
);
1767 if (NT_SUCCESS(LockStatus
))
1769 ReleaseRemoteDatabaseSemaphore(DeviceExtension
);
1774 case IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED
:
1775 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1777 LockStatus
= WaitForRemoteDatabaseSemaphore(DeviceExtension
);
1778 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1779 Status
= MountMgrVolumeMountPointDeleted(DeviceExtension
, Irp
, LockStatus
);
1780 if (NT_SUCCESS(LockStatus
))
1782 ReleaseRemoteDatabaseSemaphore(DeviceExtension
);
1787 case IOCTL_MOUNTMGR_CHANGE_NOTIFY
:
1788 Status
= MountMgrChangeNotify(DeviceExtension
, Irp
);
1791 case IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE
:
1792 Status
= MountMgrKeepLinksWhenOffline(DeviceExtension
, Irp
);
1795 case IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES
:
1796 Status
= MountMgrCheckUnprocessedVolumes(DeviceExtension
, Irp
);
1799 case IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
:
1800 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1801 Status
= MountMgrVolumeArrivalNotification(DeviceExtension
, Irp
);
1804 case IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
:
1805 Status
= MountMgrQueryDosVolumePath(DeviceExtension
, Irp
);
1808 case IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
:
1809 Status
= MountMgrQueryDosVolumePaths(DeviceExtension
, Irp
);
1812 case IOCTL_MOUNTMGR_SCRUB_REGISTRY
:
1813 Status
= MountMgrScrubRegistry(DeviceExtension
);
1816 case IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT
:
1817 Status
= MountMgrQueryAutoMount(DeviceExtension
, Irp
);
1820 case IOCTL_MOUNTMGR_SET_AUTO_MOUNT
:
1821 Status
= MountMgrSetAutoMount(DeviceExtension
, Irp
);
1825 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1828 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1830 if (Status
!= STATUS_PENDING
)
1838 Irp
->IoStatus
.Status
= Status
;
1839 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);