ReactOS 0.4.16-dev-976-g18fc5a1
device.c
Go to the documentation of this file.
1/*
2 * ReactOS kernel
3 * Copyright (C) 2011-2012 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/mountmgr/device.c
22 * PURPOSE: Mount Manager - Device Control
23 * PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
24 */
25
26#include "mntmgr.h"
27
28#define MAX_DEVICES 0x3E8 /* Matches 1000 devices */
29
30#define NDEBUG
31#include <debug.h>
32
33/*
34 * @implemented
35 */
38 IN PIRP Irp)
39{
44
45 /* Get the I/O buffer */
47 ChangeNotify = (PMOUNTMGR_CHANGE_NOTIFY_INFO)Irp->AssociatedIrp.SystemBuffer;
48
49 /* Validate it */
50 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO) ||
51 Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO))
52 {
54 }
55
56 /* If epic number doesn't match, just return now one */
57 if (DeviceExtension->EpicNumber != ChangeNotify->EpicNumber)
58 {
59 ChangeNotify->EpicNumber = DeviceExtension->EpicNumber;
60 Irp->IoStatus.Information = sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO);
61 return STATUS_SUCCESS;
62 }
63
64 /* If IRP is to be canceled, forget about that */
66 if (Irp->Cancel)
67 {
69 }
70 /* Otherwise queue the IRP to be notified with the next epic number change */
71 else
72 {
73 InsertTailList(&(DeviceExtension->IrpListHead), &(Irp->Tail.Overlay.ListEntry));
77 }
79
80 return Status;
81}
82
83/*
84 * @implemented
85 */
88{
89 ULONG Value = DeviceExtension->NoAutoMount;
90
92 DeviceExtension->RegistryPath.Buffer,
93 L"NoAutoMount",
95 &Value,
96 sizeof(Value));
97}
98
99/*
100 * @implemented
101 */
104 IN PIRP Irp)
105{
108
110
111 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_SET_AUTO_MOUNT))
112 {
113 Irp->IoStatus.Information = 0;
115 }
116
117 /* Change the state only if there is a real difference
118 * with the user-provided NewState (normalized) */
119 SetState = (PMOUNTMGR_SET_AUTO_MOUNT)Irp->AssociatedIrp.SystemBuffer;
120 if ((SetState->NewState != Enabled) == DeviceExtension->NoAutoMount)
121 {
122 Irp->IoStatus.Information = 0;
123 return STATUS_SUCCESS;
124 }
125
126 /* Set new state */
127 DeviceExtension->NoAutoMount = (SetState->NewState != Enabled);
128 Irp->IoStatus.Information = 0;
129 return MountmgrWriteNoAutoMount(DeviceExtension);
130}
131
132/*
133 * @implemented
134 */
137 IN PIRP Irp)
138{
141
143
144 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_QUERY_AUTO_MOUNT))
145 {
146 Irp->IoStatus.Information = 0;
148 }
149
150 QueryState = (PMOUNTMGR_QUERY_AUTO_MOUNT)Irp->AssociatedIrp.SystemBuffer;
151 QueryState->CurrentState = !DeviceExtension->NoAutoMount;
152 Irp->IoStatus.Information = sizeof(MOUNTMGR_QUERY_AUTO_MOUNT);
153
154 return STATUS_SUCCESS;
155}
156
157/*
158 * @implemented
159 */
161NTAPI
168{
170 PLIST_ENTRY NextEntry;
172 PBOOLEAN Continue = EntryContext;
173 PDEVICE_EXTENSION DeviceExtension = Context;
174
175 if (ValueType != REG_BINARY)
176 {
177 return STATUS_SUCCESS;
178 }
179
180 /* Delete values for devices that don't have the matching unique ID */
181 if (!IsListEmpty(&(DeviceExtension->DeviceListHead)))
182 {
183 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
184 NextEntry != &(DeviceExtension->DeviceListHead);
185 NextEntry = NextEntry->Flink)
186 {
187 DeviceInfo = CONTAINING_RECORD(NextEntry,
189 DeviceListEntry);
190
191 if (!DeviceInfo->UniqueId || DeviceInfo->UniqueId->UniqueIdLength != ValueLength)
192 {
193 continue;
194 }
195
197 {
198 return STATUS_SUCCESS;
199 }
200 }
201 }
202
203 /* Wrong unique ID, scrub it */
206 ValueName);
207 if (!NT_SUCCESS(Status))
208 {
209 *Continue = TRUE;
210 return STATUS_UNSUCCESSFUL;
211 }
212
213 *Continue = FALSE;
214 return Status;
215}
216
217/*
218 * @implemented
219 */
222{
224 BOOLEAN Continue;
226
227 do
228 {
231 QueryTable[0].EntryContext = &Continue;
232 Continue = FALSE;
233
237 DeviceExtension,
238 NULL);
239 }
240 while (Continue);
241
242 return Status;
243}
244
245/*
246 * @implemented
247 */
250 IN PIRP Irp)
251{
252 ULONG MaxLength;
256
258
259 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_CREATE_POINT_INPUT))
260 {
262 }
263
264 Point = (PMOUNTMGR_CREATE_POINT_INPUT)Irp->AssociatedIrp.SystemBuffer;
265
266 MaxLength = MAX((Point->DeviceNameOffset + Point->DeviceNameLength),
267 (Point->SymbolicLinkNameLength + Point->SymbolicLinkNameOffset));
268 if (MaxLength > Stack->Parameters.DeviceIoControl.InputBufferLength)
269 {
271 }
272
273 /* Get all the strings and call the worker */
274 SymbolicName.Length = Point->SymbolicLinkNameLength;
275 SymbolicName.MaximumLength = Point->SymbolicLinkNameLength;
276 DeviceName.Length = Point->DeviceNameLength;
277 DeviceName.MaximumLength = Point->DeviceNameLength;
278 SymbolicName.Buffer = (PVOID)((ULONG_PTR)Point + Point->SymbolicLinkNameOffset);
279 DeviceName.Buffer = (PVOID)((ULONG_PTR)Point + Point->DeviceNameOffset);
280
281 return MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &DeviceName);
282}
283
284/*
285 * @implemented
286 */
289 IN PIRP Irp)
290{
291 PLIST_ENTRY NextEntry;
292 PDEVICE_INFORMATION DeviceInformation;
293 NTSTATUS ArrivalStatus, Status = STATUS_SUCCESS;
294
296
297 /* No offline volumes, nothing more to do */
298 if (IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
299 {
300 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
301 return STATUS_SUCCESS;
302 }
303
304 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
305
306 /* Reactivate all the offline volumes */
307 while (!IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
308 {
309 NextEntry = RemoveHeadList(&(DeviceExtension->OfflineDeviceListHead));
310 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
311
312 ArrivalStatus = MountMgrMountedDeviceArrival(DeviceExtension,
313 &(DeviceInformation->SymbolicName),
314 DeviceInformation->ManuallyRegistered);
315 /* Then, remove them dead information */
316 MountMgrFreeDeadDeviceInfo(DeviceInformation);
317
318 if (NT_SUCCESS(Status))
319 {
320 Status = ArrivalStatus;
321 }
322 }
323
324 return Status;
325}
326
327/*
328 * @implemented
329 */
332{
336 PDEVICE_OBJECT DeviceObject, FileDeviceObject;
337
338 /* Get device object */
341 &FileObject,
342 &DeviceObject);
343 if (!NT_SUCCESS(Status))
344 return FALSE;
345
346 /* Get attached device */
347 FileDeviceObject = FileObject->DeviceObject;
348 DeviceObject = IoGetAttachedDeviceReference(FileDeviceObject);
349
350 /* FT volume can't be removable */
351 if (FileDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
352 {
355 return FALSE;
356 }
357
359
360 /* Get partition information */
361 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO,
363 NULL,
364 0,
366 sizeof(PartitionInfo),
367 NULL);
368
370 if (!NT_SUCCESS(Status))
371 return FALSE;
372
373 /* Check if this is a FT volume */
374 return IsFTPartition(PartitionInfo.PartitionType);
375}
376
377/*
378 * @implemented
379 */
380VOID
382{
383 WCHAR NameBuffer[DRIVE_LETTER_LENGTH / sizeof(WCHAR)];
384 PLIST_ENTRY NextEntry;
386 PDEVICE_INFORMATION DeviceInformation;
387
388 /* No devices? Nothing to do! */
389 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
390 {
391 return;
392 }
393
394 /* For all the devices */
395 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
396 NextEntry != &(DeviceExtension->DeviceListHead);
397 NextEntry = NextEntry->Flink)
398 {
399 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
400
401 /* If no drive letter */
402 if (DeviceInformation->SuggestedDriveLetter == (UCHAR)-1)
403 {
404 /* Ensure it has no entry yet */
405 if (!HasDriveLetter(DeviceInformation) &&
406 !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
407 {
408 /* And create one */
409 CreateNoDriveLetterEntry(DeviceInformation->UniqueId);
410 }
411
412 DeviceInformation->SuggestedDriveLetter = 0;
413 }
414 /* Suggested letter & no entry */
415 else if (DeviceInformation->SuggestedDriveLetter &&
416 !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
417 {
418 /* Just create a mount point */
419 SymbolicName.Buffer = NameBuffer;
421 NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
422 NameBuffer[COLON_POSITION] = L':';
425
426 MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &(DeviceInformation->DeviceName));
427 }
428 }
429}
430
431/*
432 * @implemented
433 */
438{
440 UCHAR DriveLetter;
441 PLIST_ENTRY NextEntry;
442 PMOUNTDEV_UNIQUE_ID UniqueId;
443 BOOLEAN Removable, GptDriveLetter;
444 PDEVICE_INFORMATION DeviceInformation;
445 WCHAR NameBuffer[DRIVE_LETTER_LENGTH];
446 PSYMLINK_INFORMATION SymlinkInformation;
447 UNICODE_STRING TargetDeviceName, SymbolicName;
448
449 /* First, process suggested letters */
450 if (!DeviceExtension->ProcessedSuggestions)
451 {
452 ProcessSuggestedDriveLetters(DeviceExtension);
453 DeviceExtension->ProcessedSuggestions = TRUE;
454 }
455
456 /* Then, get information about the device */
457 Status = QueryDeviceInformation(DeviceName, &TargetDeviceName, NULL, &Removable, &GptDriveLetter, NULL, NULL, NULL);
458 if (!NT_SUCCESS(Status))
459 {
460 return Status;
461 }
462
463 /* Ensure we have such device */
464 NextEntry = DeviceExtension->DeviceListHead.Flink;
465 while (NextEntry != &(DeviceExtension->DeviceListHead))
466 {
467 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
468
469 if (RtlCompareUnicodeString(&(DeviceInformation->DeviceName), &TargetDeviceName, TRUE) == 0)
470 {
471 break;
472 }
473
474 NextEntry = NextEntry->Flink;
475 }
476
477 if (NextEntry == &(DeviceExtension->DeviceListHead))
478 {
479 FreePool(TargetDeviceName.Buffer);
481 }
482
483 /* Now, assume we will assign a letter */
484 DeviceInformation->LetterAssigned =
485 DriveLetterInfo->DriveLetterWasAssigned = TRUE;
486
487 /* Browse all the symlinks to check if there is already a drive letter */
488 NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
489 while (NextEntry != &(DeviceInformation->SymbolicLinksListHead))
490 {
491 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
492
493 /* If this is a drive letter and it is online, forget about new drive letter */
494 if (IsDriveLetter(&(SymlinkInformation->Name)) && SymlinkInformation->Online)
495 {
496 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
497 DriveLetterInfo->CurrentDriveLetter = (CHAR)SymlinkInformation->Name.Buffer[LETTER_POSITION];
498 break;
499 }
500
501 NextEntry = NextEntry->Flink;
502 }
503
504 /* If we didn't find a drive letter online, ensure this is not
505 * a no-drive entry by querying GPT attributes & database */
506 if (NextEntry == &(DeviceInformation->SymbolicLinksListHead))
507 {
508 if (!GptDriveLetter || HasNoDriveLetterEntry(DeviceInformation->UniqueId))
509 {
510 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
511 DriveLetterInfo->CurrentDriveLetter = 0;
512 goto Release;
513 }
514 }
515
516 /* If automount is disabled, and the device is not removable
517 * but needs a drive letter, don't assign one and bail out */
518 if (DeviceExtension->NoAutoMount && !Removable)
519 {
520 if (DriveLetterInfo->DriveLetterWasAssigned)
521 {
522 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
523 DriveLetterInfo->CurrentDriveLetter = 0;
524 goto Release;
525 }
526 }
527
528 /* Stop now if we don't need to assign the drive a letter */
529 if (!DriveLetterInfo->DriveLetterWasAssigned)
530 goto Release;
531
532 /* Now everything is fine, begin drive letter assignment */
533
534 if (RtlPrefixUnicodeString(&DeviceFloppy, &TargetDeviceName, TRUE))
535 {
536 /* If the device is a floppy, start with letter A */
537 DriveLetter = 'A';
538 }
539 else if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
540 {
541 /* If the device is a CD-ROM, start with letter D */
542 DriveLetter = 'D';
543 }
544 else
545 {
546 /* Finally, if it's a disk, use C */
547 DriveLetter = 'C';
548 }
549
550 /* We cannot set NO drive letter */
551 ASSERT(DeviceInformation->SuggestedDriveLetter != (UCHAR)-1);
552
553 /* If we don't have suggested letter but it's a FT volume, fail */
554 if (!DeviceInformation->SuggestedDriveLetter && IsFtVolume(&(DeviceInformation->DeviceName)))
555 {
556 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
557 DriveLetterInfo->CurrentDriveLetter = 0;
558 goto Release;
559 }
560
561 /* Prepare buffer */
563 NameBuffer[COLON_POSITION] = L':';
564 SymbolicName.Buffer = NameBuffer;
567
568 /* It's all prepared, create mount point */
569 if (DeviceInformation->SuggestedDriveLetter)
570 {
571 DriveLetterInfo->CurrentDriveLetter = DeviceInformation->SuggestedDriveLetter;
572 NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
573
574 Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
575 if (NT_SUCCESS(Status))
576 {
577 goto Release;
578 }
579 }
580
581 /* It failed with this letter... Try another one! */
582 for (DriveLetterInfo->CurrentDriveLetter = DriveLetter;
583 DriveLetterInfo->CurrentDriveLetter <= L'Z';
584 DriveLetterInfo->CurrentDriveLetter++)
585 {
586 NameBuffer[LETTER_POSITION] = DriveLetterInfo->CurrentDriveLetter;
587
588 Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
589 if (NT_SUCCESS(Status))
590 {
591 break;
592 }
593 }
594
595 /* We failed setting a letter */
596 if (DriveLetterInfo->CurrentDriveLetter > L'Z')
597 {
598 DriveLetterInfo->DriveLetterWasAssigned = FALSE;
599 DriveLetterInfo->CurrentDriveLetter = 0;
600
601 /* Try at least to add a no drive letter entry */
602 Status = QueryDeviceInformation(&TargetDeviceName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
603 if (NT_SUCCESS(Status))
604 {
605 CreateNoDriveLetterEntry(UniqueId);
606 FreePool(UniqueId);
607 }
608 }
609
610Release:
611 FreePool(TargetDeviceName.Buffer);
612
613 return STATUS_SUCCESS;
614}
615
616
617/*
618 * @implemented
619 */
622 IN PIRP Irp)
623{
627 PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget;
628 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
629
631
632 /* Validate input */
633 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) ||
634 Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION))
635 {
637 }
638
639 DriveLetterTarget = (PMOUNTMGR_DRIVE_LETTER_TARGET)Irp->AssociatedIrp.SystemBuffer;
641 Stack->Parameters.DeviceIoControl.InputBufferLength)
642 {
644 }
645
646 /* Call the worker */
647 DeviceName.Buffer = DriveLetterTarget->DeviceName;
648 DeviceName.Length =
649 DeviceName.MaximumLength = DriveLetterTarget->DeviceNameLength;
650
652 &DriveLetterInformation);
653 if (NT_SUCCESS(Status))
654 {
655 *(PMOUNTMGR_DRIVE_LETTER_INFORMATION)Irp->AssociatedIrp.SystemBuffer =
656 DriveLetterInformation;
657 Irp->IoStatus.Information = sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION);
658 }
659
660 return Status;
661}
662
663/*
664 * @implemented
665 */
667NTAPI
674{
675 UNICODE_STRING ValueString;
676 PUNICODE_STRING SystemVolumeName;
677
681
682 if (ValueType != REG_SZ)
683 {
684 return STATUS_SUCCESS;
685 }
686
687 RtlInitUnicodeString(&ValueString, ValueData);
688 SystemVolumeName = Context;
689
690 /* Return a string containing system volume name */
691 SystemVolumeName->Length = ValueString.Length;
692 SystemVolumeName->MaximumLength = ValueString.Length + sizeof(WCHAR);
693 SystemVolumeName->Buffer = AllocatePool(SystemVolumeName->MaximumLength);
694 if (SystemVolumeName->Buffer)
695 {
696 RtlCopyMemory(SystemVolumeName->Buffer, ValueData, ValueString.Length);
697 SystemVolumeName->Buffer[ValueString.Length / sizeof(WCHAR)] = UNICODE_NULL;
698 }
699
700 return STATUS_SUCCESS;
701
702}
703
704/*
705 * @implemented
706 */
709{
711
715 QueryTable[0].Name = L"SystemPartition";
716
717 SystemVolumeName->Buffer = NULL;
718
720 L"\\Registry\\Machine\\System\\Setup",
722 SystemVolumeName,
723 NULL);
724
725 if (SystemVolumeName->Buffer)
726 {
727 return STATUS_SUCCESS;
728 }
729
730 return STATUS_UNSUCCESSFUL;
731}
732
733/*
734 * @implemented
735 */
736VOID
738{
740 PLIST_ENTRY NextEntry;
741 UNICODE_STRING SystemVolumeName;
742 PDEVICE_INFORMATION DeviceInformation;
743 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
744
745 /* First, get system volume name */
746 Status = MountMgrQuerySystemVolumeName(&SystemVolumeName);
747
748 /* If there are no device, it's all done */
749 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
750 {
751 if (NT_SUCCESS(Status))
752 {
753 FreePool(SystemVolumeName.Buffer);
754 }
755
756 return;
757 }
758
759 /* Now, for all the devices... */
760 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
761 NextEntry != &(DeviceExtension->DeviceListHead);
762 NextEntry = NextEntry->Flink)
763 {
764 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
765
766 /* If the device doesn't have a letter assigned, do it! */
767 if (!DeviceInformation->LetterAssigned)
768 {
769 MountMgrNextDriveLetterWorker(DeviceExtension,
770 &(DeviceInformation->DeviceName),
771 &DriveLetterInformation);
772 }
773
774 /* If it's the system volume */
775 if (NT_SUCCESS(Status) && RtlEqualUnicodeString(&SystemVolumeName, &(DeviceInformation->DeviceName), TRUE))
776 {
777 /* Keep track of it */
778 DeviceExtension->DriveLetterData = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength +
779 sizeof(MOUNTDEV_UNIQUE_ID));
780 if (DeviceExtension->DriveLetterData)
781 {
782 RtlCopyMemory(DeviceExtension->DriveLetterData,
783 DeviceInformation->UniqueId,
784 DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
785 }
786
787 /* Ensure it gets mounted if automount is disabled */
788 if (DeviceExtension->NoAutoMount)
789 {
790 /* Temporarily re-enable automount for the
791 * worker to mount and set a drive letter */
792 DeviceExtension->NoAutoMount = FALSE;
793
794 MountMgrNextDriveLetterWorker(DeviceExtension,
795 &(DeviceInformation->DeviceName),
796 &DriveLetterInformation);
797
798 /* And re-disable automount */
799 DeviceExtension->NoAutoMount = TRUE;
800 }
801 }
802 }
803
804 if (NT_SUCCESS(Status))
805 {
806 FreePool(SystemVolumeName.Buffer);
807 }
808}
809
810/*
811 * @implemented
812 */
815 IN PIRP Irp)
816{
818 ULONG DevicesFound;
820 PLIST_ENTRY SymlinksEntry;
824 PWSTR DeviceString, OldBuffer;
825 USHORT DeviceLength, OldLength;
826 PDEVICE_INFORMATION DeviceInformation;
827 PSYMLINK_INFORMATION SymlinkInformation;
829
831
832 /* Validate input size */
833 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
834 {
836 }
837
838 /* Ensure we have received UNICODE_STRING */
839 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
840 if (Target->DeviceNameLength & 1)
841 {
843 }
844
845 /* Validate the entry structure size */
846 if (FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Target->DeviceNameLength >
847 Stack->Parameters.DeviceIoControl.InputBufferLength)
848 {
850 }
851
852 /* Ensure we can at least return needed size */
853 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz))
854 {
856 }
857
858 /* Construct string for query */
860 SymbolicName.MaximumLength = Target->DeviceNameLength;
861 SymbolicName.Buffer = Target->DeviceName;
862
863 /* Find device with our info */
864 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
865 if (!NT_SUCCESS(Status))
866 {
867 return Status;
868 }
869
870 DeviceLength = 0;
871 DeviceString = NULL;
872 DevicesFound = 0;
873
874 /* Try to find associated device info */
875 while (TRUE)
876 {
877 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
878 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
879 SymlinksEntry = SymlinksEntry->Flink)
880 {
881 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
882
883 /* Try to find with drive letter */
884 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
885 {
886 break;
887 }
888 }
889
890 /* If we've found a device via drive letter, do default processing */
891 if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
892 break;
893
894 /* If it doesn't have an associated device, go to fallback method */
895 if (IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
896 goto TryWithVolumeName;
897
898 /* Create a string with the information about the device */
899 AssociatedDevice = CONTAINING_RECORD(&(DeviceInformation->AssociatedDevicesHead), ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
900 OldLength = DeviceLength;
901 OldBuffer = DeviceString;
902 DeviceLength += AssociatedDevice->String.Length;
903 DeviceString = AllocatePool(DeviceLength);
904 if (!DeviceString)
905 {
906 if (OldBuffer)
907 {
908 FreePool(OldBuffer);
909 }
910
912 }
913
914 /* Store our info and previous if any */
915 RtlCopyMemory(DeviceString, AssociatedDevice->String.Buffer, AssociatedDevice->String.Length);
916 if (OldBuffer)
917 {
918 RtlCopyMemory(&DeviceString[AssociatedDevice->String.Length / sizeof(WCHAR)], OldBuffer, OldLength);
919 FreePool(OldBuffer);
920 }
921
922 /* Count and continue looking */
923 ++DevicesFound;
924 DeviceInformation = AssociatedDevice->DeviceInformation;
925
926 /* If too many devices, try another way */
927 if (DevicesFound > MAX_DEVICES) /* 1000 */
928 {
929 goto TryWithVolumeName;
930 }
931 }
932
933 /* Reallocate our string, so that we can prepend disk letter */
934 OldBuffer = DeviceString;
935 OldLength = DeviceLength;
936 DeviceLength += 2 * sizeof(WCHAR);
937 DeviceString = AllocatePool(DeviceLength);
938 if (!DeviceString)
939 {
940 if (OldBuffer)
941 {
942 FreePool(OldBuffer);
943 }
944
946 }
947
948 /* Get the letter */
949 DeviceString[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
950 DeviceString[1] = L':';
951
952 /* And copy the rest */
953 if (OldBuffer)
954 {
955 RtlCopyMemory(&DeviceString[2], OldBuffer, OldLength);
956 FreePool(OldBuffer);
957 }
958
959TryWithVolumeName:
960 /* If we didn't find anything, try differently */
961 if (DeviceLength < 2 * sizeof(WCHAR) || DeviceString[1] != L':')
962 {
963 if (DeviceString)
964 {
965 FreePool(DeviceString);
966 DeviceString = NULL;
967 DeviceLength = 0;
968 }
969
970 /* Try to find a volume name matching */
971 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
972 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
973 SymlinksEntry = SymlinksEntry->Flink)
974 {
975 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
976
977 if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation->Name))
978 {
979 break;
980 }
981 }
982
983 /* If found copy */
984 if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
985 {
986 DeviceLength = SymlinkInformation->Name.Length;
987 DeviceString = AllocatePool(DeviceLength);
988 if (!DeviceString)
989 {
991 }
992
993 RtlCopyMemory(DeviceString, SymlinkInformation->Name.Buffer, DeviceLength);
994 /* Ensure we are in the Win32 namespace; [1] can be '?' */
995 DeviceString[1] = L'\\';
996 }
997 }
998
999 /* If we didn't find something, fail */
1000 if (!DeviceString)
1001 return STATUS_NOT_FOUND;
1002
1003 /* Get the output buffer */
1004 Output = (PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer;
1005
1006 /* At least, we will return our length */
1007 Output->MultiSzLength = DeviceLength + 2 * sizeof(UNICODE_NULL);
1008 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz) + Output->MultiSzLength;
1009
1010 /* If we have enough room for copying the string */
1011 if (Irp->IoStatus.Information <= Stack->Parameters.DeviceIoControl.OutputBufferLength)
1012 {
1013 /* Copy it */
1014 if (DeviceLength)
1015 {
1016 RtlCopyMemory(Output->MultiSz, DeviceString, DeviceLength);
1017 }
1018
1019 /* And double-NUL at its end - this is needed in case of
1020 * multiple paths which are separated by a single NUL */
1021 FreePool(DeviceString);
1022 Output->MultiSz[DeviceLength / sizeof(WCHAR)] = UNICODE_NULL;
1023 Output->MultiSz[DeviceLength / sizeof(WCHAR) + 1] = UNICODE_NULL;
1024
1025 return STATUS_SUCCESS;
1026 }
1027 else
1028 {
1029 /* Just return the size needed and leave */
1030 FreePool(DeviceString);
1031 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz);
1033 }
1034}
1035
1036/*
1037 * @implemented
1038 */
1041 IN PDEVICE_INFORMATION DeviceInformation,
1043{
1044 HANDLE Handle;
1046 PLIST_ENTRY SymlinksEntry;
1048 PREPARSE_DATA_BUFFER ReparseData;
1050 UNICODE_STRING FullName, SubstituteName;
1051 PSYMLINK_INFORMATION SymlinkInformation;
1052
1053 /* Initialize & allocate a string big enough to contain our complete mount point name */
1054 FullName.Length = 0;
1055 FullName.MaximumLength = AssociatedDeviceEntry->String.Length
1056 + AssociatedDeviceEntry->DeviceInformation->DeviceName.Length
1057 + sizeof(WCHAR)
1058 + sizeof(UNICODE_NULL);
1060 if (!FullName.Buffer)
1061 {
1063 }
1064
1065 /* Create the path */
1066 RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->DeviceInformation->DeviceName);
1067 FullName.Buffer[FullName.Length / sizeof(WCHAR)] = L'\\';
1068 RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->String);
1070
1071 /* Open it to query the reparse point */
1073 &FullName,
1075 NULL,
1076 NULL);
1083
1084 if (!NT_SUCCESS(Status))
1085 {
1086 *Invalid = TRUE;
1087 return STATUS_SUCCESS;
1088 }
1089
1090 /* Allocate a buffer big enough to read reparse data */
1092 if (ReparseData == NULL)
1093 {
1094 ZwClose(Handle);
1096 }
1097
1098 /* Query reparse data */
1100 NULL, NULL, NULL,
1103 NULL, 0,
1105 ZwClose(Handle);
1106
1107 if (!NT_SUCCESS(Status))
1108 {
1109 FreePool(ReparseData);
1110 *Invalid = TRUE;
1111 return STATUS_SUCCESS;
1112 }
1113
1114 /* Create a string with the substitute name */
1115 SubstituteName.Length = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
1116 SubstituteName.MaximumLength = SubstituteName.Length;
1117 SubstituteName.Buffer = (PWSTR)((ULONG_PTR)ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset);
1118
1119 /* If that's a volume name that matches our associated device, that's a success! */
1120 if (MOUNTMGR_IS_VOLUME_NAME(&SubstituteName))
1121 {
1122 if (SubstituteName.Length == 98 && SubstituteName.Buffer[1] == L'?')
1123 {
1124 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1125 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
1126 SymlinksEntry = SymlinksEntry->Flink)
1127 {
1128 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1129
1130 if (RtlEqualUnicodeString(&SubstituteName, &SymlinkInformation->Name, TRUE))
1131 {
1132 FreePool(ReparseData);
1133 return STATUS_SUCCESS;
1134 }
1135 }
1136 }
1137 }
1138
1139 FreePool(ReparseData);
1140 *Invalid = TRUE;
1141 return STATUS_SUCCESS;
1142}
1143
1144/*
1145 * @implemented
1146 */
1149 IN PDEVICE_INFORMATION DeviceInformation,
1150 IN PLIST_ENTRY DeviceInfoList,
1151 OUT PMOUNTMGR_VOLUME_PATHS * VolumePaths,
1152 OUT PDEVICE_INFORMATION *FailedDevice)
1153{
1154 ULONG Written;
1157 PSYMLINK_INFORMATION SymlinkInformation;
1158 PDEVICE_INFORMATION_ENTRY DeviceInfoEntry;
1159 PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry;
1160 PMOUNTMGR_VOLUME_PATHS * Paths = NULL, * CurrentPath;
1161 ULONG OutputPathLength, NumberOfPaths, ReturnedPaths;
1162
1163 /* We return at least null char */
1164 OutputPathLength = sizeof(UNICODE_NULL);
1165
1166 for (Entry = DeviceInformation->SymbolicLinksListHead.Flink;
1167 Entry != &(DeviceInformation->SymbolicLinksListHead);
1168 Entry = Entry->Flink)
1169 {
1170 SymlinkInformation = CONTAINING_RECORD(Entry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1171
1172 /* Try to find the drive letter (ie, DOS device) */
1173 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
1174 {
1175 /* We'll return the letter */
1176 OutputPathLength = 4 * sizeof(WCHAR);
1177 break;
1178 }
1179 }
1180
1181 /* We didn't find any */
1182 if (Entry == &(DeviceInformation->SymbolicLinksListHead))
1183 {
1184 SymlinkInformation = NULL;
1185 }
1186
1187 /* Do we have any device info to return? */
1188 for (Entry = DeviceInfoList->Flink; Entry != DeviceInfoList; Entry = Entry->Flink)
1189 {
1190 DeviceInfoEntry = CONTAINING_RECORD(Entry, DEVICE_INFORMATION_ENTRY, DeviceInformationEntry);
1191
1192 /* Matching current device */
1193 if (DeviceInfoEntry->DeviceInformation == DeviceInformation)
1194 {
1195 /* Allocate the output buffer */
1196 *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1197 if (*VolumePaths == NULL)
1198 {
1200 }
1201
1202 /* Set size */
1203 (*VolumePaths)->MultiSzLength = OutputPathLength;
1204 /* If we have a drive letter, return it */
1205 if (SymlinkInformation != NULL)
1206 {
1207 (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1208 (*VolumePaths)->MultiSz[1] = L':';
1209 (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1210 (*VolumePaths)->MultiSz[3] = UNICODE_NULL;
1211 }
1212 else
1213 {
1214 (*VolumePaths)->MultiSz[0] = UNICODE_NULL;
1215 }
1216
1217 return STATUS_SUCCESS;
1218 }
1219 }
1220
1221 /* Allocate a new device entry */
1222 DeviceInfoEntry = AllocatePool(sizeof(DEVICE_INFORMATION_ENTRY));
1223 if (DeviceInfoEntry == NULL)
1224 {
1226 }
1227
1228 /* Add it to the list */
1229 DeviceInfoEntry->DeviceInformation = DeviceInformation;
1230 InsertTailList(DeviceInfoList, &DeviceInfoEntry->DeviceInformationEntry);
1231
1232 NumberOfPaths = 0;
1233 /* Count the amount of devices we will have to handle */
1234 if (!IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
1235 {
1236 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1237 Entry != &DeviceInformation->AssociatedDevicesHead;
1238 Entry = Entry->Flink)
1239 {
1240 ++NumberOfPaths;
1241 }
1242
1243 ASSERT(NumberOfPaths != 0);
1244 /* And allocate a big enough buffer */
1245 Paths = AllocatePool(NumberOfPaths * sizeof(PMOUNTMGR_VOLUME_PATHS));
1246 if (Paths == NULL)
1247 {
1248 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1249 FreePool(DeviceInfoEntry);
1251 }
1252 }
1253
1254 /* Start the hot loop to gather all the paths and be able to compute total output length! */
1255 ReturnedPaths = 0;
1256 CurrentPath = Paths;
1257 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1258 Entry != &DeviceInformation->AssociatedDevicesHead;
1259 Entry = Entry->Flink)
1260 {
1261 USHORT InnerStrings;
1263
1264 AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1265
1266 /* Validate the fact its a mount point by query reparse data */
1267 Status = MountMgrValidateBackPointer(AssociatedDeviceEntry, DeviceInformation, &Invalid);
1268
1269 /* If we found an invalid device, that's a failure */
1270 if (Invalid)
1271 {
1272 *FailedDevice = AssociatedDeviceEntry->DeviceInformation;
1274 }
1275
1276 /* Check whether we failed, if so, bail out */
1277 if (!NT_SUCCESS(Status))
1278 {
1279 ULONG i;
1280
1281 for (i = 0; i < ReturnedPaths; ++i)
1282 {
1283 FreePool(Paths[i]);
1284 }
1285
1286 if (Paths != NULL)
1287 {
1288 FreePool(Paths);
1289 }
1290 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1291 FreePool(DeviceInfoEntry);
1292 return Status;
1293 }
1294
1295 /* Query associated paths (hello ourselves :-)) */
1296 Status = MountMgrQueryVolumePaths(DeviceExtension,
1297 AssociatedDeviceEntry->DeviceInformation,
1298 DeviceInfoList,
1299 CurrentPath,
1300 FailedDevice);
1301 if (!NT_SUCCESS(Status))
1302 {
1303 ULONG i;
1304
1305 for (i = 0; i < ReturnedPaths; ++i)
1306 {
1307 FreePool(Paths[i]);
1308 }
1309
1310 if (Paths != NULL)
1311 {
1312 FreePool(Paths);
1313 }
1314 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1315 FreePool(DeviceInfoEntry);
1316 return Status;
1317 }
1318
1319 /* Count the number of strings we have in the multi string buffer */
1320 InnerStrings = 0;
1321 if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1322 {
1323 ULONG i;
1324 PWSTR MultiSz = (*CurrentPath)->MultiSz;
1325
1326 for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR); ++i, ++MultiSz)
1327 {
1328 if (*MultiSz == UNICODE_NULL)
1329 {
1330 ++InnerStrings;
1331 }
1332 }
1333 }
1334
1335 /* We returned one more path (ie, one more allocated buffer) */
1336 ++ReturnedPaths;
1337 /* Move the next pointer to use in the array */
1338 ++CurrentPath;
1339 /* Multiply String.Length by the number of found paths, we always add it after a path */
1340 OutputPathLength += (*CurrentPath)->MultiSzLength + InnerStrings * AssociatedDeviceEntry->String.Length - sizeof(UNICODE_NULL);
1341 }
1342
1343 /* Allocate the output buffer */
1344 *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1345 if (*VolumePaths == NULL)
1346 {
1347 ULONG i;
1348
1349 for (i = 0; i < ReturnedPaths; ++i)
1350 {
1351 FreePool(Paths[i]);
1352 }
1353
1354 if (Paths != NULL)
1355 {
1356 FreePool(Paths);
1357 }
1358 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1359 FreePool(DeviceInfoEntry);
1361 }
1362
1363 Written = 0;
1364 /* If we had found a DOS letter, that's the first thing we return */
1365 (*VolumePaths)->MultiSzLength = OutputPathLength;
1366 if (SymlinkInformation != NULL)
1367 {
1368 (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1369 (*VolumePaths)->MultiSz[1] = L':';
1370 (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1371 Written = 3;
1372 }
1373
1374 /* Now, browse again all our paths to return them */
1375 CurrentPath = Paths;
1376 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1377 Entry != &DeviceInformation->AssociatedDevicesHead;
1378 Entry = Entry->Flink)
1379 {
1380 AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1381
1382 /* If we had a path... */
1383 if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1384 {
1385 ULONG i, Offset;
1386 PWSTR MultiSz;
1387
1388 /* This offset is used to "jump" into MultiSz, so, start with the string begin (ie, skip MultiSzLength) */
1389 Offset = sizeof(ULONG);
1390 /* Browse every single letter, and skip last UNICODE_NULL */
1391 for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR) - 1; ++i)
1392 {
1393 /* Get the letter */
1394 MultiSz = (PWSTR)((ULONG_PTR)(*CurrentPath) + Offset);
1395 /* If it was part of the path, just return it */
1396 if (*MultiSz != UNICODE_NULL)
1397 {
1398 (*VolumePaths)->MultiSz[Written] = *MultiSz;
1399 }
1400 else
1401 {
1402 /* Otherwise, as planed, return our whole associated device name */
1403 RtlCopyMemory(&(*VolumePaths)->MultiSz[Written],
1404 AssociatedDeviceEntry->String.Buffer,
1405 AssociatedDeviceEntry->String.Length);
1406 Written += AssociatedDeviceEntry->String.Length / sizeof(WCHAR);
1407 /* And don't forget to nullify */
1408 (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1409 }
1410
1411 /* We at least return a letter or a null char */
1412 ++Written;
1413 /* Move to the next letter */
1414 Offset += sizeof(WCHAR);
1415 }
1416 }
1417
1418 FreePool(*CurrentPath);
1419 ++CurrentPath;
1420 }
1421
1422 /* MultiSz: don't forget last null char */
1423 (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1424 /* Cleanup everything and return success! */
1425 if (Paths != NULL)
1426 {
1427 FreePool(Paths);
1428 }
1429 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1430 FreePool(DeviceInfoEntry);
1431 return STATUS_SUCCESS;
1432}
1433
1434/*
1435 * @implemented
1436 */
1439 IN PIRP Irp)
1440{
1443 LIST_ENTRY Devices;
1444 BOOLEAN NeedNotification;
1447 ULONG Attempts, OutputLength;
1450 RECONCILE_WORK_ITEM_CONTEXT ReconcileContext;
1451 PDEVICE_INFORMATION DeviceInformation, ListDeviceInfo, FailedDevice;
1452
1454
1455 /* Validate input size */
1456 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1457 {
1459 }
1460
1461 /* Ensure we have received UNICODE_STRING */
1462 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1463 if (Target->DeviceNameLength & 1)
1464 {
1466 }
1467
1468 /* Validate the entry structure size */
1469 if (FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Target->DeviceNameLength >
1470 Stack->Parameters.DeviceIoControl.InputBufferLength)
1471 {
1473 }
1474
1475 /* Ensure we can at least return needed size */
1476 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz))
1477 {
1479 }
1480
1481 /* Construct string for query */
1483 SymbolicName.MaximumLength = Target->DeviceNameLength;
1484 SymbolicName.Buffer = Target->DeviceName;
1485
1486 /* Find device with our info */
1487 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1488 if (!NT_SUCCESS(Status))
1489 {
1490 return Status;
1491 }
1492
1493 NeedNotification = FALSE;
1494 Attempts = 0;
1495 for (;;)
1496 {
1497 FailedDevice = NULL;
1498 InitializeListHead(&Devices);
1499
1500 /* Query paths */
1501 Status = MountMgrQueryVolumePaths(DeviceExtension, DeviceInformation, &Devices, &Paths, &FailedDevice);
1502 if (NT_SUCCESS(Status))
1503 {
1504 break;
1505 }
1506
1507 /* If it failed for generic reason (memory, whatever), bail out (ie, FailedDevice not set) */
1508 if (FailedDevice == NULL)
1509 {
1510 return Status;
1511 }
1512
1513 /* If PnP, let's notify in case of success */
1514 if (!DeviceInformation->ManuallyRegistered)
1515 {
1516 NeedNotification = TRUE;
1517 }
1518
1519 /* Reconcile database */
1520 ReconcileContext.DeviceExtension = DeviceExtension;
1521 ReconcileContext.DeviceInformation = FailedDevice;
1522 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1523 ReconcileThisDatabaseWithMasterWorker(&ReconcileContext);
1524 KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1525
1526 /* Look for our device, to check it's online */
1527 for (Entry = DeviceExtension->DeviceListHead.Flink;
1528 Entry != &DeviceExtension->DeviceListHead;
1529 Entry = Entry->Flink)
1530 {
1531 ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
1532 /* It's online, it's OK! */
1533 if (ListDeviceInfo == DeviceInformation)
1534 {
1535 break;
1536 }
1537 }
1538
1539 /* It's not online, it's not good */
1540 if (Entry == &DeviceExtension->DeviceListHead)
1541 {
1543 }
1544
1545 /* Increase attempts count */
1546 ++Attempts;
1547 /* Don't look forever and fail if we get out of attempts */
1548 if (Attempts >= 1000)
1549 {
1550 return Status;
1551 }
1552 }
1553
1554 /* We need to notify? Go ahead */
1555 if (NeedNotification)
1556 {
1557 MountMgrNotifyNameChange(DeviceExtension, &SymbolicName, FALSE);
1558 }
1559
1560 /* Get the output buffer */
1561 Output = (PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer;
1562
1563 /* Set required size */
1564 Output->MultiSzLength = Paths->MultiSzLength;
1565
1566 /* Compute total length */
1567 OutputLength = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz) + Output->MultiSzLength;
1568
1569 /* If it cannot fit, just return the size needed and leave */
1570 if (OutputLength > Stack->Parameters.DeviceIoControl.OutputBufferLength)
1571 {
1572 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz);
1573 FreePool(Paths);
1575 }
1576
1577 /* Copy data and quit */
1578 Irp->IoStatus.Information = OutputLength;
1579 RtlCopyMemory(Output->MultiSz, Paths->MultiSz, Output->MultiSzLength);
1580 FreePool(Paths);
1581 return STATUS_SUCCESS;
1582}
1583
1584/*
1585 * @implemented
1586 */
1589 IN PIRP Irp)
1590{
1595 PDEVICE_INFORMATION DeviceInformation;
1596
1598
1599 /* Validate input */
1600 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1601 {
1603 }
1604
1605 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1606 if (FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Target->DeviceNameLength >
1607 Stack->Parameters.DeviceIoControl.InputBufferLength)
1608 {
1610 }
1611
1613 SymbolicName.MaximumLength = Target->DeviceNameLength;
1614 SymbolicName.Buffer = Target->DeviceName;
1615
1616 /* Find the associated device */
1617 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1618 if (!NT_SUCCESS(Status))
1619 {
1620 return Status;
1621 }
1622
1623 /* Mark we want to keep links */
1624 DeviceInformation->KeepLinks = TRUE;
1625
1626 return STATUS_SUCCESS;
1627}
1628
1629/*
1630 * @implemented
1631 */
1634 IN PIRP Irp)
1635{
1637 BOOLEAN OldState;
1641
1643
1644 /* Validate input */
1645 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1646 {
1648 }
1649
1650 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1651 if (FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Target->DeviceNameLength >
1652 Stack->Parameters.DeviceIoControl.InputBufferLength)
1653 {
1655 }
1656
1658 SymbolicName.MaximumLength = Target->DeviceNameLength;
1659 SymbolicName.Buffer = Target->DeviceName;
1660
1661 /* Disable hard errors */
1664
1665 /* Call real worker */
1667
1669
1670 return Status;
1671}
1672
1673/*
1674 * @implemented
1675 */
1678 IN PIRP Irp)
1679{
1682 PMOUNTDEV_UNIQUE_ID UniqueId;
1683 PMOUNTMGR_MOUNT_POINT MountPoint;
1685
1687
1688 /* Validate input... */
1689 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1690 {
1692 }
1693
1694 MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1695 if (!MountPoint->SymbolicLinkNameLength)
1696 {
1697 MountPoint->SymbolicLinkNameOffset = 0;
1698 }
1699
1700 if (!MountPoint->UniqueIdLength)
1701 {
1702 MountPoint->UniqueIdOffset = 0;
1703 }
1704
1705 if (!MountPoint->DeviceNameLength)
1706 {
1707 MountPoint->DeviceNameOffset = 0;
1708 }
1709
1710 /* Addresses can't be odd */
1711 if ((MountPoint->SymbolicLinkNameOffset & 1) ||
1712 (MountPoint->SymbolicLinkNameLength & 1))
1713 {
1715 }
1716
1717 if ((MountPoint->UniqueIdOffset & 1) ||
1718 (MountPoint->UniqueIdLength & 1))
1719 {
1721 }
1722
1723 if ((MountPoint->DeviceNameOffset & 1) ||
1724 (MountPoint->DeviceNameLength & 1))
1725 {
1727 }
1728
1729 /* We can't go beyond */
1730 if (((ULONG)MountPoint->SymbolicLinkNameLength + MountPoint->UniqueIdLength +
1731 MountPoint->DeviceNameLength) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1732 {
1734 }
1735
1736 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_MOUNT_POINTS))
1737 {
1739 }
1740
1741 /* If caller provided a Symlink, use it */
1742 if (MountPoint->SymbolicLinkNameLength != 0)
1743 {
1744 if (MountPoint->SymbolicLinkNameLength > MAXSHORT)
1745 {
1747 }
1748
1752 if (!SymbolicName.Buffer)
1753 {
1755 }
1756
1758 (PWSTR)((ULONG_PTR)MountPoint + MountPoint->SymbolicLinkNameOffset),
1761
1762 /* Query links using it */
1765 }
1766 /* If user provided an unique ID */
1767 else if (MountPoint->UniqueIdLength != 0)
1768 {
1769 UniqueId = AllocatePool(MountPoint->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1770 if (!UniqueId)
1771 {
1773 }
1774
1775 UniqueId->UniqueIdLength = MountPoint->UniqueIdLength;
1776 RtlCopyMemory(UniqueId->UniqueId,
1777 (PVOID)((ULONG_PTR)MountPoint + MountPoint->UniqueIdOffset),
1778 MountPoint->UniqueIdLength);
1779
1780 /* Query links using it */
1781 Status = QueryPointsFromMemory(DeviceExtension, Irp, UniqueId, NULL);
1782 FreePool(UniqueId);
1783 }
1784 /* If caller provided a device name */
1785 else if (MountPoint->DeviceNameLength != 0)
1786 {
1787 if (MountPoint->DeviceNameLength > MAXSHORT)
1788 {
1790 }
1791
1792 DeviceName.Length = MountPoint->DeviceNameLength;
1793 DeviceName.MaximumLength = MountPoint->DeviceNameLength + sizeof(WCHAR);
1794 DeviceName.Buffer = AllocatePool(DeviceName.MaximumLength);
1795 if (!DeviceName.Buffer)
1796 {
1798 }
1799
1801 (PWSTR)((ULONG_PTR)MountPoint + MountPoint->DeviceNameOffset),
1802 DeviceName.Length);
1803 DeviceName.Buffer[DeviceName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1804
1805 /* Query links using it */
1806 Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, &DeviceName);
1807 FreePool(DeviceName.Buffer);
1808 }
1809 else
1810 {
1811 /* Otherwise, query all links */
1812 Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, NULL);
1813 }
1814
1815 return Status;
1816}
1817
1818/*
1819 * @implemented
1820 */
1823 IN PIRP Irp)
1824{
1825 ULONG Link;
1827 BOOLEAN CreateNoDrive;
1829 PMOUNTDEV_UNIQUE_ID UniqueId;
1830 PMOUNTMGR_MOUNT_POINT MountPoint;
1831 PMOUNTMGR_MOUNT_POINTS MountPoints;
1833
1835
1836 /* Validate input */
1837 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1838 {
1840 }
1841
1842 /* Query points */
1843 MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1844 CreateNoDrive = (MountPoint->SymbolicLinkNameOffset && MountPoint->SymbolicLinkNameLength);
1845
1846 Status = MountMgrQueryPoints(DeviceExtension, Irp);
1847 if (!NT_SUCCESS(Status))
1848 {
1849 return Status;
1850 }
1851
1852 /* For all the points matching the request */
1853 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1854 for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1855 {
1859 if (!SymbolicName.Buffer)
1860 {
1862 }
1863
1865 (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1868
1869 /* Create a no drive entry for the drive letters */
1870 if (CreateNoDrive && IsDriveLetter(&SymbolicName))
1871 {
1872 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1873 if (UniqueId)
1874 {
1875 UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1876 RtlCopyMemory(UniqueId->UniqueId,
1877 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1878 MountPoints->MountPoints[Link].UniqueIdLength);
1879
1880 CreateNoDriveLetterEntry(UniqueId);
1881 FreePool(UniqueId);
1882 }
1883 }
1884
1885 /* If there are no link any more, and no need to create a no drive entry */
1886 if (Link == 0 && !CreateNoDrive)
1887 {
1888 /* Then, delete everything */
1889 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength);
1890 if (UniqueId)
1891 {
1892 RtlCopyMemory(UniqueId,
1893 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1894 MountPoints->MountPoints[Link].UniqueIdLength);
1895
1896 DeleteNoDriveLetterEntry(UniqueId);
1897 FreePool(UniqueId);
1898 }
1899 }
1900
1901 /* Delete all the information about the mount point */
1906
1907 /* Notify the change */
1908 DeviceName.Length = DeviceName.MaximumLength =
1909 MountPoints->MountPoints[Link].DeviceNameLength;
1910 DeviceName.Buffer = (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].DeviceNameOffset);
1911 MountMgrNotifyNameChange(DeviceExtension, &DeviceName, TRUE);
1912 }
1913
1914 MountMgrNotify(DeviceExtension);
1915
1916 return Status;
1917}
1918
1919/*
1920 * @implemented
1921 */
1924 IN PIRP Irp)
1925{
1926 ULONG Link;
1929 PMOUNTDEV_UNIQUE_ID UniqueId;
1930 PMOUNTMGR_MOUNT_POINTS MountPoints;
1931
1932 /* Query points */
1933 Status = MountMgrQueryPoints(DeviceExtension, Irp);
1934 if (!NT_SUCCESS(Status))
1935 {
1936 return Status;
1937 }
1938
1939 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1940 if (MountPoints->NumberOfMountPoints == 0)
1941 {
1942 return Status;
1943 }
1944
1945 /* For all the mount points */
1946 for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1947 {
1951 if (!SymbolicName.Buffer)
1952 {
1954 }
1955
1957 (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1960
1961 /* If the only mount point is a drive letter, then create a no letter drive entry */
1962 if (MountPoints->NumberOfMountPoints == 1 && IsDriveLetter(&SymbolicName))
1963 {
1964 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1965 if (UniqueId)
1966 {
1967 UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1968 RtlCopyMemory(UniqueId->UniqueId,
1969 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1970 MountPoints->MountPoints[Link].UniqueIdLength);
1971
1972 CreateNoDriveLetterEntry(UniqueId);
1973 FreePool(UniqueId);
1974 }
1975 }
1976
1977 /* Simply delete mount point from DB */
1981 }
1982
1983 return Status;
1984}
1985
1986/*
1987 * @implemented
1988 */
1991 IN PIRP Irp,
1992 IN NTSTATUS LockStatus,
1993 OUT PUNICODE_STRING SourceDeviceName,
1994 OUT PUNICODE_STRING SourceSymbolicName,
1995 OUT PUNICODE_STRING TargetVolumeName)
1996{
1997 HANDLE Handle;
2001 ULONG Length, SavedLength;
2002 BOOLEAN FOReferenced = FALSE;
2005 PDEVICE_INFORMATION DeviceInformation;
2006 OBJECT_NAME_INFORMATION ObjectNameInfo;
2007 FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
2008 PFILE_NAME_INFORMATION FileNameInfo = NULL;
2009 PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint;
2010 POBJECT_NAME_INFORMATION ObjectNameInfoPtr = NULL;
2011 UNICODE_STRING SourceVolumeName, TargetDeviceName;
2012
2014
2015 /* Validate input */
2016 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_VOLUME_MOUNT_POINT))
2017 {
2019 }
2020
2021 VolumeMountPoint = (PMOUNTMGR_VOLUME_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
2022
2023 if (((ULONG)VolumeMountPoint->SourceVolumeNameLength + VolumeMountPoint->TargetVolumeNameLength) <
2024 Stack->Parameters.DeviceIoControl.InputBufferLength)
2025 {
2027 }
2028
2029 /* Get source volume name */
2030 SourceVolumeName.Length =
2031 SourceVolumeName.MaximumLength = VolumeMountPoint->SourceVolumeNameLength;
2032 SourceVolumeName.Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset);
2033
2035 &SourceVolumeName,
2037 NULL,
2038 NULL);
2039
2040 /* Open it */
2047 if (!NT_SUCCESS(Status))
2048 {
2049 return Status;
2050 }
2051
2052 TargetDeviceName.Buffer = NULL;
2053
2054 /* Query its attributes */
2057 &FsDeviceInfo,
2058 sizeof(FsDeviceInfo),
2060 if (!NT_SUCCESS(Status))
2061 {
2062 goto Cleanup;
2063 }
2064
2065 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 // NOTE: On Win7+, this is handled during driver re-initialization.
2704 DeviceExtension->AutomaticDriveLetter = TRUE;
2705 MountMgrAssignDriveLetters(DeviceExtension);
2706 ReconcileAllDatabasesWithMaster(DeviceExtension);
2707 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 STATUS_PENDING
Definition: d3dkmdt.h:43
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL NTAPI QueryDeviceInformation(_In_ PWCHAR DriveRoot, _Out_ PVOID DeviceInformation, _In_ ULONG BufferSize)
Retrieves disk device information.
Definition: query.c:79
static const WCHAR Cleanup[]
Definition: register.c:80
NTSTATUS CloseRemoteDatabase(IN HANDLE Database)
Definition: database.c:82
NTSTATUS DeleteRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:233
NTSTATUS WaitForRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:371
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c: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:1633
NTSTATUS MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1822
NTSTATUS MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1588
#define MAX_DEVICES
Definition: device.c:28
NTSTATUS MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus)
Definition: device.c:2216
NTSTATUS MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName)
Definition: device.c:708
NTSTATUS MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:221
NTSTATUS MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1438
NTSTATUS NTAPI ScrubRegistryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: device.c:162
NTSTATUS MountMgrChangeNotify(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:37
NTSTATUS MountMgrQueryVolumePaths(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation, IN PLIST_ENTRY DeviceInfoList, OUT PMOUNTMGR_VOLUME_PATHS *VolumePaths, OUT PDEVICE_INFORMATION *FailedDevice)
Definition: device.c:1148
NTSTATUS NTAPI MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: device.c:668
NTSTATUS MountMgrQueryAutoMount(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:136
NTSTATUS MountMgrValidateBackPointer(IN PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry, IN PDEVICE_INFORMATION DeviceInformation, OUT PBOOLEAN Invalid)
Definition: device.c:1040
NTSTATUS MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1923
NTSTATUS MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:288
NTSTATUS MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:621
VOID MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:737
NTSTATUS MountmgrWriteNoAutoMount(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:87
VOID ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:381
NTSTATUS MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus, OUT PUNICODE_STRING SourceDeviceName, OUT PUNICODE_STRING SourceSymbolicName, OUT PUNICODE_STRING TargetVolumeName)
Definition: device.c:1990
NTSTATUS MountMgrCreatePoint(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:249
NTSTATUS MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:814
NTSTATUS MountMgrSetAutoMount(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:103
NTSTATUS MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo)
Definition: device.c:435
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
@ FileNameInformation
Definition: from_kernel.h:70
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
@ FileFsDeviceInformation
Definition: from_kernel.h:222
pRequest Complete(RequestStatus)
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR)
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
IoMarkIrpPending(Irp)
IoSetCancelRoutine(Irp, CancelRoutine)
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:145
NTSTATUS MountMgrQuerySymbolicLink(IN PUNICODE_STRING SymbolicName, IN OUT PUNICODE_STRING LinkTarget)
Definition: symlink.c:849
DRIVER_DISPATCH MountMgrDeviceControl
Definition: mntmgr.h:344
UNICODE_STRING DeviceFloppy
Definition: symlink.c:43
struct _DATABASE_ENTRY DATABASE_ENTRY
NTSTATUS FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:561
#define COLON_POSITION
Definition: mntmgr.h:160
VOID MountMgrNotifyNameChange(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN BOOLEAN ValidateVolume)
Definition: notify.c:328
NTSTATUS MountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName)
Definition: point.c:35
VOID PostOnlineNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName)
Definition: notify.c:122
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:812
UNICODE_STRING DeviceCdRom
Definition: symlink.c:44
#define DRIVE_LETTER_LENGTH
Definition: mntmgr.h:161
NTSTATUS QueryPointsFromSymbolicLinkName(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN PIRP Irp)
Definition: point.c:463
#define LETTER_POSITION
Definition: mntmgr.h:159
VOID NTAPI MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1592
VOID MountMgrNotify(IN PDEVICE_EXTENSION DeviceExtension)
Definition: notify.c:288
VOID WaitForOnlinesToComplete(IN PDEVICE_EXTENSION DeviceExtension)
Definition: notify.c:174
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:626
VOID DeleteSymbolicLinkNameFromMemory(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLink, IN BOOLEAN MarkOffline)
Definition: symlink.c:754
NTSTATUS QueryPointsFromMemory(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL, IN PUNICODE_STRING SymbolicName OPTIONAL)
Definition: point.c:236
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:167
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define FreePool(P)
Definition: mntmgr.h:154
UNICODE_STRING DosDevices
Definition: symlink.c:42
VOID CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:269
BOOLEAN HasNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:354
NTSTATUS MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION Extension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN FromVolume)
Definition: mountmgr.c:855
#define ASSERT(a)
Definition: mode.c:44
#define for
Definition: utility.h:88
struct _MOUNTMGR_MOUNT_POINT * PMOUNTMGR_MOUNT_POINT
#define IOCTL_MOUNTMGR_DELETE_POINTS
Definition: imports.h:122
struct _MOUNTMGR_MOUNT_POINTS * PMOUNTMGR_MOUNT_POINTS
struct _MOUNTMGR_TARGET_NAME * PMOUNTMGR_TARGET_NAME
#define IOCTL_MOUNTMGR_CREATE_POINT
Definition: imports.h:116
#define IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
Definition: imports.h:128
struct _MOUNTMGR_CREATE_POINT_INPUT * PMOUNTMGR_CREATE_POINT_INPUT
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:81
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
Definition: mountmgr.h:147
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
Definition: mountmgr.h:149
struct _MOUNTMGR_CHANGE_NOTIFY_INFO * PMOUNTMGR_CHANGE_NOTIFY_INFO
#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
Definition: mountmgr.h:55
#define IOCTL_MOUNTMGR_QUERY_POINTS
Definition: mountmgr.h:49
@ Enabled
Definition: mountmgr.h:179
struct _MOUNTMGR_QUERY_AUTO_MOUNT * PMOUNTMGR_QUERY_AUTO_MOUNT
struct _MOUNTMGR_VOLUME_PATHS * PMOUNTMGR_VOLUME_PATHS
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED
Definition: mountmgr.h:59
struct _MOUNTMGR_VOLUME_MOUNT_POINT * PMOUNTMGR_VOLUME_MOUNT_POINT
#define IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES
Definition: mountmgr.h:65
struct _MOUNTMGR_DRIVE_LETTER_INFORMATION * PMOUNTMGR_DRIVE_LETTER_INFORMATION
struct _MOUNTMGR_SET_AUTO_MOUNT * PMOUNTMGR_SET_AUTO_MOUNT
#define MOUNTMGR_IS_DRIVE_LETTER(s)
Definition: mountmgr.h:73
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
Definition: mountmgr.h:53
#define IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY
Definition: mountmgr.h:51
#define IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE
Definition: mountmgr.h:63
struct _MOUNTMGR_DRIVE_LETTER_TARGET * PMOUNTMGR_DRIVE_LETTER_TARGET
#define IOCTL_MOUNTMGR_SCRUB_REGISTRY
Definition: mountmgr.h:170
#define IOCTL_MOUNTMGR_CHANGE_NOTIFY
Definition: mountmgr.h:61
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED
Definition: mountmgr.h:57
#define IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT
Definition: mountmgr.h:172
#define IOCTL_MOUNTMGR_SET_AUTO_MOUNT
Definition: mountmgr.h:174
struct _MOUNTMGR_CHANGE_NOTIFY_INFO MOUNTMGR_CHANGE_NOTIFY_INFO
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4677
#define KernelMode
Definition: asm.h:38
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4202
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4203
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_REMOTE_DEVICE
Definition: nt_native.h:811
#define SYNCHRONIZE
Definition: nt_native.h:61
#define REG_BINARY
Definition: nt_native.h:1496
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h:315
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSYSAPI NTSTATUS NTAPI ZwFsControlFile(IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize)
NTSYSAPI NTSTATUS NTAPI ZwQueryVolumeInformationFile(IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass)
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
VOID NTAPI PsSetThreadHardErrorsAreDisabled(IN PETHREAD Thread, IN BOOLEAN HardErrorsAreDisabled)
Definition: thread.c:898
BOOLEAN NTAPI PsGetThreadHardErrorsAreDisabled(IN PETHREAD Thread)
Definition: thread.c:695
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:746
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
#define FILE_DEVICE_VIRTUAL_DISK
Definition: winioctl.h:81
#define REG_DWORD
Definition: sdbapi.c:596
@ Removable
Definition: arc.h:81
@ Output
Definition: arc.h:85
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
base of all file and directory entries
Definition: entries.h:83
Definition: mntmgr.h:96
LIST_ENTRY AssociatedDevicesEntry
Definition: mntmgr.h:97
UNICODE_STRING String
Definition: mntmgr.h:99
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:98
Definition: mntmgr.h:86
USHORT UniqueIdOffset
Definition: mntmgr.h:91
USHORT SymbolicNameLength
Definition: mntmgr.h:90
USHORT UniqueIdLength
Definition: mntmgr.h:92
ULONG EntrySize
Definition: mntmgr.h:87
ULONG EntryReferences
Definition: mntmgr.h:88
USHORT SymbolicNameOffset
Definition: mntmgr.h:89
Definition: mntmgr.h:103
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:105
LIST_ENTRY DeviceInformationEntry
Definition: mntmgr.h:104
BOOLEAN LetterAssigned
Definition: mntmgr.h:55
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
BOOLEAN ManuallyRegistered
Definition: mntmgr.h:53
BOOLEAN KeepLinks
Definition: mntmgr.h:51
UCHAR SuggestedDriveLetter
Definition: mntmgr.h:52
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:49
BOOLEAN SkipNotifications
Definition: mntmgr.h:58
UNICODE_STRING DeviceName
Definition: mntmgr.h:50
LIST_ENTRY ReplicatedUniqueIdsListHead
Definition: mntmgr.h:46
LIST_ENTRY AssociatedDevicesHead
Definition: mntmgr.h:47
LIST_ENTRY SymbolicLinksListHead
Definition: mntmgr.h:45
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT UniqueIdLength
Definition: imports.h:136
UCHAR UniqueId[1]
Definition: imports.h:137
MOUNTMGR_MOUNT_POINT MountPoints[1]
Definition: imports.h:175
USHORT DeviceNameLength
Definition: imports.h:169
USHORT SymbolicLinkNameLength
Definition: imports.h:165
ULONG SymbolicLinkNameOffset
Definition: imports.h:164
MOUNTMGR_AUTO_MOUNT_STATE CurrentState
Definition: mountmgr.h:183
MOUNTMGR_AUTO_MOUNT_STATE NewState
Definition: mountmgr.h:187
UNICODE_STRING Name
Definition: nt_native.h:1270
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:118
PDEVICE_EXTENSION DeviceExtension
Definition: mntmgr.h:117
struct _REPARSE_DATA_BUFFER::@334::@336 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:1665
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292