3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ob/symlink.c
6 * PURPOSE: Implements symbolic links
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* INCLUDES *****************************************************************/
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
19 #include <internal/debug.h>
21 /* GLOBALS ******************************************************************/
27 UNICODE_STRING TargetName;
28 OBJECT_ATTRIBUTES Target;
29 } SYMLNK_OBJECT, *PSYMLNK_OBJECT;
31 POBJECT_TYPE ObSymbolicLinkType = NULL;
33 static GENERIC_MAPPING ObpSymbolicLinkMapping = {
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 * ObpCreateSymbolicLink
59 ObpCreateSymbolicLink(PVOID Object,
62 POBJECT_ATTRIBUTES ObjectAttributes)
64 return(STATUS_SUCCESS);
68 /**********************************************************************
70 * ObpDeleteSymbolicLink
82 ObpDeleteSymbolicLink(PVOID ObjectBody)
84 PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT)ObjectBody;
86 RtlFreeUnicodeString(&SymlinkObject->TargetName);
90 /**********************************************************************
92 * ObpParseSymbolicLink
103 ObpParseSymbolicLink(PVOID Object,
105 PUNICODE_STRING FullPath,
106 PWSTR * RemainingPath,
109 PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT) Object;
110 UNICODE_STRING TargetPath;
112 DPRINT("ObpParseSymbolicLink (RemainingPath %S)\n", *RemainingPath);
115 * Stop parsing if the entire path has been parsed and
116 * the desired object is a symbolic link object.
118 if (((*RemainingPath == NULL) || (**RemainingPath == 0)) &&
119 (Attributes & OBJ_OPENLINK))
121 DPRINT("Parsing stopped!\n");
123 return(STATUS_SUCCESS);
126 /* build the expanded path */
127 TargetPath.MaximumLength = SymlinkObject->TargetName.Length + sizeof(WCHAR);
128 if (RemainingPath && *RemainingPath)
130 TargetPath.MaximumLength += (wcslen(*RemainingPath) * sizeof(WCHAR));
132 TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
133 TargetPath.Buffer = ExAllocatePoolWithTag(NonPagedPool,
134 TargetPath.MaximumLength,
135 TAG_SYMLINK_TTARGET);
136 wcscpy(TargetPath.Buffer, SymlinkObject->TargetName.Buffer);
137 if (RemainingPath && *RemainingPath)
139 wcscat(TargetPath.Buffer, *RemainingPath);
142 /* transfer target path buffer into FullPath */
143 RtlFreeUnicodeString(FullPath);
144 FullPath->Length = TargetPath.Length;
145 FullPath->MaximumLength = TargetPath.MaximumLength;
146 FullPath->Buffer = TargetPath.Buffer;
148 /* reinitialize RemainingPath for reparsing */
149 *RemainingPath = FullPath->Buffer;
152 return STATUS_REPARSE;
156 /**********************************************************************
158 * ObInitSymbolicLinkImplementation
170 VOID ObInitSymbolicLinkImplementation (VOID)
172 ObSymbolicLinkType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
174 ObSymbolicLinkType->Tag = TAG('S', 'Y', 'M', 'T');
175 ObSymbolicLinkType->TotalObjects = 0;
176 ObSymbolicLinkType->TotalHandles = 0;
177 ObSymbolicLinkType->MaxObjects = ULONG_MAX;
178 ObSymbolicLinkType->MaxHandles = ULONG_MAX;
179 ObSymbolicLinkType->PagedPoolCharge = 0;
180 ObSymbolicLinkType->NonpagedPoolCharge = sizeof(SYMLNK_OBJECT);
181 ObSymbolicLinkType->Mapping = &ObpSymbolicLinkMapping;
182 ObSymbolicLinkType->Dump = NULL;
183 ObSymbolicLinkType->Open = NULL;
184 ObSymbolicLinkType->Close = NULL;
185 ObSymbolicLinkType->Delete = ObpDeleteSymbolicLink;
186 ObSymbolicLinkType->Parse = ObpParseSymbolicLink;
187 ObSymbolicLinkType->Security = NULL;
188 ObSymbolicLinkType->QueryName = NULL;
189 ObSymbolicLinkType->OkayToClose = NULL;
190 ObSymbolicLinkType->Create = ObpCreateSymbolicLink;
191 ObSymbolicLinkType->DuplicationNotify = NULL;
193 RtlInitUnicodeStringFromLiteral(&ObSymbolicLinkType->TypeName,
196 ObpCreateTypeObject(ObSymbolicLinkType);
200 /**********************************************************************
202 * NtCreateSymbolicLinkObject
214 NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,
215 IN ACCESS_MASK DesiredAccess,
216 IN POBJECT_ATTRIBUTES ObjectAttributes,
217 IN PUNICODE_STRING DeviceName)
219 PSYMLNK_OBJECT SymbolicLink;
222 assert_irql(PASSIVE_LEVEL);
224 DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %wZ)\n",
230 Status = ObCreateObject(SymbolicLinkHandle,
234 (PVOID*)&SymbolicLink);
235 if (!NT_SUCCESS(Status))
240 SymbolicLink->TargetName.Length = 0;
241 SymbolicLink->TargetName.MaximumLength =
242 ((wcslen(DeviceName->Buffer) + 1) * sizeof(WCHAR));
243 SymbolicLink->TargetName.Buffer =
244 ExAllocatePoolWithTag(NonPagedPool,
245 SymbolicLink->TargetName.MaximumLength,
247 RtlCopyUnicodeString(&SymbolicLink->TargetName,
250 DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
252 InitializeObjectAttributes(&SymbolicLink->Target,
253 &SymbolicLink->TargetName,
258 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
259 ObDereferenceObject(SymbolicLink);
261 return(STATUS_SUCCESS);
265 /**********************************************************************
267 * NtOpenSymbolicLinkObject
279 NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle,
280 IN ACCESS_MASK DesiredAccess,
281 IN POBJECT_ATTRIBUTES ObjectAttributes)
283 DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
284 ObjectAttributes->ObjectName);
286 return(ObOpenObjectByName(ObjectAttributes,
296 /**********************************************************************
298 * NtQuerySymbolicLinkObject
310 NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
311 IN OUT PUNICODE_STRING LinkTarget,
312 OUT PULONG ReturnedLength OPTIONAL)
314 PSYMLNK_OBJECT SymlinkObject;
317 Status = ObReferenceObjectByHandle(LinkHandle,
321 (PVOID *)&SymlinkObject,
323 if (!NT_SUCCESS(Status))
328 RtlCopyUnicodeString(LinkTarget,
329 SymlinkObject->Target.ObjectName);
330 if (ReturnedLength != NULL)
332 *ReturnedLength = SymlinkObject->Target.Length;
334 ObDereferenceObject(SymlinkObject);
336 return(STATUS_SUCCESS);