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