- reverted ObpCaptureObjectAttributes back to my old implementation (slightly modifie...
[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 extern ULONG NtGlobalFlag;
18
19 /* GLOBALS ****************************************************************/
20
21 POBJECT_TYPE ObDirectoryType = NULL;
22 POBJECT_TYPE ObTypeObjectType = NULL;
23
24 PDIRECTORY_OBJECT NameSpaceRoot = NULL;
25 PDIRECTORY_OBJECT ObpTypeDirectoryObject = NULL;
26 /* FIXME: Move this somewhere else once devicemap support is in */
27 PDEVICE_MAP ObSystemDeviceMap = NULL;
28 KEVENT ObpDefaultObject;
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 NTSTATUS
43 STDCALL
44 ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
45 PUNICODE_STRING ObjectName,
46 POBJECT_TYPE ObjectType,
47 ULONG ObjectSize,
48 POBJECT_HEADER *ObjectHeader);
49
50 /* FUNCTIONS **************************************************************/
51
52 /*
53 * @implemented
54 */
55 NTSTATUS STDCALL
56 ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
57 ULONG Attributes,
58 PACCESS_STATE PassedAccessState,
59 ACCESS_MASK DesiredAccess,
60 POBJECT_TYPE ObjectType,
61 KPROCESSOR_MODE AccessMode,
62 PVOID ParseContext,
63 PVOID* ObjectPtr)
64 {
65 PVOID Object = NULL;
66 UNICODE_STRING RemainingPath;
67 UNICODE_STRING ObjectName;
68 OBJECT_ATTRIBUTES ObjectAttributes;
69 OBJECT_CREATE_INFORMATION ObjectCreateInfo;
70 NTSTATUS Status;
71
72 PAGED_CODE();
73
74 /* capture the ObjectPath */
75 Status = RtlCaptureUnicodeString(&ObjectName,
76 AccessMode,
77 NonPagedPool, /* FIXME */
78 FALSE,
79 ObjectPath);
80 if (!NT_SUCCESS(Status))
81 {
82 DPRINT("RtlCaptureUnicodeString() failed (Status %lx)\n", Status);
83 return Status;
84 }
85
86 InitializeObjectAttributes(&ObjectAttributes,
87 &ObjectName,
88 Attributes | OBJ_OPENIF,
89 NULL,
90 NULL);
91
92 /* "Capture" all the info, it doesn't make sense to capture from the kernel
93 stack as the information should be safe anyway...just do a raw copy of the
94 data into the OBJECT_CREATE_INFORMATION structure */
95 DPRINT("Capturing Create Info\n");
96 Status = ObpCaptureObjectAttributes(&ObjectAttributes,
97 KernelMode, /* raw copy! */
98 NonPagedPool,
99 FALSE,
100 &ObjectCreateInfo,
101 NULL);
102 if (!NT_SUCCESS(Status))
103 {
104 DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
105 return Status;
106 }
107
108 Status = ObFindObject(&ObjectCreateInfo,
109 &ObjectName,
110 &Object,
111 &RemainingPath,
112 ObjectType);
113
114 /* we don't need to release the "captured" object attributes! Nothing was allocated! */
115 #if 0
116 ObpReleaseCapturedAttributes(&ObjectCreateInfo,
117 NULL,
118 AccessMode,
119 FALSE);
120 #endif
121
122 /* free the captured ObjectPath if needed */
123 RtlReleaseCapturedUnicodeString(&ObjectName,
124 AccessMode,
125 FALSE);
126
127 if (!NT_SUCCESS(Status))
128 {
129 return(Status);
130 }
131 DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
132
133 if (RemainingPath.Buffer != NULL || Object == NULL)
134 {
135 DPRINT("Object %p\n", Object);
136 *ObjectPtr = NULL;
137 RtlFreeUnicodeString (&RemainingPath);
138 return(STATUS_OBJECT_NAME_NOT_FOUND);
139 }
140 *ObjectPtr = Object;
141 RtlFreeUnicodeString (&RemainingPath);
142 return(STATUS_SUCCESS);
143 }
144
145
146 /**********************************************************************
147 * NAME EXPORTED
148 * ObOpenObjectByName
149 *
150 * DESCRIPTION
151 * Obtain a handle to an existing object.
152 *
153 * ARGUMENTS
154 * ObjectAttributes
155 * ...
156 * ObjectType
157 * ...
158 * ParseContext
159 * ...
160 * AccessMode
161 * ...
162 * DesiredAccess
163 * ...
164 * PassedAccessState
165 * ...
166 * Handle
167 * Handle to close.
168 *
169 * RETURN VALUE
170 * Status.
171 *
172 * @implemented
173 */
174 NTSTATUS STDCALL
175 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
176 IN POBJECT_TYPE ObjectType,
177 IN OUT PVOID ParseContext,
178 IN KPROCESSOR_MODE AccessMode,
179 IN ACCESS_MASK DesiredAccess,
180 IN PACCESS_STATE PassedAccessState,
181 OUT PHANDLE Handle)
182 {
183 UNICODE_STRING RemainingPath;
184 PVOID Object = NULL;
185 UNICODE_STRING ObjectName;
186 OBJECT_CREATE_INFORMATION ObjectCreateInfo;
187 NTSTATUS Status;
188
189 PAGED_CODE();
190
191 DPRINT("ObOpenObjectByName(...)\n");
192
193 /* Capture all the info */
194 DPRINT("Capturing Create Info\n");
195 Status = ObpCaptureObjectAttributes(ObjectAttributes,
196 AccessMode,
197 PagedPool,
198 FALSE,
199 &ObjectCreateInfo,
200 &ObjectName);
201 if (!NT_SUCCESS(Status))
202 {
203 DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
204 return Status;
205 }
206
207 Status = ObFindObject(&ObjectCreateInfo,
208 &ObjectName,
209 &Object,
210 &RemainingPath,
211 ObjectType);
212 ObpReleaseCapturedAttributes(&ObjectCreateInfo,
213 &ObjectName,
214 AccessMode,
215 FALSE);
216 if (!NT_SUCCESS(Status))
217 {
218 DPRINT("ObFindObject() failed (Status %lx)\n", Status);
219 return Status;
220 }
221
222 DPRINT("OBject: %x, Remaining Path: %wZ\n", Object, &RemainingPath);
223 if (Object == NULL)
224 {
225 RtlFreeUnicodeString(&RemainingPath);
226 return STATUS_UNSUCCESSFUL;
227 }
228 if (RemainingPath.Buffer != NULL)
229 {
230 if (wcschr(RemainingPath.Buffer + 1, L'\\') == NULL)
231 Status = STATUS_OBJECT_NAME_NOT_FOUND;
232 else
233 Status =STATUS_OBJECT_PATH_NOT_FOUND;
234 RtlFreeUnicodeString(&RemainingPath);
235 ObDereferenceObject(Object);
236 return Status;
237 }
238
239 Status = ObpCreateHandle(PsGetCurrentProcess(),
240 Object,
241 DesiredAccess,
242 FALSE,
243 Handle);
244
245 ObDereferenceObject(Object);
246 RtlFreeUnicodeString(&RemainingPath);
247
248 return Status;
249 }
250
251 VOID
252 STDCALL
253 ObQueryDeviceMapInformation(PEPROCESS Process,
254 PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
255 {
256 //KIRQL OldIrql ;
257
258 /*
259 * FIXME: This is an ugly hack for now, to always return the System Device Map
260 * instead of returning the Process Device Map. Not important yet since we don't use it
261 */
262
263 /* FIXME: Acquire the DeviceMap Spinlock */
264 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
265
266 /* Make a copy */
267 DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
268 RtlMoveMemory(DeviceMapInfo->Query.DriveType, ObSystemDeviceMap->DriveType, sizeof(ObSystemDeviceMap->DriveType));
269
270 /* FIXME: Release the DeviceMap Spinlock */
271 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
272 }
273
274 VOID
275 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
276 POBJECT_HEADER Header,
277 PWSTR Name)
278 /*
279 * FUNCTION: Add an entry to a namespace directory
280 * ARGUMENTS:
281 * Parent = directory to add in
282 * Header = Header of the object to add the entry for
283 * Name = Name to give the entry
284 */
285 {
286 KIRQL oldlvl;
287
288 ASSERT(HEADER_TO_OBJECT_NAME(Header));
289 HEADER_TO_OBJECT_NAME(Header)->Directory = Parent;
290
291 KeAcquireSpinLock(&Parent->Lock, &oldlvl);
292 InsertTailList(&Parent->head, &Header->Entry);
293 KeReleaseSpinLock(&Parent->Lock, oldlvl);
294 }
295
296
297 VOID
298 ObpRemoveEntryDirectory(POBJECT_HEADER Header)
299 /*
300 * FUNCTION: Remove an entry from a namespace directory
301 * ARGUMENTS:
302 * Header = Header of the object to remove
303 */
304 {
305 KIRQL oldlvl;
306
307 DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
308
309 KeAcquireSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),&oldlvl);
310 if (Header->Entry.Flink && Header->Entry.Blink)
311 {
312 RemoveEntryList(&(Header->Entry));
313 Header->Entry.Flink = Header->Entry.Blink = NULL;
314 }
315 KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),oldlvl);
316 }
317
318 NTSTATUS
319 STDCALL
320 ObpCreateDirectory(OB_OPEN_REASON Reason,
321 PVOID ObjectBody,
322 PEPROCESS Process,
323 ULONG HandleCount,
324 ACCESS_MASK GrantedAccess)
325 {
326 PDIRECTORY_OBJECT Directory = ObjectBody;
327
328 if (Reason == ObCreateHandle)
329 {
330 InitializeListHead(&Directory->head);
331 KeInitializeSpinLock(&Directory->Lock);
332 }
333
334 return STATUS_SUCCESS;
335 }
336
337 PVOID
338 ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
339 PWSTR Name,
340 ULONG Attributes)
341 {
342 PLIST_ENTRY current = DirectoryObject->head.Flink;
343 POBJECT_HEADER current_obj;
344
345 DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
346
347 if (Name[0]==0)
348 {
349 return(DirectoryObject);
350 }
351 if (Name[0]=='.' && Name[1]==0)
352 {
353 return(DirectoryObject);
354 }
355 if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
356 {
357 return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject))->Directory);
358 }
359 while (current!=(&(DirectoryObject->head)))
360 {
361 current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
362 DPRINT(" Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name);
363 if (Attributes & OBJ_CASE_INSENSITIVE)
364 {
365 if (_wcsicmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
366 {
367 DPRINT("Found it %x\n",&current_obj->Body);
368 return(&current_obj->Body);
369 }
370 }
371 else
372 {
373 if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
374 {
375 DPRINT("Found it %x\n",&current_obj->Body);
376 return(&current_obj->Body);
377 }
378 }
379 current = current->Flink;
380 }
381 DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__);
382 return(NULL);
383 }
384
385
386 NTSTATUS STDCALL
387 ObpParseDirectory(PVOID Object,
388 PVOID * NextObject,
389 PUNICODE_STRING FullPath,
390 PWSTR * Path,
391 ULONG Attributes)
392 {
393 PWSTR Start;
394 PWSTR End;
395 PVOID FoundObject;
396 KIRQL oldlvl;
397
398 DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
399 Object,Path,*Path);
400
401 *NextObject = NULL;
402
403 if ((*Path) == NULL)
404 {
405 return STATUS_UNSUCCESSFUL;
406 }
407
408 Start = *Path;
409 if (*Start == L'\\')
410 Start++;
411
412 End = wcschr(Start, L'\\');
413 if (End != NULL)
414 {
415 *End = 0;
416 }
417
418 KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl);
419 FoundObject = ObpFindEntryDirectory(Object, Start, Attributes);
420 if (FoundObject == NULL)
421 {
422 KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
423 if (End != NULL)
424 {
425 *End = L'\\';
426 }
427 return STATUS_UNSUCCESSFUL;
428 }
429
430 ObReferenceObjectByPointer(FoundObject,
431 STANDARD_RIGHTS_REQUIRED,
432 NULL,
433 UserMode);
434 KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
435 if (End != NULL)
436 {
437 *End = L'\\';
438 *Path = End;
439 }
440 else
441 {
442 *Path = NULL;
443 }
444
445 *NextObject = FoundObject;
446
447 return STATUS_SUCCESS;
448 }
449
450 VOID
451 INIT_FUNCTION
452 ObInit(VOID)
453 {
454 OBJECT_ATTRIBUTES ObjectAttributes;
455 UNICODE_STRING Name;
456 SECURITY_DESCRIPTOR SecurityDescriptor;
457 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
458
459 /* Initialize the security descriptor cache */
460 ObpInitSdCache();
461
462 /* Initialize the Default Event */
463 KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE );
464
465 /* Create the Type Type */
466 DPRINT("Creating Type Type\n");
467 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
468 RtlInitUnicodeString(&Name, L"Type");
469 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
470 ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
471 ObjectTypeInitializer.UseDefaultObject = TRUE;
472 ObjectTypeInitializer.MaintainTypeList = TRUE;
473 ObjectTypeInitializer.PoolType = NonPagedPool;
474 ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
475 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
476 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObTypeObjectType);
477
478 /* Create the Directory Type */
479 DPRINT("Creating Directory Type\n");
480 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
481 RtlInitUnicodeString(&Name, L"Directory");
482 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
483 ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
484 ObjectTypeInitializer.UseDefaultObject = FALSE;
485 ObjectTypeInitializer.OpenProcedure = ObpCreateDirectory;
486 ObjectTypeInitializer.ParseProcedure = ObpParseDirectory;
487 ObjectTypeInitializer.MaintainTypeList = FALSE;
488 ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
489 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DIRECTORY_OBJECT);
490 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObDirectoryType);
491
492 /* Create security descriptor */
493 RtlCreateSecurityDescriptor(&SecurityDescriptor,
494 SECURITY_DESCRIPTOR_REVISION1);
495 RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
496 SeAliasAdminsSid,
497 FALSE);
498 RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
499 SeLocalSystemSid,
500 FALSE);
501 RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
502 TRUE,
503 SePublicDefaultDacl,
504 FALSE);
505
506 /* Create root directory */
507 DPRINT("Creating Root Directory\n");
508 InitializeObjectAttributes(&ObjectAttributes,
509 NULL,
510 OBJ_PERMANENT,
511 NULL,
512 &SecurityDescriptor);
513 ObCreateObject(KernelMode,
514 ObDirectoryType,
515 &ObjectAttributes,
516 KernelMode,
517 NULL,
518 sizeof(DIRECTORY_OBJECT),
519 0,
520 0,
521 (PVOID*)&NameSpaceRoot);
522 ObInsertObject((PVOID)NameSpaceRoot,
523 NULL,
524 DIRECTORY_ALL_ACCESS,
525 0,
526 NULL,
527 NULL);
528
529 /* Create '\ObjectTypes' directory */
530 RtlInitUnicodeString(&Name, L"\\ObjectTypes");
531 InitializeObjectAttributes(&ObjectAttributes,
532 &Name,
533 OBJ_PERMANENT,
534 NULL,
535 &SecurityDescriptor);
536 ObCreateObject(KernelMode,
537 ObDirectoryType,
538 &ObjectAttributes,
539 KernelMode,
540 NULL,
541 sizeof(DIRECTORY_OBJECT),
542 0,
543 0,
544 (PVOID*)&ObpTypeDirectoryObject);
545 ObInsertObject((PVOID)ObpTypeDirectoryObject,
546 NULL,
547 DIRECTORY_ALL_ACCESS,
548 0,
549 NULL,
550 NULL);
551
552 /* Insert the two objects we already created but couldn't add */
553 /* NOTE: Uses TypeList & Creator Info in OB 2.0 */
554 ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObTypeObjectType), NULL);
555 ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObDirectoryType), NULL);
556
557 /* Create 'symbolic link' object type */
558 ObInitSymbolicLinkImplementation();
559
560 /* FIXME: Hack Hack! */
561 ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
562 RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
563 }
564
565 NTSTATUS
566 STDCALL
567 ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
568 PUNICODE_STRING TypeName,
569 POBJECT_TYPE *ObjectType)
570 {
571 POBJECT_HEADER Header;
572 POBJECT_TYPE LocalObjectType;
573 ULONG HeaderSize;
574 NTSTATUS Status;
575
576 DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", TypeName);
577
578 /* Allocate the Object */
579 Status = ObpAllocateObject(NULL,
580 TypeName,
581 ObTypeObjectType,
582 OBJECT_ALLOC_SIZE(sizeof(OBJECT_TYPE)),
583 &Header);
584 if (!NT_SUCCESS(Status))
585 {
586 DPRINT1("ObpAllocateObject failed!\n");
587 return Status;
588 }
589
590 LocalObjectType = (POBJECT_TYPE)&Header->Body;
591 DPRINT("Local ObjectType: %p Header: %p \n", LocalObjectType, Header);
592
593 /* Check if this is the first Object Type */
594 if (!ObTypeObjectType)
595 {
596 ObTypeObjectType = LocalObjectType;
597 Header->Type = ObTypeObjectType;
598 LocalObjectType->Key = TAG('O', 'b', 'j', 'T');
599 }
600 else
601 {
602 CHAR Tag[4];
603 Tag[0] = TypeName->Buffer[0];
604 Tag[1] = TypeName->Buffer[1];
605 Tag[2] = TypeName->Buffer[2];
606 Tag[3] = TypeName->Buffer[3];
607
608 /* Set Tag */
609 DPRINT("Convert: %s \n", Tag);
610 LocalObjectType->Key = *(PULONG)Tag;
611 }
612
613 /* Set it up */
614 LocalObjectType->TypeInfo = *ObjectTypeInitializer;
615 LocalObjectType->Name = *TypeName;
616 LocalObjectType->TypeInfo.PoolType = ObjectTypeInitializer->PoolType;
617
618 /* These two flags need to be manually set up */
619 Header->Flags |= OB_FLAG_KERNEL_MODE | OB_FLAG_PERMANENT;
620
621 /* Check if we have to maintain a type list */
622 if (NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST)
623 {
624 /* Enable support */
625 LocalObjectType->TypeInfo.MaintainTypeList = TRUE;
626 }
627
628 /* Calculate how much space our header'll take up */
629 HeaderSize = sizeof(OBJECT_HEADER) + sizeof(OBJECT_HEADER_NAME_INFO) +
630 (ObjectTypeInitializer->MaintainHandleCount ?
631 sizeof(OBJECT_HEADER_HANDLE_INFO) : 0);
632
633 /* Update the Pool Charges */
634 if (ObjectTypeInitializer->PoolType == NonPagedPool)
635 {
636 LocalObjectType->TypeInfo.DefaultNonPagedPoolCharge += HeaderSize;
637 }
638 else
639 {
640 LocalObjectType->TypeInfo.DefaultPagedPoolCharge += HeaderSize;
641 }
642
643 /* All objects types need a security procedure */
644 if (!ObjectTypeInitializer->SecurityProcedure)
645 {
646 LocalObjectType->TypeInfo.SecurityProcedure = SeDefaultObjectMethod;
647 }
648
649 /* Select the Wait Object */
650 if (LocalObjectType->TypeInfo.UseDefaultObject)
651 {
652 /* Add the SYNCHRONIZE access mask since it's waitable */
653 LocalObjectType->TypeInfo.ValidAccessMask |= SYNCHRONIZE;
654
655 /* Use the "Default Object", a simple event */
656 LocalObjectType->DefaultObject = &ObpDefaultObject;
657 }
658 /* Special system objects get an optimized hack so they can be waited on */
659 else if (TypeName->Length == 8 && !wcscmp(TypeName->Buffer, L"File"))
660 {
661 LocalObjectType->DefaultObject = (PVOID)FIELD_OFFSET(FILE_OBJECT, Event);
662 }
663 /* FIXME: When LPC stops sucking, add a hack for Waitable Ports */
664 else
665 {
666 /* No default Object */
667 LocalObjectType->DefaultObject = NULL;
668 }
669
670 /* Initialize Object Type components */
671 ExInitializeResourceLite(&LocalObjectType->Mutex);
672 InitializeListHead(&LocalObjectType->TypeList);
673
674 /* Insert it into the Object Directory */
675 if (ObpTypeDirectoryObject)
676 {
677 ObpAddEntryDirectory(ObpTypeDirectoryObject, Header, TypeName->Buffer);
678 ObReferenceObject(ObpTypeDirectoryObject);
679 }
680
681 *ObjectType = LocalObjectType;
682 return Status;
683 }
684
685 /* EOF */