ReactOS 0.4.15-dev-7958-gcd0bb1a
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
42/*
43 * @implemented
44 */
47{
49 ULONG IsOffline, Default;
51
52 /* Prepare to look in the registry to see if
53 * given volume is offline
54 */
60 QueryTable[0].DefaultLength = sizeof(ULONG);
61 QueryTable[0].DefaultData = &Default;
62
63 Default = 0;
64
65 /* Query status */
69 NULL,
70 NULL);
71 if (!NT_SUCCESS(Status))
72 {
73 IsOffline = 0;
74 }
75
76 return (IsOffline != 0);
77}
78
79/*
80 * @implemented
81 */
84{
85 PLIST_ENTRY NextEntry;
86 PSYMLINK_INFORMATION SymlinkInfo;
87
88 /* Browse all the symlinks to check if there is at least a drive letter */
89 for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
90 NextEntry != &DeviceInformation->SymbolicLinksListHead;
91 NextEntry = NextEntry->Flink)
92 {
93 SymlinkInfo = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
94
95 if (IsDriveLetter(&SymlinkInfo->Name) && SymlinkInfo->Online)
96 {
97 return TRUE;
98 }
99 }
100
101 return FALSE;
102}
103
104/*
105 * @implemented
106 */
112{
114
115 /* Allocate a big enough buffer to contain the symbolic link */
116 DriveLetter->MaximumLength = DosDevices.Length + 3 * sizeof(WCHAR);
117 DriveLetter->Buffer = AllocatePool(DriveLetter->MaximumLength);
118 if (!DriveLetter->Buffer)
119 {
121 }
122
123 /* Copy prefix */
124 RtlCopyUnicodeString(DriveLetter, &DosDevices);
125
126 /* Update string to reflect real contents */
127 DriveLetter->Length = DosDevices.Length + 2 * sizeof(WCHAR);
128 DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR) + 2] = UNICODE_NULL;
129 DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR) + 1] = L':';
130
131 /* If caller wants a no drive entry */
132 if (Letter == (UCHAR)-1)
133 {
134 /* Then, create a no letter entry */
135 CreateNoDriveLetterEntry(UniqueId);
136 FreePool(DriveLetter->Buffer);
137 return STATUS_UNSUCCESSFUL;
138 }
139 else if (Letter)
140 {
141 /* Use the letter given by the caller */
142 DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR)] = (WCHAR)Letter;
144 if (NT_SUCCESS(Status))
145 {
146 return Status;
147 }
148 }
149
150 /* If caller didn't provide a letter, let's find one for him */
151
153 {
154 /* If the device is a floppy, start with letter A */
155 Letter = 'A';
156 }
158 {
159 /* If the device is a CD-ROM, start with letter D */
160 Letter = 'D';
161 }
162 else
163 {
164 /* Finally, if it's a disk, use C */
165 Letter = 'C';
166 }
167
168 /* Try to affect a letter (up to Z, ofc) until it's possible */
169 for (; Letter <= 'Z'; Letter++)
170 {
171 DriveLetter->Buffer[DosDevices.Length / sizeof(WCHAR)] = (WCHAR)Letter;
173 if (NT_SUCCESS(Status))
174 {
175 DPRINT("Assigned drive %c: to %wZ\n", Letter, DeviceName);
176 return Status;
177 }
178 }
179
180 /* We failed to allocate a letter */
181 FreePool(DriveLetter->Buffer);
182 DPRINT("Failed to create a drive letter for %wZ\n", DeviceName);
183 return Status;
184}
185
186/*
187 * @implemented
188 */
194 OUT PBOOLEAN GptDriveLetter OPTIONAL,
195 OUT PBOOLEAN HasGuid OPTIONAL,
196 IN OUT LPGUID StableGuid OPTIONAL,
197 OUT PBOOLEAN Valid OPTIONAL)
198{
199 PIRP Irp;
200 USHORT Size;
202 BOOLEAN IsRemovable;
207 NTSTATUS Status, IntStatus;
211 STORAGE_DEVICE_NUMBER StorageDeviceNumber;
213
214 /* Get device associated with the symbolic name */
217 &FileObject,
218 &DeviceObject);
219 if (!NT_SUCCESS(Status))
220 {
221 return Status;
222 }
223
224 /* The associate FO can't have a file name */
225 if (FileObject->FileName.Length)
226 {
229 }
230
231 /* Check if it's removable & return to the user (if asked to) */
232 IsRemovable = (FileObject->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
233 if (Removable)
234 {
235 *Removable = IsRemovable;
236 }
237
238 /* Get the attached device */
240
241 /* If we've been asked for a GPT drive letter */
242 if (GptDriveLetter)
243 {
244 /* Consider it has one */
245 *GptDriveLetter = TRUE;
246
247 if (!IsRemovable)
248 {
249 /* Query the GPT attributes */
253 NULL,
254 0,
255 &GptAttributes,
256 sizeof(GptAttributes),
257 FALSE,
258 &Event,
260 if (!Irp)
261 {
265 }
266
268 if (Status == STATUS_PENDING)
269 {
272 }
273
274 /* In case of failure, don't fail, that's no vital */
275 if (!NT_SUCCESS(Status))
276 {
278 }
279 /* Check if it has a drive letter */
280 else if (GptAttributes.GptAttributes & GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER)
281 {
282 *GptDriveLetter = FALSE;
283 }
284 }
285 }
286
287 /* If caller wants to know if there's valid contents */
288 if (Valid)
289 {
290 /* Suppose it's not OK */
291 *Valid = FALSE;
292
293 if (!IsRemovable)
294 {
295 /* Query partitions information */
299 NULL,
300 0,
302 sizeof(PartitionInfo),
303 FALSE,
304 &Event,
306 if (!Irp)
307 {
311 }
312
314 if (Status == STATUS_PENDING)
315 {
318 }
319
320 /* Once again here, failure isn't major */
321 if (!NT_SUCCESS(Status))
322 {
324 }
325 /* Verify we know something in */
326 else if (PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR &&
327 IsRecognizedPartition(PartitionInfo.Mbr.PartitionType))
328 {
329 *Valid = TRUE;
330 }
331
332 /* It looks correct, ensure it is & query device number */
333 if (*Valid)
334 {
338 NULL,
339 0,
340 &StorageDeviceNumber,
341 sizeof(StorageDeviceNumber),
342 FALSE,
343 &Event,
345 if (!Irp)
346 {
350 }
351
353 if (Status == STATUS_PENDING)
354 {
357 }
358
359 if (!NT_SUCCESS(Status))
360 {
362 }
363 else
364 {
365 *Valid = FALSE;
366 }
367 }
368 }
369 }
370
371 /* If caller needs device name */
372 if (DeviceName)
373 {
374 /* Allocate a buffer just to request length */
376 if (!Name)
377 {
381 }
382
383 /* Query device name */
387 NULL,
388 0,
389 Name,
390 sizeof(MOUNTDEV_NAME),
391 FALSE,
392 &Event,
394 if (!Irp)
395 {
396 FreePool(Name);
400 }
401
403 Stack->FileObject = FileObject;
404
406 if (Status == STATUS_PENDING)
407 {
410 }
411
412 /* Now, we've got the correct length */
414 {
415 Size = Name->NameLength + sizeof(MOUNTDEV_NAME);
416
417 FreePool(Name);
418
419 /* Allocate proper size */
421 if (!Name)
422 {
426 }
427
428 /* And query name (for real that time) */
432 NULL,
433 0,
434 Name,
435 Size,
436 FALSE,
437 &Event,
439 if (!Irp)
440 {
441 FreePool(Name);
445 }
446
448 Stack->FileObject = FileObject;
449
451 if (Status == STATUS_PENDING)
452 {
455 }
456 }
457
458 if (NT_SUCCESS(Status))
459 {
460 /* Copy back found name to the caller */
461 DeviceName->Length = Name->NameLength;
462 DeviceName->MaximumLength = Name->NameLength + sizeof(WCHAR);
463 DeviceName->Buffer = AllocatePool(DeviceName->MaximumLength);
464 if (!DeviceName->Buffer)
465 {
467 }
468 else
469 {
470 RtlCopyMemory(DeviceName->Buffer, Name->Name, Name->NameLength);
471 DeviceName->Buffer[Name->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
472 }
473 }
474
475 FreePool(Name);
476 }
477
478 if (!NT_SUCCESS(Status))
479 {
482 return Status;
483 }
484
485 /* If caller wants device unique ID */
486 if (UniqueId)
487 {
488 /* Prepare buffer to probe length */
490 if (!Id)
491 {
495 }
496
497 /* Query unique ID length */
501 NULL,
502 0,
503 Id,
504 sizeof(MOUNTDEV_UNIQUE_ID),
505 FALSE,
506 &Event,
508 if (!Irp)
509 {
510 FreePool(Id);
514 }
515
517 Stack->FileObject = FileObject;
518
520 if (Status == STATUS_PENDING)
521 {
524 }
525
526 /* Retry with appropriate length */
528 {
529 Size = Id->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID);
530
531 FreePool(Id);
532
533 /* Allocate the correct buffer */
535 if (!Id)
536 {
540 }
541
542 /* Query unique ID */
546 NULL,
547 0,
548 Id,
549 Size,
550 FALSE,
551 &Event,
553 if (!Irp)
554 {
555 FreePool(Id);
559 }
560
562 Stack->FileObject = FileObject;
563
565 if (Status == STATUS_PENDING)
566 {
569 }
570 }
571
572 /* Hands back unique ID */
573 if (NT_SUCCESS(Status))
574 {
575 *UniqueId = Id;
576 }
577 else
578 {
579 /* In case of failure, also free the rest */
580 FreePool(Id);
581 if (DeviceName->Length)
582 {
583 FreePool(DeviceName->Buffer);
584 }
585
588
589 return Status;
590 }
591 }
592
593 /* If user wants to know about GUID */
594 if (HasGuid)
595 {
596 /* Query device stable GUID */
600 NULL,
601 0,
602 StableGuid,
603 sizeof(GUID),
604 FALSE,
605 &Event,
607 if (!Irp)
608 {
612 }
613
615 Stack->FileObject = FileObject;
616
617 IntStatus = IoCallDriver(DeviceObject, Irp);
618 if (IntStatus == STATUS_PENDING)
619 {
621 IntStatus = IoStatusBlock.Status;
622 }
623
624 *HasGuid = NT_SUCCESS(IntStatus);
625 }
626
629 return Status;
630}
631
632/*
633 * @implemented
634 */
638 IN BOOLEAN DeviceNameGiven,
639 OUT PDEVICE_INFORMATION * DeviceInformation)
640{
642 PLIST_ENTRY NextEntry;
645
646 /* If a device name was given, use it */
647 if (DeviceNameGiven)
648 {
651 }
652 else
653 {
654 /* Otherwise, query it */
656 &DeviceName,
657 NULL, NULL,
658 NULL, NULL,
659 NULL, NULL);
660 if (!NT_SUCCESS(Status))
661 {
662 return Status;
663 }
664 }
665
666 /* Look for device information matching devive */
667 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
668 NextEntry != &(DeviceExtension->DeviceListHead);
669 NextEntry = NextEntry->Flink)
670 {
671 DeviceInfo = CONTAINING_RECORD(NextEntry,
673 DeviceListEntry);
674
675 if (RtlEqualUnicodeString(&DeviceName, &(DeviceInfo->DeviceName), TRUE))
676 {
677 break;
678 }
679 }
680
681 /* Release our buffer if required */
682 if (!DeviceNameGiven)
683 {
684 FreePool(DeviceName.Buffer);
685 }
686
687 /* Return found information */
688 if (NextEntry == &(DeviceExtension->DeviceListHead))
689 {
691 }
692
693 *DeviceInformation = DeviceInfo;
694 return STATUS_SUCCESS;
695}
696
697/*
698 * @implemented
699 */
700VOID
702{
703 FreePool(DeviceInformation->SymbolicName.Buffer);
704 FreePool(DeviceInformation);
705}
706
707/*
708 * @implemented
709 */
710VOID
712{
713 PLIST_ENTRY NextEntry;
714 PSYMLINK_INFORMATION SymLink;
715 PUNIQUE_ID_REPLICATE UniqueId;
717
718 /* Purge symbolic links list */
719 while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
720 {
721 NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
722 SymLink = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
723
724 GlobalDeleteSymbolicLink(&(SymLink->Name));
725 FreePool(SymLink->Name.Buffer);
726 }
727
728 /* Purge replicated unique IDs list */
729 while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
730 {
731 NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
732 UniqueId = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
733
734 FreePool(UniqueId->UniqueId);
735 FreePool(UniqueId);
736 }
737
738 while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
739 {
740 NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
741 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
742
743 FreePool(AssociatedDevice->String.Buffer);
745 }
746
747 /* Free the rest of the buffers */
748 FreePool(DeviceInformation->SymbolicName.Buffer);
749 if (DeviceInformation->KeepLinks)
750 {
751 FreePool(DeviceInformation->UniqueId);
752 }
753 FreePool(DeviceInformation->DeviceName.Buffer);
754
755 /* Finally, stop waiting for notifications for this device */
756 if (DeviceInformation->TargetDeviceNotificationEntry)
757 {
758 IoUnregisterPlugPlayNotification(DeviceInformation->TargetDeviceNotificationEntry);
759 }
760}
761
762/*
763 * @implemented
764 */
765VOID
767{
768 PLIST_ENTRY NextEntry;
769 PSYMLINK_INFORMATION SymlinkInformation;
770
771 /* For all the saved links */
772 while (!IsListEmpty(&(SavedLinkInformation->SymbolicLinksListHead)))
773 {
774 NextEntry = RemoveHeadList(&(SavedLinkInformation->SymbolicLinksListHead));
775 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
776
777 /* Remove from system & free */
778 GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
779 FreePool(SymlinkInformation->Name.Buffer);
780 FreePool(SymlinkInformation);
781 }
782
783 /* And free unique ID & entry */
784 FreePool(SavedLinkInformation->UniqueId);
785 FreePool(SavedLinkInformation);
786}
787
788
789/*
790 * @implemented
791 */
792VOID
793NTAPI
795{
796 PLIST_ENTRY NextEntry;
798 PDEVICE_EXTENSION DeviceExtension;
799 PDEVICE_INFORMATION DeviceInformation;
800 PSAVED_LINK_INFORMATION SavedLinkInformation;
801
803
804 /* Don't get notification any longer */
806
807 /* Free registry buffer */
808 DeviceExtension = gdeviceObject->DeviceExtension;
809 if (DeviceExtension->RegistryPath.Buffer)
810 {
811 FreePool(DeviceExtension->RegistryPath.Buffer);
812 DeviceExtension->RegistryPath.Buffer = NULL;
813 }
814
816
818
819 /* Wait for workers to finish */
820 if (InterlockedIncrement(&DeviceExtension->WorkerReferences) > 0)
821 {
822 KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore),
824
826 }
827 else
828 {
829 InterlockedDecrement(&(DeviceExtension->WorkerReferences));
830 }
831
832 /* Don't get any notification any longer² */
833 IoUnregisterPlugPlayNotification(DeviceExtension->NotificationEntry);
834
835 /* Acquire the driver exclusively */
836 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode,
837 FALSE, NULL);
838
839 /* Clear offline devices list */
840 while (!IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
841 {
842 NextEntry = RemoveHeadList(&(DeviceExtension->OfflineDeviceListHead));
843 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
844 MountMgrFreeDeadDeviceInfo(DeviceInformation);
845 }
846
847 /* Clear saved links list */
848 while (!IsListEmpty(&(DeviceExtension->SavedLinksListHead)))
849 {
850 NextEntry = RemoveHeadList(&(DeviceExtension->SavedLinksListHead));
851 SavedLinkInformation = CONTAINING_RECORD(NextEntry, SAVED_LINK_INFORMATION, SavedLinksListEntry);
852 MountMgrFreeSavedLink(SavedLinkInformation);
853 }
854
855 /* Clear workers list */
856 while (!IsListEmpty(&(DeviceExtension->UniqueIdWorkerItemListHead)))
857 {
858 NextEntry = RemoveHeadList(&(DeviceExtension->UniqueIdWorkerItemListHead));
859 WorkItem = CONTAINING_RECORD(NextEntry, UNIQUE_ID_WORK_ITEM, UniqueIdWorkerItemListEntry);
860
862 WorkItem->Event = &UnloadEvent;
863
864 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
865 1, FALSE);
866
867 IoCancelIrp(WorkItem->Irp);
869
870 IoFreeIrp(WorkItem->Irp);
871 FreePool(WorkItem->DeviceName.Buffer);
872 FreePool(WorkItem->IrpBuffer);
874
875 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode,
876 FALSE, NULL);
877 }
878
879 /* If we have drive letter data, release */
880 if (DeviceExtension->DriveLetterData)
881 {
882 FreePool(DeviceExtension->DriveLetterData);
883 DeviceExtension->DriveLetterData = NULL;
884 }
885
886 /* Release driver & quit */
887 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
888
891}
892
893/*
894 * @implemented
895 */
896CODE_SEG("INIT")
899{
901 ULONG Result, Default = 0;
903
905
906 /* Simply read data from register */
908 QueryTable[0].Name = L"NoAutoMount";
911 QueryTable[0].DefaultData = &Default;
912 QueryTable[0].DefaultLength = sizeof(ULONG);
913
915 RegistryPath->Buffer,
917 NULL,
918 NULL);
919 if (!NT_SUCCESS(Status))
920 {
921 return (Default != 0);
922 }
923
924 return (Result != 0);
925}
926
927/*
928 * @implemented
929 */
933 IN BOOLEAN ManuallyRegistered)
934{
936 GUID StableGuid;
937 HANDLE LinkHandle;
938 ULONG SymLinkCount, i;
939 PLIST_ENTRY NextEntry;
940 PUNICODE_STRING SymLinks;
941 NTSTATUS Status, IntStatus;
943 PSYMLINK_INFORMATION SymlinkInformation;
944 PMOUNTDEV_UNIQUE_ID UniqueId, NewUniqueId;
945 PSAVED_LINK_INFORMATION SavedLinkInformation;
946 PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
947 WCHAR CSymLinkBuffer[RTL_NUMBER_OF(Cunc)], LinkTargetBuffer[MAX_PATH];
948 UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink;
949 BOOLEAN HasGuid, HasGptDriveLetter, Valid, UseOnlyIfThereAreNoOtherLinks, IsDrvLetter, IsOff, IsVolumeName, LinkError;
950
951 /* New device = new structure to represent it */
952 DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION));
953 if (!DeviceInformation)
954 {
956 }
957
958 /* Initialise device structure */
959 RtlZeroMemory(DeviceInformation, sizeof(DEVICE_INFORMATION));
960 InitializeListHead(&(DeviceInformation->SymbolicLinksListHead));
961 InitializeListHead(&(DeviceInformation->ReplicatedUniqueIdsListHead));
962 InitializeListHead(&(DeviceInformation->AssociatedDevicesHead));
963 DeviceInformation->SymbolicName.Length = SymbolicName->Length;
964 DeviceInformation->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(UNICODE_NULL);
965 DeviceInformation->SymbolicName.Buffer = AllocatePool(DeviceInformation->SymbolicName.MaximumLength);
966 if (!DeviceInformation->SymbolicName.Buffer)
967 {
968 FreePool(DeviceInformation);
970 }
971
972 /* Copy symbolic name */
974 DeviceInformation->SymbolicName.Buffer[DeviceInformation->SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
975 DeviceInformation->ManuallyRegistered = ManuallyRegistered;
976 DeviceInformation->DeviceExtension = DeviceExtension;
977
978 /* Query as much data as possible about device */
980 &TargetDeviceName,
981 &UniqueId,
982 &(DeviceInformation->Removable),
983 &HasGptDriveLetter,
984 &HasGuid,
985 &StableGuid,
986 &Valid);
987 if (!NT_SUCCESS(Status))
988 {
989 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
990
991 for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
992 NextEntry != &(DeviceExtension->OfflineDeviceListHead);
993 NextEntry = NextEntry->Flink)
994 {
995 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
996
997 if (RtlEqualUnicodeString(&(DeviceInformation->SymbolicName), &(CurrentDevice->SymbolicName), TRUE))
998 {
999 break;
1000 }
1001 }
1002
1003 if (NextEntry != &(DeviceExtension->OfflineDeviceListHead))
1004 {
1005 MountMgrFreeDeadDeviceInfo(DeviceInformation);
1006 }
1007 else
1008 {
1009 InsertTailList(&(DeviceExtension->OfflineDeviceListHead), &(DeviceInformation->DeviceListEntry));
1010 }
1011
1012 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1013
1014 return Status;
1015 }
1016
1017 /* Save gathered data */
1018 DeviceInformation->UniqueId = UniqueId;
1019 DeviceInformation->DeviceName = TargetDeviceName;
1020 DeviceInformation->KeepLinks = FALSE;
1021
1022 /* If we found system partition, mark it */
1023 if (DeviceExtension->DriveLetterData && UniqueId->UniqueIdLength == DeviceExtension->DriveLetterData->UniqueIdLength)
1024 {
1025 if (RtlCompareMemory(UniqueId->UniqueId, DeviceExtension->DriveLetterData->UniqueId, UniqueId->UniqueIdLength)
1026 == UniqueId->UniqueIdLength)
1027 {
1028 IoSetSystemPartition(&TargetDeviceName);
1029 }
1030 }
1031
1032 /* Check suggested link name */
1033 Status = QuerySuggestedLinkName(&(DeviceInformation->SymbolicName),
1034 &SuggestedLinkName,
1035 &UseOnlyIfThereAreNoOtherLinks);
1036 if (!NT_SUCCESS(Status))
1037 {
1038 SuggestedLinkName.Buffer = NULL;
1039 }
1040
1041 /* If it's OK, set it and save its letter (if any) */
1042 if (SuggestedLinkName.Buffer && IsDriveLetter(&SuggestedLinkName))
1043 {
1044 DeviceInformation->SuggestedDriveLetter = (UCHAR)SuggestedLinkName.Buffer[LETTER_POSITION];
1045 }
1046
1047 /* Acquire driver exclusively */
1048 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1049
1050 /* Check if we already have device in to prevent double registration */
1051 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1052 NextEntry != &(DeviceExtension->DeviceListHead);
1053 NextEntry = NextEntry->Flink)
1054 {
1055 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1056
1057 if (RtlEqualUnicodeString(&(CurrentDevice->DeviceName), &TargetDeviceName, TRUE))
1058 {
1059 break;
1060 }
1061 }
1062
1063 /* If we found it, clear ours, and return success, all correct */
1064 if (NextEntry != &(DeviceExtension->DeviceListHead))
1065 {
1066 if (SuggestedLinkName.Buffer)
1067 {
1068 FreePool(SuggestedLinkName.Buffer);
1069 }
1070
1071 FreePool(UniqueId);
1072 FreePool(TargetDeviceName.Buffer);
1073 FreePool(DeviceInformation->DeviceName.Buffer);
1074 FreePool(DeviceInformation);
1075
1076 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1077
1078 return STATUS_SUCCESS;
1079 }
1080
1081 /* Check if there are symlinks associated with our device in registry */
1082 Status = QuerySymbolicLinkNamesFromStorage(DeviceExtension,
1083 DeviceInformation,
1084 (SuggestedLinkName.Buffer) ? &SuggestedLinkName : NULL,
1085 UseOnlyIfThereAreNoOtherLinks,
1086 &SymLinks,
1087 &SymLinkCount,
1088 HasGuid,
1089 &StableGuid);
1090
1091 /* If our device is a CD-ROM */
1092 if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
1093 {
1094 LinkTarget.Length = 0;
1095 LinkTarget.MaximumLength = sizeof(LinkTargetBuffer);
1096 LinkTarget.Buffer = LinkTargetBuffer;
1097
1098 RtlCopyMemory(CSymLinkBuffer, Cunc, sizeof(Cunc));
1099 RtlInitUnicodeString(&CSymLink, CSymLinkBuffer);
1100
1101 /* Start checking all letters that could have been associated */
1102 for (Letter = L'D'; Letter <= L'Z'; Letter++)
1103 {
1105
1107 &CSymLink,
1109 NULL,
1110 NULL);
1111
1112 /* Try to open the associated symlink */
1114 if (!NT_SUCCESS(Status))
1115 {
1116 continue;
1117 }
1118
1119 /* And query its target */
1120 Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);
1121 ZwClose(LinkHandle);
1122
1123 if (!NT_SUCCESS(Status))
1124 {
1125 continue;
1126 }
1127
1128 IntStatus = STATUS_UNSUCCESSFUL;
1129 if (!RtlEqualUnicodeString(&LinkTarget, &DeviceInformation->DeviceName, FALSE))
1130 {
1131 continue;
1132 }
1133
1134 /* This link is matching our device, whereas it's not supposed to have any
1135 * symlink associated.
1136 * Delete it
1137 */
1138 if (!SymLinkCount)
1139 {
1140 IoDeleteSymbolicLink(&CSymLink);
1141 continue;
1142 }
1143
1144 /* Now, for all the symlinks, check for ours */
1145 for (i = 0; i < SymLinkCount; i++)
1146 {
1147 if (IsDriveLetter(&(SymLinks[i])))
1148 {
1149 /* If it exists, that's correct */
1150 if (SymLinks[i].Buffer[LETTER_POSITION] == Letter)
1151 {
1152 IntStatus = STATUS_SUCCESS;
1153 }
1154 }
1155 }
1156
1157 /* Useless link, delete it */
1158 if (IntStatus == STATUS_UNSUCCESSFUL)
1159 {
1160 IoDeleteSymbolicLink(&CSymLink);
1161 }
1162 }
1163 }
1164
1165 /* Suggested name is no longer required */
1166 if (SuggestedLinkName.Buffer)
1167 {
1168 FreePool(SuggestedLinkName.Buffer);
1169 }
1170
1171 /* If if failed, ensure we don't take symlinks into account */
1172 if (!NT_SUCCESS(Status))
1173 {
1174 SymLinks = NULL;
1175 SymLinkCount = 0;
1176 }
1177
1178 /* Now we queried them, remove the symlinks */
1179 SavedLinkInformation = RemoveSavedLinks(DeviceExtension, UniqueId);
1180
1181 IsDrvLetter = FALSE;
1182 IsOff = FALSE;
1183 IsVolumeName = FALSE;
1184 /* For all the symlinks */
1185 for (i = 0; i < SymLinkCount; i++)
1186 {
1187 /* Check if our device is a volume */
1188 if (MOUNTMGR_IS_VOLUME_NAME(&(SymLinks[i])))
1189 {
1190 IsVolumeName = TRUE;
1191 }
1192 /* If it has a drive letter */
1193 else if (IsDriveLetter(&(SymLinks[i])))
1194 {
1195 if (IsDrvLetter)
1196 {
1197 DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1198 continue;
1199 }
1200 else
1201 {
1202 IsDrvLetter = TRUE;
1203 }
1204 }
1205
1206 /* And recreate the symlink to our device */
1207 Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName);
1208 if (!NT_SUCCESS(Status))
1209 {
1210 LinkError = TRUE;
1211
1212 if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) ||
1213 !SavedLinkInformation)
1214 {
1216 if (NT_SUCCESS(Status))
1217 {
1218 LinkError = RtlEqualUnicodeString(&TargetDeviceName, &DeviceName, TRUE);
1219 FreePool(DeviceName.Buffer);
1220 }
1221
1222 if (!LinkError)
1223 {
1224 if (IsDriveLetter(&(SymLinks[i])))
1225 {
1226 IsDrvLetter = FALSE;
1227 DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1228 }
1229
1230 FreePool(SymLinks[i].Buffer);
1231 continue;
1232 }
1233 }
1234 }
1235
1236 /* Check if was offline */
1237 if (IsOffline(&(SymLinks[i])))
1238 {
1239 IsOff = TRUE;
1240 }
1241
1242 /* Finally, associate this symlink with the device */
1243 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1244 if (!SymlinkInformation)
1245 {
1246 GlobalDeleteSymbolicLink(&(SymLinks[i]));
1247 FreePool(SymLinks[i].Buffer);
1248 continue;
1249 }
1250
1251 SymlinkInformation->Name = SymLinks[i];
1252 SymlinkInformation->Online = TRUE;
1253
1254 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1255 &(SymlinkInformation->SymbolicLinksListEntry));
1256 }
1257
1258 /* Now, for all the recreated symlinks, notify their recreation */
1259 for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1260 NextEntry != &(DeviceInformation->SymbolicLinksListHead);
1261 NextEntry = NextEntry->Flink)
1262 {
1263 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1264
1265 SendLinkCreated(&(SymlinkInformation->Name));
1266 }
1267
1268 /* If we had saved links, it's time to free them */
1269 if (SavedLinkInformation)
1270 {
1271 MountMgrFreeSavedLink(SavedLinkInformation);
1272 }
1273
1274 /* If our device doesn't have a volume name */
1275 if (!IsVolumeName)
1276 {
1277 /* It's time to create one */
1279 if (NT_SUCCESS(Status))
1280 {
1281 /* Write it to global database */
1285 REG_BINARY,
1286 UniqueId->UniqueId,
1287 UniqueId->UniqueIdLength);
1288
1289 /* And create the symlink */
1290 GlobalCreateSymbolicLink(&VolumeName, &TargetDeviceName);
1291
1292 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1293 if (!SymlinkInformation)
1294 {
1296 }
1297 /* Finally, associate it with the device and notify creation */
1298 else
1299 {
1300 SymlinkInformation->Name = VolumeName;
1301 SymlinkInformation->Online = TRUE;
1302 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1303 &(SymlinkInformation->SymbolicLinksListEntry));
1304
1306 }
1307 }
1308 }
1309
1310 /* If we found a drive letter, then, ignore the suggested one */
1311 if (IsDrvLetter)
1312 {
1313 DeviceInformation->SuggestedDriveLetter = 0;
1314 }
1315 /* Else, it's time to set up one */
1316 else if ((DeviceExtension->NoAutoMount || DeviceInformation->Removable) &&
1317 DeviceExtension->AutomaticDriveLetter &&
1318 (HasGptDriveLetter || DeviceInformation->SuggestedDriveLetter) &&
1319 !HasNoDriveLetterEntry(UniqueId))
1320 {
1321 /* Create a new drive letter */
1322 Status = CreateNewDriveLetterName(&DriveLetter, &TargetDeviceName,
1323 DeviceInformation->SuggestedDriveLetter,
1324 NULL);
1325 if (!NT_SUCCESS(Status))
1326 {
1327 CreateNoDriveLetterEntry(UniqueId);
1328 }
1329 else
1330 {
1331 /* Save it to global database */
1334 DriveLetter.Buffer,
1335 REG_BINARY,
1336 UniqueId->UniqueId,
1337 UniqueId->UniqueIdLength);
1338
1339 /* Associate it with the device and notify creation */
1340 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1341 if (!SymlinkInformation)
1342 {
1343 FreePool(DriveLetter.Buffer);
1344 }
1345 else
1346 {
1347 SymlinkInformation->Name = DriveLetter;
1348 SymlinkInformation->Online = TRUE;
1349 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1350 &(SymlinkInformation->SymbolicLinksListEntry));
1351
1352 SendLinkCreated(&DriveLetter);
1353 }
1354 }
1355 }
1356
1357 /* If that's a PnP device, register for notifications */
1358 if (!ManuallyRegistered)
1359 {
1360 RegisterForTargetDeviceNotification(DeviceExtension, DeviceInformation);
1361 }
1362
1363 /* Finally, insert the device into our devices list */
1364 InsertTailList(&(DeviceExtension->DeviceListHead), &(DeviceInformation->DeviceListEntry));
1365
1366 /* Copy device unique ID */
1367 NewUniqueId = AllocatePool(UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1368 if (NewUniqueId)
1369 {
1370 NewUniqueId->UniqueIdLength = UniqueId->UniqueIdLength;
1371 RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength);
1372 }
1373
1374 /* If device's offline or valid, skip its notifications */
1375 if (IsOff || Valid)
1376 {
1377 DeviceInformation->SkipNotifications = TRUE;
1378 }
1379
1380 /* In case device is valid and is set to no automount,
1381 * set it offline.
1382 */
1383 if (DeviceExtension->NoAutoMount || IsDrvLetter)
1384 {
1385 IsOff = !DeviceInformation->SkipNotifications;
1386 }
1387 else
1388 {
1389 IsOff = FALSE;
1390 }
1391
1392 /* Finally, release the exclusive lock */
1393 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1394
1395 /* If device is not offline, notify its arrival */
1396 if (!IsOff)
1397 {
1399 }
1400
1401 /* If we had symlinks (from storage), free them */
1402 if (SymLinks)
1403 {
1404 FreePool(SymLinks);
1405 }
1406
1407 /* Notify about unique id change */
1408 if (NewUniqueId)
1409 {
1410 IssueUniqueIdChangeNotify(DeviceExtension, SymbolicName, NewUniqueId);
1411 FreePool(NewUniqueId);
1412 }
1413
1414 /* If this drive was set to have a drive letter automatically
1415 * Now it's back, local databases sync will be required
1416 */
1417 if (DeviceExtension->AutomaticDriveLetter)
1418 {
1419 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1420
1421 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
1422
1423 NextEntry = DeviceExtension->DeviceListHead.Flink;
1424 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1425 while (CurrentDevice != DeviceInformation)
1426 {
1427 if (!CurrentDevice->NoDatabase)
1428 {
1429 ReconcileThisDatabaseWithMaster(DeviceExtension, CurrentDevice);
1430 }
1431
1432 NextEntry = NextEntry->Flink;
1433 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1434 }
1435
1436 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1437 }
1438
1439 return STATUS_SUCCESS;
1440}
1441
1442/*
1443 * @implemented
1444 */
1445VOID
1448{
1449 PLIST_ENTRY NextEntry, DeviceEntry;
1450 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
1451 PSYMLINK_INFORMATION SymlinkInformation;
1453 PSAVED_LINK_INFORMATION SavedLinkInformation = NULL;
1454 PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
1455
1456 /* Acquire device exclusively */
1457 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1458
1459 /* Look for the leaving device */
1460 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1461 NextEntry != &(DeviceExtension->DeviceListHead);
1462 NextEntry = NextEntry->Flink)
1463 {
1464 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1465
1466 if (!RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE))
1467 {
1468 break;
1469 }
1470 }
1471
1472 /* If we found it */
1473 if (NextEntry != &(DeviceExtension->DeviceListHead))
1474 {
1475 /* If it's asked to keep links, then, prepare to save them */
1476 if (DeviceInformation->KeepLinks)
1477 {
1478 SavedLinkInformation = AllocatePool(sizeof(SAVED_LINK_INFORMATION));
1479 if (!SavedLinkInformation)
1480 {
1481 DeviceInformation->KeepLinks = FALSE;
1482 }
1483 }
1484
1485 /* If it's possible (and asked), start to save them */
1486 if (DeviceInformation->KeepLinks)
1487 {
1488 InsertTailList(&(DeviceExtension->SavedLinksListHead), &(SavedLinkInformation->SavedLinksListEntry));
1489 InitializeListHead(&(SavedLinkInformation->SymbolicLinksListHead));
1490 SavedLinkInformation->UniqueId = DeviceInformation->UniqueId;
1491 }
1492
1493 /* For all the symlinks */
1494 while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
1495 {
1496 NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
1497 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1498
1499 /* If we have to, save the link */
1500 if (DeviceInformation->KeepLinks)
1501 {
1502 InsertTailList(&(SavedLinkInformation->SymbolicLinksListHead), &(SymlinkInformation->SymbolicLinksListEntry));
1503 }
1504 /* Otherwise, just release it */
1505 else
1506 {
1507 GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
1508 FreePool(SymlinkInformation->Name.Buffer);
1509 FreePool(SymlinkInformation);
1510 }
1511 }
1512
1513 /* Free all the replicated unique IDs */
1514 while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
1515 {
1516 NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
1517 UniqueIdReplicate = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
1518
1519
1520 FreePool(UniqueIdReplicate->UniqueId);
1521 FreePool(UniqueIdReplicate);
1522 }
1523
1524 while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
1525 {
1526 NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
1527 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1528
1529 DeviceInformation->NoDatabase = TRUE;
1530 FreePool(AssociatedDevice->String.Buffer);
1532 }
1533
1534 /* Remove device from the device list */
1535 RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1536
1537 /* If there are still devices, check if some were associated with ours */
1538 if (!IsListEmpty(&(DeviceInformation->DeviceListEntry)))
1539 {
1540 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1541 NextEntry != &(DeviceExtension->DeviceListHead);
1542 NextEntry = NextEntry->Flink)
1543 {
1544 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1545
1546 /* And then, remove them */
1547 DeviceEntry = CurrentDevice->AssociatedDevicesHead.Flink;
1548 while (DeviceEntry != &(CurrentDevice->AssociatedDevicesHead))
1549 {
1550 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1551 DeviceEntry = DeviceEntry->Flink;
1552
1553 if (AssociatedDevice->DeviceInformation != DeviceInformation)
1554 {
1555 continue;
1556 }
1557
1558 RemoveEntryList(&(AssociatedDevice->AssociatedDevicesEntry));
1559 FreePool(AssociatedDevice->String.Buffer);
1561 }
1562 }
1563 }
1564
1565 /* Finally, clean up device name, symbolic name */
1566 FreePool(DeviceInformation->SymbolicName.Buffer);
1567 if (!DeviceInformation->KeepLinks)
1568 {
1569 FreePool(DeviceInformation->UniqueId);
1570 }
1571 FreePool(DeviceInformation->DeviceName.Buffer);
1572
1573 /* Unregister notifications */
1574 if (DeviceInformation->TargetDeviceNotificationEntry)
1575 {
1577 }
1578
1579 /* And leave */
1580 FreePool(DeviceInformation);
1581 }
1582 else
1583 {
1584 /* We didn't find device, perhaps because it was offline */
1585 for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
1586 NextEntry != &(DeviceExtension->OfflineDeviceListHead);
1587 NextEntry = NextEntry->Flink)
1588 {
1589 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1590
1591 /* It was, remove it */
1592 if (RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE) == 0)
1593 {
1594 RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1595 MountMgrFreeDeadDeviceInfo(DeviceInformation);
1596 break;
1597 }
1598 }
1599 }
1600
1601 /* Release driver */
1602 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1603}
1604
1605/*
1606 * @implemented
1607 */
1609NTAPI
1612{
1613 BOOLEAN OldState;
1614 PDEVICE_EXTENSION DeviceExtension;
1616
1617 /* Notification for a device arrived */
1618 /* Disable hard errors */
1621
1622 DeviceExtension = Context;
1624
1625 /* Dispatch according to the event */
1627 {
1628 MountMgrMountedDeviceArrival(DeviceExtension, Notification->SymbolicLinkName, FALSE);
1629 }
1631 {
1632 MountMgrMountedDeviceRemoval(DeviceExtension, Notification->SymbolicLinkName);
1633 }
1634
1635 /* Reset hard errors */
1637
1638 return STATUS_SUCCESS;
1639}
1640
1641/*
1642 * @implemented
1643 */
1645NTAPI
1647 IN PIRP Irp)
1648{
1651
1653
1655
1656 /* Allow driver opening for communication
1657 * as long as it's not taken for a directory
1658 */
1659 if (Stack->MajorFunction == IRP_MJ_CREATE &&
1660 Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
1661 {
1663 }
1664
1665 Irp->IoStatus.Status = Status;
1666 Irp->IoStatus.Information = 0;
1668 return Status;
1669}
1670
1671/*
1672 * @implemented
1673 */
1674VOID
1675NTAPI
1677 IN PIRP Irp)
1678{
1680
1681 RemoveEntryList(&(Irp->Tail.Overlay.ListEntry));
1682
1683 IoReleaseCancelSpinLock(Irp->CancelIrql);
1684
1685 Irp->IoStatus.Information = 0;
1686 Irp->IoStatus.Status = STATUS_CANCELLED;
1688}
1689
1690/*
1691 * @implemented
1692 */
1694NTAPI
1696 IN PIRP Irp)
1697{
1698 PIRP ListIrp;
1699 KIRQL OldIrql;
1700 PLIST_ENTRY NextEntry;
1703 PDEVICE_EXTENSION DeviceExtension;
1704
1705 DeviceExtension = DeviceObject->DeviceExtension;
1707 FileObject = Stack->FileObject;
1708
1710
1711 /* If IRP list if empty, it's OK */
1712 if (IsListEmpty(&(DeviceExtension->IrpListHead)))
1713 {
1715
1716 Irp->IoStatus.Status = STATUS_SUCCESS;
1717 Irp->IoStatus.Information = 0;
1719
1720 return STATUS_SUCCESS;
1721 }
1722
1723 /* Otherwise, cancel all the IRPs */
1724 NextEntry = DeviceExtension->IrpListHead.Flink;
1725 do
1726 {
1727 ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
1729 {
1730 ListIrp->Cancel = TRUE;
1731 ListIrp->CancelIrql = OldIrql;
1732 ListIrp->CancelRoutine = NULL;
1733 MountMgrCancel(DeviceObject, ListIrp);
1734
1736 }
1737
1738 NextEntry = NextEntry->Flink;
1739 }
1740 while (NextEntry != &(DeviceExtension->IrpListHead));
1741
1743
1744 Irp->IoStatus.Status = STATUS_SUCCESS;
1745 Irp->IoStatus.Information = 0;
1747
1748 return STATUS_SUCCESS;
1749}
1750
1751/*
1752 * @implemented
1753 */
1755NTAPI
1757 IN PIRP Irp)
1758{
1759 PDEVICE_EXTENSION DeviceExtension;
1760
1761 DeviceExtension = DeviceObject->DeviceExtension;
1762
1764
1766
1767 /* Wait for workers */
1768 if (InterlockedIncrement(&(DeviceExtension->WorkerReferences)) > 0)
1769 {
1770 KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore),
1772 1,
1773 FALSE);
1775 }
1776 else
1777 {
1778 InterlockedDecrement(&(DeviceExtension->WorkerReferences));
1779 }
1780
1781 Irp->IoStatus.Status = STATUS_SUCCESS;
1782 Irp->IoStatus.Information = 0;
1784
1785 return STATUS_SUCCESS;
1786}
1787
1788/* FUNCTIONS ****************************************************************/
1789
1790CODE_SEG("INIT")
1792NTAPI
1795{
1798 PDEVICE_EXTENSION DeviceExtension;
1799
1801
1803 sizeof(DEVICE_EXTENSION),
1804 &DeviceMount,
1807 FALSE,
1808 &DeviceObject);
1809 if (!NT_SUCCESS(Status))
1810 {
1811 return Status;
1812 }
1813
1814 DriverObject->DriverUnload = MountMgrUnload;
1815
1816 DeviceExtension = DeviceObject->DeviceExtension;
1817 RtlZeroMemory(DeviceExtension, sizeof(DEVICE_EXTENSION));
1818 DeviceExtension->DeviceObject = DeviceObject;
1819 DeviceExtension->DriverObject = DriverObject;
1820
1821 InitializeListHead(&(DeviceExtension->DeviceListHead));
1822 InitializeListHead(&(DeviceExtension->OfflineDeviceListHead));
1823
1824 KeInitializeSemaphore(&(DeviceExtension->DeviceLock), 1, 1);
1825 KeInitializeSemaphore(&(DeviceExtension->RemoteDatabaseLock), 1, 1);
1826
1827 InitializeListHead(&(DeviceExtension->IrpListHead));
1828 DeviceExtension->EpicNumber = 1;
1829
1830 InitializeListHead(&(DeviceExtension->SavedLinksListHead));
1831
1832 InitializeListHead(&(DeviceExtension->WorkerQueueListHead));
1833 KeInitializeSemaphore(&(DeviceExtension->WorkerSemaphore), 0, MAXLONG);
1834 DeviceExtension->WorkerReferences = -1;
1835 KeInitializeSpinLock(&(DeviceExtension->WorkerLock));
1836
1837 InitializeListHead(&(DeviceExtension->UniqueIdWorkerItemListHead));
1838 InitializeListHead(&(DeviceExtension->OnlineNotificationListHead));
1839 DeviceExtension->OnlineNotificationCount = 1;
1840
1841 DeviceExtension->RegistryPath.Length = RegistryPath->Length;
1842 DeviceExtension->RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
1843 DeviceExtension->RegistryPath.Buffer = AllocatePool(DeviceExtension->RegistryPath.MaximumLength);
1844 if (!DeviceExtension->RegistryPath.Buffer)
1845 {
1848 }
1849
1850 RtlCopyUnicodeString(&(DeviceExtension->RegistryPath), RegistryPath);
1851
1852 DeviceExtension->NoAutoMount = MountmgrReadNoAutoMount(&(DeviceExtension->RegistryPath));
1853
1855
1856 /* Register for device arrival & removal. Ask to be notified for already
1857 * present devices
1858 */
1864 DeviceExtension,
1865 &(DeviceExtension->NotificationEntry));
1866
1867 if (!NT_SUCCESS(Status))
1868 {
1870 return Status;
1871 }
1872
1873 DriverObject->MajorFunction[IRP_MJ_CREATE] =
1878
1880
1882 if (!NT_SUCCESS(Status))
1883 {
1885 }
1886
1887 return Status;
1888}
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:32
#define MAX_PATH
Definition: compat.h:34
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
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 RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
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:514
VOID SendLinkCreated(IN PUNICODE_STRING SymbolicName)
Definition: symlink.c:160
VOID SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
Definition: notify.c:38
NTSTATUS GlobalCreateSymbolicLink(IN PUNICODE_STRING DosName, IN PUNICODE_STRING DeviceName)
Definition: symlink.c:111
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:136
DRIVER_DISPATCH MountMgrDeviceControl
Definition: mntmgr.h:340
UNICODE_STRING DeviceFloppy
Definition: symlink.c:34
UNICODE_STRING DosDevicesMount
Definition: symlink.c:32
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:922
UNICODE_STRING DeviceMount
Definition: symlink.c:31
NTSTATUS CreateNewVolumeName(OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL)
Definition: symlink.c:462
UNICODE_STRING DeviceCdRom
Definition: symlink.c:35
VOID RegisterForTargetDeviceNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: notify.c:273
#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:660
NTSTATUS QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING SuggestedLinkName, OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
Definition: symlink.c:684
PSAVED_LINK_INFORMATION RemoveSavedLinks(IN PDEVICE_EXTENSION DeviceExtension, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: symlink.c:640
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define FreePool(P)
Definition: mntmgr.h:154
UNICODE_STRING DosDevices
Definition: symlink.c:33
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:827
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
VOID NTAPI MountMgrUnload(IN struct _DRIVER_OBJECT *DriverObject)
Definition: mountmgr.c:794
NTSTATUS NTAPI MountMgrShutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1756
BOOLEAN IsOffline(PUNICODE_STRING SymbolicName)
Definition: mountmgr.c:46
BOOLEAN MountmgrReadNoAutoMount(IN PUNICODE_STRING RegistryPath)
Definition: mountmgr.c:898
NTSTATUS NTAPI MountMgrMountedDeviceNotification(IN PVOID NotificationStructure, IN PVOID Context)
Definition: mountmgr.c:1610
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:190
KEVENT UnloadEvent
Definition: mountmgr.c:36
NTSTATUS MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN ManuallyRegistered)
Definition: mountmgr.c:931
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:636
VOID MountMgrFreeMountedDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:711
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:1695
#define Cunc_LETTER_POSITION
Definition: mountmgr.c:40
VOID NTAPI MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1676
NTSTATUS CreateNewDriveLetterName(OUT PUNICODE_STRING DriveLetter, IN PUNICODE_STRING DeviceName, IN UCHAR Letter, IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL)
Definition: mountmgr.c:108
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:701
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:83
VOID MountMgrMountedDeviceRemoval(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName)
Definition: mountmgr.c:1446
VOID MountMgrFreeSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation)
Definition: mountmgr.c:766
NTSTATUS NTAPI MountMgrCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: mountmgr.c:1646
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:61
_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:4208
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 REG_NONE
Definition: nt_native.h:1492
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:342
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES
Definition: ntddvol.h:56
@ 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
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:124
#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:71
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
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_ 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