f67794ad08c948252520865072582252ed1d719c
[reactos.git] / reactos / 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 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES ***************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17
18 /* GLOBALS ****************************************************************/
19
20 POBJECT_TYPE ObDirectoryType = NULL;
21 POBJECT_TYPE ObTypeObjectType = NULL;
22
23 PDIRECTORY_OBJECT NameSpaceRoot = NULL;
24 /* FIXME: Move this somewhere else once devicemap support is in */
25 PDEVICE_MAP ObSystemDeviceMap = NULL;
26
27 static GENERIC_MAPPING ObpDirectoryMapping = {
28 STANDARD_RIGHTS_READ|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
29 STANDARD_RIGHTS_WRITE|DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY,
30 STANDARD_RIGHTS_EXECUTE|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
31 DIRECTORY_ALL_ACCESS};
32
33 static GENERIC_MAPPING ObpTypeMapping = {
34 STANDARD_RIGHTS_READ,
35 STANDARD_RIGHTS_WRITE,
36 STANDARD_RIGHTS_EXECUTE,
37 0x000F0001};
38
39 /* FUNCTIONS **************************************************************/
40
41 /*
42 * @implemented
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 PAGED_CODE();
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_OBJECT_NAME_NOT_FOUND);
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 * @implemented
118 */
119 NTSTATUS STDCALL
120 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
121 IN POBJECT_TYPE ObjectType,
122 IN OUT PVOID ParseContext,
123 IN KPROCESSOR_MODE AccessMode,
124 IN ACCESS_MASK DesiredAccess,
125 IN PACCESS_STATE PassedAccessState,
126 OUT PHANDLE Handle)
127 {
128 UNICODE_STRING RemainingPath;
129 PVOID Object = NULL;
130 NTSTATUS Status;
131
132 PAGED_CODE();
133
134 DPRINT("ObOpenObjectByName(...)\n");
135
136 Status = ObFindObject(ObjectAttributes,
137 &Object,
138 &RemainingPath,
139 ObjectType);
140 if (!NT_SUCCESS(Status))
141 {
142 DPRINT("ObFindObject() failed (Status %lx)\n", Status);
143 return Status;
144 }
145
146 if (RemainingPath.Buffer != NULL ||
147 Object == NULL)
148 {
149 RtlFreeUnicodeString(&RemainingPath);
150 return STATUS_UNSUCCESSFUL;
151 }
152
153 Status = ObCreateHandle(PsGetCurrentProcess(),
154 Object,
155 DesiredAccess,
156 FALSE,
157 Handle);
158
159 ObDereferenceObject(Object);
160 RtlFreeUnicodeString(&RemainingPath);
161
162 return Status;
163 }
164
165 VOID
166 STDCALL
167 ObQueryDeviceMapInformation(PEPROCESS Process,
168 PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
169 {
170 //KIRQL OldIrql ;
171
172 /*
173 * FIXME: This is an ugly hack for now, to always return the System Device Map
174 * instead of returning the Process Device Map. Not important yet since we don't use it
175 */
176
177 /* FIXME: Acquire the DeviceMap Spinlock */
178 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
179
180 /* Make a copy */
181 DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
182 RtlMoveMemory(DeviceMapInfo->Query.DriveType, ObSystemDeviceMap->DriveType, sizeof(ObSystemDeviceMap->DriveType));
183
184 /* FIXME: Release the DeviceMap Spinlock */
185 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
186 }
187
188 VOID
189 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
190 POBJECT_HEADER Header,
191 PWSTR Name)
192 /*
193 * FUNCTION: Add an entry to a namespace directory
194 * ARGUMENTS:
195 * Parent = directory to add in
196 * Header = Header of the object to add the entry for
197 * Name = Name to give the entry
198 */
199 {
200 KIRQL oldlvl;
201
202 RtlpCreateUnicodeString(&Header->Name, Name, NonPagedPool);
203 Header->Parent = Parent;
204
205 KeAcquireSpinLock(&Parent->Lock, &oldlvl);
206 InsertTailList(&Parent->head, &Header->Entry);
207 KeReleaseSpinLock(&Parent->Lock, oldlvl);
208 }
209
210
211 VOID
212 ObpRemoveEntryDirectory(POBJECT_HEADER Header)
213 /*
214 * FUNCTION: Remove an entry from a namespace directory
215 * ARGUMENTS:
216 * Header = Header of the object to remove
217 */
218 {
219 KIRQL oldlvl;
220
221 DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
222
223 KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);
224 RemoveEntryList(&(Header->Entry));
225 KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl);
226 }
227
228
229 PVOID
230 ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
231 PWSTR Name,
232 ULONG Attributes)
233 {
234 PLIST_ENTRY current = DirectoryObject->head.Flink;
235 POBJECT_HEADER current_obj;
236
237 DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
238
239 if (Name[0]==0)
240 {
241 return(DirectoryObject);
242 }
243 if (Name[0]=='.' && Name[1]==0)
244 {
245 return(DirectoryObject);
246 }
247 if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
248 {
249 return(BODY_TO_HEADER(DirectoryObject)->Parent);
250 }
251 while (current!=(&(DirectoryObject->head)))
252 {
253 current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
254 DPRINT(" Scanning: %S for: %S\n",current_obj->Name.Buffer, Name);
255 if (Attributes & OBJ_CASE_INSENSITIVE)
256 {
257 if (_wcsicmp(current_obj->Name.Buffer, Name)==0)
258 {
259 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
260 return(HEADER_TO_BODY(current_obj));
261 }
262 }
263 else
264 {
265 if ( wcscmp(current_obj->Name.Buffer, Name)==0)
266 {
267 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
268 return(HEADER_TO_BODY(current_obj));
269 }
270 }
271 current = current->Flink;
272 }
273 DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__);
274 return(NULL);
275 }
276
277
278 NTSTATUS STDCALL
279 ObpParseDirectory(PVOID Object,
280 PVOID * NextObject,
281 PUNICODE_STRING FullPath,
282 PWSTR * Path,
283 ULONG Attributes)
284 {
285 PWSTR Start;
286 PWSTR End;
287 PVOID FoundObject;
288
289 DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
290 Object,Path,*Path);
291
292 *NextObject = NULL;
293
294 if ((*Path) == NULL)
295 {
296 return STATUS_UNSUCCESSFUL;
297 }
298
299 Start = *Path;
300 if (*Start == L'\\')
301 Start++;
302
303 End = wcschr(Start, L'\\');
304 if (End != NULL)
305 {
306 *End = 0;
307 }
308
309 FoundObject = ObpFindEntryDirectory(Object, Start, Attributes);
310 if (FoundObject == NULL)
311 {
312 if (End != NULL)
313 {
314 *End = L'\\';
315 }
316 return STATUS_UNSUCCESSFUL;
317 }
318
319 ObReferenceObjectByPointer(FoundObject,
320 STANDARD_RIGHTS_REQUIRED,
321 NULL,
322 UserMode);
323
324 if (End != NULL)
325 {
326 *End = L'\\';
327 *Path = End;
328 }
329 else
330 {
331 *Path = NULL;
332 }
333
334 *NextObject = FoundObject;
335
336 return STATUS_SUCCESS;
337 }
338
339
340 NTSTATUS STDCALL
341 ObpCreateDirectory(PVOID ObjectBody,
342 PVOID Parent,
343 PWSTR RemainingPath,
344 POBJECT_ATTRIBUTES ObjectAttributes)
345 {
346 PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody;
347
348 DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n",
349 ObjectBody, Parent, RemainingPath);
350
351 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
352 {
353 return(STATUS_UNSUCCESSFUL);
354 }
355
356 InitializeListHead(&DirectoryObject->head);
357 KeInitializeSpinLock(&DirectoryObject->Lock);
358
359 return(STATUS_SUCCESS);
360 }
361
362
363 VOID INIT_FUNCTION
364 ObInit(VOID)
365 /*
366 * FUNCTION: Initialize the object manager namespace
367 */
368 {
369 OBJECT_ATTRIBUTES ObjectAttributes;
370 UNICODE_STRING Name;
371 SECURITY_DESCRIPTOR SecurityDescriptor;
372
373 /* Initialize the security descriptor cache */
374 ObpInitSdCache();
375
376 /* create 'directory' object type */
377 ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
378
379 ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T');
380 ObDirectoryType->TotalObjects = 0;
381 ObDirectoryType->TotalHandles = 0;
382 ObDirectoryType->PeakObjects = 0;
383 ObDirectoryType->PeakHandles = 0;
384 ObDirectoryType->PagedPoolCharge = 0;
385 ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
386 ObDirectoryType->Mapping = &ObpDirectoryMapping;
387 ObDirectoryType->Dump = NULL;
388 ObDirectoryType->Open = NULL;
389 ObDirectoryType->Close = NULL;
390 ObDirectoryType->Delete = NULL;
391 ObDirectoryType->Parse = ObpParseDirectory;
392 ObDirectoryType->Security = NULL;
393 ObDirectoryType->QueryName = NULL;
394 ObDirectoryType->OkayToClose = NULL;
395 ObDirectoryType->Create = ObpCreateDirectory;
396 ObDirectoryType->DuplicationNotify = NULL;
397
398 RtlInitUnicodeString(&ObDirectoryType->TypeName,
399 L"Directory");
400
401 /* create 'type' object type*/
402 ObTypeObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
403
404 ObTypeObjectType->Tag = TAG('T', 'y', 'p', 'T');
405 ObTypeObjectType->TotalObjects = 0;
406 ObTypeObjectType->TotalHandles = 0;
407 ObTypeObjectType->PeakObjects = 0;
408 ObTypeObjectType->PeakHandles = 0;
409 ObTypeObjectType->PagedPoolCharge = 0;
410 ObTypeObjectType->NonpagedPoolCharge = sizeof(TYPE_OBJECT);
411 ObTypeObjectType->Mapping = &ObpTypeMapping;
412 ObTypeObjectType->Dump = NULL;
413 ObTypeObjectType->Open = NULL;
414 ObTypeObjectType->Close = NULL;
415 ObTypeObjectType->Delete = NULL;
416 ObTypeObjectType->Parse = NULL;
417 ObTypeObjectType->Security = NULL;
418 ObTypeObjectType->QueryName = NULL;
419 ObTypeObjectType->OkayToClose = NULL;
420 ObTypeObjectType->Create = NULL;
421 ObTypeObjectType->DuplicationNotify = NULL;
422
423 RtlInitUnicodeString(&ObTypeObjectType->TypeName,
424 L"ObjectType");
425
426 /* Create security descriptor */
427 RtlCreateSecurityDescriptor(&SecurityDescriptor,
428 SECURITY_DESCRIPTOR_REVISION1);
429
430 RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
431 SeAliasAdminsSid,
432 FALSE);
433
434 RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
435 SeLocalSystemSid,
436 FALSE);
437
438 RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
439 TRUE,
440 SePublicDefaultDacl,
441 FALSE);
442
443 /* Create root directory */
444 InitializeObjectAttributes(&ObjectAttributes,
445 NULL,
446 OBJ_PERMANENT,
447 NULL,
448 &SecurityDescriptor);
449 ObCreateObject(KernelMode,
450 ObDirectoryType,
451 &ObjectAttributes,
452 KernelMode,
453 NULL,
454 sizeof(DIRECTORY_OBJECT),
455 0,
456 0,
457 (PVOID*)&NameSpaceRoot);
458
459 /* Create '\ObjectTypes' directory */
460 RtlRosInitUnicodeStringFromLiteral(&Name,
461 L"\\ObjectTypes");
462 InitializeObjectAttributes(&ObjectAttributes,
463 &Name,
464 OBJ_PERMANENT,
465 NULL,
466 &SecurityDescriptor);
467 ObCreateObject(KernelMode,
468 ObDirectoryType,
469 &ObjectAttributes,
470 KernelMode,
471 NULL,
472 sizeof(DIRECTORY_OBJECT),
473 0,
474 0,
475 NULL);
476
477 ObpCreateTypeObject(ObDirectoryType);
478 ObpCreateTypeObject(ObTypeObjectType);
479
480 /* Create 'symbolic link' object type */
481 ObInitSymbolicLinkImplementation();
482
483 /* FIXME: Hack Hack! */
484 ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
485 RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
486 }
487
488
489 NTSTATUS
490 ObpCreateTypeObject(POBJECT_TYPE ObjectType)
491 {
492 OBJECT_ATTRIBUTES ObjectAttributes;
493 WCHAR NameString[120];
494 PTYPE_OBJECT TypeObject = NULL;
495 UNICODE_STRING Name;
496 NTSTATUS Status;
497
498 DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", &ObjectType->TypeName);
499 wcscpy(NameString, L"\\ObjectTypes\\");
500 wcscat(NameString, ObjectType->TypeName.Buffer);
501 RtlInitUnicodeString(&Name,
502 NameString);
503
504 InitializeObjectAttributes(&ObjectAttributes,
505 &Name,
506 OBJ_PERMANENT,
507 NULL,
508 NULL);
509 Status = ObCreateObject(KernelMode,
510 ObTypeObjectType,
511 &ObjectAttributes,
512 KernelMode,
513 NULL,
514 sizeof(TYPE_OBJECT),
515 0,
516 0,
517 (PVOID*)&TypeObject);
518 if (NT_SUCCESS(Status))
519 {
520 TypeObject->ObjectType = ObjectType;
521 }
522
523 return(STATUS_SUCCESS);
524 }
525
526 /* EOF */