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 *****************************************************************/
30 #define MAX_DEVICES 0x3E8 /* Matches 1000 devices */
39 MountMgrChangeNotify(IN PDEVICE_EXTENSION DeviceExtension
,
44 PIO_STACK_LOCATION Stack
;
45 PMOUNTMGR_CHANGE_NOTIFY_INFO ChangeNotify
;
47 /* Get the I/O buffer */
48 Stack
= IoGetCurrentIrpStackLocation(Irp
);
49 ChangeNotify
= (PMOUNTMGR_CHANGE_NOTIFY_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
52 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO
) ||
53 Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO
))
55 return STATUS_INVALID_PARAMETER
;
58 /* If epic number doesn't match, just return now one */
59 if (DeviceExtension
->EpicNumber
!= ChangeNotify
->EpicNumber
)
61 ChangeNotify
->EpicNumber
= DeviceExtension
->EpicNumber
;
62 Irp
->IoStatus
.Information
= 0;
63 return STATUS_SUCCESS
;
66 /* If IRP is to be canceled, forget about that */
67 IoAcquireCancelSpinLock(&OldIrql
);
70 Status
= STATUS_CANCELLED
;
72 /* Otherwise queue the IRP to be notified with the next epic number change */
75 InsertTailList(&(DeviceExtension
->IrpListHead
), &(Irp
->Tail
.Overlay
.ListEntry
));
76 IoMarkIrpPending(Irp
);
77 IoSetCancelRoutine(Irp
, MountMgrCancel
);
78 Status
= STATUS_PENDING
;
80 IoReleaseCancelSpinLock(OldIrql
);
89 MountmgrWriteNoAutoMount(IN PDEVICE_EXTENSION DeviceExtension
)
91 ULONG Value
= DeviceExtension
->NoAutoMount
;
93 return RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
94 DeviceExtension
->RegistryPath
.Buffer
,
106 MountMgrSetAutoMount(IN PDEVICE_EXTENSION DeviceExtension
,
109 PIO_STACK_LOCATION Stack
;
110 PMOUNTMGR_SET_AUTO_MOUNT SetState
;
112 Stack
= IoGetCurrentIrpStackLocation(Irp
);
114 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_SET_AUTO_MOUNT
))
116 Irp
->IoStatus
.Information
= 0;
117 return STATUS_INVALID_PARAMETER
;
120 /* Only change if there's a real difference */
121 SetState
= (PMOUNTMGR_SET_AUTO_MOUNT
)Irp
->AssociatedIrp
.SystemBuffer
;
122 if (SetState
->NewState
== !DeviceExtension
->NoAutoMount
)
124 Irp
->IoStatus
.Information
= 0;
125 return STATUS_SUCCESS
;
128 /* Set new state; ! on purpose */
129 DeviceExtension
->NoAutoMount
= !SetState
->NewState
;
130 Irp
->IoStatus
.Information
= 0;
131 return MountmgrWriteNoAutoMount(DeviceExtension
);
138 MountMgrQueryAutoMount(IN PDEVICE_EXTENSION DeviceExtension
,
141 PIO_STACK_LOCATION Stack
;
142 PMOUNTMGR_QUERY_AUTO_MOUNT QueryState
;
144 Stack
= IoGetCurrentIrpStackLocation(Irp
);
146 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_QUERY_AUTO_MOUNT
))
148 Irp
->IoStatus
.Information
= 0;
149 return STATUS_INVALID_PARAMETER
;
152 QueryState
= (PMOUNTMGR_QUERY_AUTO_MOUNT
)Irp
->AssociatedIrp
.SystemBuffer
;
153 QueryState
->CurrentState
= !DeviceExtension
->NoAutoMount
;
154 Irp
->IoStatus
.Information
= sizeof(MOUNTMGR_QUERY_AUTO_MOUNT
);
156 return STATUS_SUCCESS
;
164 ScrubRegistryRoutine(IN PWSTR ValueName
,
167 IN ULONG ValueLength
,
169 IN PVOID EntryContext
)
172 PLIST_ENTRY NextEntry
;
173 PDEVICE_INFORMATION DeviceInfo
;
174 PBOOLEAN Continue
= EntryContext
;
175 PDEVICE_EXTENSION DeviceExtension
= Context
;
177 if (ValueType
!= REG_BINARY
)
179 return STATUS_SUCCESS
;
182 /* Delete values for devices that don't have the matching unique ID */
183 if (!IsListEmpty(&(DeviceExtension
->DeviceListHead
)))
185 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
186 NextEntry
!= &(DeviceExtension
->DeviceListHead
);
187 NextEntry
= NextEntry
->Flink
)
189 DeviceInfo
= CONTAINING_RECORD(NextEntry
,
193 if (!DeviceInfo
->UniqueId
|| DeviceInfo
->UniqueId
->UniqueIdLength
!= ValueLength
)
198 if (RtlCompareMemory(DeviceInfo
->UniqueId
->UniqueId
, ValueData
, ValueLength
) == ValueLength
)
200 return STATUS_SUCCESS
;
205 /* Wrong unique ID, scrub it */
206 Status
= RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
209 if (!NT_SUCCESS(Status
))
212 return STATUS_UNSUCCESSFUL
;
223 MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension
)
227 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
231 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
232 QueryTable
[0].QueryRoutine
= ScrubRegistryRoutine
;
233 QueryTable
[0].EntryContext
= &Continue
;
236 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
251 MountMgrCreatePoint(IN PDEVICE_EXTENSION DeviceExtension
,
255 PIO_STACK_LOCATION Stack
;
256 PMOUNTMGR_CREATE_POINT_INPUT Point
;
257 UNICODE_STRING DeviceName
, SymbolicName
;
259 Stack
= IoGetCurrentIrpStackLocation(Irp
);
261 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_CREATE_POINT_INPUT
))
263 return STATUS_INVALID_PARAMETER
;
266 Point
= (PMOUNTMGR_CREATE_POINT_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
268 MaxLength
= MAX((Point
->DeviceNameOffset
+ Point
->DeviceNameLength
),
269 (Point
->SymbolicLinkNameLength
+ Point
->SymbolicLinkNameOffset
));
270 if (MaxLength
>= Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
272 return STATUS_INVALID_PARAMETER
;
275 /* Get all the strings and call the worker */
276 SymbolicName
.Length
= Point
->SymbolicLinkNameLength
;
277 SymbolicName
.MaximumLength
= Point
->SymbolicLinkNameLength
;
278 DeviceName
.Length
= Point
->DeviceNameLength
;
279 DeviceName
.MaximumLength
= Point
->DeviceNameLength
;
280 SymbolicName
.Buffer
= (PVOID
)((ULONG_PTR
)Point
+ Point
->SymbolicLinkNameOffset
);
281 DeviceName
.Buffer
= (PVOID
)((ULONG_PTR
)Point
+ Point
->DeviceNameOffset
);
283 return MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &DeviceName
);
290 MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension
,
293 PLIST_ENTRY NextEntry
;
294 PDEVICE_INFORMATION DeviceInformation
;
295 NTSTATUS ArrivalStatus
, Status
= STATUS_SUCCESS
;
297 UNREFERENCED_PARAMETER(Irp
);
299 /* No offline volumes, nothing more to do */
300 if (IsListEmpty(&(DeviceExtension
->OfflineDeviceListHead
)))
302 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
303 return STATUS_SUCCESS
;
306 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
308 /* Reactivate all the offline volumes */
309 while (!IsListEmpty(&(DeviceExtension
->OfflineDeviceListHead
)))
311 NextEntry
= RemoveHeadList(&(DeviceExtension
->OfflineDeviceListHead
));
312 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
314 ArrivalStatus
= MountMgrMountedDeviceArrival(DeviceExtension
,
315 &(DeviceInformation
->SymbolicName
),
316 DeviceInformation
->Volume
);
317 /* Then, remove them dead information */
318 MountMgrFreeDeadDeviceInfo(DeviceInformation
);
320 if (NT_SUCCESS(Status
))
322 Status
= ArrivalStatus
;
333 IsFtVolume(IN PUNICODE_STRING SymbolicName
)
338 PFILE_OBJECT FileObject
;
339 IO_STATUS_BLOCK IoStatusBlock
;
340 PARTITION_INFORMATION PartitionInfo
;
341 PDEVICE_OBJECT DeviceObject
, FileDeviceObject
;
343 /* Get device object */
344 Status
= IoGetDeviceObjectPointer(SymbolicName
,
345 FILE_READ_ATTRIBUTES
,
348 if (!NT_SUCCESS(Status
))
353 /* Get attached device */
354 FileDeviceObject
= FileObject
->DeviceObject
;
355 DeviceObject
= IoGetAttachedDeviceReference(FileDeviceObject
);
357 /* FT volume can't be removable */
358 if (FileDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
360 ObDereferenceObject(DeviceObject
);
361 ObDereferenceObject(FileObject
);
365 ObDereferenceObject(FileObject
);
367 /* Get partition information */
368 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
369 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
374 sizeof(PartitionInfo
),
380 ObDereferenceObject(DeviceObject
);
384 Status
= IoCallDriver(DeviceObject
, Irp
);
385 if (Status
== STATUS_PENDING
)
387 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
388 Status
= IoStatusBlock
.Status
;
391 ObDereferenceObject(DeviceObject
);
392 if (!NT_SUCCESS(Status
))
397 /* Check if this is a FT volume */
398 return IsRecognizedPartition(PartitionInfo
.PartitionType
);
405 ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension
)
407 WCHAR NameBuffer
[DRIVE_LETTER_LENGTH
/ sizeof(WCHAR
)];
408 PLIST_ENTRY NextEntry
;
409 UNICODE_STRING SymbolicName
;
410 PDEVICE_INFORMATION DeviceInformation
;
412 /* No devices? Nothing to do! */
413 if (IsListEmpty(&(DeviceExtension
->DeviceListHead
)))
418 /* For all the devices */
419 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
420 NextEntry
!= &(DeviceExtension
->DeviceListHead
);
421 NextEntry
= NextEntry
->Flink
)
423 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
425 /* If no drive letter */
426 if (DeviceInformation
->SuggestedDriveLetter
== (UCHAR
)-1)
428 /* Ensure it has no entry yet */
429 if (!HasDriveLetter(DeviceInformation
) &&
430 !HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
433 CreateNoDriveLetterEntry(DeviceInformation
->UniqueId
);
436 DeviceInformation
->SuggestedDriveLetter
= 0;
438 /* Suggested letter & no entry */
439 else if (DeviceInformation
->SuggestedDriveLetter
&&
440 !HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
442 /* Just create a mount point */
443 SymbolicName
.Buffer
= NameBuffer
;
444 RtlCopyMemory(NameBuffer
, DosDevices
.Buffer
, DosDevices
.Length
);
445 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
446 NameBuffer
[COLON_POSITION
] = L
':';
447 SymbolicName
.Length
=
448 SymbolicName
.MaximumLength
= DRIVE_LETTER_LENGTH
;
450 MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &(DeviceInformation
->DeviceName
));
459 MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension
,
460 IN PUNICODE_STRING DeviceName
,
461 OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo
)
465 PLIST_ENTRY NextEntry
;
466 PMOUNTDEV_UNIQUE_ID UniqueId
;
467 BOOLEAN Removable
, GptDriveLetter
;
468 PDEVICE_INFORMATION DeviceInformation
;
469 WCHAR NameBuffer
[DRIVE_LETTER_LENGTH
];
470 PSYMLINK_INFORMATION SymlinkInformation
;
471 UNICODE_STRING TargetDeviceName
, SymbolicName
;
473 /* First, process suggested letters */
474 if (!DeviceExtension
->ProcessedSuggestions
)
476 ProcessSuggestedDriveLetters(DeviceExtension
);
477 DeviceExtension
->ProcessedSuggestions
= TRUE
;
480 /* Then, get information about the device */
481 Status
= QueryDeviceInformation(DeviceName
, &TargetDeviceName
, NULL
, &Removable
, &GptDriveLetter
, NULL
, NULL
, NULL
);
482 if (!NT_SUCCESS(Status
))
487 /* Ensure we have such device */
488 NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
489 while (NextEntry
!= &(DeviceExtension
->DeviceListHead
))
491 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
493 if (RtlCompareUnicodeString(&(DeviceInformation
->DeviceName
), &TargetDeviceName
, TRUE
) == 0)
498 NextEntry
= NextEntry
->Flink
;
501 if (NextEntry
== &(DeviceExtension
->DeviceListHead
))
503 FreePool(TargetDeviceName
.Buffer
);
504 return STATUS_OBJECT_NAME_NOT_FOUND
;
507 /* Now, mark we have assigned a letter (assumption) */
508 DeviceInformation
->LetterAssigned
=
509 DriveLetterInfo
->DriveLetterWasAssigned
= TRUE
;
511 /* Browse all the symlink to see if there's already a drive letter */
512 NextEntry
= DeviceInformation
->SymbolicLinksListHead
.Flink
;
513 while (NextEntry
!= &(DeviceInformation
->SymbolicLinksListHead
))
515 SymlinkInformation
= CONTAINING_RECORD(NextEntry
, SYMLINK_INFORMATION
, SymbolicLinksListEntry
);
517 /* This is a driver letter & online one, forget about new drive eltter */
518 if (IsDriveLetter(&(SymlinkInformation
->Name
)) && SymlinkInformation
->Online
)
520 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
521 DriveLetterInfo
->CurrentDriveLetter
= (CHAR
)SymlinkInformation
->Name
.Buffer
[LETTER_POSITION
];
525 NextEntry
= NextEntry
->Flink
;
528 /* If we didn't find a drive letter online
529 * ensure there's no GPT drive letter nor no drive entry
531 if (NextEntry
== &(DeviceInformation
->SymbolicLinksListHead
))
533 if (GptDriveLetter
|| HasNoDriveLetterEntry(DeviceInformation
->UniqueId
))
535 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
536 DriveLetterInfo
->CurrentDriveLetter
= 0;
542 /* No, ensure that the device is not automonted nor removable */
543 if (!DeviceExtension
->NoAutoMount
&& !Removable
)
545 if (DriveLetterInfo
->DriveLetterWasAssigned
)
547 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
548 DriveLetterInfo
->CurrentDriveLetter
= 0;
554 if (!DriveLetterInfo
->DriveLetterWasAssigned
)
559 /* Now everything is fine, start processing */
561 if (RtlPrefixUnicodeString(&DeviceFloppy
, &TargetDeviceName
, TRUE
))
563 /* If the device is a floppy, start with letter A */
566 else if (RtlPrefixUnicodeString(&DeviceCdRom
, &TargetDeviceName
, TRUE
))
568 /* If the device is a CD-ROM, start with letter D */
573 /* Finally, if it's a disk, use C */
577 /* We cannot set NO drive letter */
578 ASSERT(DeviceInformation
->SuggestedDriveLetter
!= (UCHAR
)-1);
580 /* If we don't have suggested letter but it's a FT volume, fail */
581 if (!DeviceInformation
->SuggestedDriveLetter
&& IsFtVolume(&(DeviceInformation
->DeviceName
)))
583 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
584 DriveLetterInfo
->CurrentDriveLetter
= 0;
590 RtlCopyMemory(NameBuffer
, DosDevices
.Buffer
, DosDevices
.Length
);
591 NameBuffer
[COLON_POSITION
] = L
':';
592 SymbolicName
.Buffer
= NameBuffer
;
593 SymbolicName
.Length
=
594 SymbolicName
.MaximumLength
= DRIVE_LETTER_LENGTH
;
596 /* It's all prepared, create mount point */
597 if (DeviceInformation
->SuggestedDriveLetter
)
599 DriveLetterInfo
->CurrentDriveLetter
= DeviceInformation
->SuggestedDriveLetter
;
600 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
602 Status
= MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &TargetDeviceName
);
603 if (NT_SUCCESS(Status
))
609 /* It failed with this letter... Try another one! */
610 for (DriveLetterInfo
->CurrentDriveLetter
= DriveLetter
;
611 DriveLetterInfo
->CurrentDriveLetter
<= L
'Z';
612 DriveLetterInfo
->CurrentDriveLetter
++)
614 NameBuffer
[LETTER_POSITION
] = DeviceInformation
->SuggestedDriveLetter
;
616 Status
= MountMgrCreatePointWorker(DeviceExtension
, &SymbolicName
, &TargetDeviceName
);
617 if (NT_SUCCESS(Status
))
623 /* We failed setting a letter */
624 if (DriveLetterInfo
->CurrentDriveLetter
> L
'Z')
626 DriveLetterInfo
->DriveLetterWasAssigned
= FALSE
;
627 DriveLetterInfo
->CurrentDriveLetter
= 0;
629 /* Try at least to add a no drive letter entry */
630 Status
= QueryDeviceInformation(&TargetDeviceName
, NULL
, &UniqueId
, NULL
, NULL
, NULL
, NULL
, NULL
);
631 if (NT_SUCCESS(Status
))
633 CreateNoDriveLetterEntry(UniqueId
);
639 FreePool(TargetDeviceName
.Buffer
);
641 return STATUS_SUCCESS
;
649 MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension
,
653 PIO_STACK_LOCATION Stack
;
654 UNICODE_STRING DeviceName
;
655 PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget
;
656 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation
;
658 Stack
= IoGetNextIrpStackLocation(Irp
);
661 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_DRIVE_LETTER_TARGET
) ||
662 Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION
))
664 return STATUS_INVALID_PARAMETER
;
667 DriveLetterTarget
= (PMOUNTMGR_DRIVE_LETTER_TARGET
)Irp
->AssociatedIrp
.SystemBuffer
;
668 if (DriveLetterTarget
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
670 return STATUS_INVALID_PARAMETER
;
673 /* Call the worker */
674 DeviceName
.Buffer
= DriveLetterTarget
->DeviceName
;
676 DeviceName
.MaximumLength
= DriveLetterTarget
->DeviceNameLength
;
678 Status
= MountMgrNextDriveLetterWorker(DeviceExtension
, &DeviceName
,
679 &DriveLetterInformation
);
680 if (NT_SUCCESS(Status
))
682 *(PMOUNTMGR_DRIVE_LETTER_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
=
683 DriveLetterInformation
;
684 Irp
->IoStatus
.Information
= sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION
);
695 MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName
,
698 IN ULONG ValueLength
,
700 IN PVOID EntryContext
)
702 UNICODE_STRING ValueString
;
703 PUNICODE_STRING SystemVolumeName
;
705 UNREFERENCED_PARAMETER(ValueName
);
706 UNREFERENCED_PARAMETER(ValueLength
);
707 UNREFERENCED_PARAMETER(EntryContext
);
709 if (ValueType
!= REG_SZ
)
711 return STATUS_SUCCESS
;
714 RtlInitUnicodeString(&ValueString
, ValueData
);
715 SystemVolumeName
= Context
;
717 /* Return a string containing system volume name */
718 SystemVolumeName
->Length
= ValueString
.Length
;
719 SystemVolumeName
->MaximumLength
= ValueString
.Length
+ sizeof(WCHAR
);
720 SystemVolumeName
->Buffer
= AllocatePool(SystemVolumeName
->MaximumLength
);
721 if (SystemVolumeName
->Buffer
)
723 RtlCopyMemory(SystemVolumeName
->Buffer
, ValueData
, ValueString
.Length
);
724 SystemVolumeName
->Buffer
[ValueString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
727 return STATUS_SUCCESS
;
735 MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName
)
737 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
739 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
740 QueryTable
[0].QueryRoutine
= MountMgrQuerySystemVolumeNameQueryRoutine
;
741 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
742 QueryTable
[0].Name
= L
"SystemPartition";
744 SystemVolumeName
->Buffer
= NULL
;
746 RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
747 L
"\\Registry\\Machine\\System\\Setup",
752 if (SystemVolumeName
->Buffer
)
754 return STATUS_SUCCESS
;
757 return STATUS_UNSUCCESSFUL
;
764 MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension
)
767 PLIST_ENTRY NextEntry
;
768 UNICODE_STRING SystemVolumeName
;
769 PDEVICE_INFORMATION DeviceInformation
;
770 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation
;
772 /* First, get system volume name */
773 Status
= MountMgrQuerySystemVolumeName(&SystemVolumeName
);
775 /* If there are no device, it's all done */
776 if (IsListEmpty(&(DeviceExtension
->DeviceListHead
)))
778 if (NT_SUCCESS(Status
))
780 FreePool(SystemVolumeName
.Buffer
);
786 /* Now, for all the devices... */
787 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
788 NextEntry
!= &(DeviceExtension
->DeviceListHead
);
789 NextEntry
= NextEntry
->Flink
)
791 DeviceInformation
= CONTAINING_RECORD(NextEntry
, DEVICE_INFORMATION
, DeviceListEntry
);
793 /* If the device doesn't have a letter assigned, do it! */
794 if (!DeviceInformation
->LetterAssigned
)
796 MountMgrNextDriveLetterWorker(DeviceExtension
,
797 &(DeviceInformation
->DeviceName
),
798 &DriveLetterInformation
);
801 /* If it was the system volume */
802 if (NT_SUCCESS(Status
) && RtlEqualUnicodeString(&SystemVolumeName
, &(DeviceInformation
->DeviceName
), TRUE
))
804 /* Keep track of it */
805 DeviceExtension
->DriveLetterData
= AllocatePool(DeviceInformation
->UniqueId
->UniqueIdLength
+
806 sizeof(MOUNTDEV_UNIQUE_ID
));
807 if (DeviceExtension
->DriveLetterData
)
809 RtlCopyMemory(DeviceExtension
->DriveLetterData
,
810 DeviceInformation
->UniqueId
,
811 DeviceInformation
->UniqueId
->UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
814 /* If it was not automount, ensure it gets mounted */
815 if (!DeviceExtension
->NoAutoMount
)
817 DeviceExtension
->NoAutoMount
= TRUE
;
819 MountMgrNextDriveLetterWorker(DeviceExtension
,
820 &(DeviceInformation
->DeviceName
),
821 &DriveLetterInformation
);
823 DeviceExtension
->NoAutoMount
= FALSE
;
828 if (NT_SUCCESS(Status
))
830 FreePool(SystemVolumeName
.Buffer
);
835 MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension
,
840 PIO_STACK_LOCATION Stack
;
841 PLIST_ENTRY SymlinksEntry
;
842 UNICODE_STRING SymbolicName
;
843 PMOUNTMGR_TARGET_NAME Target
;
844 PWSTR DeviceString
, OldBuffer
;
845 USHORT DeviceLength
, OldLength
;
846 PDEVICE_INFORMATION DeviceInformation
;
847 PSYMLINK_INFORMATION SymlinkInformation
;
848 PASSOCIATED_DEVICE_ENTRY AssociatedDevice
;
850 Stack
= IoGetNextIrpStackLocation(Irp
);
852 /* Validate input size */
853 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_TARGET_NAME
))
855 return STATUS_INVALID_PARAMETER
;
858 /* Ensure we have received UNICODE_STRING */
859 Target
= (PMOUNTMGR_TARGET_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
860 if (Target
->DeviceNameLength
& 1)
862 return STATUS_INVALID_PARAMETER
;
865 /* Validate the entry structure size */
866 if (Target
->DeviceNameLength
+ sizeof(UNICODE_NULL
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
868 return STATUS_INVALID_PARAMETER
;
871 /* Ensure we can at least return needed size */
872 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
874 return STATUS_INVALID_PARAMETER
;
877 /* Construct string for query */
878 SymbolicName
.Length
= Target
->DeviceNameLength
;
879 SymbolicName
.MaximumLength
= Target
->DeviceNameLength
+ sizeof(UNICODE_NULL
);
880 SymbolicName
.Buffer
= Target
->DeviceName
;
882 /* Find device with our info */
883 Status
= FindDeviceInfo(DeviceExtension
, &SymbolicName
, FALSE
, &DeviceInformation
);
884 if (!NT_SUCCESS(Status
))
893 /* Try to find associated device info */
896 for (SymlinksEntry
= DeviceInformation
->SymbolicLinksListHead
.Flink
;
897 SymlinksEntry
!= &(DeviceInformation
->SymbolicLinksListHead
);
898 SymlinksEntry
= SymlinksEntry
->Flink
)
900 SymlinkInformation
= CONTAINING_RECORD(SymlinksEntry
, SYMLINK_INFORMATION
, SymbolicLinksListEntry
);
902 /* Try to find with drive letter */
903 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation
->Name
) && SymlinkInformation
->Online
)
909 /* We didn't find, break */
910 if (SymlinksEntry
== &(DeviceInformation
->SymbolicLinksListHead
))
915 /* It doesn't have associated device, go to fallback method */
916 if (IsListEmpty(&DeviceInformation
->AssociatedDevicesHead
))
918 goto TryWithVolumeName
;
921 /* Create a string with the information about the device */
922 AssociatedDevice
= CONTAINING_RECORD(&(DeviceInformation
->SymbolicLinksListHead
), ASSOCIATED_DEVICE_ENTRY
, AssociatedDevicesEntry
);
923 OldLength
= DeviceLength
;
924 OldBuffer
= DeviceString
;
925 DeviceLength
+= AssociatedDevice
->String
.Length
;
926 DeviceString
= AllocatePool(DeviceLength
);
934 return STATUS_INSUFFICIENT_RESOURCES
;
937 /* Store our info and previous if any */
938 RtlCopyMemory(DeviceString
, AssociatedDevice
->String
.Buffer
, AssociatedDevice
->String
.Length
);
941 RtlCopyMemory(&DeviceString
[AssociatedDevice
->String
.Length
/ sizeof(WCHAR
)], OldBuffer
, OldLength
);
945 /* Count and continue looking */
947 DeviceInformation
= AssociatedDevice
->DeviceInformation
;
949 /* If too many devices, try another way */
950 if (DevicesFound
> MAX_DEVICES
) /* 1000 */
952 goto TryWithVolumeName
;
956 /* Reallocate our string, so that we can prepend disk letter */
957 OldBuffer
= DeviceString
;
958 OldLength
= DeviceLength
;
959 DeviceLength
+= 2 * sizeof(WCHAR
);
960 DeviceString
= AllocatePool(DeviceLength
);
968 return STATUS_INSUFFICIENT_RESOURCES
;
972 DeviceString
[0] = SymlinkInformation
->Name
.Buffer
[12];
973 DeviceString
[1] = L
':';
975 /* And copy the rest */
978 RtlCopyMemory(&DeviceString
[2], OldBuffer
, OldLength
);
983 /* If we didn't find anything, try differently */
984 if (DeviceLength
< 2 * sizeof(WCHAR
) || DeviceString
[1] != L
':')
988 FreePool(DeviceString
);
992 /* Try to find a volume name matching */
993 for (SymlinksEntry
= DeviceInformation
->SymbolicLinksListHead
.Flink
;
994 SymlinksEntry
!= &(DeviceInformation
->SymbolicLinksListHead
);
995 SymlinksEntry
= SymlinksEntry
->Flink
)
997 SymlinkInformation
= CONTAINING_RECORD(SymlinksEntry
, SYMLINK_INFORMATION
, SymbolicLinksListEntry
);
999 if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation
->Name
))
1006 if (SymlinksEntry
!= &(DeviceInformation
->SymbolicLinksListHead
))
1008 DeviceLength
= SymlinkInformation
->Name
.Length
;
1009 DeviceString
= AllocatePool(DeviceLength
);
1012 return STATUS_INSUFFICIENT_RESOURCES
;
1015 RtlCopyMemory(DeviceString
, SymlinkInformation
->Name
.Buffer
, DeviceLength
);
1016 /* Ensure we are in the right namespace; [1] can be ? */
1017 DeviceString
[1] = L
'\\';
1021 /* If we found something */
1024 /* At least, we will return our length */
1025 ((PMOUNTMGR_VOLUME_PATHS
)Irp
->AssociatedIrp
.SystemBuffer
)->MultiSzLength
= DeviceLength
;
1026 /* MOUNTMGR_VOLUME_PATHS is a string + a ULONG */
1027 Irp
->IoStatus
.Information
= DeviceLength
+ sizeof(ULONG
);
1029 /* If we have enough room for copying the string */
1030 if (sizeof(ULONG
) + DeviceLength
<= Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
1035 RtlCopyMemory(((PMOUNTMGR_VOLUME_PATHS
)Irp
->AssociatedIrp
.SystemBuffer
)->MultiSz
, DeviceString
, DeviceLength
);
1038 /* And double zero at its end - this is needed in case of multiple paths which are separated by a single 0 */
1039 FreePool(DeviceString
);
1040 ((PMOUNTMGR_VOLUME_PATHS
)Irp
->AssociatedIrp
.SystemBuffer
)->MultiSz
[DeviceLength
/ sizeof(WCHAR
)] = 0;
1041 ((PMOUNTMGR_VOLUME_PATHS
)Irp
->AssociatedIrp
.SystemBuffer
)->MultiSz
[DeviceLength
/ sizeof(WCHAR
) + 1] = 0;
1043 return STATUS_SUCCESS
;
1047 /* Just return appropriate size and leave */
1048 FreePool(DeviceString
);
1049 Irp
->IoStatus
.Information
= sizeof(ULONG
);
1050 return STATUS_BUFFER_OVERFLOW
;
1055 return STATUS_NOT_FOUND
;
1059 MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension
,
1062 UNREFERENCED_PARAMETER(DeviceExtension
);
1063 UNREFERENCED_PARAMETER(Irp
);
1064 return STATUS_NOT_IMPLEMENTED
;
1071 MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension
,
1075 PIO_STACK_LOCATION Stack
;
1076 UNICODE_STRING SymbolicName
;
1077 PMOUNTMGR_TARGET_NAME Target
;
1078 PDEVICE_INFORMATION DeviceInformation
;
1080 Stack
= IoGetNextIrpStackLocation(Irp
);
1082 /* Validate input */
1083 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_TARGET_NAME
))
1085 return STATUS_INVALID_PARAMETER
;
1088 Target
= (PMOUNTMGR_TARGET_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
1089 if (Target
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1091 return STATUS_INVALID_PARAMETER
;
1094 SymbolicName
.Length
=
1095 SymbolicName
.MaximumLength
= Target
->DeviceNameLength
;
1096 SymbolicName
.Buffer
= Target
->DeviceName
;
1098 /* Find the associated device */
1099 Status
= FindDeviceInfo(DeviceExtension
, &SymbolicName
, FALSE
, &DeviceInformation
);
1100 if (!NT_SUCCESS(Status
))
1105 /* Mark we want to keep links */
1106 DeviceInformation
->KeepLinks
= TRUE
;
1108 return STATUS_SUCCESS
;
1115 MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension
,
1120 PIO_STACK_LOCATION Stack
;
1121 UNICODE_STRING SymbolicName
;
1122 PMOUNTMGR_TARGET_NAME Target
;
1124 Stack
= IoGetNextIrpStackLocation(Irp
);
1126 /* Validate input */
1127 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_TARGET_NAME
))
1129 return STATUS_INVALID_PARAMETER
;
1132 Target
= (PMOUNTMGR_TARGET_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
1133 if (Target
->DeviceNameLength
+ sizeof(USHORT
) > Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1135 return STATUS_INVALID_PARAMETER
;
1138 SymbolicName
.Length
=
1139 SymbolicName
.MaximumLength
= Target
->DeviceNameLength
;
1140 SymbolicName
.Buffer
= Target
->DeviceName
;
1142 /* Disable hard errors */
1143 OldState
= PsGetThreadHardErrorsAreDisabled(PsGetCurrentThread());
1144 PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), TRUE
);
1146 /* Call real worker */
1147 Status
= MountMgrMountedDeviceArrival(DeviceExtension
, &SymbolicName
, TRUE
);
1149 PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), OldState
);
1158 MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension
,
1162 PIO_STACK_LOCATION Stack
;
1163 PMOUNTDEV_UNIQUE_ID UniqueId
;
1164 PMOUNTMGR_MOUNT_POINT MountPoint
;
1165 UNICODE_STRING SymbolicName
, DeviceName
;
1167 Stack
= IoGetNextIrpStackLocation(Irp
);
1169 /* Validate input... */
1170 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINT
))
1172 return STATUS_INVALID_PARAMETER
;
1175 MountPoint
= (PMOUNTMGR_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
1176 if (!MountPoint
->SymbolicLinkNameLength
)
1178 MountPoint
->SymbolicLinkNameOffset
= 0;
1181 if (!MountPoint
->UniqueIdLength
)
1183 MountPoint
->UniqueIdOffset
= 0;
1186 if (!MountPoint
->DeviceNameLength
)
1188 MountPoint
->DeviceNameOffset
= 0;
1191 /* Addresses can't be odd */
1192 if ((MountPoint
->SymbolicLinkNameOffset
& 1) ||
1193 (MountPoint
->SymbolicLinkNameLength
& 1))
1195 return STATUS_INVALID_PARAMETER
;
1198 if ((MountPoint
->UniqueIdOffset
& 1) ||
1199 (MountPoint
->UniqueIdLength
& 1))
1201 return STATUS_INVALID_PARAMETER
;
1204 if ((MountPoint
->DeviceNameOffset
& 1) ||
1205 (MountPoint
->DeviceNameLength
& 1))
1207 return STATUS_INVALID_PARAMETER
;
1210 /* We can't go beyond */
1211 if (((ULONG
)MountPoint
->SymbolicLinkNameLength
+ MountPoint
->UniqueIdLength
+
1212 MountPoint
->DeviceNameLength
) < Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1214 return STATUS_INVALID_PARAMETER
;
1217 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINTS
))
1219 return STATUS_INVALID_PARAMETER
;
1222 /* If caller provided a Symlink, use it */
1223 if (MountPoint
->SymbolicLinkNameLength
!= 0)
1225 if (MountPoint
->SymbolicLinkNameLength
> MAXSHORT
)
1227 return STATUS_INVALID_PARAMETER
;
1230 SymbolicName
.Length
= MountPoint
->SymbolicLinkNameLength
;
1231 SymbolicName
.MaximumLength
= MountPoint
->SymbolicLinkNameLength
+ sizeof(WCHAR
);
1232 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
1233 if (!SymbolicName
.Buffer
)
1235 return STATUS_INSUFFICIENT_RESOURCES
;
1238 RtlCopyMemory(SymbolicName
.Buffer
,
1239 (PWSTR
)((ULONG_PTR
)MountPoint
+ MountPoint
->SymbolicLinkNameOffset
),
1240 SymbolicName
.Length
);
1241 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1243 /* Query links using it */
1244 Status
= QueryPointsFromSymbolicLinkName(DeviceExtension
, &SymbolicName
, Irp
);
1245 FreePool(SymbolicName
.Buffer
);
1247 /* If user provided an unique ID */
1248 else if (MountPoint
->UniqueIdLength
!= 0)
1250 UniqueId
= AllocatePool(MountPoint
->UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1253 return STATUS_INSUFFICIENT_RESOURCES
;
1256 UniqueId
->UniqueIdLength
= MountPoint
->UniqueIdLength
;
1257 RtlCopyMemory(UniqueId
->UniqueId
,
1258 (PVOID
)((ULONG_PTR
)MountPoint
+ MountPoint
->UniqueIdOffset
),
1259 MountPoint
->UniqueIdLength
);
1261 /* Query links using it */
1262 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, UniqueId
, NULL
);
1265 /* If caller provided a device name */
1266 else if (MountPoint
->DeviceNameLength
!= 0)
1268 if (MountPoint
->DeviceNameLength
> MAXSHORT
)
1270 return STATUS_INVALID_PARAMETER
;
1273 DeviceName
.Length
= MountPoint
->DeviceNameLength
;
1274 DeviceName
.MaximumLength
= MountPoint
->DeviceNameLength
+ sizeof(WCHAR
);
1275 DeviceName
.Buffer
= AllocatePool(DeviceName
.MaximumLength
);
1276 if (!DeviceName
.Buffer
)
1278 return STATUS_INSUFFICIENT_RESOURCES
;
1281 RtlCopyMemory(DeviceName
.Buffer
,
1282 (PWSTR
)((ULONG_PTR
)MountPoint
+ MountPoint
->DeviceNameOffset
),
1284 DeviceName
.Buffer
[DeviceName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1286 /* Query links using it */
1287 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, NULL
, &DeviceName
);
1288 FreePool(DeviceName
.Buffer
);
1292 /* Otherwise, query all links */
1293 Status
= QueryPointsFromMemory(DeviceExtension
, Irp
, NULL
, NULL
);
1303 MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension
,
1308 BOOLEAN CreateNoDrive
;
1309 PIO_STACK_LOCATION Stack
;
1310 PMOUNTDEV_UNIQUE_ID UniqueId
;
1311 PMOUNTMGR_MOUNT_POINT MountPoint
;
1312 PMOUNTMGR_MOUNT_POINTS MountPoints
;
1313 UNICODE_STRING SymbolicName
, DeviceName
;
1315 Stack
= IoGetNextIrpStackLocation(Irp
);
1317 /* Validate input */
1318 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_MOUNT_POINT
))
1320 return STATUS_INVALID_PARAMETER
;
1324 MountPoint
= (PMOUNTMGR_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
1325 CreateNoDrive
= (MountPoint
->SymbolicLinkNameOffset
&& MountPoint
->SymbolicLinkNameLength
);
1327 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1328 if (!NT_SUCCESS(Status
))
1333 /* For all the points matching the request */
1334 MountPoints
= (PMOUNTMGR_MOUNT_POINTS
)Irp
->AssociatedIrp
.SystemBuffer
;
1335 for (Link
= 0; Link
< MountPoints
->NumberOfMountPoints
; Link
++)
1337 SymbolicName
.Length
= MountPoints
->MountPoints
[Link
].SymbolicLinkNameLength
;
1338 SymbolicName
.MaximumLength
= SymbolicName
.Length
+ sizeof(WCHAR
);
1339 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
1340 if (!SymbolicName
.Buffer
)
1342 return STATUS_INSUFFICIENT_RESOURCES
;
1345 RtlCopyMemory(SymbolicName
.Buffer
,
1346 (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].SymbolicLinkNameOffset
),
1347 SymbolicName
.Length
);
1348 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1350 /* Create a no drive entry for the drive letters */
1351 if (CreateNoDrive
&& IsDriveLetter(&SymbolicName
))
1353 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1356 UniqueId
->UniqueIdLength
= MountPoints
->MountPoints
[Link
].UniqueIdLength
;
1357 RtlCopyMemory(UniqueId
->UniqueId
,
1358 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1359 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1361 CreateNoDriveLetterEntry(UniqueId
);
1366 /* If there are no link any more, and no need to create a no drive entry */
1367 if (Link
== 0 && !CreateNoDrive
)
1369 /* Then, delete everything */
1370 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1373 RtlCopyMemory(UniqueId
,
1374 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1375 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1377 DeleteNoDriveLetterEntry(UniqueId
);
1382 /* Delete all the information about the mount point */
1383 GlobalDeleteSymbolicLink(&SymbolicName
);
1384 DeleteSymbolicLinkNameFromMemory(DeviceExtension
, &SymbolicName
, FALSE
);
1385 RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE
, DatabasePath
, SymbolicName
.Buffer
);
1386 FreePool(SymbolicName
.Buffer
);
1388 /* Notify the change */
1389 DeviceName
.Length
= DeviceName
.MaximumLength
=
1390 MountPoints
->MountPoints
[Link
].DeviceNameLength
;
1391 DeviceName
.Buffer
= (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].DeviceNameOffset
);
1392 MountMgrNotifyNameChange(DeviceExtension
, &DeviceName
, TRUE
);
1395 MountMgrNotify(DeviceExtension
);
1404 MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension
,
1409 UNICODE_STRING SymbolicName
;
1410 PMOUNTDEV_UNIQUE_ID UniqueId
;
1411 PMOUNTMGR_MOUNT_POINTS MountPoints
;
1414 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1415 if (!NT_SUCCESS(Status
))
1420 MountPoints
= (PMOUNTMGR_MOUNT_POINTS
)Irp
->AssociatedIrp
.SystemBuffer
;
1421 if (MountPoints
->NumberOfMountPoints
== 0)
1426 /* For all the mount points */
1427 for (Link
= 0; Link
< MountPoints
->NumberOfMountPoints
; Link
++)
1429 SymbolicName
.Length
= MountPoints
->MountPoints
[Link
].SymbolicLinkNameLength
;
1430 SymbolicName
.MaximumLength
= SymbolicName
.Length
+ sizeof(WCHAR
);
1431 SymbolicName
.Buffer
= AllocatePool(SymbolicName
.MaximumLength
);
1432 if (!SymbolicName
.Buffer
)
1434 return STATUS_INSUFFICIENT_RESOURCES
;
1437 RtlCopyMemory(SymbolicName
.Buffer
,
1438 (PWSTR
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].SymbolicLinkNameOffset
),
1439 SymbolicName
.Length
);
1440 SymbolicName
.Buffer
[SymbolicName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1442 /* If the only mount point is a drive letter, then create a no letter drive entry */
1443 if (MountPoints
->NumberOfMountPoints
== 1 && IsDriveLetter(&SymbolicName
))
1445 UniqueId
= AllocatePool(MountPoints
->MountPoints
[Link
].UniqueIdLength
+ sizeof(MOUNTDEV_UNIQUE_ID
));
1448 UniqueId
->UniqueIdLength
= MountPoints
->MountPoints
[Link
].UniqueIdLength
;
1449 RtlCopyMemory(UniqueId
->UniqueId
,
1450 (PMOUNTDEV_UNIQUE_ID
)((ULONG_PTR
)MountPoints
+ MountPoints
->MountPoints
[Link
].UniqueIdOffset
),
1451 MountPoints
->MountPoints
[Link
].UniqueIdLength
);
1453 CreateNoDriveLetterEntry(UniqueId
);
1458 /* Simply delete mount point from DB */
1459 DeleteSymbolicLinkNameFromMemory(DeviceExtension
, &SymbolicName
, TRUE
);
1460 RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE
, DatabasePath
, SymbolicName
.Buffer
);
1461 FreePool(SymbolicName
.Buffer
);
1471 MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension
,
1473 IN NTSTATUS LockStatus
,
1474 OUT PUNICODE_STRING SourceDeviceName
,
1475 OUT PUNICODE_STRING SourceSymbolicName
,
1476 OUT PUNICODE_STRING TargetVolumeName
)
1480 PFILE_OBJECT FileObject
;
1481 PIO_STACK_LOCATION Stack
;
1482 ULONG Length
, SavedLength
;
1483 BOOLEAN FOReferenced
= FALSE
;
1484 IO_STATUS_BLOCK IoStatusBlock
;
1485 OBJECT_ATTRIBUTES ObjectAttributes
;
1486 PDEVICE_INFORMATION DeviceInformation
;
1487 OBJECT_NAME_INFORMATION ObjectNameInfo
;
1488 FILE_FS_DEVICE_INFORMATION FsDeviceInfo
;
1489 PFILE_NAME_INFORMATION FileNameInfo
= NULL
;
1490 PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint
;
1491 POBJECT_NAME_INFORMATION ObjectNameInfoPtr
= NULL
;
1492 UNICODE_STRING SourceVolumeName
, TargetDeviceName
;
1494 Stack
= IoGetNextIrpStackLocation(Irp
);
1496 /* Validate input */
1497 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(MOUNTMGR_VOLUME_MOUNT_POINT
))
1499 return STATUS_INVALID_PARAMETER
;
1502 VolumeMountPoint
= (PMOUNTMGR_VOLUME_MOUNT_POINT
)Irp
->AssociatedIrp
.SystemBuffer
;
1504 if (((ULONG
)VolumeMountPoint
->SourceVolumeNameLength
+ VolumeMountPoint
->TargetVolumeNameLength
) <
1505 Stack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1507 return STATUS_INVALID_PARAMETER
;
1510 /* Get source volume name */
1511 SourceVolumeName
.Length
=
1512 SourceVolumeName
.MaximumLength
= VolumeMountPoint
->SourceVolumeNameLength
;
1513 SourceVolumeName
.Buffer
= (PWSTR
)((ULONG_PTR
)VolumeMountPoint
+ VolumeMountPoint
->SourceVolumeNameOffset
);
1515 InitializeObjectAttributes(&ObjectAttributes
,
1517 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
1522 Status
= ZwOpenFile(&Handle
,
1523 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
1526 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1527 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_REPARSE_POINT
);
1528 if (!NT_SUCCESS(Status
))
1533 TargetDeviceName
.Buffer
= NULL
;
1535 /* Query its attributes */
1536 Status
= ZwQueryVolumeInformationFile(Handle
,
1539 sizeof(FsDeviceInfo
),
1540 FileFsDeviceInformation
);
1541 if (!NT_SUCCESS(Status
))
1546 if (FsDeviceInfo
.DeviceType
!= FILE_DEVICE_DISK
&& FsDeviceInfo
.DeviceType
!= FILE_DEVICE_VIRTUAL_DISK
)
1551 if (FsDeviceInfo
.Characteristics
!= (FILE_REMOTE_DEVICE
| FILE_REMOVABLE_MEDIA
))
1557 Status
= ObReferenceObjectByHandle(Handle
, 0, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
1558 if (!NT_SUCCESS(Status
))
1562 FOReferenced
= TRUE
;
1565 FileNameInfo
= AllocatePool(sizeof(FILE_NAME_INFORMATION
));
1568 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1572 Status
= ZwQueryInformationFile(Handle
, &IoStatusBlock
, FileNameInfo
,
1573 sizeof(FILE_NAME_INFORMATION
),
1574 FileNameInformation
);
1575 if (Status
== STATUS_BUFFER_OVERFLOW
)
1577 /* Now we have real length, use it */
1578 Length
= FileNameInfo
->FileNameLength
;
1579 FreePool(FileNameInfo
);
1581 FileNameInfo
= AllocatePool(sizeof(FILE_NAME_INFORMATION
) + Length
);
1584 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1588 /* Really query file name */
1589 Status
= ZwQueryInformationFile(Handle
, &IoStatusBlock
, FileNameInfo
,
1590 sizeof(FILE_NAME_INFORMATION
) + Length
,
1591 FileNameInformation
);
1594 if (!NT_SUCCESS(Status
))
1599 /* Get symbolic name */
1600 ObjectNameInfoPtr
= &ObjectNameInfo
;
1601 SavedLength
= sizeof(OBJECT_NAME_INFORMATION
);
1602 Status
= ObQueryNameString(FileObject
->DeviceObject
, ObjectNameInfoPtr
, sizeof(OBJECT_NAME_INFORMATION
), &Length
);
1603 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
1605 /* Once again, with proper size, it works better */
1606 ObjectNameInfoPtr
= AllocatePool(Length
);
1607 if (!ObjectNameInfoPtr
)
1609 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1613 SavedLength
= Length
;
1614 Status
= ObQueryNameString(FileObject
->DeviceObject
, ObjectNameInfoPtr
, SavedLength
, &Length
);
1617 if (!NT_SUCCESS(Status
))
1622 /* Now, query the device name */
1623 Status
= QueryDeviceInformation(&ObjectNameInfoPtr
->Name
, SourceDeviceName
,
1624 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1625 if (!NT_SUCCESS(Status
))
1630 /* For target volume name, use input */
1631 TargetVolumeName
->Length
=
1632 TargetVolumeName
->MaximumLength
= VolumeMountPoint
->TargetVolumeNameLength
;
1633 TargetVolumeName
->Buffer
= (PWSTR
)((ULONG_PTR
)VolumeMountPoint
+ VolumeMountPoint
->TargetVolumeNameOffset
);
1635 /* Query its device name */
1636 Status
= QueryDeviceInformation(TargetVolumeName
, &TargetDeviceName
,
1637 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1638 if (!NT_SUCCESS(Status
))
1643 /* Return symbolic name */
1644 SourceSymbolicName
->Length
=
1645 SourceSymbolicName
->MaximumLength
= (USHORT
)FileNameInfo
->FileNameLength
;
1646 SourceSymbolicName
->Buffer
= (PWSTR
)FileNameInfo
;
1647 /* memmove allows memory overlap */
1648 RtlMoveMemory(SourceSymbolicName
->Buffer
, FileNameInfo
->FileName
, SourceSymbolicName
->Length
);
1649 FileNameInfo
= NULL
;
1651 /* Notify the change */
1652 MountMgrNotify(DeviceExtension
);
1653 MountMgrNotifyNameChange(DeviceExtension
, &TargetDeviceName
, TRUE
);
1655 /* If we are locked, sync databases if possible */
1656 if (NT_SUCCESS(LockStatus
))
1658 Status
= FindDeviceInfo(DeviceExtension
, SourceDeviceName
, FALSE
, &DeviceInformation
);
1659 if (NT_SUCCESS(Status
))
1661 ReconcileThisDatabaseWithMaster(DeviceExtension
, DeviceInformation
);
1665 Status
= STATUS_PENDING
;
1670 if (TargetDeviceName
.Buffer
)
1672 FreePool(TargetDeviceName
.Buffer
);
1675 if (ObjectNameInfoPtr
&& ObjectNameInfoPtr
!= &ObjectNameInfo
)
1677 FreePool(ObjectNameInfoPtr
);
1682 FreePool(FileNameInfo
);
1687 ObDereferenceObject(FileObject
);
1694 MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension
,
1696 IN NTSTATUS LockStatus
)
1698 UNREFERENCED_PARAMETER(DeviceExtension
);
1699 UNREFERENCED_PARAMETER(Irp
);
1700 UNREFERENCED_PARAMETER(LockStatus
);
1701 return STATUS_NOT_IMPLEMENTED
;
1705 MountMgrVolumeMountPointDeleted(IN PDEVICE_EXTENSION DeviceExtension
,
1707 IN NTSTATUS LockStatus
)
1709 UNREFERENCED_PARAMETER(DeviceExtension
);
1710 UNREFERENCED_PARAMETER(Irp
);
1711 UNREFERENCED_PARAMETER(LockStatus
);
1712 return STATUS_NOT_IMPLEMENTED
;
1720 MountMgrDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1723 PIO_STACK_LOCATION Stack
;
1724 NTSTATUS Status
, LockStatus
;
1725 PDEVICE_EXTENSION DeviceExtension
;
1727 Stack
= IoGetNextIrpStackLocation(Irp
);
1728 DeviceExtension
= DeviceObject
->DeviceExtension
;
1730 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1732 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
1734 case IOCTL_MOUNTMGR_CREATE_POINT
:
1735 Status
= MountMgrCreatePoint(DeviceExtension
, Irp
);
1738 case IOCTL_MOUNTMGR_DELETE_POINTS
:
1739 Status
= MountMgrDeletePoints(DeviceExtension
, Irp
);
1742 case IOCTL_MOUNTMGR_QUERY_POINTS
:
1743 Status
= MountMgrQueryPoints(DeviceExtension
, Irp
);
1746 case IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY
:
1747 Status
= MountMgrDeletePointsDbOnly(DeviceExtension
, Irp
);
1750 case IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
:
1751 Status
= MountMgrNextDriveLetter(DeviceExtension
, Irp
);
1754 case IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
:
1755 DeviceExtension
->AutomaticDriveLetter
= TRUE
;
1756 Status
= STATUS_SUCCESS
;
1758 MountMgrAssignDriveLetters(DeviceExtension
);
1759 ReconcileAllDatabasesWithMaster(DeviceExtension
);
1760 WaitForOnlinesToComplete(DeviceExtension
);
1763 case IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED
:
1764 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1766 LockStatus
= WaitForRemoteDatabaseSemaphore(DeviceExtension
);
1767 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1768 Status
= MountMgrVolumeMountPointCreated(DeviceExtension
, Irp
, LockStatus
);
1769 if (NT_SUCCESS(LockStatus
))
1771 ReleaseRemoteDatabaseSemaphore(DeviceExtension
);
1776 case IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED
:
1777 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1779 LockStatus
= WaitForRemoteDatabaseSemaphore(DeviceExtension
);
1780 KeWaitForSingleObject(&(DeviceExtension
->DeviceLock
), Executive
, KernelMode
, FALSE
, NULL
);
1781 Status
= MountMgrVolumeMountPointDeleted(DeviceExtension
, Irp
, LockStatus
);
1782 if (NT_SUCCESS(LockStatus
))
1784 ReleaseRemoteDatabaseSemaphore(DeviceExtension
);
1789 case IOCTL_MOUNTMGR_CHANGE_NOTIFY
:
1790 Status
= MountMgrChangeNotify(DeviceExtension
, Irp
);
1793 case IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE
:
1794 Status
= MountMgrKeepLinksWhenOffline(DeviceExtension
, Irp
);
1797 case IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES
:
1798 Status
= MountMgrCheckUnprocessedVolumes(DeviceExtension
, Irp
);
1801 case IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
:
1802 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1803 Status
= MountMgrVolumeArrivalNotification(DeviceExtension
, Irp
);
1806 case IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
:
1807 Status
= MountMgrQueryDosVolumePath(DeviceExtension
, Irp
);
1810 case IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
:
1811 Status
= MountMgrQueryDosVolumePaths(DeviceExtension
, Irp
);
1814 case IOCTL_MOUNTMGR_SCRUB_REGISTRY
:
1815 Status
= MountMgrScrubRegistry(DeviceExtension
);
1818 case IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT
:
1819 Status
= MountMgrQueryAutoMount(DeviceExtension
, Irp
);
1822 case IOCTL_MOUNTMGR_SET_AUTO_MOUNT
:
1823 Status
= MountMgrSetAutoMount(DeviceExtension
, Irp
);
1827 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1830 KeReleaseSemaphore(&(DeviceExtension
->DeviceLock
), IO_NO_INCREMENT
, 1, FALSE
);
1832 if (Status
!= STATUS_PENDING
)
1840 Irp
->IoStatus
.Status
= Status
;
1841 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);