Process Hacker
ndis.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Extra Plugins -
3  * Network Adapters Plugin
4  *
5  * Copyright (C) 2015 dmex
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 "main.h"
24 
25 HMODULE IphlpHandle = NULL;
28 
30  _In_ HANDLE DeviceHandle
31  )
32 {
33  NDIS_OID opcode;
34  IO_STATUS_BLOCK isb;
35  BOOLEAN ndisQuerySupported = FALSE;
36  BOOLEAN adapterNameSupported = FALSE;
37  BOOLEAN adapterStatsSupported = FALSE;
38  BOOLEAN adapterLinkStateSupported = FALSE;
39  BOOLEAN adapterLinkSpeedSupported = FALSE;
40  PNDIS_OID ndisObjectIdentifiers = NULL;
41 
42  // https://msdn.microsoft.com/en-us/library/ff569642.aspx
43  opcode = OID_GEN_SUPPORTED_LIST;
44 
45  // TODO: 4096 objects might be too small...
46  ndisObjectIdentifiers = PhAllocate(sizeof(NDIS_OID) * PAGE_SIZE);
47  memset(ndisObjectIdentifiers, 0, sizeof(NDIS_OID) * PAGE_SIZE);
48 
50  DeviceHandle,
51  NULL,
52  NULL,
53  NULL,
54  &isb,
55  IOCTL_NDIS_QUERY_GLOBAL_STATS,
56  &opcode,
57  sizeof(NDIS_OID),
58  ndisObjectIdentifiers,
59  sizeof(NDIS_OID) * PAGE_SIZE
60  )))
61  {
62  ndisQuerySupported = TRUE;
63 
64  for (ULONG i = 0; i < (ULONG)isb.Information; i++)
65  {
66  NDIS_OID opcode = ndisObjectIdentifiers[i];
67 
68  switch (opcode)
69  {
70  case OID_GEN_FRIENDLY_NAME:
71  adapterNameSupported = TRUE;
72  break;
73  case OID_GEN_STATISTICS:
74  adapterStatsSupported = TRUE;
75  break;
76  case OID_GEN_LINK_STATE:
77  adapterLinkStateSupported = TRUE;
78  break;
79  case OID_GEN_LINK_SPEED:
80  adapterLinkSpeedSupported = TRUE;
81  break;
82  }
83  }
84  }
85 
86  PhFree(ndisObjectIdentifiers);
87 
88  if (!adapterNameSupported)
89  ndisQuerySupported = FALSE;
90  if (!adapterStatsSupported)
91  ndisQuerySupported = FALSE;
92  if (!adapterLinkStateSupported)
93  ndisQuerySupported = FALSE;
94  if (!adapterLinkSpeedSupported)
95  ndisQuerySupported = FALSE;
96 
97  return ndisQuerySupported;
98 }
99 
101  _In_ HANDLE DeviceHandle,
102  _Out_opt_ PUINT MajorVersion,
103  _Out_opt_ PUINT MinorVersion
104  )
105 {
106  NDIS_OID opcode;
107  IO_STATUS_BLOCK isb;
108  ULONG versionResult = 0;
109 
110  // https://msdn.microsoft.com/en-us/library/ff569582.aspx
111  opcode = OID_GEN_DRIVER_VERSION; // OID_GEN_VENDOR_DRIVER_VERSION
112 
114  DeviceHandle,
115  NULL,
116  NULL,
117  NULL,
118  &isb,
119  IOCTL_NDIS_QUERY_GLOBAL_STATS,
120  &opcode,
121  sizeof(NDIS_OID),
122  &versionResult,
123  sizeof(versionResult)
124  )))
125  {
126  if (MajorVersion)
127  {
128  *MajorVersion = HIBYTE(versionResult);
129  }
130 
131  if (MinorVersion)
132  {
133  *MinorVersion = LOBYTE(versionResult);
134  }
135 
136  return TRUE;
137  }
138 
139  return FALSE;
140 }
141 
143  _Inout_ PPH_NETADAPTER_SYSINFO_CONTEXT Context
144  )
145 {
146  NDIS_OID opcode;
147  IO_STATUS_BLOCK isb;
148  WCHAR adapterNameBuffer[MAX_PATH] = L"";
149 
150  // https://msdn.microsoft.com/en-us/library/ff569584.aspx
151  opcode = OID_GEN_FRIENDLY_NAME;
152 
154  Context->DeviceHandle,
155  NULL,
156  NULL,
157  NULL,
158  &isb,
159  IOCTL_NDIS_QUERY_GLOBAL_STATS,
160  &opcode,
161  sizeof(NDIS_OID),
162  adapterNameBuffer,
163  sizeof(adapterNameBuffer)
164  )))
165  {
166  return PhCreateString(adapterNameBuffer);
167  }
168 
169  // HACK: Query adapter description using undocumented function.
171  {
172  GUID deviceGuid = GUID_NULL;
173  UNICODE_STRING guidStringUs;
174 
175  PhStringRefToUnicodeString(&Context->AdapterEntry->InterfaceGuid->sr, &guidStringUs);
176 
177  if (NT_SUCCESS(RtlGUIDFromString(&guidStringUs, &deviceGuid)))
178  {
179  SIZE_T adapterDescriptionLength = 0;
180  WCHAR adapterDescription[NDIS_IF_MAX_STRING_SIZE + 1] = L"";
181 
182  adapterDescriptionLength = sizeof(adapterDescription);
183 
184  if (SUCCEEDED(GetInterfaceDescriptionFromGuid_I(&deviceGuid, adapterDescription, &adapterDescriptionLength, NULL, NULL)))
185  {
186  return PhCreateString(adapterDescription);
187  }
188  }
189  }
190 
191  return PhCreateString(L"Unknown");
192 }
193 
195  _In_ HANDLE DeviceHandle,
196  _Out_ PNDIS_STATISTICS_INFO Info
197  )
198 {
199  NTSTATUS status;
200  NDIS_OID opcode;
201  IO_STATUS_BLOCK isb;
202  NDIS_STATISTICS_INFO result;
203 
204  // https://msdn.microsoft.com/en-us/library/ff569640.aspx
205  opcode = OID_GEN_STATISTICS;
206 
207  memset(&result, 0, sizeof(NDIS_STATISTICS_INFO));
208  result.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
209  result.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
210  result.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
211 
212  status = NtDeviceIoControlFile(
213  DeviceHandle,
214  NULL,
215  NULL,
216  NULL,
217  &isb,
218  IOCTL_NDIS_QUERY_GLOBAL_STATS,
219  &opcode,
220  sizeof(NDIS_OID),
221  &result,
222  sizeof(result)
223  );
224 
225  *Info = result;
226 
227  return status;
228 }
229 
231  _In_ HANDLE DeviceHandle,
232  _Out_ PNDIS_LINK_STATE State
233  )
234 {
235  NTSTATUS status;
236  NDIS_OID opcode;
237  IO_STATUS_BLOCK isb;
238  NDIS_LINK_STATE result;
239 
240  // https://msdn.microsoft.com/en-us/library/ff569595.aspx
241  opcode = OID_GEN_LINK_STATE; // OID_GEN_MEDIA_CONNECT_STATUS;
242 
243  memset(&result, 0, sizeof(NDIS_LINK_STATE));
244  result.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
245  result.Header.Revision = NDIS_LINK_STATE_REVISION_1;
246  result.Header.Size = NDIS_SIZEOF_LINK_STATE_REVISION_1;
247 
248  status = NtDeviceIoControlFile(
249  DeviceHandle,
250  NULL,
251  NULL,
252  NULL,
253  &isb,
254  IOCTL_NDIS_QUERY_GLOBAL_STATS,
255  &opcode,
256  sizeof(NDIS_OID),
257  &result,
258  sizeof(result)
259  );
260 
261  *State = result;
262 
263  return status;
264 }
265 
267  _In_ HANDLE DeviceHandle,
268  _Out_ PNDIS_PHYSICAL_MEDIUM Medium
269  )
270 {
271  NDIS_OID opcode;
272  IO_STATUS_BLOCK isb;
273  NDIS_PHYSICAL_MEDIUM adapterMediaType = NdisPhysicalMediumUnspecified;
274 
275  // https://msdn.microsoft.com/en-us/library/ff569622.aspx
276  opcode = OID_GEN_PHYSICAL_MEDIUM_EX;
277 
279  DeviceHandle,
280  NULL,
281  NULL,
282  NULL,
283  &isb,
284  IOCTL_NDIS_QUERY_GLOBAL_STATS,
285  &opcode,
286  sizeof(NDIS_OID),
287  &adapterMediaType,
288  sizeof(adapterMediaType)
289  )))
290  {
291  *Medium = adapterMediaType;
292  }
293 
294  if (adapterMediaType != NdisPhysicalMediumUnspecified)
295  return TRUE;
296 
297  // https://msdn.microsoft.com/en-us/library/ff569621.aspx
298  opcode = OID_GEN_PHYSICAL_MEDIUM;
299  adapterMediaType = NdisPhysicalMediumUnspecified;
300  memset(&isb, 0, sizeof(IO_STATUS_BLOCK));
301 
303  DeviceHandle,
304  NULL,
305  NULL,
306  NULL,
307  &isb,
308  IOCTL_NDIS_QUERY_GLOBAL_STATS,
309  &opcode,
310  sizeof(NDIS_OID),
311  &adapterMediaType,
312  sizeof(adapterMediaType)
313  )))
314  {
315  *Medium = adapterMediaType;
316  }
317 
318  if (adapterMediaType != NdisPhysicalMediumUnspecified)
319  return TRUE;
320 
321  //NDIS_MEDIUM adapterMediaType = NdisMediumMax;
322  //opcode = OID_GEN_MEDIA_IN_USE;
323 
324  return FALSE;
325 }
326 
328  _In_ HANDLE DeviceHandle,
329  _Out_ PULONG64 LinkSpeed
330  )
331 {
332  NTSTATUS status;
333  NDIS_OID opcode;
334  IO_STATUS_BLOCK isb;
335  NDIS_CO_LINK_SPEED result;
336 
337  // https://msdn.microsoft.com/en-us/library/ff569593.aspx
338  opcode = OID_GEN_LINK_SPEED;
339 
340  memset(&result, 0, sizeof(NDIS_CO_LINK_SPEED));
341 
342  status = NtDeviceIoControlFile(
343  DeviceHandle,
344  NULL,
345  NULL,
346  NULL,
347  &isb,
348  IOCTL_NDIS_QUERY_GLOBAL_STATS,
349  &opcode,
350  sizeof(NDIS_OID),
351  &result,
352  sizeof(result)
353  );
354 
355  *LinkSpeed = UInt32x32To64(result.Outbound, NDIS_UNIT_OF_MEASUREMENT);
356 
357  return status;
358 }
359 
361  _In_ HANDLE DeviceHandle,
362  _In_ NDIS_OID OpCode
363  )
364 {
365  IO_STATUS_BLOCK isb;
366  ULONG64 result = 0;
367 
369  DeviceHandle,
370  NULL,
371  NULL,
372  NULL,
373  &isb,
374  IOCTL_NDIS_QUERY_GLOBAL_STATS,
375  &OpCode,
376  sizeof(NDIS_OID),
377  &result,
378  sizeof(result)
379  )))
380  {
381  return result;
382  }
383 
384  return 0;
385 }
386 
388  _Inout_ PPH_NETADAPTER_SYSINFO_CONTEXT Context
389  )
390 {
391  MIB_IF_ROW2 interfaceRow;
392 
393  memset(&interfaceRow, 0, sizeof(MIB_IF_ROW2));
394 
395  interfaceRow.InterfaceLuid = Context->AdapterEntry->InterfaceLuid;
396  interfaceRow.InterfaceIndex = Context->AdapterEntry->InterfaceIndex;
397 
398  if (GetIfEntry2_I)
399  {
400  GetIfEntry2_I(&interfaceRow);
401  }
402 
403  //MIB_IPINTERFACE_ROW interfaceTable;
404  //memset(&interfaceTable, 0, sizeof(MIB_IPINTERFACE_ROW));
405  //interfaceTable.Family = AF_INET;
406  //interfaceTable.InterfaceLuid.Value = Context->AdapterEntry->InterfaceLuidValue;
407  //interfaceTable.InterfaceIndex = Context->AdapterEntry->InterfaceIndex;
408  //GetIpInterfaceEntry(&interfaceTable);
409 
410  return interfaceRow;
411 }
412 
414  _Inout_ PPH_NETADAPTER_SYSINFO_CONTEXT Context
415  )
416 {
417  MIB_IFROW interfaceRow;
418 
419  memset(&interfaceRow, 0, sizeof(MIB_IFROW));
420 
421  interfaceRow.dwIndex = Context->AdapterEntry->InterfaceIndex;
422 
423  GetIfEntry(&interfaceRow);
424 
425  //MIB_IPINTERFACE_ROW interfaceTable;
426  //memset(&interfaceTable, 0, sizeof(MIB_IPINTERFACE_ROW));
427  //interfaceTable.Family = AF_INET;
428  //interfaceTable.InterfaceIndex = Context->AdapterEntry->InterfaceIndex;
429  //GetIpInterfaceEntry(&interfaceTable);
430 
431  return interfaceRow;
432 }