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