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