void Thread::Thread_init() { PsCreateSystemThreadEx(&system_thread_handle, // Thread Handle 0, // KernelStackSize stack_size, // Stack Size 0, // TlsDataSize &Id, // Thread ID NULL, // StartContext1 NULL, // StartContext2 TRUE, // CreateSuspended FALSE, // DebugStack (PKSTART_ROUTINE)&callback); // StartRoutine ObReferenceObjectByHandle(system_thread_handle, (POBJECT_TYPE)PsThreadObjectType, &system_thread_handle); //#define LOW_PRIORITY 0 //#define LOW_REALTIME_PRIORITY 16 //#define HIGH_PRIORITY 31 //#define MAXIMUM_PRIORITY 32 KeSetBasePriorityThread((PKTHREAD)system_thread_handle, (PVOID)0); //Default the thread to low priority state = ThreadState::Unstarted; Id = GlobalId++; //increment Id so every thread Id is unique }
void Thread::SetPriority(int priority) { if((priority != 0) && (priority != 16) && (priority != 31) && (priority != 32)) return; //no valid values ObReferenceObjectByHandle(system_thread_handle, (POBJECT_TYPE)PsThreadObjectType, &system_thread_handle); KeSetBasePriorityThread((PKTHREAD)system_thread_handle, (PVOID)priority); }
/*++ * @name ExpWorkerThreadBalanceManager * * The ExpWorkerThreadBalanceManager routine is the entrypoint for the * worker thread balance set manager. * * @param Context * Unused. * * @return None. * * @remarks The worker thread balance set manager listens every second, but can * also be woken up by an event when a new thread is needed, or by the * special shutdown event. This thread runs at priority 7. * * This routine must run at IRQL == PASSIVE_LEVEL. * *--*/ VOID NTAPI ExpWorkerThreadBalanceManager(IN PVOID Context) { KTIMER Timer; LARGE_INTEGER Timeout; NTSTATUS Status; PVOID WaitEvents[3]; PAGED_CODE(); UNREFERENCED_PARAMETER(Context); /* Raise our priority above all other worker threads */ KeSetBasePriorityThread(KeGetCurrentThread(), EX_CRITICAL_QUEUE_PRIORITY_INCREMENT + 1); /* Setup the timer */ KeInitializeTimer(&Timer); Timeout.QuadPart = Int32x32To64(-1, 10000000); /* We'll wait on the periodic timer and also the emergency event */ WaitEvents[0] = &Timer; WaitEvents[1] = &ExpThreadSetManagerEvent; WaitEvents[2] = &ExpThreadSetManagerShutdownEvent; /* Start wait loop */ for (;;) { /* Wait for the timer */ KeSetTimer(&Timer, Timeout, NULL); Status = KeWaitForMultipleObjects(3, WaitEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (Status == 0) { /* Our timer expired. Check for deadlocks */ ExpDetectWorkerThreadDeadlock(); } else if (Status == 1) { /* Someone notified us, verify if we should create a new thread */ ExpCheckDynamicThreadCount(); } else if (Status == 2) { /* We are shutting down. Cancel the timer */ DPRINT1("System shutdown\n"); KeCancelTimer(&Timer); /* Make sure we have a final thread */ ASSERT(ExpLastWorkerThread); /* Wait for it */ KeWaitForSingleObject(ExpLastWorkerThread, Executive, KernelMode, FALSE, NULL); /* Dereference it and kill us */ ObDereferenceObject(ExpLastWorkerThread); PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN); } } }
/*++ * @name ExpCreateWorkerThread * * The ExpCreateWorkerThread routine creates a new worker thread for the * specified queue. ** * @param QueueType * Type of the queue to use for this thread. Valid values are: * - DelayedWorkQueue * - CriticalWorkQueue * - HyperCriticalWorkQueue * * @param Dynamic * Specifies whether or not this thread is a dynamic thread. * * @return None. * * @remarks HyperCritical work threads run at priority 7; Critical work threads * run at priority 5, and delayed work threads run at priority 4. * * This, worker threads cannot pre-empty a normal user-mode thread. * *--*/ VOID NTAPI ExpCreateWorkerThread(WORK_QUEUE_TYPE WorkQueueType, IN BOOLEAN Dynamic) { PETHREAD Thread; HANDLE hThread; ULONG Context; KPRIORITY Priority; /* Check if this is going to be a dynamic thread */ Context = WorkQueueType; /* Add the dynamic mask */ if (Dynamic) Context |= EX_DYNAMIC_WORK_THREAD; /* Create the System Thread */ PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, ExpWorkerThreadEntryPoint, UlongToPtr(Context)); /* If the thread is dynamic */ if (Dynamic) { /* Increase the count */ InterlockedIncrement(&ExWorkerQueue[WorkQueueType].DynamicThreadCount); } /* Set the priority */ if (WorkQueueType == DelayedWorkQueue) { /* Priority == 4 */ Priority = EX_DELAYED_QUEUE_PRIORITY_INCREMENT; } else if (WorkQueueType == CriticalWorkQueue) { /* Priority == 5 */ Priority = EX_CRITICAL_QUEUE_PRIORITY_INCREMENT; } else { /* Priority == 7 */ Priority = EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT; } /* Get the Thread */ ObReferenceObjectByHandle(hThread, THREAD_SET_INFORMATION, PsThreadType, KernelMode, (PVOID*)&Thread, NULL); /* Set the Priority */ KeSetBasePriorityThread(&Thread->Tcb, Priority); /* Dereference and close handle */ ObDereferenceObject(Thread); ObCloseHandle(hThread, KernelMode); }
NTSTATUS ExpCreateWorkerThread ( IN WORK_QUEUE_TYPE QueueType, IN BOOLEAN Dynamic ) /*++ Routine Description: This function creates a single new static or dynamic worker thread for the given queue type. Arguments: QueueType - Supplies the type of the queue for which the worker thread should be created. Dynamic - If TRUE, the worker thread is created as a dynamic thread that will terminate after a sufficient period of inactivity. If FALSE, the worker thread will never terminate. Return Value: The final status of the operation. Notes: This routine is only called from the worker thread set balance thread, therefore it will not be reentered. --*/ { OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; HANDLE ThreadHandle; ULONG Context; ULONG BasePriority; PETHREAD Thread; InitializeObjectAttributes (&ObjectAttributes, NULL, 0, NULL, NULL); Context = QueueType; if (Dynamic != FALSE) { Context |= DYNAMIC_WORKER_THREAD; } Status = PsCreateSystemThread (&ThreadHandle, THREAD_ALL_ACCESS, &ObjectAttributes, 0L, NULL, ExpWorkerThread, (PVOID)(ULONG_PTR)Context); if (!NT_SUCCESS(Status)) { return Status; } if (Dynamic != FALSE) { InterlockedIncrement ((PLONG)&ExWorkerQueue[QueueType].DynamicThreadCount); } // // Set the priority according to the type of worker thread. // switch (QueueType) { case HyperCriticalWorkQueue: BasePriority = HYPER_CRITICAL_WORK_QUEUE_PRIORITY; break; case CriticalWorkQueue: BasePriority = CRITICAL_WORK_QUEUE_PRIORITY; break; case DelayedWorkQueue: default: BasePriority = DELAYED_WORK_QUEUE_PRIORITY; break; } // // Set the base priority of the just-created thread. // Status = ObReferenceObjectByHandle (ThreadHandle, THREAD_SET_INFORMATION, PsThreadType, KernelMode, (PVOID *)&Thread, NULL); if (NT_SUCCESS(Status)) { KeSetBasePriorityThread (&Thread->Tcb, BasePriority); ObDereferenceObject (Thread); } ZwClose (ThreadHandle); return Status; }
VOID ExpWorkerThreadBalanceManager ( IN PVOID StartContext ) /*++ Routine Description: This function is the startup code for the worker thread manager thread. The worker thread manager thread is created during system initialization and begins execution in this function. This thread is responsible for detecting and breaking circular deadlocks in the system worker thread queues. It will also create and destroy additional worker threads as needed based on loading. Arguments: Context - Supplies a pointer to an arbitrary data structure (NULL). Return Value: None. --*/ { KTIMER PeriodTimer; LARGE_INTEGER DueTime; PVOID WaitObjects[MaximumBalanceObject]; NTSTATUS Status; PAGED_CODE(); UNREFERENCED_PARAMETER (StartContext); // // Raise the thread priority to just higher than the priority of the // critical work queue. // KeSetBasePriorityThread (KeGetCurrentThread(), CRITICAL_WORK_QUEUE_PRIORITY + 1); // // Initialize the periodic timer and set the manager period. // KeInitializeTimer (&PeriodTimer); DueTime.QuadPart = - THREAD_SET_INTERVAL; // // Initialize the wait object array. // WaitObjects[TimerExpiration] = (PVOID)&PeriodTimer; WaitObjects[ThreadSetManagerEvent] = (PVOID)&ExpThreadSetManagerEvent; WaitObjects[ShutdownEvent] = (PVOID)&ExpThreadSetManagerShutdownEvent; // // Loop forever processing events. // while (TRUE) { // // Set the timer to expire at the next periodic interval. // KeSetTimer (&PeriodTimer, DueTime, NULL); // // Wake up when the timer expires or the set manager event is // signaled. // Status = KeWaitForMultipleObjects (MaximumBalanceObject, WaitObjects, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); switch (Status) { case TimerExpiration: // // Periodic timer expiration - go see if any work queues // are deadlocked. // ExpDetectWorkerThreadDeadlock (); break; case ThreadSetManagerEvent: // // Someone has asked us to check some metrics to determine // whether we should create another worker thread. // ExpCheckDynamicThreadCount (); break; case ShutdownEvent: // // Time to exit... // KeCancelTimer (&PeriodTimer); ASSERT (ExpLastWorkerThread); // // Wait for the last worker thread to terminate // KeWaitForSingleObject (ExpLastWorkerThread, Executive, KernelMode, FALSE, NULL); ObDereferenceObject (ExpLastWorkerThread); PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN); break; } // // Special debugger support. // // This checks if special debugging routines need to be run on the // behalf of the debugger. // if (ExpDebuggerWork == 1) { ExInitializeWorkItem(&ExpDebuggerWorkItem, ExpDebuggerWorker, NULL); ExpDebuggerWork = 2; ExQueueWorkItem(&ExpDebuggerWorkItem, DelayedWorkQueue); } } }
BOOLEAN CLog::Init() { BOOLEAN bRet = FALSE; NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; HANDLE hThead = NULL; KdPrintKrnl(LOG_PRINTF_LEVEL_INFO, LOG_RECORED_LEVEL_NEEDNOT, L"begin"); __try { InitializeListHead(&ms_ListHead); KeInitializeSpinLock(&ms_SpLock); ExInitializeResourceLite(&ms_Lock); KeInitializeEvent(&ms_UnloadEvent, NotificationEvent, FALSE); ms_pLogFile = new(MEMORY_TAG_LOG) CKrnlStr; ms_pLogDir = new(MEMORY_TAG_LOG) CKrnlStr; ntStatus = PsCreateSystemThread( &hThead, GENERIC_ALL, NULL, NULL, NULL, ThreadStart, NULL ); if (!NT_SUCCESS(ntStatus)) { KdPrintKrnl(LOG_PRINTF_LEVEL_ERROR, LOG_RECORED_LEVEL_NEEDNOT, L"PsCreateSystemThread failed. (%x)", ntStatus); __leave; } ntStatus = ObReferenceObjectByHandle( hThead, GENERIC_ALL, *PsThreadType, KernelMode, (PVOID *)&ms_pEThread, NULL ); if (!NT_SUCCESS(ntStatus)) { KdPrintKrnl(LOG_PRINTF_LEVEL_ERROR, LOG_RECORED_LEVEL_NEEDNOT, L"ObReferenceObjectByHandle failed. (%x)", ntStatus); __leave; } KeSetBasePriorityThread(ms_pEThread, -4); ms_bCanInsertLog = TRUE; bRet = TRUE; } __finally { // 不要置为NULL if (ms_pEThread) ObDereferenceObject(ms_pEThread); if (hThead) { ZwClose(hThead); hThead = NULL; } if (!bRet) { delete ms_pLogFile; ms_pLogFile = NULL; delete ms_pLogDir; ms_pLogDir = NULL; ExDeleteResourceLite(&ms_Lock); RtlZeroMemory(&ms_Lock, sizeof(ms_Lock)); } } KdPrintKrnl(LOG_PRINTF_LEVEL_INFO, LOG_RECORED_LEVEL_NEEDNOT, L"end"); return bRet; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath) { NTSTATUS status = STATUS_SUCCESS; NTSTATUS symbolicLinkCreationStatus = STATUS_SUCCESS; UNICODE_STRING deviceName; UNICODE_STRING dosDeviceName; HANDLE threadHandle; NET_BUFFER_LIST_POOL_PARAMETERS nblPoolParams = {0}; UNICODE_STRING defaultSDDLString; #ifdef DEBUG DbgBreakPoint(); #endif status = drvCtlInit(driverObject); if (!NT_SUCCESS(status)) { goto Exit; } gDriverUnloading = FALSE; RtlInitUnicodeString(&defaultSDDLString, L"D:P(A;;GA;;;BU)"); RtlInitUnicodeString(&deviceName, DEVICE_NAME); status = IoCreateDeviceSecure( driverObject, 0, &deviceName, FILE_DEVICE_NETWORK, 0, FALSE, &defaultSDDLString, NULL, &gDeviceObject); if (!NT_SUCCESS(status)) { goto Exit; } RtlInitUnicodeString(&dosDeviceName, SYMBOLIC_LINK_NAME); status = IoCreateSymbolicLink(&dosDeviceName, &deviceName); symbolicLinkCreationStatus = status; if (!NT_SUCCESS(status)) { goto Exit; } status = FwpsInjectionHandleCreate0( AF_UNSPEC, FWPS_INJECTION_TYPE_STREAM, &gInjectionHandle); if (!NT_SUCCESS(status)) { goto Exit; } gNdisGenericObj = NdisAllocateGenericObject( driverObject, TAG_NDIS_OBJ, 0); if (gNdisGenericObj == NULL) { status = STATUS_NO_MEMORY; goto Exit; } nblPoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; nblPoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; nblPoolParams.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; nblPoolParams.fAllocateNetBuffer = TRUE; nblPoolParams.DataSize = 0; nblPoolParams.PoolTag = TAG_NBL_POOL; gNetBufferListPool = NdisAllocateNetBufferListPool( gNdisGenericObj, &nblPoolParams); if(gNetBufferListPool == NULL) { status = STATUS_NO_MEMORY; goto Exit; } InitializeListHead(&gPacketQueue); KeInitializeSpinLock(&gPacketQueueLock); InitializeListHead(&flowContextList); KeInitializeSpinLock(&flowContextListLock); KeInitializeEvent( &gWorkerEvent, NotificationEvent, FALSE ); status = RegisterCallouts(gDeviceObject); if (!NT_SUCCESS(status)) { goto Exit; } status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, thAnalyzer, NULL); if (!NT_SUCCESS(status)) { goto Exit; } status = ObReferenceObjectByHandle( threadHandle, 0, NULL, KernelMode, (PVOID*) &gThreadObj, NULL); ASSERT(NT_SUCCESS(status)); KeSetBasePriorityThread( (PKTHREAD) gThreadObj, -2); ZwClose(threadHandle); driverObject->DriverUnload = DriverUnload; Exit: if (!NT_SUCCESS(status)) { if (gFwpmEngineHandle != NULL) { UnregisterCallouts(); } if (gInjectionHandle != NULL) { FwpsInjectionHandleDestroy0(gInjectionHandle); } if (gDeviceObject) { IoDeleteDevice(gDeviceObject); } if(NT_SUCCESS(symbolicLinkCreationStatus)) { IoDeleteSymbolicLink(&dosDeviceName); } if (gNetBufferListPool != NULL) { NdisFreeNetBufferListPool(gNetBufferListPool); } if (gNdisGenericObj != NULL) { NdisFreeGenericObject(gNdisGenericObj); } } return status; }