Process Hacker
counters.c
Go to the documentation of this file.
1 /*
2  * Process Hacker .NET Tools -
3  * performance counter support functions
4  *
5  * Copyright (C) 2011 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 
26  _In_ HKEY Key,
27  _In_ PWSTR ValueName,
28  _Out_ PVOID *Data,
29  _Out_opt_ PULONG DataSize
30  )
31 {
32  LONG result;
33  PVOID data;
34  ULONG dataSize;
35  ULONG bufferSize;
36 
37  dataSize = 0x800;
38  data = PhAllocate(dataSize);
39 
40  while (TRUE)
41  {
42  bufferSize = dataSize;
43  result = RegQueryValueEx(Key, ValueName, NULL, NULL, data, &bufferSize);
44 
45  if (result == ERROR_MORE_DATA)
46  {
47  PhFree(data);
48  dataSize += 4096 * 4;
49  data = PhAllocate(dataSize);
50  }
51  else
52  {
53  break;
54  }
55  }
56 
57  if (result == ERROR_SUCCESS)
58  {
59  *Data = data;
60 
61  if (DataSize)
62  *DataSize = dataSize;
63 
64  return TRUE;
65  }
66  else
67  {
68  return FALSE;
69  }
70 }
71 
73  _In_ PVOID TextData,
74  _In_ ULONG Index
75  )
76 {
77  PWSTR textData;
78 
79  textData = TextData;
80 
81  // Skip the first pair.
82  textData += PhCountStringZ(textData) + 1;
83  textData += PhCountStringZ(textData) + 1;
84 
85  while (*textData)
86  {
87  ULONG index;
88 
89  index = _wtoi(textData);
90  textData += PhCountStringZ(textData) + 1;
91 
92  if (index == Index)
93  {
94  return textData;
95  }
96 
97  textData += PhCountStringZ(textData) + 1;
98  }
99 
100  return NULL;
101 }
102 
104  _In_ PVOID TextData,
105  _In_ PPH_STRINGREF Text
106  )
107 {
108  PWSTR textData;
109 
110  textData = TextData;
111 
112  // Skip the first pair.
113  textData += PhCountStringZ(textData) + 1;
114  textData += PhCountStringZ(textData) + 1;
115 
116  while (*textData)
117  {
118  ULONG index;
119  PWSTR text;
120  SIZE_T length;
121  PH_STRINGREF textSr;
122 
123  index = _wtoi(textData);
124  textData += PhCountStringZ(textData) + 1;
125 
126  text = textData;
127  length = PhCountStringZ(textData);
128  textData += length + 1;
129 
130  textSr.Buffer = text;
131  textSr.Length = length * sizeof(WCHAR);
132 
133  if (PhEqualStringRef(&textSr, Text, TRUE))
134  return index;
135  }
136 
137  return -1;
138 }
139 
141  _In_opt_ PPH_STRINGREF Filter,
142  _Out_ PPERF_OBJECT_TYPE_INFO *Info,
143  _Out_ PULONG Count
144  )
145 {
146  BOOLEAN result;
147  PVOID textData = NULL;
148  PVOID data = NULL;
149  PPERF_OBJECT_TYPE_INFO info = NULL;
150  ULONG infoCount;
151  ULONG infoAllocated;
152  PPERF_DATA_BLOCK block;
153  PPERF_OBJECT_TYPE objectType;
154  ULONG i;
155 
156  result = FALSE;
157 
158  if (!QueryPerfInfoVariableSize(HKEY_PERFORMANCE_DATA, L"Counter 009", &textData, NULL)) // can't support non-English because of filter
159  return FALSE;
160 
161  if (!QueryPerfInfoVariableSize(HKEY_PERFORMANCE_DATA, L"Global", &data, NULL))
162  goto ExitCleanup;
163 
164  block = data;
165 
166  if (memcmp(block->Signature, L"PERF", sizeof(WCHAR) * 4) != 0)
167  goto ExitCleanup;
168 
169  objectType = (PPERF_OBJECT_TYPE)((PCHAR)block + block->HeaderLength);
170  infoCount = 0;
171  infoAllocated = 16;
172  info = PhAllocate(sizeof(PERF_OBJECT_TYPE_INFO) * infoAllocated);
173 
174  for (i = 0; i < block->NumObjectTypes; i++)
175  {
176  PWSTR objectTypeName;
177  PPERF_OBJECT_TYPE_INFO infoMember;
178 
179  objectTypeName = FindPerfTextInTextData(textData, objectType->ObjectNameTitleIndex);
180 
181  if (objectTypeName)
182  {
183  PH_STRINGREF objectTypeNameSr;
184 
185  PhInitializeStringRef(&objectTypeNameSr, objectTypeName);
186 
187  if (!Filter || PhStartsWithStringRef(&objectTypeNameSr, Filter, TRUE))
188  {
189  if (infoCount == infoAllocated)
190  {
191  infoAllocated *= 2;
192  info = PhReAllocate(info, sizeof(PERF_OBJECT_TYPE_INFO) * infoAllocated);
193  }
194 
195  infoMember = &info[infoCount++];
196  infoMember->NameIndex = objectType->ObjectHelpTitleIndex;
197  infoMember->NameBuffer = PhCreateString(objectTypeName);
198  infoMember->Name = infoMember->NameBuffer->sr;
199  }
200  }
201 
202  objectType = (PPERF_OBJECT_TYPE)((PCHAR)objectType + objectType->TotalByteLength);
203  }
204 
205  *Info = info;
206  *Count = infoCount;
207  result = TRUE;
208 
209 ExitCleanup:
210  if (!result)
211  {
212  if (info)
213  PhFree(info);
214  }
215 
216  if (data)
217  PhFree(data);
218  if (textData)
219  PhFree(textData);
220 
221  return result;
222 }
223 
225  _In_ PPH_STRINGREF NameList,
226  _Out_ PPERF_OBJECT_TYPE_INFO *Info,
227  _Out_ PULONG Count,
228  _Out_opt_ PVOID *TextData
229  )
230 {
231  BOOLEAN result;
232  PVOID textData = NULL;
233  PH_STRINGREF part;
234  PH_STRINGREF remainingPart;
235  PPERF_OBJECT_TYPE_INFO info = NULL;
236  ULONG infoCount;
237  ULONG infoAllocated;
238 
239  result = FALSE;
240 
241  if (!QueryPerfInfoVariableSize(HKEY_PERFORMANCE_DATA, L"Counter 009", &textData, NULL)) // can't support non-English because of filter
242  return FALSE;
243 
244  infoCount = 0;
245  infoAllocated = 16;
246  info = PhAllocate(sizeof(PERF_OBJECT_TYPE_INFO) * infoAllocated);
247 
248  remainingPart = *NameList;
249 
250  while (remainingPart.Length != 0)
251  {
252  PhSplitStringRefAtChar(&remainingPart, ';', &part, &remainingPart);
253 
254  if (part.Length != 0)
255  {
256  ULONG index;
257 
258  index = FindPerfIndexInTextData(textData, &part);
259 
260  if (index != -1)
261  {
262  PPERF_OBJECT_TYPE_INFO infoMember;
263 
264  if (infoCount == infoAllocated)
265  {
266  infoAllocated *= 2;
267  info = PhReAllocate(info, sizeof(PERF_OBJECT_TYPE_INFO) * infoAllocated);
268  }
269 
270  infoMember = &info[infoCount++];
271  infoMember->NameIndex = index;
272  infoMember->Name = part;
273  infoMember->NameBuffer = NULL;
274  }
275  }
276  }
277 
278  *Info = info;
279  *Count = infoCount;
280  result = TRUE;
281 
282  if (TextData)
283  {
284  *TextData = textData;
285  }
286  else
287  {
288  PhFree(textData);
289  }
290 
291  return result;
292 }