Added ObGetObjectHandleCount().
[reactos.git] / reactos / ntoskrnl / io / symlink.c
1 /* $Id: symlink.c,v 1.25 2002/02/19 14:06:36 ekohl Exp $
2 *
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)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <limits.h>
15 #include <ddk/ntddk.h>
16 #include <internal/pool.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21 /* GLOBALS ******************************************************************/
22
23 typedef struct
24 {
25 CSHORT Type;
26 CSHORT Size;
27 UNICODE_STRING TargetName;
28 OBJECT_ATTRIBUTES Target;
29 } SYMLNK_OBJECT, *PSYMLNK_OBJECT;
30
31 POBJECT_TYPE IoSymbolicLinkType = NULL;
32
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};
38
39 #define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
40 #define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
41
42 /* FUNCTIONS *****************************************************************/
43
44
45 /**********************************************************************
46 * NAME INTERNAL
47 * IopCreateSymbolicLink
48 *
49 * DESCRIPTION
50 *
51 * ARGUMENTS
52 *
53 * RETURNN VALUE
54 * Status.
55 *
56 * REVISIONS
57 */
58 NTSTATUS STDCALL
59 IopCreateSymbolicLink(PVOID Object,
60 PVOID Parent,
61 PWSTR RemainingPath,
62 POBJECT_ATTRIBUTES ObjectAttributes)
63 {
64 return(STATUS_SUCCESS);
65 }
66
67
68 /**********************************************************************
69 * NAME INTERNAL
70 * IopParseSymbolicLink
71 *
72 * DESCRIPTION
73 *
74 * ARGUMENTS
75 *
76 * RETURN VALUE
77 *
78 * REVISIONS
79 */
80 NTSTATUS STDCALL
81 IopParseSymbolicLink(PVOID Object,
82 PVOID * NextObject,
83 PUNICODE_STRING FullPath,
84 PWSTR * RemainingPath,
85 POBJECT_TYPE ObjectType,
86 ULONG Attributes)
87 {
88 NTSTATUS Status;
89 PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT) Object;
90 PVOID ReturnedObject;
91 UNICODE_STRING TargetPath;
92
93 DPRINT("IopParseSymbolicLink (RemainingPath %S)\n", *RemainingPath);
94 /*
95 * Stop parsing if the entire path has been parsed and
96 * the desired object is a symbolic link object.
97 */
98 if (((*RemainingPath == NULL) || (**RemainingPath == 0)) &&
99 (ObjectType == IoSymbolicLinkType))
100 {
101 DPRINT("Parsing stopped!\n");
102 *NextObject = NULL;
103 return STATUS_SUCCESS;
104 }
105
106 Status = ObReferenceObjectByName(SymlinkObject->Target.ObjectName,
107 0,
108 NULL,
109 STANDARD_RIGHTS_REQUIRED,
110 NULL,
111 UserMode,
112 NULL,
113 &ReturnedObject);
114 if (NT_SUCCESS(Status))
115 {
116 *NextObject = ReturnedObject;
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 * NAME INTERNAL
151 * IoInitSymbolicLinkImplementation
152 *
153 * DESCRIPTION
154 *
155 * ARGUMENTS
156 * None.
157 *
158 * RETURNN VALUE
159 * None.
160 *
161 * REVISIONS
162 */
163 VOID IoInitSymbolicLinkImplementation (VOID)
164 {
165 IoSymbolicLinkType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
166
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;
185
186 RtlInitUnicodeString(&IoSymbolicLinkType->TypeName,
187 L"SymbolicLink");
188 }
189
190
191 /**********************************************************************
192 * NAME EXPORTED
193 * NtOpenSymbolicLinkObject
194 *
195 * DESCRIPTION
196 *
197 * ARGUMENTS
198 *
199 * RETURN VALUE
200 *
201 * REVISIONS
202 *
203 */
204 NTSTATUS STDCALL
205 NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle,
206 IN ACCESS_MASK DesiredAccess,
207 IN POBJECT_ATTRIBUTES ObjectAttributes)
208 {
209 DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
210 ObjectAttributes->ObjectName);
211
212 return(ObOpenObjectByName(ObjectAttributes,
213 IoSymbolicLinkType,
214 NULL,
215 UserMode,
216 DesiredAccess,
217 NULL,
218 LinkHandle));
219 }
220
221
222 /**********************************************************************
223 * NAME EXPORTED
224 * NtQuerySymbolicLinkObject
225 *
226 * DESCRIPTION
227 *
228 * ARGUMENTS
229 *
230 * RETURN VALUE
231 *
232 * REVISIONS
233 *
234 */
235 NTSTATUS STDCALL
236 NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
237 IN OUT PUNICODE_STRING LinkTarget,
238 OUT PULONG ReturnedLength OPTIONAL)
239 {
240 PSYMLNK_OBJECT SymlinkObject;
241 NTSTATUS Status;
242
243 Status = ObReferenceObjectByHandle(LinkHandle,
244 SYMBOLIC_LINK_QUERY,
245 IoSymbolicLinkType,
246 UserMode,
247 (PVOID *)&SymlinkObject,
248 NULL);
249 if (!NT_SUCCESS(Status))
250 {
251 return(Status);
252 }
253
254 RtlCopyUnicodeString(LinkTarget,
255 SymlinkObject->Target.ObjectName);
256 if (ReturnedLength != NULL)
257 {
258 *ReturnedLength = SymlinkObject->Target.Length;
259 }
260 ObDereferenceObject(SymlinkObject);
261
262 return(STATUS_SUCCESS);
263 }
264
265
266 /**********************************************************************
267 * NAME EXPORTED
268 * IoCreateUnprotectedSymbolicLink
269 *
270 * DESCRIPTION
271 *
272 * ARGUMENTS
273 *
274 * RETURN VALUE
275 *
276 * REVISIONS
277 *
278 */
279 NTSTATUS STDCALL
280 IoCreateUnprotectedSymbolicLink(PUNICODE_STRING SymbolicLinkName,
281 PUNICODE_STRING DeviceName)
282 {
283 return(IoCreateSymbolicLink(SymbolicLinkName,
284 DeviceName));
285 }
286
287
288 /**********************************************************************
289 * NAME EXPORTED
290 * IoCreateSymbolicLink
291 *
292 * DESCRIPTION
293 *
294 * ARGUMENTS
295 *
296 * RETURN VALUE
297 *
298 * REVISIONS
299 *
300 */
301 NTSTATUS STDCALL
302 IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName,
303 PUNICODE_STRING DeviceName)
304 {
305 OBJECT_ATTRIBUTES ObjectAttributes;
306 PSYMLNK_OBJECT SymbolicLink;
307 NTSTATUS Status;
308
309 assert_irql(PASSIVE_LEVEL);
310
311 DPRINT(
312 "IoCreateSymbolicLink(SymbolicLinkName %S, DeviceName %S)\n",
313 SymbolicLinkName->Buffer,
314 DeviceName->Buffer
315 );
316
317 InitializeObjectAttributes(
318 & ObjectAttributes,
319 SymbolicLinkName,
320 OBJ_PERMANENT,
321 NULL,
322 NULL
323 );
324 Status = ObCreateObject(
325 NULL,
326 SYMBOLIC_LINK_ALL_ACCESS,
327 & ObjectAttributes,
328 IoSymbolicLinkType,
329 (PVOID*)&SymbolicLink
330 );
331 if (!NT_SUCCESS(Status))
332 {
333 return(Status);
334 }
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,
341 TAG_SYMLINK_TARGET);
342 RtlCopyUnicodeString(
343 & (SymbolicLink->TargetName),
344 DeviceName
345 );
346
347 DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
348
349 InitializeObjectAttributes(
350 & (SymbolicLink->Target),
351 & (SymbolicLink->TargetName),
352 0,
353 NULL,
354 NULL
355 );
356
357 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
358 ObDereferenceObject( SymbolicLink );
359 return STATUS_SUCCESS;
360 }
361
362
363 /**********************************************************************
364 * NAME EXPORTED
365 * IoDeleteSymbolicLink
366 *
367 * DESCRIPTION
368 *
369 * ARGUMENTS
370 *
371 * RETURN VALUE
372 *
373 * REVISIONS
374 *
375 */
376 NTSTATUS STDCALL
377 IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName)
378 {
379 OBJECT_ATTRIBUTES ObjectAttributes;
380 HANDLE Handle;
381 NTSTATUS Status;
382
383 assert_irql(PASSIVE_LEVEL);
384
385 DPRINT("IoDeleteSymbolicLink (SymbolicLinkName %S)\n",
386 SymbolicLinkName->Buffer);
387
388 InitializeObjectAttributes (&ObjectAttributes,
389 SymbolicLinkName,
390 0,
391 NULL,
392 NULL);
393
394 Status = NtOpenSymbolicLinkObject (&Handle,
395 SYMBOLIC_LINK_ALL_ACCESS,
396 &ObjectAttributes);
397 if (!NT_SUCCESS(Status))
398 return Status;
399
400 Status = NtMakeTemporaryObject (Handle);
401 NtClose (Handle);
402
403 return Status;
404 }
405
406
407 /**********************************************************************
408 * NAME (EXPORTED as Zw)
409 * NtCreateSymbolicLinkObject
410 *
411 * DESCRIPTION
412 *
413 * ARGUMENTS
414 *
415 * RETURN VALUE
416 *
417 * REVISIONS
418 *
419 */
420 NTSTATUS STDCALL
421 NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,
422 IN ACCESS_MASK DesiredAccess,
423 IN POBJECT_ATTRIBUTES ObjectAttributes,
424 IN PUNICODE_STRING DeviceName)
425 {
426 PSYMLNK_OBJECT SymbolicLink;
427 NTSTATUS Status;
428
429 assert_irql(PASSIVE_LEVEL);
430
431 DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %S)\n",
432 SymbolicLinkHandle,
433 DesiredAccess,
434 ObjectAttributes,
435 DeviceName->Buffer);
436
437 Status = ObCreateObject(SymbolicLinkHandle,
438 DesiredAccess,
439 ObjectAttributes,
440 IoSymbolicLinkType,
441 (PVOID*)&SymbolicLink);
442 if (!NT_SUCCESS(Status))
443 {
444 return(Status);
445 }
446
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,
453 TAG_SYMLINK_TARGET);
454 RtlCopyUnicodeString(&SymbolicLink->TargetName,
455 DeviceName);
456
457 DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
458
459 InitializeObjectAttributes(&SymbolicLink->Target,
460 &SymbolicLink->TargetName,
461 0,
462 NULL,
463 NULL);
464
465 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
466 ObDereferenceObject(SymbolicLink);
467 return(STATUS_SUCCESS);
468 }
469
470 /* EOF */