@implemented and @unimplemented comments for ntoskrnl/ob/*.c
[reactos.git] / reactos / ntoskrnl / ob / namespc.c
1 /* $Id: namespc.c,v 1.39 2003/07/10 21:34:29 royce Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ob/namespc.c
6 * PURPOSE: Manages the system namespace
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * 22/05/98: Created
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 <internal/io.h>
19 #include <internal/pool.h>
20
21 #define NDEBUG
22 #include <internal/debug.h>
23
24
25 /* GLOBALS ****************************************************************/
26
27 POBJECT_TYPE ObDirectoryType = NULL;
28 POBJECT_TYPE ObTypeObjectType = NULL;
29
30 PDIRECTORY_OBJECT NameSpaceRoot = NULL;
31
32 static GENERIC_MAPPING ObpDirectoryMapping = {
33 STANDARD_RIGHTS_READ|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
34 STANDARD_RIGHTS_WRITE|DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY,
35 STANDARD_RIGHTS_EXECUTE|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
36 DIRECTORY_ALL_ACCESS};
37
38 static GENERIC_MAPPING ObpTypeMapping = {
39 STANDARD_RIGHTS_READ,
40 STANDARD_RIGHTS_WRITE,
41 STANDARD_RIGHTS_EXECUTE,
42 0x000F0001};
43
44 /* FUNCTIONS **************************************************************/
45
46 /*
47 * @implemented
48 */
49 NTSTATUS STDCALL
50 ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
51 ULONG Attributes,
52 PACCESS_STATE PassedAccessState,
53 ACCESS_MASK DesiredAccess,
54 POBJECT_TYPE ObjectType,
55 KPROCESSOR_MODE AccessMode,
56 PVOID ParseContext,
57 PVOID* ObjectPtr)
58 {
59 PVOID Object = NULL;
60 UNICODE_STRING RemainingPath;
61 OBJECT_ATTRIBUTES ObjectAttributes;
62 NTSTATUS Status;
63
64 InitializeObjectAttributes(&ObjectAttributes,
65 ObjectPath,
66 Attributes,
67 NULL,
68 NULL);
69 Status = ObFindObject(&ObjectAttributes,
70 &Object,
71 &RemainingPath,
72 ObjectType);
73 if (!NT_SUCCESS(Status))
74 {
75 return(Status);
76 }
77 CHECKPOINT;
78 DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
79
80 if (RemainingPath.Buffer != NULL || Object == NULL)
81 {
82 CHECKPOINT;
83 DPRINT("Object %p\n", Object);
84 *ObjectPtr = NULL;
85 RtlFreeUnicodeString (&RemainingPath);
86 return(STATUS_UNSUCCESSFUL);
87 }
88 *ObjectPtr = Object;
89 RtlFreeUnicodeString (&RemainingPath);
90 return(STATUS_SUCCESS);
91 }
92
93
94 /**********************************************************************
95 * NAME EXPORTED
96 * ObOpenObjectByName
97 *
98 * DESCRIPTION
99 * Obtain a handle to an existing object.
100 *
101 * ARGUMENTS
102 * ObjectAttributes
103 * ...
104 * ObjectType
105 * ...
106 * ParseContext
107 * ...
108 * AccessMode
109 * ...
110 * DesiredAccess
111 * ...
112 * PassedAccessState
113 * ...
114 * Handle
115 * Handle to close.
116 *
117 * RETURN VALUE
118 * Status.
119 *
120 * @implemented
121 */
122 NTSTATUS STDCALL
123 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
124 IN POBJECT_TYPE ObjectType,
125 IN OUT PVOID ParseContext,
126 IN KPROCESSOR_MODE AccessMode,
127 IN ACCESS_MASK DesiredAccess,
128 IN PACCESS_STATE PassedAccessState,
129 OUT PHANDLE Handle)
130 {
131 UNICODE_STRING RemainingPath;
132 PVOID Object = NULL;
133 NTSTATUS Status;
134
135 DPRINT("ObOpenObjectByName(...)\n");
136
137 Status = ObFindObject(ObjectAttributes,
138 &Object,
139 &RemainingPath,
140 ObjectType);
141 if (!NT_SUCCESS(Status))
142 {
143 DPRINT("ObFindObject() failed (Status %lx)\n", Status);
144 return Status;
145 }
146
147 if (RemainingPath.Buffer != NULL ||
148 Object == NULL)
149 {
150 RtlFreeUnicodeString(&RemainingPath);
151 return STATUS_UNSUCCESSFUL;
152 }
153
154 Status = ObCreateHandle(PsGetCurrentProcess(),
155 Object,
156 DesiredAccess,
157 FALSE,
158 Handle);
159
160 ObDereferenceObject(Object);
161 RtlFreeUnicodeString(&RemainingPath);
162
163 return Status;
164 }
165
166
167 VOID
168 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
169 POBJECT_HEADER Header,
170 PWSTR Name)
171 /*
172 * FUNCTION: Add an entry to a namespace directory
173 * ARGUMENTS:
174 * Parent = directory to add in
175 * Header = Header of the object to add the entry for
176 * Name = Name to give the entry
177 */
178 {
179 KIRQL oldlvl;
180
181 RtlCreateUnicodeString(&Header->Name, Name);
182 Header->Parent = Parent;
183
184 KeAcquireSpinLock(&Parent->Lock, &oldlvl);
185 InsertTailList(&Parent->head, &Header->Entry);
186 KeReleaseSpinLock(&Parent->Lock, oldlvl);
187 }
188
189
190 VOID
191 ObpRemoveEntryDirectory(POBJECT_HEADER Header)
192 /*
193 * FUNCTION: Remove an entry from a namespace directory
194 * ARGUMENTS:
195 * Header = Header of the object to remove
196 */
197 {
198 KIRQL oldlvl;
199
200 DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
201
202 KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);
203 RemoveEntryList(&(Header->Entry));
204 KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl);
205 }
206
207
208 PVOID
209 ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
210 PWSTR Name,
211 ULONG Attributes)
212 {
213 PLIST_ENTRY current = DirectoryObject->head.Flink;
214 POBJECT_HEADER current_obj;
215
216 DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
217
218 if (Name[0]==0)
219 {
220 return(DirectoryObject);
221 }
222 if (Name[0]=='.' && Name[1]==0)
223 {
224 return(DirectoryObject);
225 }
226 if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
227 {
228 return(BODY_TO_HEADER(DirectoryObject)->Parent);
229 }
230 while (current!=(&(DirectoryObject->head)))
231 {
232 current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
233 DPRINT(" Scanning: %S for: %S\n",current_obj->Name.Buffer, Name);
234 if (Attributes & OBJ_CASE_INSENSITIVE)
235 {
236 if (_wcsicmp(current_obj->Name.Buffer, Name)==0)
237 {
238 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
239 return(HEADER_TO_BODY(current_obj));
240 }
241 }
242 else
243 {
244 if ( wcscmp(current_obj->Name.Buffer, Name)==0)
245 {
246 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
247 return(HEADER_TO_BODY(current_obj));
248 }
249 }
250 current = current->Flink;
251 }
252 DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__);
253 return(NULL);
254 }
255
256
257 NTSTATUS STDCALL
258 ObpParseDirectory(PVOID Object,
259 PVOID * NextObject,
260 PUNICODE_STRING FullPath,
261 PWSTR * Path,
262 ULONG Attributes)
263 {
264 PWSTR Start;
265 PWSTR End;
266 PVOID FoundObject;
267
268 DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
269 Object,Path,*Path);
270
271 *NextObject = NULL;
272
273 if ((*Path) == NULL)
274 {
275 return STATUS_UNSUCCESSFUL;
276 }
277
278 Start = *Path;
279 if (*Start == L'\\')
280 Start++;
281
282 End = wcschr(Start, L'\\');
283 if (End != NULL)
284 {
285 *End = 0;
286 }
287
288 FoundObject = ObpFindEntryDirectory(Object, Start, Attributes);
289 if (FoundObject == NULL)
290 {
291 if (End != NULL)
292 {
293 *End = L'\\';
294 }
295 return STATUS_UNSUCCESSFUL;
296 }
297
298 ObReferenceObjectByPointer(FoundObject,
299 STANDARD_RIGHTS_REQUIRED,
300 NULL,
301 UserMode);
302
303 if (End != NULL)
304 {
305 *End = L'\\';
306 *Path = End;
307 }
308 else
309 {
310 *Path = NULL;
311 }
312
313 *NextObject = FoundObject;
314
315 return STATUS_SUCCESS;
316 }
317
318
319 NTSTATUS STDCALL
320 ObpCreateDirectory(PVOID ObjectBody,
321 PVOID Parent,
322 PWSTR RemainingPath,
323 POBJECT_ATTRIBUTES ObjectAttributes)
324 {
325 PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody;
326
327 DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n",
328 ObjectBody, Parent, RemainingPath);
329
330 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
331 {
332 return(STATUS_UNSUCCESSFUL);
333 }
334
335 InitializeListHead(&DirectoryObject->head);
336 KeInitializeSpinLock(&DirectoryObject->Lock);
337
338 return(STATUS_SUCCESS);
339 }
340
341
342 VOID
343 ObInit(VOID)
344 /*
345 * FUNCTION: Initialize the object manager namespace
346 */
347 {
348 OBJECT_ATTRIBUTES ObjectAttributes;
349 UNICODE_STRING Name;
350
351 /* create 'directory' object type */
352 ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
353
354 ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T');
355 ObDirectoryType->TotalObjects = 0;
356 ObDirectoryType->TotalHandles = 0;
357 ObDirectoryType->MaxObjects = ULONG_MAX;
358 ObDirectoryType->MaxHandles = ULONG_MAX;
359 ObDirectoryType->PagedPoolCharge = 0;
360 ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
361 ObDirectoryType->Mapping = &ObpDirectoryMapping;
362 ObDirectoryType->Dump = NULL;
363 ObDirectoryType->Open = NULL;
364 ObDirectoryType->Close = NULL;
365 ObDirectoryType->Delete = NULL;
366 ObDirectoryType->Parse = ObpParseDirectory;
367 ObDirectoryType->Security = NULL;
368 ObDirectoryType->QueryName = NULL;
369 ObDirectoryType->OkayToClose = NULL;
370 ObDirectoryType->Create = ObpCreateDirectory;
371 ObDirectoryType->DuplicationNotify = NULL;
372
373 RtlInitUnicodeStringFromLiteral(&ObDirectoryType->TypeName,
374 L"Directory");
375
376 /* create 'type' object type*/
377 ObTypeObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
378
379 ObTypeObjectType->Tag = TAG('T', 'y', 'p', 'T');
380 ObTypeObjectType->TotalObjects = 0;
381 ObTypeObjectType->TotalHandles = 0;
382 ObTypeObjectType->MaxObjects = ULONG_MAX;
383 ObTypeObjectType->MaxHandles = ULONG_MAX;
384 ObTypeObjectType->PagedPoolCharge = 0;
385 ObTypeObjectType->NonpagedPoolCharge = sizeof(TYPE_OBJECT);
386 ObTypeObjectType->Mapping = &ObpTypeMapping;
387 ObTypeObjectType->Dump = NULL;
388 ObTypeObjectType->Open = NULL;
389 ObTypeObjectType->Close = NULL;
390 ObTypeObjectType->Delete = NULL;
391 ObTypeObjectType->Parse = NULL;
392 ObTypeObjectType->Security = NULL;
393 ObTypeObjectType->QueryName = NULL;
394 ObTypeObjectType->OkayToClose = NULL;
395 ObTypeObjectType->Create = NULL;
396 ObTypeObjectType->DuplicationNotify = NULL;
397
398 RtlInitUnicodeStringFromLiteral(&ObTypeObjectType->TypeName,
399 L"ObjectType");
400
401 /* create root directory */
402 ObRosCreateObject(NULL,
403 STANDARD_RIGHTS_REQUIRED,
404 NULL,
405 ObDirectoryType,
406 (PVOID*)&NameSpaceRoot);
407
408 /* create '\ObjectTypes' directory */
409 RtlInitUnicodeStringFromLiteral(&Name,
410 L"\\ObjectTypes");
411 InitializeObjectAttributes(&ObjectAttributes,
412 &Name,
413 OBJ_PERMANENT,
414 NULL,
415 NULL);
416 ObRosCreateObject(NULL,
417 STANDARD_RIGHTS_REQUIRED,
418 &ObjectAttributes,
419 ObDirectoryType,
420 NULL);
421
422 ObpCreateTypeObject(ObDirectoryType);
423 ObpCreateTypeObject(ObTypeObjectType);
424
425 /* Create 'symbolic link' object type */
426 ObInitSymbolicLinkImplementation();
427 }
428
429
430 NTSTATUS
431 ObpCreateTypeObject(POBJECT_TYPE ObjectType)
432 {
433 OBJECT_ATTRIBUTES ObjectAttributes;
434 WCHAR NameString[120];
435 PTYPE_OBJECT TypeObject = NULL;
436 UNICODE_STRING Name;
437 NTSTATUS Status;
438
439 DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", &ObjectType->TypeName);
440 wcscpy(NameString, L"\\ObjectTypes\\");
441 wcscat(NameString, ObjectType->TypeName.Buffer);
442 RtlInitUnicodeString(&Name,
443 NameString);
444
445 InitializeObjectAttributes(&ObjectAttributes,
446 &Name,
447 OBJ_PERMANENT,
448 NULL,
449 NULL);
450 Status = ObRosCreateObject(NULL,
451 STANDARD_RIGHTS_REQUIRED,
452 &ObjectAttributes,
453 ObTypeObjectType,
454 (PVOID*)&TypeObject);
455 if (NT_SUCCESS(Status))
456 {
457 TypeObject->ObjectType = ObjectType;
458 }
459
460 return(STATUS_SUCCESS);
461 }
462
463 /* EOF */