コード例 #1
0
ファイル: timerobj.c プロジェクト: GYGit/reactos
/*
 * @implemented
 */
BOOLEAN
NTAPI
KeSetTimerEx(IN OUT PKTIMER Timer,
             IN LARGE_INTEGER DueTime,
             IN LONG Period,
             IN PKDPC Dpc OPTIONAL)
{
    KIRQL OldIrql;
    BOOLEAN Inserted;
    ULONG Hand = 0;
    BOOLEAN RequestInterrupt = FALSE;
    ASSERT_TIMER(Timer);
    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
    DPRINT("KeSetTimerEx(): Timer %p, DueTime %I64d, Period %d, Dpc %p\n",
           Timer, DueTime.QuadPart, Period, Dpc);

    /* Lock the Database and Raise IRQL */
    OldIrql = KiAcquireDispatcherLock();

    /* Check if it's inserted, and remove it if it is */
    Inserted = Timer->Header.Inserted;
    if (Inserted) KxRemoveTreeTimer(Timer);

    /* Set Default Timer Data */
    Timer->Dpc = Dpc;
    Timer->Period = Period;
    if (!KiComputeDueTime(Timer, DueTime, &Hand))
    {
        /* Signal the timer */
        RequestInterrupt = KiSignalTimer(Timer);
        
        /* Release the dispatcher lock */
        KiReleaseDispatcherLockFromDpcLevel();
        
        /* Check if we need to do an interrupt */
        if (RequestInterrupt) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);        
    }
    else
    {
        /* Insert the timer */
        Timer->Header.SignalState = FALSE;
        KxInsertTimer(Timer, Hand);        
    }
    
    /* Exit the dispatcher */
    KiExitDispatcher(OldIrql);

    /* Return old state */
    return Inserted;
}
コード例 #2
0
ファイル: thrdschd.c プロジェクト: SnakeSolidNL/reactos
VOID
NTAPI
KiAdjustQuantumThread(IN PKTHREAD Thread)
{
    PKPRCB Prcb = KeGetCurrentPrcb();
    PKTHREAD NextThread;

    /* Acquire thread and PRCB lock */
    KiAcquireThreadLock(Thread);
    KiAcquirePrcbLock(Prcb);

    /* Don't adjust for RT threads */
    if ((Thread->Priority < LOW_REALTIME_PRIORITY) &&
            (Thread->BasePriority < (LOW_REALTIME_PRIORITY - 2)))
    {
        /* Decrease Quantum by one and see if we've ran out */
        if (--Thread->Quantum <= 0)
        {
            /* Return quantum */
            Thread->Quantum = Thread->QuantumReset;

            /* Calculate new Priority */
            Thread->Priority = KiComputeNewPriority(Thread, 1);

            /* Check if there's no next thread scheduled */
            if (!Prcb->NextThread)
            {
                /* Select a ready thread and check if we found one */
                NextThread = KiSelectReadyThread(Thread->Priority, Prcb);
                if (NextThread)
                {
                    /* Set it on standby and switch to it */
                    NextThread->State = Standby;
                    Prcb->NextThread = NextThread;
                }
            }
            else
            {
                /* This thread can be preempted again */
                Thread->Preempted = FALSE;
            }
        }
    }

    /* Release locks */
    KiReleasePrcbLock(Prcb);
    KiReleaseThreadLock(Thread);
    KiExitDispatcher(Thread->WaitIrql);
}
コード例 #3
0
ファイル: apc.c プロジェクト: GYGit/reactos
/*++
 * @name KeInsertQueueApc
 * @implemented NT4
 *
 *     The KeInsertQueueApc routine queues a APC for execution when the right
 *     scheduler environment exists.
 *
 * @param Apc
 *        Pointer to an initialized control object of type APC for which the
 *        caller provides the storage.
 *
 * @param SystemArgument[1,2]
 *        Pointer to a set of two parameters that contain untyped data.
 *
 * @param PriorityBoost
 *        Priority Boost to apply to the Thread.
 *
 * @return If the APC is already inserted or APC queueing is disabled, FALSE.
 *         Otherwise, TRUE.
 *
 * @remarks The APC will execute at APC_LEVEL for the KernelRoutine registered,
 *          and at PASSIVE_LEVEL for the NormalRoutine registered.
 *
 *          Callers of this routine must be running at IRQL <= DISPATCH_LEVEL.
 *
 *--*/
BOOLEAN
NTAPI
KeInsertQueueApc(IN PKAPC Apc,
                 IN PVOID SystemArgument1,
                 IN PVOID SystemArgument2,
                 IN KPRIORITY PriorityBoost)
{
    PKTHREAD Thread = Apc->Thread;
    KLOCK_QUEUE_HANDLE ApcLock;
    BOOLEAN State = TRUE;
    ASSERT_APC(Apc);
    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);

    /* Get the APC lock */
    KiAcquireApcLock(Thread, &ApcLock);

    /* Make sure we can Queue APCs and that this one isn't already inserted */
    if (!(Thread->ApcQueueable) || (Apc->Inserted))
    {
        /* Fail */
        State = FALSE;
    }
    else
    {
        /* Set the System Arguments and set it as inserted */
        Apc->SystemArgument1 = SystemArgument1;
        Apc->SystemArgument2 = SystemArgument2;
        Apc->Inserted = TRUE;

        /* Call the Internal Function */
        KiInsertQueueApc(Apc, PriorityBoost);
    }

    /* Release the APC lock and return success */
    KiReleaseApcLockFromDpcLevel(&ApcLock);
    KiExitDispatcher(ApcLock.OldIrql);
    return State;
}
コード例 #4
0
ファイル: gateobj.c プロジェクト: BaoYu0721/WRK-1.2
VOID
FASTCALL
KeSignalGateBoostPriority (
    __inout PKGATE Gate
    )

/*++

Routine Description:

    This function conditionally sets the signal state of a gate object and
    attempts to unwait the first waiter.

Arguments:

    Gate - Supplies a pointer to a dispatcher object of type gate.

Return Value:

    None.

--*/

{

    PKTHREAD CurrentThread;
    PLIST_ENTRY Entry;
    KIRQL OldIrql;
    SCHAR Priority;
    PKQUEUE Queue;
    PKWAIT_BLOCK WaitBlock;
    PKTHREAD WaitThread;

    ASSERT_GATE(Gate);

    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

    //
    // Raise IRQL to SYNCH_LEVEL and acquire the object lock.
    //
    // If the object is not already signaled, then attempt to wake a waiter.
    //

    CurrentThread = KeGetCurrentThread();
    do {
        OldIrql = KeRaiseIrqlToSynchLevel();
        KiAcquireKobjectLock(Gate);
        if (Gate->Header.SignalState == 0) {
    
            //
            // If there are any waiters, then remove and ready the first
            // waiter. Otherwise, set the signal state.
            //
    
            if (IsListEmpty(&Gate->Header.WaitListHead) == FALSE) {
                Entry = Gate->Header.WaitListHead.Flink;
                WaitBlock = CONTAINING_RECORD(Entry, KWAIT_BLOCK, WaitListEntry);
                WaitThread = WaitBlock->Thread;

                //
                // Try to acquire the thread lock.
                //
                // If the thread lock cannot be acquired, then release the
                // object lock, lower IRQL to is previous value, and try to
                // signal the gate again. Otherwise, remove the entry from
                // the list, set the wait completion status to success, set
                // the deferred processor number, set the thread state to
                // deferred ready, release the thread lock, release the
                // object lock, compute the new thread priority, ready the
                // thread for execution, and exit the dispatcher.
                //

                if (KiTryToAcquireThreadLock(WaitThread)) {
                    RemoveEntryList(Entry);
                    WaitThread->WaitStatus = STATUS_SUCCESS;
                    WaitThread->State = DeferredReady;
                    WaitThread->DeferredProcessor = KeGetCurrentPrcb()->Number;
                    KiReleaseKobjectLock(Gate);
                    KiReleaseThreadLock(WaitThread);
                    Priority = CurrentThread->Priority;
                    if (Priority < LOW_REALTIME_PRIORITY) {
                        Priority = Priority - CurrentThread->PriorityDecrement;
                        if (Priority < CurrentThread->BasePriority) {
                            Priority = CurrentThread->BasePriority;
                        }

                        if (CurrentThread->PriorityDecrement != 0) {
                            CurrentThread->PriorityDecrement = 0;
                            CurrentThread->Quantum = CLOCK_QUANTUM_DECREMENT;
                        }
                    }

                    WaitThread->AdjustIncrement = Priority;
                    WaitThread->AdjustReason = (UCHAR)AdjustBoost;

                    //
                    // If the wait thread is associated with a queue, then
                    // increment the concurrency level.
                    //
                    // N.B. This can be done after dropping all other locks,
                    //      but must be done holding the dispatcher lock
                    //      since the concurrency count is not accessed with
                    //      interlocked operations elsewhere.
                    //    

                    if (WaitThread->Queue != NULL) {
                        KiLockDispatcherDatabaseAtSynchLevel();
                        if ((Queue = WaitThread->Queue) != NULL) {
                            Queue->CurrentCount += 1;
                        }

                        KiUnlockDispatcherDatabaseFromSynchLevel();
                    }

                    KiDeferredReadyThread(WaitThread);
                    KiExitDispatcher(OldIrql);
                    return;

                } else {
                    KiReleaseKobjectLock(Gate);
                    KeLowerIrql(OldIrql);
                    continue;
                }

    
            } else {
                Gate->Header.SignalState = 1;
                break;
            }

        } else {
            break;
        }

    } while (TRUE);

    //
    // Release the object lock and lower IRQL to its previous value.
    //

    KiReleaseKobjectLock(Gate);
    KeLowerIrql(OldIrql);
    return;
}
コード例 #5
0
ファイル: scan.c プロジェクト: 340211173/hf-2011
/************************************************************************
*************************************** PgDumpTimerTable
*************************************************************************

Description:

	All PatchGuard 2 related timers will wear the "suspect" sttribute.

	ATTENTION: The code uses undocumented kernel APIs. Please keep in mind
	that you shouldn't change the code logic and remember that during
	enumeration your code will run at DISPATCH_LEVEL! 

*/
NTSTATUS PgDumpTimerTable()
{
	KIRQL					OldIrql;
	ULONG					Index;
	PKSPIN_LOCK_QUEUE		LockQueue;
	PKTIMER_TABLE_ENTRY		TimerListHead;
	PLIST_ENTRY				TimerList;
	PKTIMER					Timer;
	PKDPC					TimerDpc;
	CHAR					LogEntryText[2048];
	NTSTATUS				Result = STATUS_SUCCESS;
	HANDLE					hLogFile;
	UNICODE_STRING			LogFileName;
	OBJECT_ATTRIBUTES		ObjAttr;
	IO_STATUS_BLOCK			IOStatus;
	ULONG					LogEntryTextLen;
	SINGLE_LIST_ENTRY		LogListHead = {NULL};
	PSINGLE_LIST_ENTRY		LogList;
	LOGENTRY*				LogEntry;

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	/*
		Open log file...
	*/
	RtlInitUnicodeString(&LogFileName, L"\\??\\C:\\patchguard.log");

	InitializeObjectAttributes(
		&ObjAttr, 
		&LogFileName, 
		OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
		NULL, NULL)

	if(!NT_SUCCESS(Result = ZwCreateFile(
			&hLogFile,
			GENERIC_WRITE,
			&ObjAttr,
			&IOStatus,
			NULL,
			FILE_ATTRIBUTE_NORMAL,
			FILE_SHARE_READ,
			FILE_OVERWRITE_IF,
			FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
			NULL, 0)))
	{
		KdPrint(("\r\n" "ERROR: Unable to open file \"\\??\\C:\\patchguard.log\". (NTSTATUS: 0x%p)\r\n", (void*)Result));

		return Result;
	}
	
	/*
		Lock the dispatcher database and loop through the timer list...
	*/
	Result = STATUS_SUCCESS;

	OldIrql = KiAcquireDispatcherLockRaiseToSynch();

	for(Index = 0; Index < TIMER_TABLE_SIZE; Index++)
	{
		// we have to emulate the windows timer bug "Index & 0xFF" for this to work...
		LockQueue = KeTimerIndexToLockQueue((UCHAR)(Index & 0xFF));

		KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);
		
		// now we can work with the timer list...
		TimerListHead = &KiTimerTableListHead[Index];
		TimerList = TimerListHead->Entry.Flink;

		while(TimerList != (PLIST_ENTRY)TimerListHead)
		{
			Timer = CONTAINING_RECORD(TimerList, KTIMER, TimerListEntry);
			TimerDpc = PgDeobfuscateTimerDpc(Timer);
			TimerList = TimerList->Flink;

			if(TimerDpc != NULL)
			{
				memset(LogEntryText, 0, sizeof(LogEntryText));

				LogEntryTextLen = _snprintf(LogEntryText, sizeof(LogEntryText) - 1, 
					"<timer address=\"%p\" index=\"%d\" period=\"0x%p\" hand=\"%d\" duetime=\"0x%p\">\r\n"
					"%s"
					"    <dpc>\r\n"
					"        <DeferredContext value=\"0x%p\">%s</DeferredContext>\r\n"
					"        <DeferredRoutine>0x%p</DeferredRoutine>\r\n"
					"        <DpcListBlink value=\"0x%p\">%s</DpcListBlink>\r\n"
					"        <DpcListFlink value=\"0x%p\">%s</DpcListFlink>\r\n"
					"        <DpcData value=\"0x%p\">%s</DpcData>\r\n"
					"        <Importance>%d</Importance>\r\n"
					"        <Number>%d</Number>\r\n"
					"        <SystemArgument1 value=\"0x%p\">%s</SystemArgument1>\r\n"
					"        <SystemArgument2 value=\"0x%p\">%s</SystemArgument2>\r\n"
					"        <Type>%d</Type>\r\n"
					"    </dpc>\r\n"
					"</timer>\r\n\r\n",
					Timer,
					Index,
					(ULONGLONG)Timer->Period,
					(ULONG)Timer->Header.Hand,
					Timer->DueTime.QuadPart,
					PgIsPatchGuardContext(TimerDpc->DeferredContext)?"    <SUSPECT>true</SUSPECT>\t\n":"",
					TimerDpc->DeferredContext, PointerToString(TimerDpc->DeferredContext),
					TimerDpc->DeferredRoutine, 
					TimerDpc->DpcListEntry.Blink, PointerToString(TimerDpc->DpcListEntry.Blink),
					TimerDpc->DpcListEntry.Flink, PointerToString(TimerDpc->DpcListEntry.Flink),
					TimerDpc->DpcData, PointerToString(TimerDpc->DpcData),
					(ULONG)TimerDpc->Importance,
					(ULONG)TimerDpc->Number,
					TimerDpc->SystemArgument1, PointerToString(TimerDpc->SystemArgument1),
					TimerDpc->SystemArgument2, PointerToString(TimerDpc->SystemArgument2),
					(ULONG)TimerDpc->Type
				);

				// allocate memory and add log entry to list...
				if((LogEntry = (LOGENTRY*)ExAllocatePool(NonPagedPool, sizeof(LOGENTRY) + LogEntryTextLen + 1)) == NULL)
				{
					KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);

					Result = STATUS_NO_MEMORY;

					DbgPrint("\r\n" "WARNING: Not enough non-paged memory to write suspect timer to file. Aborting enumeration...\r\n");

					break;
				}

				LogEntry->Text = (CHAR*)(LogEntry + 1);
				LogEntry->Length = LogEntryTextLen;

				memcpy(LogEntry->Text, LogEntryText, LogEntryTextLen);

				PushEntryList(&LogListHead, &LogEntry->List);
			}
		}

		KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);
	}

	KiReleaseDispatcherLockFromSynchLevel();

	KiExitDispatcher(OldIrql);
		
	KdPrint(("\r\n" "INFORMATION: Completed PatchGuard scan...\r\n"));

	/*
		Loop through the log entries and flush them to disk...
		In case of an error during enumeration this actually won't write any
		files, but just free allocated memory...
	*/
	LogList = PopEntryList(&LogListHead);

	while(LogList != NULL)
	{
		LogEntry = CONTAINING_RECORD(LogList, LOGENTRY, List);

		if(NT_SUCCESS(Result))
		{
			Result = ZwWriteFile(
					hLogFile,
					NULL, NULL, NULL,
					&IOStatus,
					LogEntry->Text,
					LogEntry->Length,
					NULL, NULL);
		}

		ExFreePool(LogEntry);

		LogList = PopEntryList(&LogListHead);
	}

	ZwClose(hLogFile);

	return Result;
}