Process Hacker
treeext.c
Go to the documentation of this file.
1 /*
2  * Process Hacker .NET Tools -
3  * thread list extensions
4  *
5  * Copyright (C) 2015 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "dn.h"
24 #include "clrsup.h"
25 
27  _In_ PVOID Object,
28  _In_ PH_EM_OBJECT_TYPE ObjectType,
29  _In_ PVOID Extension
30  );
31 
33  _In_ PVOID Object,
34  _In_ PH_EM_OBJECT_TYPE ObjectType,
35  _In_ PVOID Extension
36  );
37 
39  _In_ PVOID Parameter
40  );
41 
43  _In_ PVOID Node1,
44  _In_ PVOID Node2,
45  _In_ ULONG SubId,
46  _In_ PVOID Context
47  );
48 
49 #define THREAD_TREE_CONTEXT_TYPE 1
50 
51 typedef struct _THREAD_TREE_CONTEXT
52 {
53  ULONG Type;
54  HANDLE ProcessId;
55  PH_CALLBACK_REGISTRATION AddedCallbackRegistration;
56  PCLR_PROCESS_SUPPORT Support;
58 
59 static PPH_HASHTABLE ContextHashtable;
60 static PH_QUEUED_LOCK ContextHashtableLock = PH_QUEUED_LOCK_INIT;
61 static PH_INITONCE ContextHashtableInitOnce = PH_INITONCE_INIT;
62 
64  VOID
65  )
66 {
70  sizeof(THREAD_TREE_CONTEXT),
73  );
74 }
75 
77  _In_ PPH_PLUGIN_TREENEW_INFORMATION TreeNewInfo,
78  _In_ PVOID Context,
79  _In_ ULONG SubId,
80  _In_ BOOLEAN Visible,
81  _In_ PWSTR Text,
82  _In_ ULONG Width,
83  _In_ ULONG Alignment,
84  _In_ ULONG TextFlags,
85  _In_ BOOLEAN SortDescending,
86  _In_ PPH_PLUGIN_TREENEW_SORT_FUNCTION SortFunction
87  )
88 {
89  PH_TREENEW_COLUMN column;
90 
91  memset(&column, 0, sizeof(PH_TREENEW_COLUMN));
92  column.Visible = Visible;
93  column.SortDescending = SortDescending;
94  column.Text = Text;
95  column.Width = Width;
96  column.Alignment = Alignment;
97  column.DisplayIndex = TreeNew_GetVisibleColumnCount(TreeNewInfo->TreeNewHandle);
98  column.TextFlags = TextFlags;
99 
102  TreeNewInfo->CmData,
103  &column,
104  SubId,
105  Context,
106  SortFunction
107  );
108 }
109 
111  _In_ PVOID Parameter
112  )
113 {
114  PPH_PLUGIN_TREENEW_MESSAGE message = Parameter;
115 
116  switch (*(PULONG)message->Context)
117  {
119  ThreadTreeNewMessage(Parameter);
120  break;
121  }
122 }
123 
124 static VOID ThreadAddedHandler(
125  _In_opt_ PVOID Parameter,
126  _In_opt_ PVOID Context
127  )
128 {
129  PPH_THREAD_ITEM threadItem = Parameter;
130  PDN_THREAD_ITEM dnThread;
131  PTHREAD_TREE_CONTEXT context = Context;
132 
134  memset(dnThread, 0, sizeof(DN_THREAD_ITEM));
135  dnThread->ThreadItem = threadItem;
136 }
137 
139  _In_ PVOID Object,
140  _In_ PH_EM_OBJECT_TYPE ObjectType,
141  _In_ PVOID Extension
142  )
143 {
144  PPH_THREADS_CONTEXT threadsContext = Object;
145  PTHREAD_TREE_CONTEXT context = Extension;
146 
147  memset(context, 0, sizeof(THREAD_TREE_CONTEXT));
148  context->Type = THREAD_TREE_CONTEXT_TYPE;
149  context->ProcessId = threadsContext->Provider->ProcessId;
150 
152  &threadsContext->Provider->ThreadAddedEvent,
153  ThreadAddedHandler,
154  context,
155  &context->AddedCallbackRegistration
156  );
157 }
158 
160  _In_ PVOID Object,
161  _In_ PH_EM_OBJECT_TYPE ObjectType,
162  _In_ PVOID Extension
163  )
164 {
165  PPH_THREADS_CONTEXT threadsContext = Object;
166  PTHREAD_TREE_CONTEXT context = Extension;
167 
169  &threadsContext->Provider->ThreadAddedEvent,
170  &context->AddedCallbackRegistration
171  );
172 
173  if (context->Support)
174  FreeClrProcessSupport(context->Support);
175 }
176 
178  _In_ PVOID Parameter
179  )
180 {
181  PPH_PLUGIN_TREENEW_INFORMATION info = Parameter;
182  PPH_THREADS_CONTEXT threadsContext;
183  PTHREAD_TREE_CONTEXT context;
184  BOOLEAN isDotNet;
185 
186  threadsContext = info->SystemContext;
188 
189  if (NT_SUCCESS(PhGetProcessIsDotNet(threadsContext->Provider->ProcessId, &isDotNet)) && isDotNet)
190  {
191  PCLR_PROCESS_SUPPORT support;
192 
193  support = CreateClrProcessSupport(threadsContext->Provider->ProcessId);
194 
195  if (!support)
196  return;
197 
198  context->Support = support;
199 
200  AddTreeNewColumn(info, context, DNTHTNC_APPDOMAIN, TRUE, L"AppDomain", 120, PH_ALIGN_LEFT, 0, FALSE, ThreadTreeNewSortFunction);
201  }
202 }
203 
205  _In_ PVOID Parameter
206  )
207 {
208  NOTHING;
209 }
210 
212  _In_ PTHREAD_TREE_CONTEXT Context,
213  _Inout_ PDN_THREAD_ITEM DnThread
214  )
215 {
216  if (!DnThread->ClrDataValid)
217  {
218  IXCLRDataProcess *process;
219  IXCLRDataTask *task;
220  IXCLRDataAppDomain *appDomain;
221 
222  if (Context->Support)
223  process = Context->Support->DataProcess;
224  else
225  return;
226 
227  if (SUCCEEDED(IXCLRDataProcess_GetTaskByOSThreadID(process, (ULONG)DnThread->ThreadItem->ThreadId, &task)))
228  {
229  if (SUCCEEDED(IXCLRDataTask_GetCurrentAppDomain(task, &appDomain)))
230  {
231  DnThread->AppDomainText = GetNameXClrDataAppDomain(appDomain);
232  IXCLRDataAppDomain_Release(appDomain);
233  }
234 
235  IXCLRDataTask_Release(task);
236  }
237 
238  DnThread->ClrDataValid = TRUE;
239  }
240 }
241 
243  _In_ PVOID Parameter
244  )
245 {
246  PPH_PLUGIN_TREENEW_MESSAGE message = Parameter;
247  PTHREAD_TREE_CONTEXT context = message->Context;
248 
249  if (message->Message == TreeNewGetCellText)
250  {
251  PPH_TREENEW_GET_CELL_TEXT getCellText = message->Parameter1;
252  PPH_THREAD_NODE threadNode = (PPH_THREAD_NODE)getCellText->Node;
253  PDN_THREAD_ITEM dnThread;
254 
256 
257  switch (message->SubId)
258  {
259  case DNTHTNC_APPDOMAIN:
260  UpdateThreadClrData(context, dnThread);
261  getCellText->Text = PhGetStringRef(dnThread->AppDomainText);
262  break;
263  }
264  }
265 }
266 
268  _In_ PVOID Node1,
269  _In_ PVOID Node2,
270  _In_ ULONG SubId,
271  _In_ PVOID Context
272  )
273 {
274  PTHREAD_TREE_CONTEXT context = Context;
275  LONG result;
276  PPH_THREAD_NODE node1 = Node1;
277  PPH_THREAD_NODE node2 = Node2;
278  PDN_THREAD_ITEM dnThread1;
279  PDN_THREAD_ITEM dnThread2;
280 
283 
284  result = 0;
285 
286  switch (SubId)
287  {
288  case DNTHTNC_APPDOMAIN:
289  UpdateThreadClrData(context, dnThread1);
290  UpdateThreadClrData(context, dnThread2);
291  result = PhCompareStringWithNull(dnThread1->AppDomainText, dnThread2->AppDomainText, TRUE);
292  break;
293  }
294 
295  return result;
296 }