ReactOS 0.4.15-dev-8219-ge8b88cf
symlink.c File Reference
#include "mntmgr.h"
#include <debug.h>
Include dependency graph for symlink.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED   CTL_CODE(MOUNTDEVCONTROLTYPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
#define IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED   CTL_CODE(MOUNTDEVCONTROLTYPE, 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
 

Functions

NTSTATUS CreateStringWithGlobal (IN PUNICODE_STRING DosName, OUT PUNICODE_STRING GlobalString)
 
NTSTATUS GlobalCreateSymbolicLink (IN PUNICODE_STRING DosName, IN PUNICODE_STRING DeviceName)
 
NTSTATUS GlobalDeleteSymbolicLink (IN PUNICODE_STRING DosName)
 
VOID SendLinkCreated (IN PUNICODE_STRING SymbolicName)
 
VOID SendLinkDeleted (IN PUNICODE_STRING DeviceName, IN PUNICODE_STRING SymbolicName)
 
NTSTATUS NTAPI SymbolicLinkNamesFromUniqueIdCount (IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
 
NTSTATUS NTAPI SymbolicLinkNamesFromUniqueIdQuery (IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
 
NTSTATUS CreateNewVolumeName (OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL)
 
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)
 
PSAVED_LINK_INFORMATION RemoveSavedLinks (IN PDEVICE_EXTENSION DeviceExtension, IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
NTSTATUS QuerySuggestedLinkName (IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING SuggestedLinkName, OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
 
BOOLEAN RedirectSavedLink (IN PSAVED_LINK_INFORMATION SavedLinkInformation, IN PUNICODE_STRING DosName, IN PUNICODE_STRING NewLink)
 
VOID DeleteSymbolicLinkNameFromMemory (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLink, IN BOOLEAN MarkOffline)
 
BOOLEAN IsDriveLetter (PUNICODE_STRING SymbolicName)
 
NTSTATUS MountMgrQuerySymbolicLink (IN PUNICODE_STRING SymbolicName, IN OUT PUNICODE_STRING LinkTarget)
 

Variables

UNICODE_STRING DeviceMount = RTL_CONSTANT_STRING(MOUNTMGR_DEVICE_NAME)
 
UNICODE_STRING DosDevicesMount = RTL_CONSTANT_STRING(L"\\DosDevices\\MountPointManager")
 
UNICODE_STRING DosDevices = RTL_CONSTANT_STRING(L"\\DosDevices\\")
 
UNICODE_STRING DeviceFloppy = RTL_CONSTANT_STRING(L"\\Device\\Floppy")
 
UNICODE_STRING DeviceCdRom = RTL_CONSTANT_STRING(L"\\Device\\CdRom")
 
UNICODE_STRING DosGlobal = RTL_CONSTANT_STRING(L"\\GLOBAL??\\")
 
UNICODE_STRING Global = RTL_CONSTANT_STRING(L"\\??\\")
 
UNICODE_STRING SafeVolumes = RTL_CONSTANT_STRING(L"\\Device\\VolumesSafeForWriteAccess")
 
UNICODE_STRING Volume = RTL_CONSTANT_STRING(L"\\??\\Volume")
 
UNICODE_STRING ReparseIndex = RTL_CONSTANT_STRING(L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION")
 

Macro Definition Documentation

◆ IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED

#define IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED   CTL_CODE(MOUNTDEVCONTROLTYPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS)

Definition at line 36 of file symlink.c.

◆ IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED

#define IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED   CTL_CODE(MOUNTDEVCONTROLTYPE, 5, METHOD_BUFFERED, FILE_ANY_ACCESS)

Definition at line 37 of file symlink.c.

◆ NDEBUG

#define NDEBUG

Definition at line 28 of file symlink.c.

Function Documentation

◆ CreateNewVolumeName()

NTSTATUS CreateNewVolumeName ( OUT PUNICODE_STRING  VolumeName,
IN PGUID VolumeGuid  OPTIONAL 
)

Definition at line 399 of file symlink.c.

401{
402 GUID Guid;
405
406 /* If no GUID was provided, then create one */
407 if (!VolumeGuid)
408 {
410 if (!NT_SUCCESS(Status))
411 {
412 return Status;
413 }
414 }
415 else
416 {
417 RtlCopyMemory(&Guid, VolumeGuid, sizeof(GUID));
418 }
419
420 /* Convert GUID to string */
422 if (!NT_SUCCESS(Status))
423 {
424 return Status;
425 }
426
427 /* Size for volume namespace, literal GUID, and null char */
428 VolumeName->MaximumLength = 0x14 + 0x4C + sizeof(UNICODE_NULL);
429 VolumeName->Buffer = AllocatePool(0x14 + 0x4C + sizeof(UNICODE_NULL));
430 if (!VolumeName->Buffer)
431 {
433 }
434 else
435 {
440 }
441
442 ExFreePoolWithTag(GuidString.Buffer, 0);
443
444 return Status;
445}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
Status
Definition: gdiplustypes.h:25
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
#define AllocatePool(Size)
Definition: mntmgr.h:153
NTKERNELAPI NTSTATUS ExUuidCreate(OUT UUID *Uuid)
Definition: uuid.c:380
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static PWSTR GuidString
Definition: apphelp.c:93
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define UNICODE_NULL
#define STATUS_SUCCESS
Definition: shellext.h:65
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by MountMgrMountedDeviceArrival(), and QuerySymbolicLinkNamesFromStorage().

◆ CreateStringWithGlobal()

NTSTATUS CreateStringWithGlobal ( IN PUNICODE_STRING  DosName,
OUT PUNICODE_STRING  GlobalString 
)

Definition at line 55 of file symlink.c.

57{
58 UNICODE_STRING IntGlobal;
59
61 {
62 /* DOS device - use DOS global */
64 IntGlobal.MaximumLength = IntGlobal.Length + sizeof(WCHAR);
65 IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength);
66 if (!IntGlobal.Buffer)
67 {
69 }
70
72 RtlCopyMemory(IntGlobal.Buffer + (DosGlobal.Length / sizeof(WCHAR)),
73 DosName->Buffer + (DosDevices.Length / sizeof(WCHAR)),
75 IntGlobal.Buffer[IntGlobal.Length / sizeof(WCHAR)] = UNICODE_NULL;
76 }
78 {
79 /* Switch to DOS global */
81 IntGlobal.MaximumLength = IntGlobal.Length + sizeof(WCHAR);
82 IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength);
83 if (!IntGlobal.Buffer)
84 {
86 }
87
89 RtlCopyMemory(IntGlobal.Buffer + (DosGlobal.Length / sizeof(WCHAR)),
90 DosName->Buffer + (Global.Length / sizeof(WCHAR)),
92 IntGlobal.Buffer[IntGlobal.Length / sizeof(WCHAR)] = UNICODE_NULL;
93 }
94 else
95 {
96 /* Simply duplicate string */
97 IntGlobal.Length = DosName->Length;
99 IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength);
100 if (!IntGlobal.Buffer)
101 {
103 }
104
105 RtlCopyMemory(IntGlobal.Buffer, DosName->Buffer, IntGlobal.MaximumLength);
106 }
107
108 /* Return string */
109 GlobalString->Length = IntGlobal.Length;
110 GlobalString->MaximumLength = IntGlobal.MaximumLength;
111 GlobalString->Buffer = IntGlobal.Buffer;
112
113 return STATUS_SUCCESS;
114}
#define TRUE
Definition: types.h:120
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1269

Referenced by GlobalCreateSymbolicLink(), and GlobalDeleteSymbolicLink().

◆ DeleteSymbolicLinkNameFromMemory()

VOID DeleteSymbolicLinkNameFromMemory ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  SymbolicLink,
IN BOOLEAN  MarkOffline 
)

Definition at line 754 of file symlink.c.

757{
758 PLIST_ENTRY DeviceEntry, SymbolEntry;
759 PDEVICE_INFORMATION DeviceInformation;
760 PSYMLINK_INFORMATION SymlinkInformation;
761
762 /* First of all, ensure we have devices */
763 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
764 {
765 return;
766 }
767
768 /* Then, look for the symbolic name */
769 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
770 DeviceEntry != &(DeviceExtension->DeviceListHead);
771 DeviceEntry = DeviceEntry->Flink)
772 {
773 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
774
775 for (SymbolEntry = DeviceInformation->SymbolicLinksListHead.Flink;
776 SymbolEntry != &(DeviceInformation->SymbolicLinksListHead);
777 SymbolEntry = SymbolEntry->Flink)
778 {
779 SymlinkInformation = CONTAINING_RECORD(SymbolEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
780
781 /* One we have found it */
782 if (RtlCompareUnicodeString(SymbolicLink, &(SymlinkInformation->Name), TRUE) == 0)
783 {
784 /* Check if caller just want it to be offline */
785 if (MarkOffline)
786 {
787 SymlinkInformation->Online = FALSE;
788 }
789 else
790 {
791 /* If not, delete it & notify */
792 SendLinkDeleted(&(DeviceInformation->SymbolicName), SymbolicLink);
793 RemoveEntryList(&(SymlinkInformation->SymbolicLinksListEntry));
794
795 FreePool(SymlinkInformation->Name.Buffer);
796 FreePool(SymlinkInformation);
797 }
798
799 /* No need to go farther */
800 return;
801 }
802 }
803 }
804
805 return;
806}
#define FALSE
Definition: types.h:117
static const WCHAR SymbolicLink[]
Definition: interface.c:31
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define FreePool(P)
Definition: mntmgr.h:154
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
LIST_ENTRY SymbolicLinksListHead
Definition: mntmgr.h:45
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by MountMgrDeletePoints(), and MountMgrDeletePointsDbOnly().

◆ GlobalCreateSymbolicLink()

NTSTATUS GlobalCreateSymbolicLink ( IN PUNICODE_STRING  DosName,
IN PUNICODE_STRING  DeviceName 
)

Definition at line 120 of file symlink.c.

122{
124 UNICODE_STRING GlobalName;
125
126 /* First create the global string */
127 Status = CreateStringWithGlobal(DosName, &GlobalName);
128 if (!NT_SUCCESS(Status))
129 {
130 return Status;
131 }
132
133 /* Then, create the symlink */
134 Status = IoCreateSymbolicLink(&GlobalName, DeviceName);
135
136 FreePool(GlobalName.Buffer);
137
138 return Status;
139}
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275

Referenced by CreateNewDriveLetterName(), DriverEntry(), MountMgrCreatePointWorker(), MountMgrMountedDeviceArrival(), and RedirectSavedLink().

◆ GlobalDeleteSymbolicLink()

NTSTATUS GlobalDeleteSymbolicLink ( IN PUNICODE_STRING  DosName)

Definition at line 145 of file symlink.c.

146{
148 UNICODE_STRING GlobalName;
149
150 /* Recreate the string (to find the link) */
151 Status = CreateStringWithGlobal(DosName, &GlobalName);
152 if (!NT_SUCCESS(Status))
153 {
154 return Status;
155 }
156
157 /* And delete the link */
158 Status = IoDeleteSymbolicLink(&GlobalName);
159
160 FreePool(GlobalName.Buffer);
161
162 return Status;
163}

Referenced by MountMgrCreatePointWorker(), MountMgrDeletePoints(), MountMgrFreeMountedDeviceInfo(), MountMgrFreeSavedLink(), MountMgrMountedDeviceArrival(), MountMgrMountedDeviceRemoval(), MountMgrUnload(), and RedirectSavedLink().

◆ IsDriveLetter()

BOOLEAN IsDriveLetter ( PUNICODE_STRING  SymbolicName)

Definition at line 812 of file symlink.c.

813{
815
816 /* We must have a precise length */
817 if (SymbolicName->Length != DosDevices.Length + 2 * sizeof(WCHAR))
818 {
819 return FALSE;
820 }
821
822 /* Must start with the DosDevices prefix */
824 {
825 return FALSE;
826 }
827
828 /* Check if letter is correct */
830 if ((Letter < L'A' || Letter > L'Z') && Letter != (WCHAR)-1)
831 {
832 return FALSE;
833 }
834
835 /* And finally it must end with a colon */
837 if (Colon != L':')
838 {
839 return FALSE;
840 }
841
842 return TRUE;
843}
WCHAR Letter
@ Colon
Definition: asmpp.cpp:43
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4677
#define L(x)
Definition: ntvdm.h:50

Referenced by DeleteDriveLetterRoutine(), HasDriveLetter(), MountMgrCreatePointWorker(), MountMgrDeletePoints(), MountMgrDeletePointsDbOnly(), MountMgrMountedDeviceArrival(), MountMgrNextDriveLetterWorker(), and QuerySymbolicLinkNamesFromStorage().

◆ MountMgrQuerySymbolicLink()

NTSTATUS MountMgrQuerySymbolicLink ( IN PUNICODE_STRING  SymbolicName,
IN OUT PUNICODE_STRING  LinkTarget 
)

Definition at line 849 of file symlink.c.

851{
853 HANDLE LinkHandle;
855
856 /* Open the symbolic link */
860 NULL,
861 NULL);
862
863 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
866 if (!NT_SUCCESS(Status))
867 {
868 return Status;
869 }
870
871 /* Query its target */
872 Status = ZwQuerySymbolicLinkObject(LinkHandle,
874 NULL);
875
876 ZwClose(LinkHandle);
877
878 if (!NT_SUCCESS(Status))
879 {
880 return Status;
881 }
882
883 if (LinkTarget->Length <= sizeof(WCHAR))
884 {
885 return Status;
886 }
887
888 /* If it's not finished by \, just return */
889 if (LinkTarget->Buffer[LinkTarget->Length / sizeof(WCHAR) - 1] != L'\\')
890 {
891 return Status;
892 }
893
894 /* Otherwise, ensure to drop the tailing \ */
895 LinkTarget->Length -= sizeof(WCHAR);
897
898 return Status;
899}
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define GENERIC_READ
Definition: compat.h:135
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292

Referenced by MountMgrVolumeMountPointCreated(), and MountMgrVolumeMountPointDeleted().

◆ QuerySuggestedLinkName()

NTSTATUS QuerySuggestedLinkName ( IN PUNICODE_STRING  SymbolicName,
OUT PUNICODE_STRING  SuggestedLinkName,
OUT PBOOLEAN  UseOnlyIfThereAreNoOtherLinks 
)

Definition at line 621 of file symlink.c.

624{
626 USHORT NameLength;
629 PMOUNTDEV_SUGGESTED_LINK_NAME IoCtlSuggested;
630
631 /* First, get device */
634 &FileObject,
635 &DeviceObject);
636 if (!NT_SUCCESS(Status))
637 {
638 return Status;
639 }
640
641 /* Then, get attached device */
643
644 /* Then, prepare buffer to query suggested name */
645 IoCtlSuggested = AllocatePool(sizeof(MOUNTDEV_SUGGESTED_LINK_NAME));
646 if (!IoCtlSuggested)
647 {
649 goto Dereference;
650 }
651
652 /* Prepare request */
653 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME,
655 NULL,
656 0,
657 IoCtlSuggested,
659 FileObject);
660 /* Retry with appropriate length */
662 {
663 /* Reallocate big enough buffer */
664 NameLength = IoCtlSuggested->NameLength + sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
665 FreePool(IoCtlSuggested);
666
667 IoCtlSuggested = AllocatePool(NameLength);
668 if (!IoCtlSuggested)
669 {
671 goto Dereference;
672 }
673
674 /* And re-ask */
675 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME,
677 NULL,
678 0,
679 IoCtlSuggested,
680 NameLength,
681 FileObject);
682 }
683 if (!NT_SUCCESS(Status))
684 goto Release;
685
686 /* Now we have suggested name, copy it */
687 SuggestedLinkName->Length = IoCtlSuggested->NameLength;
688 SuggestedLinkName->MaximumLength = IoCtlSuggested->NameLength + sizeof(UNICODE_NULL);
689 SuggestedLinkName->Buffer = AllocatePool(IoCtlSuggested->NameLength + sizeof(UNICODE_NULL));
690 if (!SuggestedLinkName->Buffer)
691 {
693 }
694 else
695 {
696 RtlCopyMemory(SuggestedLinkName->Buffer, IoCtlSuggested->Name, IoCtlSuggested->NameLength);
697 SuggestedLinkName->Buffer[SuggestedLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL;
698 }
699
700 /* Also return its priority */
701 *UseOnlyIfThereAreNoOtherLinks = IoCtlSuggested->UseOnlyIfThereAreNoOtherLinks;
702
703Release:
704 FreePool(IoCtlSuggested);
705
706Dereference:
709
710 return Status;
711}
_In_ BOOLEAN Release
Definition: cdrom.h:920
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
struct _MOUNTDEV_SUGGESTED_LINK_NAME MOUNTDEV_SUGGESTED_LINK_NAME
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
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
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by MountMgrMountedDeviceArrival().

◆ QuerySymbolicLinkNamesFromStorage()

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 at line 451 of file symlink.c.

459{
461 BOOLEAN WriteNew;
463
464 UNREFERENCED_PARAMETER(DeviceExtension);
465
466 /* First of all, count links */
469 QueryTable[0].EntryContext = SymLinkCount;
470 *SymLinkCount = 0;
471
475 DeviceInformation->UniqueId,
476 NULL);
477 if (!NT_SUCCESS(Status))
478 {
479 *SymLinkCount = 0;
480 }
481
482 /* Check if we have to write a new one first */
483 if (SuggestedLinkName && !IsDriveLetter(SuggestedLinkName) &&
484 UseOnlyIfThereAreNoOtherLinks && *SymLinkCount == 0)
485 {
486 WriteNew = TRUE;
487 }
488 else
489 {
490 WriteNew = FALSE;
491 }
492
493 /* If has GUID, it makes one more link */
494 if (HasGuid)
495 {
496 (*SymLinkCount)++;
497 }
498
499 if (WriteNew)
500 {
501 /* Write link */
504 SuggestedLinkName->Buffer,
506 DeviceInformation->UniqueId->UniqueId,
507 DeviceInformation->UniqueId->UniqueIdLength);
508
509 /* And recount all the needed links */
512 QueryTable[0].EntryContext = SymLinkCount;
513 *SymLinkCount = 0;
514
518 DeviceInformation->UniqueId,
519 NULL);
520 if (!NT_SUCCESS(Status))
521 {
522 return STATUS_NOT_FOUND;
523 }
524 }
525
526 /* Not links found? */
527 if (!*SymLinkCount)
528 {
529 return STATUS_NOT_FOUND;
530 }
531
532 /* Allocate a buffer big enough to hold symlinks (table of unicode strings) */
533 *SymLinks = AllocatePool(*SymLinkCount * sizeof(UNICODE_STRING));
534 if (!*SymLinks)
535 {
537 }
538
539 /* Prepare to query links */
540 RtlZeroMemory(*SymLinks, *SymLinkCount * sizeof(UNICODE_STRING));
543
544 /* No GUID? Keep it that way */
545 if (!HasGuid)
546 {
547 QueryTable[0].EntryContext = *SymLinks;
548 }
549 /* Otherwise, first create volume name */
550 else
551 {
552 Status = CreateNewVolumeName(SymLinks[0], Guid);
553 if (!NT_SUCCESS(Status))
554 {
555 FreePool(*SymLinks);
556 return Status;
557 }
558
559 /* Skip first link (ours) */
560 QueryTable[0].EntryContext = *SymLinks + 1;
561 }
562
563 /* Now, query */
567 DeviceInformation->UniqueId,
568 NULL);
569
570 return STATUS_SUCCESS;
571}
unsigned char BOOLEAN
PWSTR DatabasePath
Definition: database.c:31
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4208
#define REG_BINARY
Definition: nt_native.h:1496
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_NOT_FOUND
Definition: shellext.h:72
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by MountMgrMountedDeviceArrival().

◆ RedirectSavedLink()

BOOLEAN RedirectSavedLink ( IN PSAVED_LINK_INFORMATION  SavedLinkInformation,
IN PUNICODE_STRING  DosName,
IN PUNICODE_STRING  NewLink 
)

Definition at line 717 of file symlink.c.

720{
721 PLIST_ENTRY NextEntry;
722 PSYMLINK_INFORMATION SymlinkInformation;
723
724 /* Find the link */
725 for (NextEntry = SavedLinkInformation->SymbolicLinksListHead.Flink;
726 NextEntry != &(SavedLinkInformation->SymbolicLinksListHead);
727 NextEntry = NextEntry->Flink)
728 {
729 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
730
731 if (!RtlEqualUnicodeString(DosName, &(SymlinkInformation->Name), TRUE))
732 {
733 /* Delete old link */
735 /* Set its new location */
737
738 /* And remove it from the list (not valid any more) */
739 RemoveEntryList(&(SymlinkInformation->SymbolicLinksListEntry));
740 FreePool(SymlinkInformation->Name.Buffer);
741 FreePool(SymlinkInformation);
742
743 return TRUE;
744 }
745 }
746
747 return FALSE;
748}
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)

Referenced by MountMgrMountedDeviceArrival().

◆ RemoveSavedLinks()

PSAVED_LINK_INFORMATION RemoveSavedLinks ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PMOUNTDEV_UNIQUE_ID  UniqueId 
)

Definition at line 577 of file symlink.c.

579{
580 PLIST_ENTRY NextEntry;
581 PSAVED_LINK_INFORMATION SavedLinkInformation;
582
583 /* No saved links? Easy! */
584 if (IsListEmpty(&(DeviceExtension->SavedLinksListHead)))
585 {
586 return NULL;
587 }
588
589 /* Now, browse saved links */
590 for (NextEntry = DeviceExtension->SavedLinksListHead.Flink;
591 NextEntry != &(DeviceExtension->SavedLinksListHead);
592 NextEntry = NextEntry->Flink)
593 {
594 SavedLinkInformation = CONTAINING_RECORD(NextEntry,
596 SavedLinksListEntry);
597
598 /* Find the one that matches */
599 if (SavedLinkInformation->UniqueId->UniqueIdLength == UniqueId->UniqueIdLength)
600 {
601 if (RtlCompareMemory(SavedLinkInformation->UniqueId->UniqueId,
602 UniqueId->UniqueId,
603 UniqueId->UniqueIdLength) ==
604 UniqueId->UniqueIdLength)
605 {
606 /* Remove it and return it */
607 RemoveEntryList(&(SavedLinkInformation->SavedLinksListEntry));
608 return SavedLinkInformation;
609 }
610 }
611 }
612
613 /* None found (none removed) */
614 return NULL;
615}
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
USHORT UniqueIdLength
Definition: imports.h:138
UCHAR UniqueId[1]
Definition: imports.h:139

Referenced by MountMgrMountedDeviceArrival().

◆ SendLinkCreated()

VOID SendLinkCreated ( IN PUNICODE_STRING  SymbolicName)

Definition at line 169 of file symlink.c.

170{
172 ULONG NameSize;
176
177 /* Get the device associated with the name */
180 &FileObject,
181 &DeviceObject);
182 if (!NT_SUCCESS(Status))
183 return;
184
185 /* Get attached device (will notify it) */
187
188 /* NameSize is the size of the whole MOUNTDEV_NAME structure */
189 NameSize = sizeof(USHORT) + SymbolicName->Length;
190 Name = AllocatePool(NameSize);
191 if (!Name)
192 goto Cleanup;
193
194 /* Initialize structure */
195 Name->NameLength = SymbolicName->Length;
197
198 /* Send the notification, using the new (Windows 2003+) IOCTL definition
199 * (with limited access) first. If this fails, the called driver may be
200 * for an older NT version, and so, we send again the notification using
201 * the old (Windows 2000) IOCTL definition (with any access). */
202 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_CREATED,
204 Name,
205 NameSize,
206 NULL,
207 0,
208 FileObject);
209 /* This one can fail, no one matters */
211#if (NTDDI_VERSION >= NTDDI_WS03)
212 /* Then, second one */
213 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED,
215 Name,
216 NameSize,
217 NULL,
218 0,
219 FileObject);
221#endif // (NTDDI_VERSION >= NTDDI_WS03)
222
223Cleanup:
224 if (Name)
225 FreePool(Name);
226
229
230 return;
231}
static const WCHAR Cleanup[]
Definition: register.c:80
#define IOCTL_MOUNTDEV_LINK_CREATED
Definition: imports.h:106
uint32_t ULONG
Definition: typedefs.h:59

Referenced by MountMgrCreatePointWorker(), and MountMgrMountedDeviceArrival().

◆ SendLinkDeleted()

VOID SendLinkDeleted ( IN PUNICODE_STRING  DeviceName,
IN PUNICODE_STRING  SymbolicName 
)

Definition at line 237 of file symlink.c.

239{
241 ULONG NameSize;
245
246 /* Get the device associated with the name */
249 &FileObject,
250 &DeviceObject);
251 if (!NT_SUCCESS(Status))
252 return;
253
254 /* Get attached device (will notify it) */
256
257 /* NameSize is the size of the whole MOUNTDEV_NAME structure */
258 NameSize = sizeof(USHORT) + SymbolicName->Length;
259 Name = AllocatePool(NameSize);
260 if (!Name)
261 goto Cleanup;
262
263 /* Initialize structure */
264 Name->NameLength = SymbolicName->Length;
266
267 /* Send the notification, using the new (Windows 2003+) IOCTL definition
268 * (with limited access) first. If this fails, the called driver may be
269 * for an older NT version, and so, we send again the notification using
270 * the old (Windows 2000) IOCTL definition (with any access). */
271 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_DELETED,
273 Name,
274 NameSize,
275 NULL,
276 0,
277 FileObject);
278 /* This one can fail, no one matters */
280#if (NTDDI_VERSION >= NTDDI_WS03)
281 /* Then, second one */
282 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED,
284 Name,
285 NameSize,
286 NULL,
287 0,
288 FileObject);
290#endif // (NTDDI_VERSION >= NTDDI_WS03)
291
292Cleanup:
293 if (Name)
294 FreePool(Name);
295
298
299 return;
300}
#define IOCTL_MOUNTDEV_LINK_DELETED
Definition: imports.h:112

Referenced by DeleteSymbolicLinkNameFromMemory().

◆ SymbolicLinkNamesFromUniqueIdCount()

NTSTATUS NTAPI SymbolicLinkNamesFromUniqueIdCount ( IN PWSTR  ValueName,
IN ULONG  ValueType,
IN PVOID  ValueData,
IN ULONG  ValueLength,
IN PVOID  Context,
IN PVOID  EntryContext 
)

Definition at line 307 of file symlink.c.

313{
314 UNICODE_STRING ValueNameString;
315 PMOUNTDEV_UNIQUE_ID UniqueId = Context;
316
317 if (ValueName[0] != L'#' || ValueType != REG_BINARY ||
318 (UniqueId->UniqueIdLength != ValueLength))
319 {
320 return STATUS_SUCCESS;
321 }
322
324 {
325 return STATUS_SUCCESS;
326 }
327
328 /* That one matched, increase count */
329 RtlInitUnicodeString(&ValueNameString, ValueName);
330 if (ValueNameString.Length)
331 {
332 (*((PULONG)EntryContext))++;
333 }
334
335 return STATUS_SUCCESS;
336}
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4207
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
uint32_t * PULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275

Referenced by QuerySymbolicLinkNamesFromStorage().

◆ SymbolicLinkNamesFromUniqueIdQuery()

NTSTATUS NTAPI SymbolicLinkNamesFromUniqueIdQuery ( IN PWSTR  ValueName,
IN ULONG  ValueType,
IN PVOID  ValueData,
IN ULONG  ValueLength,
IN PVOID  Context,
IN PVOID  EntryContext 
)

Definition at line 343 of file symlink.c.

349{
350 UNICODE_STRING ValueNameString;
351 PMOUNTDEV_UNIQUE_ID UniqueId = Context;
352 /* Unicode strings table */
353 PUNICODE_STRING ReturnString = EntryContext;
354
355 if (ValueName[0] != L'#' || ValueType != REG_BINARY ||
356 (UniqueId->UniqueIdLength != ValueLength))
357 {
358 return STATUS_SUCCESS;
359 }
360
362 {
363 return STATUS_SUCCESS;
364 }
365
366 /* Unique ID matches, let's put the symlink */
367 RtlInitUnicodeString(&ValueNameString, ValueName);
368 if (!ValueNameString.Length)
369 {
370 return STATUS_SUCCESS;
371 }
372
373 /* Allocate string to copy */
374 ValueNameString.Buffer = AllocatePool(ValueNameString.MaximumLength);
375 if (!ValueNameString.Buffer)
376 {
377 return STATUS_SUCCESS;
378 }
379
380 /* Copy */
381 RtlCopyMemory(ValueNameString.Buffer, ValueName, ValueNameString.Length);
382 ValueNameString.Buffer[ValueNameString.Length / sizeof(WCHAR)] = UNICODE_NULL;
383
384 while (ReturnString->Length)
385 {
386 ReturnString++;
387 }
388
389 /* And return that string */
390 *ReturnString = ValueNameString;
391
392 return STATUS_SUCCESS;
393}

Referenced by QuerySymbolicLinkNamesFromStorage().

Variable Documentation

◆ DeviceCdRom

UNICODE_STRING DeviceCdRom = RTL_CONSTANT_STRING(L"\\Device\\CdRom")

◆ DeviceFloppy

UNICODE_STRING DeviceFloppy = RTL_CONSTANT_STRING(L"\\Device\\Floppy")

Definition at line 43 of file symlink.c.

Referenced by CreateNewDriveLetterName(), and MountMgrNextDriveLetterWorker().

◆ DeviceMount

Definition at line 40 of file symlink.c.

Referenced by DriverEntry().

◆ DosDevices

◆ DosDevicesMount

UNICODE_STRING DosDevicesMount = RTL_CONSTANT_STRING(L"\\DosDevices\\MountPointManager")

Definition at line 41 of file symlink.c.

Referenced by DriverEntry(), and MountMgrUnload().

◆ DosGlobal

Definition at line 45 of file symlink.c.

Referenced by CreateStringWithGlobal().

◆ Global

◆ ReparseIndex

UNICODE_STRING ReparseIndex = RTL_CONSTANT_STRING(L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION")

Definition at line 49 of file symlink.c.

Referenced by OnlineMountedVolumes(), and ReconcileThisDatabaseWithMasterWorker().

◆ SafeVolumes

UNICODE_STRING SafeVolumes = RTL_CONSTANT_STRING(L"\\Device\\VolumesSafeForWriteAccess")

Definition at line 47 of file symlink.c.

Referenced by WorkerThread().

◆ Volume

UNICODE_STRING Volume = RTL_CONSTANT_STRING(L"\\??\\Volume")

Definition at line 48 of file symlink.c.

Referenced by CreateNewVolumeName().