ReactOS 0.4.15-dev-8434-g155a7c7
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
31/* Deprecated Windows 2000/XP versions of IOCTL_MOUNTDEV_LINK_[CREATED|DELETED]
32 * without access protection, that were updated in Windows 2003.
33 * They are sent to MountMgr clients if they do not recognize the new IOCTLs
34 * (e.g. they are for an older NT version). */
35#if (NTDDI_VERSION >= NTDDI_WS03)
36#define IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED CTL_CODE(MOUNTDEVCONTROLTYPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
37#define IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED CTL_CODE(MOUNTDEVCONTROLTYPE, 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
38#endif
39
41UNICODE_STRING DosDevicesMount = RTL_CONSTANT_STRING(L"\\DosDevices\\MountPointManager");
47UNICODE_STRING SafeVolumes = RTL_CONSTANT_STRING(L"\\Device\\VolumesSafeForWriteAccess");
49UNICODE_STRING ReparseIndex = RTL_CONSTANT_STRING(L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION");
50
51/*
52 * @implemented
53 */
56 OUT PUNICODE_STRING GlobalString)
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}
115
116/*
117 * @implemented
118 */
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}
140
141/*
142 * @implemented
143 */
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}
164
165/*
166 * @implemented
167 */
168VOID
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}
232
233/*
234 * @implemented
235 */
236VOID
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}
301
302/*
303 * @implemented
304 */
306NTAPI
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}
337
338/*
339 * @implemented
340 */
342NTAPI
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}
394
395/*
396 * @implemented
397 */
400 IN PGUID VolumeGuid OPTIONAL)
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}
446
447/*
448 * @implemented
449 */
452 IN PDEVICE_INFORMATION DeviceInformation,
453 IN PUNICODE_STRING SuggestedLinkName,
454 IN BOOLEAN UseOnlyIfThereAreNoOtherLinks,
455 OUT PUNICODE_STRING * SymLinks,
456 OUT PULONG SymLinkCount,
457 IN BOOLEAN HasGuid,
458 IN LPGUID Guid)
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}
572
573/*
574 * @implemented
575 */
578 IN PMOUNTDEV_UNIQUE_ID UniqueId)
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}
616
617/*
618 * @implemented
619 */
622 OUT PUNICODE_STRING SuggestedLinkName,
623 OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
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}
712
713/*
714 * @implemented
715 */
719 IN PUNICODE_STRING NewLink)
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}
749
750/*
751 * @implemented
752 */
753VOID
756 IN BOOLEAN MarkOffline)
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}
807
808/*
809 * @implemented
810 */
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}
844
845/*
846 * @implemented
847 */
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}
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
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define 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 RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
_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 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
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4677
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:4219
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4220
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define 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
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
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
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
#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
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
* PFILE_OBJECT
Definition: iotypes.h:1998
#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