ReactOS  0.4.13-dev-92-gf251225
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  /* To have a drive letter, a device must have symbolic links */
93  if (IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
94  {
95  return FALSE;
96  }
97 
98  /* Browse all the links untill a drive letter is found */
99  NextEntry = &(DeviceInformation->SymbolicLinksListHead);
100  do
101  {
102  SymlinkInfo = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
103 
104  if (SymlinkInfo->Online)
105  {
106  if (IsDriveLetter(&(SymlinkInfo->Name)))
107  {
108  return TRUE;
109  }
110  }
111 
112  NextEntry = NextEntry->Flink;
113  } while (NextEntry != &(DeviceInformation->SymbolicLinksListHead));
114 
115  return FALSE;
116 }
117 
118 /*
119  * @implemented
120  */
121 NTSTATUS
124  IN UCHAR Letter,
126 {
128 
129  /* Allocate a big enough buffer to contain the symbolic link */
130  DriveLetter->MaximumLength = DosDevices.Length + 3 * sizeof(WCHAR);
131  DriveLetter->Buffer = AllocatePool(DriveLetter->MaximumLength);
132  if (!DriveLetter->Buffer)
133  {
135  }
136 
137  /* Copy prefix */
138  RtlCopyUnicodeString(DriveLetter, &DosDevices);
139 
140  /* Update string to reflect real contents */
141  DriveLetter->Length = DosDevices.Length + 2 * sizeof(WCHAR);
142  DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR) + 2] = UNICODE_NULL;
143  DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR) + 1] = L':';
144 
145  /* If caller wants a no drive entry */
146  if (Letter == (UCHAR)-1)
147  {
148  /* Then, create a no letter entry */
149  CreateNoDriveLetterEntry(UniqueId);
150  FreePool(DriveLetter->Buffer);
151  return STATUS_UNSUCCESSFUL;
152  }
153  else if (Letter)
154  {
155  /* Use the letter given by the caller */
156  DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR)] = (WCHAR)Letter;
158  if (NT_SUCCESS(Status))
159  {
160  return Status;
161  }
162  }
163 
164  /* If caller didn't provide a letter, let's find one for him */
165 
167  {
168  /* If the device is a floppy, start with letter A */
169  Letter = 'A';
170  }
172  {
173  /* If the device is a CD-ROM, start with letter D */
174  Letter = 'D';
175  }
176  else
177  {
178  /* Finally, if it's a disk, use C */
179  Letter = 'C';
180  }
181 
182  /* Try to affect a letter (up to Z, ofc) until it's possible */
183  for (; Letter <= 'Z'; Letter++)
184  {
185  DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR)] = (WCHAR)Letter;
187  if (NT_SUCCESS(Status))
188  {
189  DPRINT("Assigned drive %c: to %wZ\n", Letter, DeviceName);
190  return Status;
191  }
192  }
193 
194  /* We failed to allocate a letter */
195  FreePool(DriveLetter->Buffer);
196  DPRINT("Failed to create a drive letter for %wZ\n", DeviceName);
197  return Status;
198 }
199 
200 /*
201  * @implemented
202  */
203 NTSTATUS
206  OUT PMOUNTDEV_UNIQUE_ID * UniqueId OPTIONAL,
208  OUT PBOOLEAN GptDriveLetter OPTIONAL,
209  OUT PBOOLEAN HasGuid OPTIONAL,
210  IN OUT LPGUID StableGuid OPTIONAL,
211  OUT PBOOLEAN Valid OPTIONAL)
212 {
213  PIRP Irp;
214  USHORT Size;
215  KEVENT Event;
216  BOOLEAN IsRemovable;
220  PIO_STACK_LOCATION Stack;
221  NTSTATUS Status, IntStatus;
225  STORAGE_DEVICE_NUMBER StorageDeviceNumber;
227 
228  /* Get device associated with the symbolic name */
231  &FileObject,
232  &DeviceObject);
233  if (!NT_SUCCESS(Status))
234  {
235  return Status;
236  }
237 
238  /* The associate FO can't have a file name */
239  if (FileObject->FileName.Length)
240  {
243  }
244 
245  /* Check if it's removable & return to the user (if asked to) */
246  IsRemovable = (FileObject->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
247  if (Removable)
248  {
249  *Removable = IsRemovable;
250  }
251 
252  /* Get the attached device */
254 
255  /* If we've been asked for a GPT drive letter */
256  if (GptDriveLetter)
257  {
258  /* Consider it has one */
259  *GptDriveLetter = TRUE;
260 
261  if (!IsRemovable)
262  {
263  /* Query the GPT attributes */
266  DeviceObject,
267  NULL,
268  0,
269  &GptAttributes,
270  sizeof(GptAttributes),
271  FALSE,
272  &Event,
273  &IoStatusBlock);
274  if (!Irp)
275  {
279  }
280 
282  if (Status == STATUS_PENDING)
283  {
286  }
287 
288  /* In case of failure, don't fail, that's no vital */
289  if (!NT_SUCCESS(Status))
290  {
292  }
293  /* Check if it has a drive letter */
294  else if (!(GptAttributes.GptAttributes &
295  GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER))
296  {
297  *GptDriveLetter = FALSE;
298  }
299  }
300  }
301 
302  /* If caller wants to know if there's valid contents */
303  if (Valid)
304  {
305  /* Suppose it's not OK */
306  *Valid = FALSE;
307 
308  if (!IsRemovable)
309  {
310  /* Query partitions information */
313  DeviceObject,
314  NULL,
315  0,
316  &PartitionInfo,
317  sizeof(PartitionInfo),
318  FALSE,
319  &Event,
320  &IoStatusBlock);
321  if (!Irp)
322  {
326  }
327 
329  if (Status == STATUS_PENDING)
330  {
333  }
334 
335  /* Once again here, failure isn't major */
336  if (!NT_SUCCESS(Status))
337  {
339  }
340  /* Verify we know something in */
341  else if (PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR &&
342  IsRecognizedPartition(PartitionInfo.Mbr.PartitionType))
343  {
344  *Valid = TRUE;
345  }
346 
347  /* It looks correct, ensure it is & query device number */
348  if (*Valid)
349  {
352  DeviceObject,
353  NULL,
354  0,
355  &StorageDeviceNumber,
356  sizeof(StorageDeviceNumber),
357  FALSE,
358  &Event,
359  &IoStatusBlock);
360  if (!Irp)
361  {
365  }
366 
368  if (Status == STATUS_PENDING)
369  {
372  }
373 
374  if (!NT_SUCCESS(Status))
375  {
377  }
378  else
379  {
380  *Valid = FALSE;
381  }
382  }
383  }
384  }
385 
386  /* If caller needs device name */
387  if (DeviceName)
388  {
389  /* Allocate a buffer just to request length */
390  Name = AllocatePool(sizeof(MOUNTDEV_NAME));
391  if (!Name)
392  {
396  }
397 
398  /* Query device name */
401  DeviceObject,
402  NULL,
403  0,
404  Name,
405  sizeof(MOUNTDEV_NAME),
406  FALSE,
407  &Event,
408  &IoStatusBlock);
409  if (!Irp)
410  {
411  FreePool(Name);
415  }
416 
418  Stack->FileObject = FileObject;
419 
421  if (Status == STATUS_PENDING)
422  {
425  }
426 
427  /* Now, we've got the correct length */
429  {
430  Size = Name->NameLength + sizeof(MOUNTDEV_NAME);
431 
432  FreePool(Name);
433 
434  /* Allocate proper size */
436  if (!Name)
437  {
441  }
442 
443  /* And query name (for real that time) */
446  DeviceObject,
447  NULL,
448  0,
449  Name,
450  Size,
451  FALSE,
452  &Event,
453  &IoStatusBlock);
454  if (!Irp)
455  {
456  FreePool(Name);
460  }
461 
463  Stack->FileObject = FileObject;
464 
466  if (Status == STATUS_PENDING)
467  {
470  }
471  }
472 
473  if (NT_SUCCESS(Status))
474  {
475  /* Copy back found name to the caller */
476  DeviceName->Length = Name->NameLength;
477  DeviceName->MaximumLength = Name->NameLength + sizeof(WCHAR);
478  DeviceName->Buffer = AllocatePool(DeviceName->MaximumLength);
479  if (!DeviceName->Buffer)
480  {
482  }
483  else
484  {
485  RtlCopyMemory(DeviceName->Buffer, Name->Name, Name->NameLength);
486  DeviceName->Buffer[Name->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
487  }
488  }
489 
490  FreePool(Name);
491  }
492 
493  if (!NT_SUCCESS(Status))
494  {
497  return Status;
498  }
499 
500  /* If caller wants device unique ID */
501  if (UniqueId)
502  {
503  /* Prepare buffer to probe length */
505  if (!Id)
506  {
510  }
511 
512  /* Query unique ID length */
515  DeviceObject,
516  NULL,
517  0,
518  Id,
519  sizeof(MOUNTDEV_UNIQUE_ID),
520  FALSE,
521  &Event,
522  &IoStatusBlock);
523  if (!Irp)
524  {
525  FreePool(Id);
529  }
530 
532  Stack->FileObject = FileObject;
533 
535  if (Status == STATUS_PENDING)
536  {
539  }
540 
541  /* Retry with appropriate length */
543  {
544  Size = Id->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID);
545 
546  FreePool(Id);
547 
548  /* Allocate the correct buffer */
549  Id = AllocatePool(Size);
550  if (!Id)
551  {
555  }
556 
557  /* Query unique ID */
560  DeviceObject,
561  NULL,
562  0,
563  Id,
564  Size,
565  FALSE,
566  &Event,
567  &IoStatusBlock);
568  if (!Irp)
569  {
570  FreePool(Id);
574  }
575 
577  Stack->FileObject = FileObject;
578 
580  if (Status == STATUS_PENDING)
581  {
584  }
585  }
586 
587  /* Hands back unique ID */
588  if (NT_SUCCESS(Status))
589  {
590  *UniqueId = Id;
591  }
592  else
593  {
594  /* In case of failure, also free the rest */
595  FreePool(Id);
596  if (DeviceName->Length)
597  {
598  FreePool(DeviceName->Buffer);
599  }
600 
603 
604  return Status;
605  }
606  }
607 
608  /* If user wants to know about GUID */
609  if (HasGuid)
610  {
611  /* Query device stable GUID */
614  DeviceObject,
615  NULL,
616  0,
617  StableGuid,
618  sizeof(GUID),
619  FALSE,
620  &Event,
621  &IoStatusBlock);
622  if (!Irp)
623  {
627  }
628 
630  Stack->FileObject = FileObject;
631 
632  IntStatus = IoCallDriver(DeviceObject, Irp);
633  if (IntStatus == STATUS_PENDING)
634  {
636  IntStatus = IoStatusBlock.Status;
637  }
638 
639  *HasGuid = NT_SUCCESS(IntStatus);
640  }
641 
644  return Status;
645 }
646 
647 /*
648  * @implemented
649  */
650 NTSTATUS
653  IN BOOLEAN DeviceNameGiven,
654  OUT PDEVICE_INFORMATION * DeviceInformation)
655 {
657  PLIST_ENTRY NextEntry;
660 
661  /* If a device name was given, use it */
662  if (DeviceNameGiven)
663  {
664  DeviceName.Length = SymbolicName->Length;
665  DeviceName.Buffer = SymbolicName->Buffer;
666  }
667  else
668  {
669  /* Otherwise, query it */
671  &DeviceName,
672  NULL, NULL,
673  NULL, NULL,
674  NULL, NULL);
675  if (!NT_SUCCESS(Status))
676  {
677  return Status;
678  }
679  }
680 
681  /* Look for device information matching devive */
682  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
683  NextEntry != &(DeviceExtension->DeviceListHead);
684  NextEntry = NextEntry->Flink)
685  {
686  DeviceInfo = CONTAINING_RECORD(NextEntry,
688  DeviceListEntry);
689 
690  if (RtlEqualUnicodeString(&DeviceName, &(DeviceInfo->DeviceName), TRUE))
691  {
692  break;
693  }
694  }
695 
696  /* Release our buffer if required */
697  if (!DeviceNameGiven)
698  {
699  FreePool(DeviceName.Buffer);
700  }
701 
702  /* Return found information */
703  if (NextEntry == &(DeviceExtension->DeviceListHead))
704  {
706  }
707 
708  *DeviceInformation = DeviceInfo;
709  return STATUS_SUCCESS;
710 }
711 
712 /*
713  * @implemented
714  */
715 VOID
717 {
718  FreePool(DeviceInformation->SymbolicName.Buffer);
719  FreePool(DeviceInformation);
720 }
721 
722 /*
723  * @implemented
724  */
725 VOID
727 {
728  PLIST_ENTRY NextEntry;
729  PSYMLINK_INFORMATION SymLink;
730  PUNIQUE_ID_REPLICATE UniqueId;
731  PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
732 
733  /* Purge symbolic links list */
734  while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
735  {
736  NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
737  SymLink = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
738 
739  GlobalDeleteSymbolicLink(&(SymLink->Name));
740  FreePool(SymLink->Name.Buffer);
741  }
742 
743  /* Purge replicated unique IDs list */
744  while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
745  {
746  NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
747  UniqueId = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
748 
749  FreePool(UniqueId->UniqueId);
750  FreePool(UniqueId);
751  }
752 
753  while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
754  {
755  NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
756  AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
757 
758  FreePool(AssociatedDevice->String.Buffer);
759  FreePool(AssociatedDevice);
760  }
761 
762  /* Free the rest of the buffers */
763  FreePool(DeviceInformation->SymbolicName.Buffer);
764  if (DeviceInformation->KeepLinks)
765  {
766  FreePool(DeviceInformation->UniqueId);
767  }
768  FreePool(DeviceInformation->DeviceName.Buffer);
769 
770  /* Finally, stop waiting for notifications for this device */
771  if (DeviceInformation->TargetDeviceNotificationEntry)
772  {
773  IoUnregisterPlugPlayNotification(DeviceInformation->TargetDeviceNotificationEntry);
774  }
775 }
776 
777 /*
778  * @implemented
779  */
780 VOID
782 {
783  PLIST_ENTRY NextEntry;
784  PSYMLINK_INFORMATION SymlinkInformation;
785 
786  /* For all the saved links */
787  while (!IsListEmpty(&(SavedLinkInformation->SymbolicLinksListHead)))
788  {
789  NextEntry = RemoveHeadList(&(SavedLinkInformation->SymbolicLinksListHead));
790  SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
791 
792  /* Remove from system & free */
793  GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
794  FreePool(SymlinkInformation->Name.Buffer);
795  FreePool(SymlinkInformation);
796  }
797 
798  /* And free unique ID & entry */
799  FreePool(SavedLinkInformation->UniqueId);
800  FreePool(SavedLinkInformation);
801 }
802 
803 
804 /*
805  * @implemented
806  */
807 VOID
808 NTAPI
810 {
811  PLIST_ENTRY NextEntry;
812  PUNIQUE_ID_WORK_ITEM WorkItem;
813  PDEVICE_EXTENSION DeviceExtension;
814  PDEVICE_INFORMATION DeviceInformation;
815  PSAVED_LINK_INFORMATION SavedLinkInformation;
816 
818 
819  /* Don't get notification any longer */
821 
822  /* Free registry buffer */
823  DeviceExtension = gdeviceObject->DeviceExtension;
824  if (DeviceExtension->RegistryPath.Buffer)
825  {
826  FreePool(DeviceExtension->RegistryPath.Buffer);
827  DeviceExtension->RegistryPath.Buffer = NULL;
828  }
829 
831 
833 
834  /* Wait for workers to finish */
835  if (InterlockedIncrement(&DeviceExtension->WorkerReferences))
836  {
837  KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore),
838  IO_NO_INCREMENT, 1, FALSE);
839 
841  }
842  else
843  {
844  InterlockedDecrement(&(DeviceExtension->WorkerReferences));
845  }
846 
847  /* Don't get any notification any longerĀ² */
848  IoUnregisterPlugPlayNotification(DeviceExtension->NotificationEntry);
849 
850  /* Acquire the driver exclusively */
851  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode,
852  FALSE, NULL);
853 
854  /* Clear offline devices list */
855  while (!IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
856  {
857  NextEntry = RemoveHeadList(&(DeviceExtension->OfflineDeviceListHead));
858  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
859  MountMgrFreeDeadDeviceInfo(DeviceInformation);
860  }
861 
862  /* Clear saved links list */
863  while (!IsListEmpty(&(DeviceExtension->SavedLinksListHead)))
864  {
865  NextEntry = RemoveHeadList(&(DeviceExtension->SavedLinksListHead));
866  SavedLinkInformation = CONTAINING_RECORD(NextEntry, SAVED_LINK_INFORMATION, SavedLinksListEntry);
867  MountMgrFreeSavedLink(SavedLinkInformation);
868  }
869 
870  /* Clear workers list */
871  while (!IsListEmpty(&(DeviceExtension->UniqueIdWorkerItemListHead)))
872  {
873  NextEntry = RemoveHeadList(&(DeviceExtension->UniqueIdWorkerItemListHead));
874  WorkItem = CONTAINING_RECORD(NextEntry, UNIQUE_ID_WORK_ITEM, UniqueIdWorkerItemListEntry);
875 
877  WorkItem->Event = &UnloadEvent;
878 
879  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
880  1, FALSE);
881 
882  IoCancelIrp(WorkItem->Irp);
884 
885  IoFreeIrp(WorkItem->Irp);
886  FreePool(WorkItem->DeviceName.Buffer);
887  FreePool(WorkItem->IrpBuffer);
888  FreePool(WorkItem);
889 
890  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode,
891  FALSE, NULL);
892  }
893 
894  /* If we have drive letter data, release */
895  if (DeviceExtension->DriveLetterData)
896  {
897  FreePool(DeviceExtension->DriveLetterData);
898  DeviceExtension->DriveLetterData = NULL;
899  }
900 
901  /* Release driver & quit */
902  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
903 
906 }
907 
908 /*
909  * @implemented
910  */
911 INIT_FUNCTION
912 BOOLEAN
914 {
916  ULONG Result, Default = 0;
918 
920 
921  /* Simply read data from register */
923  QueryTable[0].Name = L"NoAutoMount";
927  QueryTable[0].DefaultLength = sizeof(ULONG);
928 
931  QueryTable,
932  NULL,
933  NULL);
934  if (!NT_SUCCESS(Status))
935  {
936  return (Default != 0);
937  }
938 
939  return (Result != 0);
940 }
941 
942 /*
943  * @implemented
944  */
945 NTSTATUS
948  IN BOOLEAN ManuallyRegistered)
949 {
950  WCHAR Letter;
951  GUID StableGuid;
952  HANDLE LinkHandle;
953  ULONG SymLinkCount, i;
954  PLIST_ENTRY NextEntry;
955  PUNICODE_STRING SymLinks;
956  NTSTATUS Status, IntStatus;
958  PSYMLINK_INFORMATION SymlinkInformation;
959  PMOUNTDEV_UNIQUE_ID UniqueId, NewUniqueId;
960  PSAVED_LINK_INFORMATION SavedLinkInformation;
961  PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
962  WCHAR CSymLinkBuffer[RTL_NUMBER_OF(Cunc)], LinkTargetBuffer[MAX_PATH];
963  UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink;
964  BOOLEAN HasGuid, HasGptDriveLetter, Valid, UseOnlyIfThereAreNoOtherLinks, IsDrvLetter, IsOff, IsVolumeName, LinkError;
965 
966  /* New device = new structure to represent it */
967  DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION));
968  if (!DeviceInformation)
969  {
971  }
972 
973  /* Initialise device structure */
974  RtlZeroMemory(DeviceInformation, sizeof(DEVICE_INFORMATION));
975  InitializeListHead(&(DeviceInformation->SymbolicLinksListHead));
976  InitializeListHead(&(DeviceInformation->ReplicatedUniqueIdsListHead));
977  InitializeListHead(&(DeviceInformation->AssociatedDevicesHead));
978  DeviceInformation->SymbolicName.Length = SymbolicName->Length;
979  DeviceInformation->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(UNICODE_NULL);
980  DeviceInformation->SymbolicName.Buffer = AllocatePool(DeviceInformation->SymbolicName.MaximumLength);
981  if (!DeviceInformation->SymbolicName.Buffer)
982  {
983  FreePool(DeviceInformation);
985  }
986 
987  /* Copy symbolic name */
989  DeviceInformation->SymbolicName.Buffer[DeviceInformation->SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
990  DeviceInformation->ManuallyRegistered = ManuallyRegistered;
991  DeviceInformation->DeviceExtension = DeviceExtension;
992 
993  /* Query as much data as possible about device */
995  &TargetDeviceName,
996  &UniqueId,
997  &(DeviceInformation->Removable),
998  &HasGptDriveLetter,
999  &HasGuid,
1000  &StableGuid,
1001  &Valid);
1002  if (!NT_SUCCESS(Status))
1003  {
1004  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1005 
1006  for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
1007  NextEntry != &(DeviceExtension->OfflineDeviceListHead);
1008  NextEntry = NextEntry->Flink)
1009  {
1010  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1011 
1012  if (RtlEqualUnicodeString(&(DeviceInformation->SymbolicName), &(CurrentDevice->SymbolicName), TRUE))
1013  {
1014  break;
1015  }
1016  }
1017 
1018  if (NextEntry != &(DeviceExtension->OfflineDeviceListHead))
1019  {
1020  MountMgrFreeDeadDeviceInfo(DeviceInformation);
1021  }
1022  else
1023  {
1024  InsertTailList(&(DeviceExtension->OfflineDeviceListHead), &(DeviceInformation->DeviceListEntry));
1025  }
1026 
1027  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1028 
1029  return Status;
1030  }
1031 
1032  /* Save gathered data */
1033  DeviceInformation->UniqueId = UniqueId;
1034  DeviceInformation->DeviceName = TargetDeviceName;
1035  DeviceInformation->KeepLinks = FALSE;
1036 
1037  /* If we found system partition, mark it */
1038  if (DeviceExtension->DriveLetterData && UniqueId->UniqueIdLength == DeviceExtension->DriveLetterData->UniqueIdLength)
1039  {
1040  if (RtlCompareMemory(UniqueId->UniqueId, DeviceExtension->DriveLetterData->UniqueId, UniqueId->UniqueIdLength)
1041  == UniqueId->UniqueIdLength)
1042  {
1043  IoSetSystemPartition(&TargetDeviceName);
1044  }
1045  }
1046 
1047  /* Check suggested link name */
1048  Status = QuerySuggestedLinkName(&(DeviceInformation->SymbolicName),
1049  &SuggestedLinkName,
1050  &UseOnlyIfThereAreNoOtherLinks);
1051  if (!NT_SUCCESS(Status))
1052  {
1053  SuggestedLinkName.Buffer = NULL;
1054  }
1055 
1056  /* If it's OK, set it and save its letter (if any) */
1057  if (SuggestedLinkName.Buffer && IsDriveLetter(&SuggestedLinkName))
1058  {
1059  DeviceInformation->SuggestedDriveLetter = (UCHAR)SuggestedLinkName.Buffer[LETTER_POSITION];
1060  }
1061 
1062  /* Acquire driver exclusively */
1063  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1064 
1065  /* Check if we already have device in to prevent double registration */
1066  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1067  NextEntry != &(DeviceExtension->DeviceListHead);
1068  NextEntry = NextEntry->Flink)
1069  {
1070  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1071 
1072  if (RtlEqualUnicodeString(&(CurrentDevice->DeviceName), &TargetDeviceName, TRUE))
1073  {
1074  break;
1075  }
1076  }
1077 
1078  /* If we found it, clear ours, and return success, all correct */
1079  if (NextEntry != &(DeviceExtension->DeviceListHead))
1080  {
1081  if (SuggestedLinkName.Buffer)
1082  {
1083  FreePool(SuggestedLinkName.Buffer);
1084  }
1085 
1086  FreePool(UniqueId);
1087  FreePool(TargetDeviceName.Buffer);
1088  FreePool(DeviceInformation->DeviceName.Buffer);
1089  FreePool(DeviceInformation);
1090 
1091  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1092 
1093  return STATUS_SUCCESS;
1094  }
1095 
1096  /* Check if there are symlinks associated with our device in registry */
1097  Status = QuerySymbolicLinkNamesFromStorage(DeviceExtension,
1098  DeviceInformation,
1099  (SuggestedLinkName.Buffer) ? &SuggestedLinkName : NULL,
1100  UseOnlyIfThereAreNoOtherLinks,
1101  &SymLinks,
1102  &SymLinkCount,
1103  HasGuid,
1104  &StableGuid);
1105 
1106  /* If our device is a CD-ROM */
1107  if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
1108  {
1109  LinkTarget.Length = 0;
1110  LinkTarget.MaximumLength = sizeof(LinkTargetBuffer);
1111  LinkTarget.Buffer = LinkTargetBuffer;
1112 
1113  RtlCopyMemory(CSymLinkBuffer, Cunc, sizeof(Cunc));
1114  RtlInitUnicodeString(&CSymLink, CSymLinkBuffer);
1115 
1116  /* Start checking all letters that could have been associated */
1117  for (Letter = L'D'; Letter <= L'Z'; Letter++)
1118  {
1119  CSymLink.Buffer[LETTER_POSITION] = Letter;
1120 
1122  &CSymLink,
1124  NULL,
1125  NULL);
1126 
1127  /* Try to open the associated symlink */
1129  if (!NT_SUCCESS(Status))
1130  {
1131  continue;
1132  }
1133 
1134  /* And query its target */
1135  Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);
1136  ZwClose(LinkHandle);
1137 
1138  if (!NT_SUCCESS(Status))
1139  {
1140  continue;
1141  }
1142 
1143  IntStatus = STATUS_UNSUCCESSFUL;
1144  if (!RtlEqualUnicodeString(&LinkTarget, &DeviceInformation->DeviceName, FALSE))
1145  {
1146  continue;
1147  }
1148 
1149  /* This link is matching our device, whereas it's not supposed to have any
1150  * symlink associated.
1151  * Delete it
1152  */
1153  if (!SymLinkCount)
1154  {
1155  IoDeleteSymbolicLink(&CSymLink);
1156  continue;
1157  }
1158 
1159  /* Now, for all the symlinks, check for ours */
1160  for (i = 0; i < SymLinkCount; i++)
1161  {
1162  if (IsDriveLetter(&(SymLinks[i])))
1163  {
1164  /* If it exists, that's correct */
1165  if (SymLinks[i].Buffer[LETTER_POSITION] == Letter)
1166  {
1167  IntStatus = STATUS_SUCCESS;
1168  }
1169  }
1170  }
1171 
1172  /* Useless link, delete it */
1173  if (IntStatus == STATUS_UNSUCCESSFUL)
1174  {
1175  IoDeleteSymbolicLink(&CSymLink);
1176  }
1177  }
1178  }
1179 
1180  /* Suggested name is no longer required */
1181  if (SuggestedLinkName.Buffer)
1182  {
1183  FreePool(SuggestedLinkName.Buffer);
1184  }
1185 
1186  /* If if failed, ensure we don't take symlinks into account */
1187  if (!NT_SUCCESS(Status))
1188  {
1189  SymLinks = NULL;
1190  SymLinkCount = 0;
1191  }
1192 
1193  /* Now we queried them, remove the symlinks */
1194  SavedLinkInformation = RemoveSavedLinks(DeviceExtension, UniqueId);
1195 
1196  IsDrvLetter = FALSE;
1197  IsOff = FALSE;
1198  IsVolumeName = FALSE;
1199  /* For all the symlinks */
1200  for (i = 0; i < SymLinkCount; i++)
1201  {
1202  /* Check if our device is a volume */
1203  if (MOUNTMGR_IS_VOLUME_NAME(&(SymLinks[i])))
1204  {
1205  IsVolumeName = TRUE;
1206  }
1207  /* If it has a drive letter */
1208  else if (IsDriveLetter(&(SymLinks[i])))
1209  {
1210  if (IsDrvLetter)
1211  {
1212  DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1213  continue;
1214  }
1215  else
1216  {
1217  IsDrvLetter = TRUE;
1218  }
1219  }
1220 
1221  /* And recreate the symlink to our device */
1222  Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName);
1223  if (!NT_SUCCESS(Status))
1224  {
1225  LinkError = TRUE;
1226 
1227  if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) ||
1228  !SavedLinkInformation)
1229  {
1230  Status = QueryDeviceInformation(&(SymLinks[i]), &DeviceName, NULL, NULL, NULL, NULL, NULL, NULL);
1231  if (NT_SUCCESS(Status))
1232  {
1233  LinkError = RtlEqualUnicodeString(&TargetDeviceName, &DeviceName, TRUE);
1234  FreePool(DeviceName.Buffer);
1235  }
1236 
1237  if (!LinkError)
1238  {
1239  if (IsDriveLetter(&(SymLinks[i])))
1240  {
1241  IsDrvLetter = FALSE;
1242  DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1243  }
1244 
1245  FreePool(SymLinks[i].Buffer);
1246  continue;
1247  }
1248  }
1249  }
1250 
1251  /* Check if was offline */
1252  if (IsOffline(&(SymLinks[i])))
1253  {
1254  IsOff = TRUE;
1255  }
1256 
1257  /* Finally, associate this symlink with the device */
1258  SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1259  if (!SymlinkInformation)
1260  {
1261  GlobalDeleteSymbolicLink(&(SymLinks[i]));
1262  FreePool(SymLinks[i].Buffer);
1263  continue;
1264  }
1265 
1266  SymlinkInformation->Name = SymLinks[i];
1267  SymlinkInformation->Online = TRUE;
1268 
1269  InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1270  &(SymlinkInformation->SymbolicLinksListEntry));
1271  }
1272 
1273  /* Now, for all the recreated symlinks, notify their recreation */
1274  for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1275  NextEntry != &(DeviceInformation->SymbolicLinksListHead);
1276  NextEntry = NextEntry->Flink)
1277  {
1278  SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1279 
1280  SendLinkCreated(&(SymlinkInformation->Name));
1281  }
1282 
1283  /* If we had saved links, it's time to free them */
1284  if (SavedLinkInformation)
1285  {
1286  MountMgrFreeSavedLink(SavedLinkInformation);
1287  }
1288 
1289  /* If our device doesn't have a volume name */
1290  if (!IsVolumeName)
1291  {
1292  /* It's time to create one */
1294  if (NT_SUCCESS(Status))
1295  {
1296  /* Write it to global database */
1298  DatabasePath,
1300  REG_BINARY,
1301  UniqueId->UniqueId,
1302  UniqueId->UniqueIdLength);
1303 
1304  /* And create the symlink */
1305  GlobalCreateSymbolicLink(&VolumeName, &TargetDeviceName);
1306 
1307  SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1308  if (!SymlinkInformation)
1309  {
1311  }
1312  /* Finally, associate it with the device and notify creation */
1313  else
1314  {
1315  SymlinkInformation->Name = VolumeName;
1316  SymlinkInformation->Online = TRUE;
1317  InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1318  &(SymlinkInformation->SymbolicLinksListEntry));
1319 
1321  }
1322  }
1323  }
1324 
1325  /* If we found a drive letter, then, ignore the suggested one */
1326  if (IsDrvLetter)
1327  {
1328  DeviceInformation->SuggestedDriveLetter = 0;
1329  }
1330  /* Else, it's time to set up one */
1331  else if ((DeviceExtension->NoAutoMount || DeviceInformation->Removable) &&
1332  DeviceExtension->AutomaticDriveLetter &&
1333  (HasGptDriveLetter || DeviceInformation->SuggestedDriveLetter) &&
1334  !HasNoDriveLetterEntry(UniqueId))
1335  {
1336  /* Create a new drive letter */
1337  Status = CreateNewDriveLetterName(&DriveLetter, &TargetDeviceName,
1338  DeviceInformation->SuggestedDriveLetter,
1339  NULL);
1340  if (!NT_SUCCESS(Status))
1341  {
1342  CreateNoDriveLetterEntry(UniqueId);
1343  }
1344  else
1345  {
1346  /* Save it to global database */
1348  DatabasePath,
1349  DriveLetter.Buffer,
1350  REG_BINARY,
1351  UniqueId->UniqueId,
1352  UniqueId->UniqueIdLength);
1353 
1354  /* Associate it with the device and notify creation */
1355  SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1356  if (!SymlinkInformation)
1357  {
1358  FreePool(DriveLetter.Buffer);
1359  }
1360  else
1361  {
1362  SymlinkInformation->Name = DriveLetter;
1363  SymlinkInformation->Online = TRUE;
1364  InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1365  &(SymlinkInformation->SymbolicLinksListEntry));
1366 
1367  SendLinkCreated(&DriveLetter);
1368  }
1369  }
1370  }
1371 
1372  /* If that's a PnP device, register for notifications */
1373  if (!ManuallyRegistered)
1374  {
1375  RegisterForTargetDeviceNotification(DeviceExtension, DeviceInformation);
1376  }
1377 
1378  /* Finally, insert the device into our devices list */
1379  InsertTailList(&(DeviceExtension->DeviceListHead), &(DeviceInformation->DeviceListEntry));
1380 
1381  /* Copy device unique ID */
1382  NewUniqueId = AllocatePool(UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1383  if (NewUniqueId)
1384  {
1385  NewUniqueId->UniqueIdLength = UniqueId->UniqueIdLength;
1386  RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength);
1387  }
1388 
1389  /* If device's offline or valid, skip its notifications */
1390  if (IsOff || Valid)
1391  {
1392  DeviceInformation->SkipNotifications = TRUE;
1393  }
1394 
1395  /* In case device is valid and is set to no automount,
1396  * set it offline.
1397  */
1398  if (DeviceExtension->NoAutoMount || IsDrvLetter)
1399  {
1400  IsOff = !DeviceInformation->SkipNotifications;
1401  }
1402  else
1403  {
1404  IsOff = FALSE;
1405  }
1406 
1407  /* Finally, release the exclusive lock */
1408  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1409 
1410  /* If device is not offline, notify its arrival */
1411  if (!IsOff)
1412  {
1414  }
1415 
1416  /* If we had symlinks (from storage), free them */
1417  if (SymLinks)
1418  {
1419  FreePool(SymLinks);
1420  }
1421 
1422  /* Notify about unique id change */
1423  if (NewUniqueId)
1424  {
1425  IssueUniqueIdChangeNotify(DeviceExtension, SymbolicName, NewUniqueId);
1426  FreePool(NewUniqueId);
1427  }
1428 
1429  /* If this drive was set to have a drive letter automatically
1430  * Now it's back, local databases sync will be required
1431  */
1432  if (DeviceExtension->AutomaticDriveLetter)
1433  {
1434  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1435 
1436  ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
1437 
1438  NextEntry = DeviceExtension->DeviceListHead.Flink;
1439  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1440  while (CurrentDevice != DeviceInformation)
1441  {
1442  if (!CurrentDevice->NoDatabase)
1443  {
1444  ReconcileThisDatabaseWithMaster(DeviceExtension, CurrentDevice);
1445  }
1446 
1447  NextEntry = NextEntry->Flink;
1448  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1449  }
1450 
1451  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1452  }
1453 
1454  return STATUS_SUCCESS;
1455 }
1456 
1457 /*
1458  * @implemented
1459  */
1460 VOID
1463 {
1464  PLIST_ENTRY NextEntry, DeviceEntry;
1465  PUNIQUE_ID_REPLICATE UniqueIdReplicate;
1466  PSYMLINK_INFORMATION SymlinkInformation;
1467  PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
1468  PSAVED_LINK_INFORMATION SavedLinkInformation = NULL;
1469  PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
1470 
1471  /* Acquire device exclusively */
1472  KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1473 
1474  /* Look for the leaving device */
1475  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1476  NextEntry != &(DeviceExtension->DeviceListHead);
1477  NextEntry = NextEntry->Flink)
1478  {
1479  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1480 
1481  if (!RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE))
1482  {
1483  break;
1484  }
1485  }
1486 
1487  /* If we found it */
1488  if (NextEntry != &(DeviceExtension->DeviceListHead))
1489  {
1490  /* If it's asked to keep links, then, prepare to save them */
1491  if (DeviceInformation->KeepLinks)
1492  {
1493  SavedLinkInformation = AllocatePool(sizeof(SAVED_LINK_INFORMATION));
1494  if (!SavedLinkInformation)
1495  {
1496  DeviceInformation->KeepLinks = FALSE;
1497  }
1498  }
1499 
1500  /* If it's possible (and asked), start to save them */
1501  if (DeviceInformation->KeepLinks)
1502  {
1503  InsertTailList(&(DeviceExtension->SavedLinksListHead), &(SavedLinkInformation->SavedLinksListEntry));
1504  InitializeListHead(&(SavedLinkInformation->SymbolicLinksListHead));
1505  SavedLinkInformation->UniqueId = DeviceInformation->UniqueId;
1506  }
1507 
1508  /* For all the symlinks */
1509  while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
1510  {
1511  NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
1512  SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1513 
1514  /* If we have to, save the link */
1515  if (DeviceInformation->KeepLinks)
1516  {
1517  InsertTailList(&(SavedLinkInformation->SymbolicLinksListHead), &(SymlinkInformation->SymbolicLinksListEntry));
1518  }
1519  /* Otherwise, just release it */
1520  else
1521  {
1522  GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
1523  FreePool(SymlinkInformation->Name.Buffer);
1524  FreePool(SymlinkInformation);
1525  }
1526  }
1527 
1528  /* Free all the replicated unique IDs */
1529  while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
1530  {
1531  NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
1532  UniqueIdReplicate = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
1533 
1534 
1535  FreePool(UniqueIdReplicate->UniqueId);
1536  FreePool(UniqueIdReplicate);
1537  }
1538 
1539  while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
1540  {
1541  NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
1542  AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1543 
1544  DeviceInformation->NoDatabase = TRUE;
1545  FreePool(AssociatedDevice->String.Buffer);
1546  FreePool(AssociatedDevice);
1547  }
1548 
1549  /* Remove device from the device list */
1550  RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1551 
1552  /* If there are still devices, check if some were associated with ours */
1553  if (!IsListEmpty(&(DeviceInformation->DeviceListEntry)))
1554  {
1555  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1556  NextEntry != &(DeviceExtension->DeviceListHead);
1557  NextEntry = NextEntry->Flink)
1558  {
1559  CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1560 
1561  /* And then, remove them */
1562  DeviceEntry = CurrentDevice->AssociatedDevicesHead.Flink;
1563  while (DeviceEntry != &(CurrentDevice->AssociatedDevicesHead))
1564  {
1565  AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1566  DeviceEntry = DeviceEntry->Flink;
1567 
1568  if (AssociatedDevice->DeviceInformation != DeviceInformation)
1569  {
1570  continue;
1571  }
1572 
1573  RemoveEntryList(&(AssociatedDevice->AssociatedDevicesEntry));
1574  FreePool(AssociatedDevice->String.Buffer);
1575  FreePool(AssociatedDevice);
1576  }
1577  }
1578  }
1579 
1580  /* Finally, clean up device name, symbolic name */
1581  FreePool(DeviceInformation->SymbolicName.Buffer);
1582  if (!DeviceInformation->KeepLinks)
1583  {
1584  FreePool(DeviceInformation->UniqueId);
1585  }
1586  FreePool(DeviceInformation->DeviceName.Buffer);
1587 
1588  /* Unregister notifications */
1589  if (DeviceInformation->TargetDeviceNotificationEntry)
1590  {
1592  }
1593 
1594  /* And leave */
1595  FreePool(DeviceInformation);
1596  }
1597  else
1598  {
1599  /* We didn't find device, perhaps because it was offline */
1600  for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
1601  NextEntry != &(DeviceExtension->OfflineDeviceListHead);
1602  NextEntry = NextEntry->Flink)
1603  {
1604  DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1605 
1606  /* It was, remove it */
1607  if (RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE) == 0)
1608  {
1609  RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1610  MountMgrFreeDeadDeviceInfo(DeviceInformation);
1611  break;
1612  }
1613  }
1614  }
1615 
1616  /* Release driver */
1617  KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1618 }
1619 
1620 /*
1621  * @implemented
1622  */
1623 NTSTATUS
1624 NTAPI
1626  IN PVOID Context)
1627 {
1628  BOOLEAN OldState;
1629  PDEVICE_EXTENSION DeviceExtension;
1631 
1632  /* Notification for a device arrived */
1633  /* Disable hard errors */
1636 
1637  DeviceExtension = Context;
1638  Notification = NotificationStructure;
1639 
1640  /* Dispatch according to the event */
1641  if (IsEqualGUID(&(Notification->Event), &GUID_DEVICE_INTERFACE_ARRIVAL))
1642  {
1643  MountMgrMountedDeviceArrival(DeviceExtension, Notification->SymbolicLinkName, FALSE);
1644  }
1645  else if (IsEqualGUID(&(Notification->Event), &GUID_DEVICE_INTERFACE_REMOVAL))
1646  {
1647  MountMgrMountedDeviceRemoval(DeviceExtension, Notification->SymbolicLinkName);
1648  }
1649 
1650  /* Reset hard errors */
1652 
1653  return STATUS_SUCCESS;
1654 }
1655 
1656 /*
1657  * @implemented
1658  */
1659 NTSTATUS
1660 NTAPI
1662  IN PIRP Irp)
1663 {
1664  PIO_STACK_LOCATION Stack;
1666 
1668 
1670 
1671  /* Allow driver opening for communication
1672  * as long as it's not taken for a directory
1673  */
1674  if (Stack->MajorFunction == IRP_MJ_CREATE &&
1675  Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
1676  {
1678  }
1679 
1680  Irp->IoStatus.Status = Status;
1681  Irp->IoStatus.Information = 0;
1683  return Status;
1684 }
1685 
1686 /*
1687  * @implemented
1688  */
1689 VOID
1690 NTAPI
1692  IN PIRP Irp)
1693 {
1695 
1696  RemoveEntryList(&(Irp->Tail.Overlay.ListEntry));
1697 
1698  IoReleaseCancelSpinLock(Irp->CancelIrql);
1699 
1700  Irp->IoStatus.Information = 0;
1701  Irp->IoStatus.Status = STATUS_CANCELLED;
1703 }
1704 
1705 /*
1706  * @implemented
1707  */
1708 NTSTATUS
1709 NTAPI
1711  IN PIRP Irp)
1712 {
1713  PIRP ListIrp;
1714  KIRQL OldIrql;
1715  PLIST_ENTRY NextEntry;
1717  PIO_STACK_LOCATION Stack;
1718  PDEVICE_EXTENSION DeviceExtension;
1719 
1720  DeviceExtension = DeviceObject->DeviceExtension;
1722  FileObject = Stack->FileObject;
1723 
1725 
1726  /* If IRP list if empty, it's OK */
1727  if (IsListEmpty(&(DeviceExtension->IrpListHead)))
1728  {
1730 
1731  Irp->IoStatus.Status = STATUS_SUCCESS;
1732  Irp->IoStatus.Information = 0;
1734 
1735  return STATUS_SUCCESS;
1736  }
1737 
1738  /* Otherwise, cancel all the IRPs */
1739  NextEntry = &(DeviceExtension->IrpListHead);
1740  do
1741  {
1742  ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
1744  {
1745  ListIrp->Cancel = TRUE;
1746  ListIrp->CancelIrql = OldIrql;
1747  ListIrp->CancelRoutine = NULL;
1748  MountMgrCancel(DeviceObject, ListIrp);
1749 
1751  }
1752 
1753  NextEntry = NextEntry->Flink;
1754  }
1755  while (NextEntry != &(DeviceExtension->IrpListHead));
1756 
1758 
1759  Irp->IoStatus.Status = STATUS_SUCCESS;
1760  Irp->IoStatus.Information = 0;
1762 
1763  return STATUS_SUCCESS;
1764 }
1765 
1766 /*
1767  * @implemented
1768  */
1769 NTSTATUS
1770 NTAPI
1772  IN PIRP Irp)
1773 {
1774  PDEVICE_EXTENSION DeviceExtension;
1775 
1776  DeviceExtension = DeviceObject->DeviceExtension;
1777 
1779 
1781 
1782  /* Wait for workers */
1783  if (InterlockedIncrement(&(DeviceExtension->WorkerReferences)))
1784  {
1785  KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore),
1787  1,
1788  FALSE);
1790  }
1791  else
1792  {
1793  InterlockedDecrement(&(DeviceExtension->WorkerReferences));
1794  }
1795 
1796  Irp->IoStatus.Status = STATUS_SUCCESS;
1797  Irp->IoStatus.Information = 0;
1799 
1800  return STATUS_SUCCESS;
1801 }
1802 
1803 /* FUNCTIONS ****************************************************************/
1804 
1805 INIT_FUNCTION
1806 NTSTATUS
1807 NTAPI
1810 {
1811  NTSTATUS Status;
1813  PDEVICE_EXTENSION DeviceExtension;
1814 
1816 
1818  sizeof(DEVICE_EXTENSION),
1819  &DeviceMount,
1822  FALSE,
1823  &DeviceObject);
1824  if (!NT_SUCCESS(Status))
1825  {
1826  return Status;
1827  }
1828 
1830 
1831  DeviceExtension = DeviceObject->DeviceExtension;
1832  RtlZeroMemory(DeviceExtension, sizeof(DEVICE_EXTENSION));
1833  DeviceExtension->DeviceObject = DeviceObject;
1834  DeviceExtension->DriverObject = DriverObject;
1835 
1836  InitializeListHead(&(DeviceExtension->DeviceListHead));
1837  InitializeListHead(&(DeviceExtension->OfflineDeviceListHead));
1838 
1839  KeInitializeSemaphore(&(DeviceExtension->DeviceLock), 1, 1);
1840  KeInitializeSemaphore(&(DeviceExtension->RemoteDatabaseLock), 1, 1);
1841 
1842  InitializeListHead(&(DeviceExtension->IrpListHead));
1843  DeviceExtension->EpicNumber = 1;
1844 
1845  InitializeListHead(&(DeviceExtension->SavedLinksListHead));
1846 
1847  InitializeListHead(&(DeviceExtension->WorkerQueueListHead));
1848  KeInitializeSemaphore(&(DeviceExtension->WorkerSemaphore), 0, MAXLONG);
1849  DeviceExtension->WorkerReferences = -1;
1850  KeInitializeSpinLock(&(DeviceExtension->WorkerLock));
1851 
1852  InitializeListHead(&(DeviceExtension->UniqueIdWorkerItemListHead));
1853  InitializeListHead(&(DeviceExtension->OnlineNotificationListHead));
1854  DeviceExtension->OnlineNotificationCount = 1;
1855 
1856  DeviceExtension->RegistryPath.Length = RegistryPath->Length;
1857  DeviceExtension->RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
1858  DeviceExtension->RegistryPath.Buffer = AllocatePool(DeviceExtension->RegistryPath.MaximumLength);
1859  if (!DeviceExtension->RegistryPath.Buffer)
1860  {
1863  }
1864 
1865  RtlCopyUnicodeString(&(DeviceExtension->RegistryPath), RegistryPath);
1866 
1867  DeviceExtension->NoAutoMount = MountmgrReadNoAutoMount(&(DeviceExtension->RegistryPath));
1868 
1870 
1871  /* Register for device arrival & removal. Ask to be notified for already
1872  * present devices
1873  */
1877  DriverObject,
1879  DeviceExtension,
1880  &(DeviceExtension->NotificationEntry));
1881 
1882  if (!NT_SUCCESS(Status))
1883  {
1885  return Status;
1886  }
1887 
1893 
1895 
1897  if (!NT_SUCCESS(Status))
1898  {
1900  }
1901 
1902  return Status;
1903 }
_In_ PVOID NotificationStructure
Definition: iofuncs.h:1203
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(IN PVOID NotificationEntry)
Definition: pnpnotify.c:372
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSTATUS NTAPI MountMgrCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1661
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:82
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:3988
#define IN
Definition: typedefs.h:38
VOID MountMgrFreeMountedDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:726
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:716
#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:138
#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:1771
VOID NTAPI MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1691
VOID SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
Definition: notify.c:38
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4658
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:924
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:87
VOID RegisterForTargetDeviceNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: notify.c:273
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1434
#define PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES
Definition: iotypes.h:1195
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define LETTER_POSITION
Definition: mntmgr.h:159
IRP
Definition: iotypes.h:2462
WCHAR DeviceName[]
Definition: adapter.cpp:21
#define InsertTailList(ListHead, Entry)
NTSTATUS CreateNewVolumeName(OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL)
Definition: symlink.c:464
#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:781
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:1594
#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:946
struct NameRec_ * Name
Definition: cdprocs.h:464
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:434
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:1405
#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID
Definition: imports.h:255
NTSTATUS NTAPI IoSetSystemPartition(IN PUNICODE_STRING VolumeNameString)
Definition: volume.c:1223
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:1724
NTSTATUS QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING SuggestedLinkName, OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
Definition: symlink.c:686
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:1461
* PFILE_OBJECT
Definition: iotypes.h:1954
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:516
#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:1808
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:122
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:2179
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:250
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:642
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1250
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
#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:1625
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:651
#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:1693
_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:913
NTSTATUS NTAPI MountMgrCleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1710
#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:2180
LIST_ENTRY ReplicatedUniqueIdsListHead
Definition: mntmgr.h:46
LIST_ENTRY DeviceListEntry
Definition: mntmgr.h:44
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
#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:809
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:204
PWSTR OfflinePath
Definition: database.c:32
#define REG_NONE
Definition: nt_native.h:1492
VOID SendLinkCreated(IN PUNICODE_STRING SymbolicName)
Definition: symlink.c:162
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:2725
#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:658
#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:829
GUID MountedDevicesGuid
Definition: mountmgr.c:38
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68