ReactOS 0.4.15-dev-7674-gc0b4db1
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/*
101 * @implemented
102 */
105 IN PIRP Irp)
106{
109
111
112 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_SET_AUTO_MOUNT))
113 {
114 Irp->IoStatus.Information = 0;
116 }
117
118 /* Only change if there's a real difference */
119 SetState = (PMOUNTMGR_SET_AUTO_MOUNT)Irp->AssociatedIrp.SystemBuffer;
120 if (SetState->NewState == !DeviceExtension->NoAutoMount)
121 {
122 Irp->IoStatus.Information = 0;
123 return STATUS_SUCCESS;
124 }
125
126 /* Set new state; ! on purpose */
127 DeviceExtension->NoAutoMount = !SetState->NewState;
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{
333 PIRP Irp;
339 PDEVICE_OBJECT DeviceObject, FileDeviceObject;
340
341 /* Get device object */
344 &FileObject,
345 &DeviceObject);
346 if (!NT_SUCCESS(Status))
347 {
348 return FALSE;
349 }
350
351 /* Get attached device */
352 FileDeviceObject = FileObject->DeviceObject;
353 DeviceObject = IoGetAttachedDeviceReference(FileDeviceObject);
354
355 /* FT volume can't be removable */
356 if (FileDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
357 {
360 return FALSE;
361 }
362
364
365 /* Get partition information */
369 NULL,
370 0,
372 sizeof(PartitionInfo),
373 FALSE,
374 &Event,
376 if (!Irp)
377 {
379 return FALSE;
380 }
381
383 if (Status == STATUS_PENDING)
384 {
387 }
388
390 if (!NT_SUCCESS(Status))
391 {
392 return FALSE;
393 }
394
395 /* Check if this is a FT volume */
396 return IsFTPartition(PartitionInfo.PartitionType);
397}
398
399/*
400 * @implemented
401 */
402VOID
404{
405 WCHAR NameBuffer[DRIVE_LETTER_LENGTH / sizeof(WCHAR)];
406 PLIST_ENTRY NextEntry;
408 PDEVICE_INFORMATION DeviceInformation;
409
410 /* No devices? Nothing to do! */
411 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
412 {
413 return;
414 }
415
416 /* For all the devices */
417 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
418 NextEntry != &(DeviceExtension->DeviceListHead);
419 NextEntry = NextEntry->Flink)
420 {
421 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
422
423 /* If no drive letter */
424 if (DeviceInformation->SuggestedDriveLetter == (UCHAR)-1)
425 {
426 /* Ensure it has no entry yet */
427 if (!HasDriveLetter(DeviceInformation) &&
428 !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
429 {
430 /* And create one */
431 CreateNoDriveLetterEntry(DeviceInformation->UniqueId);
432 }
433
434 DeviceInformation->SuggestedDriveLetter = 0;
435 }
436 /* Suggested letter & no entry */
437 else if (DeviceInformation->SuggestedDriveLetter &&
438 !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
439 {
440 /* Just create a mount point */
441 SymbolicName.Buffer = NameBuffer;
443 NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
444 NameBuffer[COLON_POSITION] = L':';
447
448 MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &(DeviceInformation->DeviceName));
449 }
450 }
451}
452
453/*
454 * @implemented
455 */
460{
462 UCHAR DriveLetter;
463 PLIST_ENTRY NextEntry;
464 PMOUNTDEV_UNIQUE_ID UniqueId;
465 BOOLEAN Removable, GptDriveLetter;
466 PDEVICE_INFORMATION DeviceInformation;
467 WCHAR NameBuffer[DRIVE_LETTER_LENGTH];
468 PSYMLINK_INFORMATION SymlinkInformation;
469 UNICODE_STRING TargetDeviceName, SymbolicName;
470
471 /* First, process suggested letters */
472 if (!DeviceExtension->ProcessedSuggestions)
473 {
474 ProcessSuggestedDriveLetters(DeviceExtension);
475 DeviceExtension->ProcessedSuggestions = TRUE;
476 }
477
478 /* Then, get information about the device */
479 Status = QueryDeviceInformation(DeviceName, &TargetDeviceName, NULL, &Removable, &GptDriveLetter, NULL, NULL, NULL);
480 if (!NT_SUCCESS(Status))
481 {
482 return Status;
483 }
484
485 /* Ensure we have such device */
486 NextEntry = DeviceExtension->DeviceListHead.Flink;
487 while (NextEntry != &(DeviceExtension->DeviceListHead))
488 {
489 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
490
491 if (RtlCompareUnicodeString(&(DeviceInformation->DeviceName), &TargetDeviceName, TRUE) == 0)
492 {
493 break;
494 }
495
496 NextEntry = NextEntry->Flink;
497 }
498
499 if (NextEntry == &(DeviceExtension->DeviceListHead))
500 {
501 FreePool(TargetDeviceName.Buffer);
503 }
504
505 /* Now, mark we have assigned a letter (assumption) */
506 DeviceInformation->LetterAssigned =
507 DriveLetterInfo->DriveLetterWasAssigned = TRUE;
508
509 /* Browse all the symlinks to check if there is already a drive letter */
510 NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
511 while (NextEntry != &(DeviceInformation->SymbolicLinksListHead))
512 {
513 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
514
515 /* If this is a drive letter and it is online, forget about new drive letter */
516 if (IsDriveLetter(&(SymlinkInformation->Name)) && SymlinkInformation->Online)
517 {
518 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
519 DriveLetterInfo->CurrentDriveLetter = (CHAR)SymlinkInformation->Name.Buffer[LETTER_POSITION];
520 break;
521 }
522
523 NextEntry = NextEntry->Flink;
524 }
525
526 /* If we didn't find a drive letter online
527 * ensure this is not a no drive entry
528 * by querying GPT attributes & database
529 */
530 if (NextEntry == &(DeviceInformation->SymbolicLinksListHead))
531 {
532 if (!GptDriveLetter || HasNoDriveLetterEntry(DeviceInformation->UniqueId))
533 {
534 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
535 DriveLetterInfo->CurrentDriveLetter = 0;
536
537 goto Release;
538 }
539 }
540
541 /* No, ensure that the device is not automounted nor removable */
542 if (!DeviceExtension->NoAutoMount && !Removable)
543 {
544 if (DriveLetterInfo->DriveLetterWasAssigned)
545 {
546 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
547 DriveLetterInfo->CurrentDriveLetter = 0;
548
549 goto Release;
550 }
551 }
552
553 if (!DriveLetterInfo->DriveLetterWasAssigned)
554 {
555 goto Release;
556 }
557
558 /* Now everything is fine, start processing */
559
560 if (RtlPrefixUnicodeString(&DeviceFloppy, &TargetDeviceName, TRUE))
561 {
562 /* If the device is a floppy, start with letter A */
563 DriveLetter = 'A';
564 }
565 else if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
566 {
567 /* If the device is a CD-ROM, start with letter D */
568 DriveLetter = 'D';
569 }
570 else
571 {
572 /* Finally, if it's a disk, use C */
573 DriveLetter = 'C';
574 }
575
576 /* We cannot set NO drive letter */
577 ASSERT(DeviceInformation->SuggestedDriveLetter != (UCHAR)-1);
578
579 /* If we don't have suggested letter but it's a FT volume, fail */
580 if (!DeviceInformation->SuggestedDriveLetter && IsFtVolume(&(DeviceInformation->DeviceName)))
581 {
582 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
583 DriveLetterInfo->CurrentDriveLetter = 0;
584
585 goto Release;
586 }
587
588 /* Prepare buffer */
590 NameBuffer[COLON_POSITION] = L':';
591 SymbolicName.Buffer = NameBuffer;
594
595 /* It's all prepared, create mount point */
596 if (DeviceInformation->SuggestedDriveLetter)
597 {
598 DriveLetterInfo->CurrentDriveLetter = DeviceInformation->SuggestedDriveLetter;
599 NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
600
601 Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
602 if (NT_SUCCESS(Status))
603 {
604 goto Release;
605 }
606 }
607
608 /* It failed with this letter... Try another one! */
609 for (DriveLetterInfo->CurrentDriveLetter = DriveLetter;
610 DriveLetterInfo->CurrentDriveLetter <= L'Z';
611 DriveLetterInfo->CurrentDriveLetter++)
612 {
613 NameBuffer[LETTER_POSITION] = DriveLetterInfo->CurrentDriveLetter;
614
615 Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
616 if (NT_SUCCESS(Status))
617 {
618 break;
619 }
620 }
621
622 /* We failed setting a letter */
623 if (DriveLetterInfo->CurrentDriveLetter > L'Z')
624 {
625 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
626 DriveLetterInfo->CurrentDriveLetter = 0;
627
628 /* Try at least to add a no drive letter entry */
629 Status = QueryDeviceInformation(&TargetDeviceName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
630 if (NT_SUCCESS(Status))
631 {
632 CreateNoDriveLetterEntry(UniqueId);
633 FreePool(UniqueId);
634 }
635 }
636
637Release:
638 FreePool(TargetDeviceName.Buffer);
639
640 return STATUS_SUCCESS;
641}
642
643
644/*
645 * @implemented
646 */
649 IN PIRP Irp)
650{
654 PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget;
655 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
656
658
659 /* Validate input */
660 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) ||
661 Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION))
662 {
664 }
665
666 DriveLetterTarget = (PMOUNTMGR_DRIVE_LETTER_TARGET)Irp->AssociatedIrp.SystemBuffer;
667 if (DriveLetterTarget->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
668 {
670 }
671
672 /* Call the worker */
673 DeviceName.Buffer = DriveLetterTarget->DeviceName;
674 DeviceName.Length =
675 DeviceName.MaximumLength = DriveLetterTarget->DeviceNameLength;
676
678 &DriveLetterInformation);
679 if (NT_SUCCESS(Status))
680 {
681 *(PMOUNTMGR_DRIVE_LETTER_INFORMATION)Irp->AssociatedIrp.SystemBuffer =
682 DriveLetterInformation;
683 Irp->IoStatus.Information = sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION);
684 }
685
686 return Status;
687}
688
689/*
690 * @implemented
691 */
693NTAPI
700{
701 UNICODE_STRING ValueString;
702 PUNICODE_STRING SystemVolumeName;
703
707
708 if (ValueType != REG_SZ)
709 {
710 return STATUS_SUCCESS;
711 }
712
713 RtlInitUnicodeString(&ValueString, ValueData);
714 SystemVolumeName = Context;
715
716 /* Return a string containing system volume name */
717 SystemVolumeName->Length = ValueString.Length;
718 SystemVolumeName->MaximumLength = ValueString.Length + sizeof(WCHAR);
719 SystemVolumeName->Buffer = AllocatePool(SystemVolumeName->MaximumLength);
720 if (SystemVolumeName->Buffer)
721 {
722 RtlCopyMemory(SystemVolumeName->Buffer, ValueData, ValueString.Length);
723 SystemVolumeName->Buffer[ValueString.Length / sizeof(WCHAR)] = UNICODE_NULL;
724 }
725
726 return STATUS_SUCCESS;
727
728}
729
730/*
731 * @implemented
732 */
735{
737
741 QueryTable[0].Name = L"SystemPartition";
742
743 SystemVolumeName->Buffer = NULL;
744
746 L"\\Registry\\Machine\\System\\Setup",
748 SystemVolumeName,
749 NULL);
750
751 if (SystemVolumeName->Buffer)
752 {
753 return STATUS_SUCCESS;
754 }
755
756 return STATUS_UNSUCCESSFUL;
757}
758
759/*
760 * @implemented
761 */
762VOID
764{
766 PLIST_ENTRY NextEntry;
767 UNICODE_STRING SystemVolumeName;
768 PDEVICE_INFORMATION DeviceInformation;
769 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
770
771 /* First, get system volume name */
772 Status = MountMgrQuerySystemVolumeName(&SystemVolumeName);
773
774 /* If there are no device, it's all done */
775 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
776 {
777 if (NT_SUCCESS(Status))
778 {
779 FreePool(SystemVolumeName.Buffer);
780 }
781
782 return;
783 }
784
785 /* Now, for all the devices... */
786 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
787 NextEntry != &(DeviceExtension->DeviceListHead);
788 NextEntry = NextEntry->Flink)
789 {
790 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
791
792 /* If the device doesn't have a letter assigned, do it! */
793 if (!DeviceInformation->LetterAssigned)
794 {
795 MountMgrNextDriveLetterWorker(DeviceExtension,
796 &(DeviceInformation->DeviceName),
797 &DriveLetterInformation);
798 }
799
800 /* If it was the system volume */
801 if (NT_SUCCESS(Status) && RtlEqualUnicodeString(&SystemVolumeName, &(DeviceInformation->DeviceName), TRUE))
802 {
803 /* Keep track of it */
804 DeviceExtension->DriveLetterData = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength +
805 sizeof(MOUNTDEV_UNIQUE_ID));
806 if (DeviceExtension->DriveLetterData)
807 {
808 RtlCopyMemory(DeviceExtension->DriveLetterData,
809 DeviceInformation->UniqueId,
810 DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
811 }
812
813 /* If it was not automount, ensure it gets mounted */
814 if (!DeviceExtension->NoAutoMount)
815 {
816 DeviceExtension->NoAutoMount = TRUE;
817
818 MountMgrNextDriveLetterWorker(DeviceExtension,
819 &(DeviceInformation->DeviceName),
820 &DriveLetterInformation);
821
822 DeviceExtension->NoAutoMount = FALSE;
823 }
824 }
825 }
826
827 if (NT_SUCCESS(Status))
828 {
829 FreePool(SystemVolumeName.Buffer);
830 }
831}
832
833/*
834 * @implemented
835 */
838 IN PIRP Irp)
839{
841 ULONG DevicesFound;
843 PLIST_ENTRY SymlinksEntry;
846 PWSTR DeviceString, OldBuffer;
847 USHORT DeviceLength, OldLength;
848 PDEVICE_INFORMATION DeviceInformation;
849 PSYMLINK_INFORMATION SymlinkInformation;
851
853
854 /* Validate input size */
855 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
856 {
858 }
859
860 /* Ensure we have received UNICODE_STRING */
861 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
862 if (Target->DeviceNameLength & 1)
863 {
865 }
866
867 /* Validate the entry structure size */
868 if ((FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceNameLength) + Target->DeviceNameLength) >
869 Stack->Parameters.DeviceIoControl.InputBufferLength)
870 {
872 }
873
874 /* Ensure we can at least return needed size */
875 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
876 {
878 }
879
880 /* Construct string for query */
881 SymbolicName.Length = Target->DeviceNameLength;
882 SymbolicName.MaximumLength = Target->DeviceNameLength;
883 SymbolicName.Buffer = Target->DeviceName;
884
885 /* Find device with our info */
886 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
887 if (!NT_SUCCESS(Status))
888 {
889 return Status;
890 }
891
892 DeviceLength = 0;
893 DeviceString = NULL;
894 DevicesFound = 0;
895
896 /* Try to find associated device info */
897 while (TRUE)
898 {
899 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
900 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
901 SymlinksEntry = SymlinksEntry->Flink)
902 {
903 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
904
905 /* Try to find with drive letter */
906 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
907 {
908 break;
909 }
910 }
911
912 /* We didn't find, break */
913 if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
914 {
915 return STATUS_NOT_FOUND;
916 }
917
918 /* It doesn't have associated device, go to fallback method */
919 if (IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
920 {
921 goto TryWithVolumeName;
922 }
923
924 /* Create a string with the information about the device */
925 AssociatedDevice = CONTAINING_RECORD(&(DeviceInformation->SymbolicLinksListHead), ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
926 OldLength = DeviceLength;
927 OldBuffer = DeviceString;
928 DeviceLength += AssociatedDevice->String.Length;
929 DeviceString = AllocatePool(DeviceLength);
930 if (!DeviceString)
931 {
932 if (OldBuffer)
933 {
934 FreePool(OldBuffer);
935 }
936
938 }
939
940 /* Store our info and previous if any */
941 RtlCopyMemory(DeviceString, AssociatedDevice->String.Buffer, AssociatedDevice->String.Length);
942 if (OldBuffer)
943 {
944 RtlCopyMemory(&DeviceString[AssociatedDevice->String.Length / sizeof(WCHAR)], OldBuffer, OldLength);
945 FreePool(OldBuffer);
946 }
947
948 /* Count and continue looking */
949 ++DevicesFound;
950 DeviceInformation = AssociatedDevice->DeviceInformation;
951
952 /* If too many devices, try another way */
953 if (DevicesFound > MAX_DEVICES) /* 1000 */
954 {
955 goto TryWithVolumeName;
956 }
957 }
958
959 /* Reallocate our string, so that we can prepend disk letter */
960 OldBuffer = DeviceString;
961 OldLength = DeviceLength;
962 DeviceLength += 2 * sizeof(WCHAR);
963 DeviceString = AllocatePool(DeviceLength);
964 if (!DeviceString)
965 {
966 if (OldBuffer)
967 {
968 FreePool(OldBuffer);
969 }
970
972 }
973
974 /* Get the letter */
975 DeviceString[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
976 DeviceString[1] = L':';
977
978 /* And copy the rest */
979 if (OldBuffer)
980 {
981 RtlCopyMemory(&DeviceString[2], OldBuffer, OldLength);
982 FreePool(OldBuffer);
983 }
984
985TryWithVolumeName:
986 /* If we didn't find anything, try differently */
987 if (DeviceLength < 2 * sizeof(WCHAR) || DeviceString[1] != L':')
988 {
989 if (DeviceString)
990 {
991 FreePool(DeviceString);
992 DeviceLength = 0;
993 }
994
995 /* Try to find a volume name matching */
996 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
997 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
998 SymlinksEntry = SymlinksEntry->Flink)
999 {
1000 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1001
1002 if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation->Name))
1003 {
1004 break;
1005 }
1006 }
1007
1008 /* If found copy */
1009 if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
1010 {
1011 DeviceLength = SymlinkInformation->Name.Length;
1012 DeviceString = AllocatePool(DeviceLength);
1013 if (!DeviceString)
1014 {
1016 }
1017
1018 RtlCopyMemory(DeviceString, SymlinkInformation->Name.Buffer, DeviceLength);
1019 /* Ensure we are in the right namespace; [1] can be ? */
1020 DeviceString[1] = L'\\';
1021 }
1022 }
1023
1024 /* If we found something */
1025 if (DeviceString)
1026 {
1027 /* At least, we will return our length */
1028 ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSzLength = DeviceLength;
1029 /* MOUNTMGR_VOLUME_PATHS is a string + a ULONG */
1030 Irp->IoStatus.Information = DeviceLength + sizeof(ULONG);
1031
1032 /* If we have enough room for copying the string */
1033 if (sizeof(ULONG) + DeviceLength <= Stack->Parameters.DeviceIoControl.OutputBufferLength)
1034 {
1035 /* Copy it */
1036 if (DeviceLength)
1037 {
1038 RtlCopyMemory(((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz, DeviceString, DeviceLength);
1039 }
1040
1041 /* And double zero at its end - this is needed in case of multiple paths which are separated by a single 0 */
1042 FreePool(DeviceString);
1043 ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR)] = 0;
1044 ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR) + 1] = 0;
1045
1046 return STATUS_SUCCESS;
1047 }
1048 else
1049 {
1050 /* Just return appropriate size and leave */
1051 FreePool(DeviceString);
1052 Irp->IoStatus.Information = sizeof(ULONG);
1054 }
1055 }
1056
1057 /* Fail */
1058 return STATUS_NOT_FOUND;
1059}
1060
1061/*
1062 * @implemented
1063 */
1066 IN PDEVICE_INFORMATION DeviceInformation,
1068{
1069 HANDLE Handle;
1071 PLIST_ENTRY SymlinksEntry;
1073 PREPARSE_DATA_BUFFER ReparseData;
1075 UNICODE_STRING FullName, SubstituteName;
1076 PSYMLINK_INFORMATION SymlinkInformation;
1077
1078 /* Initialize & allocate a string big enough to contain our complete mount point name */
1079 FullName.Length = 0;
1080 FullName.MaximumLength = AssociatedDeviceEntry->String.Length
1081 + AssociatedDeviceEntry->DeviceInformation->DeviceName.Length
1082 + sizeof(WCHAR)
1083 + sizeof(UNICODE_NULL);
1085 if (!FullName.Buffer)
1086 {
1088 }
1089
1090 /* Create the path */
1091 RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->DeviceInformation->DeviceName);
1092 FullName.Buffer[FullName.Length / sizeof(WCHAR)] = L'\\';
1093 RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->String);
1095
1096 /* Open it to query the reparse point */
1098 &FullName,
1100 NULL,
1101 NULL);
1108
1109 if (!NT_SUCCESS(Status))
1110 {
1111 *Invalid = TRUE;
1112 return STATUS_SUCCESS;
1113 }
1114
1115 /* Allocate a buffer big enough to read reparse data */
1117 if (ReparseData == NULL)
1118 {
1119 ZwClose(Handle);
1121 }
1122
1123 /* Query reparse data */
1125 NULL, NULL, NULL,
1128 NULL, 0,
1130 ZwClose(Handle);
1131
1132 if (!NT_SUCCESS(Status))
1133 {
1134 FreePool(ReparseData);
1135 *Invalid = TRUE;
1136 return STATUS_SUCCESS;
1137 }
1138
1139 /* Create a string with the substitute name */
1140 SubstituteName.Length = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
1141 SubstituteName.MaximumLength = SubstituteName.Length;
1142 SubstituteName.Buffer = (PWSTR)((ULONG_PTR)ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset);
1143
1144 /* If that's a volume name that matches our associated device, that's a success! */
1145 if (MOUNTMGR_IS_VOLUME_NAME(&SubstituteName))
1146 {
1147 if (SubstituteName.Length == 98 && SubstituteName.Buffer[1] == L'?')
1148 {
1149 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1150 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
1151 SymlinksEntry = SymlinksEntry->Flink)
1152 {
1153 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1154
1155 if (RtlEqualUnicodeString(&SubstituteName, &SymlinkInformation->Name, TRUE))
1156 {
1157 FreePool(ReparseData);
1158 return STATUS_SUCCESS;
1159 }
1160 }
1161 }
1162 }
1163
1164 FreePool(ReparseData);
1165 *Invalid = TRUE;
1166 return STATUS_SUCCESS;
1167}
1168
1169/*
1170 * @implemented
1171 */
1174 IN PDEVICE_INFORMATION DeviceInformation,
1175 IN PLIST_ENTRY DeviceInfoList,
1176 OUT PMOUNTMGR_VOLUME_PATHS * VolumePaths,
1177 OUT PDEVICE_INFORMATION *FailedDevice)
1178{
1179 ULONG Written;
1182 PSYMLINK_INFORMATION SymlinkInformation;
1183 PDEVICE_INFORMATION_ENTRY DeviceInfoEntry;
1184 PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry;
1185 PMOUNTMGR_VOLUME_PATHS * Paths = NULL, * CurrentPath;
1186 ULONG OutputPathLength, NumberOfPaths, ReturnedPaths;
1187
1188 /* We return at least null char */
1189 OutputPathLength = sizeof(UNICODE_NULL);
1190
1191 for (Entry = DeviceInformation->SymbolicLinksListHead.Flink;
1192 Entry != &(DeviceInformation->SymbolicLinksListHead);
1193 Entry = Entry->Flink)
1194 {
1195 SymlinkInformation = CONTAINING_RECORD(Entry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1196
1197 /* Try to find the drive letter (ie, DOS device) */
1198 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
1199 {
1200 /* We'll return the letter */
1201 OutputPathLength = 4 * sizeof(WCHAR);
1202 break;
1203 }
1204 }
1205
1206 /* We didn't find any */
1207 if (Entry == &(DeviceInformation->SymbolicLinksListHead))
1208 {
1209 SymlinkInformation = NULL;
1210 }
1211
1212 /* Do we have any device info to return? */
1213 for (Entry = DeviceInfoList->Flink; Entry != DeviceInfoList; Entry = Entry->Flink)
1214 {
1215 DeviceInfoEntry = CONTAINING_RECORD(Entry, DEVICE_INFORMATION_ENTRY, DeviceInformationEntry);
1216
1217 /* Matching current device */
1218 if (DeviceInfoEntry->DeviceInformation == DeviceInformation)
1219 {
1220 /* Allocate the output buffer */
1221 *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1222 if (*VolumePaths == NULL)
1223 {
1225 }
1226
1227 /* Set size */
1228 (*VolumePaths)->MultiSzLength = OutputPathLength;
1229 /* If we have a drive letter, return it */
1230 if (SymlinkInformation != NULL)
1231 {
1232 (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1233 (*VolumePaths)->MultiSz[1] = L':';
1234 (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1235 (*VolumePaths)->MultiSz[3] = UNICODE_NULL;
1236 }
1237 else
1238 {
1239 (*VolumePaths)->MultiSz[0] = UNICODE_NULL;
1240 }
1241
1242 return STATUS_SUCCESS;
1243 }
1244 }
1245
1246 /* Allocate a new device entry */
1247 DeviceInfoEntry = AllocatePool(sizeof(DEVICE_INFORMATION_ENTRY));
1248 if (DeviceInfoEntry == NULL)
1249 {
1251 }
1252
1253 /* Add it to the list */
1254 DeviceInfoEntry->DeviceInformation = DeviceInformation;
1255 InsertTailList(DeviceInfoList, &DeviceInfoEntry->DeviceInformationEntry);
1256
1257 NumberOfPaths = 0;
1258 /* Count the amount of devices we will have to handle */
1259 if (!IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
1260 {
1261 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1262 Entry != &DeviceInformation->AssociatedDevicesHead;
1263 Entry = Entry->Flink)
1264 {
1265 ++NumberOfPaths;
1266 }
1267
1268 ASSERT(NumberOfPaths != 0);
1269 /* And allocate a big enough buffer */
1270 Paths = AllocatePool(NumberOfPaths * sizeof(PMOUNTMGR_VOLUME_PATHS));
1271 if (Paths == NULL)
1272 {
1273 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1274 FreePool(DeviceInfoEntry);
1276 }
1277 }
1278
1279 /* Start the hot loop to gather all the paths and be able to compute total output length! */
1280 ReturnedPaths = 0;
1281 CurrentPath = Paths;
1282 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1283 Entry != &DeviceInformation->AssociatedDevicesHead;
1284 Entry = Entry->Flink)
1285 {
1286 USHORT InnerStrings;
1288
1289 AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1290
1291 /* Validate the fact its a mount point by query reparse data */
1292 Status = MountMgrValidateBackPointer(AssociatedDeviceEntry, DeviceInformation, &Invalid);
1293
1294 /* If we found an invalid device, that's a failure */
1295 if (Invalid)
1296 {
1297 *FailedDevice = AssociatedDeviceEntry->DeviceInformation;
1299 }
1300
1301 /* Check whether we failed, if so, bail out */
1302 if (!NT_SUCCESS(Status))
1303 {
1304 ULONG i;
1305
1306 for (i = 0; i < ReturnedPaths; ++i)
1307 {
1308 FreePool(Paths[i]);
1309 }
1310
1311 if (Paths != NULL)
1312 {
1313 FreePool(Paths);
1314 }
1315 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1316 FreePool(DeviceInfoEntry);
1317 return Status;
1318 }
1319
1320 /* Query associated paths (hello ourselves :-)) */
1321 Status = MountMgrQueryVolumePaths(DeviceExtension,
1322 AssociatedDeviceEntry->DeviceInformation,
1323 DeviceInfoList,
1324 CurrentPath,
1325 FailedDevice);
1326 if (!NT_SUCCESS(Status))
1327 {
1328 ULONG i;
1329
1330 for (i = 0; i < ReturnedPaths; ++i)
1331 {
1332 FreePool(Paths[i]);
1333 }
1334
1335 if (Paths != NULL)
1336 {
1337 FreePool(Paths);
1338 }
1339 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1340 FreePool(DeviceInfoEntry);
1341 return Status;
1342 }
1343
1344 /* Count the number of strings we have in the multi string buffer */
1345 InnerStrings = 0;
1346 if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1347 {
1348 ULONG i;
1349 PWSTR MultiSz = (*CurrentPath)->MultiSz;
1350
1351 for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR); ++i, ++MultiSz)
1352 {
1353 if (*MultiSz == UNICODE_NULL)
1354 {
1355 ++InnerStrings;
1356 }
1357 }
1358 }
1359
1360 /* We returned one more path (ie, one more allocated buffer) */
1361 ++ReturnedPaths;
1362 /* Move the next pointer to use in the array */
1363 ++CurrentPath;
1364 /* Multiply String.Length by the number of found paths, we always add it after a path */
1365 OutputPathLength += (*CurrentPath)->MultiSzLength + InnerStrings * AssociatedDeviceEntry->String.Length - sizeof(UNICODE_NULL);
1366 }
1367
1368 /* Allocate the output buffer */
1369 *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1370 if (*VolumePaths == NULL)
1371 {
1372 ULONG i;
1373
1374 for (i = 0; i < ReturnedPaths; ++i)
1375 {
1376 FreePool(Paths[i]);
1377 }
1378
1379 if (Paths != NULL)
1380 {
1381 FreePool(Paths);
1382 }
1383 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1384 FreePool(DeviceInfoEntry);
1386 }
1387
1388 Written = 0;
1389 /* If we had found a DOS letter, that's the first thing we return */
1390 (*VolumePaths)->MultiSzLength = OutputPathLength;
1391 if (SymlinkInformation != NULL)
1392 {
1393 (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1394 (*VolumePaths)->MultiSz[1] = L':';
1395 (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1396 Written = 3;
1397 }
1398
1399 /* Now, browse again all our paths to return them */
1400 CurrentPath = Paths;
1401 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1402 Entry != &DeviceInformation->AssociatedDevicesHead;
1403 Entry = Entry->Flink)
1404 {
1405 AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1406
1407 /* If we had a path... */
1408 if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1409 {
1410 ULONG i, Offset;
1411 PWSTR MultiSz;
1412
1413 /* This offset is used to "jump" into MultiSz, so, start with the string begin (ie, skip MultiSzLength) */
1414 Offset = sizeof(ULONG);
1415 /* Browse every single letter, and skip last UNICODE_NULL */
1416 for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR) - 1; ++i)
1417 {
1418 /* Get the letter */
1419 MultiSz = (PWSTR)((ULONG_PTR)(*CurrentPath) + Offset);
1420 /* If it was part of the path, just return it */
1421 if (*MultiSz != UNICODE_NULL)
1422 {
1423 (*VolumePaths)->MultiSz[Written] = *MultiSz;
1424 }
1425 else
1426 {
1427 /* Otherwise, as planed, return our whole associated device name */
1428 RtlCopyMemory(&(*VolumePaths)->MultiSz[Written],
1429 AssociatedDeviceEntry->String.Buffer,
1430 AssociatedDeviceEntry->String.Length);
1431 Written += AssociatedDeviceEntry->String.Length / sizeof(WCHAR);
1432 /* And don't forget to nullify */
1433 (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1434 }
1435
1436 /* We at least return a letter or a null char */
1437 ++Written;
1438 /* Move to the next letter */
1439 Offset += sizeof(WCHAR);
1440 }
1441 }
1442
1443 FreePool(*CurrentPath);
1444 ++CurrentPath;
1445 }
1446
1447 /* MultiSz: don't forget last null char */
1448 (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1449 /* Cleanup everything and return success! */
1450 if (Paths != NULL)
1451 {
1452 FreePool(Paths);
1453 }
1454 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1455 FreePool(DeviceInfoEntry);
1456 return STATUS_SUCCESS;
1457}
1458
1459/*
1460 * @implemented
1461 */
1464 IN PIRP Irp)
1465{
1468 LIST_ENTRY Devices;
1469 BOOLEAN NeedNotification;
1472 ULONG Attempts, OutputLength;
1475 RECONCILE_WORK_ITEM_CONTEXT ReconcileContext;
1476 PDEVICE_INFORMATION DeviceInformation, ListDeviceInfo, FailedDevice;
1477
1479
1480 /* Validate input size */
1481 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1482 {
1484 }
1485
1486 /* Ensure we have received UNICODE_STRING */
1487 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1488 if (Target->DeviceNameLength & 1)
1489 {
1491 }
1492
1493 /* Validate the entry structure size */
1494 if (Target->DeviceNameLength + FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1495 {
1497 }
1498
1499 /* Ensure we can at least return needed size */
1500 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
1501 {
1503 }
1504
1505 /* Construct string for query */
1506 SymbolicName.Length = Target->DeviceNameLength;
1507 SymbolicName.MaximumLength = Target->DeviceNameLength + sizeof(UNICODE_NULL);
1508 SymbolicName.Buffer = Target->DeviceName;
1509
1510 /* Find device with our info */
1511 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1512 if (!NT_SUCCESS(Status))
1513 {
1514 return Status;
1515 }
1516
1517 NeedNotification = FALSE;
1518 Attempts = 0;
1519 for (;;)
1520 {
1521 FailedDevice = NULL;
1522 InitializeListHead(&Devices);
1523
1524 /* Query paths */
1525 Status = MountMgrQueryVolumePaths(DeviceExtension, DeviceInformation, &Devices, &Paths, &FailedDevice);
1526 if (NT_SUCCESS(Status))
1527 {
1528 break;
1529 }
1530
1531 /* If it failed for generic reason (memory, whatever), bail out (ie, FailedDevice not set) */
1532 if (FailedDevice == NULL)
1533 {
1534 return Status;
1535 }
1536
1537 /* If PnP, let's notify in case of success */
1538 if (!DeviceInformation->ManuallyRegistered)
1539 {
1540 NeedNotification = TRUE;
1541 }
1542
1543 /* Reconcile database */
1544 ReconcileContext.DeviceExtension = DeviceExtension;
1545 ReconcileContext.DeviceInformation = FailedDevice;
1546 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1547 ReconcileThisDatabaseWithMasterWorker(&ReconcileContext);
1548 KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1549
1550 /* Look for our device, to check it's online */
1551 for (Entry = DeviceExtension->DeviceListHead.Flink;
1552 Entry != &DeviceExtension->DeviceListHead;
1553 Entry = Entry->Flink)
1554 {
1555 ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
1556 /* It's online, it's OK! */
1557 if (ListDeviceInfo == DeviceInformation)
1558 {
1559 break;
1560 }
1561 }
1562
1563 /* It's not online, it's not good */
1564 if (Entry == &DeviceExtension->DeviceListHead)
1565 {
1567 }
1568
1569 /* Increase attempts count */
1570 ++Attempts;
1571 /* Don't look forever and fail if we get out of attempts */
1572 if (Attempts >= 1000)
1573 {
1574 return Status;
1575 }
1576 }
1577
1578 /* We need to notify? Go ahead */
1579 if (NeedNotification)
1580 {
1581 MountMgrNotifyNameChange(DeviceExtension, &SymbolicName, FALSE);
1582 }
1583
1584 /* Get output buffer */
1585 Output = (PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer;
1586
1587 /* Set required size */
1588 Output->MultiSzLength = Paths->MultiSzLength;
1589
1590 /* Compute total length */
1591 OutputLength = Output->MultiSzLength + sizeof(ULONG);
1592
1593 /* If it cannot fit, just return need size and quit */
1594 if (OutputLength > Stack->Parameters.DeviceIoControl.OutputBufferLength)
1595 {
1596 Irp->IoStatus.Information = sizeof(ULONG);
1597 FreePool(Paths);
1599 }
1600
1601 /* Copy data and quit */
1602 Irp->IoStatus.Information = OutputLength;
1603 RtlCopyMemory(Output->MultiSz, Paths->MultiSz, Output->MultiSzLength);
1604 FreePool(Paths);
1605 return STATUS_SUCCESS;
1606}
1607
1608/*
1609 * @implemented
1610 */
1613 IN PIRP Irp)
1614{
1619 PDEVICE_INFORMATION DeviceInformation;
1620
1622
1623 /* Validate input */
1624 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1625 {
1627 }
1628
1629 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1630 if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1631 {
1633 }
1634
1636 SymbolicName.MaximumLength = Target->DeviceNameLength;
1637 SymbolicName.Buffer = Target->DeviceName;
1638
1639 /* Find the associated device */
1640 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1641 if (!NT_SUCCESS(Status))
1642 {
1643 return Status;
1644 }
1645
1646 /* Mark we want to keep links */
1647 DeviceInformation->KeepLinks = TRUE;
1648
1649 return STATUS_SUCCESS;
1650}
1651
1652/*
1653 * @implemented
1654 */
1657 IN PIRP Irp)
1658{
1660 BOOLEAN OldState;
1664
1666
1667 /* Validate input */
1668 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1669 {
1671 }
1672
1673 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1674 if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1675 {
1677 }
1678
1680 SymbolicName.MaximumLength = Target->DeviceNameLength;
1681 SymbolicName.Buffer = Target->DeviceName;
1682
1683 /* Disable hard errors */
1686
1687 /* Call real worker */
1689
1691
1692 return Status;
1693}
1694
1695/*
1696 * @implemented
1697 */
1700 IN PIRP Irp)
1701{
1704 PMOUNTDEV_UNIQUE_ID UniqueId;
1705 PMOUNTMGR_MOUNT_POINT MountPoint;
1707
1709
1710 /* Validate input... */
1711 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1712 {
1714 }
1715
1716 MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1717 if (!MountPoint->SymbolicLinkNameLength)
1718 {
1719 MountPoint->SymbolicLinkNameOffset = 0;
1720 }
1721
1722 if (!MountPoint->UniqueIdLength)
1723 {
1724 MountPoint->UniqueIdOffset = 0;
1725 }
1726
1727 if (!MountPoint->DeviceNameLength)
1728 {
1729 MountPoint->DeviceNameOffset = 0;
1730 }
1731
1732 /* Addresses can't be odd */
1733 if ((MountPoint->SymbolicLinkNameOffset & 1) ||
1734 (MountPoint->SymbolicLinkNameLength & 1))
1735 {
1737 }
1738
1739 if ((MountPoint->UniqueIdOffset & 1) ||
1740 (MountPoint->UniqueIdLength & 1))
1741 {
1743 }
1744
1745 if ((MountPoint->DeviceNameOffset & 1) ||
1746 (MountPoint->DeviceNameLength & 1))
1747 {
1749 }
1750
1751 /* We can't go beyond */
1752 if (((ULONG)MountPoint->SymbolicLinkNameLength + MountPoint->UniqueIdLength +
1753 MountPoint->DeviceNameLength) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1754 {
1756 }
1757
1758 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_MOUNT_POINTS))
1759 {
1761 }
1762
1763 /* If caller provided a Symlink, use it */
1764 if (MountPoint->SymbolicLinkNameLength != 0)
1765 {
1766 if (MountPoint->SymbolicLinkNameLength > MAXSHORT)
1767 {
1769 }
1770
1774 if (!SymbolicName.Buffer)
1775 {
1777 }
1778
1780 (PWSTR)((ULONG_PTR)MountPoint + MountPoint->SymbolicLinkNameOffset),
1783
1784 /* Query links using it */
1787 }
1788 /* If user provided an unique ID */
1789 else if (MountPoint->UniqueIdLength != 0)
1790 {
1791 UniqueId = AllocatePool(MountPoint->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1792 if (!UniqueId)
1793 {
1795 }
1796
1797 UniqueId->UniqueIdLength = MountPoint->UniqueIdLength;
1798 RtlCopyMemory(UniqueId->UniqueId,
1799 (PVOID)((ULONG_PTR)MountPoint + MountPoint->UniqueIdOffset),
1800 MountPoint->UniqueIdLength);
1801
1802 /* Query links using it */
1803 Status = QueryPointsFromMemory(DeviceExtension, Irp, UniqueId, NULL);
1804 FreePool(UniqueId);
1805 }
1806 /* If caller provided a device name */
1807 else if (MountPoint->DeviceNameLength != 0)
1808 {
1809 if (MountPoint->DeviceNameLength > MAXSHORT)
1810 {
1812 }
1813
1814 DeviceName.Length = MountPoint->DeviceNameLength;
1815 DeviceName.MaximumLength = MountPoint->DeviceNameLength + sizeof(WCHAR);
1816 DeviceName.Buffer = AllocatePool(DeviceName.MaximumLength);
1817 if (!DeviceName.Buffer)
1818 {
1820 }
1821
1823 (PWSTR)((ULONG_PTR)MountPoint + MountPoint->DeviceNameOffset),
1824 DeviceName.Length);
1825 DeviceName.Buffer[DeviceName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1826
1827 /* Query links using it */
1828 Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, &DeviceName);
1829 FreePool(DeviceName.Buffer);
1830 }
1831 else
1832 {
1833 /* Otherwise, query all links */
1834 Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, NULL);
1835 }
1836
1837 return Status;
1838}
1839
1840/*
1841 * @implemented
1842 */
1845 IN PIRP Irp)
1846{
1847 ULONG Link;
1849 BOOLEAN CreateNoDrive;
1851 PMOUNTDEV_UNIQUE_ID UniqueId;
1852 PMOUNTMGR_MOUNT_POINT MountPoint;
1853 PMOUNTMGR_MOUNT_POINTS MountPoints;
1855
1857
1858 /* Validate input */
1859 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1860 {
1862 }
1863
1864 /* Query points */
1865 MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1866 CreateNoDrive = (MountPoint->SymbolicLinkNameOffset && MountPoint->SymbolicLinkNameLength);
1867
1868 Status = MountMgrQueryPoints(DeviceExtension, Irp);
1869 if (!NT_SUCCESS(Status))
1870 {
1871 return Status;
1872 }
1873
1874 /* For all the points matching the request */
1875 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1876 for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1877 {
1881 if (!SymbolicName.Buffer)
1882 {
1884 }
1885
1887 (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1890
1891 /* Create a no drive entry for the drive letters */
1892 if (CreateNoDrive && IsDriveLetter(&SymbolicName))
1893 {
1894 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1895 if (UniqueId)
1896 {
1897 UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1898 RtlCopyMemory(UniqueId->UniqueId,
1899 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1900 MountPoints->MountPoints[Link].UniqueIdLength);
1901
1902 CreateNoDriveLetterEntry(UniqueId);
1903 FreePool(UniqueId);
1904 }
1905 }
1906
1907 /* If there are no link any more, and no need to create a no drive entry */
1908 if (Link == 0 && !CreateNoDrive)
1909 {
1910 /* Then, delete everything */
1911 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength);
1912 if (UniqueId)
1913 {
1914 RtlCopyMemory(UniqueId,
1915 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1916 MountPoints->MountPoints[Link].UniqueIdLength);
1917
1918 DeleteNoDriveLetterEntry(UniqueId);
1919 FreePool(UniqueId);
1920 }
1921 }
1922
1923 /* Delete all the information about the mount point */
1928
1929 /* Notify the change */
1930 DeviceName.Length = DeviceName.MaximumLength =
1931 MountPoints->MountPoints[Link].DeviceNameLength;
1932 DeviceName.Buffer = (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].DeviceNameOffset);
1933 MountMgrNotifyNameChange(DeviceExtension, &DeviceName, TRUE);
1934 }
1935
1936 MountMgrNotify(DeviceExtension);
1937
1938 return Status;
1939}
1940
1941/*
1942 * @implemented
1943 */
1946 IN PIRP Irp)
1947{
1948 ULONG Link;
1951 PMOUNTDEV_UNIQUE_ID UniqueId;
1952 PMOUNTMGR_MOUNT_POINTS MountPoints;
1953
1954 /* Query points */
1955 Status = MountMgrQueryPoints(DeviceExtension, Irp);
1956 if (!NT_SUCCESS(Status))
1957 {
1958 return Status;
1959 }
1960
1961 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1962 if (MountPoints->NumberOfMountPoints == 0)
1963 {
1964 return Status;
1965 }
1966
1967 /* For all the mount points */
1968 for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1969 {
1973 if (!SymbolicName.Buffer)
1974 {
1976 }
1977
1979 (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1982
1983 /* If the only mount point is a drive letter, then create a no letter drive entry */
1984 if (MountPoints->NumberOfMountPoints == 1 && IsDriveLetter(&SymbolicName))
1985 {
1986 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1987 if (UniqueId)
1988 {
1989 UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1990 RtlCopyMemory(UniqueId->UniqueId,
1991 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1992 MountPoints->MountPoints[Link].UniqueIdLength);
1993
1994 CreateNoDriveLetterEntry(UniqueId);
1995 FreePool(UniqueId);
1996 }
1997 }
1998
1999 /* Simply delete mount point from DB */
2003 }
2004
2005 return Status;
2006}
2007
2008/*
2009 * @implemented
2010 */
2013 IN PIRP Irp,
2014 IN NTSTATUS LockStatus,
2015 OUT PUNICODE_STRING SourceDeviceName,
2016 OUT PUNICODE_STRING SourceSymbolicName,
2017 OUT PUNICODE_STRING TargetVolumeName)
2018{
2019 HANDLE Handle;
2023 ULONG Length, SavedLength;
2024 BOOLEAN FOReferenced = FALSE;
2027 PDEVICE_INFORMATION DeviceInformation;
2028 OBJECT_NAME_INFORMATION ObjectNameInfo;
2029 FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
2030 PFILE_NAME_INFORMATION FileNameInfo = NULL;
2031 PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint;
2032 POBJECT_NAME_INFORMATION ObjectNameInfoPtr = NULL;
2033 UNICODE_STRING SourceVolumeName, TargetDeviceName;
2034
2036
2037 /* Validate input */
2038 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_VOLUME_MOUNT_POINT))
2039 {
2041 }
2042
2043 VolumeMountPoint = (PMOUNTMGR_VOLUME_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
2044
2045 if (((ULONG)VolumeMountPoint->SourceVolumeNameLength + VolumeMountPoint->TargetVolumeNameLength) <
2046 Stack->Parameters.DeviceIoControl.InputBufferLength)
2047 {
2049 }
2050
2051 /* Get source volume name */
2052 SourceVolumeName.Length =
2053 SourceVolumeName.MaximumLength = VolumeMountPoint->SourceVolumeNameLength;
2054 SourceVolumeName.Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset);
2055
2057 &SourceVolumeName,
2059 NULL,
2060 NULL);
2061
2062 /* Open it */
2069 if (!NT_SUCCESS(Status))
2070 {
2071 return Status;
2072 }
2073
2074 TargetDeviceName.Buffer = NULL;
2075
2076 /* Query its attributes */
2079 &FsDeviceInfo,
2080 sizeof(FsDeviceInfo),
2082 if (!NT_SUCCESS(Status))
2083 {
2084 goto Cleanup;
2085 }
2086
2087 if (FsDeviceInfo.DeviceType != FILE_DEVICE_DISK && FsDeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK)
2088 {
2089 goto Cleanup;
2090 }
2091
2093 {
2094 goto Cleanup;
2095 }
2096
2097 /* Reference it */
2099 if (!NT_SUCCESS(Status))
2100 {
2101 goto Cleanup;
2102 }
2103 FOReferenced = TRUE;
2104
2105 /* Get file name */
2106 FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION));
2107 if (!FileNameInfo)
2108 {
2110 goto Cleanup;
2111 }
2112
2113 Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2114 sizeof(FILE_NAME_INFORMATION),
2117 {
2118 /* Now we have real length, use it */
2119 Length = FileNameInfo->FileNameLength;
2120 FreePool(FileNameInfo);
2121
2122 FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + Length);
2123 if (!FileNameInfo)
2124 {
2126 goto Cleanup;
2127 }
2128
2129 /* Really query file name */
2130 Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2131 sizeof(FILE_NAME_INFORMATION) + Length,
2133 }
2134
2135 if (!NT_SUCCESS(Status))
2136 {
2137 goto Cleanup;
2138 }
2139
2140 /* Get symbolic name */
2141 ObjectNameInfoPtr = &ObjectNameInfo;
2142 SavedLength = sizeof(OBJECT_NAME_INFORMATION);
2143 Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, sizeof(OBJECT_NAME_INFORMATION), &Length);
2145 {
2146 /* Once again, with proper size, it works better */
2147 ObjectNameInfoPtr = AllocatePool(Length);
2148 if (!ObjectNameInfoPtr)
2149 {
2151 goto Cleanup;
2152 }
2153
2154 SavedLength = Length;
2155 Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, SavedLength, &Length);
2156 }
2157
2158 if (!NT_SUCCESS(Status))
2159 {
2160 goto Cleanup;
2161 }
2162
2163 /* Now, query the device name */
2164 Status = QueryDeviceInformation(&ObjectNameInfoPtr->Name, SourceDeviceName,
2165 NULL, NULL, NULL, NULL, NULL, NULL);
2166 if (!NT_SUCCESS(Status))
2167 {
2168 goto Cleanup;
2169 }
2170
2171 /* For target volume name, use input */
2172 TargetVolumeName->Length =
2173 TargetVolumeName->MaximumLength = VolumeMountPoint->TargetVolumeNameLength;
2174 TargetVolumeName->Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset);
2175
2176 /* Query its device name */
2177 Status = QueryDeviceInformation(TargetVolumeName, &TargetDeviceName,
2178 NULL, NULL, NULL, NULL, NULL, NULL);
2179 if (!NT_SUCCESS(Status))
2180 {
2181 goto Cleanup;
2182 }
2183
2184 /* Return symbolic name */
2185 SourceSymbolicName->Length =
2186 SourceSymbolicName->MaximumLength = (USHORT)FileNameInfo->FileNameLength;
2187 SourceSymbolicName->Buffer = (PWSTR)FileNameInfo;
2188 /* memmove allows memory overlap */
2189 RtlMoveMemory(SourceSymbolicName->Buffer, FileNameInfo->FileName, SourceSymbolicName->Length);
2190 FileNameInfo = NULL;
2191
2192 /* Notify the change */
2193 MountMgrNotify(DeviceExtension);
2194 MountMgrNotifyNameChange(DeviceExtension, &TargetDeviceName, TRUE);
2195
2196 /* If we are locked, sync databases if possible */
2197 if (NT_SUCCESS(LockStatus))
2198 {
2199 Status = FindDeviceInfo(DeviceExtension, SourceDeviceName, FALSE, &DeviceInformation);
2200 if (NT_SUCCESS(Status))
2201 {
2202 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
2203 }
2204 else
2205 {
2207 }
2208 }
2209
2210Cleanup:
2211 if (TargetDeviceName.Buffer)
2212 {
2213 FreePool(TargetDeviceName.Buffer);
2214 }
2215
2216 if (ObjectNameInfoPtr && ObjectNameInfoPtr != &ObjectNameInfo)
2217 {
2218 FreePool(ObjectNameInfoPtr);
2219 }
2220
2221 if (FileNameInfo)
2222 {
2223 FreePool(FileNameInfo);
2224 }
2225
2226 if (FOReferenced)
2227 {
2229 }
2230
2231 return Status;
2232}
2233
2234/*
2235 * @implemented
2236 */
2239 IN PIRP Irp,
2240 IN NTSTATUS LockStatus)
2241{
2242 LONG Offset;
2243 BOOLEAN Found;
2246 PMOUNTDEV_UNIQUE_ID UniqueId;
2247 PDATABASE_ENTRY DatabaseEntry;
2248 PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2249 PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2250 UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2251
2252 /* Initialize string */
2253 LinkTarget.Length = 0;
2256 if (LinkTarget.Buffer == NULL)
2257 {
2259 }
2260
2261 /* If the mount point was created, then, it changed!
2262 * Also use it to query some information
2263 */
2264 Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2265 /* Pending means DB are under synchronization, bail out */
2266 if (Status == STATUS_PENDING)
2267 {
2269 FreePool(SourceDeviceName.Buffer);
2270 FreePool(SourceSymbolicName.Buffer);
2271 return STATUS_SUCCESS;
2272 }
2273 else if (!NT_SUCCESS(Status))
2274 {
2276 return Status;
2277 }
2278
2279 /* Query the device information */
2280 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2281 if (!NT_SUCCESS(Status))
2282 {
2283 /* If it failed, first try to get volume name */
2284 Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2285 if (!NT_SUCCESS(Status))
2286 {
2287 /* Then, try to read the symlink */
2288 Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2289 if (!NT_SUCCESS(Status))
2290 {
2292 FreePool(SourceDeviceName.Buffer);
2293 FreePool(SourceSymbolicName.Buffer);
2294 return Status;
2295 }
2296 }
2297 else
2298 {
2300 }
2301
2302 FreePool(SourceDeviceName.Buffer);
2303
2304 SourceDeviceName.Length = LinkTarget.Length;
2305 SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2306 SourceDeviceName.Buffer = LinkTarget.Buffer;
2307
2308 /* Now that we have the correct source, reattempt to query information */
2309 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2310 if (!NT_SUCCESS(Status))
2311 {
2312 FreePool(SourceDeviceName.Buffer);
2313 FreePool(SourceSymbolicName.Buffer);
2314 return Status;
2315 }
2316 }
2317
2318 FreePool(SourceDeviceName.Buffer);
2319
2320 /* Get information about target device */
2321 Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2322 if (!NT_SUCCESS(Status))
2323 {
2324 FreePool(SourceSymbolicName.Buffer);
2325 return Status;
2326 }
2327
2328 /* Notify if not disabled */
2329 if (!TargetDeviceInformation->SkipNotifications)
2330 {
2331 PostOnlineNotification(DeviceExtension, &TargetDeviceInformation->SymbolicName);
2332 }
2333
2334 /* Open the remote database */
2335 RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2336 if (RemoteDatabase == 0)
2337 {
2338 FreePool(SourceSymbolicName.Buffer);
2340 }
2341
2342 /* Browse all the entries */
2343 Offset = 0;
2344 Found = FALSE;
2345 for (;;)
2346 {
2348 if (DatabaseEntry == NULL)
2349 {
2350 break;
2351 }
2352
2353 /* Try to find ourselves */
2354 DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2355 DbName.Length = DbName.MaximumLength;
2356 DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2357 if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2358 {
2359 /* Reference ourselves and update the entry */
2360 ++DatabaseEntry->EntryReferences;
2362 FreePool(DatabaseEntry);
2363 Found = TRUE;
2364 break;
2365 }
2366
2367 Offset += DatabaseEntry->EntrySize;
2368 FreePool(DatabaseEntry);
2369 }
2370
2371 /* We couldn't find ourselves, we'll have to add ourselves */
2372 if (!Found)
2373 {
2375 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2376
2377 /* Query the device unique ID */
2378 Status = QueryDeviceInformation(&TargetVolumeName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
2379 if (!NT_SUCCESS(Status))
2380 {
2381 FreePool(SourceSymbolicName.Buffer);
2383 return Status;
2384 }
2385
2386 /* Allocate a database entry */
2387 EntrySize = UniqueId->UniqueIdLength + TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2388 DatabaseEntry = AllocatePool(EntrySize);
2389 if (DatabaseEntry == NULL)
2390 {
2391 FreePool(UniqueId);
2392 FreePool(SourceSymbolicName.Buffer);
2395 }
2396
2397 /* Fill it in */
2398 DatabaseEntry->EntrySize = EntrySize;
2399 DatabaseEntry->EntryReferences = 1;
2400 DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
2401 DatabaseEntry->SymbolicNameLength = TargetVolumeName.Length;
2402 DatabaseEntry->UniqueIdOffset = TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2403 DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
2404 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + sizeof(DATABASE_ENTRY)), TargetVolumeName.Buffer, DatabaseEntry->SymbolicNameLength);
2405 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
2406
2407 /* And write it down */
2409 FreePool(DatabaseEntry);
2410 if (!NT_SUCCESS(Status))
2411 {
2412 FreePool(UniqueId);
2413 FreePool(SourceSymbolicName.Buffer);
2415 return Status;
2416 }
2417
2418 /* And now, allocate an Unique ID item */
2419 UniqueIdReplicate = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
2420 if (UniqueIdReplicate == NULL)
2421 {
2422 FreePool(UniqueId);
2423 FreePool(SourceSymbolicName.Buffer);
2425 return Status;
2426 }
2427
2428 /* To associate it with the device */
2429 UniqueIdReplicate->UniqueId = UniqueId;
2430 InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2431 }
2432
2433 /* We're done with the remote database */
2435
2436 /* Check we were find writing the entry */
2437 if (!NT_SUCCESS(Status))
2438 {
2439 FreePool(SourceSymbolicName.Buffer);
2440 return Status;
2441 }
2442
2443 /* This is the end, allocate an associated entry */
2444 AssociatedEntry = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY));
2445 if (AssociatedEntry == NULL)
2446 {
2447 FreePool(SourceSymbolicName.Buffer);
2449 }
2450
2451 /* Initialize its source name string */
2452 AssociatedEntry->String.Length = SourceSymbolicName.Length;
2453 AssociatedEntry->String.MaximumLength = AssociatedEntry->String.Length + sizeof(UNICODE_NULL);
2454 AssociatedEntry->String.Buffer = AllocatePool(AssociatedEntry->String.MaximumLength);
2455 if (AssociatedEntry->String.Buffer == NULL)
2456 {
2457 FreePool(AssociatedEntry);
2458 FreePool(SourceSymbolicName.Buffer);
2460 }
2461
2462 /* Copy data & insert in list */
2463 RtlCopyMemory(AssociatedEntry->String.Buffer, SourceSymbolicName.Buffer, SourceSymbolicName.Length);
2464 AssociatedEntry->String.Buffer[SourceSymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
2465 AssociatedEntry->DeviceInformation = DeviceInformation;
2466 InsertTailList(&TargetDeviceInformation->AssociatedDevicesHead, &AssociatedEntry->AssociatedDevicesEntry);
2467
2468 /* We're done! */
2469 FreePool(SourceSymbolicName.Buffer);
2470 return STATUS_SUCCESS;
2471}
2472
2473/*
2474 * @implemented
2475 */
2478 IN PIRP Irp,
2479 IN NTSTATUS LockStatus)
2480{
2481 LONG Offset;
2485 PDATABASE_ENTRY DatabaseEntry;
2486 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2487 PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2488 PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2489 UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2490
2491 /* Initialize string */
2492 LinkTarget.Length = 0;
2495 if (LinkTarget.Buffer == NULL)
2496 {
2498 }
2499
2500 /* If the mount point was deleted, then, it changed!
2501 * Also use it to query some information
2502 */
2503 Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2504 /* Pending means DB are under synchronization, bail out */
2505 if (Status == STATUS_PENDING)
2506 {
2508 FreePool(SourceDeviceName.Buffer);
2509 FreePool(SourceSymbolicName.Buffer);
2510 return STATUS_SUCCESS;
2511 }
2512 else if (!NT_SUCCESS(Status))
2513 {
2515 return Status;
2516 }
2517
2518 /* Query the device information */
2519 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2520 if (!NT_SUCCESS(Status))
2521 {
2522 /* If it failed, first try to get volume name */
2523 Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2524 if (!NT_SUCCESS(Status))
2525 {
2526 /* Then, try to read the symlink */
2527 Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2528 if (!NT_SUCCESS(Status))
2529 {
2531 FreePool(SourceDeviceName.Buffer);
2532 FreePool(SourceSymbolicName.Buffer);
2533 return Status;
2534 }
2535 }
2536 else
2537 {
2539 }
2540
2541 FreePool(SourceDeviceName.Buffer);
2542
2543 SourceDeviceName.Length = LinkTarget.Length;
2544 SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2545 SourceDeviceName.Buffer = LinkTarget.Buffer;
2546
2547 /* Now that we have the correct source, reattempt to query information */
2548 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2549 if (!NT_SUCCESS(Status))
2550 {
2551 FreePool(SourceDeviceName.Buffer);
2552 FreePool(SourceSymbolicName.Buffer);
2553 return Status;
2554 }
2555 }
2556
2557 FreePool(SourceDeviceName.Buffer);
2558
2559 /* Get information about target device */
2560 Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2561 if (!NT_SUCCESS(Status))
2562 {
2563 FreePool(SourceSymbolicName.Buffer);
2564 return Status;
2565 }
2566
2567 /* Open the remote database */
2568 RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2569 if (RemoteDatabase == 0)
2570 {
2571 FreePool(SourceSymbolicName.Buffer);
2573 }
2574
2575 /* Browse all the entries */
2576 Offset = 0;
2577 for (;;)
2578 {
2580 if (DatabaseEntry == NULL)
2581 {
2582 /* We didn't find ourselves, that's infortunate! */
2583 FreePool(SourceSymbolicName.Buffer);
2586 }
2587
2588 /* Try to find ourselves */
2589 DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2590 DbName.Length = DbName.MaximumLength;
2591 DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2592 if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2593 {
2594 break;
2595 }
2596
2597 Offset += DatabaseEntry->EntrySize;
2598 FreePool(DatabaseEntry);
2599 }
2600
2601 /* Dereference ourselves */
2602 DatabaseEntry->EntryReferences--;
2603 if (DatabaseEntry->EntryReferences == 0)
2604 {
2605 /* If we're still referenced, just update the entry */
2607 }
2608 else
2609 {
2610 /* Otherwise, delete the entry */
2612 if (!NT_SUCCESS(Status))
2613 {
2614 FreePool(DatabaseEntry);
2615 FreePool(SourceSymbolicName.Buffer);
2617 return Status;
2618 }
2619
2620 /* Also, delete our unique ID replicated record */
2621 for (Entry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
2622 Entry != &DeviceInformation->ReplicatedUniqueIdsListHead;
2623 Entry = Entry->Flink)
2624 {
2625 UniqueIdReplicate = CONTAINING_RECORD(Entry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
2626
2627 if (UniqueIdReplicate->UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
2628 RtlCompareMemory(UniqueIdReplicate->UniqueId->UniqueId,
2629 (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
2630 DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
2631 {
2632 break;
2633 }
2634 }
2635
2636 /* It has to exist! */
2637 if (Entry == &DeviceInformation->ReplicatedUniqueIdsListHead)
2638 {
2639 FreePool(DatabaseEntry);
2640 FreePool(SourceSymbolicName.Buffer);
2642 return STATUS_UNSUCCESSFUL;
2643 }
2644
2645 /* Remove it and free it */
2646 RemoveEntryList(&UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2647 FreePool(UniqueIdReplicate->UniqueId);
2648 FreePool(UniqueIdReplicate);
2649 }
2650
2651 /* We're done with the remote database */
2652 FreePool(DatabaseEntry);
2654
2655 /* Check write operation succeed */
2656 if (!NT_SUCCESS(Status))
2657 {
2658 FreePool(SourceSymbolicName.Buffer);
2659 return Status;
2660 }
2661
2662 /* Try to find our associated device entry */
2663 for (Entry = TargetDeviceInformation->AssociatedDevicesHead.Flink;
2664 Entry != &TargetDeviceInformation->AssociatedDevicesHead;
2665 Entry = Entry->Flink)
2666 {
2667 AssociatedEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
2668
2669 /* If found, delete it */
2670 if (AssociatedEntry->DeviceInformation == DeviceInformation &&
2671 RtlEqualUnicodeString(&AssociatedEntry->String, &SourceSymbolicName, TRUE))
2672 {
2673 RemoveEntryList(&AssociatedEntry->AssociatedDevicesEntry);
2674 FreePool(AssociatedEntry->String.Buffer);
2675 FreePool(AssociatedEntry);
2676 break;
2677 }
2678 }
2679
2680 /* We're done! */
2681 FreePool(SourceSymbolicName.Buffer);
2682 return STATUS_SUCCESS;
2683}
2684
2685/*
2686 * @implemented
2687 */
2689NTAPI
2691 IN PIRP Irp)
2692{
2694 NTSTATUS Status, LockStatus;
2695 PDEVICE_EXTENSION DeviceExtension;
2696
2698 DeviceExtension = DeviceObject->DeviceExtension;
2699
2700 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2701
2702 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2703 {
2705 Status = MountMgrCreatePoint(DeviceExtension, Irp);
2706 break;
2707
2709 Status = MountMgrDeletePoints(DeviceExtension, Irp);
2710 break;
2711
2713 Status = MountMgrQueryPoints(DeviceExtension, Irp);
2714 break;
2715
2717 Status = MountMgrDeletePointsDbOnly(DeviceExtension, Irp);
2718 break;
2719
2721 Status = MountMgrNextDriveLetter(DeviceExtension, Irp);
2722 break;
2723
2725 DeviceExtension->AutomaticDriveLetter = TRUE;
2727
2728 MountMgrAssignDriveLetters(DeviceExtension);
2729 ReconcileAllDatabasesWithMaster(DeviceExtension);
2730 WaitForOnlinesToComplete(DeviceExtension);
2731 break;
2732
2734 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2735
2736 LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2737 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2738 Status = MountMgrVolumeMountPointCreated(DeviceExtension, Irp, LockStatus);
2739 if (NT_SUCCESS(LockStatus))
2740 {
2741 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2742 }
2743
2744 break;
2745
2747 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2748
2749 LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2750 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2751 Status = MountMgrVolumeMountPointDeleted(DeviceExtension, Irp, LockStatus);
2752 if (NT_SUCCESS(LockStatus))
2753 {
2754 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2755 }
2756
2757 break;
2758
2760 Status = MountMgrChangeNotify(DeviceExtension, Irp);
2761 break;
2762
2764 Status = MountMgrKeepLinksWhenOffline(DeviceExtension, Irp);
2765 break;
2766
2768 Status = MountMgrCheckUnprocessedVolumes(DeviceExtension, Irp);
2769 goto Complete;
2770
2772 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2773 Status = MountMgrVolumeArrivalNotification(DeviceExtension, Irp);
2774 goto Complete;
2775
2777 Status = MountMgrQueryDosVolumePath(DeviceExtension, Irp);
2778 break;
2779
2781 Status = MountMgrQueryDosVolumePaths(DeviceExtension, Irp);
2782 break;
2783
2785 Status = MountMgrScrubRegistry(DeviceExtension);
2786 break;
2787
2789 Status = MountMgrQueryAutoMount(DeviceExtension, Irp);
2790 break;
2791
2793 Status = MountMgrSetAutoMount(DeviceExtension, Irp);
2794 break;
2795
2798 DPRINT1("Winism! Rewrite the caller!\n");
2799 default:
2801 }
2802
2803 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2804
2805 if (Status != STATUS_PENDING)
2806 {
2807 goto Complete;
2808 }
2809
2810 return Status;
2811
2812Complete:
2813 Irp->IoStatus.Status = Status;
2815
2816 return Status;
2817}
unsigned char BOOLEAN
@ Invalid
Definition: asmpp.cpp:30
LONG NTSTATUS
Definition: precomp.h:26
#define MAX(x, y)
Definition: rdesktop.h:175
#define DPRINT1
Definition: precomp.h:8
#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 NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define FILE_SHARE_READ
Definition: compat.h:136
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:1613
VOID NTAPI ReconcileThisDatabaseWithMasterWorker(IN PVOID Parameter)
Definition: database.c:560
VOID DeleteNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:2100
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:1659
HANDLE OpenRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN BOOLEAN MigrateDatabase)
Definition: database.c:1837
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:2477
BOOLEAN IsFtVolume(IN PUNICODE_STRING SymbolicName)
Definition: device.c:331
NTSTATUS MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1699
NTSTATUS MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1656
NTSTATUS MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1844
NTSTATUS MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1612
#define MAX_DEVICES
Definition: device.c:28
NTSTATUS MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus)
Definition: device.c:2238
NTSTATUS MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName)
Definition: device.c:734
NTSTATUS MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:221
NTSTATUS MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1463
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:1173
NTSTATUS NTAPI MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: device.c:694
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:1065
NTSTATUS MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1945
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:648
VOID MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:763
NTSTATUS MountmgrWriteNoAutoMount(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:87
VOID ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:403
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:2012
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:837
NTSTATUS MountMgrSetAutoMount(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:104
NTSTATUS MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo)
Definition: device.c:457
#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 KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#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:136
NTSTATUS MountMgrQuerySymbolicLink(IN PUNICODE_STRING SymbolicName, IN OUT PUNICODE_STRING LinkTarget)
Definition: symlink.c:959
NTSTATUS QueryDeviceInformation(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING DeviceName OPTIONAL, OUT PMOUNTDEV_UNIQUE_ID *UniqueId OPTIONAL, OUT PBOOLEAN Removable OPTIONAL, OUT PBOOLEAN GptDriveLetter OPTIONAL, OUT PBOOLEAN HasGuid OPTIONAL, IN OUT LPGUID StableGuid OPTIONAL, OUT PBOOLEAN Valid OPTIONAL)
Definition: mountmgr.c:190
DRIVER_DISPATCH MountMgrDeviceControl
Definition: mntmgr.h:340
UNICODE_STRING DeviceFloppy
Definition: symlink.c:34
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:636
#define COLON_POSITION
Definition: mntmgr.h:160
VOID MountMgrNotifyNameChange(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN BOOLEAN ValidateVolume)
Definition: notify.c:351
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:145
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:922
UNICODE_STRING DeviceCdRom
Definition: symlink.c:35
#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:1676
VOID MountMgrNotify(IN PDEVICE_EXTENSION DeviceExtension)
Definition: notify.c:311
VOID WaitForOnlinesToComplete(IN PDEVICE_EXTENSION DeviceExtension)
Definition: notify.c:197
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:701
VOID DeleteSymbolicLinkNameFromMemory(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLink, IN BOOLEAN MarkOffline)
Definition: symlink.c:864
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:83
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define FreePool(P)
Definition: mntmgr.h:154
UNICODE_STRING DosDevices
Definition: symlink.c:33
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:931
#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:124
struct _MOUNTMGR_MOUNT_POINTS * PMOUNTMGR_MOUNT_POINTS
struct _MOUNTMGR_TARGET_NAME * PMOUNTMGR_TARGET_NAME
#define IOCTL_MOUNTMGR_CREATE_POINT
Definition: imports.h:118
#define IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
Definition: imports.h:130
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 IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
Definition: mountmgr.h:16
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:61
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
Definition: mountmgr.h:127
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
Definition: mountmgr.h:129
struct _MOUNTMGR_CHANGE_NOTIFY_INFO * PMOUNTMGR_CHANGE_NOTIFY_INFO
#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
Definition: mountmgr.h:36
#define IOCTL_MOUNTMGR_QUERY_POINTS
Definition: mountmgr.h:30
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:40
struct _MOUNTMGR_VOLUME_MOUNT_POINT * PMOUNTMGR_VOLUME_MOUNT_POINT
#define IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES
Definition: mountmgr.h:46
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:53
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
Definition: mountmgr.h:34
#define IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY
Definition: mountmgr.h:32
#define IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE
Definition: mountmgr.h:44
struct _MOUNTMGR_DRIVE_LETTER_TARGET * PMOUNTMGR_DRIVE_LETTER_TARGET
#define IOCTL_MOUNTMGR_SCRUB_REGISTRY
Definition: mountmgr.h:150
#define IOCTL_MOUNTMGR_CHANGE_NOTIFY
Definition: mountmgr.h:42
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED
Definition: mountmgr.h:38
#define IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT
Definition: mountmgr.h:152
#define IOCTL_MOUNTMGR_SET_AUTO_MOUNT
Definition: mountmgr.h:154
#define IOCTL_MOUNTMGR_DEFINE_UNIX_DRIVE
Definition: mountmgr.h:15
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:34
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:4207
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4208
#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:317
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h:307
#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
@ NotificationEvent
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
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IoCallDriver
Definition: irp.c:1225
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 STATUS_PENDING
Definition: ntstatus.h:82
#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:97
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
#define FILE_DEVICE_VIRTUAL_DISK
Definition: winioctl.h:142
#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:138
UCHAR UniqueId[1]
Definition: imports.h:139
MOUNTMGR_MOUNT_POINT MountPoints[1]
Definition: imports.h:177
USHORT DeviceNameLength
Definition: imports.h:171
USHORT SymbolicLinkNameLength
Definition: imports.h:167
ULONG SymbolicLinkNameOffset
Definition: imports.h:166
MOUNTMGR_AUTO_MOUNT_STATE CurrentState
Definition: mountmgr.h:163
MOUNTMGR_AUTO_MOUNT_STATE NewState
Definition: mountmgr.h:167
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::@319::@321 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
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
_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:7213
_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:1648
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292