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