ReactOS 0.4.15-dev-8434-g155a7c7
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/* FIXME */
33GUID MountedDevicesGuid = {0x53F5630D, 0xB6BF, 0x11D0, {0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B}};
34
38
39static const WCHAR Cunc[] = L"\\??\\C:";
40#define Cunc_LETTER_POSITION 4
41
77MountMgrSendSyncDeviceIoCtl(
85{
89 PIRP Irp;
90
91 /* We must be at passive level as we are using an on-stack event, and
92 * APCs must be enabled for allowing the Special Kernel APC queued by
93 * the IO Manager to run for completing the IRP */
96
97 /* Initialize the on-stack notification event and build the threaded IRP */
105 FALSE,
106 &Event,
108 if (!Irp)
110
111 /* Set up the FileObject for the IOCTL if required */
112 if (FileObject)
114
115 /* Finally, call the driver and wait for IRP completion if necessary */
117 if (Status == STATUS_PENDING)
118 {
121 }
122
123 return Status;
124}
125
126/*
127 * @implemented
128 */
131{
133 ULONG IsOffline, Default;
135
136 /* Prepare to look in the registry to see if
137 * given volume is offline
138 */
144 QueryTable[0].DefaultLength = sizeof(ULONG);
145 QueryTable[0].DefaultData = &Default;
146
147 Default = 0;
148
149 /* Query status */
153 NULL,
154 NULL);
155 if (!NT_SUCCESS(Status))
156 {
157 IsOffline = 0;
158 }
159
160 return (IsOffline != 0);
161}
162
163/*
164 * @implemented
165 */
168{
169 PLIST_ENTRY NextEntry;
170 PSYMLINK_INFORMATION SymlinkInfo;
171
172 /* Browse all the symlinks to check if there is at least a drive letter */
173 for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
174 NextEntry != &DeviceInformation->SymbolicLinksListHead;
175 NextEntry = NextEntry->Flink)
176 {
177 SymlinkInfo = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
178
179 if (IsDriveLetter(&SymlinkInfo->Name) && SymlinkInfo->Online)
180 {
181 return TRUE;
182 }
183 }
184
185 return FALSE;
186}
187
188/*
189 * @implemented
190 */
196{
198
199 /* Allocate a big enough buffer to contain the symbolic link */
200 DriveLetter->MaximumLength = DosDevices.Length + 3 * sizeof(WCHAR);
201 DriveLetter->Buffer = AllocatePool(DriveLetter->MaximumLength);
202 if (!DriveLetter->Buffer)
203 {
205 }
206
207 /* Copy prefix */
208 RtlCopyUnicodeString(DriveLetter, &DosDevices);
209
210 /* Update string to reflect real contents */
211 DriveLetter->Length = DosDevices.Length + 2 * sizeof(WCHAR);
212 DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR) + 2] = UNICODE_NULL;
213 DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR) + 1] = L':';
214
215 /* If caller wants a no drive entry */
216 if (Letter == (UCHAR)-1)
217 {
218 /* Then, create a no letter entry */
219 CreateNoDriveLetterEntry(UniqueId);
220 FreePool(DriveLetter->Buffer);
221 return STATUS_UNSUCCESSFUL;
222 }
223 else if (Letter)
224 {
225 /* Use the letter given by the caller */
226 DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR)] = (WCHAR)Letter;
228 if (NT_SUCCESS(Status))
229 {
230 return Status;
231 }
232 }
233
234 /* If caller didn't provide a letter, let's find one for him */
235
237 {
238 /* If the device is a floppy, start with letter A */
239 Letter = 'A';
240 }
242 {
243 /* If the device is a CD-ROM, start with letter D */
244 Letter = 'D';
245 }
246 else
247 {
248 /* Finally, if it's a disk, use C */
249 Letter = 'C';
250 }
251
252 /* Try to affect a letter (up to Z, ofc) until it's possible */
253 for (; Letter <= 'Z'; Letter++)
254 {
255 DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR)] = (WCHAR)Letter;
257 if (NT_SUCCESS(Status))
258 {
259 DPRINT("Assigned drive %c: to %wZ\n", Letter, DeviceName);
260 return Status;
261 }
262 }
263
264 /* We failed to allocate a letter */
265 FreePool(DriveLetter->Buffer);
266 DPRINT("Failed to create a drive letter for %wZ\n", DeviceName);
267 return Status;
268}
269
270/*
271 * @implemented
272 */
279 _Out_opt_ PBOOLEAN GptDriveLetter,
280 _Out_opt_ PBOOLEAN HasGuid,
281 _Inout_opt_ LPGUID StableGuid,
282 _Out_opt_ PBOOLEAN IsFT)
283{
285 USHORT Size;
286 BOOLEAN IsRemovable;
292 STORAGE_DEVICE_NUMBER StorageDeviceNumber;
294
295 /* Get device associated with the symbolic name */
298 &FileObject,
299 &DeviceObject);
300 if (!NT_SUCCESS(Status))
301 {
302 return Status;
303 }
304
305 /* The associate FO can't have a file name */
306 if (FileObject->FileName.Length)
307 {
310 }
311
312 /* Check if it's removable & return to the user (if asked to) */
313 IsRemovable = (FileObject->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
314 if (Removable)
315 {
316 *Removable = IsRemovable;
317 }
318
319 /* Get the attached device */
321
322 /* If we've been asked for a GPT drive letter */
323 if (GptDriveLetter)
324 {
325 /* Consider it has one */
326 *GptDriveLetter = TRUE;
327
328 if (!IsRemovable)
329 {
330 /* Query the GPT attributes */
331 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_VOLUME_GET_GPT_ATTRIBUTES,
333 NULL,
334 0,
335 &GptAttributes,
336 sizeof(GptAttributes),
337 NULL);
338 /* Failure isn't major */
339 if (!NT_SUCCESS(Status))
340 {
342 }
343 /* Check if it has a drive letter */
344 else if (GptAttributes.GptAttributes & GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER)
345 {
346 *GptDriveLetter = FALSE;
347 }
348 }
349 }
350
351 /* If caller wants to know if this is a FT volume */
352 if (IsFT)
353 {
354 /* Suppose it's not */
355 *IsFT = FALSE;
356
357 /* FT volume can't be removable */
358 if (!IsRemovable)
359 {
360 /* Query partition information */
361 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX,
363 NULL,
364 0,
366 sizeof(PartitionInfo),
367 NULL);
368 /* Failure isn't major */
369 if (!NT_SUCCESS(Status))
370 {
372 }
373 /* Check if this is a FT volume */
374 else if ((PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR) &&
375 IsFTPartition(PartitionInfo.Mbr.PartitionType))
376 {
377 *IsFT = TRUE;
378 }
379
380 /* It looks like a FT volume. Verify it is really one by checking
381 * that it does NOT lie on a specific storage device (i.e. it is
382 * not a basic volume). */
383 if (*IsFT)
384 {
385 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER,
387 NULL,
388 0,
389 &StorageDeviceNumber,
390 sizeof(StorageDeviceNumber),
391 NULL);
392 if (!NT_SUCCESS(Status))
394 else
395 *IsFT = FALSE; // Succeeded, so this cannot be a FT volume.
396 }
397 }
398 }
399
400 /* If caller needs device name */
401 if (DeviceName)
402 {
403 /* Allocate a buffer just to request length */
405 if (!Name)
406 {
410 }
411
412 /* Query device name */
413 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
415 NULL,
416 0,
417 Name,
418 sizeof(MOUNTDEV_NAME),
419 FileObject);
420 /* Retry with appropriate length */
422 {
423 Size = Name->NameLength + sizeof(MOUNTDEV_NAME);
424
425 FreePool(Name);
426
427 /* Allocate proper size */
429 if (!Name)
430 {
434 }
435
436 /* And query name (for real that time) */
437 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
439 NULL,
440 0,
441 Name,
442 Size,
443 FileObject);
444 }
445
446 if (NT_SUCCESS(Status))
447 {
448 /* Copy back found name to the caller */
449 DeviceName->Length = Name->NameLength;
450 DeviceName->MaximumLength = Name->NameLength + sizeof(WCHAR);
451 DeviceName->Buffer = AllocatePool(DeviceName->MaximumLength);
452 if (!DeviceName->Buffer)
453 {
455 }
456 else
457 {
458 RtlCopyMemory(DeviceName->Buffer, Name->Name, Name->NameLength);
459 DeviceName->Buffer[Name->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
460 }
461 }
462
463 FreePool(Name);
464 }
465
466 if (!NT_SUCCESS(Status))
467 {
470 return Status;
471 }
472
473 /* If caller wants device unique ID */
474 if (UniqueId)
475 {
476 /* Prepare buffer to probe length */
478 if (!Id)
479 {
483 }
484
485 /* Query unique ID length */
486 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
488 NULL,
489 0,
490 Id,
491 sizeof(MOUNTDEV_UNIQUE_ID),
492 FileObject);
493 /* Retry with appropriate length */
495 {
496 Size = Id->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID);
497
498 FreePool(Id);
499
500 /* Allocate the correct buffer */
502 if (!Id)
503 {
507 }
508
509 /* Query unique ID */
510 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
512 NULL,
513 0,
514 Id,
515 Size,
516 FileObject);
517 }
518
519 /* Hands back unique ID */
520 if (NT_SUCCESS(Status))
521 {
522 *UniqueId = Id;
523 }
524 else
525 {
526 /* In case of failure, also free the rest */
527 FreePool(Id);
528 if (DeviceName->Length)
529 FreePool(DeviceName->Buffer);
530
533 return Status;
534 }
535 }
536
537 /* If user wants to know about GUID */
538 if (HasGuid)
539 {
540 /* Query device stable GUID */
541 NTSTATUS IntStatus;
542 IntStatus = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_STABLE_GUID,
544 NULL,
545 0,
546 StableGuid,
547 sizeof(GUID),
548 FileObject);
549 *HasGuid = NT_SUCCESS(IntStatus);
550 }
551
554 return Status;
555}
556
557/*
558 * @implemented
559 */
563 IN BOOLEAN DeviceNameGiven,
564 OUT PDEVICE_INFORMATION * DeviceInformation)
565{
567 PLIST_ENTRY NextEntry;
570
571 /* If a device name was given, use it */
572 if (DeviceNameGiven)
573 {
576 }
577 else
578 {
579 /* Otherwise, query it */
581 &DeviceName,
582 NULL, NULL,
583 NULL, NULL,
584 NULL, NULL);
585 if (!NT_SUCCESS(Status))
586 {
587 return Status;
588 }
589 }
590
591 /* Look for device information matching devive */
592 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
593 NextEntry != &(DeviceExtension->DeviceListHead);
594 NextEntry = NextEntry->Flink)
595 {
596 DeviceInfo = CONTAINING_RECORD(NextEntry,
598 DeviceListEntry);
599
600 if (RtlEqualUnicodeString(&DeviceName, &(DeviceInfo->DeviceName), TRUE))
601 {
602 break;
603 }
604 }
605
606 /* Release our buffer if required */
607 if (!DeviceNameGiven)
608 {
609 FreePool(DeviceName.Buffer);
610 }
611
612 /* Return found information */
613 if (NextEntry == &(DeviceExtension->DeviceListHead))
614 {
616 }
617
618 *DeviceInformation = DeviceInfo;
619 return STATUS_SUCCESS;
620}
621
622/*
623 * @implemented
624 */
625VOID
627{
628 FreePool(DeviceInformation->SymbolicName.Buffer);
629 FreePool(DeviceInformation);
630}
631
632/*
633 * @implemented
634 */
635VOID
637{
638 PLIST_ENTRY NextEntry;
639 PSYMLINK_INFORMATION SymLink;
640 PUNIQUE_ID_REPLICATE UniqueId;
642
643 /* Purge symbolic links list */
644 while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
645 {
646 NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
647 SymLink = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
648
649 GlobalDeleteSymbolicLink(&(SymLink->Name));
650 FreePool(SymLink->Name.Buffer);
651 }
652
653 /* Purge replicated unique IDs list */
654 while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
655 {
656 NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
657 UniqueId = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
658
659 FreePool(UniqueId->UniqueId);
660 FreePool(UniqueId);
661 }
662
663 while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
664 {
665 NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
666 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
667
668 FreePool(AssociatedDevice->String.Buffer);
670 }
671
672 /* Free the rest of the buffers */
673 FreePool(DeviceInformation->SymbolicName.Buffer);
674 if (DeviceInformation->KeepLinks)
675 {
676 FreePool(DeviceInformation->UniqueId);
677 }
678 FreePool(DeviceInformation->DeviceName.Buffer);
679
680 /* Finally, stop waiting for notifications for this device */
681 if (DeviceInformation->TargetDeviceNotificationEntry)
682 {
683 IoUnregisterPlugPlayNotification(DeviceInformation->TargetDeviceNotificationEntry);
684 }
685}
686
687/*
688 * @implemented
689 */
690VOID
692{
693 PLIST_ENTRY NextEntry;
694 PSYMLINK_INFORMATION SymlinkInformation;
695
696 /* For all the saved links */
697 while (!IsListEmpty(&(SavedLinkInformation->SymbolicLinksListHead)))
698 {
699 NextEntry = RemoveHeadList(&(SavedLinkInformation->SymbolicLinksListHead));
700 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
701
702 /* Remove from system & free */
703 GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
704 FreePool(SymlinkInformation->Name.Buffer);
705 FreePool(SymlinkInformation);
706 }
707
708 /* And free unique ID & entry */
709 FreePool(SavedLinkInformation->UniqueId);
710 FreePool(SavedLinkInformation);
711}
712
713
714/*
715 * @implemented
716 */
717VOID
718NTAPI
720{
721 PLIST_ENTRY NextEntry;
723 PDEVICE_EXTENSION DeviceExtension;
724 PDEVICE_INFORMATION DeviceInformation;
725 PSAVED_LINK_INFORMATION SavedLinkInformation;
726
728
729 /* Don't get notification any longer */
731
732 /* Free registry buffer */
733 DeviceExtension = gdeviceObject->DeviceExtension;
734 if (DeviceExtension->RegistryPath.Buffer)
735 {
736 FreePool(DeviceExtension->RegistryPath.Buffer);
737 DeviceExtension->RegistryPath.Buffer = NULL;
738 }
739
741
743
744 /* Wait for workers to finish */
745 if (InterlockedIncrement(&DeviceExtension->WorkerReferences) > 0)
746 {
747 KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore),
749
751 }
752 else
753 {
754 InterlockedDecrement(&(DeviceExtension->WorkerReferences));
755 }
756
757 /* Don't get any notification any longer² */
758 IoUnregisterPlugPlayNotification(DeviceExtension->NotificationEntry);
759
760 /* Acquire the driver exclusively */
761 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode,
762 FALSE, NULL);
763
764 /* Clear offline devices list */
765 while (!IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
766 {
767 NextEntry = RemoveHeadList(&(DeviceExtension->OfflineDeviceListHead));
768 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
769 MountMgrFreeDeadDeviceInfo(DeviceInformation);
770 }
771
772 /* Clear saved links list */
773 while (!IsListEmpty(&(DeviceExtension->SavedLinksListHead)))
774 {
775 NextEntry = RemoveHeadList(&(DeviceExtension->SavedLinksListHead));
776 SavedLinkInformation = CONTAINING_RECORD(NextEntry, SAVED_LINK_INFORMATION, SavedLinksListEntry);
777 MountMgrFreeSavedLink(SavedLinkInformation);
778 }
779
780 /* Clear workers list */
781 while (!IsListEmpty(&(DeviceExtension->UniqueIdWorkerItemListHead)))
782 {
783 NextEntry = RemoveHeadList(&(DeviceExtension->UniqueIdWorkerItemListHead));
784 WorkItem = CONTAINING_RECORD(NextEntry, UNIQUE_ID_WORK_ITEM, UniqueIdWorkerItemListEntry);
785
787 WorkItem->Event = &UnloadEvent;
788
789 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
790 1, FALSE);
791
792 IoCancelIrp(WorkItem->Irp);
794
795 IoFreeIrp(WorkItem->Irp);
796 FreePool(WorkItem->DeviceName.Buffer);
797 FreePool(WorkItem->IrpBuffer);
799
800 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode,
801 FALSE, NULL);
802 }
803
804 /* If we have drive letter data, release */
805 if (DeviceExtension->DriveLetterData)
806 {
807 FreePool(DeviceExtension->DriveLetterData);
808 DeviceExtension->DriveLetterData = NULL;
809 }
810
811 /* Release driver & quit */
812 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
813
816}
817
822CODE_SEG("INIT")
826{
828 ULONG Result, Default = 0;
830
831 /* Retrieve data from registry */
834 QueryTable[0].Name = L"NoAutoMount";
837 QueryTable[0].DefaultData = &Default;
838 QueryTable[0].DefaultLength = sizeof(Default);
839
841 RegistryPath->Buffer,
843 NULL,
844 NULL);
845 if (!NT_SUCCESS(Status))
846 Result = Default;
847
848 return (Result != 0);
849}
850
851/*
852 * @implemented
853 */
857 IN BOOLEAN ManuallyRegistered)
858{
860 GUID StableGuid;
861 HANDLE LinkHandle;
862 ULONG SymLinkCount, i;
863 PLIST_ENTRY NextEntry;
864 PUNICODE_STRING SymLinks;
865 NTSTATUS Status, IntStatus;
867 PSYMLINK_INFORMATION SymlinkInformation;
868 PMOUNTDEV_UNIQUE_ID UniqueId, NewUniqueId;
869 PSAVED_LINK_INFORMATION SavedLinkInformation;
870 PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
871 WCHAR CSymLinkBuffer[RTL_NUMBER_OF(Cunc)], LinkTargetBuffer[MAX_PATH];
872 UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink;
873 BOOLEAN HasGuid, HasGptDriveLetter, IsFT, UseOnlyIfThereAreNoOtherLinks;
874 BOOLEAN IsDrvLetter, IsOff, IsVolumeName, SetOnline;
875
876 /* New device = new structure to represent it */
877 DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION));
878 if (!DeviceInformation)
879 {
881 }
882
883 /* Initialise device structure */
884 RtlZeroMemory(DeviceInformation, sizeof(DEVICE_INFORMATION));
885 InitializeListHead(&(DeviceInformation->SymbolicLinksListHead));
886 InitializeListHead(&(DeviceInformation->ReplicatedUniqueIdsListHead));
887 InitializeListHead(&(DeviceInformation->AssociatedDevicesHead));
888 DeviceInformation->SymbolicName.Length = SymbolicName->Length;
889 DeviceInformation->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(UNICODE_NULL);
890 DeviceInformation->SymbolicName.Buffer = AllocatePool(DeviceInformation->SymbolicName.MaximumLength);
891 if (!DeviceInformation->SymbolicName.Buffer)
892 {
893 FreePool(DeviceInformation);
895 }
896
897 /* Copy symbolic name */
899 DeviceInformation->SymbolicName.Buffer[DeviceInformation->SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
900 DeviceInformation->ManuallyRegistered = ManuallyRegistered;
901 DeviceInformation->DeviceExtension = DeviceExtension;
902
903 /* Query as much data as possible about device */
905 &TargetDeviceName,
906 &UniqueId,
907 &(DeviceInformation->Removable),
908 &HasGptDriveLetter,
909 &HasGuid,
910 &StableGuid,
911 &IsFT);
912 if (!NT_SUCCESS(Status))
913 {
914 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
915
916 for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
917 NextEntry != &(DeviceExtension->OfflineDeviceListHead);
918 NextEntry = NextEntry->Flink)
919 {
920 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
921
922 if (RtlEqualUnicodeString(&(DeviceInformation->SymbolicName), &(CurrentDevice->SymbolicName), TRUE))
923 {
924 break;
925 }
926 }
927
928 if (NextEntry != &(DeviceExtension->OfflineDeviceListHead))
929 {
930 MountMgrFreeDeadDeviceInfo(DeviceInformation);
931 }
932 else
933 {
934 InsertTailList(&(DeviceExtension->OfflineDeviceListHead), &(DeviceInformation->DeviceListEntry));
935 }
936
937 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
938
939 return Status;
940 }
941
942 /* Save gathered data */
943 DeviceInformation->UniqueId = UniqueId;
944 DeviceInformation->DeviceName = TargetDeviceName;
945 DeviceInformation->KeepLinks = FALSE;
946
947 /* If we found system partition, mark it */
948 if (DeviceExtension->DriveLetterData && UniqueId->UniqueIdLength == DeviceExtension->DriveLetterData->UniqueIdLength)
949 {
950 if (RtlCompareMemory(UniqueId->UniqueId, DeviceExtension->DriveLetterData->UniqueId, UniqueId->UniqueIdLength)
951 == UniqueId->UniqueIdLength)
952 {
953 IoSetSystemPartition(&TargetDeviceName);
954 }
955 }
956
957 /* Check suggested link name */
958 Status = QuerySuggestedLinkName(&(DeviceInformation->SymbolicName),
959 &SuggestedLinkName,
960 &UseOnlyIfThereAreNoOtherLinks);
961 if (!NT_SUCCESS(Status))
962 {
963 SuggestedLinkName.Buffer = NULL;
964 }
965
966 /* If it's OK, set it and save its letter (if any) */
967 if (SuggestedLinkName.Buffer && IsDriveLetter(&SuggestedLinkName))
968 {
969 DeviceInformation->SuggestedDriveLetter = (UCHAR)SuggestedLinkName.Buffer[LETTER_POSITION];
970 }
971
972 /* Acquire driver exclusively */
973 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
974
975 /* Check if we already have device in to prevent double registration */
976 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
977 NextEntry != &(DeviceExtension->DeviceListHead);
978 NextEntry = NextEntry->Flink)
979 {
980 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
981
982 if (RtlEqualUnicodeString(&(CurrentDevice->DeviceName), &TargetDeviceName, TRUE))
983 {
984 break;
985 }
986 }
987
988 /* If we found it, clear ours, and return success, all correct */
989 if (NextEntry != &(DeviceExtension->DeviceListHead))
990 {
991 if (SuggestedLinkName.Buffer)
992 {
993 FreePool(SuggestedLinkName.Buffer);
994 }
995
996 FreePool(UniqueId);
997 FreePool(TargetDeviceName.Buffer);
998 FreePool(DeviceInformation->DeviceName.Buffer);
999 FreePool(DeviceInformation);
1000
1001 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1002
1003 return STATUS_SUCCESS;
1004 }
1005
1006 /* Check if there are symlinks associated with our device in registry */
1007 Status = QuerySymbolicLinkNamesFromStorage(DeviceExtension,
1008 DeviceInformation,
1009 (SuggestedLinkName.Buffer) ? &SuggestedLinkName : NULL,
1010 UseOnlyIfThereAreNoOtherLinks,
1011 &SymLinks,
1012 &SymLinkCount,
1013 HasGuid,
1014 &StableGuid);
1015
1016 /* If our device is a CD-ROM */
1017 if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
1018 {
1019 LinkTarget.Length = 0;
1020 LinkTarget.MaximumLength = sizeof(LinkTargetBuffer);
1021 LinkTarget.Buffer = LinkTargetBuffer;
1022
1023 RtlCopyMemory(CSymLinkBuffer, Cunc, sizeof(Cunc));
1024 RtlInitUnicodeString(&CSymLink, CSymLinkBuffer);
1025
1026 /* Start checking all letters that could have been associated */
1027 for (Letter = L'D'; Letter <= L'Z'; Letter++)
1028 {
1030
1032 &CSymLink,
1034 NULL,
1035 NULL);
1036
1037 /* Try to open the associated symlink */
1039 if (!NT_SUCCESS(Status))
1040 {
1041 continue;
1042 }
1043
1044 /* And query its target */
1045 Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);
1046 ZwClose(LinkHandle);
1047
1048 if (!NT_SUCCESS(Status))
1049 {
1050 continue;
1051 }
1052
1053 IntStatus = STATUS_UNSUCCESSFUL;
1054 if (!RtlEqualUnicodeString(&LinkTarget, &DeviceInformation->DeviceName, FALSE))
1055 {
1056 continue;
1057 }
1058
1059 /* This link is matching our device, whereas it's not supposed to have any
1060 * symlink associated.
1061 * Delete it
1062 */
1063 if (!SymLinkCount)
1064 {
1065 IoDeleteSymbolicLink(&CSymLink);
1066 continue;
1067 }
1068
1069 /* Now, for all the symlinks, check for ours */
1070 for (i = 0; i < SymLinkCount; i++)
1071 {
1072 if (IsDriveLetter(&(SymLinks[i])))
1073 {
1074 /* If it exists, that's correct */
1075 if (SymLinks[i].Buffer[LETTER_POSITION] == Letter)
1076 {
1077 IntStatus = STATUS_SUCCESS;
1078 }
1079 }
1080 }
1081
1082 /* Useless link, delete it */
1083 if (IntStatus == STATUS_UNSUCCESSFUL)
1084 {
1085 IoDeleteSymbolicLink(&CSymLink);
1086 }
1087 }
1088 }
1089
1090 /* Suggested name is no longer required */
1091 if (SuggestedLinkName.Buffer)
1092 {
1093 FreePool(SuggestedLinkName.Buffer);
1094 }
1095
1096 /* If if failed, ensure we don't take symlinks into account */
1097 if (!NT_SUCCESS(Status))
1098 {
1099 SymLinks = NULL;
1100 SymLinkCount = 0;
1101 }
1102
1103 /* Now we queried them, remove the symlinks */
1104 SavedLinkInformation = RemoveSavedLinks(DeviceExtension, UniqueId);
1105
1106 IsDrvLetter = FALSE;
1107 IsOff = FALSE;
1108 IsVolumeName = FALSE;
1109 /* For all the symlinks */
1110 for (i = 0; i < SymLinkCount; i++)
1111 {
1112 /* Check if our device is a volume */
1113 if (MOUNTMGR_IS_VOLUME_NAME(&(SymLinks[i])))
1114 {
1115 IsVolumeName = TRUE;
1116 }
1117 /* If it has a drive letter */
1118 else if (IsDriveLetter(&(SymLinks[i])))
1119 {
1120 if (IsDrvLetter)
1121 {
1122 DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1123 continue;
1124 }
1125 else
1126 {
1127 IsDrvLetter = TRUE;
1128 }
1129 }
1130
1131 /* And recreate the symlink to our device */
1132 Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName);
1133 if (!NT_SUCCESS(Status))
1134 {
1135 BOOLEAN LinkError = TRUE;
1136
1137 if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) ||
1138 !SavedLinkInformation)
1139 {
1141 if (NT_SUCCESS(Status))
1142 {
1143 LinkError = RtlEqualUnicodeString(&TargetDeviceName, &DeviceName, TRUE);
1144 FreePool(DeviceName.Buffer);
1145 }
1146
1147 if (!LinkError)
1148 {
1149 if (IsDriveLetter(&(SymLinks[i])))
1150 {
1151 IsDrvLetter = FALSE;
1152 DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1153 }
1154
1155 FreePool(SymLinks[i].Buffer);
1156 continue;
1157 }
1158 }
1159 }
1160
1161 /* Check if was offline */
1162 if (IsOffline(&(SymLinks[i])))
1163 {
1164 IsOff = TRUE;
1165 }
1166
1167 /* Finally, associate this symlink with the device */
1168 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1169 if (!SymlinkInformation)
1170 {
1171 GlobalDeleteSymbolicLink(&(SymLinks[i]));
1172 FreePool(SymLinks[i].Buffer);
1173 continue;
1174 }
1175
1176 SymlinkInformation->Name = SymLinks[i];
1177 SymlinkInformation->Online = TRUE;
1178
1179 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1180 &(SymlinkInformation->SymbolicLinksListEntry));
1181 }
1182
1183 /* Now, for all the recreated symlinks, notify their recreation */
1184 for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1185 NextEntry != &(DeviceInformation->SymbolicLinksListHead);
1186 NextEntry = NextEntry->Flink)
1187 {
1188 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1189
1190 SendLinkCreated(&(SymlinkInformation->Name));
1191 }
1192
1193 /* If we had saved links, it's time to free them */
1194 if (SavedLinkInformation)
1195 {
1196 MountMgrFreeSavedLink(SavedLinkInformation);
1197 }
1198
1199 /* If our device doesn't have a volume name */
1200 if (!IsVolumeName)
1201 {
1202 /* It's time to create one */
1204 if (NT_SUCCESS(Status))
1205 {
1206 /* Write it to global database */
1210 REG_BINARY,
1211 UniqueId->UniqueId,
1212 UniqueId->UniqueIdLength);
1213
1214 /* And create the symlink */
1215 GlobalCreateSymbolicLink(&VolumeName, &TargetDeviceName);
1216
1217 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1218 if (!SymlinkInformation)
1219 {
1221 }
1222 /* Finally, associate it with the device and notify creation */
1223 else
1224 {
1225 SymlinkInformation->Name = VolumeName;
1226 SymlinkInformation->Online = TRUE;
1227 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1228 &(SymlinkInformation->SymbolicLinksListEntry));
1229
1231 }
1232 }
1233 }
1234
1235 /* If we found a drive letter, then, ignore the suggested one */
1236 if (IsDrvLetter)
1237 {
1238 DeviceInformation->SuggestedDriveLetter = 0;
1239 }
1240 /* Else, it's time to set up one */
1241 else if ((!DeviceExtension->NoAutoMount || DeviceInformation->Removable) &&
1242 DeviceExtension->AutomaticDriveLetter &&
1243 (HasGptDriveLetter || DeviceInformation->SuggestedDriveLetter) &&
1244 !HasNoDriveLetterEntry(UniqueId))
1245 {
1246 /* Create a new drive letter */
1247 Status = CreateNewDriveLetterName(&DriveLetter, &TargetDeviceName,
1248 DeviceInformation->SuggestedDriveLetter,
1249 NULL);
1250 if (!NT_SUCCESS(Status))
1251 {
1252 CreateNoDriveLetterEntry(UniqueId);
1253 }
1254 else
1255 {
1256 /* Save it to global database */
1259 DriveLetter.Buffer,
1260 REG_BINARY,
1261 UniqueId->UniqueId,
1262 UniqueId->UniqueIdLength);
1263
1264 /* Associate it with the device and notify creation */
1265 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1266 if (!SymlinkInformation)
1267 {
1268 FreePool(DriveLetter.Buffer);
1269 }
1270 else
1271 {
1272 SymlinkInformation->Name = DriveLetter;
1273 SymlinkInformation->Online = TRUE;
1274 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1275 &(SymlinkInformation->SymbolicLinksListEntry));
1276
1277 SendLinkCreated(&DriveLetter);
1278 }
1279 }
1280 }
1281
1282 /* If that's a PnP device, register for notifications */
1283 if (!ManuallyRegistered)
1284 {
1285 RegisterForTargetDeviceNotification(DeviceExtension, DeviceInformation);
1286 }
1287
1288 /* Finally, insert the device into our devices list */
1289 InsertTailList(&(DeviceExtension->DeviceListHead), &(DeviceInformation->DeviceListEntry));
1290
1291 /* Copy device unique ID */
1292 NewUniqueId = AllocatePool(UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1293 if (NewUniqueId)
1294 {
1295 NewUniqueId->UniqueIdLength = UniqueId->UniqueIdLength;
1296 RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength);
1297 }
1298
1299 /* Skip online notifications if the device is offline or a FT volume */
1300 if (IsOff || IsFT)
1301 DeviceInformation->SkipNotifications = TRUE;
1302
1303 /* If automount is enabled or the device was already mounted, send now
1304 * the online notification if needed; otherwise, defer its posting */
1305 if (!DeviceExtension->NoAutoMount || IsDrvLetter)
1306 SetOnline = !DeviceInformation->SkipNotifications;
1307 else
1308 SetOnline = FALSE;
1309
1310 /* Finally, release the exclusive lock */
1311 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1312
1313 /* Set the device online now if necessary */
1314 if (SetOnline)
1316
1317 /* If we had symlinks (from storage), free them */
1318 if (SymLinks)
1319 {
1320 FreePool(SymLinks);
1321 }
1322
1323 /* Notify about unique id change */
1324 if (NewUniqueId)
1325 {
1326 IssueUniqueIdChangeNotify(DeviceExtension, SymbolicName, NewUniqueId);
1327 FreePool(NewUniqueId);
1328 }
1329
1330 /* If this drive was set to have a drive letter automatically
1331 * Now it's back, local databases sync will be required
1332 */
1333 if (DeviceExtension->AutomaticDriveLetter)
1334 {
1335 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1336
1337 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
1338
1339 NextEntry = DeviceExtension->DeviceListHead.Flink;
1340 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1341 while (CurrentDevice != DeviceInformation)
1342 {
1343 if (!CurrentDevice->NoDatabase)
1344 {
1345 ReconcileThisDatabaseWithMaster(DeviceExtension, CurrentDevice);
1346 }
1347
1348 NextEntry = NextEntry->Flink;
1349 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1350 }
1351
1352 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1353 }
1354
1355 return STATUS_SUCCESS;
1356}
1357
1358/*
1359 * @implemented
1360 */
1361VOID
1364{
1365 PLIST_ENTRY NextEntry, DeviceEntry;
1366 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
1367 PSYMLINK_INFORMATION SymlinkInformation;
1369 PSAVED_LINK_INFORMATION SavedLinkInformation = NULL;
1370 PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
1371
1372 /* Acquire device exclusively */
1373 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1374
1375 /* Look for the leaving device */
1376 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1377 NextEntry != &(DeviceExtension->DeviceListHead);
1378 NextEntry = NextEntry->Flink)
1379 {
1380 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1381
1382 if (!RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE))
1383 {
1384 break;
1385 }
1386 }
1387
1388 /* If we found it */
1389 if (NextEntry != &(DeviceExtension->DeviceListHead))
1390 {
1391 /* If it's asked to keep links, then, prepare to save them */
1392 if (DeviceInformation->KeepLinks)
1393 {
1394 SavedLinkInformation = AllocatePool(sizeof(SAVED_LINK_INFORMATION));
1395 if (!SavedLinkInformation)
1396 {
1397 DeviceInformation->KeepLinks = FALSE;
1398 }
1399 }
1400
1401 /* If it's possible (and asked), start to save them */
1402 if (DeviceInformation->KeepLinks)
1403 {
1404 InsertTailList(&(DeviceExtension->SavedLinksListHead), &(SavedLinkInformation->SavedLinksListEntry));
1405 InitializeListHead(&(SavedLinkInformation->SymbolicLinksListHead));
1406 SavedLinkInformation->UniqueId = DeviceInformation->UniqueId;
1407 }
1408
1409 /* For all the symlinks */
1410 while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
1411 {
1412 NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
1413 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1414
1415 /* If we have to, save the link */
1416 if (DeviceInformation->KeepLinks)
1417 {
1418 InsertTailList(&(SavedLinkInformation->SymbolicLinksListHead), &(SymlinkInformation->SymbolicLinksListEntry));
1419 }
1420 /* Otherwise, just release it */
1421 else
1422 {
1423 GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
1424 FreePool(SymlinkInformation->Name.Buffer);
1425 FreePool(SymlinkInformation);
1426 }
1427 }
1428
1429 /* Free all the replicated unique IDs */
1430 while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
1431 {
1432 NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
1433 UniqueIdReplicate = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
1434
1435
1436 FreePool(UniqueIdReplicate->UniqueId);
1437 FreePool(UniqueIdReplicate);
1438 }
1439
1440 while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
1441 {
1442 NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
1443 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1444
1445 DeviceInformation->NoDatabase = TRUE;
1446 FreePool(AssociatedDevice->String.Buffer);
1448 }
1449
1450 /* Remove device from the device list */
1451 RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1452
1453 /* If there are still devices, check if some were associated with ours */
1454 if (!IsListEmpty(&(DeviceInformation->DeviceListEntry)))
1455 {
1456 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1457 NextEntry != &(DeviceExtension->DeviceListHead);
1458 NextEntry = NextEntry->Flink)
1459 {
1460 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1461
1462 /* And then, remove them */
1463 DeviceEntry = CurrentDevice->AssociatedDevicesHead.Flink;
1464 while (DeviceEntry != &(CurrentDevice->AssociatedDevicesHead))
1465 {
1466 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1467 DeviceEntry = DeviceEntry->Flink;
1468
1469 if (AssociatedDevice->DeviceInformation != DeviceInformation)
1470 {
1471 continue;
1472 }
1473
1474 RemoveEntryList(&(AssociatedDevice->AssociatedDevicesEntry));
1475 FreePool(AssociatedDevice->String.Buffer);
1477 }
1478 }
1479 }
1480
1481 /* Finally, clean up device name, symbolic name */
1482 FreePool(DeviceInformation->SymbolicName.Buffer);
1483 if (!DeviceInformation->KeepLinks)
1484 {
1485 FreePool(DeviceInformation->UniqueId);
1486 }
1487 FreePool(DeviceInformation->DeviceName.Buffer);
1488
1489 /* Unregister notifications */
1490 if (DeviceInformation->TargetDeviceNotificationEntry)
1491 {
1493 }
1494
1495 /* And leave */
1496 FreePool(DeviceInformation);
1497 }
1498 else
1499 {
1500 /* We didn't find device, perhaps because it was offline */
1501 for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
1502 NextEntry != &(DeviceExtension->OfflineDeviceListHead);
1503 NextEntry = NextEntry->Flink)
1504 {
1505 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1506
1507 /* It was, remove it */
1508 if (RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE) == 0)
1509 {
1510 RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1511 MountMgrFreeDeadDeviceInfo(DeviceInformation);
1512 break;
1513 }
1514 }
1515 }
1516
1517 /* Release driver */
1518 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1519}
1520
1521/*
1522 * @implemented
1523 */
1525NTAPI
1528{
1529 BOOLEAN OldState;
1530 PDEVICE_EXTENSION DeviceExtension;
1532
1533 /* Notification for a device arrived */
1534 /* Disable hard errors */
1537
1538 DeviceExtension = Context;
1540
1541 /* Dispatch according to the event */
1543 {
1544 MountMgrMountedDeviceArrival(DeviceExtension, Notification->SymbolicLinkName, FALSE);
1545 }
1547 {
1548 MountMgrMountedDeviceRemoval(DeviceExtension, Notification->SymbolicLinkName);
1549 }
1550
1551 /* Reset hard errors */
1553
1554 return STATUS_SUCCESS;
1555}
1556
1557/*
1558 * @implemented
1559 */
1561NTAPI
1563 IN PIRP Irp)
1564{
1567
1569
1571
1572 /* Allow driver opening for communication
1573 * as long as it's not taken for a directory
1574 */
1575 if (Stack->MajorFunction == IRP_MJ_CREATE &&
1576 Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
1577 {
1579 }
1580
1581 Irp->IoStatus.Status = Status;
1582 Irp->IoStatus.Information = 0;
1584 return Status;
1585}
1586
1587/*
1588 * @implemented
1589 */
1590VOID
1591NTAPI
1593 IN PIRP Irp)
1594{
1596
1597 RemoveEntryList(&(Irp->Tail.Overlay.ListEntry));
1598
1599 IoReleaseCancelSpinLock(Irp->CancelIrql);
1600
1601 Irp->IoStatus.Information = 0;
1602 Irp->IoStatus.Status = STATUS_CANCELLED;
1604}
1605
1606/*
1607 * @implemented
1608 */
1610NTAPI
1612 IN PIRP Irp)
1613{
1614 PIRP ListIrp;
1615 KIRQL OldIrql;
1616 PLIST_ENTRY NextEntry;
1619 PDEVICE_EXTENSION DeviceExtension;
1620
1621 DeviceExtension = DeviceObject->DeviceExtension;
1623 FileObject = Stack->FileObject;
1624
1626
1627 /* If IRP list if empty, it's OK */
1628 if (IsListEmpty(&(DeviceExtension->IrpListHead)))
1629 {
1631
1632 Irp->IoStatus.Status = STATUS_SUCCESS;
1633 Irp->IoStatus.Information = 0;
1635
1636 return STATUS_SUCCESS;
1637 }
1638
1639 /* Otherwise, cancel all the IRPs */
1640 NextEntry = DeviceExtension->IrpListHead.Flink;
1641 do
1642 {
1643 ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
1645 {
1646 ListIrp->Cancel = TRUE;
1647 ListIrp->CancelIrql = OldIrql;
1648 ListIrp->CancelRoutine = NULL;
1649 MountMgrCancel(DeviceObject, ListIrp);
1650
1652 }
1653
1654 NextEntry = NextEntry->Flink;
1655 }
1656 while (NextEntry != &(DeviceExtension->IrpListHead));
1657
1659
1660 Irp->IoStatus.Status = STATUS_SUCCESS;
1661 Irp->IoStatus.Information = 0;
1663
1664 return STATUS_SUCCESS;
1665}
1666
1667/*
1668 * @implemented
1669 */
1671NTAPI
1673 IN PIRP Irp)
1674{
1675 PDEVICE_EXTENSION DeviceExtension;
1676
1677 DeviceExtension = DeviceObject->DeviceExtension;
1678
1680
1682
1683 /* Wait for workers */
1684 if (InterlockedIncrement(&(DeviceExtension->WorkerReferences)) > 0)
1685 {
1686 KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore),
1688 1,
1689 FALSE);
1691 }
1692 else
1693 {
1694 InterlockedDecrement(&(DeviceExtension->WorkerReferences));
1695 }
1696
1697 Irp->IoStatus.Status = STATUS_SUCCESS;
1698 Irp->IoStatus.Information = 0;
1700
1701 return STATUS_SUCCESS;
1702}
1703
1704/* FUNCTIONS ****************************************************************/
1705
1706CODE_SEG("INIT")
1708NTAPI
1711{
1714 PDEVICE_EXTENSION DeviceExtension;
1715
1717
1719 sizeof(DEVICE_EXTENSION),
1720 &DeviceMount,
1723 FALSE,
1724 &DeviceObject);
1725 if (!NT_SUCCESS(Status))
1726 {
1727 return Status;
1728 }
1729
1730 DriverObject->DriverUnload = MountMgrUnload;
1731
1732 DeviceExtension = DeviceObject->DeviceExtension;
1733 RtlZeroMemory(DeviceExtension, sizeof(DEVICE_EXTENSION));
1734 DeviceExtension->DeviceObject = DeviceObject;
1735 DeviceExtension->DriverObject = DriverObject;
1736
1737 InitializeListHead(&(DeviceExtension->DeviceListHead));
1738 InitializeListHead(&(DeviceExtension->OfflineDeviceListHead));
1739
1740 KeInitializeSemaphore(&(DeviceExtension->DeviceLock), 1, 1);
1741 KeInitializeSemaphore(&(DeviceExtension->RemoteDatabaseLock), 1, 1);
1742
1743 InitializeListHead(&(DeviceExtension->IrpListHead));
1744 DeviceExtension->EpicNumber = 1;
1745
1746 InitializeListHead(&(DeviceExtension->SavedLinksListHead));
1747
1748 InitializeListHead(&(DeviceExtension->WorkerQueueListHead));
1749 KeInitializeSemaphore(&(DeviceExtension->WorkerSemaphore), 0, MAXLONG);
1750 DeviceExtension->WorkerReferences = -1;
1751 KeInitializeSpinLock(&(DeviceExtension->WorkerLock));
1752
1753 InitializeListHead(&(DeviceExtension->UniqueIdWorkerItemListHead));
1754 InitializeListHead(&(DeviceExtension->OnlineNotificationListHead));
1755 DeviceExtension->OnlineNotificationCount = 1;
1756
1757 DeviceExtension->RegistryPath.Length = RegistryPath->Length;
1758 DeviceExtension->RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
1759 DeviceExtension->RegistryPath.Buffer = AllocatePool(DeviceExtension->RegistryPath.MaximumLength);
1760 if (!DeviceExtension->RegistryPath.Buffer)
1761 {
1764 }
1765
1766 RtlCopyUnicodeString(&(DeviceExtension->RegistryPath), RegistryPath);
1767
1768 DeviceExtension->NoAutoMount = MountmgrReadNoAutoMount(&(DeviceExtension->RegistryPath));
1769
1771
1772 /* Register for device arrival & removal. Ask to be notified for already
1773 * present devices
1774 */
1780 DeviceExtension,
1781 &(DeviceExtension->NotificationEntry));
1782
1783 if (!NT_SUCCESS(Status))
1784 {
1786 return Status;
1787 }
1788
1789 DriverObject->MajorFunction[IRP_MJ_CREATE] =
1794
1796
1798 if (!NT_SUCCESS(Status))
1799 {
1801 }
1802
1803 return Status;
1804}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define CODE_SEG(...)
DWORD Id
WCHAR Letter
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
struct NameRec_ * Name
Definition: cdprocs.h:460
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define MAX_PATH
Definition: compat.h:34
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1613
PWSTR OfflinePath
Definition: database.c:32
PWSTR DatabasePath
Definition: database.c:31
VOID DeleteFromLocalDatabase(IN PUNICODE_STRING SymbolicLink, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:351
const GUID GUID_DEVICE_INTERFACE_ARRIVAL
Definition: deviface.c:14
const GUID GUID_DEVICE_INTERFACE_REMOVAL
Definition: deviface.c:15
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
Status
Definition: gdiplustypes.h:25
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 OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
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:451
VOID SendLinkCreated(IN PUNICODE_STRING SymbolicName)
Definition: symlink.c:169
VOID SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
Definition: notify.c:38
NTSTATUS GlobalCreateSymbolicLink(IN PUNICODE_STRING DosName, IN PUNICODE_STRING DeviceName)
Definition: symlink.c:120
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:145
DRIVER_DISPATCH MountMgrDeviceControl
Definition: mntmgr.h:344
UNICODE_STRING DeviceFloppy
Definition: symlink.c:43
UNICODE_STRING DosDevicesMount
Definition: symlink.c:41
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:812
UNICODE_STRING DeviceMount
Definition: symlink.c:40
NTSTATUS CreateNewVolumeName(OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL)
Definition: symlink.c:399
UNICODE_STRING DeviceCdRom
Definition: symlink.c:44
VOID RegisterForTargetDeviceNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: notify.c:250
#define LETTER_POSITION
Definition: mntmgr.h:159
VOID IssueUniqueIdChangeNotify(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: notify.c:637
NTSTATUS QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING SuggestedLinkName, OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
Definition: symlink.c:621
PSAVED_LINK_INFORMATION RemoveSavedLinks(IN PDEVICE_EXTENSION DeviceExtension, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: symlink.c:577
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define FreePool(P)
Definition: mntmgr.h:154
UNICODE_STRING DosDevices
Definition: symlink.c:42
VOID CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:269
BOOLEAN HasNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:354
BOOLEAN RedirectSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation, IN PUNICODE_STRING DosName, IN PUNICODE_STRING NewLink)
Definition: symlink.c:717
#define ASSERT(a)
Definition: mode.c:44
struct _MOUNTDEV_NAME MOUNTDEV_NAME
struct _MOUNTDEV_UNIQUE_ID MOUNTDEV_UNIQUE_ID
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID
Definition: imports.h:255
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
@ PARTITION_STYLE_MBR
Definition: imports.h:201
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
LONG Unloading
Definition: mountmgr.c:37
NTSTATUS NTAPI MountMgrShutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1672
BOOLEAN IsOffline(PUNICODE_STRING SymbolicName)
Definition: mountmgr.c:130
NTSTATUS NTAPI MountMgrMountedDeviceNotification(IN PVOID NotificationStructure, IN PVOID Context)
Definition: mountmgr.c:1526
NTSTATUS QueryDeviceInformation(_In_ PUNICODE_STRING SymbolicName, _Out_opt_ PUNICODE_STRING DeviceName, _Out_opt_ PMOUNTDEV_UNIQUE_ID *UniqueId, _Out_opt_ PBOOLEAN Removable, _Out_opt_ PBOOLEAN GptDriveLetter, _Out_opt_ PBOOLEAN HasGuid, _Inout_opt_ LPGUID StableGuid, _Out_opt_ PBOOLEAN IsFT)
Definition: mountmgr.c:274
VOID NTAPI MountMgrUnload(IN PDRIVER_OBJECT DriverObject)
Definition: mountmgr.c:719
KEVENT UnloadEvent
Definition: mountmgr.c:36
NTSTATUS MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN ManuallyRegistered)
Definition: mountmgr.c:855
GUID MountedDevicesGuid
Definition: mountmgr.c:33
NTSTATUS FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:561
VOID MountMgrFreeMountedDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:636
static const WCHAR Cunc[]
Definition: mountmgr.c:39
PDEVICE_OBJECT gdeviceObject
Definition: mountmgr.c:35
NTSTATUS NTAPI MountMgrCleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1611
#define Cunc_LETTER_POSITION
Definition: mountmgr.c:40
VOID NTAPI MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1592
NTSTATUS CreateNewDriveLetterName(OUT PUNICODE_STRING DriveLetter, IN PUNICODE_STRING DeviceName, IN UCHAR Letter, IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL)
Definition: mountmgr.c:192
BOOLEAN MountmgrReadNoAutoMount(_In_ PUNICODE_STRING RegistryPath)
Retrieves the "NoAutoMount" setting.
Definition: mountmgr.c:824
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:626
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:167
VOID MountMgrMountedDeviceRemoval(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName)
Definition: mountmgr.c:1362
VOID MountMgrFreeSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation)
Definition: mountmgr.c:691
NTSTATUS NTAPI MountMgrCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1562
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:81
#define _Out_opt_
Definition: ms_sal.h:346
#define _Inout_opt_
Definition: ms_sal.h:379
#define _In_
Definition: ms_sal.h:308
#define _In_reads_bytes_opt_(size)
Definition: ms_sal.h:322
#define _In_opt_
Definition: ms_sal.h:309
#define _Out_writes_bytes_opt_(size)
Definition: ms_sal.h:351
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4677
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI NTSTATUS NTAPI RtlCreateRegistryKey(_In_ ULONG RelativeTo, _In_ PWSTR Path)
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4220
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define SYMBOLIC_LINK_QUERY
Definition: nt_native.h:1265
#define REG_BINARY
Definition: nt_native.h:1496
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h:315
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES
Definition: ntddvol.h:133
@ NotificationEvent
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
NTSTATUS NTAPI IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1694
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
VOID NTAPI IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1725
#define IoCompleteRequest
Definition: irp.c:1240
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
Definition: irp.c:1101
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
NTSTATUS NTAPI IoSetSystemPartition(IN PUNICODE_STRING VolumeNameString)
Definition: volume.c:1226
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
VOID NTAPI PsSetThreadHardErrorsAreDisabled(IN PETHREAD Thread, IN BOOLEAN HardErrorsAreDisabled)
Definition: thread.c:898
BOOLEAN NTAPI PsGetThreadHardErrorsAreDisabled(IN PETHREAD Thread)
Definition: thread.c:695
#define STATUS_PENDING
Definition: ntstatus.h:82
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS NTAPI IoRegisterPlugPlayNotification(_In_ IO_NOTIFICATION_EVENT_CATEGORY EventCategory, _In_ ULONG EventCategoryFlags, _In_opt_ PVOID EventCategoryData, _In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, _Inout_opt_ PVOID Context, _Out_ PVOID *NotificationEntry)
Definition: pnpnotify.c:345
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(_In_ PVOID NotificationEntry)
Definition: pnpnotify.c:479
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define FILE_DEVICE_NETWORK
Definition: winioctl.h:63
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define REG_DWORD
Definition: sdbapi.c:596
@ Removable
Definition: arc.h:81
VOID NTAPI KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit)
Definition: semphobj.c:22
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: mntmgr.h:96
BOOLEAN Removable
Definition: mntmgr.h:54
PVOID TargetDeviceNotificationEntry
Definition: mntmgr.h:61
PDEVICE_EXTENSION DeviceExtension
Definition: mntmgr.h:62
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
BOOLEAN ManuallyRegistered
Definition: mntmgr.h:53
BOOLEAN KeepLinks
Definition: mntmgr.h:51
BOOLEAN NoDatabase
Definition: mntmgr.h:57
UCHAR SuggestedDriveLetter
Definition: mntmgr.h:52
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:49
BOOLEAN SkipNotifications
Definition: mntmgr.h:58
UNICODE_STRING DeviceName
Definition: mntmgr.h:50
LIST_ENTRY ReplicatedUniqueIdsListHead
Definition: mntmgr.h:46
LIST_ENTRY AssociatedDevicesHead
Definition: mntmgr.h:47
LIST_ENTRY SymbolicLinksListHead
Definition: mntmgr.h:45
LIST_ENTRY DeviceListEntry
Definition: mntmgr.h:44
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT UniqueIdLength
Definition: imports.h:138
UCHAR UniqueId[1]
Definition: imports.h:139
USHORT MaximumLength
Definition: env_spec_w32.h:370
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:82
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define MAXLONG
Definition: umtypes.h:116
_In_ PWDFDEVICE_INIT _In_ PFN_WDF_DEVICE_SHUTDOWN_NOTIFICATION Notification
Definition: wdfcontrol.h:115
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_In_ WDFDEVICE AssociatedDevice
Definition: wdfinterrupt.h:173
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:325
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:320
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
Definition: wdfio.h:322
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
_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:409
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
_In_ PVOID NotificationStructure
Definition: iofuncs.h:1206
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ EventCategoryDeviceInterfaceChange
Definition: iotypes.h:1226
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MJ_SHUTDOWN
#define IRP_MJ_CLEANUP
#define PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES
Definition: iotypes.h:1239
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:415
#define ObDereferenceObject
Definition: obfuncs.h:203
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292