- Moved symbolic link object type.
[reactos.git] / reactos / ntoskrnl / ob / symlink.c
1 /* $Id: symlink.c,v 1.6 2003/10/14 14:45:23 ekohl Exp $
2 *
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)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <limits.h>
15 #define NTOS_MODE_KERNEL
16 #include <ntos.h>
17 #include <internal/ob.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22
23 /* GLOBALS ******************************************************************/
24
25 POBJECT_TYPE ObSymbolicLinkType = NULL;
26
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};
32
33 #define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
34 #define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
35
36
37 /* FUNCTIONS ****************************************************************/
38
39 /**********************************************************************
40 * NAME INTERNAL
41 * ObpCreateSymbolicLink
42 *
43 * DESCRIPTION
44 *
45 * ARGUMENTS
46 *
47 * RETURNN VALUE
48 * Status.
49 *
50 * REVISIONS
51 */
52 NTSTATUS STDCALL
53 ObpCreateSymbolicLink(PVOID Object,
54 PVOID Parent,
55 PWSTR RemainingPath,
56 POBJECT_ATTRIBUTES ObjectAttributes)
57 {
58 return(STATUS_SUCCESS);
59 }
60
61
62 /**********************************************************************
63 * NAME INTERNAL
64 * ObpDeleteSymbolicLink
65 *
66 * DESCRIPTION
67 *
68 * ARGUMENTS
69 *
70 * RETURNN VALUE
71 * Status.
72 *
73 * REVISIONS
74 */
75 VOID STDCALL
76 ObpDeleteSymbolicLink(PVOID ObjectBody)
77 {
78 PSYMLINK_OBJECT SymlinkObject = (PSYMLINK_OBJECT)ObjectBody;
79
80 RtlFreeUnicodeString(&SymlinkObject->TargetName);
81 }
82
83
84 /**********************************************************************
85 * NAME INTERNAL
86 * ObpParseSymbolicLink
87 *
88 * DESCRIPTION
89 *
90 * ARGUMENTS
91 *
92 * RETURN VALUE
93 *
94 * REVISIONS
95 */
96 NTSTATUS STDCALL
97 ObpParseSymbolicLink(PVOID Object,
98 PVOID * NextObject,
99 PUNICODE_STRING FullPath,
100 PWSTR * RemainingPath,
101 ULONG Attributes)
102 {
103 PSYMLINK_OBJECT SymlinkObject = (PSYMLINK_OBJECT) Object;
104 UNICODE_STRING TargetPath;
105
106 DPRINT("ObpParseSymbolicLink (RemainingPath %S)\n", *RemainingPath);
107
108 /*
109 * Stop parsing if the entire path has been parsed and
110 * the desired object is a symbolic link object.
111 */
112 if (((*RemainingPath == NULL) || (**RemainingPath == 0)) &&
113 (Attributes & OBJ_OPENLINK))
114 {
115 DPRINT("Parsing stopped!\n");
116 *NextObject = NULL;
117 return(STATUS_SUCCESS);
118 }
119
120 /* build the expanded path */
121 TargetPath.MaximumLength = SymlinkObject->TargetName.Length + sizeof(WCHAR);
122 if (RemainingPath && *RemainingPath)
123 {
124 TargetPath.MaximumLength += (wcslen(*RemainingPath) * sizeof(WCHAR));
125 }
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)
132 {
133 wcscat(TargetPath.Buffer, *RemainingPath);
134 }
135
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;
141
142 /* reinitialize RemainingPath for reparsing */
143 *RemainingPath = FullPath->Buffer;
144
145 *NextObject = NULL;
146 return STATUS_REPARSE;
147 }
148
149
150 /**********************************************************************
151 * NAME INTERNAL
152 * ObInitSymbolicLinkImplementation
153 *
154 * DESCRIPTION
155 *
156 * ARGUMENTS
157 * None.
158 *
159 * RETURNN VALUE
160 * None.
161 *
162 * REVISIONS
163 */
164 VOID INIT_FUNCTION
165 ObInitSymbolicLinkImplementation (VOID)
166 {
167 ObSymbolicLinkType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
168
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;
187
188 RtlInitUnicodeStringFromLiteral(&ObSymbolicLinkType->TypeName,
189 L"SymbolicLink");
190
191 ObpCreateTypeObject(ObSymbolicLinkType);
192 }
193
194
195 /**********************************************************************
196 * NAME EXPORTED
197 * NtCreateSymbolicLinkObject
198 *
199 * DESCRIPTION
200 *
201 * ARGUMENTS
202 *
203 * RETURN VALUE
204 *
205 * REVISIONS
206 *
207 */
208 NTSTATUS STDCALL
209 NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,
210 IN ACCESS_MASK DesiredAccess,
211 IN POBJECT_ATTRIBUTES ObjectAttributes,
212 IN PUNICODE_STRING DeviceName)
213 {
214 PSYMLINK_OBJECT SymbolicLink;
215 NTSTATUS Status;
216
217 assert_irql(PASSIVE_LEVEL);
218
219 DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %wZ)\n",
220 SymbolicLinkHandle,
221 DesiredAccess,
222 ObjectAttributes,
223 DeviceName);
224
225 Status = ObCreateObject(ExGetPreviousMode(),
226 ObSymbolicLinkType,
227 ObjectAttributes,
228 ExGetPreviousMode(),
229 NULL,
230 sizeof(SYMLINK_OBJECT),
231 0,
232 0,
233 (PVOID*)&SymbolicLink);
234 if (!NT_SUCCESS(Status))
235 {
236 return(Status);
237 }
238
239 Status = ObInsertObject ((PVOID)SymbolicLink,
240 NULL,
241 DesiredAccess,
242 0,
243 NULL,
244 SymbolicLinkHandle);
245 if (!NT_SUCCESS(Status))
246 {
247 ObDereferenceObject (SymbolicLink);
248 return Status;
249 }
250
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,
257 TAG_SYMLINK_TARGET);
258 RtlCopyUnicodeString(&SymbolicLink->TargetName,
259 DeviceName);
260
261 DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
262
263 NtQuerySystemTime (&SymbolicLink->CreateTime);
264
265 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
266 ObDereferenceObject(SymbolicLink);
267
268 return(STATUS_SUCCESS);
269 }
270
271
272 /**********************************************************************
273 * NAME EXPORTED
274 * NtOpenSymbolicLinkObject
275 *
276 * DESCRIPTION
277 *
278 * ARGUMENTS
279 *
280 * RETURN VALUE
281 *
282 * REVISIONS
283 *
284 */
285 NTSTATUS STDCALL
286 NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle,
287 IN ACCESS_MASK DesiredAccess,
288 IN POBJECT_ATTRIBUTES ObjectAttributes)
289 {
290 DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
291 ObjectAttributes->ObjectName);
292
293 return(ObOpenObjectByName(ObjectAttributes,
294 ObSymbolicLinkType,
295 NULL,
296 KeGetPreviousMode(),
297 DesiredAccess,
298 NULL,
299 LinkHandle));
300 }
301
302
303 /**********************************************************************
304 * NAME EXPORTED
305 * NtQuerySymbolicLinkObject
306 *
307 * DESCRIPTION
308 *
309 * ARGUMENTS
310 *
311 * RETURN VALUE
312 *
313 * REVISIONS
314 *
315 */
316 NTSTATUS STDCALL
317 NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
318 IN OUT PUNICODE_STRING LinkTarget,
319 OUT PULONG ReturnedLength OPTIONAL)
320 {
321 PSYMLINK_OBJECT SymlinkObject;
322 NTSTATUS Status;
323
324 Status = ObReferenceObjectByHandle(LinkHandle,
325 SYMBOLIC_LINK_QUERY,
326 ObSymbolicLinkType,
327 KeGetPreviousMode(),
328 (PVOID *)&SymlinkObject,
329 NULL);
330 if (!NT_SUCCESS(Status))
331 {
332 return Status;
333 }
334
335 if (ReturnedLength != NULL)
336 {
337 *ReturnedLength = (ULONG)SymlinkObject->TargetName.Length + sizeof(WCHAR);
338 }
339
340 if (LinkTarget->MaximumLength >= SymlinkObject->TargetName.Length + sizeof(WCHAR))
341 {
342 RtlCopyUnicodeString(LinkTarget,
343 &SymlinkObject->TargetName);
344 Status = STATUS_SUCCESS;
345 }
346 else
347 {
348 Status = STATUS_BUFFER_TOO_SMALL;
349 }
350
351 ObDereferenceObject(SymlinkObject);
352
353 return Status;
354 }
355
356 /* EOF */