ReactOS  0.4.12-dev-720-g6accaef
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;
42  PIO_STACK_LOCATION Stack;
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 = 0;
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 {
107  PIO_STACK_LOCATION Stack;
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 {
139  PIO_STACK_LOCATION Stack;
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;
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 {
226 
227  do
228  {
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;
253  PIO_STACK_LOCATION Stack;
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 IsRecognizedPartition(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 symlink to see if there's 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  /* This is a driver letter & online one, forget about new drive eltter */
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 there's no GPT drive letter nor no drive entry
528  */
529  if (NextEntry == &(DeviceInformation->SymbolicLinksListHead))
530  {
531  if (GptDriveLetter || HasNoDriveLetterEntry(DeviceInformation->UniqueId))
532  {
533  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
534  DriveLetterInfo->CurrentDriveLetter = 0;
535 
536  goto Release;
537  }
538  }
539 
540  /* No, ensure that the device is not automounted nor removable */
541  if (!DeviceExtension->NoAutoMount && !Removable)
542  {
543  if (DriveLetterInfo->DriveLetterWasAssigned)
544  {
545  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
546  DriveLetterInfo->CurrentDriveLetter = 0;
547 
548  goto Release;
549  }
550  }
551 
552  if (!DriveLetterInfo->DriveLetterWasAssigned)
553  {
554  goto Release;
555  }
556 
557  /* Now everything is fine, start processing */
558 
559  if (RtlPrefixUnicodeString(&DeviceFloppy, &TargetDeviceName, TRUE))
560  {
561  /* If the device is a floppy, start with letter A */
562  DriveLetter = 'A';
563  }
564  else if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
565  {
566  /* If the device is a CD-ROM, start with letter D */
567  DriveLetter = 'D';
568  }
569  else
570  {
571  /* Finally, if it's a disk, use C */
572  DriveLetter = 'C';
573  }
574 
575  /* We cannot set NO drive letter */
576  ASSERT(DeviceInformation->SuggestedDriveLetter != (UCHAR)-1);
577 
578  /* If we don't have suggested letter but it's a FT volume, fail */
579  if (!DeviceInformation->SuggestedDriveLetter && IsFtVolume(&(DeviceInformation->DeviceName)))
580  {
581  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
582  DriveLetterInfo->CurrentDriveLetter = 0;
583 
584  goto Release;
585  }
586 
587  /* Prepare buffer */
589  NameBuffer[COLON_POSITION] = L':';
590  SymbolicName.Buffer = NameBuffer;
593 
594  /* It's all prepared, create mount point */
595  if (DeviceInformation->SuggestedDriveLetter)
596  {
597  DriveLetterInfo->CurrentDriveLetter = DeviceInformation->SuggestedDriveLetter;
598  NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
599 
600  Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
601  if (NT_SUCCESS(Status))
602  {
603  goto Release;
604  }
605  }
606 
607  /* It failed with this letter... Try another one! */
608  for (DriveLetterInfo->CurrentDriveLetter = DriveLetter;
609  DriveLetterInfo->CurrentDriveLetter <= L'Z';
610  DriveLetterInfo->CurrentDriveLetter++)
611  {
612  NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
613 
614  Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
615  if (NT_SUCCESS(Status))
616  {
617  break;
618  }
619  }
620 
621  /* We failed setting a letter */
622  if (DriveLetterInfo->CurrentDriveLetter > L'Z')
623  {
624  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
625  DriveLetterInfo->CurrentDriveLetter = 0;
626 
627  /* Try at least to add a no drive letter entry */
628  Status = QueryDeviceInformation(&TargetDeviceName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
629  if (NT_SUCCESS(Status))
630  {
631  CreateNoDriveLetterEntry(UniqueId);
632  FreePool(UniqueId);
633  }
634  }
635 
636 Release:
637  FreePool(TargetDeviceName.Buffer);
638 
639  return STATUS_SUCCESS;
640 }
641 
642 
643 /*
644  * @implemented
645  */
646 NTSTATUS
648  IN PIRP Irp)
649 {
651  PIO_STACK_LOCATION Stack;
653  PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget;
654  MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
655 
657 
658  /* Validate input */
659  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) ||
660  Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION))
661  {
663  }
664 
665  DriveLetterTarget = (PMOUNTMGR_DRIVE_LETTER_TARGET)Irp->AssociatedIrp.SystemBuffer;
666  if (DriveLetterTarget->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
667  {
669  }
670 
671  /* Call the worker */
672  DeviceName.Buffer = DriveLetterTarget->DeviceName;
673  DeviceName.Length =
674  DeviceName.MaximumLength = DriveLetterTarget->DeviceNameLength;
675 
676  Status = MountMgrNextDriveLetterWorker(DeviceExtension, &DeviceName,
677  &DriveLetterInformation);
678  if (NT_SUCCESS(Status))
679  {
680  *(PMOUNTMGR_DRIVE_LETTER_INFORMATION)Irp->AssociatedIrp.SystemBuffer =
681  DriveLetterInformation;
682  Irp->IoStatus.Information = sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION);
683  }
684 
685  return Status;
686 }
687 
688 /*
689  * @implemented
690  */
691 NTSTATUS
692 NTAPI
697  IN PVOID Context,
699 {
700  UNICODE_STRING ValueString;
701  PUNICODE_STRING SystemVolumeName;
702 
706 
707  if (ValueType != REG_SZ)
708  {
709  return STATUS_SUCCESS;
710  }
711 
712  RtlInitUnicodeString(&ValueString, ValueData);
713  SystemVolumeName = Context;
714 
715  /* Return a string containing system volume name */
716  SystemVolumeName->Length = ValueString.Length;
717  SystemVolumeName->MaximumLength = ValueString.Length + sizeof(WCHAR);
718  SystemVolumeName->Buffer = AllocatePool(SystemVolumeName->MaximumLength);
719  if (SystemVolumeName->Buffer)
720  {
721  RtlCopyMemory(SystemVolumeName->Buffer, ValueData, ValueString.Length);
722  SystemVolumeName->Buffer[ValueString.Length / sizeof(WCHAR)] = UNICODE_NULL;
723  }
724 
725  return STATUS_SUCCESS;
726 
727 }
728 
729 /*
730  * @implemented
731  */
732 NTSTATUS
734 {
736 
740  QueryTable[0].Name = L"SystemPartition";
741 
742  SystemVolumeName->Buffer = NULL;
743 
745  L"\\Registry\\Machine\\System\\Setup",
746  QueryTable,
747  SystemVolumeName,
748  NULL);
749 
750  if (SystemVolumeName->Buffer)
751  {
752  return STATUS_SUCCESS;
753  }
754 
755  return STATUS_UNSUCCESSFUL;
756 }
757 
758 /*
759  * @implemented
760  */
761 VOID
763 {
765  PLIST_ENTRY NextEntry;
766  UNICODE_STRING SystemVolumeName;
767  PDEVICE_INFORMATION DeviceInformation;
768  MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
769 
770  /* First, get system volume name */
771  Status = MountMgrQuerySystemVolumeName(&SystemVolumeName);
772 
773  /* If there are no device, it's all done */
774  if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
775  {
776  if (NT_SUCCESS(Status))
777  {
778  FreePool(SystemVolumeName.Buffer);
779  }
780 
781  return;
782  }
783 
784  /* Now, for all the devices... */
785  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
786  NextEntry != &(DeviceExtension->DeviceListHead);
787  NextEntry = NextEntry->Flink)
788  {
789  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
790 
791  /* If the device doesn't have a letter assigned, do it! */
792  if (!DeviceInformation->LetterAssigned)
793  {
794  MountMgrNextDriveLetterWorker(DeviceExtension,
795  &(DeviceInformation->DeviceName),
796  &DriveLetterInformation);
797  }
798 
799  /* If it was the system volume */
800  if (NT_SUCCESS(Status) && RtlEqualUnicodeString(&SystemVolumeName, &(DeviceInformation->DeviceName), TRUE))
801  {
802  /* Keep track of it */
803  DeviceExtension->DriveLetterData = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength +
804  sizeof(MOUNTDEV_UNIQUE_ID));
805  if (DeviceExtension->DriveLetterData)
806  {
807  RtlCopyMemory(DeviceExtension->DriveLetterData,
808  DeviceInformation->UniqueId,
809  DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
810  }
811 
812  /* If it was not automount, ensure it gets mounted */
813  if (!DeviceExtension->NoAutoMount)
814  {
815  DeviceExtension->NoAutoMount = TRUE;
816 
817  MountMgrNextDriveLetterWorker(DeviceExtension,
818  &(DeviceInformation->DeviceName),
819  &DriveLetterInformation);
820 
821  DeviceExtension->NoAutoMount = FALSE;
822  }
823  }
824  }
825 
826  if (NT_SUCCESS(Status))
827  {
828  FreePool(SystemVolumeName.Buffer);
829  }
830 }
831 
832 /*
833  * @implemented
834  */
835 NTSTATUS
837  IN PIRP Irp)
838 {
840  ULONG DevicesFound;
841  PIO_STACK_LOCATION Stack;
842  PLIST_ENTRY SymlinksEntry;
845  PWSTR DeviceString, OldBuffer;
846  USHORT DeviceLength, OldLength;
847  PDEVICE_INFORMATION DeviceInformation;
848  PSYMLINK_INFORMATION SymlinkInformation;
849  PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
850 
852 
853  /* Validate input size */
854  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
855  {
857  }
858 
859  /* Ensure we have received UNICODE_STRING */
860  Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
861  if (Target->DeviceNameLength & 1)
862  {
864  }
865 
866  /* Validate the entry structure size */
867  if (Target->DeviceNameLength + sizeof(UNICODE_NULL) > Stack->Parameters.DeviceIoControl.InputBufferLength)
868  {
870  }
871 
872  /* Ensure we can at least return needed size */
873  if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
874  {
876  }
877 
878  /* Construct string for query */
879  SymbolicName.Length = Target->DeviceNameLength;
880  SymbolicName.MaximumLength = Target->DeviceNameLength + sizeof(UNICODE_NULL);
881  SymbolicName.Buffer = Target->DeviceName;
882 
883  /* Find device with our info */
884  Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
885  if (!NT_SUCCESS(Status))
886  {
887  return Status;
888  }
889 
890  DeviceLength = 0;
891  DeviceString = NULL;
892  DevicesFound = 0;
893 
894  /* Try to find associated device info */
895  while (TRUE)
896  {
897  for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
898  SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
899  SymlinksEntry = SymlinksEntry->Flink)
900  {
901  SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
902 
903  /* Try to find with drive letter */
904  if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
905  {
906  break;
907  }
908  }
909 
910  /* We didn't find, break */
911  if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
912  {
913  break;
914  }
915 
916  /* It doesn't have associated device, go to fallback method */
917  if (IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
918  {
919  goto TryWithVolumeName;
920  }
921 
922  /* Create a string with the information about the device */
923  AssociatedDevice = CONTAINING_RECORD(&(DeviceInformation->SymbolicLinksListHead), ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
924  OldLength = DeviceLength;
925  OldBuffer = DeviceString;
926  DeviceLength += AssociatedDevice->String.Length;
927  DeviceString = AllocatePool(DeviceLength);
928  if (!DeviceString)
929  {
930  if (OldBuffer)
931  {
932  FreePool(OldBuffer);
933  }
934 
936  }
937 
938  /* Store our info and previous if any */
939  RtlCopyMemory(DeviceString, AssociatedDevice->String.Buffer, AssociatedDevice->String.Length);
940  if (OldBuffer)
941  {
942  RtlCopyMemory(&DeviceString[AssociatedDevice->String.Length / sizeof(WCHAR)], OldBuffer, OldLength);
943  FreePool(OldBuffer);
944  }
945 
946  /* Count and continue looking */
947  ++DevicesFound;
948  DeviceInformation = AssociatedDevice->DeviceInformation;
949 
950  /* If too many devices, try another way */
951  if (DevicesFound > MAX_DEVICES) /* 1000 */
952  {
953  goto TryWithVolumeName;
954  }
955  }
956 
957  /* Reallocate our string, so that we can prepend disk letter */
958  OldBuffer = DeviceString;
959  OldLength = DeviceLength;
960  DeviceLength += 2 * sizeof(WCHAR);
961  DeviceString = AllocatePool(DeviceLength);
962  if (!DeviceString)
963  {
964  if (OldBuffer)
965  {
966  FreePool(OldBuffer);
967  }
968 
970  }
971 
972  /* Get the letter */
973  DeviceString[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
974  DeviceString[1] = L':';
975 
976  /* And copy the rest */
977  if (OldBuffer)
978  {
979  RtlCopyMemory(&DeviceString[2], OldBuffer, OldLength);
980  FreePool(OldBuffer);
981  }
982 
983 TryWithVolumeName:
984  /* If we didn't find anything, try differently */
985  if (DeviceLength < 2 * sizeof(WCHAR) || DeviceString[1] != L':')
986  {
987  if (DeviceString)
988  {
989  FreePool(DeviceString);
990  DeviceLength = 0;
991  }
992 
993  /* Try to find a volume name matching */
994  for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
995  SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
996  SymlinksEntry = SymlinksEntry->Flink)
997  {
998  SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
999 
1000  if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation->Name))
1001  {
1002  break;
1003  }
1004  }
1005 
1006  /* If found copy */
1007  if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
1008  {
1009  DeviceLength = SymlinkInformation->Name.Length;
1010  DeviceString = AllocatePool(DeviceLength);
1011  if (!DeviceString)
1012  {
1014  }
1015 
1016  RtlCopyMemory(DeviceString, SymlinkInformation->Name.Buffer, DeviceLength);
1017  /* Ensure we are in the right namespace; [1] can be ? */
1018  DeviceString[1] = L'\\';
1019  }
1020  }
1021 
1022  /* If we found something */
1023  if (DeviceString)
1024  {
1025  /* At least, we will return our length */
1026  ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSzLength = DeviceLength;
1027  /* MOUNTMGR_VOLUME_PATHS is a string + a ULONG */
1028  Irp->IoStatus.Information = DeviceLength + sizeof(ULONG);
1029 
1030  /* If we have enough room for copying the string */
1031  if (sizeof(ULONG) + DeviceLength <= Stack->Parameters.DeviceIoControl.OutputBufferLength)
1032  {
1033  /* Copy it */
1034  if (DeviceLength)
1035  {
1036  RtlCopyMemory(((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz, DeviceString, DeviceLength);
1037  }
1038 
1039  /* And double zero at its end - this is needed in case of multiple paths which are separated by a single 0 */
1040  FreePool(DeviceString);
1041  ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR)] = 0;
1042  ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR) + 1] = 0;
1043 
1044  return STATUS_SUCCESS;
1045  }
1046  else
1047  {
1048  /* Just return appropriate size and leave */
1049  FreePool(DeviceString);
1050  Irp->IoStatus.Information = sizeof(ULONG);
1051  return STATUS_BUFFER_OVERFLOW;
1052  }
1053  }
1054 
1055  /* Fail */
1056  return STATUS_NOT_FOUND;
1057 }
1058 
1059 /*
1060  * @implemented
1061  */
1062 NTSTATUS
1064  IN PDEVICE_INFORMATION DeviceInformation,
1065  OUT PBOOLEAN Invalid)
1066 {
1067  HANDLE Handle;
1068  NTSTATUS Status;
1069  PLIST_ENTRY SymlinksEntry;
1071  PREPARSE_DATA_BUFFER ReparseData;
1073  UNICODE_STRING FullName, SubstituteName;
1074  PSYMLINK_INFORMATION SymlinkInformation;
1075 
1076  /* Initialize & allocate a string big enough to contain our complete mount point name */
1077  FullName.Length = AssociatedDeviceEntry->String.Length + AssociatedDeviceEntry->DeviceInformation->DeviceName.Length + sizeof(WCHAR);
1080  if (!FullName.Buffer)
1081  {
1083  }
1084 
1085  /* Create the path */
1086  RtlCopyMemory(FullName.Buffer, AssociatedDeviceEntry->DeviceInformation->DeviceName.Buffer, AssociatedDeviceEntry->DeviceInformation->DeviceName.Length);
1087  FullName.Buffer[AssociatedDeviceEntry->DeviceInformation->DeviceName.Length / sizeof(WCHAR)] = L'\\';
1088  RtlCopyMemory(&FullName.Buffer[AssociatedDeviceEntry->DeviceInformation->DeviceName.Length / sizeof(WCHAR) + 1], AssociatedDeviceEntry->String.Buffer, AssociatedDeviceEntry->String.Length);
1090 
1091  /* Open it to query the reparse point */
1093  &FullName,
1095  NULL,
1096  NULL);
1103 
1104  if (!NT_SUCCESS(Status))
1105  {
1106  *Invalid = TRUE;
1107  return STATUS_SUCCESS;
1108  }
1109 
1110  /* Allocate a buffer big enough to read reparse data */
1112  if (ReparseData == NULL)
1113  {
1114  ZwClose(Handle);
1116  }
1117 
1118  /* Query reparse data */
1120  NULL, NULL, NULL,
1121  &IoStatusBlock,
1123  NULL, 0,
1124  ReparseData, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1125  ZwClose(Handle);
1126 
1127  if (!NT_SUCCESS(Status))
1128  {
1129  FreePool(ReparseData);
1130  *Invalid = TRUE;
1131  return STATUS_SUCCESS;
1132  }
1133 
1134  /* Create a string with the substitute name */
1135  SubstituteName.Length = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
1136  SubstituteName.MaximumLength = SubstituteName.Length;
1137  SubstituteName.Buffer = (PWSTR)((ULONG_PTR)ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset);
1138 
1139  /* If that's a volume name that matches our associated device, that's a success! */
1140  if (MOUNTMGR_IS_VOLUME_NAME(&SubstituteName))
1141  {
1142  if (SubstituteName.Length == 98 && SubstituteName.Buffer[1] == L'?')
1143  {
1144  for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1145  SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
1146  SymlinksEntry = SymlinksEntry->Flink)
1147  {
1148  SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1149 
1150  if (RtlEqualUnicodeString(&SubstituteName, &SymlinkInformation->Name, TRUE))
1151  {
1152  FreePool(ReparseData);
1153  return STATUS_SUCCESS;
1154  }
1155  }
1156  }
1157  }
1158 
1159  FreePool(ReparseData);
1160  *Invalid = TRUE;
1161  return STATUS_SUCCESS;
1162 }
1163 
1164 /*
1165  * @implemented
1166  */
1167 NTSTATUS
1169  IN PDEVICE_INFORMATION DeviceInformation,
1170  IN PLIST_ENTRY DeviceInfoList,
1171  OUT PMOUNTMGR_VOLUME_PATHS * VolumePaths,
1172  OUT PDEVICE_INFORMATION *FailedDevice)
1173 {
1174  ULONG Written;
1175  NTSTATUS Status;
1177  PSYMLINK_INFORMATION SymlinkInformation;
1178  PDEVICE_INFORMATION_ENTRY DeviceInfoEntry;
1179  PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry;
1180  PMOUNTMGR_VOLUME_PATHS * Paths = NULL, * CurrentPath;
1181  ULONG OutputPathLength, NumberOfPaths, ReturnedPaths;
1182 
1183  /* We return at least null char */
1184  OutputPathLength = sizeof(UNICODE_NULL);
1185 
1186  for (Entry = DeviceInformation->SymbolicLinksListHead.Flink;
1187  Entry != &(DeviceInformation->SymbolicLinksListHead);
1188  Entry = Entry->Flink)
1189  {
1190  SymlinkInformation = CONTAINING_RECORD(Entry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1191 
1192  /* Try to find the drive letter (ie, DOS device) */
1193  if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
1194  {
1195  /* We'll return the letter */
1196  OutputPathLength = 4 * sizeof(WCHAR);
1197  break;
1198  }
1199  }
1200 
1201  /* We didn't find any */
1202  if (Entry == &(DeviceInformation->SymbolicLinksListHead))
1203  {
1204  SymlinkInformation = NULL;
1205  }
1206 
1207  /* Do we have any device info to return? */
1208  for (Entry = DeviceInfoList->Flink; Entry != DeviceInfoList; Entry = Entry->Flink)
1209  {
1210  DeviceInfoEntry = CONTAINING_RECORD(Entry, DEVICE_INFORMATION_ENTRY, DeviceInformationEntry);
1211 
1212  /* Matching current device */
1213  if (DeviceInfoEntry->DeviceInformation == DeviceInformation)
1214  {
1215  /* Allocate the output buffer */
1216  *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1217  if (*VolumePaths == NULL)
1218  {
1220  }
1221 
1222  /* Set size */
1223  (*VolumePaths)->MultiSzLength = OutputPathLength;
1224  /* If we have a drive letter, return it */
1225  if (SymlinkInformation != NULL)
1226  {
1227  (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1228  (*VolumePaths)->MultiSz[1] = L':';
1229  (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1230  (*VolumePaths)->MultiSz[3] = UNICODE_NULL;
1231  }
1232  else
1233  {
1234  (*VolumePaths)->MultiSz[0] = UNICODE_NULL;
1235  }
1236 
1237  return STATUS_SUCCESS;
1238  }
1239  }
1240 
1241  /* Allocate a new device entry */
1242  DeviceInfoEntry = AllocatePool(sizeof(DEVICE_INFORMATION_ENTRY));
1243  if (DeviceInfoEntry == NULL)
1244  {
1246  }
1247 
1248  /* Add it to the list */
1249  DeviceInfoEntry->DeviceInformation = DeviceInformation;
1250  InsertTailList(DeviceInfoList, &DeviceInfoEntry->DeviceInformationEntry);
1251 
1252  NumberOfPaths = 0;
1253  /* Count the amount of devices we will have to handle */
1254  if (!IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
1255  {
1256  for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1257  Entry != &DeviceInformation->AssociatedDevicesHead;
1258  Entry = Entry->Flink)
1259  {
1260  ++NumberOfPaths;
1261  }
1262 
1263  ASSERT(NumberOfPaths != 0);
1264  /* And allocate a big enough buffer */
1265  Paths = AllocatePool(NumberOfPaths * sizeof(PMOUNTMGR_VOLUME_PATHS));
1266  if (Paths == NULL)
1267  {
1268  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1269  FreePool(DeviceInfoEntry);
1271  }
1272  }
1273 
1274  /* Start the hot loop to gather all the paths and be able to compute total output length! */
1275  ReturnedPaths = 0;
1276  CurrentPath = Paths;
1277  for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1278  Entry != &DeviceInformation->AssociatedDevicesHead;
1279  Entry = Entry->Flink)
1280  {
1281  USHORT InnerStrings;
1282  BOOLEAN Invalid = FALSE;
1283 
1284  AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1285 
1286  /* Validate the fact its a mount point by query reparse data */
1287  Status = MountMgrValidateBackPointer(AssociatedDeviceEntry, DeviceInformation, &Invalid);
1288 
1289  /* If we found an invalid device, that's a failure */
1290  if (Invalid)
1291  {
1292  *FailedDevice = AssociatedDeviceEntry->DeviceInformation;
1294  }
1295 
1296  /* Check whether we failed, if so, bail out */
1297  if (!NT_SUCCESS(Status))
1298  {
1299  ULONG i;
1300 
1301  for (i = 0; i < ReturnedPaths; ++i)
1302  {
1303  FreePool(Paths[i]);
1304  }
1305 
1306  if (Paths != NULL)
1307  {
1308  FreePool(Paths);
1309  }
1310  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1311  FreePool(DeviceInfoEntry);
1312  return Status;
1313  }
1314 
1315  /* Query associated paths (hello ourselves :-)) */
1316  Status = MountMgrQueryVolumePaths(DeviceExtension,
1317  AssociatedDeviceEntry->DeviceInformation,
1318  DeviceInfoList,
1319  CurrentPath,
1320  FailedDevice);
1321  if (!NT_SUCCESS(Status))
1322  {
1323  ULONG i;
1324 
1325  for (i = 0; i < ReturnedPaths; ++i)
1326  {
1327  FreePool(Paths[i]);
1328  }
1329 
1330  if (Paths != NULL)
1331  {
1332  FreePool(Paths);
1333  }
1334  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1335  FreePool(DeviceInfoEntry);
1336  return Status;
1337  }
1338 
1339  /* Count the number of strings we have in the multi string buffer */
1340  InnerStrings = 0;
1341  if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1342  {
1343  ULONG i;
1344  PWSTR MultiSz = (*CurrentPath)->MultiSz;
1345 
1346  for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR); ++i, ++MultiSz)
1347  {
1348  if (*MultiSz == UNICODE_NULL)
1349  {
1350  ++InnerStrings;
1351  }
1352  }
1353  }
1354 
1355  /* We returned one more path (ie, one more allocated buffer) */
1356  ++ReturnedPaths;
1357  /* Move the next pointer to use in the array */
1358  ++CurrentPath;
1359  /* Multiply String.Length by the number of found paths, we always add it after a path */
1360  OutputPathLength += (*CurrentPath)->MultiSzLength + InnerStrings * AssociatedDeviceEntry->String.Length - sizeof(UNICODE_NULL);
1361  }
1362 
1363  /* Allocate the output buffer */
1364  *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1365  if (*VolumePaths == NULL)
1366  {
1367  ULONG i;
1368 
1369  for (i = 0; i < ReturnedPaths; ++i)
1370  {
1371  FreePool(Paths[i]);
1372  }
1373 
1374  if (Paths != NULL)
1375  {
1376  FreePool(Paths);
1377  }
1378  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1379  FreePool(DeviceInfoEntry);
1381  }
1382 
1383  Written = 0;
1384  /* If we had found a DOS letter, that's the first thing we return */
1385  (*VolumePaths)->MultiSzLength = OutputPathLength;
1386  if (SymlinkInformation != NULL)
1387  {
1388  (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1389  (*VolumePaths)->MultiSz[1] = L':';
1390  (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1391  Written = 3;
1392  }
1393 
1394  /* Now, browse again all our paths to return them */
1395  CurrentPath = Paths;
1396  for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1397  Entry != &DeviceInformation->AssociatedDevicesHead;
1398  Entry = Entry->Flink)
1399  {
1400  AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1401 
1402  /* If we had a path... */
1403  if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1404  {
1405  ULONG i, Offset;
1406  PWSTR MultiSz;
1407 
1408  /* This offset is used to "jump" into MultiSz, so, start with the string begin (ie, skip MultiSzLength) */
1409  Offset = sizeof(ULONG);
1410  /* Browse every single letter, and skip last UNICODE_NULL */
1411  for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR) - 1; ++i)
1412  {
1413  /* Get the letter */
1414  MultiSz = (PWSTR)((ULONG_PTR)(*CurrentPath) + Offset);
1415  /* If it was part of the path, just return it */
1416  if (*MultiSz != UNICODE_NULL)
1417  {
1418  (*VolumePaths)->MultiSz[Written] = *MultiSz;
1419  }
1420  else
1421  {
1422  /* Otherwise, as planed, return our whole associated device name */
1423  RtlCopyMemory(&(*VolumePaths)->MultiSz[Written],
1424  AssociatedDeviceEntry->String.Buffer,
1425  AssociatedDeviceEntry->String.Length);
1426  Written += AssociatedDeviceEntry->String.Length / sizeof(WCHAR);
1427  /* And don't forget to nullify */
1428  (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1429  }
1430 
1431  /* We at least return a letter or a null char */
1432  ++Written;
1433  /* Move to the next letter */
1434  Offset += sizeof(WCHAR);
1435  }
1436  }
1437 
1438  FreePool(*CurrentPath);
1439  ++CurrentPath;
1440  }
1441 
1442  /* MultiSz: don't forget last null char */
1443  (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1444  /* Cleanup everything and return success! */
1445  if (Paths != NULL)
1446  {
1447  FreePool(Paths);
1448  }
1449  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1450  FreePool(DeviceInfoEntry);
1451  return STATUS_SUCCESS;
1452 }
1453 
1454 /*
1455  * @implemented
1456  */
1457 NTSTATUS
1459  IN PIRP Irp)
1460 {
1461  NTSTATUS Status;
1463  LIST_ENTRY Devices;
1464  BOOLEAN NeedNotification;
1465  PIO_STACK_LOCATION Stack;
1467  ULONG Attempts, OutputLength;
1470  RECONCILE_WORK_ITEM_CONTEXT ReconcileContext;
1471  PDEVICE_INFORMATION DeviceInformation, ListDeviceInfo, FailedDevice;
1472 
1474 
1475  /* Validate input size */
1476  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1477  {
1478  return STATUS_INVALID_PARAMETER;
1479  }
1480 
1481  /* Ensure we have received UNICODE_STRING */
1482  Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1483  if (Target->DeviceNameLength & 1)
1484  {
1485  return STATUS_INVALID_PARAMETER;
1486  }
1487 
1488  /* Validate the entry structure size */
1489  if (Target->DeviceNameLength + FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1490  {
1491  return STATUS_INVALID_PARAMETER;
1492  }
1493 
1494  /* Ensure we can at least return needed size */
1495  if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
1496  {
1497  return STATUS_INVALID_PARAMETER;
1498  }
1499 
1500  /* Construct string for query */
1501  SymbolicName.Length = Target->DeviceNameLength;
1502  SymbolicName.MaximumLength = Target->DeviceNameLength + sizeof(UNICODE_NULL);
1503  SymbolicName.Buffer = Target->DeviceName;
1504 
1505  /* Find device with our info */
1506  Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1507  if (!NT_SUCCESS(Status))
1508  {
1509  return Status;
1510  }
1511 
1512  NeedNotification = FALSE;
1513  Attempts = 0;
1514  for (;;)
1515  {
1516  FailedDevice = NULL;
1517  InitializeListHead(&Devices);
1518 
1519  /* Query paths */
1520  Status = MountMgrQueryVolumePaths(DeviceExtension, DeviceInformation, &Devices, &Paths, &FailedDevice);
1521  if (NT_SUCCESS(Status))
1522  {
1523  break;
1524  }
1525 
1526  /* If it failed for generic reason (memory, whatever), bail out (ie, FailedDevice not set) */
1527  if (FailedDevice == NULL)
1528  {
1529  return Status;
1530  }
1531 
1532  /* If PnP, let's notify in case of success */
1533  if (!DeviceInformation->ManuallyRegistered)
1534  {
1535  NeedNotification = TRUE;
1536  }
1537 
1538  /* Reconcile database */
1539  ReconcileContext.DeviceExtension = DeviceExtension;
1540  ReconcileContext.DeviceInformation = FailedDevice;
1541  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1542  ReconcileThisDatabaseWithMasterWorker(&ReconcileContext);
1543  KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1544 
1545  /* Look for our device, to check it's online */
1546  for (Entry = DeviceExtension->DeviceListHead.Flink;
1547  Entry != &DeviceExtension->DeviceListHead;
1548  Entry = Entry->Flink)
1549  {
1550  ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
1551  /* It's online, it's OK! */
1552  if (ListDeviceInfo == DeviceInformation)
1553  {
1554  break;
1555  }
1556  }
1557 
1558  /* It's not online, it's not good */
1559  if (Entry == &DeviceExtension->DeviceListHead)
1560  {
1562  }
1563 
1564  /* Increase attempts count */
1565  ++Attempts;
1566  /* Don't look forever and fail if we get out of attempts */
1567  if (Attempts >= 1000)
1568  {
1569  return Status;
1570  }
1571  }
1572 
1573  /* We need to notify? Go ahead */
1574  if (NeedNotification)
1575  {
1576  MountMgrNotifyNameChange(DeviceExtension, &SymbolicName, FALSE);
1577  }
1578 
1579  /* Get output buffer */
1580  Output = (PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer;
1581 
1582  /* Set required size */
1583  Output->MultiSzLength = Paths->MultiSzLength;
1584 
1585  /* Compute total length */
1586  OutputLength = Output->MultiSzLength + sizeof(ULONG);
1587 
1588  /* If it cannot fit, just return need size and quit */
1589  if (OutputLength > Stack->Parameters.DeviceIoControl.OutputBufferLength)
1590  {
1591  Irp->IoStatus.Information = sizeof(ULONG);
1592  FreePool(Paths);
1593  return STATUS_BUFFER_OVERFLOW;
1594  }
1595 
1596  /* Copy data and quit */
1597  Irp->IoStatus.Information = OutputLength;
1598  RtlCopyMemory(Output->MultiSz, Paths->MultiSz, Output->MultiSzLength);
1599  FreePool(Paths);
1600  return STATUS_SUCCESS;
1601 }
1602 
1603 /*
1604  * @implemented
1605  */
1606 NTSTATUS
1608  IN PIRP Irp)
1609 {
1610  NTSTATUS Status;
1611  PIO_STACK_LOCATION Stack;
1614  PDEVICE_INFORMATION DeviceInformation;
1615 
1617 
1618  /* Validate input */
1619  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1620  {
1621  return STATUS_INVALID_PARAMETER;
1622  }
1623 
1624  Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1625  if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1626  {
1627  return STATUS_INVALID_PARAMETER;
1628  }
1629 
1631  SymbolicName.MaximumLength = Target->DeviceNameLength;
1632  SymbolicName.Buffer = Target->DeviceName;
1633 
1634  /* Find the associated device */
1635  Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1636  if (!NT_SUCCESS(Status))
1637  {
1638  return Status;
1639  }
1640 
1641  /* Mark we want to keep links */
1642  DeviceInformation->KeepLinks = TRUE;
1643 
1644  return STATUS_SUCCESS;
1645 }
1646 
1647 /*
1648  * @implemented
1649  */
1650 NTSTATUS
1652  IN PIRP Irp)
1653 {
1654  NTSTATUS Status;
1655  BOOLEAN OldState;
1656  PIO_STACK_LOCATION Stack;
1659 
1661 
1662  /* Validate input */
1663  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1664  {
1665  return STATUS_INVALID_PARAMETER;
1666  }
1667 
1668  Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1669  if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1670  {
1671  return STATUS_INVALID_PARAMETER;
1672  }
1673 
1675  SymbolicName.MaximumLength = Target->DeviceNameLength;
1676  SymbolicName.Buffer = Target->DeviceName;
1677 
1678  /* Disable hard errors */
1681 
1682  /* Call real worker */
1683  Status = MountMgrMountedDeviceArrival(DeviceExtension, &SymbolicName, TRUE);
1684 
1686 
1687  return Status;
1688 }
1689 
1690 /*
1691  * @implemented
1692  */
1693 NTSTATUS
1695  IN PIRP Irp)
1696 {
1697  NTSTATUS Status;
1698  PIO_STACK_LOCATION Stack;
1699  PMOUNTDEV_UNIQUE_ID UniqueId;
1700  PMOUNTMGR_MOUNT_POINT MountPoint;
1702 
1704 
1705  /* Validate input... */
1706  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1707  {
1708  return STATUS_INVALID_PARAMETER;
1709  }
1710 
1711  MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1712  if (!MountPoint->SymbolicLinkNameLength)
1713  {
1714  MountPoint->SymbolicLinkNameOffset = 0;
1715  }
1716 
1717  if (!MountPoint->UniqueIdLength)
1718  {
1719  MountPoint->UniqueIdOffset = 0;
1720  }
1721 
1722  if (!MountPoint->DeviceNameLength)
1723  {
1724  MountPoint->DeviceNameOffset = 0;
1725  }
1726 
1727  /* Addresses can't be odd */
1728  if ((MountPoint->SymbolicLinkNameOffset & 1) ||
1729  (MountPoint->SymbolicLinkNameLength & 1))
1730  {
1731  return STATUS_INVALID_PARAMETER;
1732  }
1733 
1734  if ((MountPoint->UniqueIdOffset & 1) ||
1735  (MountPoint->UniqueIdLength & 1))
1736  {
1737  return STATUS_INVALID_PARAMETER;
1738  }
1739 
1740  if ((MountPoint->DeviceNameOffset & 1) ||
1741  (MountPoint->DeviceNameLength & 1))
1742  {
1743  return STATUS_INVALID_PARAMETER;
1744  }
1745 
1746  /* We can't go beyond */
1747  if (((ULONG)MountPoint->SymbolicLinkNameLength + MountPoint->UniqueIdLength +
1748  MountPoint->DeviceNameLength) < Stack->Parameters.DeviceIoControl.InputBufferLength)
1749  {
1750  return STATUS_INVALID_PARAMETER;
1751  }
1752 
1753  if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_MOUNT_POINTS))
1754  {
1755  return STATUS_INVALID_PARAMETER;
1756  }
1757 
1758  /* If caller provided a Symlink, use it */
1759  if (MountPoint->SymbolicLinkNameLength != 0)
1760  {
1761  if (MountPoint->SymbolicLinkNameLength > MAXSHORT)
1762  {
1763  return STATUS_INVALID_PARAMETER;
1764  }
1765 
1767  SymbolicName.MaximumLength = MountPoint->SymbolicLinkNameLength + sizeof(WCHAR);
1769  if (!SymbolicName.Buffer)
1770  {
1772  }
1773 
1775  (PWSTR)((ULONG_PTR)MountPoint + MountPoint->SymbolicLinkNameOffset),
1778 
1779  /* Query links using it */
1782  }
1783  /* If user provided an unique ID */
1784  else if (MountPoint->UniqueIdLength != 0)
1785  {
1786  UniqueId = AllocatePool(MountPoint->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1787  if (!UniqueId)
1788  {
1790  }
1791 
1792  UniqueId->UniqueIdLength = MountPoint->UniqueIdLength;
1793  RtlCopyMemory(UniqueId->UniqueId,
1794  (PVOID)((ULONG_PTR)MountPoint + MountPoint->UniqueIdOffset),
1795  MountPoint->UniqueIdLength);
1796 
1797  /* Query links using it */
1798  Status = QueryPointsFromMemory(DeviceExtension, Irp, UniqueId, NULL);
1799  FreePool(UniqueId);
1800  }
1801  /* If caller provided a device name */
1802  else if (MountPoint->DeviceNameLength != 0)
1803  {
1804  if (MountPoint->DeviceNameLength > MAXSHORT)
1805  {
1806  return STATUS_INVALID_PARAMETER;
1807  }
1808 
1809  DeviceName.Length = MountPoint->DeviceNameLength;
1810  DeviceName.MaximumLength = MountPoint->DeviceNameLength + sizeof(WCHAR);
1811  DeviceName.Buffer = AllocatePool(DeviceName.MaximumLength);
1812  if (!DeviceName.Buffer)
1813  {
1815  }
1816 
1817  RtlCopyMemory(DeviceName.Buffer,
1818  (PWSTR)((ULONG_PTR)MountPoint + MountPoint->DeviceNameOffset),
1819  DeviceName.Length);
1820  DeviceName.Buffer[DeviceName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1821 
1822  /* Query links using it */
1823  Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, &DeviceName);
1824  FreePool(DeviceName.Buffer);
1825  }
1826  else
1827  {
1828  /* Otherwise, query all links */
1829  Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, NULL);
1830  }
1831 
1832  return Status;
1833 }
1834 
1835 /*
1836  * @implemented
1837  */
1838 NTSTATUS
1840  IN PIRP Irp)
1841 {
1842  ULONG Link;
1843  NTSTATUS Status;
1844  BOOLEAN CreateNoDrive;
1845  PIO_STACK_LOCATION Stack;
1846  PMOUNTDEV_UNIQUE_ID UniqueId;
1847  PMOUNTMGR_MOUNT_POINT MountPoint;
1848  PMOUNTMGR_MOUNT_POINTS MountPoints;
1850 
1852 
1853  /* Validate input */
1854  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1855  {
1856  return STATUS_INVALID_PARAMETER;
1857  }
1858 
1859  /* Query points */
1860  MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1861  CreateNoDrive = (MountPoint->SymbolicLinkNameOffset && MountPoint->SymbolicLinkNameLength);
1862 
1863  Status = MountMgrQueryPoints(DeviceExtension, Irp);
1864  if (!NT_SUCCESS(Status))
1865  {
1866  return Status;
1867  }
1868 
1869  /* For all the points matching the request */
1870  MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1871  for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1872  {
1876  if (!SymbolicName.Buffer)
1877  {
1879  }
1880 
1882  (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1885 
1886  /* Create a no drive entry for the drive letters */
1887  if (CreateNoDrive && IsDriveLetter(&SymbolicName))
1888  {
1889  UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1890  if (UniqueId)
1891  {
1892  UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1893  RtlCopyMemory(UniqueId->UniqueId,
1894  (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1895  MountPoints->MountPoints[Link].UniqueIdLength);
1896 
1897  CreateNoDriveLetterEntry(UniqueId);
1898  FreePool(UniqueId);
1899  }
1900  }
1901 
1902  /* If there are no link any more, and no need to create a no drive entry */
1903  if (Link == 0 && !CreateNoDrive)
1904  {
1905  /* Then, delete everything */
1906  UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength);
1907  if (UniqueId)
1908  {
1909  RtlCopyMemory(UniqueId,
1910  (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1911  MountPoints->MountPoints[Link].UniqueIdLength);
1912 
1913  DeleteNoDriveLetterEntry(UniqueId);
1914  FreePool(UniqueId);
1915  }
1916  }
1917 
1918  /* Delete all the information about the mount point */
1923 
1924  /* Notify the change */
1925  DeviceName.Length = DeviceName.MaximumLength =
1926  MountPoints->MountPoints[Link].DeviceNameLength;
1927  DeviceName.Buffer = (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].DeviceNameOffset);
1928  MountMgrNotifyNameChange(DeviceExtension, &DeviceName, TRUE);
1929  }
1930 
1931  MountMgrNotify(DeviceExtension);
1932 
1933  return Status;
1934 }
1935 
1936 /*
1937  * @implemented
1938  */
1939 NTSTATUS
1941  IN PIRP Irp)
1942 {
1943  ULONG Link;
1944  NTSTATUS Status;
1946  PMOUNTDEV_UNIQUE_ID UniqueId;
1947  PMOUNTMGR_MOUNT_POINTS MountPoints;
1948 
1949  /* Query points */
1950  Status = MountMgrQueryPoints(DeviceExtension, Irp);
1951  if (!NT_SUCCESS(Status))
1952  {
1953  return Status;
1954  }
1955 
1956  MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1957  if (MountPoints->NumberOfMountPoints == 0)
1958  {
1959  return Status;
1960  }
1961 
1962  /* For all the mount points */
1963  for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1964  {
1968  if (!SymbolicName.Buffer)
1969  {
1971  }
1972 
1974  (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1977 
1978  /* If the only mount point is a drive letter, then create a no letter drive entry */
1979  if (MountPoints->NumberOfMountPoints == 1 && IsDriveLetter(&SymbolicName))
1980  {
1981  UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1982  if (UniqueId)
1983  {
1984  UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1985  RtlCopyMemory(UniqueId->UniqueId,
1986  (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1987  MountPoints->MountPoints[Link].UniqueIdLength);
1988 
1989  CreateNoDriveLetterEntry(UniqueId);
1990  FreePool(UniqueId);
1991  }
1992  }
1993 
1994  /* Simply delete mount point from DB */
1998  }
1999 
2000  return Status;
2001 }
2002 
2003 /*
2004  * @implemented
2005  */
2006 NTSTATUS
2008  IN PIRP Irp,
2009  IN NTSTATUS LockStatus,
2010  OUT PUNICODE_STRING SourceDeviceName,
2011  OUT PUNICODE_STRING SourceSymbolicName,
2012  OUT PUNICODE_STRING TargetVolumeName)
2013 {
2014  HANDLE Handle;
2015  NTSTATUS Status;
2017  PIO_STACK_LOCATION Stack;
2018  ULONG Length, SavedLength;
2019  BOOLEAN FOReferenced = FALSE;
2022  PDEVICE_INFORMATION DeviceInformation;
2023  OBJECT_NAME_INFORMATION ObjectNameInfo;
2024  FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
2025  PFILE_NAME_INFORMATION FileNameInfo = NULL;
2026  PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint;
2027  POBJECT_NAME_INFORMATION ObjectNameInfoPtr = NULL;
2028  UNICODE_STRING SourceVolumeName, TargetDeviceName;
2029 
2031 
2032  /* Validate input */
2033  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_VOLUME_MOUNT_POINT))
2034  {
2035  return STATUS_INVALID_PARAMETER;
2036  }
2037 
2038  VolumeMountPoint = (PMOUNTMGR_VOLUME_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
2039 
2040  if (((ULONG)VolumeMountPoint->SourceVolumeNameLength + VolumeMountPoint->TargetVolumeNameLength) <
2041  Stack->Parameters.DeviceIoControl.InputBufferLength)
2042  {
2043  return STATUS_INVALID_PARAMETER;
2044  }
2045 
2046  /* Get source volume name */
2047  SourceVolumeName.Length =
2048  SourceVolumeName.MaximumLength = VolumeMountPoint->SourceVolumeNameLength;
2049  SourceVolumeName.Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset);
2050 
2052  &SourceVolumeName,
2054  NULL,
2055  NULL);
2056 
2057  /* Open it */
2061  &IoStatusBlock,
2064  if (!NT_SUCCESS(Status))
2065  {
2066  return Status;
2067  }
2068 
2069  TargetDeviceName.Buffer = NULL;
2070 
2071  /* Query its attributes */
2073  &IoStatusBlock,
2074  &FsDeviceInfo,
2075  sizeof(FsDeviceInfo),
2077  if (!NT_SUCCESS(Status))
2078  {
2079  goto Cleanup;
2080  }
2081 
2082  if (FsDeviceInfo.DeviceType != FILE_DEVICE_DISK && FsDeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK)
2083  {
2084  goto Cleanup;
2085  }
2086 
2088  {
2089  goto Cleanup;
2090  }
2091 
2092  /* Reference it */
2094  if (!NT_SUCCESS(Status))
2095  {
2096  goto Cleanup;
2097  }
2098  FOReferenced = TRUE;
2099 
2100  /* Get file name */
2101  FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION));
2102  if (!FileNameInfo)
2103  {
2105  goto Cleanup;
2106  }
2107 
2108  Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2109  sizeof(FILE_NAME_INFORMATION),
2112  {
2113  /* Now we have real length, use it */
2114  Length = FileNameInfo->FileNameLength;
2115  FreePool(FileNameInfo);
2116 
2117  FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + Length);
2118  if (!FileNameInfo)
2119  {
2121  goto Cleanup;
2122  }
2123 
2124  /* Really query file name */
2125  Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2126  sizeof(FILE_NAME_INFORMATION) + Length,
2128  }
2129 
2130  if (!NT_SUCCESS(Status))
2131  {
2132  goto Cleanup;
2133  }
2134 
2135  /* Get symbolic name */
2136  ObjectNameInfoPtr = &ObjectNameInfo;
2137  SavedLength = sizeof(OBJECT_NAME_INFORMATION);
2138  Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, sizeof(OBJECT_NAME_INFORMATION), &Length);
2140  {
2141  /* Once again, with proper size, it works better */
2142  ObjectNameInfoPtr = AllocatePool(Length);
2143  if (!ObjectNameInfoPtr)
2144  {
2146  goto Cleanup;
2147  }
2148 
2149  SavedLength = Length;
2150  Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, SavedLength, &Length);
2151  }
2152 
2153  if (!NT_SUCCESS(Status))
2154  {
2155  goto Cleanup;
2156  }
2157 
2158  /* Now, query the device name */
2159  Status = QueryDeviceInformation(&ObjectNameInfoPtr->Name, SourceDeviceName,
2160  NULL, NULL, NULL, NULL, NULL, NULL);
2161  if (!NT_SUCCESS(Status))
2162  {
2163  goto Cleanup;
2164  }
2165 
2166  /* For target volume name, use input */
2167  TargetVolumeName->Length =
2168  TargetVolumeName->MaximumLength = VolumeMountPoint->TargetVolumeNameLength;
2169  TargetVolumeName->Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset);
2170 
2171  /* Query its device name */
2172  Status = QueryDeviceInformation(TargetVolumeName, &TargetDeviceName,
2173  NULL, NULL, NULL, NULL, NULL, NULL);
2174  if (!NT_SUCCESS(Status))
2175  {
2176  goto Cleanup;
2177  }
2178 
2179  /* Return symbolic name */
2180  SourceSymbolicName->Length =
2181  SourceSymbolicName->MaximumLength = (USHORT)FileNameInfo->FileNameLength;
2182  SourceSymbolicName->Buffer = (PWSTR)FileNameInfo;
2183  /* memmove allows memory overlap */
2184  RtlMoveMemory(SourceSymbolicName->Buffer, FileNameInfo->FileName, SourceSymbolicName->Length);
2185  FileNameInfo = NULL;
2186 
2187  /* Notify the change */
2188  MountMgrNotify(DeviceExtension);
2189  MountMgrNotifyNameChange(DeviceExtension, &TargetDeviceName, TRUE);
2190 
2191  /* If we are locked, sync databases if possible */
2192  if (NT_SUCCESS(LockStatus))
2193  {
2194  Status = FindDeviceInfo(DeviceExtension, SourceDeviceName, FALSE, &DeviceInformation);
2195  if (NT_SUCCESS(Status))
2196  {
2197  ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
2198  }
2199  else
2200  {
2202  }
2203  }
2204 
2205 Cleanup:
2206  if (TargetDeviceName.Buffer)
2207  {
2208  FreePool(TargetDeviceName.Buffer);
2209  }
2210 
2211  if (ObjectNameInfoPtr && ObjectNameInfoPtr != &ObjectNameInfo)
2212  {
2213  FreePool(ObjectNameInfoPtr);
2214  }
2215 
2216  if (FileNameInfo)
2217  {
2218  FreePool(FileNameInfo);
2219  }
2220 
2221  if (FOReferenced)
2222  {
2224  }
2225 
2226  return Status;
2227 }
2228 
2229 /*
2230  * @implemented
2231  */
2232 NTSTATUS
2234  IN PIRP Irp,
2235  IN NTSTATUS LockStatus)
2236 {
2237  LONG Offset;
2238  BOOLEAN Found;
2239  NTSTATUS Status;
2241  PMOUNTDEV_UNIQUE_ID UniqueId;
2242  PDATABASE_ENTRY DatabaseEntry;
2243  PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2244  PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2245  UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2246 
2247  /* Initialize string */
2248  LinkTarget.Length = 0;
2249  LinkTarget.MaximumLength = 0xC8;
2251  if (LinkTarget.Buffer == NULL)
2252  {
2254  }
2255 
2256  /* If the mount point was created, then, it changed!
2257  * Also use it to query some information
2258  */
2259  Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2260  /* Pending means DB are under synchronization, bail out */
2261  if (Status == STATUS_PENDING)
2262  {
2264  FreePool(SourceDeviceName.Buffer);
2265  FreePool(SourceSymbolicName.Buffer);
2266  return STATUS_SUCCESS;
2267  }
2268  else if (!NT_SUCCESS(Status))
2269  {
2271  return Status;
2272  }
2273 
2274  /* Query the device information */
2275  Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2276  if (!NT_SUCCESS(Status))
2277  {
2278  /* If it failed, first try to get volume name */
2279  Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2280  if (!NT_SUCCESS(Status))
2281  {
2282  /* Then, try to read the symlink */
2283  Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2284  if (!NT_SUCCESS(Status))
2285  {
2287  FreePool(SourceDeviceName.Buffer);
2288  FreePool(SourceSymbolicName.Buffer);
2289  return Status;
2290  }
2291  }
2292  else
2293  {
2295  }
2296 
2297  FreePool(SourceDeviceName.Buffer);
2298 
2299  SourceDeviceName.Length = LinkTarget.Length;
2300  SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2301  SourceDeviceName.Buffer = LinkTarget.Buffer;
2302 
2303  /* Now that we have the correct source, reattempt to query information */
2304  Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2305  if (!NT_SUCCESS(Status))
2306  {
2307  FreePool(SourceDeviceName.Buffer);
2308  FreePool(SourceSymbolicName.Buffer);
2309  return Status;
2310  }
2311  }
2312 
2313  FreePool(SourceDeviceName.Buffer);
2314 
2315  /* Get information about target device */
2316  Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2317  if (!NT_SUCCESS(Status))
2318  {
2319  FreePool(SourceSymbolicName.Buffer);
2320  return Status;
2321  }
2322 
2323  /* Notify if not disabled */
2324  if (!TargetDeviceInformation->SkipNotifications)
2325  {
2326  PostOnlineNotification(DeviceExtension, &TargetDeviceInformation->SymbolicName);
2327  }
2328 
2329  /* Open the remote database */
2330  RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2331  if (RemoteDatabase == 0)
2332  {
2333  FreePool(SourceSymbolicName.Buffer);
2335  }
2336 
2337  /* Browse all the entries */
2338  Offset = 0;
2339  Found = FALSE;
2340  for (;;)
2341  {
2342  DatabaseEntry = GetRemoteDatabaseEntry(RemoteDatabase, Offset);
2343  if (DatabaseEntry == NULL)
2344  {
2345  break;
2346  }
2347 
2348  /* Try to find ourselves */
2349  DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2350  DbName.Length = DbName.MaximumLength;
2351  DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2352  if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2353  {
2354  /* Reference ourselves and update the entry */
2355  ++DatabaseEntry->EntryReferences;
2357  FreePool(DatabaseEntry);
2358  Found = TRUE;
2359  break;
2360  }
2361 
2362  Offset += DatabaseEntry->EntrySize;
2363  FreePool(DatabaseEntry);
2364  }
2365 
2366  /* We couldn't find ourselves, we'll have to add ourselves */
2367  if (!Found)
2368  {
2369  ULONG EntrySize;
2370  PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2371 
2372  /* Query the device unique ID */
2373  Status = QueryDeviceInformation(&TargetVolumeName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
2374  if (!NT_SUCCESS(Status))
2375  {
2376  FreePool(SourceSymbolicName.Buffer);
2378  return Status;
2379  }
2380 
2381  /* Allocate a database entry */
2382  EntrySize = UniqueId->UniqueIdLength + TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2383  DatabaseEntry = AllocatePool(EntrySize);
2384  if (DatabaseEntry == NULL)
2385  {
2386  FreePool(UniqueId);
2387  FreePool(SourceSymbolicName.Buffer);
2390  }
2391 
2392  /* Fill it in */
2393  DatabaseEntry->EntrySize = EntrySize;
2394  DatabaseEntry->EntryReferences = 1;
2395  DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
2396  DatabaseEntry->SymbolicNameLength = TargetVolumeName.Length;
2397  DatabaseEntry->UniqueIdOffset = TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2398  DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
2399  RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + sizeof(DATABASE_ENTRY)), TargetVolumeName.Buffer, DatabaseEntry->SymbolicNameLength);
2400  RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
2401 
2402  /* And write it down */
2403  Status = AddRemoteDatabaseEntry(RemoteDatabase, DatabaseEntry);
2404  FreePool(DatabaseEntry);
2405  if (!NT_SUCCESS(Status))
2406  {
2407  FreePool(UniqueId);
2408  FreePool(SourceSymbolicName.Buffer);
2410  return Status;
2411  }
2412 
2413  /* And now, allocate an Unique ID item */
2414  UniqueIdReplicate = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
2415  if (UniqueIdReplicate == NULL)
2416  {
2417  FreePool(UniqueId);
2418  FreePool(SourceSymbolicName.Buffer);
2420  return Status;
2421  }
2422 
2423  /* To associate it with the device */
2424  UniqueIdReplicate->UniqueId = UniqueId;
2425  InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2426  }
2427 
2428  /* We're done with the remote database */
2430 
2431  /* Check we were find writing the entry */
2432  if (!NT_SUCCESS(Status))
2433  {
2434  FreePool(SourceSymbolicName.Buffer);
2435  return Status;
2436  }
2437 
2438  /* This is the end, allocate an associated entry */
2439  AssociatedEntry = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY));
2440  if (AssociatedEntry == NULL)
2441  {
2442  FreePool(SourceSymbolicName.Buffer);
2444  }
2445 
2446  /* Initialize its source name string */
2447  AssociatedEntry->String.Length = SourceSymbolicName.Length;
2448  AssociatedEntry->String.MaximumLength = AssociatedEntry->String.Length + sizeof(UNICODE_NULL);
2449  AssociatedEntry->String.Buffer = AllocatePool(AssociatedEntry->String.MaximumLength);
2450  if (AssociatedEntry->String.Buffer == NULL)
2451  {
2452  FreePool(AssociatedEntry);
2453  FreePool(SourceSymbolicName.Buffer);
2455  }
2456 
2457  /* Copy data & insert in list */
2458  RtlCopyMemory(AssociatedEntry->String.Buffer, SourceSymbolicName.Buffer, SourceSymbolicName.Length);
2459  AssociatedEntry->String.Buffer[SourceSymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
2460  AssociatedEntry->DeviceInformation = DeviceInformation;
2461  InsertTailList(&TargetDeviceInformation->AssociatedDevicesHead, &AssociatedEntry->AssociatedDevicesEntry);
2462 
2463  /* We're done! */
2464  FreePool(SourceSymbolicName.Buffer);
2465  return STATUS_SUCCESS;
2466 }
2467 
2468 /*
2469  * @implemented
2470  */
2471 NTSTATUS
2473  IN PIRP Irp,
2474  IN NTSTATUS LockStatus)
2475 {
2476  LONG Offset;
2477  NTSTATUS Status;
2480  PDATABASE_ENTRY DatabaseEntry;
2481  PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2482  PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2483  PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2484  UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2485 
2486  /* Initialize string */
2487  LinkTarget.Length = 0;
2488  LinkTarget.MaximumLength = 0xC8;
2490  if (LinkTarget.Buffer == NULL)
2491  {
2493  }
2494 
2495  /* If the mount point was deleted, then, it changed!
2496  * Also use it to query some information
2497  */
2498  Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2499  /* Pending means DB are under synchronization, bail out */
2500  if (Status == STATUS_PENDING)
2501  {
2503  FreePool(SourceDeviceName.Buffer);
2504  FreePool(SourceSymbolicName.Buffer);
2505  return STATUS_SUCCESS;
2506  }
2507  else if (!NT_SUCCESS(Status))
2508  {
2510  return Status;
2511  }
2512 
2513  /* Query the device information */
2514  Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2515  if (!NT_SUCCESS(Status))
2516  {
2517  /* If it failed, first try to get volume name */
2518  Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2519  if (!NT_SUCCESS(Status))
2520  {
2521  /* Then, try to read the symlink */
2522  Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2523  if (!NT_SUCCESS(Status))
2524  {
2526  FreePool(SourceDeviceName.Buffer);
2527  FreePool(SourceSymbolicName.Buffer);
2528  return Status;
2529  }
2530  }
2531  else
2532  {
2534  }
2535 
2536  FreePool(SourceDeviceName.Buffer);
2537 
2538  SourceDeviceName.Length = LinkTarget.Length;
2539  SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2540  SourceDeviceName.Buffer = LinkTarget.Buffer;
2541 
2542  /* Now that we have the correct source, reattempt to query information */
2543  Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2544  if (!NT_SUCCESS(Status))
2545  {
2546  FreePool(SourceDeviceName.Buffer);
2547  FreePool(SourceSymbolicName.Buffer);
2548  return Status;
2549  }
2550  }
2551 
2552  FreePool(SourceDeviceName.Buffer);
2553 
2554  /* Get information about target device */
2555  Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2556  if (!NT_SUCCESS(Status))
2557  {
2558  FreePool(SourceSymbolicName.Buffer);
2559  return Status;
2560  }
2561 
2562  /* Open the remote database */
2563  RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2564  if (RemoteDatabase == 0)
2565  {
2566  FreePool(SourceSymbolicName.Buffer);
2568  }
2569 
2570  /* Browse all the entries */
2571  Offset = 0;
2572  for (;;)
2573  {
2574  DatabaseEntry = GetRemoteDatabaseEntry(RemoteDatabase, Offset);
2575  if (DatabaseEntry == NULL)
2576  {
2577  /* We didn't find ourselves, that's infortunate! */
2578  FreePool(SourceSymbolicName.Buffer);
2580  return STATUS_INVALID_PARAMETER;
2581  }
2582 
2583  /* Try to find ourselves */
2584  DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2585  DbName.Length = DbName.MaximumLength;
2586  DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2587  if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2588  {
2589  break;
2590  }
2591 
2592  Offset += DatabaseEntry->EntrySize;
2593  FreePool(DatabaseEntry);
2594  }
2595 
2596  /* Dereference ourselves */
2597  DatabaseEntry->EntryReferences--;
2598  if (DatabaseEntry->EntryReferences == 0)
2599  {
2600  /* If we're still referenced, just update the entry */
2602  }
2603  else
2604  {
2605  /* Otherwise, delete the entry */
2607  if (!NT_SUCCESS(Status))
2608  {
2609  FreePool(DatabaseEntry);
2610  FreePool(SourceSymbolicName.Buffer);
2612  return Status;
2613  }
2614 
2615  /* Also, delete our unique ID replicated record */
2616  for (Entry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
2617  Entry != &DeviceInformation->ReplicatedUniqueIdsListHead;
2618  Entry = Entry->Flink)
2619  {
2620  UniqueIdReplicate = CONTAINING_RECORD(Entry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
2621 
2622  if (UniqueIdReplicate->UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
2623  RtlCompareMemory(UniqueIdReplicate->UniqueId->UniqueId,
2624  (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
2625  DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
2626  {
2627  break;
2628  }
2629  }
2630 
2631  /* It has to exist! */
2632  if (Entry == &DeviceInformation->ReplicatedUniqueIdsListHead)
2633  {
2634  FreePool(DatabaseEntry);
2635  FreePool(SourceSymbolicName.Buffer);
2637  return STATUS_UNSUCCESSFUL;
2638  }
2639 
2640  /* Remove it and free it */
2641  RemoveEntryList(&UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2642  FreePool(UniqueIdReplicate->UniqueId);
2643  FreePool(UniqueIdReplicate);
2644  }
2645 
2646  /* We're done with the remote database */
2647  FreePool(DatabaseEntry);
2649 
2650  /* Check write operation succeed */
2651  if (!NT_SUCCESS(Status))
2652  {
2653  FreePool(SourceSymbolicName.Buffer);
2654  return Status;
2655  }
2656 
2657  /* Try to find our associated device entry */
2658  for (Entry = TargetDeviceInformation->AssociatedDevicesHead.Flink;
2659  Entry != &TargetDeviceInformation->AssociatedDevicesHead;
2660  Entry = Entry->Flink)
2661  {
2662  AssociatedEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
2663 
2664  /* If found, delete it */
2665  if (AssociatedEntry->DeviceInformation == DeviceInformation &&
2666  RtlEqualUnicodeString(&AssociatedEntry->String, &SourceSymbolicName, TRUE))
2667  {
2668  RemoveEntryList(&AssociatedEntry->AssociatedDevicesEntry);
2669  FreePool(AssociatedEntry->String.Buffer);
2670  FreePool(AssociatedEntry);
2671  break;
2672  }
2673  }
2674 
2675  /* We're done! */
2676  FreePool(SourceSymbolicName.Buffer);
2677  return STATUS_SUCCESS;
2678 }
2679 
2680 /*
2681  * @implemented
2682  */
2683 NTSTATUS
2684 NTAPI
2686  IN PIRP Irp)
2687 {
2688  PIO_STACK_LOCATION Stack;
2689  NTSTATUS Status, LockStatus;
2690  PDEVICE_EXTENSION DeviceExtension;
2691 
2693  DeviceExtension = DeviceObject->DeviceExtension;
2694 
2695  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2696 
2697  switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2698  {
2700  Status = MountMgrCreatePoint(DeviceExtension, Irp);
2701  break;
2702 
2704  Status = MountMgrDeletePoints(DeviceExtension, Irp);
2705  break;
2706 
2708  Status = MountMgrQueryPoints(DeviceExtension, Irp);
2709  break;
2710 
2712  Status = MountMgrDeletePointsDbOnly(DeviceExtension, Irp);
2713  break;
2714 
2716  Status = MountMgrNextDriveLetter(DeviceExtension, Irp);
2717  break;
2718 
2720  DeviceExtension->AutomaticDriveLetter = TRUE;
2722 
2723  MountMgrAssignDriveLetters(DeviceExtension);
2724  ReconcileAllDatabasesWithMaster(DeviceExtension);
2725  WaitForOnlinesToComplete(DeviceExtension);
2726  break;
2727 
2729  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2730 
2731  LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2732  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2733  Status = MountMgrVolumeMountPointCreated(DeviceExtension, Irp, LockStatus);
2734  if (NT_SUCCESS(LockStatus))
2735  {
2736  ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2737  }
2738 
2739  break;
2740 
2742  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2743 
2744  LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2745  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2746  Status = MountMgrVolumeMountPointDeleted(DeviceExtension, Irp, LockStatus);
2747  if (NT_SUCCESS(LockStatus))
2748  {
2749  ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2750  }
2751 
2752  break;
2753 
2755  Status = MountMgrChangeNotify(DeviceExtension, Irp);
2756  break;
2757 
2759  Status = MountMgrKeepLinksWhenOffline(DeviceExtension, Irp);
2760  break;
2761 
2763  Status = MountMgrCheckUnprocessedVolumes(DeviceExtension, Irp);
2764  goto Complete;
2765 
2767  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2768  Status = MountMgrVolumeArrivalNotification(DeviceExtension, Irp);
2769  goto Complete;
2770 
2772  Status = MountMgrQueryDosVolumePath(DeviceExtension, Irp);
2773  break;
2774 
2776  Status = MountMgrQueryDosVolumePaths(DeviceExtension, Irp);
2777  break;
2778 
2780  Status = MountMgrScrubRegistry(DeviceExtension);
2781  break;
2782 
2784  Status = MountMgrQueryAutoMount(DeviceExtension, Irp);
2785  break;
2786 
2788  Status = MountMgrSetAutoMount(DeviceExtension, Irp);
2789  break;
2790 
2793  DPRINT1("Winism! Rewrite the caller!\n");
2794  default:
2796  }
2797 
2798  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2799 
2800  if (Status != STATUS_PENDING)
2801  {
2802  goto Complete;
2803  }
2804 
2805  return Status;
2806 
2807 Complete:
2808  Irp->IoStatus.Status = Status;
2810 
2811  return Status;
2812 }
struct _MOUNTMGR_VOLUME_MOUNT_POINT * PMOUNTMGR_VOLUME_MOUNT_POINT
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
Definition: mountmgr.h:127
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
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:2007
USHORT UniqueIdOffset
Definition: mntmgr.h:91
VOID NTAPI MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1691
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:82
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:3988
#define IN
Definition: typedefs.h:38
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
VOID NTAPI ReconcileThisDatabaseWithMasterWorker(IN PVOID Parameter)
Definition: database.c:560
struct _MOUNTMGR_DRIVE_LETTER_INFORMATION * PMOUNTMGR_DRIVE_LETTER_INFORMATION
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
NTSTATUS MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo)
Definition: device.c:457
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
UNICODE_STRING DosDevices
Definition: symlink.c:33
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
NTSTATUS DeleteRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:233
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR)
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED
Definition: mountmgr.h:40
struct _Entry Entry
Definition: kefuncs.h:640
ULONG EntryReferences
Definition: mntmgr.h:88
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
_In_ BOOLEAN Release
Definition: classpnp.h:929
USHORT MaximumLength
Definition: env_spec_w32.h:370
struct _REPARSE_DATA_BUFFER::@299::@301 SymbolicLinkReparseBuffer
ULONG EntrySize
Definition: mntmgr.h:87
struct _MOUNTMGR_MOUNT_POINTS * PMOUNTMGR_MOUNT_POINTS
#define REG_BINARY
Definition: nt_native.h:1496
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED
Definition: mountmgr.h:38
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
__wchar_t WCHAR
Definition: xmlstorage.h:180
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:54
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:138
#define MAX_DEVICES
Definition: device.c:28
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:1168
NTSTATUS MountMgrQuerySymbolicLink(IN PUNICODE_STRING SymbolicName, IN OUT PUNICODE_STRING LinkTarget)
Definition: symlink.c:961
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:98
_In_ PCWSTR _In_z_ PCWSTR _In_ ULONG ValueType
Definition: rtlfuncs.h:4000
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4658
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
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:924
#define IOCTL_MOUNTMGR_SET_AUTO_MOUNT
Definition: mountmgr.h:154
UNICODE_STRING RemoteDatabase
Definition: database.c:34
#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:1135
unsigned short Length
Definition: sprintf.c:451
BOOLEAN IsFtVolume(IN PUNICODE_STRING SymbolicName)
Definition: device.c:331
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1434
#define FILE_DEVICE_VIRTUAL_DISK
Definition: winioctl.h:141
VOID DeleteSymbolicLinkNameFromMemory(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLink, IN BOOLEAN MarkOffline)
Definition: symlink.c:866
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
NTSTATUS MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:288
NTSTATUS MountMgrQueryAutoMount(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:136
#define LETTER_POSITION
Definition: mntmgr.h:159
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
UNICODE_STRING Name
Definition: nt_native.h:1270
WCHAR DeviceName[]
Definition: adapter.cpp:21
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:97
#define InsertTailList(ListHead, Entry)
USHORT SymbolicNameLength
Definition: mntmgr.h:90
#define WCHAR
Definition: msvc.h:43
VOID DeleteNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:2079
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:640
#define FreePool(P)
Definition: mntmgr.h:154
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
_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:125
#define IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
Definition: mountmgr.h:16
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
Definition: imports.h:130
NTSTATUS MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus)
Definition: device.c:2233
NTSTATUS MountMgrCreatePoint(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:249
#define IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE
Definition: mountmgr.h:44
uint32_t ULONG_PTR
Definition: typedefs.h:63
NTSTATUS MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1651
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
NTSTATUS MountMgrValidateBackPointer(IN PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry, IN PDEVICE_INFORMATION DeviceInformation, OUT PBOOLEAN Invalid)
Definition: device.c:1063
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
#define IOCTL_MOUNTMGR_QUERY_POINTS
Definition: mountmgr.h:30
NTSTATUS MountMgrChangeNotify(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:37
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
void * Buffer
Definition: sprintf.c:453
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1594
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:496
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
Definition: mountmgr.h:129
HANDLE OpenRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN BOOLEAN MigrateDatabase)
Definition: database.c:1817
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
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define UNICODE_NULL
NTSTATUS MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName)
Definition: device.c:733
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
Definition: mountmgr.h:34
long LONG
Definition: pedump.c:60
MOUNTMGR_AUTO_MOUNT_STATE NewState
Definition: mountmgr.h:167
#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:434
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 MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1839
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:3988
smooth NULL
Definition: ftsmooth.c:416
#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 FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:651
return Found
Definition: dirsup.c:1270
void * PVOID
Definition: retypes.h:9
NTSTATUS MountMgrVolumeMountPointDeleted(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus)
Definition: device.c:2472
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
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
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1405
NTSTATUS MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1458
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:204
#define IOCTL_MOUNTMGR_CHANGE_NOTIFY
Definition: mountmgr.h:42
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:118
NTSTATUS CloseRemoteDatabase(IN HANDLE Database)
Definition: database.c:82
struct _DATABASE_ENTRY DATABASE_ENTRY
NTSTATUS MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1607
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
#define STATUS_NOT_FOUND
Definition: shellext.h:67
BOOLEAN KeepLinks
Definition: mntmgr.h:51
BOOLEAN SkipNotifications
Definition: mntmgr.h:58
struct _MOUNTMGR_SET_AUTO_MOUNT * PMOUNTMGR_SET_AUTO_MOUNT
if(!(yy_init))
Definition: macro.lex.yy.c:714
NTSTATUS MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1940
VOID NTAPI PsSetThreadHardErrorsAreDisabled(IN PETHREAD Thread, IN BOOLEAN HardErrorsAreDisabled)
Definition: thread.c:898
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define STATUS_PENDING
Definition: ntstatus.h:82
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:271
Definition: mntmgr.h:95
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:2101
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
NTSTATUS NTAPI MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: device.c:693
_In_ PSTRING FullName
Definition: rtlfuncs.h:1649
USHORT SymbolicNameOffset
Definition: mntmgr.h:89
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
NTSTATUS QueryPointsFromSymbolicLinkName(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN PIRP Irp)
Definition: point.c:426
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Must_inspect_result_ typedef _In_ ULONG _In_ BOOLEAN Target
Definition: iotypes.h:1067
* PFILE_OBJECT
Definition: iotypes.h:1954
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define MOUNTMGR_IS_DRIVE_LETTER(s)
Definition: mountmgr.h:53
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
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
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)
volatile int Continue
Definition: gdblib.c:102
struct _MOUNTMGR_CHANGE_NOTIFY_INFO MOUNTMGR_CHANGE_NOTIFY_INFO
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:269
char * PBOOLEAN
Definition: retypes.h:11
struct Point Point
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
NTSTATUS MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1694
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:88
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
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: arc.h:85
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
MOUNTMGR_AUTO_MOUNT_STATE CurrentState
Definition: mountmgr.h:163
#define FILE_REMOTE_DEVICE
Definition: nt_native.h:811
BOOLEAN NTAPI PsGetThreadHardErrorsAreDisabled(IN PETHREAD Thread)
Definition: thread.c:695
#define IOCTL_MOUNTMGR_DEFINE_UNIX_DRIVE
Definition: mountmgr.h:15
Definition: typedefs.h:117
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
PWSTR DatabasePath
Definition: database.c:31
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:716
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
Status
Definition: gdiplustypes.h:24
#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
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:105
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
NTSTATUS MountMgrSetAutoMount(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:104
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define MAXSHORT
Definition: umtypes.h:114
NTSTATUS NTAPI MountMgrDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: device.c:2685
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
NTSTATUS WriteRemoteDatabaseEntry(IN HANDLE Database, IN LONG Offset, IN PDATABASE_ENTRY Entry)
Definition: database.c:200
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
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
#define COLON_POSITION
Definition: mntmgr.h:160
VOID ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:403
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
NTSTATUS MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:647
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
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:1273
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
NTSTATUS MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:221
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:87
VOID MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:762
NTSTATUS MountmgrWriteNoAutoMount(IN PDEVICE_EXTENSION DeviceExtension)
Definition: device.c:87
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
NTSTATUS WaitForRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:371
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
PDATABASE_ENTRY GetRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:125
#define OUT
Definition: typedefs.h:39
ULONG SymbolicLinkNameOffset
Definition: imports.h:166
LIST_ENTRY ReplicatedUniqueIdsListHead
Definition: mntmgr.h:46
#define IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY
Definition: mountmgr.h:32
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
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:261
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
Definition: mntmgr.h:102
NTSTATUS AddRemoteDatabaseEntry(IN HANDLE Database, IN PDATABASE_ENTRY Entry)
Definition: database.c:64
PDEVICE_EXTENSION DeviceExtension
Definition: mntmgr.h:117
#define IOCTL_MOUNTMGR_SCRUB_REGISTRY
Definition: mountmgr.h:150
NTSTATUS MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:836
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
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
VOID ReleaseRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:391
VOID ReconcileAllDatabasesWithMaster(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:1640
NTSTATUS MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION Extension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN FromVolume)
Definition: mountmgr.c:946
return STATUS_SUCCESS
Definition: btrfs.c:2725
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:539
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE
Definition: iotypes.h:6856
#define CHAR(Char)
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:49
#define DRIVE_LETTER_LENGTH
Definition: mntmgr.h:161
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#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
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:350
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
#define REG_SZ
Definition: layer.c:22
struct _MOUNTMGR_CHANGE_NOTIFY_INFO * PMOUNTMGR_CHANGE_NOTIFY_INFO