added #ifdef around headers to support private test build and modified debug messages.
[reactos.git] / reactos / ntoskrnl / ob / namespc.c
1 /* $Id: namespc.c,v 1.35 2002/11/10 13:36:15 robd 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 #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
416
417 NTSTATUS
418 ObpCreateTypeObject(POBJECT_TYPE ObjectType)
419 {
420 OBJECT_ATTRIBUTES ObjectAttributes;
421 WCHAR NameString[120];
422 PTYPE_OBJECT TypeObject = NULL;
423 UNICODE_STRING Name;
424 NTSTATUS Status;
425
426 DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", &ObjectType->TypeName);
427 wcscpy(NameString, L"\\ObjectTypes\\");
428 wcscat(NameString, ObjectType->TypeName.Buffer);
429 RtlInitUnicodeString(&Name,
430 NameString);
431
432 InitializeObjectAttributes(&ObjectAttributes,
433 &Name,
434 OBJ_PERMANENT,
435 NULL,
436 NULL);
437 Status = ObCreateObject(NULL,
438 STANDARD_RIGHTS_REQUIRED,
439 &ObjectAttributes,
440 ObTypeObjectType,
441 (PVOID*)&TypeObject);
442 if (NT_SUCCESS(Status))
443 {
444 TypeObject->ObjectType = ObjectType;
445 }
446
447 return(STATUS_SUCCESS);
448 }
449
450
451 /* EOF */