diff --git a/trunk/CHANGELOG.txt b/trunk/CHANGELOG.txt index c7685705c..509c9d854 100644 --- a/trunk/CHANGELOG.txt +++ b/trunk/CHANGELOG.txt @@ -23,6 +23,8 @@ Process Hacker * Custom module information querying; can now display the modules for protected processes * Displays service DLL paths * Thread list displays cycles instead of context switches on Windows Vista + * GUI threads are highlighted (with KProcessHacker) + * Suspended and GUI thread highlighting can be configured * FIXED: * #2642442 - "System Information label text gets clipped" * #2694437 - "Crash when sorting the process list" diff --git a/trunk/KProcessHacker/i386/kprocesshacker.sys b/trunk/KProcessHacker/i386/kprocesshacker.sys index 3f49db79d..ed33b4dca 100644 Binary files a/trunk/KProcessHacker/i386/kprocesshacker.sys and b/trunk/KProcessHacker/i386/kprocesshacker.sys differ diff --git a/trunk/KProcessHacker/kph_nt.c b/trunk/KProcessHacker/kph_nt.c index a1345e46a..02f8d270a 100644 --- a/trunk/KProcessHacker/kph_nt.c +++ b/trunk/KProcessHacker/kph_nt.c @@ -100,6 +100,48 @@ NTSTATUS KphGetContextThread( return status; } +NTSTATUS KphGetThreadWin32Thread( + HANDLE ThreadHandle, + PVOID *Win32Thread, + KPROCESSOR_MODE AccessMode + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PETHREAD threadObject; + PVOID win32Thread; + + if (AccessMode == UserMode) + { + __try + { + ProbeForWrite(Win32Thread, sizeof(PVOID), 1); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return STATUS_ACCESS_VIOLATION; + } + } + + status = ObReferenceObjectByHandle(ThreadHandle, 0, *PsThreadType, KernelMode, &threadObject, NULL); + + if (!NT_SUCCESS(status)) + return status; + + win32Thread = PsGetThreadWin32Thread(threadObject); + ObDereferenceObject(threadObject); + + __try + { + *Win32Thread = win32Thread; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return STATUS_ACCESS_VIOLATION; + } + + return status; +} + NTSTATUS KphOpenProcess( PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, diff --git a/trunk/KProcessHacker/kph_nt.h b/trunk/KProcessHacker/kph_nt.h index 22cf9c0ee..4f797bea9 100644 --- a/trunk/KProcessHacker/kph_nt.h +++ b/trunk/KProcessHacker/kph_nt.h @@ -36,19 +36,23 @@ NTSTATUS NTAPI ObOpenObjectByName( PHANDLE Handle ); -NTSTATUS PsGetContextThread( +NTSTATUS NTAPI PsGetContextThread( PETHREAD Thread, PCONTEXT ThreadContext, KPROCESSOR_MODE PreviousMode ); +PVOID NTAPI PsGetThreadWin32Thread( + PETHREAD Thread + ); + NTSTATUS NTAPI PsLookupProcessThreadByCid( PCLIENT_ID ClientId, PEPROCESS *Process, PETHREAD *Thread ); -NTSTATUS PsSetContextThread( +NTSTATUS NTAPI PsSetContextThread( PETHREAD Thread, PCONTEXT ThreadContext, KPROCESSOR_MODE PreviousMode @@ -104,6 +108,12 @@ NTSTATUS KphGetContextThread( KPROCESSOR_MODE AccessMode ); +NTSTATUS KphGetThreadWin32Thread( + HANDLE ThreadHandle, + PVOID *Win32Thread, + KPROCESSOR_MODE AccessMode + ); + NTSTATUS KphOpenProcess( PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, diff --git a/trunk/KProcessHacker/kprocesshacker.c b/trunk/KProcessHacker/kprocesshacker.c index 9a006c9b0..6384caafb 100644 --- a/trunk/KProcessHacker/kprocesshacker.c +++ b/trunk/KProcessHacker/kprocesshacker.c @@ -294,6 +294,8 @@ char *GetIoControlName(ULONG ControlCode) return "KphGetContextThread"; else if (ControlCode == KPH_SETCONTEXTTHREAD) return "KphSetContextThread"; + else if (ControlCode == KPH_GETTHREADWIN32THREAD) + return "KphGetThreadWin32Thread"; else return "Unknown"; } @@ -853,6 +855,26 @@ NTSTATUS KphIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } break; + case KPH_GETTHREADWIN32THREAD: + { + HANDLE threadHandle; + + if (inLength < 4 || outLength < 4) + { + status = STATUS_BUFFER_TOO_SMALL; + goto IoControlEnd; + } + + threadHandle = *(HANDLE *)dataBuffer; + status = KphGetThreadWin32Thread(threadHandle, (PVOID *)dataBuffer, KernelMode); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + retLength = 4; + } + break; + default: { dprintf("KProcessHacker: unrecognized IOCTL code 0x%08x\n", controlCode); diff --git a/trunk/KProcessHacker/kprocesshacker.h b/trunk/KProcessHacker/kprocesshacker.h index a9adb4248..d58a3d2fd 100644 --- a/trunk/KProcessHacker/kprocesshacker.h +++ b/trunk/KProcessHacker/kprocesshacker.h @@ -65,6 +65,7 @@ typedef struct _SYSTEM_HANDLE_INFORMATION #define KPH_OPENPROCESSJOB KPH_CTL_CODE(17) #define KPH_GETCONTEXTTHREAD KPH_CTL_CODE(18) #define KPH_SETCONTEXTTHREAD KPH_CTL_CODE(19) +#define KPH_GETTHREADWIN32THREAD KPH_CTL_CODE(20) NTSTATUS KphCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp); NTSTATUS KphClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); diff --git a/trunk/ProcessHacker/Components/ThreadList.cs b/trunk/ProcessHacker/Components/ThreadList.cs index 8bba70843..a87ba5a4d 100644 --- a/trunk/ProcessHacker/Components/ThreadList.cs +++ b/trunk/ProcessHacker/Components/ThreadList.cs @@ -260,8 +260,10 @@ namespace ProcessHacker private System.Drawing.Color GetThreadColor(ThreadItem titem) { - if (titem.WaitReason == Win32.KWAIT_REASON.Suspended) - return System.Drawing.Color.LightGray; + if (Properties.Settings.Default.UseColorSuspended && titem.WaitReason == Win32.KWAIT_REASON.Suspended) + return Properties.Settings.Default.ColorSuspended; + else if (Properties.Settings.Default.UseColorGuiThreads && titem.IsGuiThread) + return Properties.Settings.Default.ColorGuiThreads; return System.Drawing.SystemColors.Window; } diff --git a/trunk/ProcessHacker/Forms/HackerWindow.cs b/trunk/ProcessHacker/Forms/HackerWindow.cs index 66d2e92eb..ecde1f1fa 100644 --- a/trunk/ProcessHacker/Forms/HackerWindow.cs +++ b/trunk/ProcessHacker/Forms/HackerWindow.cs @@ -1799,10 +1799,10 @@ namespace ProcessHacker ColumnSettings.LoadSettings(Properties.Settings.Default.ServiceListViewColumns, listServices.List); ColumnSettings.LoadSettings(Properties.Settings.Default.NetworkListViewColumns, listNetwork.List); - HighlightingContext.Colors[ListViewItemState.New] = Properties.Settings.Default.ColorNewProcesses; - HighlightingContext.Colors[ListViewItemState.Removed] = Properties.Settings.Default.ColorRemovedProcesses; - TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.New] = Properties.Settings.Default.ColorNewProcesses; - TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.Removed] = Properties.Settings.Default.ColorRemovedProcesses; + HighlightingContext.Colors[ListViewItemState.New] = Properties.Settings.Default.ColorNew; + HighlightingContext.Colors[ListViewItemState.Removed] = Properties.Settings.Default.ColorRemoved; + TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.New] = Properties.Settings.Default.ColorNew; + TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.Removed] = Properties.Settings.Default.ColorRemoved; Program.ImposterNames = new System.Collections.Specialized.StringCollection(); diff --git a/trunk/ProcessHacker/Forms/OptionsWindow.cs b/trunk/ProcessHacker/Forms/OptionsWindow.cs index cee69650d..8fbd88415 100644 --- a/trunk/ProcessHacker/Forms/OptionsWindow.cs +++ b/trunk/ProcessHacker/Forms/OptionsWindow.cs @@ -65,8 +65,8 @@ namespace ProcessHacker textImposterNames.Text = Properties.Settings.Default.ImposterNames; textHighlightingDuration.Value = Properties.Settings.Default.HighlightingDuration; - colorNewProcesses.Color = Properties.Settings.Default.ColorNewProcesses; - colorRemovedProcesses.Color = Properties.Settings.Default.ColorRemovedProcesses; + colorNewProcesses.Color = Properties.Settings.Default.ColorNew; + colorRemovedProcesses.Color = Properties.Settings.Default.ColorRemoved; this.InitializeHighlightingColors(); checkPlotterAntialias.Checked = Properties.Settings.Default.PlotterAntialias; @@ -193,6 +193,10 @@ namespace ProcessHacker "Executables are sometimes \"packed\" to reduce their size.\n" + "\"Dangerous processes\" includes processes with invalid signatures and unverified " + "processes with the name of a system process."); + AddToList("ColorSuspended", "Suspended Threads", + "Threads that are suspended from execution."); + AddToList("ColorGuiThreads", "GUI Threads", + "Threads that have made at least one GUI-related system call."); foreach (ListViewItem item in listHighlightingColors.Items) { @@ -280,8 +284,8 @@ namespace ProcessHacker Program.HackerWindow.NetworkProvider.Interval = Properties.Settings.Default.RefreshInterval; Properties.Settings.Default.HighlightingDuration = (int)textHighlightingDuration.Value; - Properties.Settings.Default.ColorNewProcesses = colorNewProcesses.Color; - Properties.Settings.Default.ColorRemovedProcesses = colorRemovedProcesses.Color; + Properties.Settings.Default.ColorNew = colorNewProcesses.Color; + Properties.Settings.Default.ColorRemoved = colorRemovedProcesses.Color; foreach (ListViewItem item in listHighlightingColors.Items) { @@ -299,10 +303,10 @@ namespace ProcessHacker // apply the settings immediately if we can HighlightingContext.HighlightingDuration = Properties.Settings.Default.HighlightingDuration; - HighlightingContext.Colors[ListViewItemState.New] = Properties.Settings.Default.ColorNewProcesses; - HighlightingContext.Colors[ListViewItemState.Removed] = Properties.Settings.Default.ColorRemovedProcesses; - TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.New] = Properties.Settings.Default.ColorNewProcesses; - TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.Removed] = Properties.Settings.Default.ColorRemovedProcesses; + HighlightingContext.Colors[ListViewItemState.New] = Properties.Settings.Default.ColorNew; + HighlightingContext.Colors[ListViewItemState.Removed] = Properties.Settings.Default.ColorRemoved; + TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.New] = Properties.Settings.Default.ColorNew; + TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.Removed] = Properties.Settings.Default.ColorRemoved; if (checkReplaceTaskManager.Enabled) { diff --git a/trunk/ProcessHacker/KProcessHacker.cs b/trunk/ProcessHacker/KProcessHacker.cs index 284629634..524898f22 100644 --- a/trunk/ProcessHacker/KProcessHacker.cs +++ b/trunk/ProcessHacker/KProcessHacker.cs @@ -60,7 +60,8 @@ namespace ProcessHacker GetHandleObjectName, KphOpenProcessJob, KphGetContextThread, - KphSetContextThread + KphSetContextThread, + KphGetThreadWin32Thread } private string _deviceName; @@ -224,6 +225,16 @@ namespace ProcessHacker _fileHandle.IoControl(CtlCode(Control.KphGetContextThread), data, null); } + public int KphGetThreadWin32Thread(Win32.ThreadHandle threadHandle) + { + byte[] inData = Misc.IntToBytes(threadHandle, Misc.Endianness.Little); + byte[] outData = new byte[4]; + + _fileHandle.IoControl(CtlCode(Control.KphGetThreadWin32Thread), inData, outData); + + return Misc.BytesToInt(outData, Misc.Endianness.Little); + } + public int KphOpenProcess(int pid, Win32.PROCESS_RIGHTS desiredAccess) { byte[] inData = new byte[8]; diff --git a/trunk/ProcessHacker/Properties/Settings.Designer.cs b/trunk/ProcessHacker/Properties/Settings.Designer.cs index 5e35e6ff9..1a56dd8a3 100644 --- a/trunk/ProcessHacker/Properties/Settings.Designer.cs +++ b/trunk/ProcessHacker/Properties/Settings.Designer.cs @@ -362,24 +362,24 @@ namespace ProcessHacker.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("Chartreuse")] - public global::System.Drawing.Color ColorNewProcesses { + public global::System.Drawing.Color ColorNew { get { - return ((global::System.Drawing.Color)(this["ColorNewProcesses"])); + return ((global::System.Drawing.Color)(this["ColorNew"])); } set { - this["ColorNewProcesses"] = value; + this["ColorNew"] = value; } } [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("255, 60, 40")] - public global::System.Drawing.Color ColorRemovedProcesses { + public global::System.Drawing.Color ColorRemoved { get { - return ((global::System.Drawing.Color)(this["ColorRemovedProcesses"])); + return ((global::System.Drawing.Color)(this["ColorRemoved"])); } set { - this["ColorRemovedProcesses"] = value; + this["ColorRemoved"] = value; } } @@ -1200,5 +1200,53 @@ namespace ProcessHacker.Properties { this["ServiceMiniListColumns"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Silver")] + public global::System.Drawing.Color ColorSuspended { + get { + return ((global::System.Drawing.Color)(this["ColorSuspended"])); + } + set { + this["ColorSuspended"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool UseColorSuspended { + get { + return ((bool)(this["UseColorSuspended"])); + } + set { + this["UseColorSuspended"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("255, 255, 128")] + public global::System.Drawing.Color ColorGuiThreads { + get { + return ((global::System.Drawing.Color)(this["ColorGuiThreads"])); + } + set { + this["ColorGuiThreads"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool UseColorGuiThreads { + get { + return ((bool)(this["UseColorGuiThreads"])); + } + set { + this["UseColorGuiThreads"] = value; + } + } } } diff --git a/trunk/ProcessHacker/Properties/Settings.settings b/trunk/ProcessHacker/Properties/Settings.settings index bb1994c04..e631f1d1d 100644 --- a/trunk/ProcessHacker/Properties/Settings.settings +++ b/trunk/ProcessHacker/Properties/Settings.settings @@ -86,10 +86,10 @@ http://www.google.com/search?q=%s - + Chartreuse - + 255, 60, 40 @@ -296,5 +296,17 @@ + + Silver + + + True + + + 255, 255, 128 + + + True + \ No newline at end of file diff --git a/trunk/ProcessHacker/Providers/ThreadProvider.cs b/trunk/ProcessHacker/Providers/ThreadProvider.cs index 8bd5fa3d4..84c40479d 100644 --- a/trunk/ProcessHacker/Providers/ThreadProvider.cs +++ b/trunk/ProcessHacker/Providers/ThreadProvider.cs @@ -46,6 +46,7 @@ namespace ProcessHacker public uint StartAddressI; public string StartAddress; public Win32.KWAIT_REASON WaitReason; + public bool IsGuiThread; public Win32.ThreadHandle ThreadQueryLimitedHandle; } @@ -170,6 +171,16 @@ namespace ProcessHacker catch { } + if (Program.KPH != null) + { + try + { + item.IsGuiThread = Program.KPH.KphGetThreadWin32Thread(item.ThreadQueryLimitedHandle) != 0; + } + catch + { } + } + if (Program.WindowsVersion != WindowsVersion.XP) { try @@ -237,6 +248,16 @@ namespace ProcessHacker catch { } + if (Program.KPH != null) + { + try + { + newitem.IsGuiThread = Program.KPH.KphGetThreadWin32Thread(newitem.ThreadQueryLimitedHandle) != 0; + } + catch + { } + } + if (Program.WindowsVersion != WindowsVersion.XP) { try @@ -266,6 +287,7 @@ namespace ProcessHacker newitem.ContextSwitchesDelta != item.ContextSwitchesDelta || newitem.Cycles != item.Cycles || newitem.CyclesDelta != item.CyclesDelta || + newitem.IsGuiThread != item.IsGuiThread || newitem.Priority != item.Priority || newitem.StartAddress != item.StartAddress || newitem.WaitReason != item.WaitReason diff --git a/trunk/ProcessHacker/app.config b/trunk/ProcessHacker/app.config index 456369319..16b22e8fd 100644 --- a/trunk/ProcessHacker/app.config +++ b/trunk/ProcessHacker/app.config @@ -91,10 +91,10 @@ http://www.google.com/search?q=%s - + Chartreuse - + 255, 60, 40 @@ -301,6 +301,18 @@ + + Silver + + + True + + + 255, 255, 128 + + + True + \ No newline at end of file