1 /* $Id: symlink.c,v 1.8 2003/12/30 18:52:05 fireball 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>
18 #include <rosrtl/string.h>
21 #include <internal/debug.h>
24 /* GLOBALS ******************************************************************/
26 POBJECT_TYPE ObSymbolicLinkType
= NULL
;
28 static GENERIC_MAPPING ObpSymbolicLinkMapping
= {
29 STANDARD_RIGHTS_READ
|SYMBOLIC_LINK_QUERY
,
30 STANDARD_RIGHTS_WRITE
,
31 STANDARD_RIGHTS_EXECUTE
|SYMBOLIC_LINK_QUERY
,
32 SYMBOLIC_LINK_ALL_ACCESS
};
34 #define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
35 #define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
38 /* FUNCTIONS ****************************************************************/
40 /**********************************************************************
42 * ObpCreateSymbolicLink
54 ObpCreateSymbolicLink(PVOID Object
,
57 POBJECT_ATTRIBUTES ObjectAttributes
)
59 return(STATUS_SUCCESS
);
63 /**********************************************************************
65 * ObpDeleteSymbolicLink
77 ObpDeleteSymbolicLink(PVOID ObjectBody
)
79 PSYMLINK_OBJECT SymlinkObject
= (PSYMLINK_OBJECT
)ObjectBody
;
81 RtlFreeUnicodeString(&SymlinkObject
->TargetName
);
85 /**********************************************************************
87 * ObpParseSymbolicLink
98 ObpParseSymbolicLink(PVOID Object
,
100 PUNICODE_STRING FullPath
,
101 PWSTR
* RemainingPath
,
104 PSYMLINK_OBJECT SymlinkObject
= (PSYMLINK_OBJECT
) Object
;
105 UNICODE_STRING TargetPath
;
107 DPRINT("ObpParseSymbolicLink (RemainingPath %S)\n", *RemainingPath
);
110 * Stop parsing if the entire path has been parsed and
111 * the desired object is a symbolic link object.
113 if (((*RemainingPath
== NULL
) || (**RemainingPath
== 0)) &&
114 (Attributes
& OBJ_OPENLINK
))
116 DPRINT("Parsing stopped!\n");
118 return(STATUS_SUCCESS
);
121 /* build the expanded path */
122 TargetPath
.MaximumLength
= SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
);
123 if (RemainingPath
&& *RemainingPath
)
125 TargetPath
.MaximumLength
+= (wcslen(*RemainingPath
) * sizeof(WCHAR
));
127 TargetPath
.Length
= TargetPath
.MaximumLength
- sizeof(WCHAR
);
128 TargetPath
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
129 TargetPath
.MaximumLength
,
130 TAG_SYMLINK_TTARGET
);
131 wcscpy(TargetPath
.Buffer
, SymlinkObject
->TargetName
.Buffer
);
132 if (RemainingPath
&& *RemainingPath
)
134 wcscat(TargetPath
.Buffer
, *RemainingPath
);
137 /* transfer target path buffer into FullPath */
138 RtlFreeUnicodeString(FullPath
);
139 FullPath
->Length
= TargetPath
.Length
;
140 FullPath
->MaximumLength
= TargetPath
.MaximumLength
;
141 FullPath
->Buffer
= TargetPath
.Buffer
;
143 /* reinitialize RemainingPath for reparsing */
144 *RemainingPath
= FullPath
->Buffer
;
147 return STATUS_REPARSE
;
151 /**********************************************************************
153 * ObInitSymbolicLinkImplementation
166 ObInitSymbolicLinkImplementation (VOID
)
168 ObSymbolicLinkType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
170 ObSymbolicLinkType
->Tag
= TAG('S', 'Y', 'M', 'T');
171 ObSymbolicLinkType
->TotalObjects
= 0;
172 ObSymbolicLinkType
->TotalHandles
= 0;
173 ObSymbolicLinkType
->MaxObjects
= ULONG_MAX
;
174 ObSymbolicLinkType
->MaxHandles
= ULONG_MAX
;
175 ObSymbolicLinkType
->PagedPoolCharge
= 0;
176 ObSymbolicLinkType
->NonpagedPoolCharge
= sizeof(SYMLINK_OBJECT
);
177 ObSymbolicLinkType
->Mapping
= &ObpSymbolicLinkMapping
;
178 ObSymbolicLinkType
->Dump
= NULL
;
179 ObSymbolicLinkType
->Open
= NULL
;
180 ObSymbolicLinkType
->Close
= NULL
;
181 ObSymbolicLinkType
->Delete
= ObpDeleteSymbolicLink
;
182 ObSymbolicLinkType
->Parse
= ObpParseSymbolicLink
;
183 ObSymbolicLinkType
->Security
= NULL
;
184 ObSymbolicLinkType
->QueryName
= NULL
;
185 ObSymbolicLinkType
->OkayToClose
= NULL
;
186 ObSymbolicLinkType
->Create
= ObpCreateSymbolicLink
;
187 ObSymbolicLinkType
->DuplicationNotify
= NULL
;
189 RtlRosInitUnicodeStringFromLiteral(&ObSymbolicLinkType
->TypeName
,
192 ObpCreateTypeObject(ObSymbolicLinkType
);
196 /**********************************************************************
198 * NtCreateSymbolicLinkObject
210 NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle
,
211 IN ACCESS_MASK DesiredAccess
,
212 IN POBJECT_ATTRIBUTES ObjectAttributes
,
213 IN PUNICODE_STRING DeviceName
)
215 PSYMLINK_OBJECT SymbolicLink
;
218 assert_irql(PASSIVE_LEVEL
);
220 DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %wZ)\n",
226 Status
= ObCreateObject(ExGetPreviousMode(),
231 sizeof(SYMLINK_OBJECT
),
234 (PVOID
*)&SymbolicLink
);
235 if (!NT_SUCCESS(Status
))
240 Status
= ObInsertObject ((PVOID
)SymbolicLink
,
246 if (!NT_SUCCESS(Status
))
248 ObDereferenceObject (SymbolicLink
);
252 SymbolicLink
->TargetName
.Length
= 0;
253 SymbolicLink
->TargetName
.MaximumLength
=
254 ((wcslen(DeviceName
->Buffer
) + 1) * sizeof(WCHAR
));
255 SymbolicLink
->TargetName
.Buffer
=
256 ExAllocatePoolWithTag(NonPagedPool
,
257 SymbolicLink
->TargetName
.MaximumLength
,
259 RtlCopyUnicodeString(&SymbolicLink
->TargetName
,
262 DPRINT("DeviceName %S\n", SymbolicLink
->TargetName
.Buffer
);
264 NtQuerySystemTime (&SymbolicLink
->CreateTime
);
266 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__
);
267 ObDereferenceObject(SymbolicLink
);
269 return(STATUS_SUCCESS
);
273 /**********************************************************************
275 * NtOpenSymbolicLinkObject
287 NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle
,
288 IN ACCESS_MASK DesiredAccess
,
289 IN POBJECT_ATTRIBUTES ObjectAttributes
)
291 DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
292 ObjectAttributes
->ObjectName
);
294 return(ObOpenObjectByName(ObjectAttributes
,
297 (KPROCESSOR_MODE
)KeGetPreviousMode(),
304 /**********************************************************************
306 * NtQuerySymbolicLinkObject
318 NtQuerySymbolicLinkObject(IN HANDLE LinkHandle
,
319 IN OUT PUNICODE_STRING LinkTarget
,
320 OUT PULONG ReturnedLength OPTIONAL
)
322 PSYMLINK_OBJECT SymlinkObject
;
325 Status
= ObReferenceObjectByHandle(LinkHandle
,
328 (KPROCESSOR_MODE
)KeGetPreviousMode(),
329 (PVOID
*)&SymlinkObject
,
331 if (!NT_SUCCESS(Status
))
336 if (ReturnedLength
!= NULL
)
338 *ReturnedLength
= (ULONG
)SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
);
341 if (LinkTarget
->MaximumLength
>= SymlinkObject
->TargetName
.Length
+ sizeof(WCHAR
))
343 RtlCopyUnicodeString(LinkTarget
,
344 &SymlinkObject
->TargetName
);
345 Status
= STATUS_SUCCESS
;
349 Status
= STATUS_BUFFER_TOO_SMALL
;
352 ObDereferenceObject(SymlinkObject
);