ReactOS 0.4.15-dev-7842-g558ab78
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
 

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

◆ 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 462 of file symlink.c.

464{
465 GUID Guid;
468
469 /* If no GUID was provided, then create one */
470 if (!VolumeGuid)
471 {
473 if (!NT_SUCCESS(Status))
474 {
475 return Status;
476 }
477 }
478 else
479 {
480 RtlCopyMemory(&Guid, VolumeGuid, sizeof(GUID));
481 }
482
483 /* Convert GUID to string */
485 if (!NT_SUCCESS(Status))
486 {
487 return Status;
488 }
489
490 /* Size for volume namespace, literal GUID, and null char */
491 VolumeName->MaximumLength = 0x14 + 0x4C + sizeof(UNICODE_NULL);
492 VolumeName->Buffer = AllocatePool(0x14 + 0x4C + sizeof(UNICODE_NULL));
493 if (!VolumeName->Buffer)
494 {
496 }
497 else
498 {
503 }
504
505 ExFreePoolWithTag(GuidString.Buffer, 0);
506
507 return Status;
508}
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 46 of file symlink.c.

48{
49 UNICODE_STRING IntGlobal;
50
52 {
53 /* DOS device - use DOS global */
55 IntGlobal.MaximumLength = IntGlobal.Length + sizeof(WCHAR);
56 IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength);
57 if (!IntGlobal.Buffer)
58 {
60 }
61
63 RtlCopyMemory(IntGlobal.Buffer + (DosGlobal.Length / sizeof(WCHAR)),
64 DosName->Buffer + (DosDevices.Length / sizeof(WCHAR)),
66 IntGlobal.Buffer[IntGlobal.Length / sizeof(WCHAR)] = UNICODE_NULL;
67 }
69 {
70 /* Switch to DOS global */
72 IntGlobal.MaximumLength = IntGlobal.Length + sizeof(WCHAR);
73 IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength);
74 if (!IntGlobal.Buffer)
75 {
77 }
78
80 RtlCopyMemory(IntGlobal.Buffer + (DosGlobal.Length / sizeof(WCHAR)),
81 DosName->Buffer + (Global.Length / sizeof(WCHAR)),
83 IntGlobal.Buffer[IntGlobal.Length / sizeof(WCHAR)] = UNICODE_NULL;
84 }
85 else
86 {
87 /* Simply duplicate string */
88 IntGlobal.Length = DosName->Length;
90 IntGlobal.Buffer = AllocatePool(IntGlobal.MaximumLength);
91 if (!IntGlobal.Buffer)
92 {
94 }
95
96 RtlCopyMemory(IntGlobal.Buffer, DosName->Buffer, IntGlobal.MaximumLength);
97 }
98
99 /* Return string */
100 GlobalString->Length = IntGlobal.Length;
101 GlobalString->MaximumLength = IntGlobal.MaximumLength;
102 GlobalString->Buffer = IntGlobal.Buffer;
103
104 return STATUS_SUCCESS;
105}
#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 864 of file symlink.c.

867{
868 PLIST_ENTRY DeviceEntry, SymbolEntry;
869 PDEVICE_INFORMATION DeviceInformation;
870 PSYMLINK_INFORMATION SymlinkInformation;
871
872 /* First of all, ensure we have devices */
873 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
874 {
875 return;
876 }
877
878 /* Then, look for the symbolic name */
879 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
880 DeviceEntry != &(DeviceExtension->DeviceListHead);
881 DeviceEntry = DeviceEntry->Flink)
882 {
883 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
884
885 for (SymbolEntry = DeviceInformation->SymbolicLinksListHead.Flink;
886 SymbolEntry != &(DeviceInformation->SymbolicLinksListHead);
887 SymbolEntry = SymbolEntry->Flink)
888 {
889 SymlinkInformation = CONTAINING_RECORD(SymbolEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
890
891 /* One we have found it */
892 if (RtlCompareUnicodeString(SymbolicLink, &(SymlinkInformation->Name), TRUE) == 0)
893 {
894 /* Check if caller just want it to be offline */
895 if (MarkOffline)
896 {
897 SymlinkInformation->Online = FALSE;
898 }
899 else
900 {
901 /* If not, delete it & notify */
902 SendLinkDeleted(&(DeviceInformation->SymbolicName), SymbolicLink);
903 RemoveEntryList(&(SymlinkInformation->SymbolicLinksListEntry));
904
905 FreePool(SymlinkInformation->Name.Buffer);
906 FreePool(SymlinkInformation);
907 }
908
909 /* No need to go farther */
910 return;
911 }
912 }
913 }
914
915 return;
916}
#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 111 of file symlink.c.

113{
115 UNICODE_STRING GlobalName;
116
117 /* First create the global string */
118 Status = CreateStringWithGlobal(DosName, &GlobalName);
119 if (!NT_SUCCESS(Status))
120 {
121 return Status;
122 }
123
124 /* Then, create the symlink */
125 Status = IoCreateSymbolicLink(&GlobalName, DeviceName);
126
127 FreePool(GlobalName.Buffer);
128
129 return Status;
130}
_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 136 of file symlink.c.

137{
139 UNICODE_STRING GlobalName;
140
141 /* Recreate the string (to find the link) */
142 Status = CreateStringWithGlobal(DosName, &GlobalName);
143 if (!NT_SUCCESS(Status))
144 {
145 return Status;
146 }
147
148 /* And delete the link */
149 Status = IoDeleteSymbolicLink(&GlobalName);
150
151 FreePool(GlobalName.Buffer);
152
153 return Status;
154}

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

◆ IsDriveLetter()

BOOLEAN IsDriveLetter ( PUNICODE_STRING  SymbolicName)

Definition at line 922 of file symlink.c.

923{
925
926 /* We must have a precise length */
927 if (SymbolicName->Length != DosDevices.Length + 2 * sizeof(WCHAR))
928 {
929 return FALSE;
930 }
931
932 /* Must start with the DosDevices prefix */
934 {
935 return FALSE;
936 }
937
938 /* Check if letter is correct */
940 if ((Letter < L'A' || Letter > L'Z') && Letter != (WCHAR)-1)
941 {
942 return FALSE;
943 }
944
945 /* And finally it must end with a colon */
947 if (Colon != L':')
948 {
949 return FALSE;
950 }
951
952 return TRUE;
953}
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 959 of file symlink.c.

961{
963 HANDLE LinkHandle;
965
966 /* Open the symbolic link */
970 NULL,
971 NULL);
972
973 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
976 if (!NT_SUCCESS(Status))
977 {
978 return Status;
979 }
980
981 /* Query its target */
982 Status = ZwQuerySymbolicLinkObject(LinkHandle,
984 NULL);
985
986 ZwClose(LinkHandle);
987
988 if (!NT_SUCCESS(Status))
989 {
990 return Status;
991 }
992
993 if (LinkTarget->Length <= sizeof(WCHAR))
994 {
995 return Status;
996 }
997
998 /* If it's not finished by \, just return */
999 if (LinkTarget->Buffer[LinkTarget->Length / sizeof(WCHAR) - 1] != L'\\')
1000 {
1001 return Status;
1002 }
1003
1004 /* Otherwise, ensure to drop the tailing \ */
1005 LinkTarget->Length -= sizeof(WCHAR);
1007
1008 return Status;
1009}
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 684 of file symlink.c.

687{
688 PIRP Irp;
691 USHORT NameLength;
695 PIO_STACK_LOCATION IoStackLocation;
696 PMOUNTDEV_SUGGESTED_LINK_NAME IoCtlSuggested;
697
698 /* First, get device */
701 &FileObject,
702 &DeviceObject);
703 if (!NT_SUCCESS(Status))
704 {
705 return Status;
706 }
707
708 /* Then, get attached device */
710
711 /* Then, prepare buffer to query suggested name */
712 IoCtlSuggested = AllocatePool(sizeof(MOUNTDEV_SUGGESTED_LINK_NAME));
713 if (!IoCtlSuggested)
714 {
716 goto Dereference;
717 }
718
719 /* Prepare request */
723 NULL,
724 0,
725 IoCtlSuggested,
727 FALSE,
728 &Event,
730 if (!Irp)
731 {
733 goto Release;
734 }
735
736 IoStackLocation = IoGetNextIrpStackLocation(Irp);
737 IoStackLocation->FileObject = FileObject;
738
739 /* And ask */
741 if (Status == STATUS_PENDING)
742 {
744 FALSE, NULL);
746 }
747
748 /* Overflow? Normal */
750 {
751 /* Reallocate big enough buffer */
752 NameLength = IoCtlSuggested->NameLength + sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
753 FreePool(IoCtlSuggested);
754
755 IoCtlSuggested = AllocatePool(NameLength);
756 if (!IoCtlSuggested)
757 {
759 goto Dereference;
760 }
761
762 /* And reask */
766 NULL,
767 0,
768 IoCtlSuggested,
769 NameLength,
770 FALSE,
771 &Event,
773 if (!Irp)
774 {
776 goto Release;
777 }
778
779 IoStackLocation = IoGetNextIrpStackLocation(Irp);
780 IoStackLocation->FileObject = FileObject;
781
783 if (Status == STATUS_PENDING)
784 {
786 FALSE, NULL);
788 }
789 }
790
791 if (!NT_SUCCESS(Status))
792 {
793 goto Release;
794 }
795
796 /* Now we have suggested name, copy it */
797 SuggestedLinkName->Length = IoCtlSuggested->NameLength;
798 SuggestedLinkName->MaximumLength = IoCtlSuggested->NameLength + sizeof(UNICODE_NULL);
799 SuggestedLinkName->Buffer = AllocatePool(IoCtlSuggested->NameLength + sizeof(UNICODE_NULL));
800 if (!SuggestedLinkName->Buffer)
801 {
803 }
804 else
805 {
806 RtlCopyMemory(SuggestedLinkName->Buffer, IoCtlSuggested->Name, IoCtlSuggested->NameLength);
807 SuggestedLinkName->Buffer[SuggestedLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL;
808 }
809
810 /* Also return its priority */
811 *UseOnlyIfThereAreNoOtherLinks = IoCtlSuggested->UseOnlyIfThereAreNoOtherLinks;
812
813Release:
814 FreePool(IoCtlSuggested);
815
816Dereference:
819
820 return Status;
821}
_In_ BOOLEAN Release
Definition: cdrom.h:920
_In_ PIRP Irp
Definition: csq.h:116
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
struct _MOUNTDEV_SUGGESTED_LINK_NAME MOUNTDEV_SUGGESTED_LINK_NAME
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define KernelMode
Definition: asm.h:34
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
@ NotificationEvent
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
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
#define STATUS_PENDING
Definition: ntstatus.h:82
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
* PFILE_OBJECT
Definition: iotypes.h:1998
@ Executive
Definition: ketypes.h:415
#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 514 of file symlink.c.

522{
524 BOOLEAN WriteNew;
526
527 UNREFERENCED_PARAMETER(DeviceExtension);
528
529 /* First of all, count links */
532 QueryTable[0].EntryContext = SymLinkCount;
533 *SymLinkCount = 0;
534
538 DeviceInformation->UniqueId,
539 NULL);
540 if (!NT_SUCCESS(Status))
541 {
542 *SymLinkCount = 0;
543 }
544
545 /* Check if we have to write a new one first */
546 if (SuggestedLinkName && !IsDriveLetter(SuggestedLinkName) &&
547 UseOnlyIfThereAreNoOtherLinks && *SymLinkCount == 0)
548 {
549 WriteNew = TRUE;
550 }
551 else
552 {
553 WriteNew = FALSE;
554 }
555
556 /* If has GUID, it makes one more link */
557 if (HasGuid)
558 {
559 (*SymLinkCount)++;
560 }
561
562 if (WriteNew)
563 {
564 /* Write link */
567 SuggestedLinkName->Buffer,
569 DeviceInformation->UniqueId->UniqueId,
570 DeviceInformation->UniqueId->UniqueIdLength);
571
572 /* And recount all the needed links */
575 QueryTable[0].EntryContext = SymLinkCount;
576 *SymLinkCount = 0;
577
581 DeviceInformation->UniqueId,
582 NULL);
583 if (!NT_SUCCESS(Status))
584 {
585 return STATUS_NOT_FOUND;
586 }
587 }
588
589 /* Not links found? */
590 if (!*SymLinkCount)
591 {
592 return STATUS_NOT_FOUND;
593 }
594
595 /* Allocate a buffer big enough to hold symlinks (table of unicode strings) */
596 *SymLinks = AllocatePool(*SymLinkCount * sizeof(UNICODE_STRING));
597 if (!*SymLinks)
598 {
600 }
601
602 /* Prepare to query links */
603 RtlZeroMemory(*SymLinks, *SymLinkCount * sizeof(UNICODE_STRING));
606
607 /* No GUID? Keep it that way */
608 if (!HasGuid)
609 {
610 QueryTable[0].EntryContext = *SymLinks;
611 }
612 /* Otherwise, first create volume name */
613 else
614 {
615 Status = CreateNewVolumeName(SymLinks[0], Guid);
616 if (!NT_SUCCESS(Status))
617 {
618 FreePool(*SymLinks);
619 return Status;
620 }
621
622 /* Skip first link (ours) */
623 QueryTable[0].EntryContext = *SymLinks + 1;
624 }
625
626 /* Now, query */
630 DeviceInformation->UniqueId,
631 NULL);
632
633 return STATUS_SUCCESS;
634}
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 827 of file symlink.c.

830{
831 PLIST_ENTRY NextEntry;
832 PSYMLINK_INFORMATION SymlinkInformation;
833
834 /* Find the link */
835 for (NextEntry = SavedLinkInformation->SymbolicLinksListHead.Flink;
836 NextEntry != &(SavedLinkInformation->SymbolicLinksListHead);
837 NextEntry = NextEntry->Flink)
838 {
839 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
840
841 if (!RtlEqualUnicodeString(DosName, &(SymlinkInformation->Name), TRUE))
842 {
843 /* Delete old link */
845 /* Set its new location */
847
848 /* And remove it from the list (not valid any more) */
849 RemoveEntryList(&(SymlinkInformation->SymbolicLinksListEntry));
850 FreePool(SymlinkInformation->Name.Buffer);
851 FreePool(SymlinkInformation);
852
853 return TRUE;
854 }
855 }
856
857 return FALSE;
858}
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 640 of file symlink.c.

642{
643 PLIST_ENTRY NextEntry;
644 PSAVED_LINK_INFORMATION SavedLinkInformation;
645
646 /* No saved links? Easy! */
647 if (IsListEmpty(&(DeviceExtension->SavedLinksListHead)))
648 {
649 return NULL;
650 }
651
652 /* Now, browse saved links */
653 for (NextEntry = DeviceExtension->SavedLinksListHead.Flink;
654 NextEntry != &(DeviceExtension->SavedLinksListHead);
655 NextEntry = NextEntry->Flink)
656 {
657 SavedLinkInformation = CONTAINING_RECORD(NextEntry,
659 SavedLinksListEntry);
660
661 /* Find the one that matches */
662 if (SavedLinkInformation->UniqueId->UniqueIdLength == UniqueId->UniqueIdLength)
663 {
664 if (RtlCompareMemory(SavedLinkInformation->UniqueId->UniqueId,
665 UniqueId->UniqueId,
666 UniqueId->UniqueIdLength) ==
667 UniqueId->UniqueIdLength)
668 {
669 /* Remove it and return it */
670 RemoveEntryList(&(SavedLinkInformation->SavedLinksListEntry));
671 return SavedLinkInformation;
672 }
673 }
674 }
675
676 /* None found (none removed) */
677 return NULL;
678}
#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 160 of file symlink.c.

161{
162 PIRP Irp;
164 ULONG NameSize;
171
172 /* Get the device associated with the name */
175 &FileObject,
176 &DeviceObject);
177 if (!NT_SUCCESS(Status))
178 {
179 return;
180 }
181
182 /* Get attached device (will notify it) */
184
185 /* NameSize is the size of the whole MOUNTDEV_NAME struct */
186 NameSize = sizeof(USHORT) + SymbolicName->Length;
187 Name = AllocatePool(NameSize);
188 if (!Name)
189 {
190 goto Cleanup;
191 }
192
193 /* Initialize struct */
194 Name->NameLength = SymbolicName->Length;
196
198 /* Microsoft does it twice... Once with limited access, second with any
199 * So, first one here
200 */
203 Name,
204 NameSize,
205 NULL,
206 0,
207 FALSE,
208 &Event,
210 /* This one can fail, no one matters */
211 if (Irp)
212 {
214 Stack->FileObject = FileObject;
215
217 if (Status == STATUS_PENDING)
218 {
220 }
221 }
222
223 /* Then, second one */
227 Name,
228 NameSize,
229 NULL,
230 0,
231 FALSE,
232 &Event,
234 if (!Irp)
235 {
236 goto Cleanup;
237 }
238
240 Stack->FileObject = FileObject;
241
242 /* Really notify */
244 if (Status == STATUS_PENDING)
245 {
247 }
248
249Cleanup:
250 if (Name)
251 {
252 FreePool(Name);
253 }
254
257
258 return;
259}
static const WCHAR Cleanup[]
Definition: register.c:80
#define IOCTL_MOUNTDEV_LINK_CREATED
Definition: imports.h:106
#define MOUNTDEVCONTROLTYPE
Definition: imports.h:78
#define CTL_CODE(DeviceType, Function, Method, Access)
Definition: nt_native.h:586
#define FILE_WRITE_ACCESS
Definition: nt_native.h:611
#define METHOD_BUFFERED
Definition: nt_native.h:594
#define FILE_READ_ACCESS
Definition: nt_native.h:610
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639

Referenced by MountMgrCreatePointWorker(), and MountMgrMountedDeviceArrival().

◆ SendLinkDeleted()

VOID SendLinkDeleted ( IN PUNICODE_STRING  DeviceName,
IN PUNICODE_STRING  SymbolicName 
)

Definition at line 265 of file symlink.c.

267{
268 PIRP Irp;
270 ULONG NameSize;
277
278 /* Get the device associated with the name */
281 &FileObject,
282 &DeviceObject);
283 if (!NT_SUCCESS(Status))
284 {
285 return;
286 }
287
288 /* Get attached device (will notify it) */
290
291 /* NameSize is the size of the whole MOUNTDEV_NAME struct */
292 NameSize = sizeof(USHORT) + SymbolicName->Length;
293 Name = AllocatePool(NameSize);
294 if (!Name)
295 {
296 goto Cleanup;
297 }
298
299 /* Initialize struct */
300 Name->NameLength = SymbolicName->Length;
302
304 /* Cf: SendLinkCreated comment */
307 Name,
308 NameSize,
309 NULL,
310 0,
311 FALSE,
312 &Event,
314 /* This one can fail, no one matters */
315 if (Irp)
316 {
318 Stack->FileObject = FileObject;
319
321 if (Status == STATUS_PENDING)
322 {
324 }
325 }
326
327 /* Then, second one */
331 Name,
332 NameSize,
333 NULL,
334 0,
335 FALSE,
336 &Event,
338 if (!Irp)
339 {
340 goto Cleanup;
341 }
342
344 Stack->FileObject = FileObject;
345
346 /* Really notify */
348 if (Status == STATUS_PENDING)
349 {
351 }
352
353Cleanup:
354 if (Name)
355 {
356 FreePool(Name);
357 }
358
361
362 return;
363}
#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 370 of file symlink.c.

376{
377 UNICODE_STRING ValueNameString;
378 PMOUNTDEV_UNIQUE_ID UniqueId = Context;
379
380 if (ValueName[0] != L'#' || ValueType != REG_BINARY ||
381 (UniqueId->UniqueIdLength != ValueLength))
382 {
383 return STATUS_SUCCESS;
384 }
385
387 {
388 return STATUS_SUCCESS;
389 }
390
391 /* That one matched, increase count */
392 RtlInitUnicodeString(&ValueNameString, ValueName);
393 if (ValueNameString.Length)
394 {
395 (*((PULONG)EntryContext))++;
396 }
397
398 return STATUS_SUCCESS;
399}
_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 406 of file symlink.c.

412{
413 UNICODE_STRING ValueNameString;
414 PMOUNTDEV_UNIQUE_ID UniqueId = Context;
415 /* Unicode strings table */
416 PUNICODE_STRING ReturnString = EntryContext;
417
418 if (ValueName[0] != L'#' || ValueType != REG_BINARY ||
419 (UniqueId->UniqueIdLength != ValueLength))
420 {
421 return STATUS_SUCCESS;
422 }
423
425 {
426 return STATUS_SUCCESS;
427 }
428
429 /* Unique ID matches, let's put the symlink */
430 RtlInitUnicodeString(&ValueNameString, ValueName);
431 if (!ValueNameString.Length)
432 {
433 return STATUS_SUCCESS;
434 }
435
436 /* Allocate string to copy */
437 ValueNameString.Buffer = AllocatePool(ValueNameString.MaximumLength);
438 if (!ValueNameString.Buffer)
439 {
440 return STATUS_SUCCESS;
441 }
442
443 /* Copy */
444 RtlCopyMemory(ValueNameString.Buffer, ValueName, ValueNameString.Length);
445 ValueNameString.Buffer[ValueNameString.Length / sizeof(WCHAR)] = UNICODE_NULL;
446
447 while (ReturnString->Length)
448 {
449 ReturnString++;
450 }
451
452 /* And return that string */
453 *ReturnString = ValueNameString;
454
455 return STATUS_SUCCESS;
456}

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 34 of file symlink.c.

Referenced by CreateNewDriveLetterName(), and MountMgrNextDriveLetterWorker().

◆ DeviceMount

Definition at line 31 of file symlink.c.

Referenced by DriverEntry().

◆ DosDevices

◆ DosDevicesMount

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

Definition at line 32 of file symlink.c.

Referenced by DriverEntry(), and MountMgrUnload().

◆ DosGlobal

Definition at line 36 of file symlink.c.

Referenced by CreateStringWithGlobal().

◆ Global

◆ ReparseIndex

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

Definition at line 40 of file symlink.c.

Referenced by OnlineMountedVolumes(), and ReconcileThisDatabaseWithMasterWorker().

◆ SafeVolumes

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

Definition at line 38 of file symlink.c.

Referenced by WorkerThread().

◆ Volume

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

Definition at line 39 of file symlink.c.

Referenced by CreateNewVolumeName().