ReactOS 0.4.16-dev-122-g325d74c
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;
640 if (DriveLetterTarget->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
641 {
643 }
644
645 /* Call the worker */
646 DeviceName.Buffer = DriveLetterTarget->DeviceName;
647 DeviceName.Length =
648 DeviceName.MaximumLength = DriveLetterTarget->DeviceNameLength;
649
651 &DriveLetterInformation);
652 if (NT_SUCCESS(Status))
653 {
654 *(PMOUNTMGR_DRIVE_LETTER_INFORMATION)Irp->AssociatedIrp.SystemBuffer =
655 DriveLetterInformation;
656 Irp->IoStatus.Information = sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION);
657 }
658
659 return Status;
660}
661
662/*
663 * @implemented
664 */
666NTAPI
673{
674 UNICODE_STRING ValueString;
675 PUNICODE_STRING SystemVolumeName;
676
680
681 if (ValueType != REG_SZ)
682 {
683 return STATUS_SUCCESS;
684 }
685
686 RtlInitUnicodeString(&ValueString, ValueData);
687 SystemVolumeName = Context;
688
689 /* Return a string containing system volume name */
690 SystemVolumeName->Length = ValueString.Length;
691 SystemVolumeName->MaximumLength = ValueString.Length + sizeof(WCHAR);
692 SystemVolumeName->Buffer = AllocatePool(SystemVolumeName->MaximumLength);
693 if (SystemVolumeName->Buffer)
694 {
695 RtlCopyMemory(SystemVolumeName->Buffer, ValueData, ValueString.Length);
696 SystemVolumeName->Buffer[ValueString.Length / sizeof(WCHAR)] = UNICODE_NULL;
697 }
698
699 return STATUS_SUCCESS;
700
701}
702
703/*
704 * @implemented
705 */
708{
710
714 QueryTable[0].Name = L"SystemPartition";
715
716 SystemVolumeName->Buffer = NULL;
717
719 L"\\Registry\\Machine\\System\\Setup",
721 SystemVolumeName,
722 NULL);
723
724 if (SystemVolumeName->Buffer)
725 {
726 return STATUS_SUCCESS;
727 }
728
729 return STATUS_UNSUCCESSFUL;
730}
731
732/*
733 * @implemented
734 */
735VOID
737{
739 PLIST_ENTRY NextEntry;
740 UNICODE_STRING SystemVolumeName;
741 PDEVICE_INFORMATION DeviceInformation;
742 MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
743
744 /* First, get system volume name */
745 Status = MountMgrQuerySystemVolumeName(&SystemVolumeName);
746
747 /* If there are no device, it's all done */
748 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
749 {
750 if (NT_SUCCESS(Status))
751 {
752 FreePool(SystemVolumeName.Buffer);
753 }
754
755 return;
756 }
757
758 /* Now, for all the devices... */
759 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
760 NextEntry != &(DeviceExtension->DeviceListHead);
761 NextEntry = NextEntry->Flink)
762 {
763 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
764
765 /* If the device doesn't have a letter assigned, do it! */
766 if (!DeviceInformation->LetterAssigned)
767 {
768 MountMgrNextDriveLetterWorker(DeviceExtension,
769 &(DeviceInformation->DeviceName),
770 &DriveLetterInformation);
771 }
772
773 /* If it's the system volume */
774 if (NT_SUCCESS(Status) && RtlEqualUnicodeString(&SystemVolumeName, &(DeviceInformation->DeviceName), TRUE))
775 {
776 /* Keep track of it */
777 DeviceExtension->DriveLetterData = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength +
778 sizeof(MOUNTDEV_UNIQUE_ID));
779 if (DeviceExtension->DriveLetterData)
780 {
781 RtlCopyMemory(DeviceExtension->DriveLetterData,
782 DeviceInformation->UniqueId,
783 DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
784 }
785
786 /* Ensure it gets mounted if automount is disabled */
787 if (DeviceExtension->NoAutoMount)
788 {
789 /* Temporarily re-enable automount for the
790 * worker to mount and set a drive letter */
791 DeviceExtension->NoAutoMount = FALSE;
792
793 MountMgrNextDriveLetterWorker(DeviceExtension,
794 &(DeviceInformation->DeviceName),
795 &DriveLetterInformation);
796
797 /* And re-disable automount */
798 DeviceExtension->NoAutoMount = TRUE;
799 }
800 }
801 }
802
803 if (NT_SUCCESS(Status))
804 {
805 FreePool(SystemVolumeName.Buffer);
806 }
807}
808
809/*
810 * @implemented
811 */
814 IN PIRP Irp)
815{
817 ULONG DevicesFound;
819 PLIST_ENTRY SymlinksEntry;
822 PWSTR DeviceString, OldBuffer;
823 USHORT DeviceLength, OldLength;
824 PDEVICE_INFORMATION DeviceInformation;
825 PSYMLINK_INFORMATION SymlinkInformation;
827
829
830 /* Validate input size */
831 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
832 {
834 }
835
836 /* Ensure we have received UNICODE_STRING */
837 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
838 if (Target->DeviceNameLength & 1)
839 {
841 }
842
843 /* Validate the entry structure size */
844 if ((FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceNameLength) + Target->DeviceNameLength) >
845 Stack->Parameters.DeviceIoControl.InputBufferLength)
846 {
848 }
849
850 /* Ensure we can at least return needed size */
851 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
852 {
854 }
855
856 /* Construct string for query */
857 SymbolicName.Length = Target->DeviceNameLength;
858 SymbolicName.MaximumLength = Target->DeviceNameLength;
859 SymbolicName.Buffer = Target->DeviceName;
860
861 /* Find device with our info */
862 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
863 if (!NT_SUCCESS(Status))
864 {
865 return Status;
866 }
867
868 DeviceLength = 0;
869 DeviceString = NULL;
870 DevicesFound = 0;
871
872 /* Try to find associated device info */
873 while (TRUE)
874 {
875 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
876 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
877 SymlinksEntry = SymlinksEntry->Flink)
878 {
879 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
880
881 /* Try to find with drive letter */
882 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
883 {
884 break;
885 }
886 }
887
888 /* We didn't find, break */
889 if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
890 {
891 return STATUS_NOT_FOUND;
892 }
893
894 /* It doesn't have associated device, go to fallback method */
895 if (IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
896 {
897 goto TryWithVolumeName;
898 }
899
900 /* Create a string with the information about the device */
901 AssociatedDevice = CONTAINING_RECORD(&(DeviceInformation->SymbolicLinksListHead), ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
902 OldLength = DeviceLength;
903 OldBuffer = DeviceString;
904 DeviceLength += AssociatedDevice->String.Length;
905 DeviceString = AllocatePool(DeviceLength);
906 if (!DeviceString)
907 {
908 if (OldBuffer)
909 {
910 FreePool(OldBuffer);
911 }
912
914 }
915
916 /* Store our info and previous if any */
917 RtlCopyMemory(DeviceString, AssociatedDevice->String.Buffer, AssociatedDevice->String.Length);
918 if (OldBuffer)
919 {
920 RtlCopyMemory(&DeviceString[AssociatedDevice->String.Length / sizeof(WCHAR)], OldBuffer, OldLength);
921 FreePool(OldBuffer);
922 }
923
924 /* Count and continue looking */
925 ++DevicesFound;
926 DeviceInformation = AssociatedDevice->DeviceInformation;
927
928 /* If too many devices, try another way */
929 if (DevicesFound > MAX_DEVICES) /* 1000 */
930 {
931 goto TryWithVolumeName;
932 }
933 }
934
935 /* Reallocate our string, so that we can prepend disk letter */
936 OldBuffer = DeviceString;
937 OldLength = DeviceLength;
938 DeviceLength += 2 * sizeof(WCHAR);
939 DeviceString = AllocatePool(DeviceLength);
940 if (!DeviceString)
941 {
942 if (OldBuffer)
943 {
944 FreePool(OldBuffer);
945 }
946
948 }
949
950 /* Get the letter */
951 DeviceString[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
952 DeviceString[1] = L':';
953
954 /* And copy the rest */
955 if (OldBuffer)
956 {
957 RtlCopyMemory(&DeviceString[2], OldBuffer, OldLength);
958 FreePool(OldBuffer);
959 }
960
961TryWithVolumeName:
962 /* If we didn't find anything, try differently */
963 if (DeviceLength < 2 * sizeof(WCHAR) || DeviceString[1] != L':')
964 {
965 if (DeviceString)
966 {
967 FreePool(DeviceString);
968 DeviceLength = 0;
969 }
970
971 /* Try to find a volume name matching */
972 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
973 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
974 SymlinksEntry = SymlinksEntry->Flink)
975 {
976 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
977
978 if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation->Name))
979 {
980 break;
981 }
982 }
983
984 /* If found copy */
985 if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
986 {
987 DeviceLength = SymlinkInformation->Name.Length;
988 DeviceString = AllocatePool(DeviceLength);
989 if (!DeviceString)
990 {
992 }
993
994 RtlCopyMemory(DeviceString, SymlinkInformation->Name.Buffer, DeviceLength);
995 /* Ensure we are in the right namespace; [1] can be ? */
996 DeviceString[1] = L'\\';
997 }
998 }
999
1000 /* If we found something */
1001 if (DeviceString)
1002 {
1003 /* At least, we will return our length */
1004 ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSzLength = DeviceLength;
1005 /* MOUNTMGR_VOLUME_PATHS is a string + a ULONG */
1006 Irp->IoStatus.Information = DeviceLength + sizeof(ULONG);
1007
1008 /* If we have enough room for copying the string */
1009 if (sizeof(ULONG) + DeviceLength <= Stack->Parameters.DeviceIoControl.OutputBufferLength)
1010 {
1011 /* Copy it */
1012 if (DeviceLength)
1013 {
1014 RtlCopyMemory(((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz, DeviceString, DeviceLength);
1015 }
1016
1017 /* And double zero at its end - this is needed in case of multiple paths which are separated by a single 0 */
1018 FreePool(DeviceString);
1019 ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR)] = 0;
1020 ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR) + 1] = 0;
1021
1022 return STATUS_SUCCESS;
1023 }
1024 else
1025 {
1026 /* Just return appropriate size and leave */
1027 FreePool(DeviceString);
1028 Irp->IoStatus.Information = sizeof(ULONG);
1030 }
1031 }
1032
1033 /* Fail */
1034 return STATUS_NOT_FOUND;
1035}
1036
1037/*
1038 * @implemented
1039 */
1042 IN PDEVICE_INFORMATION DeviceInformation,
1044{
1045 HANDLE Handle;
1047 PLIST_ENTRY SymlinksEntry;
1049 PREPARSE_DATA_BUFFER ReparseData;
1051 UNICODE_STRING FullName, SubstituteName;
1052 PSYMLINK_INFORMATION SymlinkInformation;
1053
1054 /* Initialize & allocate a string big enough to contain our complete mount point name */
1055 FullName.Length = 0;
1056 FullName.MaximumLength = AssociatedDeviceEntry->String.Length
1057 + AssociatedDeviceEntry->DeviceInformation->DeviceName.Length
1058 + sizeof(WCHAR)
1059 + sizeof(UNICODE_NULL);
1061 if (!FullName.Buffer)
1062 {
1064 }
1065
1066 /* Create the path */
1067 RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->DeviceInformation->DeviceName);
1068 FullName.Buffer[FullName.Length / sizeof(WCHAR)] = L'\\';
1069 RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->String);
1071
1072 /* Open it to query the reparse point */
1074 &FullName,
1076 NULL,
1077 NULL);
1084
1085 if (!NT_SUCCESS(Status))
1086 {
1087 *Invalid = TRUE;
1088 return STATUS_SUCCESS;
1089 }
1090
1091 /* Allocate a buffer big enough to read reparse data */
1093 if (ReparseData == NULL)
1094 {
1095 ZwClose(Handle);
1097 }
1098
1099 /* Query reparse data */
1101 NULL, NULL, NULL,
1104 NULL, 0,
1106 ZwClose(Handle);
1107
1108 if (!NT_SUCCESS(Status))
1109 {
1110 FreePool(ReparseData);
1111 *Invalid = TRUE;
1112 return STATUS_SUCCESS;
1113 }
1114
1115 /* Create a string with the substitute name */
1116 SubstituteName.Length = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
1117 SubstituteName.MaximumLength = SubstituteName.Length;
1118 SubstituteName.Buffer = (PWSTR)((ULONG_PTR)ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset);
1119
1120 /* If that's a volume name that matches our associated device, that's a success! */
1121 if (MOUNTMGR_IS_VOLUME_NAME(&SubstituteName))
1122 {
1123 if (SubstituteName.Length == 98 && SubstituteName.Buffer[1] == L'?')
1124 {
1125 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1126 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
1127 SymlinksEntry = SymlinksEntry->Flink)
1128 {
1129 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1130
1131 if (RtlEqualUnicodeString(&SubstituteName, &SymlinkInformation->Name, TRUE))
1132 {
1133 FreePool(ReparseData);
1134 return STATUS_SUCCESS;
1135 }
1136 }
1137 }
1138 }
1139
1140 FreePool(ReparseData);
1141 *Invalid = TRUE;
1142 return STATUS_SUCCESS;
1143}
1144
1145/*
1146 * @implemented
1147 */
1150 IN PDEVICE_INFORMATION DeviceInformation,
1151 IN PLIST_ENTRY DeviceInfoList,
1152 OUT PMOUNTMGR_VOLUME_PATHS * VolumePaths,
1153 OUT PDEVICE_INFORMATION *FailedDevice)
1154{
1155 ULONG Written;
1158 PSYMLINK_INFORMATION SymlinkInformation;
1159 PDEVICE_INFORMATION_ENTRY DeviceInfoEntry;
1160 PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry;
1161 PMOUNTMGR_VOLUME_PATHS * Paths = NULL, * CurrentPath;
1162 ULONG OutputPathLength, NumberOfPaths, ReturnedPaths;
1163
1164 /* We return at least null char */
1165 OutputPathLength = sizeof(UNICODE_NULL);
1166
1167 for (Entry = DeviceInformation->SymbolicLinksListHead.Flink;
1168 Entry != &(DeviceInformation->SymbolicLinksListHead);
1169 Entry = Entry->Flink)
1170 {
1171 SymlinkInformation = CONTAINING_RECORD(Entry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1172
1173 /* Try to find the drive letter (ie, DOS device) */
1174 if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
1175 {
1176 /* We'll return the letter */
1177 OutputPathLength = 4 * sizeof(WCHAR);
1178 break;
1179 }
1180 }
1181
1182 /* We didn't find any */
1183 if (Entry == &(DeviceInformation->SymbolicLinksListHead))
1184 {
1185 SymlinkInformation = NULL;
1186 }
1187
1188 /* Do we have any device info to return? */
1189 for (Entry = DeviceInfoList->Flink; Entry != DeviceInfoList; Entry = Entry->Flink)
1190 {
1191 DeviceInfoEntry = CONTAINING_RECORD(Entry, DEVICE_INFORMATION_ENTRY, DeviceInformationEntry);
1192
1193 /* Matching current device */
1194 if (DeviceInfoEntry->DeviceInformation == DeviceInformation)
1195 {
1196 /* Allocate the output buffer */
1197 *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1198 if (*VolumePaths == NULL)
1199 {
1201 }
1202
1203 /* Set size */
1204 (*VolumePaths)->MultiSzLength = OutputPathLength;
1205 /* If we have a drive letter, return it */
1206 if (SymlinkInformation != NULL)
1207 {
1208 (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1209 (*VolumePaths)->MultiSz[1] = L':';
1210 (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1211 (*VolumePaths)->MultiSz[3] = UNICODE_NULL;
1212 }
1213 else
1214 {
1215 (*VolumePaths)->MultiSz[0] = UNICODE_NULL;
1216 }
1217
1218 return STATUS_SUCCESS;
1219 }
1220 }
1221
1222 /* Allocate a new device entry */
1223 DeviceInfoEntry = AllocatePool(sizeof(DEVICE_INFORMATION_ENTRY));
1224 if (DeviceInfoEntry == NULL)
1225 {
1227 }
1228
1229 /* Add it to the list */
1230 DeviceInfoEntry->DeviceInformation = DeviceInformation;
1231 InsertTailList(DeviceInfoList, &DeviceInfoEntry->DeviceInformationEntry);
1232
1233 NumberOfPaths = 0;
1234 /* Count the amount of devices we will have to handle */
1235 if (!IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
1236 {
1237 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1238 Entry != &DeviceInformation->AssociatedDevicesHead;
1239 Entry = Entry->Flink)
1240 {
1241 ++NumberOfPaths;
1242 }
1243
1244 ASSERT(NumberOfPaths != 0);
1245 /* And allocate a big enough buffer */
1246 Paths = AllocatePool(NumberOfPaths * sizeof(PMOUNTMGR_VOLUME_PATHS));
1247 if (Paths == NULL)
1248 {
1249 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1250 FreePool(DeviceInfoEntry);
1252 }
1253 }
1254
1255 /* Start the hot loop to gather all the paths and be able to compute total output length! */
1256 ReturnedPaths = 0;
1257 CurrentPath = Paths;
1258 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1259 Entry != &DeviceInformation->AssociatedDevicesHead;
1260 Entry = Entry->Flink)
1261 {
1262 USHORT InnerStrings;
1264
1265 AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1266
1267 /* Validate the fact its a mount point by query reparse data */
1268 Status = MountMgrValidateBackPointer(AssociatedDeviceEntry, DeviceInformation, &Invalid);
1269
1270 /* If we found an invalid device, that's a failure */
1271 if (Invalid)
1272 {
1273 *FailedDevice = AssociatedDeviceEntry->DeviceInformation;
1275 }
1276
1277 /* Check whether we failed, if so, bail out */
1278 if (!NT_SUCCESS(Status))
1279 {
1280 ULONG i;
1281
1282 for (i = 0; i < ReturnedPaths; ++i)
1283 {
1284 FreePool(Paths[i]);
1285 }
1286
1287 if (Paths != NULL)
1288 {
1289 FreePool(Paths);
1290 }
1291 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1292 FreePool(DeviceInfoEntry);
1293 return Status;
1294 }
1295
1296 /* Query associated paths (hello ourselves :-)) */
1297 Status = MountMgrQueryVolumePaths(DeviceExtension,
1298 AssociatedDeviceEntry->DeviceInformation,
1299 DeviceInfoList,
1300 CurrentPath,
1301 FailedDevice);
1302 if (!NT_SUCCESS(Status))
1303 {
1304 ULONG i;
1305
1306 for (i = 0; i < ReturnedPaths; ++i)
1307 {
1308 FreePool(Paths[i]);
1309 }
1310
1311 if (Paths != NULL)
1312 {
1313 FreePool(Paths);
1314 }
1315 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1316 FreePool(DeviceInfoEntry);
1317 return Status;
1318 }
1319
1320 /* Count the number of strings we have in the multi string buffer */
1321 InnerStrings = 0;
1322 if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1323 {
1324 ULONG i;
1325 PWSTR MultiSz = (*CurrentPath)->MultiSz;
1326
1327 for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR); ++i, ++MultiSz)
1328 {
1329 if (*MultiSz == UNICODE_NULL)
1330 {
1331 ++InnerStrings;
1332 }
1333 }
1334 }
1335
1336 /* We returned one more path (ie, one more allocated buffer) */
1337 ++ReturnedPaths;
1338 /* Move the next pointer to use in the array */
1339 ++CurrentPath;
1340 /* Multiply String.Length by the number of found paths, we always add it after a path */
1341 OutputPathLength += (*CurrentPath)->MultiSzLength + InnerStrings * AssociatedDeviceEntry->String.Length - sizeof(UNICODE_NULL);
1342 }
1343
1344 /* Allocate the output buffer */
1345 *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1346 if (*VolumePaths == NULL)
1347 {
1348 ULONG i;
1349
1350 for (i = 0; i < ReturnedPaths; ++i)
1351 {
1352 FreePool(Paths[i]);
1353 }
1354
1355 if (Paths != NULL)
1356 {
1357 FreePool(Paths);
1358 }
1359 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1360 FreePool(DeviceInfoEntry);
1362 }
1363
1364 Written = 0;
1365 /* If we had found a DOS letter, that's the first thing we return */
1366 (*VolumePaths)->MultiSzLength = OutputPathLength;
1367 if (SymlinkInformation != NULL)
1368 {
1369 (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1370 (*VolumePaths)->MultiSz[1] = L':';
1371 (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1372 Written = 3;
1373 }
1374
1375 /* Now, browse again all our paths to return them */
1376 CurrentPath = Paths;
1377 for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1378 Entry != &DeviceInformation->AssociatedDevicesHead;
1379 Entry = Entry->Flink)
1380 {
1381 AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1382
1383 /* If we had a path... */
1384 if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1385 {
1386 ULONG i, Offset;
1387 PWSTR MultiSz;
1388
1389 /* This offset is used to "jump" into MultiSz, so, start with the string begin (ie, skip MultiSzLength) */
1390 Offset = sizeof(ULONG);
1391 /* Browse every single letter, and skip last UNICODE_NULL */
1392 for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR) - 1; ++i)
1393 {
1394 /* Get the letter */
1395 MultiSz = (PWSTR)((ULONG_PTR)(*CurrentPath) + Offset);
1396 /* If it was part of the path, just return it */
1397 if (*MultiSz != UNICODE_NULL)
1398 {
1399 (*VolumePaths)->MultiSz[Written] = *MultiSz;
1400 }
1401 else
1402 {
1403 /* Otherwise, as planed, return our whole associated device name */
1404 RtlCopyMemory(&(*VolumePaths)->MultiSz[Written],
1405 AssociatedDeviceEntry->String.Buffer,
1406 AssociatedDeviceEntry->String.Length);
1407 Written += AssociatedDeviceEntry->String.Length / sizeof(WCHAR);
1408 /* And don't forget to nullify */
1409 (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1410 }
1411
1412 /* We at least return a letter or a null char */
1413 ++Written;
1414 /* Move to the next letter */
1415 Offset += sizeof(WCHAR);
1416 }
1417 }
1418
1419 FreePool(*CurrentPath);
1420 ++CurrentPath;
1421 }
1422
1423 /* MultiSz: don't forget last null char */
1424 (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1425 /* Cleanup everything and return success! */
1426 if (Paths != NULL)
1427 {
1428 FreePool(Paths);
1429 }
1430 RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1431 FreePool(DeviceInfoEntry);
1432 return STATUS_SUCCESS;
1433}
1434
1435/*
1436 * @implemented
1437 */
1440 IN PIRP Irp)
1441{
1444 LIST_ENTRY Devices;
1445 BOOLEAN NeedNotification;
1448 ULONG Attempts, OutputLength;
1451 RECONCILE_WORK_ITEM_CONTEXT ReconcileContext;
1452 PDEVICE_INFORMATION DeviceInformation, ListDeviceInfo, FailedDevice;
1453
1455
1456 /* Validate input size */
1457 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1458 {
1460 }
1461
1462 /* Ensure we have received UNICODE_STRING */
1463 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1464 if (Target->DeviceNameLength & 1)
1465 {
1467 }
1468
1469 /* Validate the entry structure size */
1470 if (Target->DeviceNameLength + FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1471 {
1473 }
1474
1475 /* Ensure we can at least return needed size */
1476 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
1477 {
1479 }
1480
1481 /* Construct string for query */
1482 SymbolicName.Length = Target->DeviceNameLength;
1483 SymbolicName.MaximumLength = Target->DeviceNameLength + sizeof(UNICODE_NULL);
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 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 = Output->MultiSzLength + sizeof(ULONG);
1568
1569 /* If it cannot fit, just return need size and quit */
1570 if (OutputLength > Stack->Parameters.DeviceIoControl.OutputBufferLength)
1571 {
1572 Irp->IoStatus.Information = sizeof(ULONG);
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 (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1607 {
1609 }
1610
1612 SymbolicName.MaximumLength = Target->DeviceNameLength;
1613 SymbolicName.Buffer = Target->DeviceName;
1614
1615 /* Find the associated device */
1616 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1617 if (!NT_SUCCESS(Status))
1618 {
1619 return Status;
1620 }
1621
1622 /* Mark we want to keep links */
1623 DeviceInformation->KeepLinks = TRUE;
1624
1625 return STATUS_SUCCESS;
1626}
1627
1628/*
1629 * @implemented
1630 */
1633 IN PIRP Irp)
1634{
1636 BOOLEAN OldState;
1640
1642
1643 /* Validate input */
1644 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1645 {
1647 }
1648
1649 Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1650 if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1651 {
1653 }
1654
1656 SymbolicName.MaximumLength = Target->DeviceNameLength;
1657 SymbolicName.Buffer = Target->DeviceName;
1658
1659 /* Disable hard errors */
1662
1663 /* Call real worker */
1665
1667
1668 return Status;
1669}
1670
1671/*
1672 * @implemented
1673 */
1676 IN PIRP Irp)
1677{
1680 PMOUNTDEV_UNIQUE_ID UniqueId;
1681 PMOUNTMGR_MOUNT_POINT MountPoint;
1683
1685
1686 /* Validate input... */
1687 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1688 {
1690 }
1691
1692 MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1693 if (!MountPoint->SymbolicLinkNameLength)
1694 {
1695 MountPoint->SymbolicLinkNameOffset = 0;
1696 }
1697
1698 if (!MountPoint->UniqueIdLength)
1699 {
1700 MountPoint->UniqueIdOffset = 0;
1701 }
1702
1703 if (!MountPoint->DeviceNameLength)
1704 {
1705 MountPoint->DeviceNameOffset = 0;
1706 }
1707
1708 /* Addresses can't be odd */
1709 if ((MountPoint->SymbolicLinkNameOffset & 1) ||
1710 (MountPoint->SymbolicLinkNameLength & 1))
1711 {
1713 }
1714
1715 if ((MountPoint->UniqueIdOffset & 1) ||
1716 (MountPoint->UniqueIdLength & 1))
1717 {
1719 }
1720
1721 if ((MountPoint->DeviceNameOffset & 1) ||
1722 (MountPoint->DeviceNameLength & 1))
1723 {
1725 }
1726
1727 /* We can't go beyond */
1728 if (((ULONG)MountPoint->SymbolicLinkNameLength + MountPoint->UniqueIdLength +
1729 MountPoint->DeviceNameLength) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1730 {
1732 }
1733
1734 if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_MOUNT_POINTS))
1735 {
1737 }
1738
1739 /* If caller provided a Symlink, use it */
1740 if (MountPoint->SymbolicLinkNameLength != 0)
1741 {
1742 if (MountPoint->SymbolicLinkNameLength > MAXSHORT)
1743 {
1745 }
1746
1750 if (!SymbolicName.Buffer)
1751 {
1753 }
1754
1756 (PWSTR)((ULONG_PTR)MountPoint + MountPoint->SymbolicLinkNameOffset),
1759
1760 /* Query links using it */
1763 }
1764 /* If user provided an unique ID */
1765 else if (MountPoint->UniqueIdLength != 0)
1766 {
1767 UniqueId = AllocatePool(MountPoint->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1768 if (!UniqueId)
1769 {
1771 }
1772
1773 UniqueId->UniqueIdLength = MountPoint->UniqueIdLength;
1774 RtlCopyMemory(UniqueId->UniqueId,
1775 (PVOID)((ULONG_PTR)MountPoint + MountPoint->UniqueIdOffset),
1776 MountPoint->UniqueIdLength);
1777
1778 /* Query links using it */
1779 Status = QueryPointsFromMemory(DeviceExtension, Irp, UniqueId, NULL);
1780 FreePool(UniqueId);
1781 }
1782 /* If caller provided a device name */
1783 else if (MountPoint->DeviceNameLength != 0)
1784 {
1785 if (MountPoint->DeviceNameLength > MAXSHORT)
1786 {
1788 }
1789
1790 DeviceName.Length = MountPoint->DeviceNameLength;
1791 DeviceName.MaximumLength = MountPoint->DeviceNameLength + sizeof(WCHAR);
1792 DeviceName.Buffer = AllocatePool(DeviceName.MaximumLength);
1793 if (!DeviceName.Buffer)
1794 {
1796 }
1797
1799 (PWSTR)((ULONG_PTR)MountPoint + MountPoint->DeviceNameOffset),
1800 DeviceName.Length);
1801 DeviceName.Buffer[DeviceName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1802
1803 /* Query links using it */
1804 Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, &DeviceName);
1805 FreePool(DeviceName.Buffer);
1806 }
1807 else
1808 {
1809 /* Otherwise, query all links */
1810 Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, NULL);
1811 }
1812
1813 return Status;
1814}
1815
1816/*
1817 * @implemented
1818 */
1821 IN PIRP Irp)
1822{
1823 ULONG Link;
1825 BOOLEAN CreateNoDrive;
1827 PMOUNTDEV_UNIQUE_ID UniqueId;
1828 PMOUNTMGR_MOUNT_POINT MountPoint;
1829 PMOUNTMGR_MOUNT_POINTS MountPoints;
1831
1833
1834 /* Validate input */
1835 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1836 {
1838 }
1839
1840 /* Query points */
1841 MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1842 CreateNoDrive = (MountPoint->SymbolicLinkNameOffset && MountPoint->SymbolicLinkNameLength);
1843
1844 Status = MountMgrQueryPoints(DeviceExtension, Irp);
1845 if (!NT_SUCCESS(Status))
1846 {
1847 return Status;
1848 }
1849
1850 /* For all the points matching the request */
1851 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1852 for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1853 {
1857 if (!SymbolicName.Buffer)
1858 {
1860 }
1861
1863 (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1866
1867 /* Create a no drive entry for the drive letters */
1868 if (CreateNoDrive && IsDriveLetter(&SymbolicName))
1869 {
1870 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1871 if (UniqueId)
1872 {
1873 UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1874 RtlCopyMemory(UniqueId->UniqueId,
1875 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1876 MountPoints->MountPoints[Link].UniqueIdLength);
1877
1878 CreateNoDriveLetterEntry(UniqueId);
1879 FreePool(UniqueId);
1880 }
1881 }
1882
1883 /* If there are no link any more, and no need to create a no drive entry */
1884 if (Link == 0 && !CreateNoDrive)
1885 {
1886 /* Then, delete everything */
1887 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength);
1888 if (UniqueId)
1889 {
1890 RtlCopyMemory(UniqueId,
1891 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1892 MountPoints->MountPoints[Link].UniqueIdLength);
1893
1894 DeleteNoDriveLetterEntry(UniqueId);
1895 FreePool(UniqueId);
1896 }
1897 }
1898
1899 /* Delete all the information about the mount point */
1904
1905 /* Notify the change */
1906 DeviceName.Length = DeviceName.MaximumLength =
1907 MountPoints->MountPoints[Link].DeviceNameLength;
1908 DeviceName.Buffer = (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].DeviceNameOffset);
1909 MountMgrNotifyNameChange(DeviceExtension, &DeviceName, TRUE);
1910 }
1911
1912 MountMgrNotify(DeviceExtension);
1913
1914 return Status;
1915}
1916
1917/*
1918 * @implemented
1919 */
1922 IN PIRP Irp)
1923{
1924 ULONG Link;
1927 PMOUNTDEV_UNIQUE_ID UniqueId;
1928 PMOUNTMGR_MOUNT_POINTS MountPoints;
1929
1930 /* Query points */
1931 Status = MountMgrQueryPoints(DeviceExtension, Irp);
1932 if (!NT_SUCCESS(Status))
1933 {
1934 return Status;
1935 }
1936
1937 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1938 if (MountPoints->NumberOfMountPoints == 0)
1939 {
1940 return Status;
1941 }
1942
1943 /* For all the mount points */
1944 for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1945 {
1949 if (!SymbolicName.Buffer)
1950 {
1952 }
1953
1955 (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1958
1959 /* If the only mount point is a drive letter, then create a no letter drive entry */
1960 if (MountPoints->NumberOfMountPoints == 1 && IsDriveLetter(&SymbolicName))
1961 {
1962 UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1963 if (UniqueId)
1964 {
1965 UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1966 RtlCopyMemory(UniqueId->UniqueId,
1967 (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1968 MountPoints->MountPoints[Link].UniqueIdLength);
1969
1970 CreateNoDriveLetterEntry(UniqueId);
1971 FreePool(UniqueId);
1972 }
1973 }
1974
1975 /* Simply delete mount point from DB */
1979 }
1980
1981 return Status;
1982}
1983
1984/*
1985 * @implemented
1986 */
1989 IN PIRP Irp,
1990 IN NTSTATUS LockStatus,
1991 OUT PUNICODE_STRING SourceDeviceName,
1992 OUT PUNICODE_STRING SourceSymbolicName,
1993 OUT PUNICODE_STRING TargetVolumeName)
1994{
1995 HANDLE Handle;
1999 ULONG Length, SavedLength;
2000 BOOLEAN FOReferenced = FALSE;
2003 PDEVICE_INFORMATION DeviceInformation;
2004 OBJECT_NAME_INFORMATION ObjectNameInfo;
2005 FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
2006 PFILE_NAME_INFORMATION FileNameInfo = NULL;
2007 PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint;
2008 POBJECT_NAME_INFORMATION ObjectNameInfoPtr = NULL;
2009 UNICODE_STRING SourceVolumeName, TargetDeviceName;
2010
2012
2013 /* Validate input */
2014 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_VOLUME_MOUNT_POINT))
2015 {
2017 }
2018
2019 VolumeMountPoint = (PMOUNTMGR_VOLUME_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
2020
2021 if (((ULONG)VolumeMountPoint->SourceVolumeNameLength + VolumeMountPoint->TargetVolumeNameLength) <
2022 Stack->Parameters.DeviceIoControl.InputBufferLength)
2023 {
2025 }
2026
2027 /* Get source volume name */
2028 SourceVolumeName.Length =
2029 SourceVolumeName.MaximumLength = VolumeMountPoint->SourceVolumeNameLength;
2030 SourceVolumeName.Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset);
2031
2033 &SourceVolumeName,
2035 NULL,
2036 NULL);
2037
2038 /* Open it */
2045 if (!NT_SUCCESS(Status))
2046 {
2047 return Status;
2048 }
2049
2050 TargetDeviceName.Buffer = NULL;
2051
2052 /* Query its attributes */
2055 &FsDeviceInfo,
2056 sizeof(FsDeviceInfo),
2058 if (!NT_SUCCESS(Status))
2059 {
2060 goto Cleanup;
2061 }
2062
2063 if (FsDeviceInfo.DeviceType != FILE_DEVICE_DISK && FsDeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK)
2064 {
2065 goto Cleanup;
2066 }
2067
2069 {
2070 goto Cleanup;
2071 }
2072
2073 /* Reference it */
2075 if (!NT_SUCCESS(Status))
2076 {
2077 goto Cleanup;
2078 }
2079 FOReferenced = TRUE;
2080
2081 /* Get file name */
2082 FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION));
2083 if (!FileNameInfo)
2084 {
2086 goto Cleanup;
2087 }
2088
2089 Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2090 sizeof(FILE_NAME_INFORMATION),
2093 {
2094 /* Now we have real length, use it */
2095 Length = FileNameInfo->FileNameLength;
2096 FreePool(FileNameInfo);
2097
2098 FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + Length);
2099 if (!FileNameInfo)
2100 {
2102 goto Cleanup;
2103 }
2104
2105 /* Really query file name */
2106 Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2107 sizeof(FILE_NAME_INFORMATION) + Length,
2109 }
2110
2111 if (!NT_SUCCESS(Status))
2112 {
2113 goto Cleanup;
2114 }
2115
2116 /* Get symbolic name */
2117 ObjectNameInfoPtr = &ObjectNameInfo;
2118 SavedLength = sizeof(OBJECT_NAME_INFORMATION);
2119 Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, sizeof(OBJECT_NAME_INFORMATION), &Length);
2121 {
2122 /* Once again, with proper size, it works better */
2123 ObjectNameInfoPtr = AllocatePool(Length);
2124 if (!ObjectNameInfoPtr)
2125 {
2127 goto Cleanup;
2128 }
2129
2130 SavedLength = Length;
2131 Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, SavedLength, &Length);
2132 }
2133
2134 if (!NT_SUCCESS(Status))
2135 {
2136 goto Cleanup;
2137 }
2138
2139 /* Now, query the device name */
2140 Status = QueryDeviceInformation(&ObjectNameInfoPtr->Name, SourceDeviceName,
2141 NULL, NULL, NULL, NULL, NULL, NULL);
2142 if (!NT_SUCCESS(Status))
2143 {
2144 goto Cleanup;
2145 }
2146
2147 /* For target volume name, use input */
2148 TargetVolumeName->Length =
2149 TargetVolumeName->MaximumLength = VolumeMountPoint->TargetVolumeNameLength;
2150 TargetVolumeName->Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset);
2151
2152 /* Query its device name */
2153 Status = QueryDeviceInformation(TargetVolumeName, &TargetDeviceName,
2154 NULL, NULL, NULL, NULL, NULL, NULL);
2155 if (!NT_SUCCESS(Status))
2156 {
2157 goto Cleanup;
2158 }
2159
2160 /* Return symbolic name */
2161 SourceSymbolicName->Length =
2162 SourceSymbolicName->MaximumLength = (USHORT)FileNameInfo->FileNameLength;
2163 SourceSymbolicName->Buffer = (PWSTR)FileNameInfo;
2164 /* memmove allows memory overlap */
2165 RtlMoveMemory(SourceSymbolicName->Buffer, FileNameInfo->FileName, SourceSymbolicName->Length);
2166 FileNameInfo = NULL;
2167
2168 /* Notify the change */
2169 MountMgrNotify(DeviceExtension);
2170 MountMgrNotifyNameChange(DeviceExtension, &TargetDeviceName, TRUE);
2171
2172 /* If we are locked, sync databases if possible */
2173 if (NT_SUCCESS(LockStatus))
2174 {
2175 Status = FindDeviceInfo(DeviceExtension, SourceDeviceName, FALSE, &DeviceInformation);
2176 if (NT_SUCCESS(Status))
2177 {
2178 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
2179 }
2180 else
2181 {
2183 }
2184 }
2185
2186Cleanup:
2187 if (TargetDeviceName.Buffer)
2188 {
2189 FreePool(TargetDeviceName.Buffer);
2190 }
2191
2192 if (ObjectNameInfoPtr && ObjectNameInfoPtr != &ObjectNameInfo)
2193 {
2194 FreePool(ObjectNameInfoPtr);
2195 }
2196
2197 if (FileNameInfo)
2198 {
2199 FreePool(FileNameInfo);
2200 }
2201
2202 if (FOReferenced)
2203 {
2205 }
2206
2207 return Status;
2208}
2209
2210/*
2211 * @implemented
2212 */
2215 IN PIRP Irp,
2216 IN NTSTATUS LockStatus)
2217{
2218 LONG Offset;
2219 BOOLEAN Found;
2222 PMOUNTDEV_UNIQUE_ID UniqueId;
2223 PDATABASE_ENTRY DatabaseEntry;
2224 PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2225 PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2226 UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2227
2228 /* Initialize string */
2229 LinkTarget.Length = 0;
2232 if (LinkTarget.Buffer == NULL)
2233 {
2235 }
2236
2237 /* If the mount point was created, then, it changed!
2238 * Also use it to query some information
2239 */
2240 Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2241 /* Pending means DB are under synchronization, bail out */
2242 if (Status == STATUS_PENDING)
2243 {
2245 FreePool(SourceDeviceName.Buffer);
2246 FreePool(SourceSymbolicName.Buffer);
2247 return STATUS_SUCCESS;
2248 }
2249 else if (!NT_SUCCESS(Status))
2250 {
2252 return Status;
2253 }
2254
2255 /* Query the device information */
2256 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2257 if (!NT_SUCCESS(Status))
2258 {
2259 /* If it failed, first try to get volume name */
2260 Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2261 if (!NT_SUCCESS(Status))
2262 {
2263 /* Then, try to read the symlink */
2264 Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2265 if (!NT_SUCCESS(Status))
2266 {
2268 FreePool(SourceDeviceName.Buffer);
2269 FreePool(SourceSymbolicName.Buffer);
2270 return Status;
2271 }
2272 }
2273 else
2274 {
2276 }
2277
2278 FreePool(SourceDeviceName.Buffer);
2279
2280 SourceDeviceName.Length = LinkTarget.Length;
2281 SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2282 SourceDeviceName.Buffer = LinkTarget.Buffer;
2283
2284 /* Now that we have the correct source, reattempt to query information */
2285 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2286 if (!NT_SUCCESS(Status))
2287 {
2288 FreePool(SourceDeviceName.Buffer);
2289 FreePool(SourceSymbolicName.Buffer);
2290 return Status;
2291 }
2292 }
2293
2294 FreePool(SourceDeviceName.Buffer);
2295
2296 /* Get information about target device */
2297 Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2298 if (!NT_SUCCESS(Status))
2299 {
2300 FreePool(SourceSymbolicName.Buffer);
2301 return Status;
2302 }
2303
2304 /* Notify if not disabled */
2305 if (!TargetDeviceInformation->SkipNotifications)
2306 {
2307 PostOnlineNotification(DeviceExtension, &TargetDeviceInformation->SymbolicName);
2308 }
2309
2310 /* Open the remote database */
2311 RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2312 if (RemoteDatabase == 0)
2313 {
2314 FreePool(SourceSymbolicName.Buffer);
2316 }
2317
2318 /* Browse all the entries */
2319 Offset = 0;
2320 Found = FALSE;
2321 for (;;)
2322 {
2324 if (DatabaseEntry == NULL)
2325 {
2326 break;
2327 }
2328
2329 /* Try to find ourselves */
2330 DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2331 DbName.Length = DbName.MaximumLength;
2332 DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2333 if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2334 {
2335 /* Reference ourselves and update the entry */
2336 ++DatabaseEntry->EntryReferences;
2338 FreePool(DatabaseEntry);
2339 Found = TRUE;
2340 break;
2341 }
2342
2343 Offset += DatabaseEntry->EntrySize;
2344 FreePool(DatabaseEntry);
2345 }
2346
2347 /* We couldn't find ourselves, we'll have to add ourselves */
2348 if (!Found)
2349 {
2351 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2352
2353 /* Query the device unique ID */
2354 Status = QueryDeviceInformation(&TargetVolumeName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
2355 if (!NT_SUCCESS(Status))
2356 {
2357 FreePool(SourceSymbolicName.Buffer);
2359 return Status;
2360 }
2361
2362 /* Allocate a database entry */
2363 EntrySize = UniqueId->UniqueIdLength + TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2364 DatabaseEntry = AllocatePool(EntrySize);
2365 if (DatabaseEntry == NULL)
2366 {
2367 FreePool(UniqueId);
2368 FreePool(SourceSymbolicName.Buffer);
2371 }
2372
2373 /* Fill it in */
2374 DatabaseEntry->EntrySize = EntrySize;
2375 DatabaseEntry->EntryReferences = 1;
2376 DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
2377 DatabaseEntry->SymbolicNameLength = TargetVolumeName.Length;
2378 DatabaseEntry->UniqueIdOffset = TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2379 DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
2380 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + sizeof(DATABASE_ENTRY)), TargetVolumeName.Buffer, DatabaseEntry->SymbolicNameLength);
2381 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
2382
2383 /* And write it down */
2385 FreePool(DatabaseEntry);
2386 if (!NT_SUCCESS(Status))
2387 {
2388 FreePool(UniqueId);
2389 FreePool(SourceSymbolicName.Buffer);
2391 return Status;
2392 }
2393
2394 /* And now, allocate an Unique ID item */
2395 UniqueIdReplicate = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
2396 if (UniqueIdReplicate == NULL)
2397 {
2398 FreePool(UniqueId);
2399 FreePool(SourceSymbolicName.Buffer);
2401 return Status;
2402 }
2403
2404 /* To associate it with the device */
2405 UniqueIdReplicate->UniqueId = UniqueId;
2406 InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2407 }
2408
2409 /* We're done with the remote database */
2411
2412 /* Check we were find writing the entry */
2413 if (!NT_SUCCESS(Status))
2414 {
2415 FreePool(SourceSymbolicName.Buffer);
2416 return Status;
2417 }
2418
2419 /* This is the end, allocate an associated entry */
2420 AssociatedEntry = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY));
2421 if (AssociatedEntry == NULL)
2422 {
2423 FreePool(SourceSymbolicName.Buffer);
2425 }
2426
2427 /* Initialize its source name string */
2428 AssociatedEntry->String.Length = SourceSymbolicName.Length;
2429 AssociatedEntry->String.MaximumLength = AssociatedEntry->String.Length + sizeof(UNICODE_NULL);
2430 AssociatedEntry->String.Buffer = AllocatePool(AssociatedEntry->String.MaximumLength);
2431 if (AssociatedEntry->String.Buffer == NULL)
2432 {
2433 FreePool(AssociatedEntry);
2434 FreePool(SourceSymbolicName.Buffer);
2436 }
2437
2438 /* Copy data & insert in list */
2439 RtlCopyMemory(AssociatedEntry->String.Buffer, SourceSymbolicName.Buffer, SourceSymbolicName.Length);
2440 AssociatedEntry->String.Buffer[SourceSymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
2441 AssociatedEntry->DeviceInformation = DeviceInformation;
2442 InsertTailList(&TargetDeviceInformation->AssociatedDevicesHead, &AssociatedEntry->AssociatedDevicesEntry);
2443
2444 /* We're done! */
2445 FreePool(SourceSymbolicName.Buffer);
2446 return STATUS_SUCCESS;
2447}
2448
2449/*
2450 * @implemented
2451 */
2454 IN PIRP Irp,
2455 IN NTSTATUS LockStatus)
2456{
2457 LONG Offset;
2461 PDATABASE_ENTRY DatabaseEntry;
2462 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2463 PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2464 PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2465 UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2466
2467 /* Initialize string */
2468 LinkTarget.Length = 0;
2471 if (LinkTarget.Buffer == NULL)
2472 {
2474 }
2475
2476 /* If the mount point was deleted, then, it changed!
2477 * Also use it to query some information
2478 */
2479 Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2480 /* Pending means DB are under synchronization, bail out */
2481 if (Status == STATUS_PENDING)
2482 {
2484 FreePool(SourceDeviceName.Buffer);
2485 FreePool(SourceSymbolicName.Buffer);
2486 return STATUS_SUCCESS;
2487 }
2488 else if (!NT_SUCCESS(Status))
2489 {
2491 return Status;
2492 }
2493
2494 /* Query the device information */
2495 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2496 if (!NT_SUCCESS(Status))
2497 {
2498 /* If it failed, first try to get volume name */
2499 Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2500 if (!NT_SUCCESS(Status))
2501 {
2502 /* Then, try to read the symlink */
2503 Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2504 if (!NT_SUCCESS(Status))
2505 {
2507 FreePool(SourceDeviceName.Buffer);
2508 FreePool(SourceSymbolicName.Buffer);
2509 return Status;
2510 }
2511 }
2512 else
2513 {
2515 }
2516
2517 FreePool(SourceDeviceName.Buffer);
2518
2519 SourceDeviceName.Length = LinkTarget.Length;
2520 SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2521 SourceDeviceName.Buffer = LinkTarget.Buffer;
2522
2523 /* Now that we have the correct source, reattempt to query information */
2524 Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2525 if (!NT_SUCCESS(Status))
2526 {
2527 FreePool(SourceDeviceName.Buffer);
2528 FreePool(SourceSymbolicName.Buffer);
2529 return Status;
2530 }
2531 }
2532
2533 FreePool(SourceDeviceName.Buffer);
2534
2535 /* Get information about target device */
2536 Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2537 if (!NT_SUCCESS(Status))
2538 {
2539 FreePool(SourceSymbolicName.Buffer);
2540 return Status;
2541 }
2542
2543 /* Open the remote database */
2544 RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2545 if (RemoteDatabase == 0)
2546 {
2547 FreePool(SourceSymbolicName.Buffer);
2549 }
2550
2551 /* Browse all the entries */
2552 Offset = 0;
2553 for (;;)
2554 {
2556 if (DatabaseEntry == NULL)
2557 {
2558 /* We didn't find ourselves, that's infortunate! */
2559 FreePool(SourceSymbolicName.Buffer);
2562 }
2563
2564 /* Try to find ourselves */
2565 DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2566 DbName.Length = DbName.MaximumLength;
2567 DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2568 if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2569 {
2570 break;
2571 }
2572
2573 Offset += DatabaseEntry->EntrySize;
2574 FreePool(DatabaseEntry);
2575 }
2576
2577 /* Dereference ourselves */
2578 DatabaseEntry->EntryReferences--;
2579 if (DatabaseEntry->EntryReferences == 0)
2580 {
2581 /* If we're still referenced, just update the entry */
2583 }
2584 else
2585 {
2586 /* Otherwise, delete the entry */
2588 if (!NT_SUCCESS(Status))
2589 {
2590 FreePool(DatabaseEntry);
2591 FreePool(SourceSymbolicName.Buffer);
2593 return Status;
2594 }
2595
2596 /* Also, delete our unique ID replicated record */
2597 for (Entry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
2598 Entry != &DeviceInformation->ReplicatedUniqueIdsListHead;
2599 Entry = Entry->Flink)
2600 {
2601 UniqueIdReplicate = CONTAINING_RECORD(Entry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
2602
2603 if (UniqueIdReplicate->UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
2604 RtlCompareMemory(UniqueIdReplicate->UniqueId->UniqueId,
2605 (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
2606 DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
2607 {
2608 break;
2609 }
2610 }
2611
2612 /* It has to exist! */
2613 if (Entry == &DeviceInformation->ReplicatedUniqueIdsListHead)
2614 {
2615 FreePool(DatabaseEntry);
2616 FreePool(SourceSymbolicName.Buffer);
2618 return STATUS_UNSUCCESSFUL;
2619 }
2620
2621 /* Remove it and free it */
2622 RemoveEntryList(&UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2623 FreePool(UniqueIdReplicate->UniqueId);
2624 FreePool(UniqueIdReplicate);
2625 }
2626
2627 /* We're done with the remote database */
2628 FreePool(DatabaseEntry);
2630
2631 /* Check write operation succeed */
2632 if (!NT_SUCCESS(Status))
2633 {
2634 FreePool(SourceSymbolicName.Buffer);
2635 return Status;
2636 }
2637
2638 /* Try to find our associated device entry */
2639 for (Entry = TargetDeviceInformation->AssociatedDevicesHead.Flink;
2640 Entry != &TargetDeviceInformation->AssociatedDevicesHead;
2641 Entry = Entry->Flink)
2642 {
2643 AssociatedEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
2644
2645 /* If found, delete it */
2646 if (AssociatedEntry->DeviceInformation == DeviceInformation &&
2647 RtlEqualUnicodeString(&AssociatedEntry->String, &SourceSymbolicName, TRUE))
2648 {
2649 RemoveEntryList(&AssociatedEntry->AssociatedDevicesEntry);
2650 FreePool(AssociatedEntry->String.Buffer);
2651 FreePool(AssociatedEntry);
2652 break;
2653 }
2654 }
2655
2656 /* We're done! */
2657 FreePool(SourceSymbolicName.Buffer);
2658 return STATUS_SUCCESS;
2659}
2660
2661/*
2662 * @implemented
2663 */
2665NTAPI
2667 IN PIRP Irp)
2668{
2670 NTSTATUS Status, LockStatus;
2671 PDEVICE_EXTENSION DeviceExtension;
2672
2674 DeviceExtension = DeviceObject->DeviceExtension;
2675
2676 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2677
2678 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2679 {
2681 Status = MountMgrCreatePoint(DeviceExtension, Irp);
2682 break;
2683
2685 Status = MountMgrDeletePoints(DeviceExtension, Irp);
2686 break;
2687
2689 Status = MountMgrQueryPoints(DeviceExtension, Irp);
2690 break;
2691
2693 Status = MountMgrDeletePointsDbOnly(DeviceExtension, Irp);
2694 break;
2695
2697 Status = MountMgrNextDriveLetter(DeviceExtension, Irp);
2698 break;
2699
2701 // NOTE: On Win7+, this is handled during driver re-initialization.
2702 DeviceExtension->AutomaticDriveLetter = TRUE;
2703 MountMgrAssignDriveLetters(DeviceExtension);
2704 ReconcileAllDatabasesWithMaster(DeviceExtension);
2705 WaitForOnlinesToComplete(DeviceExtension);
2707 break;
2708
2710 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2711
2712 LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2713 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2714 Status = MountMgrVolumeMountPointCreated(DeviceExtension, Irp, LockStatus);
2715 if (NT_SUCCESS(LockStatus))
2716 {
2717 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2718 }
2719
2720 break;
2721
2723 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2724
2725 LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2726 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2727 Status = MountMgrVolumeMountPointDeleted(DeviceExtension, Irp, LockStatus);
2728 if (NT_SUCCESS(LockStatus))
2729 {
2730 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2731 }
2732
2733 break;
2734
2736 Status = MountMgrChangeNotify(DeviceExtension, Irp);
2737 break;
2738
2740 Status = MountMgrKeepLinksWhenOffline(DeviceExtension, Irp);
2741 break;
2742
2744 Status = MountMgrCheckUnprocessedVolumes(DeviceExtension, Irp);
2745 goto Complete;
2746
2748 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2749 Status = MountMgrVolumeArrivalNotification(DeviceExtension, Irp);
2750 goto Complete;
2751
2753 Status = MountMgrQueryDosVolumePath(DeviceExtension, Irp);
2754 break;
2755
2757 Status = MountMgrQueryDosVolumePaths(DeviceExtension, Irp);
2758 break;
2759
2761 Status = MountMgrScrubRegistry(DeviceExtension);
2762 break;
2763
2765 Status = MountMgrQueryAutoMount(DeviceExtension, Irp);
2766 break;
2767
2769 Status = MountMgrSetAutoMount(DeviceExtension, Irp);
2770 break;
2771
2772 default:
2774 }
2775
2776 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2777
2778 if (Status != STATUS_PENDING)
2779 {
2780 goto Complete;
2781 }
2782
2783 return Status;
2784
2785Complete:
2786 Irp->IoStatus.Status = Status;
2788
2789 return Status;
2790}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
@ Invalid
Definition: asmpp.cpp:30
LONG NTSTATUS
Definition: precomp.h:26
#define MAX(x, y)
Definition: rdesktop.h:175
#define CHAR(Char)
return Found
Definition: dirsup.c:1270
_In_ BOOLEAN Release
Definition: cdrom.h:920
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c: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:2453
BOOLEAN IsFtVolume(IN PUNICODE_STRING SymbolicName)
Definition: device.c:331
NTSTATUS MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1675
NTSTATUS MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1632
NTSTATUS MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1820
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:2214
NTSTATUS MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName)
Definition: device.c:707
NTSTATUS MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:221
NTSTATUS MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1439
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:1149
NTSTATUS NTAPI MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: device.c:667
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:1041
NTSTATUS MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1921
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:736
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:1988
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:813
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:34
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4219
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4220
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_REMOTE_DEVICE
Definition: nt_native.h:811
#define SYNCHRONIZE
Definition: nt_native.h:61
#define REG_BINARY
Definition: nt_native.h:1496
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h: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 STATUS_PENDING
Definition: ntstatus.h:82
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h: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::@312::@314 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:1662
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292