VOID NTAPI INIT_FUNCTION CmpInitializeCache(VOID) { ULONG Length, i; /* Calculate length for the table */ Length = CmpHashTableSize * sizeof(CM_KEY_HASH_TABLE_ENTRY); /* Allocate it */ CmpCacheTable = CmpAllocate(Length, TRUE, TAG_CM); if (!CmpCacheTable) { /* Take the system down */ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 1, 0, 0); } /* Zero out the table */ RtlZeroMemory(CmpCacheTable, Length); /* Initialize the locks */ for (i = 0; i < CmpHashTableSize; i++) { /* Setup the pushlock */ ExInitializePushLock(&CmpCacheTable[i].Lock); } /* Calculate length for the name cache */ Length = CmpHashTableSize * sizeof(CM_NAME_HASH_TABLE_ENTRY); /* Now allocate the name cache table */ CmpNameCacheTable = CmpAllocate(Length, TRUE, TAG_CM); if (!CmpNameCacheTable) { /* Take the system down */ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 3, 0, 0); } /* Zero out the table */ RtlZeroMemory(CmpNameCacheTable, Length); /* Initialize the locks */ for (i = 0; i < CmpHashTableSize; i++) { /* Setup the pushlock */ ExInitializePushLock(&CmpNameCacheTable[i].Lock); } /* Setup the delayed close table */ CmpInitializeDelayedCloseTable(); }
PGDI_POOL NTAPI GdiPoolCreate( ULONG cjAllocSize, ULONG ulTag) { PGDI_POOL pPool; /* Allocate a pool object */ pPool = EngAllocMem(0, sizeof(GDI_POOL), 'lopG'); if (!pPool) return NULL; /* Initialize the object */ ExInitializePushLock(&pPool->pushlock); InitializeListHead(&pPool->leInUseList); InitializeListHead(&pPool->leReadyList); InitializeListHead(&pPool->leEmptyList); pPool->cEmptySections = 0; pPool->cjAllocSize = cjAllocSize; pPool->ulTag = ulTag; pPool->cjSectionSize = GDI_POOL_ALLOCATION_GRANULARITY; pPool->cSlotsPerSection = pPool->cjSectionSize / cjAllocSize; DBG_INITLOG(&pPool->slhLog); return pPool; }
void RtlpInitializeLockAtomTable( IN OUT PRTL_ATOM_TABLE AtomTable ) { ExInitializePushLock( &AtomTable->PushLock ); return; }
VOID NTAPI INIT_FUNCTION ExpInitializeHandleTables(VOID) { /* Initialize the list of handle tables and the lock */ InitializeListHead(&HandleTableListHead); ExInitializePushLock(&HandleTableListLock); }
VOID ExpInitializePushLocks ( VOID ) /*++ Routine Description: Calculates the value of the pushlock spin count Arguments: None Return Value: None --*/ { #if defined(_AMD64_) EX_PUSH_LOCK ScratchPushLock; #endif #if !NT_UP if (KeNumberProcessors > 1) { ExPushLockSpinCount = 1024; } else { ExPushLockSpinCount = 0; } #endif // // Exercise the following routines early, in order to patch any // prefetchw instructions therein. // #if defined(_AMD64_) ExInitializePushLock( &ScratchPushLock ); ExfAcquirePushLockShared( &ScratchPushLock ); ExfReleasePushLock( &ScratchPushLock ); ExfAcquirePushLockShared( &ScratchPushLock ); ExfReleasePushLockShared( &ScratchPushLock ); ExfAcquirePushLockExclusive( &ScratchPushLock ); ExfReleasePushLockExclusive( &ScratchPushLock ); #endif }
VOID KphTestPushLock() { ULONG i; ExInitializePushLock(&TestLock); for (i = 0; i < 10; i++) { HANDLE threadHandle; OBJECT_ATTRIBUTES objectAttributes; InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); PsCreateSystemThread(&threadHandle, 0, &objectAttributes, NULL, NULL, KphpTestPushLockThreadStart, NULL); } }
NTSTATUS NTAPI INIT_FUNCTION ObpInitSdCache(VOID) { ULONG i; /* Loop each cache entry */ for (i = 0; i < SD_CACHE_ENTRIES; i++) { /* Initialize the lock and the list */ InitializeListHead(&ObsSecurityDescriptorCache[i].Head); ExInitializePushLock(&ObsSecurityDescriptorCache[i].PushLock); } /* Return success */ return STATUS_SUCCESS; }
NTSTATUS NTAPI CmpInitializeHive(OUT PCMHIVE *RegistryHive, IN ULONG OperationType, IN ULONG HiveFlags, IN ULONG FileType, IN PVOID HiveData OPTIONAL, IN HANDLE Primary, IN HANDLE Log, IN HANDLE External, IN PCUNICODE_STRING FileName OPTIONAL, IN ULONG CheckFlags) { PCMHIVE Hive; FILE_STANDARD_INFORMATION FileInformation; IO_STATUS_BLOCK IoStatusBlock; FILE_FS_SIZE_INFORMATION FileSizeInformation; NTSTATUS Status; ULONG Cluster; /* Assume failure */ *RegistryHive = NULL; /* * The following are invalid: * An external hive that is also internal. * A log hive that's not a primary hive too. * A volatile hive that's linked to permanent storage. * An in-memory initialization without hive data. * A log hive that's not linked to a correct file type. */ if (((External) && ((Primary) || (Log))) || ((Log) && !(Primary)) || ((HiveFlags & HIVE_VOLATILE) && ((Primary) || (External) || (Log))) || ((OperationType == HINIT_MEMORY) && (!HiveData)) || ((Log) && (FileType != HFILE_TYPE_LOG))) { /* Fail the request */ return STATUS_INVALID_PARAMETER; } /* Check if this is a primary hive */ if (Primary) { /* Get the cluster size */ Status = ZwQueryVolumeInformationFile(Primary, &IoStatusBlock, &FileSizeInformation, sizeof(FILE_FS_SIZE_INFORMATION), FileFsSizeInformation); if (!NT_SUCCESS(Status)) return Status; /* Make sure it's not larger then the block size */ if (FileSizeInformation.BytesPerSector > HBLOCK_SIZE) { /* Fail */ return STATUS_REGISTRY_IO_FAILED; } /* Otherwise, calculate the cluster */ Cluster = FileSizeInformation.BytesPerSector / HSECTOR_SIZE; Cluster = max(1, Cluster); } else { /* Otherwise use cluster 1 */ Cluster = 1; } /* Allocate the hive */ Hive = ExAllocatePoolWithTag(NonPagedPool, sizeof(CMHIVE), TAG_CMHIVE); if (!Hive) return STATUS_INSUFFICIENT_RESOURCES; /* Setup null fields */ Hive->UnloadEvent = NULL; Hive->RootKcb = NULL; Hive->Frozen = FALSE; Hive->UnloadWorkItem = NULL; Hive->GrowOnlyMode = FALSE; Hive->GrowOffset = 0; Hive->CellRemapArray = NULL; Hive->UseCountLog.Next = 0; Hive->LockHiveLog.Next = 0; Hive->FileObject = NULL; Hive->NotifyList.Flink = NULL; Hive->NotifyList.Blink = NULL; /* Set loading flag */ Hive->HiveIsLoading = TRUE; /* Set the current thread as creator */ Hive->CreatorOwner = KeGetCurrentThread(); /* Initialize lists */ InitializeListHead(&Hive->KcbConvertListHead); InitializeListHead(&Hive->KnodeConvertListHead); InitializeListHead(&Hive->TrustClassEntry); /* Allocate the view log */ Hive->ViewLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(KGUARDED_MUTEX), TAG_CMHIVE); if (!Hive->ViewLock) { /* Cleanup allocation and fail */ ExFreePoolWithTag(Hive, TAG_CMHIVE); return STATUS_INSUFFICIENT_RESOURCES; } /* Allocate the flush lock */ Hive->FlusherLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERESOURCE), TAG_CMHIVE); if (!Hive->FlusherLock) { /* Cleanup allocations and fail */ ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE); ExFreePoolWithTag(Hive, TAG_CMHIVE); return STATUS_INSUFFICIENT_RESOURCES; } /* Setup the handles */ Hive->FileHandles[HFILE_TYPE_PRIMARY] = Primary; Hive->FileHandles[HFILE_TYPE_LOG] = Log; Hive->FileHandles[HFILE_TYPE_EXTERNAL] = External; /* Initailize the guarded mutex */ KeInitializeGuardedMutex(Hive->ViewLock); Hive->ViewLockOwner = NULL; /* Initialize the flush lock */ ExInitializeResourceLite(Hive->FlusherLock); /* Setup hive locks */ ExInitializePushLock(&Hive->HiveLock); Hive->HiveLockOwner = NULL; ExInitializePushLock(&Hive->WriterLock); Hive->WriterLockOwner = NULL; ExInitializePushLock(&Hive->SecurityLock); Hive->HiveSecurityLockOwner = NULL; /* Clear file names */ RtlInitEmptyUnicodeString(&Hive->FileUserName, NULL, 0); RtlInitEmptyUnicodeString(&Hive->FileFullPath, NULL, 0); /* Initialize the view list */ CmpInitHiveViewList(Hive); /* Initailize the security cache */ CmpInitSecurityCache(Hive); /* Setup flags */ Hive->Flags = 0; Hive->FlushCount = 0; /* Set flags */ Hive->Flags = HiveFlags; /* Check if this is a primary */ if (Primary) { /* Check how large the file is */ ZwQueryInformationFile(Primary, &IoStatusBlock, &FileInformation, sizeof(FileInformation), FileStandardInformation); Cluster = FileInformation.EndOfFile.LowPart; } /* Initialize it */ Status = HvInitialize(&Hive->Hive, OperationType, FileType, HiveFlags, HiveData, CmpAllocate, CmpFree, CmpFileSetSize, CmpFileWrite, CmpFileRead, CmpFileFlush, Cluster, FileName); if (!NT_SUCCESS(Status)) { /* Cleanup allocations and fail */ ExDeleteResourceLite(Hive->FlusherLock); ExFreePoolWithTag(Hive->FlusherLock, TAG_CMHIVE); ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE); ExFreePoolWithTag(Hive, TAG_CMHIVE); return Status; } /* Check if we should verify the registry */ if ((OperationType == HINIT_FILE) || (OperationType == HINIT_MEMORY) || (OperationType == HINIT_MEMORY_INPLACE) || (OperationType == HINIT_MAPFILE)) { /* Verify integrity */ ULONG CheckStatus = CmCheckRegistry(Hive, CheckFlags); if (CheckStatus != 0) { /* Cleanup allocations and fail */ ExDeleteResourceLite(Hive->FlusherLock); ExFreePoolWithTag(Hive->FlusherLock, TAG_CMHIVE); ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE); ExFreePoolWithTag(Hive, TAG_CMHIVE); return STATUS_REGISTRY_CORRUPT; } } /* Lock the hive list */ ExAcquirePushLockExclusive(&CmpHiveListHeadLock); /* Insert this hive */ InsertHeadList(&CmpHiveListHead, &Hive->HiveList); /* Release the lock */ ExReleasePushLock(&CmpHiveListHeadLock); /* Return the hive and success */ *RegistryHive = (PCMHIVE)Hive; return STATUS_SUCCESS; }
NTKERNELAPI PEX_PUSH_LOCK_CACHE_AWARE ExAllocateCacheAwarePushLock ( VOID ) /*++ Routine Description: Allocate a cache aware (cache friendly) push lock Arguments: None Return Value: None --*/ { PEX_PUSH_LOCK_CACHE_AWARE PushLockCacheAware; PEX_PUSH_LOCK_CACHE_AWARE_PADDED PaddedPushLock; ULONG i, j, MaxLine; PushLockCacheAware = ExAllocatePoolWithTag (PagedPool, sizeof (EX_PUSH_LOCK_CACHE_AWARE), 'pclP'); if (PushLockCacheAware != NULL) { // // If we are a non-numa machine then allocate the padded push locks as a single block // if (KeNumberNodes == 1) { PaddedPushLock = ExAllocatePoolWithTag (PagedPool, sizeof (EX_PUSH_LOCK_CACHE_AWARE_PADDED)* EX_PUSH_LOCK_FANNED_COUNT, 'lclP'); if (PaddedPushLock == NULL) { ExFreePool (PushLockCacheAware); return NULL; } for (i = 0; i < EX_PUSH_LOCK_FANNED_COUNT; i++) { PaddedPushLock->Single = TRUE; ExInitializePushLock (&PaddedPushLock->Lock); PushLockCacheAware->Locks[i] = &PaddedPushLock->Lock; PaddedPushLock++; } } else { // // Allocate a different block for each lock and set affinity // so the allocation comes from that node's memory. // MaxLine = KeNumberProcessors; if (MaxLine > EX_PUSH_LOCK_FANNED_COUNT) { MaxLine = EX_PUSH_LOCK_FANNED_COUNT; } for (i = 0; i < MaxLine; i++) { KeSetSystemAffinityThread (AFFINITY_MASK (i)); PaddedPushLock = ExAllocatePoolWithTag (PagedPool, sizeof (EX_PUSH_LOCK_CACHE_AWARE_PADDED), 'lclP'); if (PaddedPushLock == NULL) { for (j = 0; j < i; j++) { ExFreePool (PushLockCacheAware->Locks[j]); } KeRevertToUserAffinityThread (); ExFreePool (PushLockCacheAware); return NULL; } PaddedPushLock->Single = FALSE; ExInitializePushLock (&PaddedPushLock->Lock); PushLockCacheAware->Locks[i] = &PaddedPushLock->Lock; } KeRevertToUserAffinityThread (); } } return PushLockCacheAware; }
BOOLEAN ExpInitializeCallbacks ( ) /*++ Routine Description: This function creates the callback object type descriptor at system initialization and stores the address of the object type descriptor in local static storage. Arguments: None. Return Value: A value of TRUE is returned if the timer object type descriptor is successfully initialized. Otherwise a value of FALSE is returned. --*/ { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; UNICODE_STRING unicodeString; ULONG i; HANDLE handle; // // Initialize the slow referencing lock // ExInitializePushLock (&ExpCallBackFlush); // // Initialize string descriptor. // RtlInitUnicodeString(&unicodeString, L"Callback"); // // Create timer object type descriptor. // RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; ObjectTypeInitializer.GenericMapping = ExpCallbackMapping; ObjectTypeInitializer.DeleteProcedure = ExpDeleteCallback; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = CALLBACK_ALL_ACCESS; Status = ObCreateObjectType(&unicodeString, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ExCallbackObjectType); if (!NT_SUCCESS(Status)) { return FALSE; } RtlInitUnicodeString( &unicodeString, ExpWstrCallback ); InitializeObjectAttributes( &ObjectAttributes, &unicodeString, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, SePublicDefaultSd ); Status = NtCreateDirectoryObject( &handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS(Status)) { return FALSE; } NtClose (handle); // // Initialize event to wait on for Unregisters which occur while // notifications are in progress // KeInitializeEvent (&ExpCallbackEvent, NotificationEvent, 0); // // Initialize NT global callbacks // for (i=0; ExpInitializeCallback[i].CallBackObject; i++) { // // Create named calledback // RtlInitUnicodeString(&unicodeString, ExpInitializeCallback[i].CallbackName); InitializeObjectAttributes( &ObjectAttributes, &unicodeString, OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ExCreateCallback ( ExpInitializeCallback[i].CallBackObject, &ObjectAttributes, TRUE, TRUE ); if (!NT_SUCCESS(Status)) { return FALSE; } } return TRUE; }