ReactOS  0.4.14-dev-49-gfb4591c
mountmgr.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2011 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/mountmgr.c
22  * PURPOSE: Mount Manager
23  * PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
24  * Alex Ionescu (alex.ionescu@reactos.org)
25  */
26 
27 #include "mntmgr.h"
28 
29 #define NDEBUG
30 #include <debug.h>
31 
32 #if defined(ALLOC_PRAGMA)
33 #pragma alloc_text(INIT, MountmgrReadNoAutoMount)
34 #pragma alloc_text(INIT, DriverEntry)
35 #endif
36 
37 /* FIXME */
38 GUID MountedDevicesGuid = {0x53F5630D, 0xB6BF, 0x11D0, {0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B}};
39 
43 
44 static const WCHAR Cunc[] = L"\\??\\C:";
45 
46 /*
47  * @implemented
48  */
49 BOOLEAN
51 {
55 
56  /* Prepare to look in the registry to see if
57  * given volume is offline
58  */
64  QueryTable[0].DefaultLength = sizeof(ULONG);
66 
67  Default = 0;
68 
69  /* Query status */
72  QueryTable,
73  NULL,
74  NULL);
75  if (!NT_SUCCESS(Status))
76  {
77  IsOffline = 0;
78  }
79 
80  return (IsOffline != 0);
81 }
82 
83 /*
84  * @implemented
85  */
86 BOOLEAN
88 {
89  PLIST_ENTRY NextEntry;
90  PSYMLINK_INFORMATION SymlinkInfo;
91 
92  /* Browse all the symlinks to check if there is at least a drive letter */
93  for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
94  NextEntry != &DeviceInformation->SymbolicLinksListHead;
95  NextEntry = NextEntry->Flink)
96  {
97  SymlinkInfo = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
98 
99  if (IsDriveLetter(&SymlinkInfo->Name) && SymlinkInfo->Online)
100  {
101  return TRUE;
102  }
103  }
104 
105  return FALSE;
106 }
107 
108 /*
109  * @implemented
110  */
111 NTSTATUS
114  IN UCHAR Letter,
116 {
118 
119  /* Allocate a big enough buffer to contain the symbolic link */
120  DriveLetter->MaximumLength = DosDevices.Length + 3 * sizeof(WCHAR);
121  DriveLetter->Buffer = AllocatePool(DriveLetter->MaximumLength);
122  if (!DriveLetter->Buffer)
123  {
125  }
126 
127  /* Copy prefix */
128  RtlCopyUnicodeString(DriveLetter, &DosDevices);
129 
130  /* Update string to reflect real contents */
131  DriveLetter->Length = DosDevices.Length + 2 * sizeof(WCHAR);
132  DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR) + 2] = UNICODE_NULL;
133  DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR) + 1] = L':';
134 
135  /* If caller wants a no drive entry */
136  if (Letter == (UCHAR)-1)
137  {
138  /* Then, create a no letter entry */
139  CreateNoDriveLetterEntry(UniqueId);
140  FreePool(DriveLetter->Buffer);
141  return STATUS_UNSUCCESSFUL;
142  }
143  else if (Letter)
144  {
145  /* Use the letter given by the caller */
146  DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR)] = (WCHAR)Letter;
148  if (NT_SUCCESS(Status))
149  {
150  return Status;
151  }
152  }
153 
154  /* If caller didn't provide a letter, let's find one for him */
155 
157  {
158  /* If the device is a floppy, start with letter A */
159  Letter = 'A';
160  }
162  {
163  /* If the device is a CD-ROM, start with letter D */
164  Letter = 'D';
165  }
166  else
167  {
168  /* Finally, if it's a disk, use C */
169  Letter = 'C';
170  }
171 
172  /* Try to affect a letter (up to Z, ofc) until it's possible */
173  for (; Letter <= 'Z'; Letter++)
174  {
175  DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR)] = (WCHAR)Letter;
177  if (NT_SUCCESS(Status))
178  {
179  DPRINT("Assigned drive %c: to %wZ\n", Letter, DeviceName);
180  return Status;
181  }
182  }
183 
184  /* We failed to allocate a letter */
185  FreePool(DriveLetter->Buffer);
186  DPRINT("Failed to create a drive letter for %wZ\n", DeviceName);
187  return Status;
188 }
189 
190 /*
191  * @implemented
192  */
193 NTSTATUS
196  OUT PMOUNTDEV_UNIQUE_ID * UniqueId OPTIONAL,
198  OUT PBOOLEAN GptDriveLetter OPTIONAL,
199  OUT PBOOLEAN HasGuid OPTIONAL,
200  IN OUT LPGUID StableGuid OPTIONAL,
201  OUT PBOOLEAN Valid OPTIONAL)
202 {
203  PIRP Irp;
204  USHORT Size;
205  KEVENT Event;
206  BOOLEAN IsRemovable;
210  PIO_STACK_LOCATION Stack;
211  NTSTATUS Status, IntStatus;
215  STORAGE_DEVICE_NUMBER StorageDeviceNumber;
217 
218  /* Get device associated with the symbolic name */
221  &FileObject,
222  &DeviceObject);
223  if (!NT_SUCCESS(Status))
224  {
225  return Status;
226  }
227 
228  /* The associate FO can't have a file name */
229  if (FileObject->FileName.Length)
230  {
233  }
234 
235  /* Check if it's removable & return to the user (if asked to) */
236  IsRemovable = (FileObject->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
237  if (Removable)
238  {
239  *Removable = IsRemovable;
240  }
241 
242  /* Get the attached device */
244 
245  /* If we've been asked for a GPT drive letter */
246  if (GptDriveLetter)
247  {
248  /* Consider it has one */
249  *GptDriveLetter = TRUE;
250 
251  if (!IsRemovable)
252  {
253  /* Query the GPT attributes */
256  DeviceObject,
257  NULL,
258  0,
259  &GptAttributes,
260  sizeof(GptAttributes),
261  FALSE,
262  &Event,
263  &IoStatusBlock);
264  if (!Irp)
265  {
269  }
270 
272  if (Status == STATUS_PENDING)
273  {
276  }
277 
278  /* In case of failure, don't fail, that's no vital */
279  if (!NT_SUCCESS(Status))
280  {
282  }
283  /* Check if it has a drive letter */
284  else if (!(GptAttributes.GptAttributes &
285  GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER))
286  {
287  *GptDriveLetter = FALSE;
288  }
289  }
290  }
291 
292  /* If caller wants to know if there's valid contents */
293  if (Valid)
294  {
295  /* Suppose it's not OK */
296  *Valid = FALSE;
297 
298  if (!IsRemovable)
299  {
300  /* Query partitions information */
303  DeviceObject,
304  NULL,
305  0,
306  &PartitionInfo,
307  sizeof(PartitionInfo),
308  FALSE,
309  &Event,
310  &IoStatusBlock);
311  if (!Irp)
312  {
316  }
317 
319  if (Status == STATUS_PENDING)
320  {
323  }
324 
325  /* Once again here, failure isn't major */
326  if (!NT_SUCCESS(Status))
327  {
329  }
330  /* Verify we know something in */
331  else if (PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR &&
332  IsRecognizedPartition(PartitionInfo.Mbr.PartitionType))
333  {
334  *Valid = TRUE;
335  }
336 
337  /* It looks correct, ensure it is & query device number */
338  if (*Valid)
339  {
342  DeviceObject,
343  NULL,
344  0,
345  &StorageDeviceNumber,
346  sizeof(StorageDeviceNumber),
347  FALSE,
348  &Event,
349  &IoStatusBlock);
350  if (!Irp)
351  {
355  }
356 
358  if (Status == STATUS_PENDING)
359  {
362  }
363 
364  if (!NT_SUCCESS(Status))
365  {
367  }
368  else
369  {
370  *Valid = FALSE;
371  }
372  }
373  }
374  }
375 
376  /* If caller needs device name */
377  if (DeviceName)
378  {
379  /* Allocate a buffer just to request length */
380  Name = AllocatePool(sizeof(MOUNTDEV_NAME));
381  if (!Name)
382  {
386  }
387 
388  /* Query device name */
391  DeviceObject,
392  NULL,
393  0,
394  Name,
395  sizeof(MOUNTDEV_NAME),
396  FALSE,
397  &Event,
398  &IoStatusBlock);
399  if (!Irp)
400  {
401  FreePool(Name);
405  }
406 
408  Stack->FileObject = FileObject;
409 
411  if (Status == STATUS_PENDING)
412  {
415  }
416 
417  /* Now, we've got the correct length */
419  {
420  Size = Name->NameLength + sizeof(MOUNTDEV_NAME);
421 
422  FreePool(Name);
423 
424  /* Allocate proper size */
426  if (!Name)
427  {
431  }
432 
433  /* And query name (for real that time) */
436  DeviceObject,
437  NULL,
438  0,
439  Name,
440  Size,
441  FALSE,
442  &Event,
443  &IoStatusBlock);
444  if (!Irp)
445  {
446  FreePool(Name);
450  }
451 
453  Stack->FileObject = FileObject;
454 
456  if (Status == STATUS_PENDING)
457  {
460  }
461  }
462 
463  if (NT_SUCCESS(Status))
464  {
465  /* Copy back found name to the caller */
466  DeviceName->Length = Name->NameLength;
467  DeviceName->MaximumLength = Name->NameLength + sizeof(WCHAR);
468  DeviceName->Buffer = AllocatePool(DeviceName->MaximumLength);
469  if (!DeviceName->Buffer)
470  {
472  }
473  else
474  {
475  RtlCopyMemory(DeviceName->Buffer, Name->Name, Name->NameLength);
476  DeviceName->Buffer[Name->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
477  }
478  }
479 
480  FreePool(Name);
481  }
482 
483  if (!NT_SUCCESS(Status))
484  {
487  return Status;
488  }
489 
490  /* If caller wants device unique ID */
491  if (UniqueId)
492  {
493  /* Prepare buffer to probe length */
495  if (!Id)
496  {
500  }
501 
502  /* Query unique ID length */
505  DeviceObject,
506  NULL,
507  0,
508  Id,
509  sizeof(MOUNTDEV_UNIQUE_ID),
510  FALSE,
511  &Event,
512  &IoStatusBlock);
513  if (!Irp)
514  {
515  FreePool(Id);
519  }
520 
522  Stack->FileObject = FileObject;
523 
525  if (Status == STATUS_PENDING)
526  {
529  }
530 
531  /* Retry with appropriate length */
533  {
534  Size = Id->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID);
535 
536  FreePool(Id);
537 
538  /* Allocate the correct buffer */
539  Id = AllocatePool(Size);
540  if (!Id)
541  {
545  }
546 
547  /* Query unique ID */
550  DeviceObject,
551  NULL,
552  0,
553  Id,
554  Size,
555  FALSE,
556  &Event,
557  &IoStatusBlock);
558  if (!Irp)
559  {
560  FreePool(Id);
564  }
565 
567  Stack->FileObject = FileObject;
568 
570  if (Status == STATUS_PENDING)
571  {
574  }
575  }
576 
577  /* Hands back unique ID */
578  if (NT_SUCCESS(Status))
579  {
580  *UniqueId = Id;
581  }
582  else
583  {
584  /* In case of failure, also free the rest */
585  FreePool(Id);
586  if (DeviceName->Length)
587  {
588  FreePool(DeviceName->Buffer);
589  }
590 
593 
594  return Status;
595  }
596  }
597 
598  /* If user wants to know about GUID */
599  if (HasGuid)
600  {
601  /* Query device stable GUID */
604  DeviceObject,
605  NULL,
606  0,
607  StableGuid,
608  sizeof(GUID),
609  FALSE,
610  &Event,
611  &IoStatusBlock);
612  if (!Irp)
613  {
617  }
618 
620  Stack->FileObject = FileObject;
621 
622  IntStatus = IoCallDriver(DeviceObject, Irp);
623  if (IntStatus == STATUS_PENDING)
624  {
626  IntStatus = IoStatusBlock.Status;
627  }
628 
629  *HasGuid = NT_SUCCESS(IntStatus);
630  }
631 
634  return Status;
635 }
636 
637 /*
638  * @implemented
639  */
640 NTSTATUS
643  IN BOOLEAN DeviceNameGiven,
644  OUT PDEVICE_INFORMATION * DeviceInformation)
645 {
647  PLIST_ENTRY NextEntry;
650 
651  /* If a device name was given, use it */
652  if (DeviceNameGiven)
653  {
654  DeviceName.Length = SymbolicName->Length;
655  DeviceName.Buffer = SymbolicName->Buffer;
656  }
657  else
658  {
659  /* Otherwise, query it */
661  &DeviceName,
662  NULL, NULL,
663  NULL, NULL,
664  NULL, NULL);
665  if (!NT_SUCCESS(Status))
666  {
667  return Status;
668  }
669  }
670 
671  /* Look for device information matching devive */
672  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
673  NextEntry != &(DeviceExtension->DeviceListHead);
674  NextEntry = NextEntry->Flink)
675  {
676  DeviceInfo = CONTAINING_RECORD(NextEntry,
678  DeviceListEntry);
679 
680  if (RtlEqualUnicodeString(&DeviceName, &(DeviceInfo->DeviceName), TRUE))
681  {
682  break;
683  }
684  }
685 
686  /* Release our buffer if required */
687  if (!DeviceNameGiven)
688  {
689  FreePool(DeviceName.Buffer);
690  }
691 
692  /* Return found information */
693  if (NextEntry == &(DeviceExtension->DeviceListHead))
694  {
696  }
697 
698  *DeviceInformation = DeviceInfo;
699  return STATUS_SUCCESS;
700 }
701 
702 /*
703  * @implemented
704  */
705 VOID
707 {
708  FreePool(DeviceInformation->SymbolicName.Buffer);
709  FreePool(DeviceInformation);
710 }
711 
712 /*
713  * @implemented
714  */
715 VOID
717 {
718  PLIST_ENTRY NextEntry;
719  PSYMLINK_INFORMATION SymLink;
720  PUNIQUE_ID_REPLICATE UniqueId;
721  PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
722 
723  /* Purge symbolic links list */
724  while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
725  {
726  NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
727  SymLink = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
728 
729  GlobalDeleteSymbolicLink(&(SymLink->Name));
730  FreePool(SymLink->Name.Buffer);
731  }
732 
733  /* Purge replicated unique IDs list */
734  while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
735  {
736  NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
737  UniqueId = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
738 
739  FreePool(UniqueId->UniqueId);
740  FreePool(UniqueId);
741  }
742 
743  while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
744  {
745  NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
746  AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
747 
748  FreePool(AssociatedDevice->String.Buffer);
749  FreePool(AssociatedDevice);
750  }
751 
752  /* Free the rest of the buffers */
753  FreePool(DeviceInformation->SymbolicName.Buffer);
754  if (DeviceInformation->KeepLinks)
755  {
756  FreePool(DeviceInformation->UniqueId);
757  }
758  FreePool(DeviceInformation->DeviceName.Buffer);
759 
760  /* Finally, stop waiting for notifications for this device */
761  if (DeviceInformation->TargetDeviceNotificationEntry)
762  {
763  IoUnregisterPlugPlayNotification(DeviceInformation->TargetDeviceNotificationEntry);
764  }
765 }
766 
767 /*
768  * @implemented
769  */
770 VOID
772 {
773  PLIST_ENTRY NextEntry;
774  PSYMLINK_INFORMATION SymlinkInformation;
775 
776  /* For all the saved links */
777  while (!IsListEmpty(&(SavedLinkInformation->SymbolicLinksListHead)))
778  {
779  NextEntry = RemoveHeadList(&(SavedLinkInformation->SymbolicLinksListHead));
780  SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
781 
782  /* Remove from system & free */
783  GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
784  FreePool(SymlinkInformation->Name.Buffer);
785  FreePool(SymlinkInformation);
786  }
787 
788  /* And free unique ID & entry */
789  FreePool(SavedLinkInformation->UniqueId);
790  FreePool(SavedLinkInformation);
791 }
792 
793 
794 /*
795  * @implemented
796  */
797 VOID
798 NTAPI
800 {
801  PLIST_ENTRY NextEntry;
802  PUNIQUE_ID_WORK_ITEM WorkItem;
803  PDEVICE_EXTENSION DeviceExtension;
804  PDEVICE_INFORMATION DeviceInformation;
805  PSAVED_LINK_INFORMATION SavedLinkInformation;
806 
808 
809  /* Don't get notification any longer */
811 
812  /* Free registry buffer */
813  DeviceExtension = gdeviceObject->DeviceExtension;
814  if (DeviceExtension->RegistryPath.Buffer)
815  {
816  FreePool(DeviceExtension->RegistryPath.Buffer);
817  DeviceExtension->RegistryPath.Buffer = NULL;
818  }
819 
821 
823 
824  /* Wait for workers to finish */
825  if (InterlockedIncrement(&DeviceExtension->WorkerReferences))
826  {
827  KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore),
828  IO_NO_INCREMENT, 1, FALSE);
829 
831  }
832  else
833  {
834  InterlockedDecrement(&(DeviceExtension->WorkerReferences));
835  }
836 
837  /* Don't get any notification any longerĀ² */
838  IoUnregisterPlugPlayNotification(DeviceExtension->NotificationEntry);
839 
840  /* Acquire the driver exclusively */
841  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode,
842  FALSE, NULL);
843 
844  /* Clear offline devices list */
845  while (!IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
846  {
847  NextEntry = RemoveHeadList(&(DeviceExtension->OfflineDeviceListHead));
848  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
849  MountMgrFreeDeadDeviceInfo(DeviceInformation);
850  }
851 
852  /* Clear saved links list */
853  while (!IsListEmpty(&(DeviceExtension->SavedLinksListHead)))
854  {
855  NextEntry = RemoveHeadList(&(DeviceExtension->SavedLinksListHead));
856  SavedLinkInformation = CONTAINING_RECORD(NextEntry, SAVED_LINK_INFORMATION, SavedLinksListEntry);
857  MountMgrFreeSavedLink(SavedLinkInformation);
858  }
859 
860  /* Clear workers list */
861  while (!IsListEmpty(&(DeviceExtension->UniqueIdWorkerItemListHead)))
862  {
863  NextEntry = RemoveHeadList(&(DeviceExtension->UniqueIdWorkerItemListHead));
864  WorkItem = CONTAINING_RECORD(NextEntry, UNIQUE_ID_WORK_ITEM, UniqueIdWorkerItemListEntry);
865 
867  WorkItem->Event = &UnloadEvent;
868 
869  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
870  1, FALSE);
871 
872  IoCancelIrp(WorkItem->Irp);
874 
875  IoFreeIrp(WorkItem->Irp);
876  FreePool(WorkItem->DeviceName.Buffer);
877  FreePool(WorkItem->IrpBuffer);
878  FreePool(WorkItem);
879 
880  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode,
881  FALSE, NULL);
882  }
883 
884  /* If we have drive letter data, release */
885  if (DeviceExtension->DriveLetterData)
886  {
887  FreePool(DeviceExtension->DriveLetterData);
888  DeviceExtension->DriveLetterData = NULL;
889  }
890 
891  /* Release driver & quit */
892  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
893 
896 }
897 
898 /*
899  * @implemented
900  */
901 INIT_FUNCTION
902 BOOLEAN
904 {
906  ULONG Result, Default = 0;
908 
910 
911  /* Simply read data from register */
913  QueryTable[0].Name = L"NoAutoMount";
917  QueryTable[0].DefaultLength = sizeof(ULONG);
918 
921  QueryTable,
922  NULL,
923  NULL);
924  if (!NT_SUCCESS(Status))
925  {
926  return (Default != 0);
927  }
928 
929  return (Result != 0);
930 }
931 
932 /*
933  * @implemented
934  */
935 NTSTATUS
938  IN BOOLEAN ManuallyRegistered)
939 {
940  WCHAR Letter;
941  GUID StableGuid;
942  HANDLE LinkHandle;
943  ULONG SymLinkCount, i;
944  PLIST_ENTRY NextEntry;
945  PUNICODE_STRING SymLinks;
946  NTSTATUS Status, IntStatus;
948  PSYMLINK_INFORMATION SymlinkInformation;
949  PMOUNTDEV_UNIQUE_ID UniqueId, NewUniqueId;
950  PSAVED_LINK_INFORMATION SavedLinkInformation;
951  PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
952  WCHAR CSymLinkBuffer[RTL_NUMBER_OF(Cunc)], LinkTargetBuffer[MAX_PATH];
953  UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink;
954  BOOLEAN HasGuid, HasGptDriveLetter, Valid, UseOnlyIfThereAreNoOtherLinks, IsDrvLetter, IsOff, IsVolumeName, LinkError;
955 
956  /* New device = new structure to represent it */
957  DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION));
958  if (!DeviceInformation)
959  {
961  }
962 
963  /* Initialise device structure */
964  RtlZeroMemory(DeviceInformation, sizeof(DEVICE_INFORMATION));
965  InitializeListHead(&(DeviceInformation->SymbolicLinksListHead));
966  InitializeListHead(&(DeviceInformation->ReplicatedUniqueIdsListHead));
967  InitializeListHead(&(DeviceInformation->AssociatedDevicesHead));
968  DeviceInformation->SymbolicName.Length = SymbolicName->Length;
969  DeviceInformation->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(UNICODE_NULL);
970  DeviceInformation->SymbolicName.Buffer = AllocatePool(DeviceInformation->SymbolicName.MaximumLength);
971  if (!DeviceInformation->SymbolicName.Buffer)
972  {
973  FreePool(DeviceInformation);
975  }
976 
977  /* Copy symbolic name */
979  DeviceInformation->SymbolicName.Buffer[DeviceInformation->SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
980  DeviceInformation->ManuallyRegistered = ManuallyRegistered;
981  DeviceInformation->DeviceExtension = DeviceExtension;
982 
983  /* Query as much data as possible about device */
985  &TargetDeviceName,
986  &UniqueId,
987  &(DeviceInformation->Removable),
988  &HasGptDriveLetter,
989  &HasGuid,
990  &StableGuid,
991  &Valid);
992  if (!NT_SUCCESS(Status))
993  {
994  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
995 
996  for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
997  NextEntry != &(DeviceExtension->OfflineDeviceListHead);
998  NextEntry = NextEntry->Flink)
999  {
1000  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1001 
1002  if (RtlEqualUnicodeString(&(DeviceInformation->SymbolicName), &(CurrentDevice->SymbolicName), TRUE))
1003  {
1004  break;
1005  }
1006  }
1007 
1008  if (NextEntry != &(DeviceExtension->OfflineDeviceListHead))
1009  {
1010  MountMgrFreeDeadDeviceInfo(DeviceInformation);
1011  }
1012  else
1013  {
1014  InsertTailList(&(DeviceExtension->OfflineDeviceListHead), &(DeviceInformation->DeviceListEntry));
1015  }
1016 
1017  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1018 
1019  return Status;
1020  }
1021 
1022  /* Save gathered data */
1023  DeviceInformation->UniqueId = UniqueId;
1024  DeviceInformation->DeviceName = TargetDeviceName;
1025  DeviceInformation->KeepLinks = FALSE;
1026 
1027  /* If we found system partition, mark it */
1028  if (DeviceExtension->DriveLetterData && UniqueId->UniqueIdLength == DeviceExtension->DriveLetterData->UniqueIdLength)
1029  {
1030  if (RtlCompareMemory(UniqueId->UniqueId, DeviceExtension->DriveLetterData->UniqueId, UniqueId->UniqueIdLength)
1031  == UniqueId->UniqueIdLength)
1032  {
1033  IoSetSystemPartition(&TargetDeviceName);
1034  }
1035  }
1036 
1037  /* Check suggested link name */
1038  Status = QuerySuggestedLinkName(&(DeviceInformation->SymbolicName),
1039  &SuggestedLinkName,
1040  &UseOnlyIfThereAreNoOtherLinks);
1041  if (!NT_SUCCESS(Status))
1042  {
1043  SuggestedLinkName.Buffer = NULL;
1044  }
1045 
1046  /* If it's OK, set it and save its letter (if any) */
1047  if (SuggestedLinkName.Buffer && IsDriveLetter(&SuggestedLinkName))
1048  {
1049  DeviceInformation->SuggestedDriveLetter = (UCHAR)SuggestedLinkName.Buffer[LETTER_POSITION];
1050  }
1051 
1052  /* Acquire driver exclusively */
1053  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1054 
1055  /* Check if we already have device in to prevent double registration */
1056  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1057  NextEntry != &(DeviceExtension->DeviceListHead);
1058  NextEntry = NextEntry->Flink)
1059  {
1060  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1061 
1062  if (RtlEqualUnicodeString(&(CurrentDevice->DeviceName), &TargetDeviceName, TRUE))
1063  {
1064  break;
1065  }
1066  }
1067 
1068  /* If we found it, clear ours, and return success, all correct */
1069  if (NextEntry != &(DeviceExtension->DeviceListHead))
1070  {
1071  if (SuggestedLinkName.Buffer)
1072  {
1073  FreePool(SuggestedLinkName.Buffer);
1074  }
1075 
1076  FreePool(UniqueId);
1077  FreePool(TargetDeviceName.Buffer);
1078  FreePool(DeviceInformation->DeviceName.Buffer);
1079  FreePool(DeviceInformation);
1080 
1081  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1082 
1083  return STATUS_SUCCESS;
1084  }
1085 
1086  /* Check if there are symlinks associated with our device in registry */
1087  Status = QuerySymbolicLinkNamesFromStorage(DeviceExtension,
1088  DeviceInformation,
1089  (SuggestedLinkName.Buffer) ? &SuggestedLinkName : NULL,
1090  UseOnlyIfThereAreNoOtherLinks,
1091  &SymLinks,
1092  &SymLinkCount,
1093  HasGuid,
1094  &StableGuid);
1095 
1096  /* If our device is a CD-ROM */
1097  if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
1098  {
1099  LinkTarget.Length = 0;
1100  LinkTarget.MaximumLength = sizeof(LinkTargetBuffer);
1101  LinkTarget.Buffer = LinkTargetBuffer;
1102 
1103  RtlCopyMemory(CSymLinkBuffer, Cunc, sizeof(Cunc));
1104  RtlInitUnicodeString(&CSymLink, CSymLinkBuffer);
1105 
1106  /* Start checking all letters that could have been associated */
1107  for (Letter = L'D'; Letter <= L'Z'; Letter++)
1108  {
1109  CSymLink.Buffer[LETTER_POSITION] = Letter;
1110 
1112  &CSymLink,
1114  NULL,
1115  NULL);
1116 
1117  /* Try to open the associated symlink */
1119  if (!NT_SUCCESS(Status))
1120  {
1121  continue;
1122  }
1123 
1124  /* And query its target */
1125  Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);
1126  ZwClose(LinkHandle);
1127 
1128  if (!NT_SUCCESS(Status))
1129  {
1130  continue;
1131  }
1132 
1133  IntStatus = STATUS_UNSUCCESSFUL;
1134  if (!RtlEqualUnicodeString(&LinkTarget, &DeviceInformation->DeviceName, FALSE))
1135  {
1136  continue;
1137  }
1138 
1139  /* This link is matching our device, whereas it's not supposed to have any
1140  * symlink associated.
1141  * Delete it
1142  */
1143  if (!SymLinkCount)
1144  {
1145  IoDeleteSymbolicLink(&CSymLink);
1146  continue;
1147  }
1148 
1149  /* Now, for all the symlinks, check for ours */
1150  for (i = 0; i < SymLinkCount; i++)
1151  {
1152  if (IsDriveLetter(&(SymLinks[i])))
1153  {
1154  /* If it exists, that's correct */
1155  if (SymLinks[i].Buffer[LETTER_POSITION] == Letter)
1156  {
1157  IntStatus = STATUS_SUCCESS;
1158  }
1159  }
1160  }
1161 
1162  /* Useless link, delete it */
1163  if (IntStatus == STATUS_UNSUCCESSFUL)
1164  {
1165  IoDeleteSymbolicLink(&CSymLink);
1166  }
1167  }
1168  }
1169 
1170  /* Suggested name is no longer required */
1171  if (SuggestedLinkName.Buffer)
1172  {
1173  FreePool(SuggestedLinkName.Buffer);
1174  }
1175 
1176  /* If if failed, ensure we don't take symlinks into account */
1177  if (!NT_SUCCESS(Status))
1178  {
1179  SymLinks = NULL;
1180  SymLinkCount = 0;
1181  }
1182 
1183  /* Now we queried them, remove the symlinks */
1184  SavedLinkInformation = RemoveSavedLinks(DeviceExtension, UniqueId);
1185 
1186  IsDrvLetter = FALSE;
1187  IsOff = FALSE;
1188  IsVolumeName = FALSE;
1189  /* For all the symlinks */
1190  for (i = 0; i < SymLinkCount; i++)
1191  {
1192  /* Check if our device is a volume */
1193  if (MOUNTMGR_IS_VOLUME_NAME(&(SymLinks[i])))
1194  {
1195  IsVolumeName = TRUE;
1196  }
1197  /* If it has a drive letter */
1198  else if (IsDriveLetter(&(SymLinks[i])))
1199  {
1200  if (IsDrvLetter)
1201  {
1202  DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1203  continue;
1204  }
1205  else
1206  {
1207  IsDrvLetter = TRUE;
1208  }
1209  }
1210 
1211  /* And recreate the symlink to our device */
1212  Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName);
1213  if (!NT_SUCCESS(Status))
1214  {
1215  LinkError = TRUE;
1216 
1217  if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) ||
1218  !SavedLinkInformation)
1219  {
1220  Status = QueryDeviceInformation(&(SymLinks[i]), &DeviceName, NULL, NULL, NULL, NULL, NULL, NULL);
1221  if (NT_SUCCESS(Status))
1222  {
1223  LinkError = RtlEqualUnicodeString(&TargetDeviceName, &DeviceName, TRUE);
1224  FreePool(DeviceName.Buffer);
1225  }
1226 
1227  if (!LinkError)
1228  {
1229  if (IsDriveLetter(&(SymLinks[i])))
1230  {
1231  IsDrvLetter = FALSE;
1232  DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1233  }
1234 
1235  FreePool(SymLinks[i].Buffer);
1236  continue;
1237  }
1238  }
1239  }
1240 
1241  /* Check if was offline */
1242  if (IsOffline(&(SymLinks[i])))
1243  {
1244  IsOff = TRUE;
1245  }
1246 
1247  /* Finally, associate this symlink with the device */
1248  SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1249  if (!SymlinkInformation)
1250  {
1251  GlobalDeleteSymbolicLink(&(SymLinks[i]));
1252  FreePool(SymLinks[i].Buffer);
1253  continue;
1254  }
1255 
1256  SymlinkInformation->Name = SymLinks[i];
1257  SymlinkInformation->Online = TRUE;
1258 
1259  InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1260  &(SymlinkInformation->SymbolicLinksListEntry));
1261  }
1262 
1263  /* Now, for all the recreated symlinks, notify their recreation */
1264  for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1265  NextEntry != &(DeviceInformation->SymbolicLinksListHead);
1266  NextEntry = NextEntry->Flink)
1267  {
1268  SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1269 
1270  SendLinkCreated(&(SymlinkInformation->Name));
1271  }
1272 
1273  /* If we had saved links, it's time to free them */
1274  if (SavedLinkInformation)
1275  {
1276  MountMgrFreeSavedLink(SavedLinkInformation);
1277  }
1278 
1279  /* If our device doesn't have a volume name */
1280  if (!IsVolumeName)
1281  {
1282  /* It's time to create one */
1284  if (NT_SUCCESS(Status))
1285  {
1286  /* Write it to global database */
1288  DatabasePath,
1290  REG_BINARY,
1291  UniqueId->UniqueId,
1292  UniqueId->UniqueIdLength);
1293 
1294  /* And create the symlink */
1295  GlobalCreateSymbolicLink(&VolumeName, &TargetDeviceName);
1296 
1297  SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1298  if (!SymlinkInformation)
1299  {
1301  }
1302  /* Finally, associate it with the device and notify creation */
1303  else
1304  {
1305  SymlinkInformation->Name = VolumeName;
1306  SymlinkInformation->Online = TRUE;
1307  InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1308  &(SymlinkInformation->SymbolicLinksListEntry));
1309 
1311  }
1312  }
1313  }
1314 
1315  /* If we found a drive letter, then, ignore the suggested one */
1316  if (IsDrvLetter)
1317  {
1318  DeviceInformation->SuggestedDriveLetter = 0;
1319  }
1320  /* Else, it's time to set up one */
1321  else if ((DeviceExtension->NoAutoMount || DeviceInformation->Removable) &&
1322  DeviceExtension->AutomaticDriveLetter &&
1323  (HasGptDriveLetter || DeviceInformation->SuggestedDriveLetter) &&
1324  !HasNoDriveLetterEntry(UniqueId))
1325  {
1326  /* Create a new drive letter */
1327  Status = CreateNewDriveLetterName(&DriveLetter, &TargetDeviceName,
1328  DeviceInformation->SuggestedDriveLetter,
1329  NULL);
1330  if (!NT_SUCCESS(Status))
1331  {
1332  CreateNoDriveLetterEntry(UniqueId);
1333  }
1334  else
1335  {
1336  /* Save it to global database */
1338  DatabasePath,
1339  DriveLetter.Buffer,
1340  REG_BINARY,
1341  UniqueId->UniqueId,
1342  UniqueId->UniqueIdLength);
1343 
1344  /* Associate it with the device and notify creation */
1345  SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1346  if (!SymlinkInformation)
1347  {
1348  FreePool(DriveLetter.Buffer);
1349  }
1350  else
1351  {
1352  SymlinkInformation->Name = DriveLetter;
1353  SymlinkInformation->Online = TRUE;
1354  InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1355  &(SymlinkInformation->SymbolicLinksListEntry));
1356 
1357  SendLinkCreated(&DriveLetter);
1358  }
1359  }
1360  }
1361 
1362  /* If that's a PnP device, register for notifications */
1363  if (!ManuallyRegistered)
1364  {
1365  RegisterForTargetDeviceNotification(DeviceExtension, DeviceInformation);
1366  }
1367 
1368  /* Finally, insert the device into our devices list */
1369  InsertTailList(&(DeviceExtension->DeviceListHead), &(DeviceInformation->DeviceListEntry));
1370 
1371  /* Copy device unique ID */
1372  NewUniqueId = AllocatePool(UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1373  if (NewUniqueId)
1374  {
1375  NewUniqueId->UniqueIdLength = UniqueId->UniqueIdLength;
1376  RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength);
1377  }
1378 
1379  /* If device's offline or valid, skip its notifications */
1380  if (IsOff || Valid)
1381  {
1382  DeviceInformation->SkipNotifications = TRUE;
1383  }
1384 
1385  /* In case device is valid and is set to no automount,
1386  * set it offline.
1387  */
1388  if (DeviceExtension->NoAutoMount || IsDrvLetter)
1389  {
1390  IsOff = !DeviceInformation->SkipNotifications;
1391  }
1392  else
1393  {
1394  IsOff = FALSE;
1395  }
1396 
1397  /* Finally, release the exclusive lock */
1398  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1399 
1400  /* If device is not offline, notify its arrival */
1401  if (!IsOff)
1402  {
1404  }
1405 
1406  /* If we had symlinks (from storage), free them */
1407  if (SymLinks)
1408  {
1409  FreePool(SymLinks);
1410  }
1411 
1412  /* Notify about unique id change */
1413  if (NewUniqueId)
1414  {
1415  IssueUniqueIdChangeNotify(DeviceExtension, SymbolicName, NewUniqueId);
1416  FreePool(NewUniqueId);
1417  }
1418 
1419  /* If this drive was set to have a drive letter automatically
1420  * Now it's back, local databases sync will be required
1421  */
1422  if (DeviceExtension->AutomaticDriveLetter)
1423  {
1424  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1425 
1426  ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
1427 
1428  NextEntry = DeviceExtension->DeviceListHead.Flink;
1429  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1430  while (CurrentDevice != DeviceInformation)
1431  {
1432  if (!CurrentDevice->NoDatabase)
1433  {
1434  ReconcileThisDatabaseWithMaster(DeviceExtension, CurrentDevice);
1435  }
1436 
1437  NextEntry = NextEntry->Flink;
1438  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1439  }
1440 
1441  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1442  }
1443 
1444  return STATUS_SUCCESS;
1445 }
1446 
1447 /*
1448  * @implemented
1449  */
1450 VOID
1453 {
1454  PLIST_ENTRY NextEntry, DeviceEntry;
1455  PUNIQUE_ID_REPLICATE UniqueIdReplicate;
1456  PSYMLINK_INFORMATION SymlinkInformation;
1457  PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
1458  PSAVED_LINK_INFORMATION SavedLinkInformation = NULL;
1459  PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
1460 
1461  /* Acquire device exclusively */
1462  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1463 
1464  /* Look for the leaving device */
1465  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1466  NextEntry != &(DeviceExtension->DeviceListHead);
1467  NextEntry = NextEntry->Flink)
1468  {
1469  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1470 
1471  if (!RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE))
1472  {
1473  break;
1474  }
1475  }
1476 
1477  /* If we found it */
1478  if (NextEntry != &(DeviceExtension->DeviceListHead))
1479  {
1480  /* If it's asked to keep links, then, prepare to save them */
1481  if (DeviceInformation->KeepLinks)
1482  {
1483  SavedLinkInformation = AllocatePool(sizeof(SAVED_LINK_INFORMATION));
1484  if (!SavedLinkInformation)
1485  {
1486  DeviceInformation->KeepLinks = FALSE;
1487  }
1488  }
1489 
1490  /* If it's possible (and asked), start to save them */
1491  if (DeviceInformation->KeepLinks)
1492  {
1493  InsertTailList(&(DeviceExtension->SavedLinksListHead), &(SavedLinkInformation->SavedLinksListEntry));
1494  InitializeListHead(&(SavedLinkInformation->SymbolicLinksListHead));
1495  SavedLinkInformation->UniqueId = DeviceInformation->UniqueId;
1496  }
1497 
1498  /* For all the symlinks */
1499  while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
1500  {
1501  NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
1502  SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1503 
1504  /* If we have to, save the link */
1505  if (DeviceInformation->KeepLinks)
1506  {
1507  InsertTailList(&(SavedLinkInformation->SymbolicLinksListHead), &(SymlinkInformation->SymbolicLinksListEntry));
1508  }
1509  /* Otherwise, just release it */
1510  else
1511  {
1512  GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
1513  FreePool(SymlinkInformation->Name.Buffer);
1514  FreePool(SymlinkInformation);
1515  }
1516  }
1517 
1518  /* Free all the replicated unique IDs */
1519  while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
1520  {
1521  NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
1522  UniqueIdReplicate = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
1523 
1524 
1525  FreePool(UniqueIdReplicate->UniqueId);
1526  FreePool(UniqueIdReplicate);
1527  }
1528 
1529  while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
1530  {
1531  NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
1532  AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1533 
1534  DeviceInformation->NoDatabase = TRUE;
1535  FreePool(AssociatedDevice->String.Buffer);
1536  FreePool(AssociatedDevice);
1537  }
1538 
1539  /* Remove device from the device list */
1540  RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1541 
1542  /* If there are still devices, check if some were associated with ours */
1543  if (!IsListEmpty(&(DeviceInformation->DeviceListEntry)))
1544  {
1545  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1546  NextEntry != &(DeviceExtension->DeviceListHead);
1547  NextEntry = NextEntry->Flink)
1548  {
1549  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1550 
1551  /* And then, remove them */
1552  DeviceEntry = CurrentDevice->AssociatedDevicesHead.Flink;
1553  while (DeviceEntry != &(CurrentDevice->AssociatedDevicesHead))
1554  {
1555  AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1556  DeviceEntry = DeviceEntry->Flink;
1557 
1558  if (AssociatedDevice->DeviceInformation != DeviceInformation)
1559  {
1560  continue;
1561  }
1562 
1563  RemoveEntryList(&(AssociatedDevice->AssociatedDevicesEntry));
1564  FreePool(AssociatedDevice->String.Buffer);
1565  FreePool(AssociatedDevice);
1566  }
1567  }
1568  }
1569 
1570  /* Finally, clean up device name, symbolic name */
1571  FreePool(DeviceInformation->SymbolicName.Buffer);
1572  if (!DeviceInformation->KeepLinks)
1573  {
1574  FreePool(DeviceInformation->UniqueId);
1575  }
1576  FreePool(DeviceInformation->DeviceName.Buffer);
1577 
1578  /* Unregister notifications */
1579  if (DeviceInformation->TargetDeviceNotificationEntry)
1580  {
1582  }
1583 
1584  /* And leave */
1585  FreePool(DeviceInformation);
1586  }
1587  else
1588  {
1589  /* We didn't find device, perhaps because it was offline */
1590  for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
1591  NextEntry != &(DeviceExtension->OfflineDeviceListHead);
1592  NextEntry = NextEntry->Flink)
1593  {
1594  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1595 
1596  /* It was, remove it */
1597  if (RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE) == 0)
1598  {
1599  RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1600  MountMgrFreeDeadDeviceInfo(DeviceInformation);
1601  break;
1602  }
1603  }
1604  }
1605 
1606  /* Release driver */
1607  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1608 }
1609 
1610 /*
1611  * @implemented
1612  */
1613 NTSTATUS
1614 NTAPI
1616  IN PVOID Context)
1617 {
1618  BOOLEAN OldState;
1619  PDEVICE_EXTENSION DeviceExtension;
1621 
1622  /* Notification for a device arrived */
1623  /* Disable hard errors */
1626 
1627  DeviceExtension = Context;
1628  Notification = NotificationStructure;
1629 
1630  /* Dispatch according to the event */
1631  if (IsEqualGUID(&(Notification->Event), &GUID_DEVICE_INTERFACE_ARRIVAL))
1632  {
1633  MountMgrMountedDeviceArrival(DeviceExtension, Notification->SymbolicLinkName, FALSE);
1634  }
1635  else if (IsEqualGUID(&(Notification->Event), &GUID_DEVICE_INTERFACE_REMOVAL))
1636  {
1637  MountMgrMountedDeviceRemoval(DeviceExtension, Notification->SymbolicLinkName);
1638  }
1639 
1640  /* Reset hard errors */
1642 
1643  return STATUS_SUCCESS;
1644 }
1645 
1646 /*
1647  * @implemented
1648  */
1649 NTSTATUS
1650 NTAPI
1652  IN PIRP Irp)
1653 {
1654  PIO_STACK_LOCATION Stack;
1656 
1658 
1660 
1661  /* Allow driver opening for communication
1662  * as long as it's not taken for a directory
1663  */
1664  if (Stack->MajorFunction == IRP_MJ_CREATE &&
1665  Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
1666  {
1668  }
1669 
1670  Irp->IoStatus.Status = Status;
1671  Irp->IoStatus.Information = 0;
1673  return Status;
1674 }
1675 
1676 /*
1677  * @implemented
1678  */
1679 VOID
1680 NTAPI
1682  IN PIRP Irp)
1683 {
1685 
1686  RemoveEntryList(&(Irp->Tail.Overlay.ListEntry));
1687 
1688  IoReleaseCancelSpinLock(Irp->CancelIrql);
1689 
1690  Irp->IoStatus.Information = 0;
1691  Irp->IoStatus.Status = STATUS_CANCELLED;
1693 }
1694 
1695 /*
1696  * @implemented
1697  */
1698 NTSTATUS
1699 NTAPI
1701  IN PIRP Irp)
1702 {
1703  PIRP ListIrp;
1704  KIRQL OldIrql;
1705  PLIST_ENTRY NextEntry;
1707  PIO_STACK_LOCATION Stack;
1708  PDEVICE_EXTENSION DeviceExtension;
1709 
1710  DeviceExtension = DeviceObject->DeviceExtension;
1712  FileObject = Stack->FileObject;
1713 
1715 
1716  /* If IRP list if empty, it's OK */
1717  if (IsListEmpty(&(DeviceExtension->IrpListHead)))
1718  {
1720 
1721  Irp->IoStatus.Status = STATUS_SUCCESS;
1722  Irp->IoStatus.Information = 0;
1724 
1725  return STATUS_SUCCESS;
1726  }
1727 
1728  /* Otherwise, cancel all the IRPs */
1729  NextEntry = DeviceExtension->IrpListHead.Flink;
1730  do
1731  {
1732  ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
1734  {
1735  ListIrp->Cancel = TRUE;
1736  ListIrp->CancelIrql = OldIrql;
1737  ListIrp->CancelRoutine = NULL;
1738  MountMgrCancel(DeviceObject, ListIrp);
1739 
1741  }
1742 
1743  NextEntry = NextEntry->Flink;
1744  }
1745  while (NextEntry != &(DeviceExtension->IrpListHead));
1746 
1748 
1749  Irp->IoStatus.Status = STATUS_SUCCESS;
1750  Irp->IoStatus.Information = 0;
1752 
1753  return STATUS_SUCCESS;
1754 }
1755 
1756 /*
1757  * @implemented
1758  */
1759 NTSTATUS
1760 NTAPI
1762  IN PIRP Irp)
1763 {
1764  PDEVICE_EXTENSION DeviceExtension;
1765 
1766  DeviceExtension = DeviceObject->DeviceExtension;
1767 
1769 
1771 
1772  /* Wait for workers */
1773  if (InterlockedIncrement(&(DeviceExtension->WorkerReferences)))
1774  {
1775  KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore),
1777  1,
1778  FALSE);
1780  }
1781  else
1782  {
1783  InterlockedDecrement(&(DeviceExtension->WorkerReferences));
1784  }
1785 
1786  Irp->IoStatus.Status = STATUS_SUCCESS;
1787  Irp->IoStatus.Information = 0;
1789 
1790  return STATUS_SUCCESS;
1791 }
1792 
1793 /* FUNCTIONS ****************************************************************/
1794 
1795 INIT_FUNCTION
1796 NTSTATUS
1797 NTAPI
1800 {
1801  NTSTATUS Status;
1803  PDEVICE_EXTENSION DeviceExtension;
1804 
1806 
1808  sizeof(DEVICE_EXTENSION),
1809  &DeviceMount,
1812  FALSE,
1813  &DeviceObject);
1814  if (!NT_SUCCESS(Status))
1815  {
1816  return Status;
1817  }
1818 
1820 
1821  DeviceExtension = DeviceObject->DeviceExtension;
1822  RtlZeroMemory(DeviceExtension, sizeof(DEVICE_EXTENSION));
1823  DeviceExtension->DeviceObject = DeviceObject;
1824  DeviceExtension->DriverObject = DriverObject;
1825 
1826  InitializeListHead(&(DeviceExtension->DeviceListHead));
1827  InitializeListHead(&(DeviceExtension->OfflineDeviceListHead));
1828 
1829  KeInitializeSemaphore(&(DeviceExtension->DeviceLock), 1, 1);
1830  KeInitializeSemaphore(&(DeviceExtension->RemoteDatabaseLock), 1, 1);
1831 
1832  InitializeListHead(&(DeviceExtension->IrpListHead));
1833  DeviceExtension->EpicNumber = 1;
1834 
1835  InitializeListHead(&(DeviceExtension->SavedLinksListHead));
1836 
1837  InitializeListHead(&(DeviceExtension->WorkerQueueListHead));
1838  KeInitializeSemaphore(&(DeviceExtension->WorkerSemaphore), 0, MAXLONG);
1839  DeviceExtension->WorkerReferences = -1;
1840  KeInitializeSpinLock(&(DeviceExtension->WorkerLock));
1841 
1842  InitializeListHead(&(DeviceExtension->UniqueIdWorkerItemListHead));
1843  InitializeListHead(&(DeviceExtension->OnlineNotificationListHead));
1844  DeviceExtension->OnlineNotificationCount = 1;
1845 
1846  DeviceExtension->RegistryPath.Length = RegistryPath->Length;
1847  DeviceExtension->RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
1848  DeviceExtension->RegistryPath.Buffer = AllocatePool(DeviceExtension->RegistryPath.MaximumLength);
1849  if (!DeviceExtension->RegistryPath.Buffer)
1850  {
1853  }
1854 
1855  RtlCopyUnicodeString(&(DeviceExtension->RegistryPath), RegistryPath);
1856 
1857  DeviceExtension->NoAutoMount = MountmgrReadNoAutoMount(&(DeviceExtension->RegistryPath));
1858 
1860 
1861  /* Register for device arrival & removal. Ask to be notified for already
1862  * present devices
1863  */
1867  DriverObject,
1869  DeviceExtension,
1870  &(DeviceExtension->NotificationEntry));
1871 
1872  if (!NT_SUCCESS(Status))
1873  {
1875  return Status;
1876  }
1877 
1883 
1885 
1887  if (!NT_SUCCESS(Status))
1888  {
1890  }
1891 
1892  return Status;
1893 }
_In_ PVOID NotificationStructure
Definition: iofuncs.h:1203
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(IN PVOID NotificationEntry)
Definition: pnpnotify.c:371
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSTATUS NTAPI MountMgrCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1651
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:82
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4004
#define IN
Definition: typedefs.h:38
VOID MountMgrFreeMountedDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:716
UNICODE_STRING DeviceName
Definition: mntmgr.h:147
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
const GUID GUID_DEVICE_INTERFACE_ARRIVAL
Definition: deviface.c:14
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
UNICODE_STRING DosDevices
Definition: symlink.c:33
VOID DeleteFromLocalDatabase(IN PUNICODE_STRING SymbolicLink, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:351
#define FILE_DEVICE_NETWORK
Definition: winioctl.h:123
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define MAXLONG
Definition: umtypes.h:116
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:706
#define IRP_MJ_SHUTDOWN
#define REG_BINARY
Definition: nt_native.h:1496
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
KEVENT UnloadEvent
Definition: mountmgr.c:41
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:136
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:98
NTSTATUS NTAPI MountMgrShutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1761
VOID NTAPI MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1681
VOID SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
Definition: notify.c:38
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4676
LONG NTSTATUS
Definition: precomp.h:26
USHORT UniqueIdLength
Definition: imports.h:138
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:922
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:87
VOID RegisterForTargetDeviceNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: notify.c:275
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
#define PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES
Definition: iotypes.h:1196
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define LETTER_POSITION
Definition: mntmgr.h:159
IRP
Definition: iotypes.h:2463
WCHAR DeviceName[]
Definition: adapter.cpp:21
#define InsertTailList(ListHead, Entry)
NTSTATUS CreateNewVolumeName(OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL)
Definition: symlink.c:462
#define FreePool(P)
Definition: mntmgr.h:154
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
LIST_ENTRY AssociatedDevicesEntry
Definition: mntmgr.h:97
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
DWORD Id
VOID MountMgrFreeSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation)
Definition: mountmgr.c:771
BOOLEAN HasNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:354
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1595
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define UNICODE_NULL
long LONG
Definition: pedump.c:60
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:61
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
NTSTATUS MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN ManuallyRegistered)
Definition: mountmgr.c:936
struct NameRec_ * Name
Definition: cdprocs.h:464
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
BOOLEAN NoDatabase
Definition: mntmgr.h:57
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
struct _MOUNTDEV_NAME MOUNTDEV_NAME
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
UNICODE_STRING DeviceMount
Definition: symlink.c:31
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
#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
void DPRINT(...)
Definition: polytest.cpp:61
NTSYSAPI NTSTATUS NTAPI RtlCreateRegistryKey(_In_ ULONG RelativeTo, _In_ PWSTR Path)
Definition: bufpool.h:45
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:132
PDEVICE_EXTENSION DeviceExtension
Definition: mntmgr.h:62
PDEVICE_OBJECT gdeviceObject
Definition: mountmgr.c:40
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID
Definition: imports.h:255
NTSTATUS NTAPI IoSetSystemPartition(IN PUNICODE_STRING VolumeNameString)
Definition: volume.c:1231
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _MOUNTDEV_UNIQUE_ID MOUNTDEV_UNIQUE_ID
BOOLEAN KeepLinks
Definition: mntmgr.h:51
VOID NTAPI KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit)
Definition: semphobj.c:22
BOOLEAN SkipNotifications
Definition: mntmgr.h:58
VOID NTAPI PsSetThreadHardErrorsAreDisabled(IN PETHREAD Thread, IN BOOLEAN HardErrorsAreDisabled)
Definition: thread.c:898
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:271
Definition: mntmgr.h:95
#define MAX_PATH
Definition: compat.h:26
LIST_ENTRY SymbolicLinksListHead
Definition: mntmgr.h:45
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
struct _DeviceInfo DeviceInfo
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2101
VOID NTAPI IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1725
NTSTATUS QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING SuggestedLinkName, OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
Definition: symlink.c:684
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
VOID MountMgrMountedDeviceRemoval(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName)
Definition: mountmgr.c:1451
* PFILE_OBJECT
Definition: iotypes.h:1955
NTSTATUS QuerySymbolicLinkNamesFromStorage(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation, IN PUNICODE_STRING SuggestedLinkName, IN BOOLEAN UseOnlyIfThereAreNoOtherLinks, OUT PUNICODE_STRING *SymLinks, OUT PULONG SymLinkCount, IN BOOLEAN HasGuid, IN LPGUID Guid)
Definition: symlink.c:514
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
BOOLEAN IsOffline(PUNICODE_STRING SymbolicName)
Definition: mountmgr.c:50
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:269
char * PBOOLEAN
Definition: retypes.h:11
static const WCHAR Cunc[]
Definition: mountmgr.c:44
INIT_FUNCTION NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
Definition: mountmgr.c:1798
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
static const WCHAR L[]
Definition: oid.c:1250
NTSTATUS CreateNewDriveLetterName(OUT PUNICODE_STRING DriveLetter, IN PUNICODE_STRING DeviceName, IN UCHAR Letter, IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL)
Definition: mountmgr.c:112
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define InterlockedDecrement
Definition: armddk.h:52
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
PDRIVER_UNLOAD DriverUnload
Definition: iotypes.h:2180
WCHAR Letter
BOOLEAN NTAPI PsGetThreadHardErrorsAreDisabled(IN PETHREAD Thread)
Definition: thread.c:695
NTSTATUS NTAPI IoRegisterPlugPlayNotification(IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, IN ULONG EventCategoryFlags, IN PVOID EventCategoryData OPTIONAL, IN PDRIVER_OBJECT DriverObject, IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, IN PVOID Context, OUT PVOID *NotificationEntry)
Definition: pnpnotify.c:249
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
BOOLEAN ManuallyRegistered
Definition: mntmgr.h:53
UNICODE_STRING String
Definition: mntmgr.h:99
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define InterlockedExchange
Definition: armddk.h:54
PWSTR DatabasePath
Definition: database.c:31
UNICODE_STRING DosDevicesMount
Definition: symlink.c:32
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
Status
Definition: gdiplustypes.h:24
DRIVER_DISPATCH MountMgrDeviceControl
Definition: mntmgr.h:340
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PSAVED_LINK_INFORMATION RemoveSavedLinks(IN PDEVICE_EXTENSION DeviceExtension, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: symlink.c:640
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
NTSTATUS NTAPI MountMgrMountedDeviceNotification(IN PVOID NotificationStructure, IN PVOID Context)
Definition: mountmgr.c:1615
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
BOOLEAN Removable
Definition: mntmgr.h:54
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
NTSTATUS GlobalCreateSymbolicLink(IN PUNICODE_STRING DosName, IN PUNICODE_STRING DeviceName)
Definition: symlink.c:111
NTSTATUS FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:641
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
const GUID GUID_DEVICE_INTERFACE_REMOVAL
Definition: deviface.c:15
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4021
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
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
UNICODE_STRING DeviceName
Definition: mntmgr.h:50
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
Definition: irp.c:1101
NTSTATUS NTAPI IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1694
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
#define IRP_MJ_CLEANUP
INIT_FUNCTION BOOLEAN MountmgrReadNoAutoMount(IN PUNICODE_STRING RegistryPath)
Definition: mountmgr.c:903
NTSTATUS NTAPI MountMgrCleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1700
#define OUT
Definition: typedefs.h:39
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1]
Definition: iotypes.h:2181
LIST_ENTRY ReplicatedUniqueIdsListHead
Definition: mntmgr.h:46
LIST_ENTRY DeviceListEntry
Definition: mntmgr.h:44
struct tagContext Context
Definition: acpixf.h:1024
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
#define SYMBOLIC_LINK_QUERY
Definition: nt_native.h:1265
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
LIST_ENTRY AssociatedDevicesHead
Definition: mntmgr.h:47
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
_In_ PUNICODE_STRING RegistryPath
Definition: wmip.h:27
VOID NTAPI MountMgrUnload(IN struct _DRIVER_OBJECT *DriverObject)
Definition: mountmgr.c:799
PVOID TargetDeviceNotificationEntry
Definition: mntmgr.h:61
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
NTSTATUS QueryDeviceInformation(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING DeviceName OPTIONAL, OUT PMOUNTDEV_UNIQUE_ID *UniqueId OPTIONAL, OUT PBOOLEAN Removable OPTIONAL, OUT PBOOLEAN GptDriveLetter OPTIONAL, OUT PBOOLEAN HasGuid OPTIONAL, IN OUT LPGUID StableGuid OPTIONAL, OUT PBOOLEAN Valid OPTIONAL)
Definition: mountmgr.c:194
PWSTR OfflinePath
Definition: database.c:32
#define REG_NONE
Definition: nt_native.h:1492
VOID SendLinkCreated(IN PUNICODE_STRING SymbolicName)
Definition: symlink.c:160
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define REG_DWORD
Definition: sdbapi.c:596
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:49
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
VOID IssueUniqueIdChangeNotify(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: notify.c:660
#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES
Definition: ntddvol.h:56
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
UCHAR UniqueId[1]
Definition: imports.h:139
UCHAR SuggestedDriveLetter
Definition: mntmgr.h:52
HRESULT Create([out]ITransactionReceiver **ppReceiver)
LONG Unloading
Definition: mountmgr.c:42
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
Definition: arc.h:81
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
UNICODE_STRING DeviceCdRom
Definition: symlink.c:35
BOOLEAN RedirectSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation, IN PUNICODE_STRING DosName, IN PUNICODE_STRING NewLink)
Definition: symlink.c:827
GUID MountedDevicesGuid
Definition: mountmgr.c:38
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68