bootstrap
[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 #ifndef LIBCAPTIVE
45
46 NTSTATUS STDCALL
47 ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
48                         ULONG Attributes,
49                         PACCESS_STATE PassedAccessState,
50                         ACCESS_MASK DesiredAccess,
51                         POBJECT_TYPE ObjectType,
52                         KPROCESSOR_MODE AccessMode,
53                         PVOID ParseContext,
54                         PVOID* ObjectPtr)
55 {
56    PVOID Object = NULL;
57    UNICODE_STRING RemainingPath;
58    OBJECT_ATTRIBUTES ObjectAttributes;
59    NTSTATUS Status;
60
61    InitializeObjectAttributes(&ObjectAttributes,
62                               ObjectPath,
63                               Attributes,
64                               NULL,
65                               NULL);
66    Status = ObFindObject(&ObjectAttributes,
67                          &Object,
68                          &RemainingPath,
69                          ObjectType);
70    if (!NT_SUCCESS(Status))
71      {
72         return(Status);
73      }
74 CHECKPOINT;
75 DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
76
77    if (RemainingPath.Buffer != NULL || Object == NULL)
78      {
79 CHECKPOINT;
80 DPRINT("Object %p\n", Object);
81         *ObjectPtr = NULL;
82         RtlFreeUnicodeString (&RemainingPath);
83         return(STATUS_UNSUCCESSFUL);
84      }
85    *ObjectPtr = Object;
86    RtlFreeUnicodeString (&RemainingPath);
87    return(STATUS_SUCCESS);
88 }
89
90
91 /**********************************************************************
92  * NAME                                                 EXPORTED
93  *      ObOpenObjectByName
94  *      
95  * DESCRIPTION
96  *      Obtain a handle to an existing object.
97  *      
98  * ARGUMENTS
99  *      ObjectAttributes
100  *              ...
101  *      ObjectType
102  *              ...
103  *      ParseContext
104  *              ...
105  *      AccessMode
106  *              ...
107  *      DesiredAccess
108  *              ...
109  *      PassedAccessState
110  *              ...
111  *      Handle
112  *              Handle to close.
113  *
114  * RETURN VALUE
115  *      Status.
116  */
117 NTSTATUS STDCALL
118 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
119                    IN POBJECT_TYPE ObjectType,
120                    IN OUT PVOID ParseContext,
121                    IN KPROCESSOR_MODE AccessMode,
122                    IN ACCESS_MASK DesiredAccess,
123                    IN PACCESS_STATE PassedAccessState,
124                    OUT PHANDLE Handle)
125 {
126    UNICODE_STRING RemainingPath;
127    PVOID Object = NULL;
128    NTSTATUS Status;
129
130    DPRINT("ObOpenObjectByName()\n");
131
132    Status = ObFindObject(ObjectAttributes,
133                          &Object,
134                          &RemainingPath,
135                          ObjectType);
136    if (!NT_SUCCESS(Status))
137      {
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 #endif /* LIBCAPTIVE */
161
162 VOID
163 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
164                      POBJECT_HEADER Header,
165                      PWSTR Name)
166 /*
167  * FUNCTION: Add an entry to a namespace directory
168  * ARGUMENTS:
169  *         Parent = directory to add in
170  *         Header = Header of the object to add the entry for
171  *         Name = Name to give the entry
172  */
173 {
174   KIRQL oldlvl;
175
176   RtlCreateUnicodeString(&Header->Name, Name);
177   Header->Parent = Parent;
178
179   KeAcquireSpinLock(&Parent->Lock, &oldlvl);
180   InsertTailList(&Parent->head, &Header->Entry);
181   KeReleaseSpinLock(&Parent->Lock, oldlvl);
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 PVOID
202 ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
203                       PWSTR Name,
204                       ULONG Attributes)
205 {
206    PLIST_ENTRY current = DirectoryObject->head.Flink;
207    POBJECT_HEADER current_obj;
208
209    DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
210    
211    if (Name[0]==0)
212      {
213         return(DirectoryObject);
214      }
215    if (Name[0]=='.' && Name[1]==0)
216      {
217         return(DirectoryObject);
218      }
219    if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
220      {
221         return(BODY_TO_HEADER(DirectoryObject)->Parent);
222      }
223    while (current!=(&(DirectoryObject->head)))
224      {
225         current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
226         DPRINT("Scanning %S %S\n",current_obj->Name.Buffer, Name);
227         if (Attributes & OBJ_CASE_INSENSITIVE)
228           {
229              if (_wcsicmp(current_obj->Name.Buffer, Name)==0)
230                {
231                   DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
232                   return(HEADER_TO_BODY(current_obj));
233                }
234           }
235         else
236           {
237              if ( wcscmp(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         current = current->Flink;
244      }
245    DPRINT("%s() = NULL\n",__FUNCTION__);
246    return(NULL);
247 }
248
249 NTSTATUS STDCALL
250 ObpParseDirectory(PVOID Object,
251                   PVOID * NextObject,
252                   PUNICODE_STRING FullPath,
253                   PWSTR * Path,
254                   ULONG Attributes)
255 {
256    PWSTR end;
257    PVOID FoundObject;
258    
259    DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
260           Object,Path,*Path);
261    
262    *NextObject = NULL;
263    
264    if ((*Path) == NULL)
265      {
266         return STATUS_UNSUCCESSFUL;
267      }
268    
269    end = wcschr((*Path)+1, '\\');
270    if (end != NULL)
271      {
272         *end = 0;
273      }
274    
275    FoundObject = ObpFindEntryDirectory(Object, (*Path)+1, Attributes);
276    
277    if (FoundObject == NULL)
278      {
279         if (end != NULL)
280           {
281              *end = '\\';
282           }
283         return STATUS_UNSUCCESSFUL;
284      }
285    
286    ObReferenceObjectByPointer(FoundObject,
287                               STANDARD_RIGHTS_REQUIRED,
288                               NULL,
289                               UserMode);
290    
291    if (end != NULL)
292      {
293         *end = '\\';
294         *Path = end;
295      }
296    else
297      {
298         *Path = NULL;
299      }
300    
301    *NextObject = FoundObject;
302    
303    return STATUS_SUCCESS;
304 }
305
306 NTSTATUS STDCALL
307 ObpCreateDirectory(PVOID ObjectBody,
308                    PVOID Parent,
309                    PWSTR RemainingPath,
310                    POBJECT_ATTRIBUTES ObjectAttributes)
311 {
312   PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody;
313
314   DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n",
315          ObjectBody, Parent, RemainingPath);
316
317   if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
318     {
319       return(STATUS_UNSUCCESSFUL);
320     }
321
322   InitializeListHead(&DirectoryObject->head);
323   KeInitializeSpinLock(&DirectoryObject->Lock);
324
325   return(STATUS_SUCCESS);
326 }
327
328
329 VOID
330 ObInit(VOID)
331 /*
332  * FUNCTION: Initialize the object manager namespace
333  */
334 {
335   OBJECT_ATTRIBUTES ObjectAttributes;
336   UNICODE_STRING Name;
337
338   /* create 'directory' object type */
339   ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
340   
341   ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T');
342   ObDirectoryType->TotalObjects = 0;
343   ObDirectoryType->TotalHandles = 0;
344   ObDirectoryType->MaxObjects = ULONG_MAX;
345   ObDirectoryType->MaxHandles = ULONG_MAX;
346   ObDirectoryType->PagedPoolCharge = 0;
347   ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
348   ObDirectoryType->Mapping = &ObpDirectoryMapping;
349   ObDirectoryType->Dump = NULL;
350   ObDirectoryType->Open = NULL;
351   ObDirectoryType->Close = NULL;
352   ObDirectoryType->Delete = NULL;
353   ObDirectoryType->Parse = ObpParseDirectory;
354   ObDirectoryType->Security = NULL;
355   ObDirectoryType->QueryName = NULL;
356   ObDirectoryType->OkayToClose = NULL;
357   ObDirectoryType->Create = ObpCreateDirectory;
358   ObDirectoryType->DuplicationNotify = NULL;
359   
360   RtlInitUnicodeStringFromLiteral(&ObDirectoryType->TypeName,
361                        REACTOS_UCS2(L"Directory"));
362
363   /* create 'type' object type*/
364   ObTypeObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
365   
366   ObTypeObjectType->Tag = TAG('T', 'y', 'p', 'T');
367   ObTypeObjectType->TotalObjects = 0;
368   ObTypeObjectType->TotalHandles = 0;
369   ObTypeObjectType->MaxObjects = ULONG_MAX;
370   ObTypeObjectType->MaxHandles = ULONG_MAX;
371   ObTypeObjectType->PagedPoolCharge = 0;
372   ObTypeObjectType->NonpagedPoolCharge = sizeof(TYPE_OBJECT);
373   ObTypeObjectType->Mapping = &ObpTypeMapping;
374   ObTypeObjectType->Dump = NULL;
375   ObTypeObjectType->Open = NULL;
376   ObTypeObjectType->Close = NULL;
377   ObTypeObjectType->Delete = NULL;
378   ObTypeObjectType->Parse = NULL;
379   ObTypeObjectType->Security = NULL;
380   ObTypeObjectType->QueryName = NULL;
381   ObTypeObjectType->OkayToClose = NULL;
382   ObTypeObjectType->Create = NULL;
383   ObTypeObjectType->DuplicationNotify = NULL;
384   
385   RtlInitUnicodeStringFromLiteral(&ObTypeObjectType->TypeName,
386                        REACTOS_UCS2(L"ObjectType"));
387
388   /* create root directory */
389   ObCreateObject(NULL,
390                  STANDARD_RIGHTS_REQUIRED,
391                  NULL,
392                  ObDirectoryType,
393                  (PVOID*)&NameSpaceRoot);
394
395   /* create '\ObjectTypes' directory */
396   RtlInitUnicodeStringFromLiteral(&Name,
397                        REACTOS_UCS2(L"\\ObjectTypes"));
398   InitializeObjectAttributes(&ObjectAttributes,
399                              &Name,
400                              OBJ_PERMANENT,
401                              NULL,
402                              NULL);
403   ObCreateObject(NULL,
404                  STANDARD_RIGHTS_REQUIRED,
405                  &ObjectAttributes,
406                  ObDirectoryType,
407                  NULL);
408
409   ObpCreateTypeObject(ObDirectoryType);
410   ObpCreateTypeObject(ObTypeObjectType);
411 }
412
413
414 NTSTATUS
415 ObpCreateTypeObject(POBJECT_TYPE ObjectType)
416 {
417   OBJECT_ATTRIBUTES ObjectAttributes;
418   WCHAR NameString[120];
419   PTYPE_OBJECT TypeObject = NULL;
420   UNICODE_STRING Name;
421   NTSTATUS Status;
422
423   DPRINT("ObjectType: %wZ\n", &ObjectType->TypeName);
424   wcscpy(NameString, REACTOS_UCS2(L"\\ObjectTypes\\"));
425   wcscat(NameString, ObjectType->TypeName.Buffer);
426   RtlInitUnicodeString(&Name,
427                        NameString);
428
429   InitializeObjectAttributes(&ObjectAttributes,
430                              &Name,
431                              OBJ_PERMANENT,
432                              NULL,
433                              NULL);
434   Status = ObCreateObject(NULL,
435                           STANDARD_RIGHTS_REQUIRED,
436                           &ObjectAttributes,
437                           ObTypeObjectType,
438                           (PVOID*)&TypeObject);
439   if (NT_SUCCESS(Status))
440     {
441       TypeObject->ObjectType = ObjectType;
442     }
443
444   return(STATUS_SUCCESS);
445 }
446
447
448 /* EOF */