:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / ob / namespc.c
1 /* $Id$
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                   ULONG Attributes)
252 {
253    PWSTR end;
254    PVOID FoundObject;
255    
256    DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
257           Object,Path,*Path);
258    
259    *NextObject = NULL;
260    
261    if ((*Path) == NULL)
262      {
263         return STATUS_UNSUCCESSFUL;
264      }
265    
266    end = wcschr((*Path)+1, '\\');
267    if (end != NULL)
268      {
269         *end = 0;
270      }
271    
272    FoundObject = ObpFindEntryDirectory(Object, (*Path)+1, Attributes);
273    
274    if (FoundObject == NULL)
275      {
276         if (end != NULL)
277           {
278              *end = '\\';
279           }
280         return STATUS_UNSUCCESSFUL;
281      }
282    
283    ObReferenceObjectByPointer(FoundObject,
284                               STANDARD_RIGHTS_REQUIRED,
285                               NULL,
286                               UserMode);
287    
288    if (end != NULL)
289      {
290         *end = '\\';
291         *Path = end;
292      }
293    else
294      {
295         *Path = NULL;
296      }
297    
298    *NextObject = FoundObject;
299    
300    return STATUS_SUCCESS;
301 }
302
303 NTSTATUS STDCALL
304 ObpCreateDirectory(PVOID ObjectBody,
305                    PVOID Parent,
306                    PWSTR RemainingPath,
307                    POBJECT_ATTRIBUTES ObjectAttributes)
308 {
309   PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody;
310
311   DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n",
312          ObjectBody, Parent, RemainingPath);
313
314   if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
315     {
316       return(STATUS_UNSUCCESSFUL);
317     }
318
319   InitializeListHead(&DirectoryObject->head);
320   KeInitializeSpinLock(&DirectoryObject->Lock);
321
322   return(STATUS_SUCCESS);
323 }
324
325
326 VOID
327 ObInit(VOID)
328 /*
329  * FUNCTION: Initialize the object manager namespace
330  */
331 {
332   OBJECT_ATTRIBUTES ObjectAttributes;
333   UNICODE_STRING Name;
334
335   /* create 'directory' object type */
336   ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
337   
338   ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T');
339   ObDirectoryType->TotalObjects = 0;
340   ObDirectoryType->TotalHandles = 0;
341   ObDirectoryType->MaxObjects = ULONG_MAX;
342   ObDirectoryType->MaxHandles = ULONG_MAX;
343   ObDirectoryType->PagedPoolCharge = 0;
344   ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
345   ObDirectoryType->Mapping = &ObpDirectoryMapping;
346   ObDirectoryType->Dump = NULL;
347   ObDirectoryType->Open = NULL;
348   ObDirectoryType->Close = NULL;
349   ObDirectoryType->Delete = NULL;
350   ObDirectoryType->Parse = ObpParseDirectory;
351   ObDirectoryType->Security = NULL;
352   ObDirectoryType->QueryName = NULL;
353   ObDirectoryType->OkayToClose = NULL;
354   ObDirectoryType->Create = ObpCreateDirectory;
355   ObDirectoryType->DuplicationNotify = NULL;
356   
357   RtlInitUnicodeStringFromLiteral(&ObDirectoryType->TypeName,
358                        L"Directory");
359
360   /* create 'type' object type*/
361   ObTypeObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
362   
363   ObTypeObjectType->Tag = TAG('T', 'y', 'p', 'T');
364   ObTypeObjectType->TotalObjects = 0;
365   ObTypeObjectType->TotalHandles = 0;
366   ObTypeObjectType->MaxObjects = ULONG_MAX;
367   ObTypeObjectType->MaxHandles = ULONG_MAX;
368   ObTypeObjectType->PagedPoolCharge = 0;
369   ObTypeObjectType->NonpagedPoolCharge = sizeof(TYPE_OBJECT);
370   ObTypeObjectType->Mapping = &ObpTypeMapping;
371   ObTypeObjectType->Dump = NULL;
372   ObTypeObjectType->Open = NULL;
373   ObTypeObjectType->Close = NULL;
374   ObTypeObjectType->Delete = NULL;
375   ObTypeObjectType->Parse = NULL;
376   ObTypeObjectType->Security = NULL;
377   ObTypeObjectType->QueryName = NULL;
378   ObTypeObjectType->OkayToClose = NULL;
379   ObTypeObjectType->Create = NULL;
380   ObTypeObjectType->DuplicationNotify = NULL;
381   
382   RtlInitUnicodeStringFromLiteral(&ObTypeObjectType->TypeName,
383                        L"ObjectType");
384
385   /* create root directory */
386   ObCreateObject(NULL,
387                  STANDARD_RIGHTS_REQUIRED,
388                  NULL,
389                  ObDirectoryType,
390                  (PVOID*)&NameSpaceRoot);
391
392   /* create '\ObjectTypes' directory */
393   RtlInitUnicodeStringFromLiteral(&Name,
394                        L"\\ObjectTypes");
395   InitializeObjectAttributes(&ObjectAttributes,
396                              &Name,
397                              OBJ_PERMANENT,
398                              NULL,
399                              NULL);
400   ObCreateObject(NULL,
401                  STANDARD_RIGHTS_REQUIRED,
402                  &ObjectAttributes,
403                  ObDirectoryType,
404                  NULL);
405
406   ObpCreateTypeObject(ObDirectoryType);
407   ObpCreateTypeObject(ObTypeObjectType);
408 }
409
410
411 NTSTATUS
412 ObpCreateTypeObject(POBJECT_TYPE ObjectType)
413 {
414   OBJECT_ATTRIBUTES ObjectAttributes;
415   WCHAR NameString[120];
416   PTYPE_OBJECT TypeObject = NULL;
417   UNICODE_STRING Name;
418   NTSTATUS Status;
419
420   DPRINT("ObjectType: %wZ\n", &ObjectType->TypeName);
421   wcscpy(NameString, L"\\ObjectTypes\\");
422   wcscat(NameString, ObjectType->TypeName.Buffer);
423   RtlInitUnicodeString(&Name,
424                        NameString);
425
426   InitializeObjectAttributes(&ObjectAttributes,
427                              &Name,
428                              OBJ_PERMANENT,
429                              NULL,
430                              NULL);
431   Status = ObCreateObject(NULL,
432                           STANDARD_RIGHTS_REQUIRED,
433                           &ObjectAttributes,
434                           ObTypeObjectType,
435                           (PVOID*)&TypeObject);
436   if (NT_SUCCESS(Status))
437     {
438       TypeObject->ObjectType = ObjectType;
439     }
440
441   return(STATUS_SUCCESS);
442 }
443
444
445 /* EOF */