ReactOS 0.4.15-dev-7942-gd23573b
symlink.c
Go to the documentation of this file.
1/*
2 * ReactOS kernel
3 * Copyright (C) 2011-2012 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/symlink.c
22 * PURPOSE: Mount Manager - Symbolic links functions
23 * PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
24 */
25
26#include "mntmgr.h"
27
28#define NDEBUG
29#include <debug.h>
30
32UNICODE_STRING DosDevicesMount = RTL_CONSTANT_STRING(L"\\DosDevices\\MountPointManager");
38UNICODE_STRING SafeVolumes = RTL_CONSTANT_STRING(L"\\Device\\VolumesSafeForWriteAccess");
40UNICODE_STRING ReparseIndex = RTL_CONSTANT_STRING(L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION");
41
42/*
43 * @implemented
44 */
47 OUT PUNICODE_STRING GlobalString)
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}
106
107/*
108 * @implemented
109 */
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}
131
132/*
133 * @implemented
134 */
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}
155
156/*
157 * @implemented
158 */
159VOID
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}
260
261/*
262 * @implemented
263 */
264VOID
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}
364
365/*
366 * @implemented
367 */
369NTAPI
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}
400
401/*
402 * @implemented
403 */
405NTAPI
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}
457
458/*
459 * @implemented
460 */
463 IN PGUID VolumeGuid OPTIONAL)
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}
509
510/*
511 * @implemented
512 */
515 IN PDEVICE_INFORMATION DeviceInformation,
516 IN PUNICODE_STRING SuggestedLinkName,
517 IN BOOLEAN UseOnlyIfThereAreNoOtherLinks,
518 OUT PUNICODE_STRING * SymLinks,
519 OUT PULONG SymLinkCount,
520 IN BOOLEAN HasGuid,
521 IN LPGUID Guid)
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}
635
636/*
637 * @implemented
638 */
641 IN PMOUNTDEV_UNIQUE_ID UniqueId)
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}
679
680/*
681 * @implemented
682 */
685 OUT PUNICODE_STRING SuggestedLinkName,
686 OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
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}
822
823/*
824 * @implemented
825 */
829 IN PUNICODE_STRING NewLink)
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}
859
860/*
861 * @implemented
862 */
863VOID
866 IN BOOLEAN MarkOffline)
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}
917
918/*
919 * @implemented
920 */
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}
954
955/*
956 * @implemented
957 */
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}
WCHAR Letter
unsigned char BOOLEAN
@ Colon
Definition: asmpp.cpp:43
LONG NTSTATUS
Definition: precomp.h:26
_In_ BOOLEAN Release
Definition: cdrom.h:920
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 GENERIC_READ
Definition: compat.h:135
static const WCHAR SymbolicLink[]
Definition: interface.c:31
static const WCHAR Cleanup[]
Definition: register.c:80
PWSTR DatabasePath
Definition: database.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 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
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
Status
Definition: gdiplustypes.h:25
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#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 RtlStringFromGUID(REFGUID, PUNICODE_STRING)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define FreePool(P)
Definition: mntmgr.h:154
NTKERNELAPI NTSTATUS ExUuidCreate(OUT UUID *Uuid)
Definition: uuid.c:380
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define IOCTL_MOUNTDEV_LINK_CREATED
Definition: imports.h:106
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
#define MOUNTDEVCONTROLTYPE
Definition: imports.h:78
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
#define IOCTL_MOUNTDEV_LINK_DELETED
Definition: imports.h:112
struct _MOUNTDEV_SUGGESTED_LINK_NAME MOUNTDEV_SUGGESTED_LINK_NAME
static PWSTR GuidString
Definition: apphelp.c:93
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_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)
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4207
_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 CTL_CODE(DeviceType, Function, Method, Access)
Definition: nt_native.h:586
#define REG_BINARY
Definition: nt_native.h:1496
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_WRITE_ACCESS
Definition: nt_native.h:611
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 METHOD_BUFFERED
Definition: nt_native.h:594
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define FILE_READ_ACCESS
Definition: nt_native.h:610
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
@ 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
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
LIST_ENTRY SymbolicLinksListHead
Definition: mntmgr.h:45
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT UniqueIdLength
Definition: imports.h:138
UCHAR UniqueId[1]
Definition: imports.h:139
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
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_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
_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
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
__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
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1269
__wchar_t WCHAR
Definition: xmlstorage.h:180
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292