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