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