private void Update()
        {
            LinkedListEntry <IProvider> tempListHead = new LinkedListEntry <IProvider>();
            LinkedListEntry <IProvider> listEntry;
            NtStatus status = NtStatus.Success;

            _threadHandle = ThreadHandle.OpenCurrent(
                ThreadAccess.Alert | (ThreadAccess)StandardRights.Synchronize
                );
            _initializedEvent.Set();

            while (!_terminating)
            {
                LinkedList.InitializeListHead(tempListHead);

                Monitor.Enter(_listHead);

                // Main loop.

                while (true)
                {
                    if (status == NtStatus.Alerted)
                    {
                        // Check if we have any more providers to boost.
                        if (_boostCount == 0)
                        {
                            break;
                        }
                    }

                    listEntry = LinkedList.RemoveHeadList(_listHead);

                    if (listEntry == _listHead)
                    {
                        break;
                    }

                    // Add the provider to the temp list.
                    LinkedList.InsertTailList(tempListHead, listEntry);

                    if (status != NtStatus.Alerted)
                    {
                        if (!listEntry.Value.Enabled || listEntry.Value.Unregistering)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (listEntry.Value.Unregistering)
                        {
                            // Give the unregistering thread a chance to fix
                            // the boost count.
                            Monitor.Exit(_listHead);
                            Monitor.Enter(_listHead);

                            continue;
                        }
                    }

                    if (status == NtStatus.Alerted)
                    {
                        listEntry.Value.Boosting = false;
                        _boostCount--;
                    }

                    Monitor.Exit(_listHead);

                    try
                    {
                        listEntry.Value.Run();
                    }
                    finally
                    {
                        Monitor.Enter(_listHead);
                    }
                }

                // Re-add the items in the temp list to the main list.

                while ((listEntry = LinkedList.RemoveHeadList(tempListHead)) != tempListHead)
                {
                    LinkedList.InsertTailList(_listHead, listEntry);
                }

                Monitor.Exit(_listHead);

                // Wait for the interval. We may get alerted.
                status = _timerHandle.Wait(true);
            }
        }
Exemple #2
0
        private void BufferWorkerThreadStart()
        {
            int cursor = 0;

            // Open a handle to the current thread so other functions
            // can alert us.
            _bufferWorkerThreadHandle = ThreadHandle.OpenCurrent(ThreadAccess.All);

            // We're ready.
            _bufferWorkerThreadReadyEvent.Set();

            while (!_terminating)
            {
                NtStatus         status;
                KphSsBlockHeader blockHeader;

                // Wait for a block to read (enable alerting so we can
                // be interrupted if someone wants us to stop).
                status = _readSemaphore.Wait(true);

                // Did we get alerted?
                if (status == NtStatus.Alerted)
                {
                    return;
                }

                // Check if we have an implicit cursor reset.
                if (_buffer.Size - cursor < Marshal.SizeOf(typeof(KphSsBlockHeader)))
                {
                    cursor = 0;
                }

                // Read the block header.
                blockHeader = _buffer.ReadStruct <KphSsBlockHeader>(cursor, 0);

                // Check if we have an explicit cursor reset.
                if (blockHeader.Type == KphSsBlockType.Reset)
                {
                    cursor      = 0;
                    blockHeader = _buffer.ReadStruct <KphSsBlockHeader>(cursor, 0);
                }

                // Process the block.
                if (blockHeader.Type == KphSsBlockType.Event)
                {
                    var      eventBlock = _buffer.ReadStruct <KphSsEventBlock>(cursor, 0);
                    int[]    arguments;
                    IntPtr[] stackTrace;

                    // Reconstruct the argument and stack trace arrays.

                    arguments  = new int[eventBlock.NumberOfArguments];
                    stackTrace = new IntPtr[eventBlock.TraceCount];

                    for (int i = 0; i < arguments.Length; i++)
                    {
                        arguments[i] = _buffer.ReadInt32(cursor + eventBlock.ArgumentsOffset, i);
                    }
                    for (int i = 0; i < stackTrace.Length; i++)
                    {
                        stackTrace[i] = _buffer.ReadIntPtr(cursor + eventBlock.TraceOffset, i);
                    }

                    // Create an event object.
                    SsEvent ssEvent = new SsEvent();

                    // Basic information
                    ssEvent.Time       = DateTime.FromFileTime(eventBlock.Time);
                    ssEvent.ThreadId   = eventBlock.ClientId.ThreadId;
                    ssEvent.ProcessId  = eventBlock.ClientId.ProcessId;
                    ssEvent.Arguments  = arguments;
                    ssEvent.StackTrace = stackTrace;

                    // Flags
                    ssEvent.ArgumentsCopyFailed =
                        (eventBlock.Flags & KphSsEventFlags.CopyArgumentsFailed) == KphSsEventFlags.CopyArgumentsFailed;
                    ssEvent.ArgumentsProbeFailed =
                        (eventBlock.Flags & KphSsEventFlags.ProbeArgumentsFailed) == KphSsEventFlags.ProbeArgumentsFailed;
                    ssEvent.CallNumber = eventBlock.Number;

                    if ((eventBlock.Flags & KphSsEventFlags.UserMode) == KphSsEventFlags.UserMode)
                    {
                        ssEvent.Mode = KProcessorMode.UserMode;
                    }
                    else
                    {
                        ssEvent.Mode = KProcessorMode.KernelMode;
                    }

                    // Raise the event.
                    if (this.EventBlockReceived != null)
                    {
                        this.EventBlockReceived(ssEvent);
                    }
                }
                else if (blockHeader.Type == KphSsBlockType.Argument)
                {
                    var          argBlock = _buffer.ReadStruct <KphSsArgumentBlock>(cursor, 0);
                    MemoryRegion dataRegion;
                    SsData       ssArg = null;

                    dataRegion = new MemoryRegion(_buffer, cursor + KphSsArgumentBlock.DataOffset);

                    // Process the argument block based on its type.
                    switch (argBlock.Type)
                    {
                    case KphSsArgumentType.Int8:
                    {
                        SsSimple simpleArg = new SsSimple();

                        simpleArg.Argument = argBlock.Data.Int8;
                        simpleArg.Type     = typeof(Byte);
                        ssArg = simpleArg;
                    }
                    break;

                    case KphSsArgumentType.Int16:
                    {
                        SsSimple simpleArg = new SsSimple();

                        simpleArg.Argument = argBlock.Data.Int16;
                        simpleArg.Type     = typeof(Int16);
                        ssArg = simpleArg;
                    }
                    break;

                    case KphSsArgumentType.Int32:
                    {
                        SsSimple simpleArg = new SsSimple();

                        simpleArg.Argument = argBlock.Data.Int32;
                        simpleArg.Type     = typeof(Int32);
                        ssArg = simpleArg;
                    }
                    break;

                    case KphSsArgumentType.Int64:
                    {
                        SsSimple simpleArg = new SsSimple();

                        simpleArg.Argument = argBlock.Data.Int64;
                        simpleArg.Type     = typeof(Int64);
                        ssArg = simpleArg;
                    }
                    break;

                    case KphSsArgumentType.Handle:
                    {
                        ssArg = new SsHandle(dataRegion);
                    }
                    break;

                    case KphSsArgumentType.UnicodeString:
                    {
                        ssArg = new SsUnicodeString(dataRegion);
                    }
                    break;

                    case KphSsArgumentType.ObjectAttributes:
                    {
                        ssArg = new SsObjectAttributes(dataRegion);
                    }
                    break;

                    case KphSsArgumentType.ClientId:
                    {
                        ssArg = new SsClientId(dataRegion);
                    }
                    break;
                    }

                    ssArg.Index = argBlock.Index;

                    // Raise the event.
                    if (ssArg != null)
                    {
                        if (this.ArgumentBlockReceived != null)
                        {
                            this.ArgumentBlockReceived(ssArg);
                        }
                    }
                }

                // Advance the cursor.
                cursor += blockHeader.Size;
                // Signal that a buffer block is available for writing.
                _writeSemaphore.Release();
            }
        }
        //public IntPtr AddNumberRule(FilterType filterType, int number)
        //{
        //    return KProcessHacker.Instance.SsAddNumberRule(
        //        _ruleSetEntryHandle,
        //        filterType.ToKphSs(),
        //        number
        //        );
        //}

        //public IntPtr AddPreviousModeRule(FilterType filterType, KProcessorMode previousMode)
        //{
        //    return KProcessHacker.Instance.SsAddPreviousModeRule(
        //        _ruleSetEntryHandle,
        //        filterType.ToKphSs(),
        //        previousMode
        //        );
        //}

        //public IntPtr AddProcessIdRule(FilterType filterType, int pid)
        //{
        //    return KProcessHacker.Instance.SsAddProcessIdRule(
        //        _ruleSetEntryHandle,
        //        filterType.ToKphSs(),
        //        pid.ToIntPtr()
        //        );
        //}

        //public IntPtr AddThreadIdRule(FilterType filterType, int tid)
        //{
        //    return KProcessHacker.Instance.SsAddProcessIdRule(
        //        _ruleSetEntryHandle,
        //        filterType.ToKphSs(),
        //        tid.ToIntPtr()
        //        );
        //}

        private void BufferWorkerThreadStart()
        {
            // Open a handle to the current thread so other functions
            // can alert us.
            _bufferWorkerThreadHandle = ThreadHandle.OpenCurrent(ThreadAccess.All);

            // We're ready.
            _bufferWorkerThreadReadyEvent.Set();

            while (!_terminating)
            {
                NtStatus         status;
                KphSsBlockHeader blockHeader;

                // Wait for a block to read (enable alerting so we can
                // be interrupted if someone wants us to stop).
                status = _readSemaphore.Wait(true);

                // Did we get alerted?
                if (status == NtStatus.Alerted)
                {
                    return;
                }

                // Check if we have an implicit cursor reset.
                if (_buffer.Size - _cursor < KphSsBlockHeader.SizeOf)
                {
                    _cursor = 0;
                }

                // Read the block header.
                blockHeader = _buffer.ReadStruct <KphSsBlockHeader>(_cursor, KphSsBlockHeader.SizeOf, 0);

                // Check if we have an explicit cursor reset.
                if (blockHeader.Type == KphSsBlockType.Reset)
                {
                    _cursor     = 0;
                    blockHeader = _buffer.ReadStruct <KphSsBlockHeader>(_cursor, KphSsBlockHeader.SizeOf, 0);
                }

                // Process the block.
                switch (blockHeader.Type)
                {
                case KphSsBlockType.Event:
                    if (this.EventBlockReceived != null)
                    {
                        this.EventBlockReceived(ReadEventBlock(new MemoryRegion(this._buffer, this._cursor)));
                    }
                    if (this.RawEventBlockReceived != null)
                    {
                        this.RawEventBlockReceived(new MemoryRegion(this._buffer, this._cursor));
                    }
                    break;

                case KphSsBlockType.Argument:
                    if (this.ArgumentBlockReceived != null)
                    {
                        this.ArgumentBlockReceived(ReadArgumentBlock(new MemoryRegion(this._buffer, this._cursor)));
                    }
                    if (this.RawArgumentBlockReceived != null)
                    {
                        this.RawArgumentBlockReceived(new MemoryRegion(this._buffer, this._cursor));
                    }
                    break;
                }

                // Advance the cursor.
                _cursor += blockHeader.Size;
                // Signal that a buffer block is available for writing.
                _writeSemaphore.Release();
            }
        }
Exemple #4
0
            private void WaiterThreadStart()
            {
                ISynchronizable[] waitObjects = null;

                // Open a handle to the current thread.
                _threadHandle = ThreadHandle.OpenCurrent(ThreadAccess.Alert);

                // Signal that the thread has been initialized.
                lock (_thread)
                {
                    _threadInitialized = true;
                    Monitor.PulseAll(_thread);
                }

                while (!_terminating)
                {
                    bool doWait;

                    lock (_waitObjects)
                    {
                        // Check if we have any objects to wait for. If we do, use WaitAny.
                        // Otherwise, wait forever (alertably).
                        if (_waitObjects.Count > 0)
                        {
                            waitObjects = _waitObjects.ToArray();
                            doWait      = true;
                        }
                        else
                        {
                            doWait = false;
                        }
                    }

                    NtStatus waitStatus;

                    if (doWait)
                    {
                        // Wait for the objects, (almost) forever.
                        waitStatus = NativeHandle.WaitAny(waitObjects, true, long.MinValue, false);
                    }
                    else
                    {
                        // Wait forever.
                        waitStatus = ThreadHandle.Sleep(true, long.MinValue, false);
                    }

                    if (waitStatus == NtStatus.Alerted)
                    {
                        // The wait was changed. Go back to refresh the wait objects array.
                        // The thread is also alerted to notify that the thread should terminate.
                        continue;
                    }
                    else if (waitStatus >= NtStatus.Wait0 && waitStatus <= NtStatus.Wait63)
                    {
                        // One of the objects was signaled.
                        ISynchronizable signaledObject = waitObjects[(int)(waitStatus - NtStatus.Wait0)];

                        // Remove the object now that it is signaled.
                        lock (_waitObjects)
                        {
                            // Just in case someone already removed the object.
                            if (_waitObjects.Contains(signaledObject))
                            {
                                _waitObjects.Remove(signaledObject);
                            }
                        }

                        // Call the object-signaled event.
                        OnObjectSignaled(signaledObject);

                        // Balance the threads (which may involve terminating the current one).
                        _owner.BalanceWaiterThreads();
                    }
                }
            }