1 /* $Id: symlink.c,v 1.25 2002/02/19 14:06:36 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/symlink.c
6 * PURPOSE: Implements symbolic links
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* INCLUDES *****************************************************************/
15 #include <ddk/ntddk.h>
16 #include <internal/pool.h>
19 #include <internal/debug.h>
21 /* GLOBALS ******************************************************************/
27 UNICODE_STRING TargetName
;
28 OBJECT_ATTRIBUTES Target
;
29 } SYMLNK_OBJECT
, *PSYMLNK_OBJECT
;
31 POBJECT_TYPE IoSymbolicLinkType
= NULL
;
33 static GENERIC_MAPPING IopSymbolicLinkMapping
= {
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 * IopCreateSymbolicLink
59 IopCreateSymbolicLink(PVOID Object
,
62 POBJECT_ATTRIBUTES ObjectAttributes
)
64 return(STATUS_SUCCESS
);
68 /**********************************************************************
70 * IopParseSymbolicLink
81 IopParseSymbolicLink(PVOID Object
,
83 PUNICODE_STRING FullPath
,
84 PWSTR
* RemainingPath
,
85 POBJECT_TYPE ObjectType
,
89 PSYMLNK_OBJECT SymlinkObject
= (PSYMLNK_OBJECT
) Object
;
91 UNICODE_STRING TargetPath
;
93 DPRINT("IopParseSymbolicLink (RemainingPath %S)\n", *RemainingPath
);
95 * Stop parsing if the entire path has been parsed and
96 * the desired object is a symbolic link object.
98 if (((*RemainingPath
== NULL
) || (**RemainingPath
== 0)) &&
99 (ObjectType
== IoSymbolicLinkType
))
101 DPRINT("Parsing stopped!\n");
103 return STATUS_SUCCESS
;
106 Status
= ObReferenceObjectByName(SymlinkObject
->Target
.ObjectName
,
109 STANDARD_RIGHTS_REQUIRED
,
114 if (NT_SUCCESS(Status
))
116 *NextObject
= ReturnedObject
;
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
;
149 /**********************************************************************
151 * IoInitSymbolicLinkImplementation
163 VOID
IoInitSymbolicLinkImplementation (VOID
)
165 IoSymbolicLinkType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
167 IoSymbolicLinkType
->Tag
= TAG('S', 'Y', 'M', 'T');
168 IoSymbolicLinkType
->TotalObjects
= 0;
169 IoSymbolicLinkType
->TotalHandles
= 0;
170 IoSymbolicLinkType
->MaxObjects
= ULONG_MAX
;
171 IoSymbolicLinkType
->MaxHandles
= ULONG_MAX
;
172 IoSymbolicLinkType
->PagedPoolCharge
= 0;
173 IoSymbolicLinkType
->NonpagedPoolCharge
= sizeof (SYMLNK_OBJECT
);
174 IoSymbolicLinkType
->Mapping
= &IopSymbolicLinkMapping
;
175 IoSymbolicLinkType
->Dump
= NULL
;
176 IoSymbolicLinkType
->Open
= NULL
;
177 IoSymbolicLinkType
->Close
= NULL
;
178 IoSymbolicLinkType
->Delete
= NULL
;
179 IoSymbolicLinkType
->Parse
= IopParseSymbolicLink
;
180 IoSymbolicLinkType
->Security
= NULL
;
181 IoSymbolicLinkType
->QueryName
= NULL
;
182 IoSymbolicLinkType
->OkayToClose
= NULL
;
183 IoSymbolicLinkType
->Create
= IopCreateSymbolicLink
;
184 IoSymbolicLinkType
->DuplicationNotify
= NULL
;
186 RtlInitUnicodeString(&IoSymbolicLinkType
->TypeName
,
191 /**********************************************************************
193 * NtOpenSymbolicLinkObject
205 NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle
,
206 IN ACCESS_MASK DesiredAccess
,
207 IN POBJECT_ATTRIBUTES ObjectAttributes
)
209 DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
210 ObjectAttributes
->ObjectName
);
212 return(ObOpenObjectByName(ObjectAttributes
,
222 /**********************************************************************
224 * NtQuerySymbolicLinkObject
236 NtQuerySymbolicLinkObject(IN HANDLE LinkHandle
,
237 IN OUT PUNICODE_STRING LinkTarget
,
238 OUT PULONG ReturnedLength OPTIONAL
)
240 PSYMLNK_OBJECT SymlinkObject
;
243 Status
= ObReferenceObjectByHandle(LinkHandle
,
247 (PVOID
*)&SymlinkObject
,
249 if (!NT_SUCCESS(Status
))
254 RtlCopyUnicodeString(LinkTarget
,
255 SymlinkObject
->Target
.ObjectName
);
256 if (ReturnedLength
!= NULL
)
258 *ReturnedLength
= SymlinkObject
->Target
.Length
;
260 ObDereferenceObject(SymlinkObject
);
262 return(STATUS_SUCCESS
);
266 /**********************************************************************
268 * IoCreateUnprotectedSymbolicLink
280 IoCreateUnprotectedSymbolicLink(PUNICODE_STRING SymbolicLinkName
,
281 PUNICODE_STRING DeviceName
)
283 return(IoCreateSymbolicLink(SymbolicLinkName
,
288 /**********************************************************************
290 * IoCreateSymbolicLink
302 IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName
,
303 PUNICODE_STRING DeviceName
)
305 OBJECT_ATTRIBUTES ObjectAttributes
;
306 PSYMLNK_OBJECT SymbolicLink
;
309 assert_irql(PASSIVE_LEVEL
);
312 "IoCreateSymbolicLink(SymbolicLinkName %S, DeviceName %S)\n",
313 SymbolicLinkName
->Buffer
,
317 InitializeObjectAttributes(
324 Status
= ObCreateObject(
326 SYMBOLIC_LINK_ALL_ACCESS
,
329 (PVOID
*)&SymbolicLink
331 if (!NT_SUCCESS(Status
))
335 SymbolicLink
->TargetName
.Length
= 0;
336 SymbolicLink
->TargetName
.MaximumLength
=
337 ((wcslen(DeviceName
->Buffer
) + 1) * sizeof(WCHAR
));
338 SymbolicLink
->TargetName
.Buffer
=
339 ExAllocatePoolWithTag(NonPagedPool
,
340 SymbolicLink
->TargetName
.MaximumLength
,
342 RtlCopyUnicodeString(
343 & (SymbolicLink
->TargetName
),
347 DPRINT("DeviceName %S\n", SymbolicLink
->TargetName
.Buffer
);
349 InitializeObjectAttributes(
350 & (SymbolicLink
->Target
),
351 & (SymbolicLink
->TargetName
),
357 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__
);
358 ObDereferenceObject( SymbolicLink
);
359 return STATUS_SUCCESS
;
363 /**********************************************************************
365 * IoDeleteSymbolicLink
377 IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName
)
379 OBJECT_ATTRIBUTES ObjectAttributes
;
383 assert_irql(PASSIVE_LEVEL
);
385 DPRINT("IoDeleteSymbolicLink (SymbolicLinkName %S)\n",
386 SymbolicLinkName
->Buffer
);
388 InitializeObjectAttributes (&ObjectAttributes
,
394 Status
= NtOpenSymbolicLinkObject (&Handle
,
395 SYMBOLIC_LINK_ALL_ACCESS
,
397 if (!NT_SUCCESS(Status
))
400 Status
= NtMakeTemporaryObject (Handle
);
407 /**********************************************************************
408 * NAME (EXPORTED as Zw)
409 * NtCreateSymbolicLinkObject
421 NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle
,
422 IN ACCESS_MASK DesiredAccess
,
423 IN POBJECT_ATTRIBUTES ObjectAttributes
,
424 IN PUNICODE_STRING DeviceName
)
426 PSYMLNK_OBJECT SymbolicLink
;
429 assert_irql(PASSIVE_LEVEL
);
431 DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %S)\n",
437 Status
= ObCreateObject(SymbolicLinkHandle
,
441 (PVOID
*)&SymbolicLink
);
442 if (!NT_SUCCESS(Status
))
447 SymbolicLink
->TargetName
.Length
= 0;
448 SymbolicLink
->TargetName
.MaximumLength
=
449 ((wcslen(DeviceName
->Buffer
) + 1) * sizeof(WCHAR
));
450 SymbolicLink
->TargetName
.Buffer
=
451 ExAllocatePoolWithTag(NonPagedPool
,
452 SymbolicLink
->TargetName
.MaximumLength
,
454 RtlCopyUnicodeString(&SymbolicLink
->TargetName
,
457 DPRINT("DeviceName %S\n", SymbolicLink
->TargetName
.Buffer
);
459 InitializeObjectAttributes(&SymbolicLink
->Target
,
460 &SymbolicLink
->TargetName
,
465 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__
);
466 ObDereferenceObject(SymbolicLink
);
467 return(STATUS_SUCCESS
);