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