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