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