1 /* $Id: symlink.c,v 1.6 2003/10/14 14:45:23 ekohl Exp $
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 #define NTOS_MODE_KERNEL
17 #include <internal/ob.h>
20 #include <internal/debug.h>
23 /* GLOBALS ******************************************************************/
25 POBJECT_TYPE ObSymbolicLinkType
= NULL
;
27 static GENERIC_MAPPING ObpSymbolicLinkMapping
= {
28 STANDARD_RIGHTS_READ
|SYMBOLIC_LINK_QUERY
,
29 STANDARD_RIGHTS_WRITE
,
30 STANDARD_RIGHTS_EXECUTE
|SYMBOLIC_LINK_QUERY
,
31 SYMBOLIC_LINK_ALL_ACCESS
};
33 #define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
34 #define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
37 /* FUNCTIONS ****************************************************************/
39 /**********************************************************************
41 * ObpCreateSymbolicLink
53 ObpCreateSymbolicLink(PVOID Object
,
56 POBJECT_ATTRIBUTES ObjectAttributes
)
58 return(STATUS_SUCCESS
);
62 /**********************************************************************
64 * ObpDeleteSymbolicLink
76 ObpDeleteSymbolicLink(PVOID ObjectBody
)
78 PSYMLINK_OBJECT SymlinkObject
= (PSYMLINK_OBJECT
)ObjectBody
;
80 RtlFreeUnicodeString(&SymlinkObject
->TargetName
);
84 /**********************************************************************
86 * ObpParseSymbolicLink
97 ObpParseSymbolicLink(PVOID Object
,
99 PUNICODE_STRING FullPath
,
100 PWSTR
* RemainingPath
,
103 PSYMLINK_OBJECT SymlinkObject
= (PSYMLINK_OBJECT
) Object
;
104 UNICODE_STRING TargetPath
;
106 DPRINT("ObpParseSymbolicLink (RemainingPath %S)\n", *RemainingPath
);
109 * Stop parsing if the entire path has been parsed and
110 * the desired object is a symbolic link object.
112 if (((*RemainingPath
== NULL
) || (**RemainingPath
== 0)) &&
113 (Attributes
& OBJ_OPENLINK
))
115 DPRINT("Parsing stopped!\n");
117 return(STATUS_SUCCESS
);
120 /* build the expanded path */
121 TargetPath
.MaximumLength
= SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
);
122 if (RemainingPath
&& *RemainingPath
)
124 TargetPath
.MaximumLength
+= (wcslen(*RemainingPath
) * sizeof(WCHAR
));
126 TargetPath
.Length
= TargetPath
.MaximumLength
- sizeof(WCHAR
);
127 TargetPath
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
128 TargetPath
.MaximumLength
,
129 TAG_SYMLINK_TTARGET
);
130 wcscpy(TargetPath
.Buffer
, SymlinkObject
->TargetName
.Buffer
);
131 if (RemainingPath
&& *RemainingPath
)
133 wcscat(TargetPath
.Buffer
, *RemainingPath
);
136 /* transfer target path buffer into FullPath */
137 RtlFreeUnicodeString(FullPath
);
138 FullPath
->Length
= TargetPath
.Length
;
139 FullPath
->MaximumLength
= TargetPath
.MaximumLength
;
140 FullPath
->Buffer
= TargetPath
.Buffer
;
142 /* reinitialize RemainingPath for reparsing */
143 *RemainingPath
= FullPath
->Buffer
;
146 return STATUS_REPARSE
;
150 /**********************************************************************
152 * ObInitSymbolicLinkImplementation
165 ObInitSymbolicLinkImplementation (VOID
)
167 ObSymbolicLinkType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
169 ObSymbolicLinkType
->Tag
= TAG('S', 'Y', 'M', 'T');
170 ObSymbolicLinkType
->TotalObjects
= 0;
171 ObSymbolicLinkType
->TotalHandles
= 0;
172 ObSymbolicLinkType
->MaxObjects
= ULONG_MAX
;
173 ObSymbolicLinkType
->MaxHandles
= ULONG_MAX
;
174 ObSymbolicLinkType
->PagedPoolCharge
= 0;
175 ObSymbolicLinkType
->NonpagedPoolCharge
= sizeof(SYMLINK_OBJECT
);
176 ObSymbolicLinkType
->Mapping
= &ObpSymbolicLinkMapping
;
177 ObSymbolicLinkType
->Dump
= NULL
;
178 ObSymbolicLinkType
->Open
= NULL
;
179 ObSymbolicLinkType
->Close
= NULL
;
180 ObSymbolicLinkType
->Delete
= ObpDeleteSymbolicLink
;
181 ObSymbolicLinkType
->Parse
= ObpParseSymbolicLink
;
182 ObSymbolicLinkType
->Security
= NULL
;
183 ObSymbolicLinkType
->QueryName
= NULL
;
184 ObSymbolicLinkType
->OkayToClose
= NULL
;
185 ObSymbolicLinkType
->Create
= ObpCreateSymbolicLink
;
186 ObSymbolicLinkType
->DuplicationNotify
= NULL
;
188 RtlInitUnicodeStringFromLiteral(&ObSymbolicLinkType
->TypeName
,
191 ObpCreateTypeObject(ObSymbolicLinkType
);
195 /**********************************************************************
197 * NtCreateSymbolicLinkObject
209 NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle
,
210 IN ACCESS_MASK DesiredAccess
,
211 IN POBJECT_ATTRIBUTES ObjectAttributes
,
212 IN PUNICODE_STRING DeviceName
)
214 PSYMLINK_OBJECT SymbolicLink
;
217 assert_irql(PASSIVE_LEVEL
);
219 DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %wZ)\n",
225 Status
= ObCreateObject(ExGetPreviousMode(),
230 sizeof(SYMLINK_OBJECT
),
233 (PVOID
*)&SymbolicLink
);
234 if (!NT_SUCCESS(Status
))
239 Status
= ObInsertObject ((PVOID
)SymbolicLink
,
245 if (!NT_SUCCESS(Status
))
247 ObDereferenceObject (SymbolicLink
);
251 SymbolicLink
->TargetName
.Length
= 0;
252 SymbolicLink
->TargetName
.MaximumLength
=
253 ((wcslen(DeviceName
->Buffer
) + 1) * sizeof(WCHAR
));
254 SymbolicLink
->TargetName
.Buffer
=
255 ExAllocatePoolWithTag(NonPagedPool
,
256 SymbolicLink
->TargetName
.MaximumLength
,
258 RtlCopyUnicodeString(&SymbolicLink
->TargetName
,
261 DPRINT("DeviceName %S\n", SymbolicLink
->TargetName
.Buffer
);
263 NtQuerySystemTime (&SymbolicLink
->CreateTime
);
265 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__
);
266 ObDereferenceObject(SymbolicLink
);
268 return(STATUS_SUCCESS
);
272 /**********************************************************************
274 * NtOpenSymbolicLinkObject
286 NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle
,
287 IN ACCESS_MASK DesiredAccess
,
288 IN POBJECT_ATTRIBUTES ObjectAttributes
)
290 DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
291 ObjectAttributes
->ObjectName
);
293 return(ObOpenObjectByName(ObjectAttributes
,
303 /**********************************************************************
305 * NtQuerySymbolicLinkObject
317 NtQuerySymbolicLinkObject(IN HANDLE LinkHandle
,
318 IN OUT PUNICODE_STRING LinkTarget
,
319 OUT PULONG ReturnedLength OPTIONAL
)
321 PSYMLINK_OBJECT SymlinkObject
;
324 Status
= ObReferenceObjectByHandle(LinkHandle
,
328 (PVOID
*)&SymlinkObject
,
330 if (!NT_SUCCESS(Status
))
335 if (ReturnedLength
!= NULL
)
337 *ReturnedLength
= (ULONG
)SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
);
340 if (LinkTarget
->MaximumLength
>= SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
))
342 RtlCopyUnicodeString(LinkTarget
,
343 &SymlinkObject
->TargetName
);
344 Status
= STATUS_SUCCESS
;
348 Status
= STATUS_BUFFER_TOO_SMALL
;
351 ObDereferenceObject(SymlinkObject
);