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