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