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 *****************************************************************/
16 #include <internal/debug.h>
19 /* GLOBALS ******************************************************************/
21 POBJECT_TYPE ObSymbolicLinkType
= NULL
;
23 static GENERIC_MAPPING ObpSymbolicLinkMapping
= {
24 STANDARD_RIGHTS_READ
|SYMBOLIC_LINK_QUERY
,
25 STANDARD_RIGHTS_WRITE
,
26 STANDARD_RIGHTS_EXECUTE
|SYMBOLIC_LINK_QUERY
,
27 SYMBOLIC_LINK_ALL_ACCESS
};
29 #define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
30 #define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
33 /* FUNCTIONS ****************************************************************/
35 /**********************************************************************
37 * ObpCreateSymbolicLink
49 ObpCreateSymbolicLink(PVOID Object
,
52 POBJECT_ATTRIBUTES ObjectAttributes
)
54 return(STATUS_SUCCESS
);
58 /**********************************************************************
60 * ObpDeleteSymbolicLink
72 ObpDeleteSymbolicLink(PVOID ObjectBody
)
74 PSYMLINK_OBJECT SymlinkObject
= (PSYMLINK_OBJECT
)ObjectBody
;
76 RtlFreeUnicodeString(&SymlinkObject
->TargetName
);
80 /**********************************************************************
82 * ObpParseSymbolicLink
93 ObpParseSymbolicLink(PVOID Object
,
95 PUNICODE_STRING FullPath
,
96 PWSTR
* RemainingPath
,
99 PSYMLINK_OBJECT SymlinkObject
= (PSYMLINK_OBJECT
) Object
;
100 UNICODE_STRING TargetPath
;
102 DPRINT("ObpParseSymbolicLink (RemainingPath %S)\n", *RemainingPath
);
105 * Stop parsing if the entire path has been parsed and
106 * the desired object is a symbolic link object.
108 if (((*RemainingPath
== NULL
) || (**RemainingPath
== 0)) &&
109 (Attributes
& OBJ_OPENLINK
))
111 DPRINT("Parsing stopped!\n");
113 return(STATUS_SUCCESS
);
116 /* build the expanded path */
117 TargetPath
.MaximumLength
= SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
);
118 if (RemainingPath
&& *RemainingPath
)
120 TargetPath
.MaximumLength
+= (wcslen(*RemainingPath
) * sizeof(WCHAR
));
122 TargetPath
.Length
= TargetPath
.MaximumLength
- sizeof(WCHAR
);
123 TargetPath
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
124 TargetPath
.MaximumLength
,
125 TAG_SYMLINK_TTARGET
);
126 wcscpy(TargetPath
.Buffer
, SymlinkObject
->TargetName
.Buffer
);
127 if (RemainingPath
&& *RemainingPath
)
129 wcscat(TargetPath
.Buffer
, *RemainingPath
);
132 /* transfer target path buffer into FullPath */
133 RtlFreeUnicodeString(FullPath
);
134 FullPath
->Length
= TargetPath
.Length
;
135 FullPath
->MaximumLength
= TargetPath
.MaximumLength
;
136 FullPath
->Buffer
= TargetPath
.Buffer
;
138 /* reinitialize RemainingPath for reparsing */
139 *RemainingPath
= FullPath
->Buffer
;
142 return STATUS_REPARSE
;
146 /**********************************************************************
148 * ObInitSymbolicLinkImplementation
161 ObInitSymbolicLinkImplementation (VOID
)
163 ObSymbolicLinkType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
165 ObSymbolicLinkType
->Tag
= TAG('S', 'Y', 'M', 'T');
166 ObSymbolicLinkType
->TotalObjects
= 0;
167 ObSymbolicLinkType
->TotalHandles
= 0;
168 ObSymbolicLinkType
->PeakObjects
= 0;
169 ObSymbolicLinkType
->PeakHandles
= 0;
170 ObSymbolicLinkType
->PagedPoolCharge
= 0;
171 ObSymbolicLinkType
->NonpagedPoolCharge
= sizeof(SYMLINK_OBJECT
);
172 ObSymbolicLinkType
->Mapping
= &ObpSymbolicLinkMapping
;
173 ObSymbolicLinkType
->Dump
= NULL
;
174 ObSymbolicLinkType
->Open
= NULL
;
175 ObSymbolicLinkType
->Close
= NULL
;
176 ObSymbolicLinkType
->Delete
= ObpDeleteSymbolicLink
;
177 ObSymbolicLinkType
->Parse
= ObpParseSymbolicLink
;
178 ObSymbolicLinkType
->Security
= NULL
;
179 ObSymbolicLinkType
->QueryName
= NULL
;
180 ObSymbolicLinkType
->OkayToClose
= NULL
;
181 ObSymbolicLinkType
->Create
= ObpCreateSymbolicLink
;
182 ObSymbolicLinkType
->DuplicationNotify
= NULL
;
184 RtlRosInitUnicodeStringFromLiteral(&ObSymbolicLinkType
->TypeName
,
187 ObpCreateTypeObject(ObSymbolicLinkType
);
191 /**********************************************************************
193 * NtCreateSymbolicLinkObject
205 NtCreateSymbolicLinkObject(OUT PHANDLE LinkHandle
,
206 IN ACCESS_MASK DesiredAccess
,
207 IN POBJECT_ATTRIBUTES ObjectAttributes
,
208 IN PUNICODE_STRING LinkTarget
)
210 PSYMLINK_OBJECT SymbolicLink
;
213 ASSERT_IRQL(PASSIVE_LEVEL
);
215 DPRINT("NtCreateSymbolicLinkObject(LinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, LinkTarget %wZ)\n",
221 Status
= ObCreateObject(ExGetPreviousMode(),
226 sizeof(SYMLINK_OBJECT
),
229 (PVOID
*)&SymbolicLink
);
230 if (!NT_SUCCESS(Status
))
235 Status
= ObInsertObject ((PVOID
)SymbolicLink
,
241 if (!NT_SUCCESS(Status
))
243 ObDereferenceObject (SymbolicLink
);
247 SymbolicLink
->TargetName
.Length
= 0;
248 SymbolicLink
->TargetName
.MaximumLength
=
249 ((wcslen(LinkTarget
->Buffer
) + 1) * sizeof(WCHAR
));
250 SymbolicLink
->TargetName
.Buffer
=
251 ExAllocatePoolWithTag(NonPagedPool
,
252 SymbolicLink
->TargetName
.MaximumLength
,
254 RtlCopyUnicodeString(&SymbolicLink
->TargetName
,
257 DPRINT("DeviceName %S\n", SymbolicLink
->TargetName
.Buffer
);
259 NtQuerySystemTime (&SymbolicLink
->CreateTime
);
261 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__
);
262 ObDereferenceObject(SymbolicLink
);
264 return(STATUS_SUCCESS
);
268 /**********************************************************************
270 * NtOpenSymbolicLinkObject
282 NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle
,
283 IN ACCESS_MASK DesiredAccess
,
284 IN POBJECT_ATTRIBUTES ObjectAttributes
)
286 DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
287 ObjectAttributes
->ObjectName
);
289 return(ObOpenObjectByName(ObjectAttributes
,
292 (KPROCESSOR_MODE
)KeGetPreviousMode(),
299 /**********************************************************************
301 * NtQuerySymbolicLinkObject
313 NtQuerySymbolicLinkObject(IN HANDLE LinkHandle
,
314 OUT PUNICODE_STRING LinkTarget
,
315 OUT PULONG ResultLength OPTIONAL
)
317 PSYMLINK_OBJECT SymlinkObject
;
320 Status
= ObReferenceObjectByHandle(LinkHandle
,
323 (KPROCESSOR_MODE
)KeGetPreviousMode(),
324 (PVOID
*)&SymlinkObject
,
326 if (!NT_SUCCESS(Status
))
331 if (ResultLength
!= NULL
)
333 *ResultLength
= (ULONG
)SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
);
336 if (LinkTarget
->MaximumLength
>= SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
))
338 RtlCopyUnicodeString(LinkTarget
,
339 &SymlinkObject
->TargetName
);
340 Status
= STATUS_SUCCESS
;
344 Status
= STATUS_BUFFER_TOO_SMALL
;
347 ObDereferenceObject(SymlinkObject
);