ReactOS 0.4.16-dev-1059-gb1cf981
device.c
Go to the documentation of this file.
1/*
2 * ReactOS kernel
3 * Copyright (C) 2011-2012 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 *
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)
24 */
25
26#include "mntmgr.h"
27
28#define MAX_DEVICES 0x3E8 /* Matches 1000 devices */
29
30#define NDEBUG
31#include <debug.h>
32
33/*
34 * @implemented
35 */
38 IN PIRP Irp)
39{
44
45 /* Get the I/O buffer */
47 ChangeNotify = (PMOUNTMGR_CHANGE_NOTIFY_INFO)Irp->AssociatedIrp.SystemBuffer;
48
49 /* Validate it */
50 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO) ||
51 Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO))
52 {
54 }
55
56 /* If epic number doesn't match, just return now one */
57 if (DeviceExtension->EpicNumber != ChangeNotify->EpicNumber)
58 {
59 ChangeNotify->EpicNumber = DeviceExtension->EpicNumber;
60 Irp->IoStatus.Information = sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO);
61 return STATUS_SUCCESS;
62 }
63
64 /* If IRP is to be canceled, forget about that */
66 if (Irp->Cancel)
67 {
69 }
70 /* Otherwise queue the IRP to be notified with the next epic number change */
71 else
72 {
73 InsertTailList(&(DeviceExtension->IrpListHead), &(Irp->Tail.Overlay.ListEntry));
77 }
79
80 return Status;
81}
82
83/*
84 * @implemented
85 */
88{
89 ULONG Value = DeviceExtension->NoAutoMount;
90
92 DeviceExtension->RegistryPath.Buffer,
93 L"NoAutoMount",
95 &Value,
96 sizeof(Value));
97}
98
99/*
100 * @implemented
101 */
104 IN PIRP Irp)
105{
108
110
111 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_SET_AUTO_MOUNT))
112 {
113 Irp->IoStatus.Information = 0;
115 }
116
117 /* Change the state only if there is a real difference
118 * with the user-provided NewState (normalized) */
119 SetState = (PMOUNTMGR_SET_AUTO_MOUNT)Irp->AssociatedIrp.SystemBuffer;
120 if ((SetState->NewState != Enabled) == DeviceExtension->NoAutoMount)
121 {
122 Irp->IoStatus.Information = 0;
123 return STATUS_SUCCESS;
124 }
125
126 /* Set new state */
127 DeviceExtension->NoAutoMount = (SetState->NewState != Enabled);
128 Irp->IoStatus.Information = 0;
129 return MountmgrWriteNoAutoMount(DeviceExtension);
130}
131
132/*
133 * @implemented
134 */
137 IN PIRP Irp)
138{
141
143
144 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_QUERY_AUTO_MOUNT))
145 {
146 Irp->IoStatus.Information = 0;
148 }
149
150 QueryState = (PMOUNTMGR_QUERY_AUTO_MOUNT)Irp->AssociatedIrp.SystemBuffer;
151 QueryState->CurrentState = !DeviceExtension->NoAutoMount;
152 Irp->IoStatus.Information = sizeof(MOUNTMGR_QUERY_AUTO_MOUNT);
153
154 return STATUS_SUCCESS;
155}
156
157/*
158 * @implemented
159 */
161NTAPI
168{
170 PLIST_ENTRY NextEntry;
172 PBOOLEAN Continue = EntryContext;
173 PDEVICE_EXTENSION DeviceExtension = Context;
174
175 if (ValueType != REG_BINARY)
176 {
177 return STATUS_SUCCESS;
178 }
179
180 /* Delete values for devices that don't have the matching unique ID */
181 if (!IsListEmpty(&(DeviceExtension->DeviceListHead)))
182 {
183 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
184 NextEntry != &(DeviceExtension->DeviceListHead);
185 NextEntry = NextEntry->Flink)
186 {
187 DeviceInfo = CONTAINING_RECORD(NextEntry,
189 DeviceListEntry);
190
191 if (!DeviceInfo->UniqueId || DeviceInfo->UniqueId->UniqueIdLength != ValueLength)
192 {
193 continue;
194 }
195
197 {
198 return STATUS_SUCCESS;
199 }
200 }
201 }
202
203 /* Wrong unique ID, scrub it */
206 ValueName);
207 if (!NT_SUCCESS(Status))
208 {
209 *Continue = TRUE;
210 return STATUS_UNSUCCESSFUL;
211 }
212
213 *Continue = FALSE;
214 return Status;
215}
216
217/*
218 * @implemented
219 */
222{
224 BOOLEAN Continue;
226
227 do
228 {
231 QueryTable[0].EntryContext = &Continue;
232 Continue = FALSE;
233
237 DeviceExtension,
238 NULL);
239 }
240 while (Continue);
241
242 return Status;
243}
244
245/*
246 * @implemented
247 */
250 IN PIRP Irp)
251{
252 ULONG MaxLength;
256
258
259 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_CREATE_POINT_INPUT))
260 {
262 }
263
264 Point = (PMOUNTMGR_CREATE_POINT_INPUT)Irp->AssociatedIrp.SystemBuffer;
265
266 MaxLength = MAX((Point->DeviceNameOffset + Point->DeviceNameLength),
267 (Point->SymbolicLinkNameLength + Point->SymbolicLinkNameOffset));
268 if (MaxLength > Stack->Parameters.DeviceIoControl.InputBufferLength)
269 {
271 }
272
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);
280
281 return MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &DeviceName);
282}
283
284/*
285 * @implemented
286 */
289 IN PIRP Irp)
290{
291 PLIST_ENTRY NextEntry;
292 PDEVICE_INFORMATION DeviceInformation;
293 NTSTATUS ArrivalStatus, Status = STATUS_SUCCESS;
294
296
297 /* No offline volumes, nothing more to do */
298 if (IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
299 {
300 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
301 return STATUS_SUCCESS;
302 }
303
304 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
305
306 /* Reactivate all the offline volumes */
307 while (!IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
308 {
309 NextEntry = RemoveHeadList(&(DeviceExtension->OfflineDeviceListHead));
310 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
311
312 ArrivalStatus = MountMgrMountedDeviceArrival(DeviceExtension,
313 &(DeviceInformation->SymbolicName),
314 DeviceInformation->ManuallyRegistered);
315 /* Then, remove them dead information */
316 MountMgrFreeDeadDeviceInfo(DeviceInformation);
317
318 if (NT_SUCCESS(Status))
319 {
320 Status = ArrivalStatus;
321 }
322 }
323
324 return Status;
325}
326
327/*
328 * @implemented
329 */
332{
336 PDEVICE_OBJECT DeviceObject, FileDeviceObject;
337
338 /* Get device object */
341 &FileObject,
342 &DeviceObject);
343 if (!NT_SUCCESS(Status))
344 return FALSE;
345
346 /* Get attached device */
347 FileDeviceObject = FileObject->DeviceObject;
348 DeviceObject = IoGetAttachedDeviceReference(FileDeviceObject);
349
350 /* FT volume can't be removable */
351 if (FileDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
352 {
355 return FALSE;
356 }
357
359
360 /* Get partition information */
361 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO,
363 NULL,
364 0,
366 sizeof(PartitionInfo),
367 NULL);
368
370 if (!NT_SUCCESS(Status))
371 return FALSE;
372
373 /* Check if this is a FT volume */
374 return IsFTPartition(PartitionInfo.PartitionType);
375}
376
377/*
378 * @implemented
379 */
380VOID
382{
383 WCHAR NameBuffer[DRIVE_LETTER_LENGTH / sizeof(WCHAR)];
384 PLIST_ENTRY NextEntry;
386 PDEVICE_INFORMATION DeviceInformation;
387
388 /* No devices? Nothing to do! */
389 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
390 {
391 return;
392 }
393
394 /* For all the devices */
395 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
396 NextEntry != &(DeviceExtension->DeviceListHead);
397 NextEntry = NextEntry->Flink)
398 {
399 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
400
401 /* If no drive letter */
402 if (DeviceInformation->SuggestedDriveLetter == (UCHAR)-1)
403 {
404 /* Ensure it has no entry yet */
405 if (!HasDriveLetter(DeviceInformation) &&
406 !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
407 {
408 /* And create one */
409 CreateNoDriveLetterEntry(DeviceInformation->UniqueId);
410 }
411
412 DeviceInformation->SuggestedDriveLetter = 0;
413 }
414 /* Suggested letter & no entry */
415 else if (DeviceInformation->SuggestedDriveLetter &&
416 !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
417 {
418 /* Just create a mount point */
419 SymbolicName.Buffer = NameBuffer;
421 NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
422 NameBuffer[COLON_POSITION] = L':';
425
426 MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &(DeviceInformation->DeviceName));
427 }
428 }
429}
430
431/*
432 * @implemented
433 */
438{
440 UCHAR DriveLetter;
441 PLIST_ENTRY NextEntry;
442 PMOUNTDEV_UNIQUE_ID UniqueId;
443 BOOLEAN Removable, GptDriveLetter;
444 PDEVICE_INFORMATION DeviceInformation;
445 WCHAR NameBuffer[DRIVE_LETTER_LENGTH];
446 PSYMLINK_INFORMATION SymlinkInformation;
447 UNICODE_STRING TargetDeviceName, SymbolicName;
448
449 /* First, process suggested letters */
450 if (!DeviceExtension->ProcessedSuggestions)
451 {
452 ProcessSuggestedDriveLetters(DeviceExtension);
453 DeviceExtension->ProcessedSuggestions = TRUE;
454 }
455
456 /* Then, get information about the device */
457 Status = QueryDeviceInformation(DeviceName, &TargetDeviceName, NULL, &Removable, &GptDriveLetter, NULL, NULL, NULL);
458 if (!NT_SUCCESS(Status))
459 {
460 return Status;
461 }
462
463 /* Ensure we have such device */
464 NextEntry = DeviceExtension->DeviceListHead.Flink;
465 while (NextEntry != &(DeviceExtension->DeviceListHead))
466 {
467 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
468
469 if (RtlCompareUnicodeString(&(DeviceInformation->DeviceName), &TargetDeviceName, TRUE) == 0)
470 {
471 break;
472 }
473
474 NextEntry = NextEntry->Flink;
475 }
476
477 if (NextEntry == &(DeviceExtension->DeviceListHead))
478 {
479 FreePool(TargetDeviceName.Buffer);
481 }
482
483 /* Now, assume we will assign a letter */
484 DeviceInformation->LetterAssigned =
485 DriveLetterInfo->DriveLetterWasAssigned = TRUE;
486
487 /* Browse all the symlinks to check if there is already a drive letter */
488 NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
489 while (NextEntry != &(DeviceInformation->SymbolicLinksListHead))
490 {
491 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
492
493 /* If this is a drive letter and it is online, forget about new drive letter */
494 if (IsDriveLetter(&(SymlinkInformation->Name)) && SymlinkInformation->Online)
495 {
496 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
497 DriveLetterInfo->CurrentDriveLetter = (CHAR)SymlinkInformation->Name.Buffer[LETTER_POSITION];
498 break;
499 }
500
501 NextEntry = NextEntry->Flink;
502 }
503
504 /* If we didn't find a drive letter online, ensure this is not
505 * a no-drive entry by querying GPT attributes & database */
506 if (NextEntry == &(DeviceInformation->SymbolicLinksListHead))
507 {
508 if (!GptDriveLetter || HasNoDriveLetterEntry(DeviceInformation->UniqueId))
509 {
510 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
511 DriveLetterInfo->CurrentDriveLetter = 0;
512 goto Release;
513 }
514 }
515
516 /* If automount is disabled, and the device is not removable
517 * but needs a drive letter, don't assign one and bail out */
518 if (DeviceExtension->NoAutoMount && !Removable)
519 {
520 if (DriveLetterInfo->DriveLetterWasAssigned)
521 {
522 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
523 DriveLetterInfo->CurrentDriveLetter = 0;
524 goto Release;
525 }
526 }
527
528 /* Stop now if we don't need to assign the drive a letter */
529 if (!DriveLetterInfo->DriveLetterWasAssigned)
530 goto Release;
531
532 /* Now everything is fine, begin drive letter assignment */
533
534 if (RtlPrefixUnicodeString(&DeviceFloppy, &TargetDeviceName, TRUE))
535 {
536 /* If the device is a floppy, start with letter A */
537 DriveLetter = 'A';
538 }
539 else if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
540 {
541 /* If the device is a CD-ROM, start with letter D */
542 DriveLetter = 'D';
543 }
544 else
545 {
546 /* Finally, if it's a disk, use C */
547 DriveLetter = 'C';
548 }
549
550 /* We cannot set NO drive letter */
551 ASSERT(DeviceInformation->SuggestedDriveLetter != (UCHAR)-1);
552
553 /* If we don't have suggested letter but it's a FT volume, fail */
554 if (!DeviceInformation->SuggestedDriveLetter && IsFtVolume(&(DeviceInformation->DeviceName)))
555 {
556 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
557 DriveLetterInfo->CurrentDriveLetter = 0;
558 goto Release;
559 }
560
561 /* Prepare buffer */
563 NameBuffer[COLON_POSITION] = L':';
564 SymbolicName.Buffer = NameBuffer;
567
568 /* It's all prepared, create mount point */
569 if (DeviceInformation->SuggestedDriveLetter)
570 {
571 DriveLetterInfo->CurrentDriveLetter = DeviceInformation->SuggestedDriveLetter;
572 NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
573
574 Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
575 if (NT_SUCCESS(Status))
576 {
577 goto Release;
578 }
579 }
580
581 /* It failed with this letter... Try another one! */
582 for (DriveLetterInfo->CurrentDriveLetter = DriveLetter;
583 DriveLetterInfo->CurrentDriveLetter <= L'Z';
584 DriveLetterInfo->CurrentDriveLetter++)
585 {
586 NameBuffer[LETTER_POSITION] = DriveLetterInfo->CurrentDriveLetter;
587
588 Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
589 if (NT_SUCCESS(Status))
590 {
591 break;
592 }
593 }
594
595 /* We failed setting a letter */
596 if (DriveLetterInfo->CurrentDriveLetter > L'Z')
597 {
598 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
599 DriveLetterInfo->CurrentDriveLetter = 0;
600
601 /* Try at least to add a no drive letter entry */
602 Status = QueryDeviceInformation(&TargetDeviceName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
603 if (NT_SUCCESS(Status))
604 {
605 CreateNoDriveLetterEntry(UniqueId);
606 FreePool(UniqueId);
607 }
608 }
609
610Release:
611 FreePool(TargetDeviceName.Buffer);
612
613 return STATUS_SUCCESS;
614}
615
616
617/*
618 * @implemented
619 */
622 IN PIRP Irp)
623{
627 PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget;
628 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
629
631
632 /* Validate input */
633 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) ||
634 Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION))
635 {
637 }
638
639 DriveLetterTarget = (PMOUNTMGR_DRIVE_LETTER_TARGET)Irp->AssociatedIrp.SystemBuffer;
641 Stack->Parameters.DeviceIoControl.InputBufferLength)
642 {
644 }
645
646 /* Call the worker */
647 DeviceName.Buffer = DriveLetterTarget->DeviceName;
648 DeviceName.Length =
649 DeviceName.MaximumLength = DriveLetterTarget->DeviceNameLength;
650
652 &DriveLetterInformation);
653 if (NT_SUCCESS(Status))
654 {
655 *(PMOUNTMGR_DRIVE_LETTER_INFORMATION)Irp->AssociatedIrp.SystemBuffer =
656 DriveLetterInformation;
657 Irp->IoStatus.Information = sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION);
658 }
659
660 return Status;
661}
662
663/*
664 * @implemented
665 */
667NTAPI
674{
675 UNICODE_STRING ValueString;
676 PUNICODE_STRING SystemVolumeName;
677
681
682 if (ValueType != REG_SZ)
683 {
684 return STATUS_SUCCESS;
685 }
686
687 RtlInitUnicodeString(&ValueString, ValueData);
688 SystemVolumeName = Context;
689
690 /* Return a string containing system volume name */
691 SystemVolumeName->Length = ValueString.Length;
692 SystemVolumeName->MaximumLength = ValueString.Length + sizeof(WCHAR);
693 SystemVolumeName->Buffer = AllocatePool(SystemVolumeName->MaximumLength);
694 if (SystemVolumeName->Buffer)
695 {
696 RtlCopyMemory(SystemVolumeName->Buffer, ValueData, ValueString.Length);
697 SystemVolumeName->Buffer[ValueString.Length / sizeof(WCHAR)] = UNICODE_NULL;
698 }
699
700 return STATUS_SUCCESS;
701
702}
703
704/*
705 * @implemented
706 */
709{
711
715 QueryTable[0].Name = L"SystemPartition";
716
717 SystemVolumeName->Buffer = NULL;
718
720 L"\\Registry\\Machine\\System\\Setup",
722 SystemVolumeName,
723 NULL);
724
725 if (SystemVolumeName->Buffer)
726 {
727 return STATUS_SUCCESS;
728 }
729
730 return STATUS_UNSUCCESSFUL;
731}
732
733/*
734 * @implemented
735 */
736VOID
738{
740 PLIST_ENTRY NextEntry;
741 UNICODE_STRING SystemVolumeName;
742 PDEVICE_INFORMATION DeviceInformation;
743 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
744
745 /* First, get system volume name */
746 Status = MountMgrQuerySystemVolumeName(&SystemVolumeName);
747
748 /* If there are no device, it's all done */
749 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
750 {
751 if (NT_SUCCESS(Status))
752 {
753 FreePool(SystemVolumeName.Buffer);
754 }
755
756 return;
757 }
758
759 /* Now, for all the devices... */
760 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
761 NextEntry != &(DeviceExtension->DeviceListHead);
762 NextEntry = NextEntry->Flink)
763 {
764 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
765
766 /* If the device doesn't have a letter assigned, do it! */
767 if (!DeviceInformation->LetterAssigned)
768 {
769 MountMgrNextDriveLetterWorker(DeviceExtension,
770 &(DeviceInformation->DeviceName),
771 &DriveLetterInformation);
772 }
773
774 /* If it's the system volume */
775 if (NT_SUCCESS(Status) && RtlEqualUnicodeString(&SystemVolumeName, &(DeviceInformation->DeviceName), TRUE))
776 {
777 /* Keep track of it */
778 DeviceExtension->DriveLetterData = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength +
779 sizeof(MOUNTDEV_UNIQUE_ID));
780 if (DeviceExtension->DriveLetterData)
781 {
782 RtlCopyMemory(DeviceExtension->DriveLetterData,
783 DeviceInformation->UniqueId,
784 DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
785 }
786
787 /* Ensure it gets mounted if automount is disabled */
788 if (DeviceExtension->NoAutoMount)
789 {
790 /* Temporarily re-enable automount for the
791 * worker to mount and set a drive letter */
792 DeviceExtension->NoAutoMount = FALSE;
793
794 MountMgrNextDriveLetterWorker(DeviceExtension,
795 &(DeviceInformation->DeviceName),
796 &DriveLetterInformation);
797
798 /* And re-disable automount */
799 DeviceExtension->NoAutoMount = TRUE;
800 }
801 }
802 }
803
804 if (NT_SUCCESS(Status))
805 {
806 FreePool(SystemVolumeName.Buffer);
807 }
808}
809
810/*
811 * @implemented
812 */
815 IN PIRP Irp)
816{
818 ULONG DevicesFound;
820 PLIST_ENTRY SymlinksEntry;
824 PWSTR DeviceString, OldBuffer;
825 USHORT DeviceLength, OldLength;
826 PDEVICE_INFORMATION DeviceInformation;
827 PSYMLINK_INFORMATION SymlinkInformation;
829
831
832 /* Validate input size */
833 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
834 {
836 }
837
838 /* Ensure we have received UNICODE_STRING */
839 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
840 if (Target->DeviceNameLength & 1)
841 {
843 }
844
845 /* Validate the entry structure size */
846 if (FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Target->DeviceNameLength >
847 Stack->Parameters.DeviceIoControl.InputBufferLength)
848 {
850 }
851
852 /* Ensure we can at least return needed size */
853 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz))
854 {
856 }
857
858 /* Construct string for query */
860 SymbolicName.MaximumLength = Target->DeviceNameLength;
861 SymbolicName.Buffer = Target->DeviceName;
862
863 /* Find device with our info */
864 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
865 if (!NT_SUCCESS(Status))
866 {
867 return Status;
868 }
869
870 DeviceLength = 0;
871 DeviceString = NULL;
872 DevicesFound = 0;
873
874 /* Try to find associated device info */
875 while (TRUE)
876 {
877 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
878 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
879 SymlinksEntry = SymlinksEntry->Flink)
880 {
881 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
882
883 /* Try to find with drive letter */
884 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
885 {
886 break;
887 }
888 }
889
890 /* If we've found a device via drive letter, do default processing */
891 if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
892 break;
893
894 /* If it doesn't have an associated device, go to fallback method */
895 if (IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
896 goto TryWithVolumeName;
897
898 /* Create a string with the information about the device */
899 AssociatedDevice = CONTAINING_RECORD(&(DeviceInformation->AssociatedDevicesHead), ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
900 OldLength = DeviceLength;
901 OldBuffer = DeviceString;
902 DeviceLength += AssociatedDevice->String.Length;
903 DeviceString = AllocatePool(DeviceLength);
904 if (!DeviceString)
905 {
906 if (OldBuffer)
907 {
908 FreePool(OldBuffer);
909 }
910
912 }
913
914 /* Store our info and previous if any */
915 RtlCopyMemory(DeviceString, AssociatedDevice->String.Buffer, AssociatedDevice->String.Length);
916 if (OldBuffer)
917 {
918 RtlCopyMemory(&DeviceString[AssociatedDevice->String.Length / sizeof(WCHAR)], OldBuffer, OldLength);
919 FreePool(OldBuffer);
920 }
921
922 /* Count and continue looking */
923 ++DevicesFound;
924 DeviceInformation = AssociatedDevice->DeviceInformation;
925
926 /* If too many devices, try another way */
927 if (DevicesFound > MAX_DEVICES) /* 1000 */
928 {
929 goto TryWithVolumeName;
930 }
931 }
932
933 /* Reallocate our string, so that we can prepend disk letter */
934 OldBuffer = DeviceString;
935 OldLength = DeviceLength;
936 DeviceLength += 2 * sizeof(WCHAR);
937 DeviceString = AllocatePool(DeviceLength);
938 if (!DeviceString)
939 {
940 if (OldBuffer)
941 {
942 FreePool(OldBuffer);
943 }
944
946 }
947
948 /* Get the letter */
949 DeviceString[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
950 DeviceString[1] = L':';
951
952 /* And copy the rest */
953 if (OldBuffer)
954 {
955 RtlCopyMemory(&DeviceString[2], OldBuffer, OldLength);
956 FreePool(OldBuffer);
957 }
958
959TryWithVolumeName:
960 /* If we didn't find anything, try differently */
961 if (DeviceLength < 2 * sizeof(WCHAR) || DeviceString[1] != L':')
962 {
963 if (DeviceString)
964 {
965 FreePool(DeviceString);
966 DeviceString = NULL;
967 DeviceLength = 0;
968 }
969
970 /* Try to find a volume name matching */
971 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
972 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
973 SymlinksEntry = SymlinksEntry->Flink)
974 {
975 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
976
977 if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation->Name))
978 {
979 break;
980 }
981 }
982
983 /* If found copy */
984 if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
985 {
986 DeviceLength = SymlinkInformation->Name.Length;
987 DeviceString = AllocatePool(DeviceLength);
988 if (!DeviceString)
989 {
991 }
992
993 RtlCopyMemory(DeviceString, SymlinkInformation->Name.Buffer, DeviceLength);
994 /* Ensure we are in the Win32 namespace; [1] can be '?' */
995 DeviceString[1] = L'\\';
996 }
997 }
998
999 /* If we didn't find something, fail */
1000 if (!DeviceString)
1001 return STATUS_NOT_FOUND;
1002
1003 /* Get the output buffer */
1004 Output = (PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer;
1005
1006 /* At least, we will return our length */
1007 Output->MultiSzLength = DeviceLength + 2 * sizeof(UNICODE_NULL);
1008 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz) + Output->MultiSzLength;
1009
1010 /* If we have enough room for copying the string */
1011 if (Irp->IoStatus.Information <= Stack->Parameters.DeviceIoControl.OutputBufferLength)
1012 {
1013 /* Copy it */
1014 if (DeviceLength)
1015 {
1016 RtlCopyMemory(Output->MultiSz, DeviceString, DeviceLength);
1017 }
1018
1019 /* And double-NUL at its end - this is needed in case of
1020 * multiple paths which are separated by a single NUL */
1021 FreePool(DeviceString);
1022 Output->MultiSz[DeviceLength / sizeof(WCHAR)] = UNICODE_NULL;
1023 Output->MultiSz[DeviceLength / sizeof(WCHAR) + 1] = UNICODE_NULL;
1024
1025 return STATUS_SUCCESS;
1026 }
1027 else
1028 {
1029 /* Just return the size needed and leave */
1030 FreePool(DeviceString);
1031 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz);
1033 }
1034}
1035
1036/*
1037 * @implemented
1038 */
1041 IN PDEVICE_INFORMATION DeviceInformation,
1043{
1044 HANDLE Handle;
1046 PLIST_ENTRY SymlinksEntry;
1048 PREPARSE_DATA_BUFFER ReparseData;
1050 UNICODE_STRING FullName, SubstituteName;
1051 PSYMLINK_INFORMATION SymlinkInformation;
1052
1053 /* Initialize & allocate a string big enough to contain our complete mount point name */
1054 FullName.Length = 0;
1055 FullName.MaximumLength = AssociatedDeviceEntry->String.Length
1056 + AssociatedDeviceEntry->DeviceInformation->DeviceName.Length
1057 + sizeof(WCHAR)
1058 + sizeof(UNICODE_NULL);
1060 if (!FullName.Buffer)
1061 {
1063 }
1064
1065 /* Create the path */
1066 RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->DeviceInformation->DeviceName);
1067 FullName.Buffer[FullName.Length / sizeof(WCHAR)] = L'\\';
1068 RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->String);
1070
1071 /* Open it to query the reparse point */
1073 &FullName,
1075 NULL,
1076 NULL);
1083
1084 if (!NT_SUCCESS(Status))
1085 {
1086 *Invalid = TRUE;
1087 return STATUS_SUCCESS;
1088 }
1089
1090 /* Allocate a buffer big enough to read reparse data */
1092 if (ReparseData == NULL)
1093 {
1094 ZwClose(Handle);
1096 }
1097
1098 /* Query reparse data */
1100 NULL, NULL, NULL,
1103 NULL, 0,
1105 ZwClose(Handle);
1106
1107 if (!NT_SUCCESS(Status))
1108 {
1109 FreePool(ReparseData);
1110 *Invalid = TRUE;
1111 return STATUS_SUCCESS;
1112 }
1113
1114 /* Create a string with the substitute name */
1115 SubstituteName.Length = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
1116 SubstituteName.MaximumLength = SubstituteName.Length;
1117 SubstituteName.Buffer = (PWSTR)((ULONG_PTR)ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset);
1118
1119 /* If that's a volume name that matches our associated device, that's a success! */
1120 if (MOUNTMGR_IS_VOLUME_NAME(&SubstituteName))
1121 {
1122 if (SubstituteName.Length == 98 && SubstituteName.Buffer[1] == L'?')
1123 {
1124 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1125 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
1126 SymlinksEntry = SymlinksEntry->Flink)
1127 {
1128 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1129
1130 if (RtlEqualUnicodeString(&SubstituteName, &SymlinkInformation->Name, TRUE))
1131 {
1132 FreePool(ReparseData);
1133 return STATUS_SUCCESS;
1134 }
1135 }
1136 }
1137 }
1138
1139 FreePool(ReparseData);
1140 *Invalid = TRUE;
1141 return STATUS_SUCCESS;
1142}
1143
1144/*
1145 * @implemented
1146 */
1149 IN PDEVICE_INFORMATION DeviceInformation,
1150 IN PLIST_ENTRY DeviceInfoList,
1151 OUT PMOUNTMGR_VOLUME_PATHS * VolumePaths,
1152 OUT PDEVICE_INFORMATION *FailedDevice)
1153{
1154 ULONG Written;
1157 PSYMLINK_INFORMATION SymlinkInformation;
1158 PDEVICE_INFORMATION_ENTRY DeviceInfoEntry;
1159 PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry;
1160 PMOUNTMGR_VOLUME_PATHS * Paths = NULL, * CurrentPath;
1161 ULONG OutputPathLength, NumberOfPaths, ReturnedPaths;
1162
1163 /* We return at least null char */
1164 OutputPathLength = sizeof(UNICODE_NULL);
1165
1166 for (Entry = DeviceInformation->SymbolicLinksListHead.Flink;
1167 Entry != &(DeviceInformation->SymbolicLinksListHead);
1168 Entry = Entry->Flink)
1169 {
1170 SymlinkInformation = CONTAINING_RECORD(Entry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1171
1172 /* Try to find the drive letter (ie, DOS device) */
1173 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
1174 {
1175 /* We'll return the letter */
1176 OutputPathLength = 4 * sizeof(WCHAR);
1177 break;
1178 }
1179 }
1180
1181 /* We didn't find any */
1182 if (Entry == &(DeviceInformation->SymbolicLinksListHead))
1183 {
1184 SymlinkInformation = NULL;
1185 }
1186
1187 /* Do we have any device info to return? */
1188 for (Entry = DeviceInfoList->Flink; Entry != DeviceInfoList; Entry = Entry->Flink)
1189 {
1190 DeviceInfoEntry = CONTAINING_RECORD(Entry, DEVICE_INFORMATION_ENTRY, DeviceInformationEntry);
1191
1192 /* Matching current device */
1193 if (DeviceInfoEntry->DeviceInformation == DeviceInformation)
1194 {
1195 /* Allocate the output buffer */
1196 *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1197 if (*VolumePaths == NULL)
1198 {
1200 }
1201
1202 /* Set size */
1203 (*VolumePaths)->MultiSzLength = OutputPathLength;
1204 /* If we have a drive letter, return it */
1205 if (SymlinkInformation != NULL)
1206 {
1207 (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1208 (*VolumePaths)->MultiSz[1] = L':';
1209 (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1210 (*VolumePaths)->MultiSz[3] = UNICODE_NULL;
1211 }
1212 else
1213 {
1214 (*VolumePaths)->MultiSz[0] = UNICODE_NULL;
1215 }
1216
1217 return STATUS_SUCCESS;
1218 }
1219 }
1220
1221 /* Allocate a new device entry */
1222 DeviceInfoEntry = AllocatePool(sizeof(DEVICE_INFORMATION_ENTRY));
1223 if (DeviceInfoEntry == NULL)
1224 {
1226 }
1227
1228 /* Add it to the list */
1229 DeviceInfoEntry->DeviceInformation = DeviceInformation;
1230 InsertTailList(DeviceInfoList, &DeviceInfoEntry->DeviceInformationEntry);
1231
1232 NumberOfPaths = 0;
1233 /* Count the amount of devices we will have to handle */
1234 if (!IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
1235 {
1236 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1237 Entry != &DeviceInformation->AssociatedDevicesHead;
1238 Entry = Entry->Flink)
1239 {
1240 ++NumberOfPaths;
1241 }
1242
1243 ASSERT(NumberOfPaths != 0);
1244 /* And allocate a big enough buffer */
1245 Paths = AllocatePool(NumberOfPaths * sizeof(PMOUNTMGR_VOLUME_PATHS));
1246 if (Paths == NULL)
1247 {
1248 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1249 FreePool(DeviceInfoEntry);
1251 }
1252 }
1253
1254 /* Start the hot loop to gather all the paths and be able to compute total output length! */
1255 ReturnedPaths = 0;
1256 CurrentPath = Paths;
1257 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1258 Entry != &DeviceInformation->AssociatedDevicesHead;
1259 Entry = Entry->Flink)
1260 {
1261 USHORT InnerStrings;
1263
1264 AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1265
1266 /* Validate the fact its a mount point by query reparse data */
1267 Status = MountMgrValidateBackPointer(AssociatedDeviceEntry, DeviceInformation, &Invalid);
1268
1269 /* If we found an invalid device, that's a failure */
1270 if (Invalid)
1271 {
1272 *FailedDevice = AssociatedDeviceEntry->DeviceInformation;
1274 }
1275
1276 /* Check whether we failed, if so, bail out */
1277 if (!NT_SUCCESS(Status))
1278 {
1279 ULONG i;
1280
1281 for (i = 0; i < ReturnedPaths; ++i)
1282 {
1283 FreePool(Paths[i]);
1284 }
1285
1286 if (Paths != NULL)
1287 {
1288 FreePool(Paths);
1289 }
1290 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1291 FreePool(DeviceInfoEntry);
1292 return Status;
1293 }
1294
1295 /* Query associated paths (hello ourselves :-)) */
1296 Status = MountMgrQueryVolumePaths(DeviceExtension,
1297 AssociatedDeviceEntry->DeviceInformation,
1298 DeviceInfoList,
1299 CurrentPath,
1300 FailedDevice);
1301 if (!NT_SUCCESS(Status))
1302 {
1303 ULONG i;
1304
1305 for (i = 0; i < ReturnedPaths; ++i)
1306 {
1307 FreePool(Paths[i]);
1308 }
1309
1310 if (Paths != NULL)
1311 {
1312 FreePool(Paths);
1313 }
1314 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1315 FreePool(DeviceInfoEntry);
1316 return Status;
1317 }
1318
1319 /* Count the number of strings we have in the multi string buffer */
1320 InnerStrings = 0;
1321 if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1322 {
1323 ULONG i;
1324 PWSTR MultiSz = (*CurrentPath)->MultiSz;
1325
1326 for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR); ++i, ++MultiSz)
1327 {
1328 if (*MultiSz == UNICODE_NULL)
1329 {
1330 ++InnerStrings;
1331 }
1332 }
1333 }
1334
1335 /* We returned one more path (ie, one more allocated buffer) */
1336 ++ReturnedPaths;
1337 /* Move the next pointer to use in the array */
1338 ++CurrentPath;
1339 /* Multiply String.Length by the number of found paths, we always add it after a path */
1340 OutputPathLength += (*CurrentPath)->MultiSzLength + InnerStrings * AssociatedDeviceEntry->String.Length - sizeof(UNICODE_NULL);
1341 }
1342
1343 /* Allocate the output buffer */
1344 *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1345 if (*VolumePaths == NULL)
1346 {
1347 ULONG i;
1348
1349 for (i = 0; i < ReturnedPaths; ++i)
1350 {
1351 FreePool(Paths[i]);
1352 }
1353
1354 if (Paths != NULL)
1355 {
1356 FreePool(Paths);
1357 }
1358 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1359 FreePool(DeviceInfoEntry);
1361 }
1362
1363 Written = 0;
1364 /* If we had found a DOS letter, that's the first thing we return */
1365 (*VolumePaths)->MultiSzLength = OutputPathLength;
1366 if (SymlinkInformation != NULL)
1367 {
1368 (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1369 (*VolumePaths)->MultiSz[1] = L':';
1370 (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1371 Written = 3;
1372 }
1373
1374 /* Now, browse again all our paths to return them */
1375 CurrentPath = Paths;
1376 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1377 Entry != &DeviceInformation->AssociatedDevicesHead;
1378 Entry = Entry->Flink)
1379 {
1380 AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1381
1382 /* If we had a path... */
1383 if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1384 {
1385 ULONG i, Offset;
1386 PWSTR MultiSz;
1387
1388 /* This offset is used to "jump" into MultiSz, so, start with the string begin (ie, skip MultiSzLength) */
1389 Offset = sizeof(ULONG);
1390 /* Browse every single letter, and skip last UNICODE_NULL */
1391 for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR) - 1; ++i)
1392 {
1393 /* Get the letter */
1394 MultiSz = (PWSTR)((ULONG_PTR)(*CurrentPath) + Offset);
1395 /* If it was part of the path, just return it */
1396 if (*MultiSz != UNICODE_NULL)
1397 {
1398 (*VolumePaths)->MultiSz[Written] = *MultiSz;
1399 }
1400 else
1401 {
1402 /* Otherwise, as planed, return our whole associated device name */
1403 RtlCopyMemory(&(*VolumePaths)->MultiSz[Written],
1404 AssociatedDeviceEntry->String.Buffer,
1405 AssociatedDeviceEntry->String.Length);
1406 Written += AssociatedDeviceEntry->String.Length / sizeof(WCHAR);
1407 /* And don't forget to nullify */
1408 (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1409 }
1410
1411 /* We at least return a letter or a null char */
1412 ++Written;
1413 /* Move to the next letter */
1414 Offset += sizeof(WCHAR);
1415 }
1416 }
1417
1418 FreePool(*CurrentPath);
1419 ++CurrentPath;
1420 }
1421
1422 /* MultiSz: don't forget last null char */
1423 (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1424 /* Cleanup everything and return success! */
1425 if (Paths != NULL)
1426 {
1427 FreePool(Paths);
1428 }
1429 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1430 FreePool(DeviceInfoEntry);
1431 return STATUS_SUCCESS;
1432}
1433
1434/*
1435 * @implemented
1436 */
1439 IN PIRP Irp)
1440{
1443 LIST_ENTRY Devices;
1444 BOOLEAN NeedNotification;
1447 ULONG Attempts, OutputLength;
1450 RECONCILE_WORK_ITEM_CONTEXT ReconcileContext;
1451 PDEVICE_INFORMATION DeviceInformation, ListDeviceInfo, FailedDevice;
1452
1454
1455 /* Validate input size */
1456 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1457 {
1459 }
1460
1461 /* Ensure we have received UNICODE_STRING */
1462 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1463 if (Target->DeviceNameLength & 1)
1464 {
1466 }
1467
1468 /* Validate the entry structure size */
1469 if (FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Target->DeviceNameLength >
1470 Stack->Parameters.DeviceIoControl.InputBufferLength)
1471 {
1473 }
1474
1475 /* Ensure we can at least return needed size */
1476 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz))
1477 {
1479 }
1480
1481 /* Construct string for query */
1483 SymbolicName.MaximumLength = Target->DeviceNameLength;
1484 SymbolicName.Buffer = Target->DeviceName;
1485
1486 /* Find device with our info */
1487 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1488 if (!NT_SUCCESS(Status))
1489 {
1490 return Status;
1491 }
1492
1493 NeedNotification = FALSE;
1494 Attempts = 0;
1495 for (;;)
1496 {
1497 FailedDevice = NULL;
1498 InitializeListHead(&Devices);
1499
1500 /* Query paths */
1501 Status = MountMgrQueryVolumePaths(DeviceExtension, DeviceInformation, &Devices, &Paths, &FailedDevice);
1502 if (NT_SUCCESS(Status))
1503 {
1504 break;
1505 }
1506
1507 /* If it failed for generic reason (memory, whatever), bail out (ie, FailedDevice not set) */
1508 if (FailedDevice == NULL)
1509 {
1510 return Status;
1511 }
1512
1513 /* If PnP, let's notify in case of success */
1514 if (!DeviceInformation->ManuallyRegistered)
1515 {
1516 NeedNotification = TRUE;
1517 }
1518
1519 /* Reconcile database */
1520 ReconcileContext.DeviceExtension = DeviceExtension;
1521 ReconcileContext.DeviceInformation = FailedDevice;
1522 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1523 ReconcileThisDatabaseWithMasterWorker(&ReconcileContext);
1524 KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1525
1526 /* Look for our device, to check it's online */
1527 for (Entry = DeviceExtension->DeviceListHead.Flink;
1528 Entry != &DeviceExtension->DeviceListHead;
1529 Entry = Entry->Flink)
1530 {
1531 ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
1532 /* It's online, it's OK! */
1533 if (ListDeviceInfo == DeviceInformation)
1534 {
1535 break;
1536 }
1537 }
1538
1539 /* It's not online, it's not good */
1540 if (Entry == &DeviceExtension->DeviceListHead)
1541 {
1543 }
1544
1545 /* Increase attempts count */
1546 ++Attempts;
1547 /* Don't look forever and fail if we get out of attempts */
1548 if (Attempts >= 1000)
1549 {
1550 return Status;
1551 }
1552 }
1553
1554 /* We need to notify? Go ahead */
1555 if (NeedNotification)
1556 {
1557 MountMgrNotifyNameChange(DeviceExtension, &SymbolicName, FALSE);
1558 }
1559
1560 /* Get the output buffer */
1561 Output = (PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer;
1562
1563 /* Set required size */
1564 Output->MultiSzLength = Paths->MultiSzLength;
1565
1566 /* Compute total length */
1567 OutputLength = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz) + Output->MultiSzLength;
1568
1569 /* If it cannot fit, just return the size needed and leave */
1570 if (OutputLength > Stack->Parameters.DeviceIoControl.OutputBufferLength)
1571 {
1572 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz);
1573 FreePool(Paths);
1575 }
1576
1577 /* Copy data and quit */
1578 Irp->IoStatus.Information = OutputLength;
1579 RtlCopyMemory(Output->MultiSz, Paths->MultiSz, Output->MultiSzLength);
1580 FreePool(Paths);
1581 return STATUS_SUCCESS;
1582}
1583
1584/*
1585 * @implemented
1586 */
1589 IN PIRP Irp)
1590{
1595 PDEVICE_INFORMATION DeviceInformation;
1596
1598
1599 /* Validate input */
1600 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1601 {
1603 }
1604
1605 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1606 if (FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Target->DeviceNameLength >
1607 Stack->Parameters.DeviceIoControl.InputBufferLength)
1608 {
1610 }
1611
1613 SymbolicName.MaximumLength = Target->DeviceNameLength;
1614 SymbolicName.Buffer = Target->DeviceName;
1615
1616 /* Find the associated device */
1617 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1618 if (!NT_SUCCESS(Status))
1619 {
1620 return Status;
1621 }
1622
1623 /* Mark we want to keep links */
1624 DeviceInformation->KeepLinks = TRUE;
1625
1626 return STATUS_SUCCESS;
1627}
1628
1629/*
1630 * @implemented
1631 */
1634 IN PIRP Irp)
1635{
1637 BOOLEAN OldState;
1641
1643
1644 /* Validate input */
1645 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1646 {
1648 }
1649
1650 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1651 if (FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Target->DeviceNameLength >
1652 Stack->Parameters.DeviceIoControl.InputBufferLength)
1653 {
1655 }
1656
1658 SymbolicName.MaximumLength = Target->DeviceNameLength;
1659 SymbolicName.Buffer = Target->DeviceName;
1660
1661 /* Disable hard errors */
1664
1665 /* Call real worker */
1667
1669
1670 return Status;
1671}
1672
1673/*
1674 * @implemented
1675 */
1678 IN PIRP Irp)
1679{
1682 PMOUNTDEV_UNIQUE_ID UniqueId;
1683 PMOUNTMGR_MOUNT_POINT MountPoint;
1685
1687
1688 /* Validate input... */
1689 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1690 {
1692 }
1693
1694 MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1695 if (!MountPoint->SymbolicLinkNameLength)
1696 {
1697 MountPoint->SymbolicLinkNameOffset = 0;
1698 }
1699
1700 if (!MountPoint->UniqueIdLength)
1701 {
1702 MountPoint->UniqueIdOffset = 0;
1703 }
1704
1705 if (!MountPoint->DeviceNameLength)
1706 {
1707 MountPoint->DeviceNameOffset = 0;
1708 }
1709
1710 /* Addresses can't be odd */
1711 if ((MountPoint->SymbolicLinkNameOffset & 1) ||
1712 (MountPoint->SymbolicLinkNameLength & 1))
1713 {
1715 }
1716
1717 if ((MountPoint->UniqueIdOffset & 1) ||
1718 (MountPoint->UniqueIdLength & 1))
1719 {
1721 }
1722
1723 if ((MountPoint->DeviceNameOffset & 1) ||
1724 (MountPoint->DeviceNameLength & 1))
1725 {
1727 }
1728
1729 /* We can't go beyond */
1730 if (((ULONG)MountPoint->SymbolicLinkNameLength + MountPoint->UniqueIdLength +
1731 MountPoint->DeviceNameLength) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1732 {
1734 }
1735
1736 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_MOUNT_POINTS))
1737 {
1739 }
1740
1741 /* If caller provided a Symlink, use it */
1742 if (MountPoint->SymbolicLinkNameLength != 0)
1743 {
1744 if (MountPoint->SymbolicLinkNameLength > MAXSHORT)
1745 {
1747 }
1748
1752 if (!SymbolicName.Buffer)
1753 {
1755 }
1756
1758 (PWSTR)((ULONG_PTR)MountPoint + MountPoint->SymbolicLinkNameOffset),
1761
1762 /* Query links using it */
1765 }
1766 /* If user provided an unique ID */
1767 else if (MountPoint->UniqueIdLength != 0)
1768 {
1769 UniqueId = AllocatePool(MountPoint->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1770 if (!UniqueId)
1771 {
1773 }
1774
1775 UniqueId->UniqueIdLength = MountPoint->UniqueIdLength;
1776 RtlCopyMemory(UniqueId->UniqueId,
1777 (PVOID)((ULONG_PTR)MountPoint + MountPoint->UniqueIdOffset),
1778 MountPoint->UniqueIdLength);
1779
1780 /* Query links using it */
1781 Status = QueryPointsFromMemory(DeviceExtension, Irp, UniqueId, NULL);
1782 FreePool(UniqueId);
1783 }
1784 /* If caller provided a device name */
1785 else if (MountPoint->DeviceNameLength != 0)
1786 {
1787 if (MountPoint->DeviceNameLength > MAXSHORT)
1788 {
1790 }
1791
1792 DeviceName.Length = MountPoint->DeviceNameLength;
1793 DeviceName.MaximumLength = MountPoint->DeviceNameLength + sizeof(WCHAR);
1794 DeviceName.Buffer = AllocatePool(DeviceName.MaximumLength);
1795 if (!DeviceName.Buffer)
1796 {
1798 }
1799
1801 (PWSTR)((ULONG_PTR)MountPoint + MountPoint->DeviceNameOffset),
1802 DeviceName.Length);
1803 DeviceName.Buffer[DeviceName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1804
1805 /* Query links using it */
1806 Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, &DeviceName);
1807 FreePool(DeviceName.Buffer);
1808 }
1809 else
1810 {
1811 /* Otherwise, query all links */
1812 Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, NULL);
1813 }
1814
1815 return Status;
1816}
1817
1818/*
1819 * @implemented
1820 */
1823 IN PIRP Irp)
1824{
1825 ULONG Link;
1827 BOOLEAN CreateNoDrive;
1829 PMOUNTDEV_UNIQUE_ID UniqueId;
1830 PMOUNTMGR_MOUNT_POINT MountPoint;
1831 PMOUNTMGR_MOUNT_POINTS MountPoints;
1833
1835
1836 /* Validate input */
1837 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1838 {
1840 }
1841
1842 /* Query points */
1843 MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1844 CreateNoDrive = (MountPoint->SymbolicLinkNameOffset && MountPoint->SymbolicLinkNameLength);
1845
1846 Status = MountMgrQueryPoints(DeviceExtension, Irp);
1847 if (!NT_SUCCESS(Status))
1848 {
1849 return Status;
1850 }
1851
1852 /* For all the points matching the request */
1853 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1854 for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1855 {
1859 if (!SymbolicName.Buffer)
1860 {
1862 }
1863
1865 (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1868
1869 /* Create a no drive entry for the drive letters */
1870 if (CreateNoDrive && IsDriveLetter(&SymbolicName))
1871 {
1872 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1873 if (UniqueId)
1874 {
1875 UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1876 RtlCopyMemory(UniqueId->UniqueId,
1877 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1878 MountPoints->MountPoints[Link].UniqueIdLength);
1879
1880 CreateNoDriveLetterEntry(UniqueId);
1881 FreePool(UniqueId);
1882 }
1883 }
1884
1885 /* If there are no link any more, and no need to create a no drive entry */
1886 if (Link == 0 && !CreateNoDrive)
1887 {
1888 /* Then, delete everything */
1889 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength);
1890 if (UniqueId)
1891 {
1892 RtlCopyMemory(UniqueId,
1893 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1894 MountPoints->MountPoints[Link].UniqueIdLength);
1895
1896 DeleteNoDriveLetterEntry(UniqueId);
1897 FreePool(UniqueId);
1898 }
1899 }
1900
1901 /* Delete all the information about the mount point */
1906
1907 /* Notify the change */
1908 DeviceName.Length = DeviceName.MaximumLength =
1909 MountPoints->MountPoints[Link].DeviceNameLength;
1910 DeviceName.Buffer = (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].DeviceNameOffset);
1911 MountMgrNotifyNameChange(DeviceExtension, &DeviceName, TRUE);
1912 }
1913
1914 MountMgrNotify(DeviceExtension);
1915
1916 return Status;
1917}
1918
1919/*
1920 * @implemented
1921 */
1924 IN PIRP Irp)
1925{
1926 ULONG Link;
1929 PMOUNTDEV_UNIQUE_ID UniqueId;
1930 PMOUNTMGR_MOUNT_POINTS MountPoints;
1931
1932 /* Query points */
1933 Status = MountMgrQueryPoints(DeviceExtension, Irp);
1934 if (!NT_SUCCESS(Status))
1935 {
1936 return Status;
1937 }
1938
1939 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1940 if (MountPoints->NumberOfMountPoints == 0)
1941 {
1942 return Status;
1943 }
1944
1945 /* For all the mount points */
1946 for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1947 {
1951 if (!SymbolicName.Buffer)
1952 {
1954 }
1955
1957 (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1960
1961 /* If the only mount point is a drive letter, then create a no letter drive entry */
1962 if (MountPoints->NumberOfMountPoints == 1 && IsDriveLetter(&SymbolicName))
1963 {
1964 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1965 if (UniqueId)
1966 {
1967 UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1968 RtlCopyMemory(UniqueId->UniqueId,
1969 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1970 MountPoints->MountPoints[Link].UniqueIdLength);
1971
1972 CreateNoDriveLetterEntry(UniqueId);
1973 FreePool(UniqueId);
1974 }
1975 }
1976
1977 /* Simply delete mount point from DB */
1981 }
1982
1983 return Status;
1984}
1985
1986/*
1987 * @implemented
1988 */
1991 IN PIRP Irp,
1992 IN NTSTATUS LockStatus,
1993 OUT PUNICODE_STRING SourceDeviceName,
1994 OUT PUNICODE_STRING SourceSymbolicName,
1995 OUT PUNICODE_STRING TargetVolumeName)
1996{
1997 HANDLE Handle;
2001 ULONG Length, SavedLength;
2002 BOOLEAN FOReferenced = FALSE;
2005 PDEVICE_INFORMATION DeviceInformation;
2006 OBJECT_NAME_INFORMATION ObjectNameInfo;
2007 FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
2008 PFILE_NAME_INFORMATION FileNameInfo = NULL;
2009 PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint;
2010 POBJECT_NAME_INFORMATION ObjectNameInfoPtr = NULL;
2011 UNICODE_STRING SourceVolumeName, TargetDeviceName;
2012
2014
2015 /* Validate input */
2016 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_VOLUME_MOUNT_POINT))
2017 {
2019 }
2020
2021 VolumeMountPoint = (PMOUNTMGR_VOLUME_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
2022
2023 if (((ULONG)VolumeMountPoint->SourceVolumeNameLength + VolumeMountPoint->TargetVolumeNameLength) <
2024 Stack->Parameters.DeviceIoControl.InputBufferLength)
2025 {
2027 }
2028
2029 /* Get source volume name */
2030 SourceVolumeName.Length =
2031 SourceVolumeName.MaximumLength = VolumeMountPoint->SourceVolumeNameLength;
2032 SourceVolumeName.Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset);
2033
2035 &SourceVolumeName,
2037 NULL,
2038 NULL);
2039
2040 /* Open it */
2047 if (!NT_SUCCESS(Status))
2048 {
2049 return Status;
2050 }
2051
2052 TargetDeviceName.Buffer = NULL;
2053
2054 /* Query its attributes */
2057 &FsDeviceInfo,
2058 sizeof(FsDeviceInfo),
2060 if (!NT_SUCCESS(Status))
2061 {
2062 goto Cleanup;
2063 }
2064
2065 /* Mount points can be stored only on storage disks */
2066 if (FsDeviceInfo.DeviceType != FILE_DEVICE_DISK && FsDeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK)
2067 {
2069 goto Cleanup;
2070 }
2071
2072 /* And they can be on local fixed disks only */
2074 {
2076 goto Cleanup;
2077 }
2078
2079 /* Reference it */
2081 if (!NT_SUCCESS(Status))
2082 {
2083 goto Cleanup;
2084 }
2085 FOReferenced = TRUE;
2086
2087 /* Get file name */
2088 FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION));
2089 if (!FileNameInfo)
2090 {
2092 goto Cleanup;
2093 }
2094
2095 Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2096 sizeof(FILE_NAME_INFORMATION),
2099 {
2100 /* Now we have real length, use it */
2101 Length = FileNameInfo->FileNameLength;
2102 FreePool(FileNameInfo);
2103
2104 FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + Length);
2105 if (!FileNameInfo)
2106 {
2108 goto Cleanup;
2109 }
2110
2111 /* Really query file name */
2112 Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2113 sizeof(FILE_NAME_INFORMATION) + Length,
2115 }
2116
2117 if (!NT_SUCCESS(Status))
2118 {
2119 goto Cleanup;
2120 }
2121
2122 /* Get symbolic name */
2123 ObjectNameInfoPtr = &ObjectNameInfo;
2124 SavedLength = sizeof(OBJECT_NAME_INFORMATION);
2125 Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, sizeof(OBJECT_NAME_INFORMATION), &Length);
2127 {
2128 /* Once again, with proper size, it works better */
2129 ObjectNameInfoPtr = AllocatePool(Length);
2130 if (!ObjectNameInfoPtr)
2131 {
2133 goto Cleanup;
2134 }
2135
2136 SavedLength = Length;
2137 Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, SavedLength, &Length);
2138 }
2139
2140 if (!NT_SUCCESS(Status))
2141 {
2142 goto Cleanup;
2143 }
2144
2145 /* Now, query the device name */
2146 Status = QueryDeviceInformation(&ObjectNameInfoPtr->Name, SourceDeviceName,
2147 NULL, NULL, NULL, NULL, NULL, NULL);
2148 if (!NT_SUCCESS(Status))
2149 {
2150 goto Cleanup;
2151 }
2152
2153 /* For target volume name, use input */
2154 TargetVolumeName->Length =
2155 TargetVolumeName->MaximumLength = VolumeMountPoint->TargetVolumeNameLength;
2156 TargetVolumeName->Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset);
2157
2158 /* Query its device name */
2159 Status = QueryDeviceInformation(TargetVolumeName, &TargetDeviceName,
2160 NULL, NULL, NULL, NULL, NULL, NULL);
2161 if (!NT_SUCCESS(Status))
2162 {
2163 goto Cleanup;
2164 }
2165
2166 /* Return symbolic name */
2167 SourceSymbolicName->Length =
2168 SourceSymbolicName->MaximumLength = (USHORT)FileNameInfo->FileNameLength;
2169 SourceSymbolicName->Buffer = (PWSTR)FileNameInfo;
2170 /* memmove allows memory overlap */
2171 RtlMoveMemory(SourceSymbolicName->Buffer, FileNameInfo->FileName, SourceSymbolicName->Length);
2172 FileNameInfo = NULL;
2173
2174 /* Notify the change */
2175 MountMgrNotify(DeviceExtension);
2176 MountMgrNotifyNameChange(DeviceExtension, &TargetDeviceName, TRUE);
2177
2178 /* If we are locked, sync databases if possible */
2179 if (NT_SUCCESS(LockStatus))
2180 {
2181 Status = FindDeviceInfo(DeviceExtension, SourceDeviceName, FALSE, &DeviceInformation);
2182 if (NT_SUCCESS(Status))
2183 {
2184 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
2185 }
2186 else
2187 {
2189 }
2190 }
2191
2192Cleanup:
2193 if (TargetDeviceName.Buffer)
2194 {
2195 FreePool(TargetDeviceName.Buffer);
2196 }
2197
2198 if (ObjectNameInfoPtr && ObjectNameInfoPtr != &ObjectNameInfo)
2199 {
2200 FreePool(ObjectNameInfoPtr);
2201 }
2202
2203 if (FileNameInfo)
2204 {
2205 FreePool(FileNameInfo);
2206 }
2207
2208 if (FOReferenced)
2209 {
2211 }
2212
2213 return Status;
2214}
2215
2216/*
2217 * @implemented
2218 */
2221 IN PIRP Irp,
2222 IN NTSTATUS LockStatus)
2223{
2224 LONG Offset;
2225 BOOLEAN Found;
2228 PMOUNTDEV_UNIQUE_ID UniqueId;
2229 PDATABASE_ENTRY DatabaseEntry;
2230 PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2231 PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2232 UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2233
2234 /* Initialize string */
2235 LinkTarget.Length = 0;
2238 if (LinkTarget.Buffer == NULL)
2239 {
2241 }
2242
2243 /* If the mount point was created, then, it changed!
2244 * Also use it to query some information
2245 */
2246 Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2247 /* Pending means DB are under synchronization, bail out */
2248 if (Status == STATUS_PENDING)
2249 {
2251 FreePool(SourceDeviceName.Buffer);
2252 FreePool(SourceSymbolicName.Buffer);
2253 return STATUS_SUCCESS;
2254 }
2255 else if (!NT_SUCCESS(Status))
2256 {
2258 return Status;
2259 }
2260
2261 /* Query the device information */
2262 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2263 if (!NT_SUCCESS(Status))
2264 {
2265 /* If it failed, first try to get volume name */
2266 Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2267 if (!NT_SUCCESS(Status))
2268 {
2269 /* Then, try to read the symlink */
2270 Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2271 if (!NT_SUCCESS(Status))
2272 {
2274 FreePool(SourceDeviceName.Buffer);
2275 FreePool(SourceSymbolicName.Buffer);
2276 return Status;
2277 }
2278 }
2279 else
2280 {
2282 }
2283
2284 FreePool(SourceDeviceName.Buffer);
2285
2286 SourceDeviceName.Length = LinkTarget.Length;
2287 SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2288 SourceDeviceName.Buffer = LinkTarget.Buffer;
2289
2290 /* Now that we have the correct source, reattempt to query information */
2291 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2292 if (!NT_SUCCESS(Status))
2293 {
2294 FreePool(SourceDeviceName.Buffer);
2295 FreePool(SourceSymbolicName.Buffer);
2296 return Status;
2297 }
2298 }
2299
2300 FreePool(SourceDeviceName.Buffer);
2301
2302 /* Get information about target device */
2303 Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2304 if (!NT_SUCCESS(Status))
2305 {
2306 FreePool(SourceSymbolicName.Buffer);
2307 return Status;
2308 }
2309
2310 /* Notify if not disabled */
2311 if (!TargetDeviceInformation->SkipNotifications)
2312 {
2313 PostOnlineNotification(DeviceExtension, &TargetDeviceInformation->SymbolicName);
2314 }
2315
2316 /* Open the remote database */
2317 RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2318 if (RemoteDatabase == 0)
2319 {
2320 FreePool(SourceSymbolicName.Buffer);
2322 }
2323
2324 /* Browse all the entries */
2325 Offset = 0;
2326 Found = FALSE;
2327 for (;;)
2328 {
2330 if (DatabaseEntry == NULL)
2331 {
2332 break;
2333 }
2334
2335 /* Try to find ourselves */
2336 DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2337 DbName.Length = DbName.MaximumLength;
2338 DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2339 if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2340 {
2341 /* Reference ourselves and update the entry */
2342 ++DatabaseEntry->EntryReferences;
2344 FreePool(DatabaseEntry);
2345 Found = TRUE;
2346 break;
2347 }
2348
2349 Offset += DatabaseEntry->EntrySize;
2350 FreePool(DatabaseEntry);
2351 }
2352
2353 /* We couldn't find ourselves, we'll have to add ourselves */
2354 if (!Found)
2355 {
2357 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2358
2359 /* Query the device unique ID */
2360 Status = QueryDeviceInformation(&TargetVolumeName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
2361 if (!NT_SUCCESS(Status))
2362 {
2363 FreePool(SourceSymbolicName.Buffer);
2365 return Status;
2366 }
2367
2368 /* Allocate a database entry */
2369 EntrySize = UniqueId->UniqueIdLength + TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2370 DatabaseEntry = AllocatePool(EntrySize);
2371 if (DatabaseEntry == NULL)
2372 {
2373 FreePool(UniqueId);
2374 FreePool(SourceSymbolicName.Buffer);
2377 }
2378
2379 /* Fill it in */
2380 DatabaseEntry->EntrySize = EntrySize;
2381 DatabaseEntry->EntryReferences = 1;
2382 DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
2383 DatabaseEntry->SymbolicNameLength = TargetVolumeName.Length;
2384 DatabaseEntry->UniqueIdOffset = TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2385 DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
2386 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + sizeof(DATABASE_ENTRY)), TargetVolumeName.Buffer, DatabaseEntry->SymbolicNameLength);
2387 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
2388
2389 /* And write it down */
2391 FreePool(DatabaseEntry);
2392 if (!NT_SUCCESS(Status))
2393 {
2394 FreePool(UniqueId);
2395 FreePool(SourceSymbolicName.Buffer);
2397 return Status;
2398 }
2399
2400 /* And now, allocate an Unique ID item */
2401 UniqueIdReplicate = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
2402 if (UniqueIdReplicate == NULL)
2403 {
2404 FreePool(UniqueId);
2405 FreePool(SourceSymbolicName.Buffer);
2407 return Status;
2408 }
2409
2410 /* To associate it with the device */
2411 UniqueIdReplicate->UniqueId = UniqueId;
2412 InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2413 }
2414
2415 /* We're done with the remote database */
2417
2418 /* Check we were find writing the entry */
2419 if (!NT_SUCCESS(Status))
2420 {
2421 FreePool(SourceSymbolicName.Buffer);
2422 return Status;
2423 }
2424
2425 /* This is the end, allocate an associated entry */
2426 AssociatedEntry = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY));
2427 if (AssociatedEntry == NULL)
2428 {
2429 FreePool(SourceSymbolicName.Buffer);
2431 }
2432
2433 /* Initialize its source name string */
2434 AssociatedEntry->String.Length = SourceSymbolicName.Length;
2435 AssociatedEntry->String.MaximumLength = AssociatedEntry->String.Length + sizeof(UNICODE_NULL);
2436 AssociatedEntry->String.Buffer = AllocatePool(AssociatedEntry->String.MaximumLength);
2437 if (AssociatedEntry->String.Buffer == NULL)
2438 {
2439 FreePool(AssociatedEntry);
2440 FreePool(SourceSymbolicName.Buffer);
2442 }
2443
2444 /* Copy data & insert in list */
2445 RtlCopyMemory(AssociatedEntry->String.Buffer, SourceSymbolicName.Buffer, SourceSymbolicName.Length);
2446 AssociatedEntry->String.Buffer[SourceSymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
2447 AssociatedEntry->DeviceInformation = DeviceInformation;
2448 InsertTailList(&TargetDeviceInformation->AssociatedDevicesHead, &AssociatedEntry->AssociatedDevicesEntry);
2449
2450 /* We're done! */
2451 FreePool(SourceSymbolicName.Buffer);
2452 return STATUS_SUCCESS;
2453}
2454
2455/*
2456 * @implemented
2457 */
2460 IN PIRP Irp,
2461 IN NTSTATUS LockStatus)
2462{
2463 LONG Offset;
2467 PDATABASE_ENTRY DatabaseEntry;
2468 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2469 PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2470 PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2471 UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2472
2473 /* Initialize string */
2474 LinkTarget.Length = 0;
2477 if (LinkTarget.Buffer == NULL)
2478 {
2480 }
2481
2482 /* If the mount point was deleted, then, it changed!
2483 * Also use it to query some information
2484 */
2485 Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2486 /* Pending means DB are under synchronization, bail out */
2487 if (Status == STATUS_PENDING)
2488 {
2490 FreePool(SourceDeviceName.Buffer);
2491 FreePool(SourceSymbolicName.Buffer);
2492 return STATUS_SUCCESS;
2493 }
2494 else if (!NT_SUCCESS(Status))
2495 {
2497 return Status;
2498 }
2499
2500 /* Query the device information */
2501 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2502 if (!NT_SUCCESS(Status))
2503 {
2504 /* If it failed, first try to get volume name */
2505 Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2506 if (!NT_SUCCESS(Status))
2507 {
2508 /* Then, try to read the symlink */
2509 Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2510 if (!NT_SUCCESS(Status))
2511 {
2513 FreePool(SourceDeviceName.Buffer);
2514 FreePool(SourceSymbolicName.Buffer);
2515 return Status;
2516 }
2517 }
2518 else
2519 {
2521 }
2522
2523 FreePool(SourceDeviceName.Buffer);
2524
2525 SourceDeviceName.Length = LinkTarget.Length;
2526 SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2527 SourceDeviceName.Buffer = LinkTarget.Buffer;
2528
2529 /* Now that we have the correct source, reattempt to query information */
2530 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2531 if (!NT_SUCCESS(Status))
2532 {
2533 FreePool(SourceDeviceName.Buffer);
2534 FreePool(SourceSymbolicName.Buffer);
2535 return Status;
2536 }
2537 }
2538
2539 FreePool(SourceDeviceName.Buffer);
2540
2541 /* Get information about target device */
2542 Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2543 if (!NT_SUCCESS(Status))
2544 {
2545 FreePool(SourceSymbolicName.Buffer);
2546 return Status;
2547 }
2548
2549 /* Open the remote database */
2550 RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2551 if (RemoteDatabase == 0)
2552 {
2553 FreePool(SourceSymbolicName.Buffer);
2555 }
2556
2557 /* Browse all the entries */
2558 Offset = 0;
2559 for (;;)
2560 {
2562 if (DatabaseEntry == NULL)
2563 {
2564 /* We didn't find ourselves, that's infortunate! */
2565 FreePool(SourceSymbolicName.Buffer);
2568 }
2569
2570 /* Try to find ourselves */
2571 DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2572 DbName.Length = DbName.MaximumLength;
2573 DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2574 if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2575 {
2576 break;
2577 }
2578
2579 Offset += DatabaseEntry->EntrySize;
2580 FreePool(DatabaseEntry);
2581 }
2582
2583 /* Dereference ourselves */
2584 DatabaseEntry->EntryReferences--;
2585 if (DatabaseEntry->EntryReferences == 0)
2586 {
2587 /* If we're still referenced, just update the entry */
2589 }
2590 else
2591 {
2592 /* Otherwise, delete the entry */
2594 if (!NT_SUCCESS(Status))
2595 {
2596 FreePool(DatabaseEntry);
2597 FreePool(SourceSymbolicName.Buffer);
2599 return Status;
2600 }
2601
2602 /* Also, delete our unique ID replicated record */
2603 for (Entry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
2604 Entry != &DeviceInformation->ReplicatedUniqueIdsListHead;
2605 Entry = Entry->Flink)
2606 {
2607 UniqueIdReplicate = CONTAINING_RECORD(Entry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
2608
2609 if (UniqueIdReplicate->UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
2610 RtlCompareMemory(UniqueIdReplicate->UniqueId->UniqueId,
2611 (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
2612 DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
2613 {
2614 break;
2615 }
2616 }
2617
2618 /* It has to exist! */
2619 if (Entry == &DeviceInformation->ReplicatedUniqueIdsListHead)
2620 {
2621 FreePool(DatabaseEntry);
2622 FreePool(SourceSymbolicName.Buffer);
2624 return STATUS_UNSUCCESSFUL;
2625 }
2626
2627 /* Remove it and free it */
2628 RemoveEntryList(&UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2629 FreePool(UniqueIdReplicate->UniqueId);
2630 FreePool(UniqueIdReplicate);
2631 }
2632
2633 /* We're done with the remote database */
2634 FreePool(DatabaseEntry);
2636
2637 /* Check write operation succeed */
2638 if (!NT_SUCCESS(Status))
2639 {
2640 FreePool(SourceSymbolicName.Buffer);
2641 return Status;
2642 }
2643
2644 /* Try to find our associated device entry */
2645 for (Entry = TargetDeviceInformation->AssociatedDevicesHead.Flink;
2646 Entry != &TargetDeviceInformation->AssociatedDevicesHead;
2647 Entry = Entry->Flink)
2648 {
2649 AssociatedEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
2650
2651 /* If found, delete it */
2652 if (AssociatedEntry->DeviceInformation == DeviceInformation &&
2653 RtlEqualUnicodeString(&AssociatedEntry->String, &SourceSymbolicName, TRUE))
2654 {
2655 RemoveEntryList(&AssociatedEntry->AssociatedDevicesEntry);
2656 FreePool(AssociatedEntry->String.Buffer);
2657 FreePool(AssociatedEntry);
2658 break;
2659 }
2660 }
2661
2662 /* We're done! */
2663 FreePool(SourceSymbolicName.Buffer);
2664 return STATUS_SUCCESS;
2665}
2666
2667/*
2668 * @implemented
2669 */
2671NTAPI
2673 IN PIRP Irp)
2674{
2676 NTSTATUS Status, LockStatus;
2677 PDEVICE_EXTENSION DeviceExtension;
2678
2680 DeviceExtension = DeviceObject->DeviceExtension;
2681
2682 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2683
2684 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2685 {
2687 Status = MountMgrCreatePoint(DeviceExtension, Irp);
2688 break;
2689
2691 Status = MountMgrDeletePoints(DeviceExtension, Irp);
2692 break;
2693
2695 Status = MountMgrQueryPoints(DeviceExtension, Irp);
2696 break;
2697
2699 Status = MountMgrDeletePointsDbOnly(DeviceExtension, Irp);
2700 break;
2701
2703 Status = MountMgrNextDriveLetter(DeviceExtension, Irp);
2704 break;
2705
2707 // NOTE: On Win7+, this is handled during driver re-initialization.
2708 DeviceExtension->AutomaticDriveLetter = TRUE;
2709 MountMgrAssignDriveLetters(DeviceExtension);
2710 ReconcileAllDatabasesWithMaster(DeviceExtension);
2711 WaitForOnlinesToComplete(DeviceExtension);
2713 break;
2714
2716 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2717
2718 LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2719 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2720 Status = MountMgrVolumeMountPointCreated(DeviceExtension, Irp, LockStatus);
2721 if (NT_SUCCESS(LockStatus))
2722 {
2723 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2724 }
2725
2726 break;
2727
2729 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2730
2731 LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2732 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2733 Status = MountMgrVolumeMountPointDeleted(DeviceExtension, Irp, LockStatus);
2734 if (NT_SUCCESS(LockStatus))
2735 {
2736 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2737 }
2738
2739 break;
2740
2742 Status = MountMgrChangeNotify(DeviceExtension, Irp);
2743 break;
2744
2746 Status = MountMgrKeepLinksWhenOffline(DeviceExtension, Irp);
2747 break;
2748
2750 Status = MountMgrCheckUnprocessedVolumes(DeviceExtension, Irp);
2751 goto Complete;
2752
2754 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2755 Status = MountMgrVolumeArrivalNotification(DeviceExtension, Irp);
2756 goto Complete;
2757
2759 Status = MountMgrQueryDosVolumePath(DeviceExtension, Irp);
2760 break;
2761
2763 Status = MountMgrQueryDosVolumePaths(DeviceExtension, Irp);
2764 break;
2765
2767 Status = MountMgrScrubRegistry(DeviceExtension);
2768 break;
2769
2771 Status = MountMgrQueryAutoMount(DeviceExtension, Irp);
2772 break;
2773
2775 Status = MountMgrSetAutoMount(DeviceExtension, Irp);
2776 break;
2777
2778 default:
2780 }
2781
2782 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2783
2784 if (Status != STATUS_PENDING)
2785 {
2786 goto Complete;
2787 }
2788
2789 return Status;
2790
2791Complete:
2792 Irp->IoStatus.Status = Status;
2794
2795 return Status;
2796}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
@ Invalid
Definition: asmpp.cpp:30
LONG NTSTATUS
Definition: precomp.h:26
#define MAX(x, y)
Definition: rdesktop.h:175
#define CHAR(Char)
return Found
Definition: dirsup.c:1270
_In_ BOOLEAN Release
Definition: cdrom.h:920
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL NTAPI QueryDeviceInformation(_In_ PWCHAR DriveRoot, _Out_ PVOID DeviceInformation, _In_ ULONG BufferSize)
Retrieves disk device information.
Definition: query.c:79
static const WCHAR Cleanup[]
Definition: register.c:80
NTSTATUS CloseRemoteDatabase(IN HANDLE Database)
Definition: database.c:82
NTSTATUS DeleteRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:233
NTSTATUS WaitForRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:371
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1615
VOID NTAPI ReconcileThisDatabaseWithMasterWorker(IN PVOID Parameter)
Definition: database.c:560
VOID DeleteNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:2102
VOID ReleaseRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:391
PWSTR DatabasePath
Definition: database.c:31
NTSTATUS AddRemoteDatabaseEntry(IN HANDLE Database, IN PDATABASE_ENTRY Entry)
Definition: database.c:64
NTSTATUS WriteRemoteDatabaseEntry(IN HANDLE Database, IN LONG Offset, IN PDATABASE_ENTRY Entry)
Definition: database.c:200
VOID ReconcileAllDatabasesWithMaster(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:1661
HANDLE OpenRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN BOOLEAN MigrateDatabase)
Definition: database.c:1839
PDATABASE_ENTRY GetRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:125
UNICODE_STRING RemoteDatabase
Definition: database.c:34
NTSTATUS QueryVolumeName(IN HANDLE RootDirectory, IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation, IN PUNICODE_STRING FileName OPTIONAL, OUT PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING VolumeName)
Definition: database.c:1292
NTSTATUS MountMgrVolumeMountPointDeleted(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus)
Definition: device.c:2459
BOOLEAN IsFtVolume(IN PUNICODE_STRING SymbolicName)
Definition: device.c:331
NTSTATUS MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1677
NTSTATUS MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1633
NTSTATUS MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1822
NTSTATUS MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1588
#define MAX_DEVICES
Definition: device.c:28
NTSTATUS MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus)
Definition: device.c:2220
NTSTATUS MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName)
Definition: device.c:708
NTSTATUS MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:221
NTSTATUS MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1438
NTSTATUS NTAPI ScrubRegistryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: device.c:162
NTSTATUS MountMgrChangeNotify(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:37
NTSTATUS MountMgrQueryVolumePaths(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation, IN PLIST_ENTRY DeviceInfoList, OUT PMOUNTMGR_VOLUME_PATHS *VolumePaths, OUT PDEVICE_INFORMATION *FailedDevice)
Definition: device.c:1148
NTSTATUS NTAPI MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: device.c:668
NTSTATUS MountMgrQueryAutoMount(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:136
NTSTATUS MountMgrValidateBackPointer(IN PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry, IN PDEVICE_INFORMATION DeviceInformation, OUT PBOOLEAN Invalid)
Definition: device.c:1040
NTSTATUS MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1923
NTSTATUS MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:288
NTSTATUS MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:621
VOID MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:737
NTSTATUS MountmgrWriteNoAutoMount(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:87
VOID ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:381
NTSTATUS MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus, OUT PUNICODE_STRING SourceDeviceName, OUT PUNICODE_STRING SourceSymbolicName, OUT PUNICODE_STRING TargetVolumeName)
Definition: device.c:1990
NTSTATUS MountMgrCreatePoint(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:249
NTSTATUS MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:814
NTSTATUS MountMgrSetAutoMount(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:103
NTSTATUS MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo)
Definition: device.c:435
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
@ FileNameInformation
Definition: from_kernel.h:70
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
@ FileFsDeviceInformation
Definition: from_kernel.h:222
pRequest Complete(RequestStatus)
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR)
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
IoMarkIrpPending(Irp)
IoSetCancelRoutine(Irp, CancelRoutine)
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:145
NTSTATUS MountMgrQuerySymbolicLink(IN PUNICODE_STRING SymbolicName, IN OUT PUNICODE_STRING LinkTarget)
Definition: symlink.c:849
DRIVER_DISPATCH MountMgrDeviceControl
Definition: mntmgr.h:344
UNICODE_STRING DeviceFloppy
Definition: symlink.c:43
struct _DATABASE_ENTRY DATABASE_ENTRY
NTSTATUS FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:561
#define COLON_POSITION
Definition: mntmgr.h:160
VOID MountMgrNotifyNameChange(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN BOOLEAN ValidateVolume)
Definition: notify.c:328
NTSTATUS MountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName)
Definition: point.c:35
VOID PostOnlineNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName)
Definition: notify.c:122
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:812
UNICODE_STRING DeviceCdRom
Definition: symlink.c:44
#define DRIVE_LETTER_LENGTH
Definition: mntmgr.h:161
NTSTATUS QueryPointsFromSymbolicLinkName(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN PIRP Irp)
Definition: point.c:463
#define LETTER_POSITION
Definition: mntmgr.h:159
VOID NTAPI MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1592
VOID MountMgrNotify(IN PDEVICE_EXTENSION DeviceExtension)
Definition: notify.c:288
VOID WaitForOnlinesToComplete(IN PDEVICE_EXTENSION DeviceExtension)
Definition: notify.c:174
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:626
VOID DeleteSymbolicLinkNameFromMemory(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLink, IN BOOLEAN MarkOffline)
Definition: symlink.c:754
NTSTATUS QueryPointsFromMemory(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL, IN PUNICODE_STRING SymbolicName OPTIONAL)
Definition: point.c:236
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:167
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define FreePool(P)
Definition: mntmgr.h:154
UNICODE_STRING DosDevices
Definition: symlink.c:42
VOID CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:269
BOOLEAN HasNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:354
NTSTATUS MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION Extension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN FromVolume)
Definition: mountmgr.c:855
#define ASSERT(a)
Definition: mode.c:44
#define for
Definition: utility.h:88
struct _MOUNTMGR_MOUNT_POINT * PMOUNTMGR_MOUNT_POINT
#define IOCTL_MOUNTMGR_DELETE_POINTS
Definition: imports.h:122
struct _MOUNTMGR_MOUNT_POINTS * PMOUNTMGR_MOUNT_POINTS
struct _MOUNTMGR_TARGET_NAME * PMOUNTMGR_TARGET_NAME
#define IOCTL_MOUNTMGR_CREATE_POINT
Definition: imports.h:116
#define IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
Definition: imports.h:128
struct _MOUNTMGR_CREATE_POINT_INPUT * PMOUNTMGR_CREATE_POINT_INPUT
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:81
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
Definition: mountmgr.h:147
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
Definition: mountmgr.h:149
struct _MOUNTMGR_CHANGE_NOTIFY_INFO * PMOUNTMGR_CHANGE_NOTIFY_INFO
#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
Definition: mountmgr.h:55
#define IOCTL_MOUNTMGR_QUERY_POINTS
Definition: mountmgr.h:49
@ Enabled
Definition: mountmgr.h:179
struct _MOUNTMGR_QUERY_AUTO_MOUNT * PMOUNTMGR_QUERY_AUTO_MOUNT
struct _MOUNTMGR_VOLUME_PATHS * PMOUNTMGR_VOLUME_PATHS
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED
Definition: mountmgr.h:59
struct _MOUNTMGR_VOLUME_MOUNT_POINT * PMOUNTMGR_VOLUME_MOUNT_POINT
#define IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES
Definition: mountmgr.h:65
struct _MOUNTMGR_DRIVE_LETTER_INFORMATION * PMOUNTMGR_DRIVE_LETTER_INFORMATION
struct _MOUNTMGR_SET_AUTO_MOUNT * PMOUNTMGR_SET_AUTO_MOUNT
#define MOUNTMGR_IS_DRIVE_LETTER(s)
Definition: mountmgr.h:73
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
Definition: mountmgr.h:53
#define IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY
Definition: mountmgr.h:51
#define IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE
Definition: mountmgr.h:63
struct _MOUNTMGR_DRIVE_LETTER_TARGET * PMOUNTMGR_DRIVE_LETTER_TARGET
#define IOCTL_MOUNTMGR_SCRUB_REGISTRY
Definition: mountmgr.h:170
#define IOCTL_MOUNTMGR_CHANGE_NOTIFY
Definition: mountmgr.h:61
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED
Definition: mountmgr.h:57
#define IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT
Definition: mountmgr.h:172
#define IOCTL_MOUNTMGR_SET_AUTO_MOUNT
Definition: mountmgr.h:174
struct _MOUNTMGR_CHANGE_NOTIFY_INFO MOUNTMGR_CHANGE_NOTIFY_INFO
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4677
#define KernelMode
Definition: asm.h:38
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4202
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4203
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_REMOTE_DEVICE
Definition: nt_native.h:811
#define SYNCHRONIZE
Definition: nt_native.h:61
#define REG_BINARY
Definition: nt_native.h:1496
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h:315
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSYSAPI NTSTATUS NTAPI ZwFsControlFile(IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize)
NTSYSAPI NTSTATUS NTAPI ZwQueryVolumeInformationFile(IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass)
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
VOID NTAPI PsSetThreadHardErrorsAreDisabled(IN PETHREAD Thread, IN BOOLEAN HardErrorsAreDisabled)
Definition: thread.c:898
BOOLEAN NTAPI PsGetThreadHardErrorsAreDisabled(IN PETHREAD Thread)
Definition: thread.c:695
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:746
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
#define FILE_DEVICE_VIRTUAL_DISK
Definition: winioctl.h:81
#define REG_DWORD
Definition: sdbapi.c:596
@ Removable
Definition: arc.h:81
@ Output
Definition: arc.h:85
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
base of all file and directory entries
Definition: entries.h:83
Definition: mntmgr.h:96
LIST_ENTRY AssociatedDevicesEntry
Definition: mntmgr.h:97
UNICODE_STRING String
Definition: mntmgr.h:99
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:98
Definition: mntmgr.h:86
USHORT UniqueIdOffset
Definition: mntmgr.h:91
USHORT SymbolicNameLength
Definition: mntmgr.h:90
USHORT UniqueIdLength
Definition: mntmgr.h:92
ULONG EntrySize
Definition: mntmgr.h:87
ULONG EntryReferences
Definition: mntmgr.h:88
USHORT SymbolicNameOffset
Definition: mntmgr.h:89
Definition: mntmgr.h:103
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:105
LIST_ENTRY DeviceInformationEntry
Definition: mntmgr.h:104
BOOLEAN LetterAssigned
Definition: mntmgr.h:55
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
BOOLEAN ManuallyRegistered
Definition: mntmgr.h:53
BOOLEAN KeepLinks
Definition: mntmgr.h:51
UCHAR SuggestedDriveLetter
Definition: mntmgr.h:52
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:49
BOOLEAN SkipNotifications
Definition: mntmgr.h:58
UNICODE_STRING DeviceName
Definition: mntmgr.h:50
LIST_ENTRY ReplicatedUniqueIdsListHead
Definition: mntmgr.h:46
LIST_ENTRY AssociatedDevicesHead
Definition: mntmgr.h:47
LIST_ENTRY SymbolicLinksListHead
Definition: mntmgr.h:45
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT UniqueIdLength
Definition: imports.h:136
UCHAR UniqueId[1]
Definition: imports.h:137
MOUNTMGR_MOUNT_POINT MountPoints[1]
Definition: imports.h:175
USHORT DeviceNameLength
Definition: imports.h:169
USHORT SymbolicLinkNameLength
Definition: imports.h:165
ULONG SymbolicLinkNameOffset
Definition: imports.h:164
MOUNTMGR_AUTO_MOUNT_STATE CurrentState
Definition: mountmgr.h:183
MOUNTMGR_AUTO_MOUNT_STATE NewState
Definition: mountmgr.h:187
UNICODE_STRING Name
Definition: nt_native.h:1270
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:118
PDEVICE_EXTENSION DeviceExtension
Definition: mntmgr.h:117
struct _REPARSE_DATA_BUFFER::@342::@344 SymbolicLinkReparseBuffer
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
unsigned short Length
Definition: sprintf.c:451
void * Buffer
Definition: sprintf.c:453
unsigned short MaximumLength
Definition: sprintf.c:452
USHORT MaximumLength
Definition: env_spec_w32.h:370
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:82
LIST_ENTRY ReplicatedUniqueIdsListEntry
Definition: mntmgr.h:81
uint16_t * PWSTR
Definition: typedefs.h:56
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define MAXSHORT
Definition: umtypes.h:114
static int Link(const char **args)
Definition: vfdcmd.c:2414
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_In_ WDFDEVICE AssociatedDevice
Definition: wdfinterrupt.h:173
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ UCHAR EntrySize
Definition: iofuncs.h:642
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
#define IO_NO_INCREMENT
Definition: iotypes.h:598
* PFILE_OBJECT
Definition: iotypes.h:1998
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE
Definition: iotypes.h:7214
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:415
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ PSTRING FullName
Definition: rtlfuncs.h:1665
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292