3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/symlink.c
6 * PURPOSE: Implements symbolic links
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* INCLUDES *****************************************************************/
15 #include <ddk/ntddk.h>
16 #include <internal/pool.h>
19 #include <internal/debug.h>
21 /* GLOBALS ******************************************************************/
27 UNICODE_STRING TargetName;
28 OBJECT_ATTRIBUTES Target;
29 } SYMLNK_OBJECT, *PSYMLNK_OBJECT;
31 POBJECT_TYPE IoSymbolicLinkType = NULL;
33 static GENERIC_MAPPING IopSymbolicLinkMapping = {
34 STANDARD_RIGHTS_READ|SYMBOLIC_LINK_QUERY,
35 STANDARD_RIGHTS_WRITE,
36 STANDARD_RIGHTS_EXECUTE|SYMBOLIC_LINK_QUERY,
37 SYMBOLIC_LINK_ALL_ACCESS};
39 #define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
40 #define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
42 /* FUNCTIONS *****************************************************************/
45 /**********************************************************************
47 * IopCreateSymbolicLink
59 IopCreateSymbolicLink(PVOID Object,
62 POBJECT_ATTRIBUTES ObjectAttributes)
64 return(STATUS_SUCCESS);
68 /**********************************************************************
70 * IopParseSymbolicLink
81 IopParseSymbolicLink(PVOID Object,
83 PUNICODE_STRING FullPath,
84 PWSTR * RemainingPath,
87 PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT) Object;
88 UNICODE_STRING TargetPath;
90 DPRINT("IopParseSymbolicLink (RemainingPath %S)\n", *RemainingPath);
92 * Stop parsing if the entire path has been parsed and
93 * the desired object is a symbolic link object.
95 if (((*RemainingPath == NULL) || (**RemainingPath == 0)) &&
96 (Attributes & OBJ_OPENLINK))
98 DPRINT("Parsing stopped!\n");
100 return STATUS_SUCCESS;
103 /* build the expanded path */
104 TargetPath.MaximumLength = SymlinkObject->TargetName.Length + sizeof(WCHAR);
105 if (RemainingPath && *RemainingPath)
107 TargetPath.MaximumLength += (wcslen(*RemainingPath) * sizeof(WCHAR));
109 TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
110 TargetPath.Buffer = ExAllocatePoolWithTag(NonPagedPool,
111 TargetPath.MaximumLength,
112 TAG_SYMLINK_TTARGET);
113 wcscpy(TargetPath.Buffer, SymlinkObject->TargetName.Buffer);
114 if (RemainingPath && *RemainingPath)
116 wcscat(TargetPath.Buffer, *RemainingPath);
119 /* transfer target path buffer into FullPath */
120 RtlFreeUnicodeString(FullPath);
121 FullPath->Length = TargetPath.Length;
122 FullPath->MaximumLength = TargetPath.MaximumLength;
123 FullPath->Buffer = TargetPath.Buffer;
125 /* reinitialize RemainingPath for reparsing */
126 *RemainingPath = FullPath->Buffer;
129 return STATUS_REPARSE;
132 /**********************************************************************
134 * IoInitSymbolicLinkImplementation
146 VOID IoInitSymbolicLinkImplementation (VOID)
148 IoSymbolicLinkType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
150 IoSymbolicLinkType->Tag = TAG('S', 'Y', 'M', 'T');
151 IoSymbolicLinkType->TotalObjects = 0;
152 IoSymbolicLinkType->TotalHandles = 0;
153 IoSymbolicLinkType->MaxObjects = ULONG_MAX;
154 IoSymbolicLinkType->MaxHandles = ULONG_MAX;
155 IoSymbolicLinkType->PagedPoolCharge = 0;
156 IoSymbolicLinkType->NonpagedPoolCharge = sizeof (SYMLNK_OBJECT);
157 IoSymbolicLinkType->Mapping = &IopSymbolicLinkMapping;
158 IoSymbolicLinkType->Dump = NULL;
159 IoSymbolicLinkType->Open = NULL;
160 IoSymbolicLinkType->Close = NULL;
161 IoSymbolicLinkType->Delete = NULL;
162 IoSymbolicLinkType->Parse = IopParseSymbolicLink;
163 IoSymbolicLinkType->Security = NULL;
164 IoSymbolicLinkType->QueryName = NULL;
165 IoSymbolicLinkType->OkayToClose = NULL;
166 IoSymbolicLinkType->Create = IopCreateSymbolicLink;
167 IoSymbolicLinkType->DuplicationNotify = NULL;
169 RtlInitUnicodeStringFromLiteral(&IoSymbolicLinkType->TypeName,
174 /**********************************************************************
176 * NtOpenSymbolicLinkObject
188 NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle,
189 IN ACCESS_MASK DesiredAccess,
190 IN POBJECT_ATTRIBUTES ObjectAttributes)
192 DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
193 ObjectAttributes->ObjectName);
195 return(ObOpenObjectByName(ObjectAttributes,
205 /**********************************************************************
207 * NtQuerySymbolicLinkObject
219 NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
220 IN OUT PUNICODE_STRING LinkTarget,
221 OUT PULONG ReturnedLength OPTIONAL)
223 PSYMLNK_OBJECT SymlinkObject;
226 Status = ObReferenceObjectByHandle(LinkHandle,
230 (PVOID *)&SymlinkObject,
232 if (!NT_SUCCESS(Status))
237 RtlCopyUnicodeString(LinkTarget,
238 SymlinkObject->Target.ObjectName);
239 if (ReturnedLength != NULL)
241 *ReturnedLength = SymlinkObject->Target.Length;
243 ObDereferenceObject(SymlinkObject);
245 return(STATUS_SUCCESS);
249 /**********************************************************************
251 * IoCreateUnprotectedSymbolicLink
263 IoCreateUnprotectedSymbolicLink(PUNICODE_STRING SymbolicLinkName,
264 PUNICODE_STRING DeviceName)
266 return(IoCreateSymbolicLink(SymbolicLinkName,
271 /**********************************************************************
273 * IoCreateSymbolicLink
285 IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName,
286 PUNICODE_STRING DeviceName)
288 OBJECT_ATTRIBUTES ObjectAttributes;
289 PSYMLNK_OBJECT SymbolicLink;
292 assert_irql(PASSIVE_LEVEL);
295 "IoCreateSymbolicLink(SymbolicLinkName %S, DeviceName %S)\n",
296 SymbolicLinkName->Buffer,
300 InitializeObjectAttributes(
307 Status = ObCreateObject(
309 SYMBOLIC_LINK_ALL_ACCESS,
312 (PVOID*)&SymbolicLink
314 if (!NT_SUCCESS(Status))
318 SymbolicLink->TargetName.Length = 0;
319 SymbolicLink->TargetName.MaximumLength =
320 ((wcslen(DeviceName->Buffer) + 1) * sizeof(WCHAR));
321 SymbolicLink->TargetName.Buffer =
322 ExAllocatePoolWithTag(NonPagedPool,
323 SymbolicLink->TargetName.MaximumLength,
325 RtlCopyUnicodeString(
326 & (SymbolicLink->TargetName),
330 DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
332 InitializeObjectAttributes(
333 & (SymbolicLink->Target),
334 & (SymbolicLink->TargetName),
340 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
341 ObDereferenceObject( SymbolicLink );
342 return STATUS_SUCCESS;
346 /**********************************************************************
348 * IoDeleteSymbolicLink
360 IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName)
362 OBJECT_ATTRIBUTES ObjectAttributes;
366 assert_irql(PASSIVE_LEVEL);
368 DPRINT("IoDeleteSymbolicLink (SymbolicLinkName %S)\n",
369 SymbolicLinkName->Buffer);
371 InitializeObjectAttributes(&ObjectAttributes,
377 Status = NtOpenSymbolicLinkObject(&Handle,
378 SYMBOLIC_LINK_ALL_ACCESS,
380 if (!NT_SUCCESS(Status))
383 Status = NtMakeTemporaryObject(Handle);
390 /**********************************************************************
391 * NAME (EXPORTED as Zw)
392 * NtCreateSymbolicLinkObject
404 NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,
405 IN ACCESS_MASK DesiredAccess,
406 IN POBJECT_ATTRIBUTES ObjectAttributes,
407 IN PUNICODE_STRING DeviceName)
409 PSYMLNK_OBJECT SymbolicLink;
412 assert_irql(PASSIVE_LEVEL);
414 DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %S)\n",
420 Status = ObCreateObject(SymbolicLinkHandle,
424 (PVOID*)&SymbolicLink);
425 if (!NT_SUCCESS(Status))
430 SymbolicLink->TargetName.Length = 0;
431 SymbolicLink->TargetName.MaximumLength =
432 ((wcslen(DeviceName->Buffer) + 1) * sizeof(WCHAR));
433 SymbolicLink->TargetName.Buffer =
434 ExAllocatePoolWithTag(NonPagedPool,
435 SymbolicLink->TargetName.MaximumLength,
437 RtlCopyUnicodeString(&SymbolicLink->TargetName,
440 DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
442 InitializeObjectAttributes(&SymbolicLink->Target,
443 &SymbolicLink->TargetName,
448 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
449 ObDereferenceObject(SymbolicLink);
450 return(STATUS_SUCCESS);