ReactOS  0.4.14-dev-77-gd9e7c48
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 = sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO);
61  return STATUS_SUCCESS;
62  }
63 
64  /* If IRP is to be canceled, forget about that */
66  if (Irp->Cancel)
67  {
69  }
70  /* Otherwise queue the IRP to be notified with the next epic number change */
71  else
72  {
73  InsertTailList(&(DeviceExtension->IrpListHead), &(Irp->Tail.Overlay.ListEntry));
77  }
79 
80  return Status;
81 }
82 
83 /*
84  * @implemented
85  */
88 {
89  ULONG Value = DeviceExtension->NoAutoMount;
90 
92  DeviceExtension->RegistryPath.Buffer,
93  L"NoAutoMount",
94  REG_DWORD,
95  &Value,
96  sizeof(Value));
97 
98 }
99 
100 /*
101  * @implemented
102  */
103 NTSTATUS
105  IN PIRP Irp)
106 {
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 IsFTPartition(PartitionInfo.PartitionType);
397 }
398 
399 /*
400  * @implemented
401  */
402 VOID
404 {
405  WCHAR NameBuffer[DRIVE_LETTER_LENGTH / sizeof(WCHAR)];
406  PLIST_ENTRY NextEntry;
408  PDEVICE_INFORMATION DeviceInformation;
409 
410  /* No devices? Nothing to do! */
411  if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
412  {
413  return;
414  }
415 
416  /* For all the devices */
417  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
418  NextEntry != &(DeviceExtension->DeviceListHead);
419  NextEntry = NextEntry->Flink)
420  {
421  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
422 
423  /* If no drive letter */
424  if (DeviceInformation->SuggestedDriveLetter == (UCHAR)-1)
425  {
426  /* Ensure it has no entry yet */
427  if (!HasDriveLetter(DeviceInformation) &&
428  !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
429  {
430  /* And create one */
431  CreateNoDriveLetterEntry(DeviceInformation->UniqueId);
432  }
433 
434  DeviceInformation->SuggestedDriveLetter = 0;
435  }
436  /* Suggested letter & no entry */
437  else if (DeviceInformation->SuggestedDriveLetter &&
438  !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
439  {
440  /* Just create a mount point */
441  SymbolicName.Buffer = NameBuffer;
443  NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
444  NameBuffer[COLON_POSITION] = L':';
447 
448  MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &(DeviceInformation->DeviceName));
449  }
450  }
451 }
452 
453 /*
454  * @implemented
455  */
456 NTSTATUS
459  OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo)
460 {
462  UCHAR DriveLetter;
463  PLIST_ENTRY NextEntry;
464  PMOUNTDEV_UNIQUE_ID UniqueId;
465  BOOLEAN Removable, GptDriveLetter;
466  PDEVICE_INFORMATION DeviceInformation;
467  WCHAR NameBuffer[DRIVE_LETTER_LENGTH];
468  PSYMLINK_INFORMATION SymlinkInformation;
469  UNICODE_STRING TargetDeviceName, SymbolicName;
470 
471  /* First, process suggested letters */
472  if (!DeviceExtension->ProcessedSuggestions)
473  {
474  ProcessSuggestedDriveLetters(DeviceExtension);
475  DeviceExtension->ProcessedSuggestions = TRUE;
476  }
477 
478  /* Then, get information about the device */
479  Status = QueryDeviceInformation(DeviceName, &TargetDeviceName, NULL, &Removable, &GptDriveLetter, NULL, NULL, NULL);
480  if (!NT_SUCCESS(Status))
481  {
482  return Status;
483  }
484 
485  /* Ensure we have such device */
486  NextEntry = DeviceExtension->DeviceListHead.Flink;
487  while (NextEntry != &(DeviceExtension->DeviceListHead))
488  {
489  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
490 
491  if (RtlCompareUnicodeString(&(DeviceInformation->DeviceName), &TargetDeviceName, TRUE) == 0)
492  {
493  break;
494  }
495 
496  NextEntry = NextEntry->Flink;
497  }
498 
499  if (NextEntry == &(DeviceExtension->DeviceListHead))
500  {
501  FreePool(TargetDeviceName.Buffer);
503  }
504 
505  /* Now, mark we have assigned a letter (assumption) */
506  DeviceInformation->LetterAssigned =
507  DriveLetterInfo->DriveLetterWasAssigned = TRUE;
508 
509  /* Browse all the symlinks to check if there is already a drive letter */
510  NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
511  while (NextEntry != &(DeviceInformation->SymbolicLinksListHead))
512  {
513  SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
514 
515  /* If this is a drive letter and it is online, forget about new drive letter */
516  if (IsDriveLetter(&(SymlinkInformation->Name)) && SymlinkInformation->Online)
517  {
518  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
519  DriveLetterInfo->CurrentDriveLetter = (CHAR)SymlinkInformation->Name.Buffer[LETTER_POSITION];
520  break;
521  }
522 
523  NextEntry = NextEntry->Flink;
524  }
525 
526  /* If we didn't find a drive letter online
527  * ensure this is not a no drive entry
528  * by querying GPT attributes & database
529  */
530  if (NextEntry == &(DeviceInformation->SymbolicLinksListHead))
531  {
532  if (!GptDriveLetter || HasNoDriveLetterEntry(DeviceInformation->UniqueId))
533  {
534  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
535  DriveLetterInfo->CurrentDriveLetter = 0;
536 
537  goto Release;
538  }
539  }
540 
541  /* No, ensure that the device is not automounted nor removable */
542  if (!DeviceExtension->NoAutoMount && !Removable)
543  {
544  if (DriveLetterInfo->DriveLetterWasAssigned)
545  {
546  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
547  DriveLetterInfo->CurrentDriveLetter = 0;
548 
549  goto Release;
550  }
551  }
552 
553  if (!DriveLetterInfo->DriveLetterWasAssigned)
554  {
555  goto Release;
556  }
557 
558  /* Now everything is fine, start processing */
559 
560  if (RtlPrefixUnicodeString(&DeviceFloppy, &TargetDeviceName, TRUE))
561  {
562  /* If the device is a floppy, start with letter A */
563  DriveLetter = 'A';
564  }
565  else if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
566  {
567  /* If the device is a CD-ROM, start with letter D */
568  DriveLetter = 'D';
569  }
570  else
571  {
572  /* Finally, if it's a disk, use C */
573  DriveLetter = 'C';
574  }
575 
576  /* We cannot set NO drive letter */
577  ASSERT(DeviceInformation->SuggestedDriveLetter != (UCHAR)-1);
578 
579  /* If we don't have suggested letter but it's a FT volume, fail */
580  if (!DeviceInformation->SuggestedDriveLetter && IsFtVolume(&(DeviceInformation->DeviceName)))
581  {
582  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
583  DriveLetterInfo->CurrentDriveLetter = 0;
584 
585  goto Release;
586  }
587 
588  /* Prepare buffer */
590  NameBuffer[COLON_POSITION] = L':';
591  SymbolicName.Buffer = NameBuffer;
594 
595  /* It's all prepared, create mount point */
596  if (DeviceInformation->SuggestedDriveLetter)
597  {
598  DriveLetterInfo->CurrentDriveLetter = DeviceInformation->SuggestedDriveLetter;
599  NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
600 
601  Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
602  if (NT_SUCCESS(Status))
603  {
604  goto Release;
605  }
606  }
607 
608  /* It failed with this letter... Try another one! */
609  for (DriveLetterInfo->CurrentDriveLetter = DriveLetter;
610  DriveLetterInfo->CurrentDriveLetter <= L'Z';
611  DriveLetterInfo->CurrentDriveLetter++)
612  {
613  NameBuffer[LETTER_POSITION] = DriveLetterInfo->CurrentDriveLetter;
614 
615  Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
616  if (NT_SUCCESS(Status))
617  {
618  break;
619  }
620  }
621 
622  /* We failed setting a letter */
623  if (DriveLetterInfo->CurrentDriveLetter > L'Z')
624  {
625  DriveLetterInfo->DriveLetterWasAssigned = FALSE;
626  DriveLetterInfo->CurrentDriveLetter = 0;
627 
628  /* Try at least to add a no drive letter entry */
629  Status = QueryDeviceInformation(&TargetDeviceName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
630  if (NT_SUCCESS(Status))
631  {
632  CreateNoDriveLetterEntry(UniqueId);
633  FreePool(UniqueId);
634  }
635  }
636 
637 Release:
638  FreePool(TargetDeviceName.Buffer);
639 
640  return STATUS_SUCCESS;
641 }
642 
643 
644 /*
645  * @implemented
646  */
647 NTSTATUS
649  IN PIRP Irp)
650 {
652  PIO_STACK_LOCATION Stack;
654  PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget;
655  MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
656 
658 
659  /* Validate input */
660  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) ||
661  Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION))
662  {
664  }
665 
666  DriveLetterTarget = (PMOUNTMGR_DRIVE_LETTER_TARGET)Irp->AssociatedIrp.SystemBuffer;
667  if (DriveLetterTarget->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
668  {
670  }
671 
672  /* Call the worker */
673  DeviceName.Buffer = DriveLetterTarget->DeviceName;
674  DeviceName.Length =
675  DeviceName.MaximumLength = DriveLetterTarget->DeviceNameLength;
676 
677  Status = MountMgrNextDriveLetterWorker(DeviceExtension, &DeviceName,
678  &DriveLetterInformation);
679  if (NT_SUCCESS(Status))
680  {
681  *(PMOUNTMGR_DRIVE_LETTER_INFORMATION)Irp->AssociatedIrp.SystemBuffer =
682  DriveLetterInformation;
683  Irp->IoStatus.Information = sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION);
684  }
685 
686  return Status;
687 }
688 
689 /*
690  * @implemented
691  */
692 NTSTATUS
693 NTAPI
698  IN PVOID Context,
700 {
701  UNICODE_STRING ValueString;
702  PUNICODE_STRING SystemVolumeName;
703 
707 
708  if (ValueType != REG_SZ)
709  {
710  return STATUS_SUCCESS;
711  }
712 
713  RtlInitUnicodeString(&ValueString, ValueData);
714  SystemVolumeName = Context;
715 
716  /* Return a string containing system volume name */
717  SystemVolumeName->Length = ValueString.Length;
718  SystemVolumeName->MaximumLength = ValueString.Length + sizeof(WCHAR);
719  SystemVolumeName->Buffer = AllocatePool(SystemVolumeName->MaximumLength);
720  if (SystemVolumeName->Buffer)
721  {
722  RtlCopyMemory(SystemVolumeName->Buffer, ValueData, ValueString.Length);
723  SystemVolumeName->Buffer[ValueString.Length / sizeof(WCHAR)] = UNICODE_NULL;
724  }
725 
726  return STATUS_SUCCESS;
727 
728 }
729 
730 /*
731  * @implemented
732  */
733 NTSTATUS
735 {
737 
741  QueryTable[0].Name = L"SystemPartition";
742 
743  SystemVolumeName->Buffer = NULL;
744 
746  L"\\Registry\\Machine\\System\\Setup",
747  QueryTable,
748  SystemVolumeName,
749  NULL);
750 
751  if (SystemVolumeName->Buffer)
752  {
753  return STATUS_SUCCESS;
754  }
755 
756  return STATUS_UNSUCCESSFUL;
757 }
758 
759 /*
760  * @implemented
761  */
762 VOID
764 {
766  PLIST_ENTRY NextEntry;
767  UNICODE_STRING SystemVolumeName;
768  PDEVICE_INFORMATION DeviceInformation;
769  MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
770 
771  /* First, get system volume name */
772  Status = MountMgrQuerySystemVolumeName(&SystemVolumeName);
773 
774  /* If there are no device, it's all done */
775  if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
776  {
777  if (NT_SUCCESS(Status))
778  {
779  FreePool(SystemVolumeName.Buffer);
780  }
781 
782  return;
783  }
784 
785  /* Now, for all the devices... */
786  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
787  NextEntry != &(DeviceExtension->DeviceListHead);
788  NextEntry = NextEntry->Flink)
789  {
790  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
791 
792  /* If the device doesn't have a letter assigned, do it! */
793  if (!DeviceInformation->LetterAssigned)
794  {
795  MountMgrNextDriveLetterWorker(DeviceExtension,
796  &(DeviceInformation->DeviceName),
797  &DriveLetterInformation);
798  }
799 
800  /* If it was the system volume */
801  if (NT_SUCCESS(Status) && RtlEqualUnicodeString(&SystemVolumeName, &(DeviceInformation->DeviceName), TRUE))
802  {
803  /* Keep track of it */
804  DeviceExtension->DriveLetterData = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength +
805  sizeof(MOUNTDEV_UNIQUE_ID));
806  if (DeviceExtension->DriveLetterData)
807  {
808  RtlCopyMemory(DeviceExtension->DriveLetterData,
809  DeviceInformation->UniqueId,
810  DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
811  }
812 
813  /* If it was not automount, ensure it gets mounted */
814  if (!DeviceExtension->NoAutoMount)
815  {
816  DeviceExtension->NoAutoMount = TRUE;
817 
818  MountMgrNextDriveLetterWorker(DeviceExtension,
819  &(DeviceInformation->DeviceName),
820  &DriveLetterInformation);
821 
822  DeviceExtension->NoAutoMount = FALSE;
823  }
824  }
825  }
826 
827  if (NT_SUCCESS(Status))
828  {
829  FreePool(SystemVolumeName.Buffer);
830  }
831 }
832 
833 /*
834  * @implemented
835  */
836 NTSTATUS
838  IN PIRP Irp)
839 {
841  ULONG DevicesFound;
842  PIO_STACK_LOCATION Stack;
843  PLIST_ENTRY SymlinksEntry;
846  PWSTR DeviceString, OldBuffer;
847  USHORT DeviceLength, OldLength;
848  PDEVICE_INFORMATION DeviceInformation;
849  PSYMLINK_INFORMATION SymlinkInformation;
850  PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
851 
853 
854  /* Validate input size */
855  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
856  {
858  }
859 
860  /* Ensure we have received UNICODE_STRING */
861  Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
862  if (Target->DeviceNameLength & 1)
863  {
865  }
866 
867  /* Validate the entry structure size */
868  if (Target->DeviceNameLength + sizeof(UNICODE_NULL) > Stack->Parameters.DeviceIoControl.InputBufferLength)
869  {
871  }
872 
873  /* Ensure we can at least return needed size */
874  if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
875  {
877  }
878 
879  /* Construct string for query */
880  SymbolicName.Length = Target->DeviceNameLength;
881  SymbolicName.MaximumLength = Target->DeviceNameLength + sizeof(UNICODE_NULL);
882  SymbolicName.Buffer = Target->DeviceName;
883 
884  /* Find device with our info */
885  Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
886  if (!NT_SUCCESS(Status))
887  {
888  return Status;
889  }
890 
891  DeviceLength = 0;
892  DeviceString = NULL;
893  DevicesFound = 0;
894 
895  /* Try to find associated device info */
896  while (TRUE)
897  {
898  for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
899  SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
900  SymlinksEntry = SymlinksEntry->Flink)
901  {
902  SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
903 
904  /* Try to find with drive letter */
905  if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
906  {
907  break;
908  }
909  }
910 
911  /* We didn't find, break */
912  if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
913  {
914  break;
915  }
916 
917  /* It doesn't have associated device, go to fallback method */
918  if (IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
919  {
920  goto TryWithVolumeName;
921  }
922 
923  /* Create a string with the information about the device */
924  AssociatedDevice = CONTAINING_RECORD(&(DeviceInformation->SymbolicLinksListHead), ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
925  OldLength = DeviceLength;
926  OldBuffer = DeviceString;
927  DeviceLength += AssociatedDevice->String.Length;
928  DeviceString = AllocatePool(DeviceLength);
929  if (!DeviceString)
930  {
931  if (OldBuffer)
932  {
933  FreePool(OldBuffer);
934  }
935 
937  }
938 
939  /* Store our info and previous if any */
940  RtlCopyMemory(DeviceString, AssociatedDevice->String.Buffer, AssociatedDevice->String.Length);
941  if (OldBuffer)
942  {
943  RtlCopyMemory(&DeviceString[AssociatedDevice->String.Length / sizeof(WCHAR)], OldBuffer, OldLength);
944  FreePool(OldBuffer);
945  }
946 
947  /* Count and continue looking */
948  ++DevicesFound;
949  DeviceInformation = AssociatedDevice->DeviceInformation;
950 
951  /* If too many devices, try another way */
952  if (DevicesFound > MAX_DEVICES) /* 1000 */
953  {
954  goto TryWithVolumeName;
955  }
956  }
957 
958  /* Reallocate our string, so that we can prepend disk letter */
959  OldBuffer = DeviceString;
960  OldLength = DeviceLength;
961  DeviceLength += 2 * sizeof(WCHAR);
962  DeviceString = AllocatePool(DeviceLength);
963  if (!DeviceString)
964  {
965  if (OldBuffer)
966  {
967  FreePool(OldBuffer);
968  }
969 
971  }
972 
973  /* Get the letter */
974  DeviceString[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
975  DeviceString[1] = L':';
976 
977  /* And copy the rest */
978  if (OldBuffer)
979  {
980  RtlCopyMemory(&DeviceString[2], OldBuffer, OldLength);
981  FreePool(OldBuffer);
982  }
983 
984 TryWithVolumeName:
985  /* If we didn't find anything, try differently */
986  if (DeviceLength < 2 * sizeof(WCHAR) || DeviceString[1] != L':')
987  {
988  if (DeviceString)
989  {
990  FreePool(DeviceString);
991  DeviceLength = 0;
992  }
993 
994  /* Try to find a volume name matching */
995  for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
996  SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
997  SymlinksEntry = SymlinksEntry->Flink)
998  {
999  SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1000 
1001  if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation->Name))
1002  {
1003  break;
1004  }
1005  }
1006 
1007  /* If found copy */
1008  if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
1009  {
1010  DeviceLength = SymlinkInformation->Name.Length;
1011  DeviceString = AllocatePool(DeviceLength);
1012  if (!DeviceString)
1013  {
1015  }
1016 
1017  RtlCopyMemory(DeviceString, SymlinkInformation->Name.Buffer, DeviceLength);
1018  /* Ensure we are in the right namespace; [1] can be ? */
1019  DeviceString[1] = L'\\';
1020  }
1021  }
1022 
1023  /* If we found something */
1024  if (DeviceString)
1025  {
1026  /* At least, we will return our length */
1027  ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSzLength = DeviceLength;
1028  /* MOUNTMGR_VOLUME_PATHS is a string + a ULONG */
1029  Irp->IoStatus.Information = DeviceLength + sizeof(ULONG);
1030 
1031  /* If we have enough room for copying the string */
1032  if (sizeof(ULONG) + DeviceLength <= Stack->Parameters.DeviceIoControl.OutputBufferLength)
1033  {
1034  /* Copy it */
1035  if (DeviceLength)
1036  {
1037  RtlCopyMemory(((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz, DeviceString, DeviceLength);
1038  }
1039 
1040  /* And double zero at its end - this is needed in case of multiple paths which are separated by a single 0 */
1041  FreePool(DeviceString);
1042  ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR)] = 0;
1043  ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR) + 1] = 0;
1044 
1045  return STATUS_SUCCESS;
1046  }
1047  else
1048  {
1049  /* Just return appropriate size and leave */
1050  FreePool(DeviceString);
1051  Irp->IoStatus.Information = sizeof(ULONG);
1052  return STATUS_BUFFER_OVERFLOW;
1053  }
1054  }
1055 
1056  /* Fail */
1057  return STATUS_NOT_FOUND;
1058 }
1059 
1060 /*
1061  * @implemented
1062  */
1063 NTSTATUS
1065  IN PDEVICE_INFORMATION DeviceInformation,
1066  OUT PBOOLEAN Invalid)
1067 {
1068  HANDLE Handle;
1069  NTSTATUS Status;
1070  PLIST_ENTRY SymlinksEntry;
1072  PREPARSE_DATA_BUFFER ReparseData;
1074  UNICODE_STRING FullName, SubstituteName;
1075  PSYMLINK_INFORMATION SymlinkInformation;
1076 
1077  /* Initialize & allocate a string big enough to contain our complete mount point name */
1078  FullName.Length = AssociatedDeviceEntry->String.Length + AssociatedDeviceEntry->DeviceInformation->DeviceName.Length + sizeof(WCHAR);
1081  if (!FullName.Buffer)
1082  {
1084  }
1085 
1086  /* Create the path */
1087  RtlCopyMemory(FullName.Buffer, AssociatedDeviceEntry->DeviceInformation->DeviceName.Buffer, AssociatedDeviceEntry->DeviceInformation->DeviceName.Length);
1088  FullName.Buffer[AssociatedDeviceEntry->DeviceInformation->DeviceName.Length / sizeof(WCHAR)] = L'\\';
1089  RtlCopyMemory(&FullName.Buffer[AssociatedDeviceEntry->DeviceInformation->DeviceName.Length / sizeof(WCHAR) + 1], AssociatedDeviceEntry->String.Buffer, AssociatedDeviceEntry->String.Length);
1091 
1092  /* Open it to query the reparse point */
1094  &FullName,
1096  NULL,
1097  NULL);
1104 
1105  if (!NT_SUCCESS(Status))
1106  {
1107  *Invalid = TRUE;
1108  return STATUS_SUCCESS;
1109  }
1110 
1111  /* Allocate a buffer big enough to read reparse data */
1113  if (ReparseData == NULL)
1114  {
1115  ZwClose(Handle);
1117  }
1118 
1119  /* Query reparse data */
1121  NULL, NULL, NULL,
1122  &IoStatusBlock,
1124  NULL, 0,
1125  ReparseData, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1126  ZwClose(Handle);
1127 
1128  if (!NT_SUCCESS(Status))
1129  {
1130  FreePool(ReparseData);
1131  *Invalid = TRUE;
1132  return STATUS_SUCCESS;
1133  }
1134 
1135  /* Create a string with the substitute name */
1136  SubstituteName.Length = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
1137  SubstituteName.MaximumLength = SubstituteName.Length;
1138  SubstituteName.Buffer = (PWSTR)((ULONG_PTR)ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset);
1139 
1140  /* If that's a volume name that matches our associated device, that's a success! */
1141  if (MOUNTMGR_IS_VOLUME_NAME(&SubstituteName))
1142  {
1143  if (SubstituteName.Length == 98 && SubstituteName.Buffer[1] == L'?')
1144  {
1145  for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1146  SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
1147  SymlinksEntry = SymlinksEntry->Flink)
1148  {
1149  SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1150 
1151  if (RtlEqualUnicodeString(&SubstituteName, &SymlinkInformation->Name, TRUE))
1152  {
1153  FreePool(ReparseData);
1154  return STATUS_SUCCESS;
1155  }
1156  }
1157  }
1158  }
1159 
1160  FreePool(ReparseData);
1161  *Invalid = TRUE;
1162  return STATUS_SUCCESS;
1163 }
1164 
1165 /*
1166  * @implemented
1167  */
1168 NTSTATUS
1170  IN PDEVICE_INFORMATION DeviceInformation,
1171  IN PLIST_ENTRY DeviceInfoList,
1172  OUT PMOUNTMGR_VOLUME_PATHS * VolumePaths,
1173  OUT PDEVICE_INFORMATION *FailedDevice)
1174 {
1175  ULONG Written;
1176  NTSTATUS Status;
1178  PSYMLINK_INFORMATION SymlinkInformation;
1179  PDEVICE_INFORMATION_ENTRY DeviceInfoEntry;
1180  PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry;
1181  PMOUNTMGR_VOLUME_PATHS * Paths = NULL, * CurrentPath;
1182  ULONG OutputPathLength, NumberOfPaths, ReturnedPaths;
1183 
1184  /* We return at least null char */
1185  OutputPathLength = sizeof(UNICODE_NULL);
1186 
1187  for (Entry = DeviceInformation->SymbolicLinksListHead.Flink;
1188  Entry != &(DeviceInformation->SymbolicLinksListHead);
1189  Entry = Entry->Flink)
1190  {
1191  SymlinkInformation = CONTAINING_RECORD(Entry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1192 
1193  /* Try to find the drive letter (ie, DOS device) */
1194  if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
1195  {
1196  /* We'll return the letter */
1197  OutputPathLength = 4 * sizeof(WCHAR);
1198  break;
1199  }
1200  }
1201 
1202  /* We didn't find any */
1203  if (Entry == &(DeviceInformation->SymbolicLinksListHead))
1204  {
1205  SymlinkInformation = NULL;
1206  }
1207 
1208  /* Do we have any device info to return? */
1209  for (Entry = DeviceInfoList->Flink; Entry != DeviceInfoList; Entry = Entry->Flink)
1210  {
1211  DeviceInfoEntry = CONTAINING_RECORD(Entry, DEVICE_INFORMATION_ENTRY, DeviceInformationEntry);
1212 
1213  /* Matching current device */
1214  if (DeviceInfoEntry->DeviceInformation == DeviceInformation)
1215  {
1216  /* Allocate the output buffer */
1217  *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1218  if (*VolumePaths == NULL)
1219  {
1221  }
1222 
1223  /* Set size */
1224  (*VolumePaths)->MultiSzLength = OutputPathLength;
1225  /* If we have a drive letter, return it */
1226  if (SymlinkInformation != NULL)
1227  {
1228  (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1229  (*VolumePaths)->MultiSz[1] = L':';
1230  (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1231  (*VolumePaths)->MultiSz[3] = UNICODE_NULL;
1232  }
1233  else
1234  {
1235  (*VolumePaths)->MultiSz[0] = UNICODE_NULL;
1236  }
1237 
1238  return STATUS_SUCCESS;
1239  }
1240  }
1241 
1242  /* Allocate a new device entry */
1243  DeviceInfoEntry = AllocatePool(sizeof(DEVICE_INFORMATION_ENTRY));
1244  if (DeviceInfoEntry == NULL)
1245  {
1247  }
1248 
1249  /* Add it to the list */
1250  DeviceInfoEntry->DeviceInformation = DeviceInformation;
1251  InsertTailList(DeviceInfoList, &DeviceInfoEntry->DeviceInformationEntry);
1252 
1253  NumberOfPaths = 0;
1254  /* Count the amount of devices we will have to handle */
1255  if (!IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
1256  {
1257  for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1258  Entry != &DeviceInformation->AssociatedDevicesHead;
1259  Entry = Entry->Flink)
1260  {
1261  ++NumberOfPaths;
1262  }
1263 
1264  ASSERT(NumberOfPaths != 0);
1265  /* And allocate a big enough buffer */
1266  Paths = AllocatePool(NumberOfPaths * sizeof(PMOUNTMGR_VOLUME_PATHS));
1267  if (Paths == NULL)
1268  {
1269  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1270  FreePool(DeviceInfoEntry);
1272  }
1273  }
1274 
1275  /* Start the hot loop to gather all the paths and be able to compute total output length! */
1276  ReturnedPaths = 0;
1277  CurrentPath = Paths;
1278  for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1279  Entry != &DeviceInformation->AssociatedDevicesHead;
1280  Entry = Entry->Flink)
1281  {
1282  USHORT InnerStrings;
1283  BOOLEAN Invalid = FALSE;
1284 
1285  AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1286 
1287  /* Validate the fact its a mount point by query reparse data */
1288  Status = MountMgrValidateBackPointer(AssociatedDeviceEntry, DeviceInformation, &Invalid);
1289 
1290  /* If we found an invalid device, that's a failure */
1291  if (Invalid)
1292  {
1293  *FailedDevice = AssociatedDeviceEntry->DeviceInformation;
1295  }
1296 
1297  /* Check whether we failed, if so, bail out */
1298  if (!NT_SUCCESS(Status))
1299  {
1300  ULONG i;
1301 
1302  for (i = 0; i < ReturnedPaths; ++i)
1303  {
1304  FreePool(Paths[i]);
1305  }
1306 
1307  if (Paths != NULL)
1308  {
1309  FreePool(Paths);
1310  }
1311  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1312  FreePool(DeviceInfoEntry);
1313  return Status;
1314  }
1315 
1316  /* Query associated paths (hello ourselves :-)) */
1317  Status = MountMgrQueryVolumePaths(DeviceExtension,
1318  AssociatedDeviceEntry->DeviceInformation,
1319  DeviceInfoList,
1320  CurrentPath,
1321  FailedDevice);
1322  if (!NT_SUCCESS(Status))
1323  {
1324  ULONG i;
1325 
1326  for (i = 0; i < ReturnedPaths; ++i)
1327  {
1328  FreePool(Paths[i]);
1329  }
1330 
1331  if (Paths != NULL)
1332  {
1333  FreePool(Paths);
1334  }
1335  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1336  FreePool(DeviceInfoEntry);
1337  return Status;
1338  }
1339 
1340  /* Count the number of strings we have in the multi string buffer */
1341  InnerStrings = 0;
1342  if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1343  {
1344  ULONG i;
1345  PWSTR MultiSz = (*CurrentPath)->MultiSz;
1346 
1347  for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR); ++i, ++MultiSz)
1348  {
1349  if (*MultiSz == UNICODE_NULL)
1350  {
1351  ++InnerStrings;
1352  }
1353  }
1354  }
1355 
1356  /* We returned one more path (ie, one more allocated buffer) */
1357  ++ReturnedPaths;
1358  /* Move the next pointer to use in the array */
1359  ++CurrentPath;
1360  /* Multiply String.Length by the number of found paths, we always add it after a path */
1361  OutputPathLength += (*CurrentPath)->MultiSzLength + InnerStrings * AssociatedDeviceEntry->String.Length - sizeof(UNICODE_NULL);
1362  }
1363 
1364  /* Allocate the output buffer */
1365  *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1366  if (*VolumePaths == NULL)
1367  {
1368  ULONG i;
1369 
1370  for (i = 0; i < ReturnedPaths; ++i)
1371  {
1372  FreePool(Paths[i]);
1373  }
1374 
1375  if (Paths != NULL)
1376  {
1377  FreePool(Paths);
1378  }
1379  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1380  FreePool(DeviceInfoEntry);
1382  }
1383 
1384  Written = 0;
1385  /* If we had found a DOS letter, that's the first thing we return */
1386  (*VolumePaths)->MultiSzLength = OutputPathLength;
1387  if (SymlinkInformation != NULL)
1388  {
1389  (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1390  (*VolumePaths)->MultiSz[1] = L':';
1391  (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1392  Written = 3;
1393  }
1394 
1395  /* Now, browse again all our paths to return them */
1396  CurrentPath = Paths;
1397  for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1398  Entry != &DeviceInformation->AssociatedDevicesHead;
1399  Entry = Entry->Flink)
1400  {
1401  AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1402 
1403  /* If we had a path... */
1404  if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1405  {
1406  ULONG i, Offset;
1407  PWSTR MultiSz;
1408 
1409  /* This offset is used to "jump" into MultiSz, so, start with the string begin (ie, skip MultiSzLength) */
1410  Offset = sizeof(ULONG);
1411  /* Browse every single letter, and skip last UNICODE_NULL */
1412  for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR) - 1; ++i)
1413  {
1414  /* Get the letter */
1415  MultiSz = (PWSTR)((ULONG_PTR)(*CurrentPath) + Offset);
1416  /* If it was part of the path, just return it */
1417  if (*MultiSz != UNICODE_NULL)
1418  {
1419  (*VolumePaths)->MultiSz[Written] = *MultiSz;
1420  }
1421  else
1422  {
1423  /* Otherwise, as planed, return our whole associated device name */
1424  RtlCopyMemory(&(*VolumePaths)->MultiSz[Written],
1425  AssociatedDeviceEntry->String.Buffer,
1426  AssociatedDeviceEntry->String.Length);
1427  Written += AssociatedDeviceEntry->String.Length / sizeof(WCHAR);
1428  /* And don't forget to nullify */
1429  (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1430  }
1431 
1432  /* We at least return a letter or a null char */
1433  ++Written;
1434  /* Move to the next letter */
1435  Offset += sizeof(WCHAR);
1436  }
1437  }
1438 
1439  FreePool(*CurrentPath);
1440  ++CurrentPath;
1441  }
1442 
1443  /* MultiSz: don't forget last null char */
1444  (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1445  /* Cleanup everything and return success! */
1446  if (Paths != NULL)
1447  {
1448  FreePool(Paths);
1449  }
1450  RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1451  FreePool(DeviceInfoEntry);
1452  return STATUS_SUCCESS;
1453 }
1454 
1455 /*
1456  * @implemented
1457  */
1458 NTSTATUS
1460  IN PIRP Irp)
1461 {
1462  NTSTATUS Status;
1464  LIST_ENTRY Devices;
1465  BOOLEAN NeedNotification;
1466  PIO_STACK_LOCATION Stack;
1468  ULONG Attempts, OutputLength;
1471  RECONCILE_WORK_ITEM_CONTEXT ReconcileContext;
1472  PDEVICE_INFORMATION DeviceInformation, ListDeviceInfo, FailedDevice;
1473 
1475 
1476  /* Validate input size */
1477  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1478  {
1479  return STATUS_INVALID_PARAMETER;
1480  }
1481 
1482  /* Ensure we have received UNICODE_STRING */
1483  Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1484  if (Target->DeviceNameLength & 1)
1485  {
1486  return STATUS_INVALID_PARAMETER;
1487  }
1488 
1489  /* Validate the entry structure size */
1490  if (Target->DeviceNameLength + FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1491  {
1492  return STATUS_INVALID_PARAMETER;
1493  }
1494 
1495  /* Ensure we can at least return needed size */
1496  if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
1497  {
1498  return STATUS_INVALID_PARAMETER;
1499  }
1500 
1501  /* Construct string for query */
1502  SymbolicName.Length = Target->DeviceNameLength;
1503  SymbolicName.MaximumLength = Target->DeviceNameLength + sizeof(UNICODE_NULL);
1504  SymbolicName.Buffer = Target->DeviceName;
1505 
1506  /* Find device with our info */
1507  Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1508  if (!NT_SUCCESS(Status))
1509  {
1510  return Status;
1511  }
1512 
1513  NeedNotification = FALSE;
1514  Attempts = 0;
1515  for (;;)
1516  {
1517  FailedDevice = NULL;
1518  InitializeListHead(&Devices);
1519 
1520  /* Query paths */
1521  Status = MountMgrQueryVolumePaths(DeviceExtension, DeviceInformation, &Devices, &Paths, &FailedDevice);
1522  if (NT_SUCCESS(Status))
1523  {
1524  break;
1525  }
1526 
1527  /* If it failed for generic reason (memory, whatever), bail out (ie, FailedDevice not set) */
1528  if (FailedDevice == NULL)
1529  {
1530  return Status;
1531  }
1532 
1533  /* If PnP, let's notify in case of success */
1534  if (!DeviceInformation->ManuallyRegistered)
1535  {
1536  NeedNotification = TRUE;
1537  }
1538 
1539  /* Reconcile database */
1540  ReconcileContext.DeviceExtension = DeviceExtension;
1541  ReconcileContext.DeviceInformation = FailedDevice;
1542  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1543  ReconcileThisDatabaseWithMasterWorker(&ReconcileContext);
1544  KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1545 
1546  /* Look for our device, to check it's online */
1547  for (Entry = DeviceExtension->DeviceListHead.Flink;
1548  Entry != &DeviceExtension->DeviceListHead;
1549  Entry = Entry->Flink)
1550  {
1551  ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
1552  /* It's online, it's OK! */
1553  if (ListDeviceInfo == DeviceInformation)
1554  {
1555  break;
1556  }
1557  }
1558 
1559  /* It's not online, it's not good */
1560  if (Entry == &DeviceExtension->DeviceListHead)
1561  {
1563  }
1564 
1565  /* Increase attempts count */
1566  ++Attempts;
1567  /* Don't look forever and fail if we get out of attempts */
1568  if (Attempts >= 1000)
1569  {
1570  return Status;
1571  }
1572  }
1573 
1574  /* We need to notify? Go ahead */
1575  if (NeedNotification)
1576  {
1577  MountMgrNotifyNameChange(DeviceExtension, &SymbolicName, FALSE);
1578  }
1579 
1580  /* Get output buffer */
1581  Output = (PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer;
1582 
1583  /* Set required size */
1584  Output->MultiSzLength = Paths->MultiSzLength;
1585 
1586  /* Compute total length */
1587  OutputLength = Output->MultiSzLength + sizeof(ULONG);
1588 
1589  /* If it cannot fit, just return need size and quit */
1590  if (OutputLength > Stack->Parameters.DeviceIoControl.OutputBufferLength)
1591  {
1592  Irp->IoStatus.Information = sizeof(ULONG);
1593  FreePool(Paths);
1594  return STATUS_BUFFER_OVERFLOW;
1595  }
1596 
1597  /* Copy data and quit */
1598  Irp->IoStatus.Information = OutputLength;
1599  RtlCopyMemory(Output->MultiSz, Paths->MultiSz, Output->MultiSzLength);
1600  FreePool(Paths);
1601  return STATUS_SUCCESS;
1602 }
1603 
1604 /*
1605  * @implemented
1606  */
1607 NTSTATUS
1609  IN PIRP Irp)
1610 {
1611  NTSTATUS Status;
1612  PIO_STACK_LOCATION Stack;
1615  PDEVICE_INFORMATION DeviceInformation;
1616 
1618 
1619  /* Validate input */
1620  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1621  {
1622  return STATUS_INVALID_PARAMETER;
1623  }
1624 
1625  Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1626  if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1627  {
1628  return STATUS_INVALID_PARAMETER;
1629  }
1630 
1632  SymbolicName.MaximumLength = Target->DeviceNameLength;
1633  SymbolicName.Buffer = Target->DeviceName;
1634 
1635  /* Find the associated device */
1636  Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1637  if (!NT_SUCCESS(Status))
1638  {
1639  return Status;
1640  }
1641 
1642  /* Mark we want to keep links */
1643  DeviceInformation->KeepLinks = TRUE;
1644 
1645  return STATUS_SUCCESS;
1646 }
1647 
1648 /*
1649  * @implemented
1650  */
1651 NTSTATUS
1653  IN PIRP Irp)
1654 {
1655  NTSTATUS Status;
1656  BOOLEAN OldState;
1657  PIO_STACK_LOCATION Stack;
1660 
1662 
1663  /* Validate input */
1664  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1665  {
1666  return STATUS_INVALID_PARAMETER;
1667  }
1668 
1669  Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1670  if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1671  {
1672  return STATUS_INVALID_PARAMETER;
1673  }
1674 
1676  SymbolicName.MaximumLength = Target->DeviceNameLength;
1677  SymbolicName.Buffer = Target->DeviceName;
1678 
1679  /* Disable hard errors */
1682 
1683  /* Call real worker */
1684  Status = MountMgrMountedDeviceArrival(DeviceExtension, &SymbolicName, TRUE);
1685 
1687 
1688  return Status;
1689 }
1690 
1691 /*
1692  * @implemented
1693  */
1694 NTSTATUS
1696  IN PIRP Irp)
1697 {
1698  NTSTATUS Status;
1699  PIO_STACK_LOCATION Stack;
1700  PMOUNTDEV_UNIQUE_ID UniqueId;
1701  PMOUNTMGR_MOUNT_POINT MountPoint;
1703 
1705 
1706  /* Validate input... */
1707  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1708  {
1709  return STATUS_INVALID_PARAMETER;
1710  }
1711 
1712  MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1713  if (!MountPoint->SymbolicLinkNameLength)
1714  {
1715  MountPoint->SymbolicLinkNameOffset = 0;
1716  }
1717 
1718  if (!MountPoint->UniqueIdLength)
1719  {
1720  MountPoint->UniqueIdOffset = 0;
1721  }
1722 
1723  if (!MountPoint->DeviceNameLength)
1724  {
1725  MountPoint->DeviceNameOffset = 0;
1726  }
1727 
1728  /* Addresses can't be odd */
1729  if ((MountPoint->SymbolicLinkNameOffset & 1) ||
1730  (MountPoint->SymbolicLinkNameLength & 1))
1731  {
1732  return STATUS_INVALID_PARAMETER;
1733  }
1734 
1735  if ((MountPoint->UniqueIdOffset & 1) ||
1736  (MountPoint->UniqueIdLength & 1))
1737  {
1738  return STATUS_INVALID_PARAMETER;
1739  }
1740 
1741  if ((MountPoint->DeviceNameOffset & 1) ||
1742  (MountPoint->DeviceNameLength & 1))
1743  {
1744  return STATUS_INVALID_PARAMETER;
1745  }
1746 
1747  /* We can't go beyond */
1748  if (((ULONG)MountPoint->SymbolicLinkNameLength + MountPoint->UniqueIdLength +
1749  MountPoint->DeviceNameLength) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1750  {
1751  return STATUS_INVALID_PARAMETER;
1752  }
1753 
1754  if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_MOUNT_POINTS))
1755  {
1756  return STATUS_INVALID_PARAMETER;
1757  }
1758 
1759  /* If caller provided a Symlink, use it */
1760  if (MountPoint->SymbolicLinkNameLength != 0)
1761  {
1762  if (MountPoint->SymbolicLinkNameLength > MAXSHORT)
1763  {
1764  return STATUS_INVALID_PARAMETER;
1765  }
1766 
1768  SymbolicName.MaximumLength = MountPoint->SymbolicLinkNameLength + sizeof(WCHAR);
1770  if (!SymbolicName.Buffer)
1771  {
1773  }
1774 
1776  (PWSTR)((ULONG_PTR)MountPoint + MountPoint->SymbolicLinkNameOffset),
1779 
1780  /* Query links using it */
1783  }
1784  /* If user provided an unique ID */
1785  else if (MountPoint->UniqueIdLength != 0)
1786  {
1787  UniqueId = AllocatePool(MountPoint->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1788  if (!UniqueId)
1789  {
1791  }
1792 
1793  UniqueId->UniqueIdLength = MountPoint->UniqueIdLength;
1794  RtlCopyMemory(UniqueId->UniqueId,
1795  (PVOID)((ULONG_PTR)MountPoint + MountPoint->UniqueIdOffset),
1796  MountPoint->UniqueIdLength);
1797 
1798  /* Query links using it */
1799  Status = QueryPointsFromMemory(DeviceExtension, Irp, UniqueId, NULL);
1800  FreePool(UniqueId);
1801  }
1802  /* If caller provided a device name */
1803  else if (MountPoint->DeviceNameLength != 0)
1804  {
1805  if (MountPoint->DeviceNameLength > MAXSHORT)
1806  {
1807  return STATUS_INVALID_PARAMETER;
1808  }
1809 
1810  DeviceName.Length = MountPoint->DeviceNameLength;
1811  DeviceName.MaximumLength = MountPoint->DeviceNameLength + sizeof(WCHAR);
1812  DeviceName.Buffer = AllocatePool(DeviceName.MaximumLength);
1813  if (!DeviceName.Buffer)
1814  {
1816  }
1817 
1818  RtlCopyMemory(DeviceName.Buffer,
1819  (PWSTR)((ULONG_PTR)MountPoint + MountPoint->DeviceNameOffset),
1820  DeviceName.Length);
1821  DeviceName.Buffer[DeviceName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1822 
1823  /* Query links using it */
1824  Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, &DeviceName);
1825  FreePool(DeviceName.Buffer);
1826  }
1827  else
1828  {
1829  /* Otherwise, query all links */
1830  Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, NULL);
1831  }
1832 
1833  return Status;
1834 }
1835 
1836 /*
1837  * @implemented
1838  */
1839 NTSTATUS
1841  IN PIRP Irp)
1842 {
1843  ULONG Link;
1844  NTSTATUS Status;
1845  BOOLEAN CreateNoDrive;
1846  PIO_STACK_LOCATION Stack;
1847  PMOUNTDEV_UNIQUE_ID UniqueId;
1848  PMOUNTMGR_MOUNT_POINT MountPoint;
1849  PMOUNTMGR_MOUNT_POINTS MountPoints;
1851 
1853 
1854  /* Validate input */
1855  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1856  {
1857  return STATUS_INVALID_PARAMETER;
1858  }
1859 
1860  /* Query points */
1861  MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1862  CreateNoDrive = (MountPoint->SymbolicLinkNameOffset && MountPoint->SymbolicLinkNameLength);
1863 
1864  Status = MountMgrQueryPoints(DeviceExtension, Irp);
1865  if (!NT_SUCCESS(Status))
1866  {
1867  return Status;
1868  }
1869 
1870  /* For all the points matching the request */
1871  MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1872  for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1873  {
1877  if (!SymbolicName.Buffer)
1878  {
1880  }
1881 
1883  (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1886 
1887  /* Create a no drive entry for the drive letters */
1888  if (CreateNoDrive && IsDriveLetter(&SymbolicName))
1889  {
1890  UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1891  if (UniqueId)
1892  {
1893  UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1894  RtlCopyMemory(UniqueId->UniqueId,
1895  (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1896  MountPoints->MountPoints[Link].UniqueIdLength);
1897 
1898  CreateNoDriveLetterEntry(UniqueId);
1899  FreePool(UniqueId);
1900  }
1901  }
1902 
1903  /* If there are no link any more, and no need to create a no drive entry */
1904  if (Link == 0 && !CreateNoDrive)
1905  {
1906  /* Then, delete everything */
1907  UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength);
1908  if (UniqueId)
1909  {
1910  RtlCopyMemory(UniqueId,
1911  (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1912  MountPoints->MountPoints[Link].UniqueIdLength);
1913 
1914  DeleteNoDriveLetterEntry(UniqueId);
1915  FreePool(UniqueId);
1916  }
1917  }
1918 
1919  /* Delete all the information about the mount point */
1924 
1925  /* Notify the change */
1926  DeviceName.Length = DeviceName.MaximumLength =
1927  MountPoints->MountPoints[Link].DeviceNameLength;
1928  DeviceName.Buffer = (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].DeviceNameOffset);
1929  MountMgrNotifyNameChange(DeviceExtension, &DeviceName, TRUE);
1930  }
1931 
1932  MountMgrNotify(DeviceExtension);
1933 
1934  return Status;
1935 }
1936 
1937 /*
1938  * @implemented
1939  */
1940 NTSTATUS
1942  IN PIRP Irp)
1943 {
1944  ULONG Link;
1945  NTSTATUS Status;
1947  PMOUNTDEV_UNIQUE_ID UniqueId;
1948  PMOUNTMGR_MOUNT_POINTS MountPoints;
1949 
1950  /* Query points */
1951  Status = MountMgrQueryPoints(DeviceExtension, Irp);
1952  if (!NT_SUCCESS(Status))
1953  {
1954  return Status;
1955  }
1956 
1957  MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1958  if (MountPoints->NumberOfMountPoints == 0)
1959  {
1960  return Status;
1961  }
1962 
1963  /* For all the mount points */
1964  for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1965  {
1969  if (!SymbolicName.Buffer)
1970  {
1972  }
1973 
1975  (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1978 
1979  /* If the only mount point is a drive letter, then create a no letter drive entry */
1980  if (MountPoints->NumberOfMountPoints == 1 && IsDriveLetter(&SymbolicName))
1981  {
1982  UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1983  if (UniqueId)
1984  {
1985  UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1986  RtlCopyMemory(UniqueId->UniqueId,
1987  (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1988  MountPoints->MountPoints[Link].UniqueIdLength);
1989 
1990  CreateNoDriveLetterEntry(UniqueId);
1991  FreePool(UniqueId);
1992  }
1993  }
1994 
1995  /* Simply delete mount point from DB */
1999  }
2000 
2001  return Status;
2002 }
2003 
2004 /*
2005  * @implemented
2006  */
2007 NTSTATUS
2009  IN PIRP Irp,
2010  IN NTSTATUS LockStatus,
2011  OUT PUNICODE_STRING SourceDeviceName,
2012  OUT PUNICODE_STRING SourceSymbolicName,
2013  OUT PUNICODE_STRING TargetVolumeName)
2014 {
2015  HANDLE Handle;
2016  NTSTATUS Status;
2018  PIO_STACK_LOCATION Stack;
2019  ULONG Length, SavedLength;
2020  BOOLEAN FOReferenced = FALSE;
2023  PDEVICE_INFORMATION DeviceInformation;
2024  OBJECT_NAME_INFORMATION ObjectNameInfo;
2025  FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
2026  PFILE_NAME_INFORMATION FileNameInfo = NULL;
2027  PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint;
2028  POBJECT_NAME_INFORMATION ObjectNameInfoPtr = NULL;
2029  UNICODE_STRING SourceVolumeName, TargetDeviceName;
2030 
2032 
2033  /* Validate input */
2034  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_VOLUME_MOUNT_POINT))
2035  {
2036  return STATUS_INVALID_PARAMETER;
2037  }
2038 
2039  VolumeMountPoint = (PMOUNTMGR_VOLUME_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
2040 
2041  if (((ULONG)VolumeMountPoint->SourceVolumeNameLength + VolumeMountPoint->TargetVolumeNameLength) <
2042  Stack->Parameters.DeviceIoControl.InputBufferLength)
2043  {
2044  return STATUS_INVALID_PARAMETER;
2045  }
2046 
2047  /* Get source volume name */
2048  SourceVolumeName.Length =
2049  SourceVolumeName.MaximumLength = VolumeMountPoint->SourceVolumeNameLength;
2050  SourceVolumeName.Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset);
2051 
2053  &SourceVolumeName,
2055  NULL,
2056  NULL);
2057 
2058  /* Open it */
2062  &IoStatusBlock,
2065  if (!NT_SUCCESS(Status))
2066  {
2067  return Status;
2068  }
2069 
2070  TargetDeviceName.Buffer = NULL;
2071 
2072  /* Query its attributes */
2074  &IoStatusBlock,
2075  &FsDeviceInfo,
2076  sizeof(FsDeviceInfo),
2078  if (!NT_SUCCESS(Status))
2079  {
2080  goto Cleanup;
2081  }
2082 
2083  if (FsDeviceInfo.DeviceType != FILE_DEVICE_DISK && FsDeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK)
2084  {
2085  goto Cleanup;
2086  }
2087 
2089  {
2090  goto Cleanup;
2091  }
2092 
2093  /* Reference it */
2095  if (!NT_SUCCESS(Status))
2096  {
2097  goto Cleanup;
2098  }
2099  FOReferenced = TRUE;
2100 
2101  /* Get file name */
2102  FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION));
2103  if (!FileNameInfo)
2104  {
2106  goto Cleanup;
2107  }
2108 
2109  Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2110  sizeof(FILE_NAME_INFORMATION),
2113  {
2114  /* Now we have real length, use it */
2115  Length = FileNameInfo->FileNameLength;
2116  FreePool(FileNameInfo);
2117 
2118  FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + Length);
2119  if (!FileNameInfo)
2120  {
2122  goto Cleanup;
2123  }
2124 
2125  /* Really query file name */
2126  Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2127  sizeof(FILE_NAME_INFORMATION) + Length,
2129  }
2130 
2131  if (!NT_SUCCESS(Status))
2132  {
2133  goto Cleanup;
2134  }
2135 
2136  /* Get symbolic name */
2137  ObjectNameInfoPtr = &ObjectNameInfo;
2138  SavedLength = sizeof(OBJECT_NAME_INFORMATION);
2139  Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, sizeof(OBJECT_NAME_INFORMATION), &Length);
2141  {
2142  /* Once again, with proper size, it works better */
2143  ObjectNameInfoPtr = AllocatePool(Length);
2144  if (!ObjectNameInfoPtr)
2145  {
2147  goto Cleanup;
2148  }
2149 
2150  SavedLength = Length;
2151  Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, SavedLength, &Length);
2152  }
2153 
2154  if (!NT_SUCCESS(Status))
2155  {
2156  goto Cleanup;
2157  }
2158 
2159  /* Now, query the device name */
2160  Status = QueryDeviceInformation(&ObjectNameInfoPtr->Name, SourceDeviceName,
2161  NULL, NULL, NULL, NULL, NULL, NULL);
2162  if (!NT_SUCCESS(Status))
2163  {
2164  goto Cleanup;
2165  }
2166 
2167  /* For target volume name, use input */
2168  TargetVolumeName->Length =
2169  TargetVolumeName->MaximumLength = VolumeMountPoint->TargetVolumeNameLength;
2170  TargetVolumeName->Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset);
2171 
2172  /* Query its device name */
2173  Status = QueryDeviceInformation(TargetVolumeName, &TargetDeviceName,
2174  NULL, NULL, NULL, NULL, NULL, NULL);
2175  if (!NT_SUCCESS(Status))
2176  {
2177  goto Cleanup;
2178  }
2179 
2180  /* Return symbolic name */
2181  SourceSymbolicName->Length =
2182  SourceSymbolicName->MaximumLength = (USHORT)FileNameInfo->FileNameLength;
2183  SourceSymbolicName->Buffer = (PWSTR)FileNameInfo;
2184  /* memmove allows memory overlap */
2185  RtlMoveMemory(SourceSymbolicName->Buffer, FileNameInfo->FileName, SourceSymbolicName->Length);
2186  FileNameInfo = NULL;
2187 
2188  /* Notify the change */
2189  MountMgrNotify(DeviceExtension);
2190  MountMgrNotifyNameChange(DeviceExtension, &TargetDeviceName, TRUE);
2191 
2192  /* If we are locked, sync databases if possible */
2193  if (NT_SUCCESS(LockStatus))
2194  {
2195  Status = FindDeviceInfo(DeviceExtension, SourceDeviceName, FALSE, &DeviceInformation);
2196  if (NT_SUCCESS(Status))
2197  {
2198  ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
2199  }
2200  else
2201  {
2203  }
2204  }
2205 
2206 Cleanup:
2207  if (TargetDeviceName.Buffer)
2208  {
2209  FreePool(TargetDeviceName.Buffer);
2210  }
2211 
2212  if (ObjectNameInfoPtr && ObjectNameInfoPtr != &ObjectNameInfo)
2213  {
2214  FreePool(ObjectNameInfoPtr);
2215  }
2216 
2217  if (FileNameInfo)
2218  {
2219  FreePool(FileNameInfo);
2220  }
2221 
2222  if (FOReferenced)
2223  {
2225  }
2226 
2227  return Status;
2228 }
2229 
2230 /*
2231  * @implemented
2232  */
2233 NTSTATUS
2235  IN PIRP Irp,
2236  IN NTSTATUS LockStatus)
2237 {
2238  LONG Offset;
2239  BOOLEAN Found;
2240  NTSTATUS Status;
2242  PMOUNTDEV_UNIQUE_ID UniqueId;
2243  PDATABASE_ENTRY DatabaseEntry;
2244  PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2245  PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2246  UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2247 
2248  /* Initialize string */
2249  LinkTarget.Length = 0;
2250  LinkTarget.MaximumLength = 0xC8;
2252  if (LinkTarget.Buffer == NULL)
2253  {
2255  }
2256 
2257  /* If the mount point was created, then, it changed!
2258  * Also use it to query some information
2259  */
2260  Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2261  /* Pending means DB are under synchronization, bail out */
2262  if (Status == STATUS_PENDING)
2263  {
2265  FreePool(SourceDeviceName.Buffer);
2266  FreePool(SourceSymbolicName.Buffer);
2267  return STATUS_SUCCESS;
2268  }
2269  else if (!NT_SUCCESS(Status))
2270  {
2272  return Status;
2273  }
2274 
2275  /* Query the device information */
2276  Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2277  if (!NT_SUCCESS(Status))
2278  {
2279  /* If it failed, first try to get volume name */
2280  Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2281  if (!NT_SUCCESS(Status))
2282  {
2283  /* Then, try to read the symlink */
2284  Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2285  if (!NT_SUCCESS(Status))
2286  {
2288  FreePool(SourceDeviceName.Buffer);
2289  FreePool(SourceSymbolicName.Buffer);
2290  return Status;
2291  }
2292  }
2293  else
2294  {
2296  }
2297 
2298  FreePool(SourceDeviceName.Buffer);
2299 
2300  SourceDeviceName.Length = LinkTarget.Length;
2301  SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2302  SourceDeviceName.Buffer = LinkTarget.Buffer;
2303 
2304  /* Now that we have the correct source, reattempt to query information */
2305  Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2306  if (!NT_SUCCESS(Status))
2307  {
2308  FreePool(SourceDeviceName.Buffer);
2309  FreePool(SourceSymbolicName.Buffer);
2310  return Status;
2311  }
2312  }
2313 
2314  FreePool(SourceDeviceName.Buffer);
2315 
2316  /* Get information about target device */
2317  Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2318  if (!NT_SUCCESS(Status))
2319  {
2320  FreePool(SourceSymbolicName.Buffer);
2321  return Status;
2322  }
2323 
2324  /* Notify if not disabled */
2325  if (!TargetDeviceInformation->SkipNotifications)
2326  {
2327  PostOnlineNotification(DeviceExtension, &TargetDeviceInformation->SymbolicName);
2328  }
2329 
2330  /* Open the remote database */
2331  RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2332  if (RemoteDatabase == 0)
2333  {
2334  FreePool(SourceSymbolicName.Buffer);
2336  }
2337 
2338  /* Browse all the entries */
2339  Offset = 0;
2340  Found = FALSE;
2341  for (;;)
2342  {
2343  DatabaseEntry = GetRemoteDatabaseEntry(RemoteDatabase, Offset);
2344  if (DatabaseEntry == NULL)
2345  {
2346  break;
2347  }
2348 
2349  /* Try to find ourselves */
2350  DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2351  DbName.Length = DbName.MaximumLength;
2352  DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2353  if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2354  {
2355  /* Reference ourselves and update the entry */
2356  ++DatabaseEntry->EntryReferences;
2358  FreePool(DatabaseEntry);
2359  Found = TRUE;
2360  break;
2361  }
2362 
2363  Offset += DatabaseEntry->EntrySize;
2364  FreePool(DatabaseEntry);
2365  }
2366 
2367  /* We couldn't find ourselves, we'll have to add ourselves */
2368  if (!Found)
2369  {
2370  ULONG EntrySize;
2371  PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2372 
2373  /* Query the device unique ID */
2374  Status = QueryDeviceInformation(&TargetVolumeName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
2375  if (!NT_SUCCESS(Status))
2376  {
2377  FreePool(SourceSymbolicName.Buffer);
2379  return Status;
2380  }
2381 
2382  /* Allocate a database entry */
2383  EntrySize = UniqueId->UniqueIdLength + TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2384  DatabaseEntry = AllocatePool(EntrySize);
2385  if (DatabaseEntry == NULL)
2386  {
2387  FreePool(UniqueId);
2388  FreePool(SourceSymbolicName.Buffer);
2391  }
2392 
2393  /* Fill it in */
2394  DatabaseEntry->EntrySize = EntrySize;
2395  DatabaseEntry->EntryReferences = 1;
2396  DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
2397  DatabaseEntry->SymbolicNameLength = TargetVolumeName.Length;
2398  DatabaseEntry->UniqueIdOffset = TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2399  DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
2400  RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + sizeof(DATABASE_ENTRY)), TargetVolumeName.Buffer, DatabaseEntry->SymbolicNameLength);
2401  RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
2402 
2403  /* And write it down */
2404  Status = AddRemoteDatabaseEntry(RemoteDatabase, DatabaseEntry);
2405  FreePool(DatabaseEntry);
2406  if (!NT_SUCCESS(Status))
2407  {
2408  FreePool(UniqueId);
2409  FreePool(SourceSymbolicName.Buffer);
2411  return Status;
2412  }
2413 
2414  /* And now, allocate an Unique ID item */
2415  UniqueIdReplicate = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
2416  if (UniqueIdReplicate == NULL)
2417  {
2418  FreePool(UniqueId);
2419  FreePool(SourceSymbolicName.Buffer);
2421  return Status;
2422  }
2423 
2424  /* To associate it with the device */
2425  UniqueIdReplicate->UniqueId = UniqueId;
2426  InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2427  }
2428 
2429  /* We're done with the remote database */
2431 
2432  /* Check we were find writing the entry */
2433  if (!NT_SUCCESS(Status))
2434  {
2435  FreePool(SourceSymbolicName.Buffer);
2436  return Status;
2437  }
2438 
2439  /* This is the end, allocate an associated entry */
2440  AssociatedEntry = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY));
2441  if (AssociatedEntry == NULL)
2442  {
2443  FreePool(SourceSymbolicName.Buffer);
2445  }
2446 
2447  /* Initialize its source name string */
2448  AssociatedEntry->String.Length = SourceSymbolicName.Length;
2449  AssociatedEntry->String.MaximumLength = AssociatedEntry->String.Length + sizeof(UNICODE_NULL);
2450  AssociatedEntry->String.Buffer = AllocatePool(AssociatedEntry->String.MaximumLength);
2451  if (AssociatedEntry->String.Buffer == NULL)
2452  {
2453  FreePool(AssociatedEntry);
2454  FreePool(SourceSymbolicName.Buffer);
2456  }
2457 
2458  /* Copy data & insert in list */
2459  RtlCopyMemory(AssociatedEntry->String.Buffer, SourceSymbolicName.Buffer, SourceSymbolicName.Length);
2460  AssociatedEntry->String.Buffer[SourceSymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
2461  AssociatedEntry->DeviceInformation = DeviceInformation;
2462  InsertTailList(&TargetDeviceInformation->AssociatedDevicesHead, &AssociatedEntry->AssociatedDevicesEntry);
2463 
2464  /* We're done! */
2465  FreePool(SourceSymbolicName.Buffer);
2466  return STATUS_SUCCESS;
2467 }
2468 
2469 /*
2470  * @implemented
2471  */
2472 NTSTATUS
2474  IN PIRP Irp,
2475  IN NTSTATUS LockStatus)
2476 {
2477  LONG Offset;
2478  NTSTATUS Status;
2481  PDATABASE_ENTRY DatabaseEntry;
2482  PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2483  PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2484  PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2485  UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2486 
2487  /* Initialize string */
2488  LinkTarget.Length = 0;
2489  LinkTarget.MaximumLength = 0xC8;
2491  if (LinkTarget.Buffer == NULL)
2492  {
2494  }
2495 
2496  /* If the mount point was deleted, then, it changed!
2497  * Also use it to query some information
2498  */
2499  Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2500  /* Pending means DB are under synchronization, bail out */
2501  if (Status == STATUS_PENDING)
2502  {
2504  FreePool(SourceDeviceName.Buffer);
2505  FreePool(SourceSymbolicName.Buffer);
2506  return STATUS_SUCCESS;
2507  }
2508  else if (!NT_SUCCESS(Status))
2509  {
2511  return Status;
2512  }
2513 
2514  /* Query the device information */
2515  Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2516  if (!NT_SUCCESS(Status))
2517  {
2518  /* If it failed, first try to get volume name */
2519  Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2520  if (!NT_SUCCESS(Status))
2521  {
2522  /* Then, try to read the symlink */
2523  Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2524  if (!NT_SUCCESS(Status))
2525  {
2527  FreePool(SourceDeviceName.Buffer);
2528  FreePool(SourceSymbolicName.Buffer);
2529  return Status;
2530  }
2531  }
2532  else
2533  {
2535  }
2536 
2537  FreePool(SourceDeviceName.Buffer);
2538 
2539  SourceDeviceName.Length = LinkTarget.Length;
2540  SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2541  SourceDeviceName.Buffer = LinkTarget.Buffer;
2542 
2543  /* Now that we have the correct source, reattempt to query information */
2544  Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2545  if (!NT_SUCCESS(Status))
2546  {
2547  FreePool(SourceDeviceName.Buffer);
2548  FreePool(SourceSymbolicName.Buffer);
2549  return Status;
2550  }
2551  }
2552 
2553  FreePool(SourceDeviceName.Buffer);
2554 
2555  /* Get information about target device */
2556  Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2557  if (!NT_SUCCESS(Status))
2558  {
2559  FreePool(SourceSymbolicName.Buffer);
2560  return Status;
2561  }
2562 
2563  /* Open the remote database */
2564  RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2565  if (RemoteDatabase == 0)
2566  {
2567  FreePool(SourceSymbolicName.Buffer);
2569  }
2570 
2571  /* Browse all the entries */
2572  Offset = 0;
2573  for (;;)
2574  {
2575  DatabaseEntry = GetRemoteDatabaseEntry(RemoteDatabase, Offset);
2576  if (DatabaseEntry == NULL)
2577  {
2578  /* We didn't find ourselves, that's infortunate! */
2579  FreePool(SourceSymbolicName.Buffer);
2581  return STATUS_INVALID_PARAMETER;
2582  }
2583 
2584  /* Try to find ourselves */
2585  DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2586  DbName.Length = DbName.MaximumLength;
2587  DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2588  if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2589  {
2590  break;
2591  }
2592 
2593  Offset += DatabaseEntry->EntrySize;
2594  FreePool(DatabaseEntry);
2595  }
2596 
2597  /* Dereference ourselves */
2598  DatabaseEntry->EntryReferences--;
2599  if (DatabaseEntry->EntryReferences == 0)
2600  {
2601  /* If we're still referenced, just update the entry */
2603  }
2604  else
2605  {
2606  /* Otherwise, delete the entry */
2608  if (!NT_SUCCESS(Status))
2609  {
2610  FreePool(DatabaseEntry);
2611  FreePool(SourceSymbolicName.Buffer);
2613  return Status;
2614  }
2615 
2616  /* Also, delete our unique ID replicated record */
2617  for (Entry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
2618  Entry != &DeviceInformation->ReplicatedUniqueIdsListHead;
2619  Entry = Entry->Flink)
2620  {
2621  UniqueIdReplicate = CONTAINING_RECORD(Entry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
2622 
2623  if (UniqueIdReplicate->UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
2624  RtlCompareMemory(UniqueIdReplicate->UniqueId->UniqueId,
2625  (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
2626  DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
2627  {
2628  break;
2629  }
2630  }
2631 
2632  /* It has to exist! */
2633  if (Entry == &DeviceInformation->ReplicatedUniqueIdsListHead)
2634  {
2635  FreePool(DatabaseEntry);
2636  FreePool(SourceSymbolicName.Buffer);
2638  return STATUS_UNSUCCESSFUL;
2639  }
2640 
2641  /* Remove it and free it */
2642  RemoveEntryList(&UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2643  FreePool(UniqueIdReplicate->UniqueId);
2644  FreePool(UniqueIdReplicate);
2645  }
2646 
2647  /* We're done with the remote database */
2648  FreePool(DatabaseEntry);
2650 
2651  /* Check write operation succeed */
2652  if (!NT_SUCCESS(Status))
2653  {
2654  FreePool(SourceSymbolicName.Buffer);
2655  return Status;
2656  }
2657 
2658  /* Try to find our associated device entry */
2659  for (Entry = TargetDeviceInformation->AssociatedDevicesHead.Flink;
2660  Entry != &TargetDeviceInformation->AssociatedDevicesHead;
2661  Entry = Entry->Flink)
2662  {
2663  AssociatedEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
2664 
2665  /* If found, delete it */
2666  if (AssociatedEntry->DeviceInformation == DeviceInformation &&
2667  RtlEqualUnicodeString(&AssociatedEntry->String, &SourceSymbolicName, TRUE))
2668  {
2669  RemoveEntryList(&AssociatedEntry->AssociatedDevicesEntry);
2670  FreePool(AssociatedEntry->String.Buffer);
2671  FreePool(AssociatedEntry);
2672  break;
2673  }
2674  }
2675 
2676  /* We're done! */
2677  FreePool(SourceSymbolicName.Buffer);
2678  return STATUS_SUCCESS;
2679 }
2680 
2681 /*
2682  * @implemented
2683  */
2684 NTSTATUS
2685 NTAPI
2687  IN PIRP Irp)
2688 {
2689  PIO_STACK_LOCATION Stack;
2690  NTSTATUS Status, LockStatus;
2691  PDEVICE_EXTENSION DeviceExtension;
2692 
2694  DeviceExtension = DeviceObject->DeviceExtension;
2695 
2696  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2697 
2698  switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2699  {
2701  Status = MountMgrCreatePoint(DeviceExtension, Irp);
2702  break;
2703 
2705  Status = MountMgrDeletePoints(DeviceExtension, Irp);
2706  break;
2707 
2709  Status = MountMgrQueryPoints(DeviceExtension, Irp);
2710  break;
2711 
2713  Status = MountMgrDeletePointsDbOnly(DeviceExtension, Irp);
2714  break;
2715 
2717  Status = MountMgrNextDriveLetter(DeviceExtension, Irp);
2718  break;
2719 
2721  DeviceExtension->AutomaticDriveLetter = TRUE;
2723 
2724  MountMgrAssignDriveLetters(DeviceExtension);
2725  ReconcileAllDatabasesWithMaster(DeviceExtension);
2726  WaitForOnlinesToComplete(DeviceExtension);
2727  break;
2728 
2730  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2731 
2732  LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2733  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2734  Status = MountMgrVolumeMountPointCreated(DeviceExtension, Irp, LockStatus);
2735  if (NT_SUCCESS(LockStatus))
2736  {
2737  ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2738  }
2739 
2740  break;
2741 
2743  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2744 
2745  LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2746  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2747  Status = MountMgrVolumeMountPointDeleted(DeviceExtension, Irp, LockStatus);
2748  if (NT_SUCCESS(LockStatus))
2749  {
2750  ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2751  }
2752 
2753  break;
2754 
2756  Status = MountMgrChangeNotify(DeviceExtension, Irp);
2757  break;
2758 
2760  Status = MountMgrKeepLinksWhenOffline(DeviceExtension, Irp);
2761  break;
2762 
2764  Status = MountMgrCheckUnprocessedVolumes(DeviceExtension, Irp);
2765  goto Complete;
2766 
2768  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2769  Status = MountMgrVolumeArrivalNotification(DeviceExtension, Irp);
2770  goto Complete;
2771 
2773  Status = MountMgrQueryDosVolumePath(DeviceExtension, Irp);
2774  break;
2775 
2777  Status = MountMgrQueryDosVolumePaths(DeviceExtension, Irp);
2778  break;
2779 
2781  Status = MountMgrScrubRegistry(DeviceExtension);
2782  break;
2783 
2785  Status = MountMgrQueryAutoMount(DeviceExtension, Irp);
2786  break;
2787 
2789  Status = MountMgrSetAutoMount(DeviceExtension, Irp);
2790  break;
2791 
2794  DPRINT1("Winism! Rewrite the caller!\n");
2795  default:
2797  }
2798 
2799  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2800 
2801  if (Status != STATUS_PENDING)
2802  {
2803  goto Complete;
2804  }
2805 
2806  return Status;
2807 
2808 Complete:
2809  Irp->IoStatus.Status = Status;
2811 
2812  return Status;
2813 }
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:2343
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:2008
USHORT UniqueIdOffset
Definition: mntmgr.h:91
VOID NTAPI MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1681
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:82
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4004
#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
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
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:54
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:136
#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:1169
NTSTATUS MountMgrQuerySymbolicLink(IN PUNICODE_STRING SymbolicName, IN OUT PUNICODE_STRING LinkTarget)
Definition: symlink.c:959
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:98
_In_ PCWSTR _In_z_ PCWSTR _In_ ULONG ValueType
Definition: rtlfuncs.h:4016
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4676
BOOLEAN LetterAssigned
Definition: mntmgr.h:55
LONG NTSTATUS
Definition: precomp.h:26
USHORT UniqueIdLength
Definition: imports.h:138
#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
Definition: mountmgr.h:36
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:922
#define IOCTL_MOUNTMGR_SET_AUTO_MOUNT
Definition: mountmgr.h:154
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:1209
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:1435
#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:864
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
VOID DeleteNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:2080
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:2234
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:1652
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:1064
_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:1595
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:1818
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:734
#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:435
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:1840
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:4004
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:641
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:2473
_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:1406
NTSTATUS MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:1459
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:194
#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:1608
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:1941
VOID NTAPI PsSetThreadHardErrorsAreDisabled(IN PETHREAD Thread, IN BOOLEAN HardErrorsAreDisabled)
Definition: thread.c:898
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
Definition: mntmgr.h:95
struct _REPARSE_DATA_BUFFER::@301::@303 SymbolicLinkReparseBuffer
LIST_ENTRY SymbolicLinksListHead
Definition: mntmgr.h:45
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
struct _DeviceInfo DeviceInfo
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h: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:694
_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:462
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Must_inspect_result_ typedef _In_ ULONG _In_ BOOLEAN Target
Definition: iotypes.h:1068
* PFILE_OBJECT
Definition: iotypes.h:1955
#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:1695
#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:313
_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:706
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:2686
#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
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h:241
NTSTATUS MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: device.c:648
#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:1274
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:763
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:1024
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
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:837
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:2772
VOID ReleaseRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:391
VOID ReconcileAllDatabasesWithMaster(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:1641
NTSTATUS MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION Extension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN FromVolume)
Definition: mountmgr.c:936
return STATUS_SUCCESS
Definition: btrfs.c:2966
unsigned short MaximumLength
Definition: sprintf.c:452
IoMarkIrpPending(Irp)
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define REG_DWORD
Definition: sdbapi.c:596
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE
Definition: iotypes.h:6857
#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:353
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