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