Пример #1
0
		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
		}
Пример #2
0
		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);
		}
Пример #3
0
/*++
 * @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);
        }
    }
}
Пример #4
0
/*++
 * @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);
}
Пример #5
0
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;
}
Пример #6
0
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);
        }
    }
}
Пример #7
0
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;
}
Пример #8
0
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;
}