1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ob/obinit.c 5 * PURPOSE: Handles Object Manager Initialization and Shutdown 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 * Eric Kohl 8 * Thomas Weidenmueller (w3seek@reactos.org) 9 */ 10 11 /* INCLUDES ******************************************************************/ 12 13 #include <ntoskrnl.h> 14 #define NDEBUG 15 #include <debug.h> 16 17 /* GLOBALS *******************************************************************/ 18 19 GENERIC_MAPPING ObpTypeMapping = 20 { 21 STANDARD_RIGHTS_READ, 22 STANDARD_RIGHTS_WRITE, 23 STANDARD_RIGHTS_EXECUTE, 24 0x000F0001 25 }; 26 27 GENERIC_MAPPING ObpDirectoryMapping = 28 { 29 STANDARD_RIGHTS_READ | DIRECTORY_QUERY | 30 DIRECTORY_TRAVERSE, 31 STANDARD_RIGHTS_WRITE | DIRECTORY_CREATE_SUBDIRECTORY | 32 DIRECTORY_CREATE_OBJECT, 33 STANDARD_RIGHTS_EXECUTE | DIRECTORY_QUERY | 34 DIRECTORY_TRAVERSE, 35 DIRECTORY_ALL_ACCESS 36 }; 37 38 GENERIC_MAPPING ObpSymbolicLinkMapping = 39 { 40 STANDARD_RIGHTS_READ | SYMBOLIC_LINK_QUERY, 41 STANDARD_RIGHTS_WRITE, 42 STANDARD_RIGHTS_EXECUTE | SYMBOLIC_LINK_QUERY, 43 SYMBOLIC_LINK_ALL_ACCESS 44 }; 45 46 PDEVICE_MAP ObSystemDeviceMap = NULL; 47 ULONG ObpTraceLevel = 0; 48 49 VOID 50 NTAPI 51 PsInitializeQuotaSystem(VOID); 52 53 ULONG ObpInitializationPhase; 54 55 /* PRIVATE FUNCTIONS *********************************************************/ 56 57 static 58 NTSTATUS 59 NTAPI 60 INIT_FUNCTION 61 ObpCreateKernelObjectsSD(OUT PSECURITY_DESCRIPTOR *SecurityDescriptor) 62 { 63 PSECURITY_DESCRIPTOR Sd = NULL; 64 PACL Dacl; 65 ULONG AclSize, SdSize; 66 NTSTATUS Status; 67 68 AclSize = sizeof(ACL) + 69 sizeof(ACE) + RtlLengthSid(SeWorldSid) + 70 sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid) + 71 sizeof(ACE) + RtlLengthSid(SeLocalSystemSid); 72 73 SdSize = sizeof(SECURITY_DESCRIPTOR) + AclSize; 74 75 /* Allocate the SD and ACL */ 76 Sd = ExAllocatePoolWithTag(PagedPool, SdSize, TAG_SD); 77 if (Sd == NULL) 78 { 79 return STATUS_INSUFFICIENT_RESOURCES; 80 } 81 82 /* Initialize the SD */ 83 Status = RtlCreateSecurityDescriptor(Sd, 84 SECURITY_DESCRIPTOR_REVISION); 85 if (!NT_SUCCESS(Status)) 86 goto done; 87 88 Dacl = (PACL)((INT_PTR)Sd + sizeof(SECURITY_DESCRIPTOR)); 89 90 /* Initialize the DACL */ 91 RtlCreateAcl(Dacl, AclSize, ACL_REVISION); 92 93 /* Add the ACEs */ 94 RtlAddAccessAllowedAce(Dacl, 95 ACL_REVISION, 96 GENERIC_READ, 97 SeWorldSid); 98 99 RtlAddAccessAllowedAce(Dacl, 100 ACL_REVISION, 101 GENERIC_ALL, 102 SeAliasAdminsSid); 103 104 RtlAddAccessAllowedAce(Dacl, 105 ACL_REVISION, 106 GENERIC_ALL, 107 SeLocalSystemSid); 108 109 /* Attach the DACL to the SD */ 110 Status = RtlSetDaclSecurityDescriptor(Sd, 111 TRUE, 112 Dacl, 113 FALSE); 114 if (!NT_SUCCESS(Status)) 115 goto done; 116 117 *SecurityDescriptor = Sd; 118 119 done: 120 if (!NT_SUCCESS(Status)) 121 { 122 if (Sd != NULL) 123 ExFreePoolWithTag(Sd, TAG_SD); 124 } 125 126 return Status; 127 } 128 129 BOOLEAN 130 INIT_FUNCTION 131 NTAPI 132 ObInit2(VOID) 133 { 134 CCHAR i; 135 PKPRCB Prcb; 136 PGENERAL_LOOKASIDE CurrentList = NULL; 137 138 /* Now allocate the per-processor lists */ 139 for (i = 0; i < KeNumberProcessors; i++) 140 { 141 /* Get the PRCB for this CPU */ 142 Prcb = KiProcessorBlock[(int)i]; 143 144 /* Set the OBJECT_CREATE_INFORMATION List */ 145 Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList; 146 CurrentList = ExAllocatePoolWithTag(NonPagedPool, 147 sizeof(GENERAL_LOOKASIDE), 148 'ICbO'); 149 if (CurrentList) 150 { 151 /* Initialize it */ 152 ExInitializeSystemLookasideList(CurrentList, 153 NonPagedPool, 154 sizeof(OBJECT_CREATE_INFORMATION), 155 'ICbO', 156 32, 157 &ExSystemLookasideListHead); 158 } 159 else 160 { 161 /* No list, use the static buffer */ 162 CurrentList = &ObpCreateInfoLookasideList; 163 } 164 165 /* Link it */ 166 Prcb->PPLookasideList[LookasideCreateInfoList].P = CurrentList; 167 168 /* Set the captured UNICODE_STRING Object Name List */ 169 Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList; 170 CurrentList = ExAllocatePoolWithTag(NonPagedPool, 171 sizeof(GENERAL_LOOKASIDE), 172 'MNbO'); 173 if (CurrentList) 174 { 175 /* Initialize it */ 176 ExInitializeSystemLookasideList(CurrentList, 177 PagedPool, 178 248, 179 'MNbO', 180 16, 181 &ExSystemLookasideListHead); 182 } 183 else 184 { 185 /* No list, use the static buffer */ 186 CurrentList = &ObpNameBufferLookasideList; 187 } 188 189 /* Link it */ 190 Prcb->PPLookasideList[LookasideNameBufferList].P = CurrentList; 191 } 192 193 return TRUE; 194 } 195 196 BOOLEAN 197 INIT_FUNCTION 198 NTAPI 199 ObInitSystem(VOID) 200 { 201 OBJECT_ATTRIBUTES ObjectAttributes; 202 UNICODE_STRING Name; 203 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 204 OBP_LOOKUP_CONTEXT Context; 205 HANDLE Handle; 206 PKPRCB Prcb = KeGetCurrentPrcb(); 207 PLIST_ENTRY ListHead, NextEntry; 208 POBJECT_HEADER Header; 209 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 210 POBJECT_HEADER_NAME_INFO NameInfo; 211 PSECURITY_DESCRIPTOR KernelObjectsSD = NULL; 212 NTSTATUS Status; 213 214 /* Check if this is actually Phase 1 initialization */ 215 if (ObpInitializationPhase != 0) goto ObPostPhase0; 216 217 /* Initialize the OBJECT_CREATE_INFORMATION List */ 218 ExInitializeSystemLookasideList(&ObpCreateInfoLookasideList, 219 NonPagedPool, 220 sizeof(OBJECT_CREATE_INFORMATION), 221 'ICbO', 222 32, 223 &ExSystemLookasideListHead); 224 225 /* Set the captured UNICODE_STRING Object Name List */ 226 ExInitializeSystemLookasideList(&ObpNameBufferLookasideList, 227 PagedPool, 228 248, 229 'MNbO', 230 16, 231 &ExSystemLookasideListHead); 232 233 /* Temporarily setup both pointers to the shared list */ 234 Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList; 235 Prcb->PPLookasideList[LookasideCreateInfoList].P = &ObpCreateInfoLookasideList; 236 Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList; 237 Prcb->PPLookasideList[LookasideNameBufferList].P = &ObpNameBufferLookasideList; 238 239 /* Initialize the security descriptor cache */ 240 ObpInitSdCache(); 241 242 /* Initialize the Default Event */ 243 KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE); 244 245 /* Initialize the Dos Device Map mutex */ 246 KeInitializeGuardedMutex(&ObpDeviceMapLock); 247 248 /* Setup default access for the system process */ 249 PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS; 250 PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS; 251 252 /* Setup the Object Reaper */ 253 ExInitializeWorkItem(&ObpReaperWorkItem, ObpReapObject, NULL); 254 255 /* Initialize default Quota block */ 256 PsInitializeQuotaSystem(); 257 258 /* Create kernel handle table */ 259 PsGetCurrentProcess()->ObjectTable = ExCreateHandleTable(NULL); 260 ObpKernelHandleTable = PsGetCurrentProcess()->ObjectTable; 261 262 /* Create the Type Type */ 263 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); 264 RtlInitUnicodeString(&Name, L"Type"); 265 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 266 ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS; 267 ObjectTypeInitializer.UseDefaultObject = TRUE; 268 ObjectTypeInitializer.MaintainTypeList = TRUE; 269 ObjectTypeInitializer.PoolType = NonPagedPool; 270 ObjectTypeInitializer.GenericMapping = ObpTypeMapping; 271 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE); 272 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 273 ObjectTypeInitializer.DeleteProcedure = ObpDeleteObjectType; 274 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObpTypeObjectType); 275 276 /* Create the Directory Type */ 277 RtlInitUnicodeString(&Name, L"Directory"); 278 ObjectTypeInitializer.PoolType = PagedPool; 279 ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS; 280 ObjectTypeInitializer.CaseInsensitive = TRUE; 281 ObjectTypeInitializer.MaintainTypeList = FALSE; 282 ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping; 283 ObjectTypeInitializer.DeleteProcedure = NULL; 284 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY); 285 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObDirectoryType); 286 ObDirectoryType->TypeInfo.ValidAccessMask &= ~SYNCHRONIZE; 287 288 /* Create 'symbolic link' object type */ 289 RtlInitUnicodeString(&Name, L"SymbolicLink"); 290 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_SYMBOLIC_LINK); 291 ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping; 292 ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS; 293 ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink; 294 ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink; 295 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObSymbolicLinkType); 296 ObSymbolicLinkType->TypeInfo.ValidAccessMask &= ~SYNCHRONIZE; 297 298 /* Phase 0 initialization complete */ 299 ObpInitializationPhase++; 300 return TRUE; 301 302 ObPostPhase0: 303 304 /* Re-initialize lookaside lists */ 305 ObInit2(); 306 307 /* Initialize Object Types directory attributes */ 308 RtlInitUnicodeString(&Name, L"\\"); 309 InitializeObjectAttributes(&ObjectAttributes, 310 &Name, 311 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 312 NULL, 313 SePublicDefaultUnrestrictedSd); 314 315 /* Create the directory */ 316 Status = NtCreateDirectoryObject(&Handle, 317 DIRECTORY_ALL_ACCESS, 318 &ObjectAttributes); 319 if (!NT_SUCCESS(Status)) return FALSE; 320 321 /* Get a handle to it */ 322 Status = ObReferenceObjectByHandle(Handle, 323 0, 324 ObDirectoryType, 325 KernelMode, 326 (PVOID*)&ObpRootDirectoryObject, 327 NULL); 328 if (!NT_SUCCESS(Status)) return FALSE; 329 330 /* Close the extra handle */ 331 Status = NtClose(Handle); 332 if (!NT_SUCCESS(Status)) return FALSE; 333 334 /* Create a custom security descriptor for the KernelObjects directory */ 335 Status = ObpCreateKernelObjectsSD(&KernelObjectsSD); 336 if (!NT_SUCCESS(Status)) 337 return FALSE; 338 339 /* Initialize the KernelObjects directory attributes */ 340 RtlInitUnicodeString(&Name, L"\\KernelObjects"); 341 InitializeObjectAttributes(&ObjectAttributes, 342 &Name, 343 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 344 NULL, 345 KernelObjectsSD); 346 347 /* Create the directory */ 348 Status = NtCreateDirectoryObject(&Handle, 349 DIRECTORY_ALL_ACCESS, 350 &ObjectAttributes); 351 ExFreePoolWithTag(KernelObjectsSD, TAG_SD); 352 if (!NT_SUCCESS(Status)) return FALSE; 353 354 /* Close the extra handle */ 355 Status = NtClose(Handle); 356 if (!NT_SUCCESS(Status)) return FALSE; 357 358 /* Initialize ObjectTypes directory attributes */ 359 RtlInitUnicodeString(&Name, L"\\ObjectTypes"); 360 InitializeObjectAttributes(&ObjectAttributes, 361 &Name, 362 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 363 NULL, 364 NULL); 365 366 /* Create the directory */ 367 Status = NtCreateDirectoryObject(&Handle, 368 DIRECTORY_ALL_ACCESS, 369 &ObjectAttributes); 370 if (!NT_SUCCESS(Status)) return FALSE; 371 372 /* Get a handle to it */ 373 Status = ObReferenceObjectByHandle(Handle, 374 0, 375 ObDirectoryType, 376 KernelMode, 377 (PVOID*)&ObpTypeDirectoryObject, 378 NULL); 379 if (!NT_SUCCESS(Status)) return FALSE; 380 381 /* Close the extra handle */ 382 Status = NtClose(Handle); 383 if (!NT_SUCCESS(Status)) return FALSE; 384 385 /* Initialize lookup context */ 386 ObpInitializeLookupContext(&Context); 387 388 /* Lock it */ 389 ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); 390 391 /* Loop the object types */ 392 ListHead = &ObpTypeObjectType->TypeList; 393 NextEntry = ListHead->Flink; 394 while (ListHead != NextEntry) 395 { 396 /* Get the creator info from the list */ 397 CreatorInfo = CONTAINING_RECORD(NextEntry, 398 OBJECT_HEADER_CREATOR_INFO, 399 TypeList); 400 401 /* Recover the header and the name header from the creator info */ 402 Header = (POBJECT_HEADER)(CreatorInfo + 1); 403 NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header); 404 405 /* Make sure we have a name, and aren't inserted yet */ 406 if ((NameInfo) && !(NameInfo->Directory)) 407 { 408 /* Do the initial lookup to setup the context */ 409 if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject, 410 &NameInfo->Name, 411 OBJ_CASE_INSENSITIVE, 412 FALSE, 413 &Context)) 414 { 415 /* Insert this object type */ 416 ObpInsertEntryDirectory(ObpTypeDirectoryObject, 417 &Context, 418 Header); 419 } 420 } 421 422 /* Move to the next entry */ 423 NextEntry = NextEntry->Flink; 424 } 425 426 /* Cleanup after lookup */ 427 ObpReleaseLookupContext(&Context); 428 429 /* Initialize DOS Devices Directory and related Symbolic Links */ 430 Status = ObpCreateDosDevicesDirectory(); 431 if (!NT_SUCCESS(Status)) return FALSE; 432 return TRUE; 433 } 434 435 /* EOF */ 436