Process Hacker
qrydrv.c
Go to the documentation of this file.
1 /*
2  * KProcessHacker
3  *
4  * Copyright (C) 2010-2011 wj32
5  *
6  * This file is part of Process Hacker.
7  *
8  * Process Hacker is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Process Hacker is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <kph.h>
23 
25  __out PVOID Information,
26  __in_opt PUNICODE_STRING UnicodeString
27  );
28 
29 #ifdef ALLOC_PRAGMA
30 #pragma alloc_text(PAGE, KpiOpenDriver)
31 #pragma alloc_text(PAGE, KpiQueryInformationDriver)
32 #pragma alloc_text(PAGE, KphpCopyInfoUnicodeString)
33 #endif
34 
35 NTSTATUS KpiOpenDriver(
36  __out PHANDLE DriverHandle,
37  __in POBJECT_ATTRIBUTES ObjectAttributes,
38  __in KPROCESSOR_MODE AccessMode
39  )
40 {
41  PAGED_CODE();
42 
43  return KphOpenNamedObject(
44  DriverHandle,
45  0,
46  ObjectAttributes,
48  AccessMode
49  );
50 }
51 
53  __in HANDLE DriverHandle,
54  __in DRIVER_INFORMATION_CLASS DriverInformationClass,
55  __out_bcount(DriverInformationLength) PVOID DriverInformation,
56  __in ULONG DriverInformationLength,
57  __out_opt PULONG ReturnLength,
58  __in KPROCESSOR_MODE AccessMode
59  )
60 {
61  NTSTATUS status = STATUS_SUCCESS;
62  PDRIVER_OBJECT driverObject;
63 
64  PAGED_CODE();
65 
66  if (AccessMode != KernelMode)
67  {
68  __try
69  {
70  ProbeForWrite(DriverInformation, DriverInformationLength, 1);
71 
72  if (ReturnLength)
73  ProbeForWrite(ReturnLength, sizeof(ULONG), 1);
74  }
75  __except (EXCEPTION_EXECUTE_HANDLER)
76  {
77  return GetExceptionCode();
78  }
79  }
80 
81  status = ObReferenceObjectByHandle(
82  DriverHandle,
83  0,
85  AccessMode,
86  &driverObject,
87  NULL
88  );
89 
90  if (!NT_SUCCESS(status))
91  return status;
92 
93  __try
94  {
95  switch (DriverInformationClass)
96  {
97  // Basic information such as flags, driver base and driver size.
99  {
100  if (DriverInformationLength == sizeof(DRIVER_BASIC_INFORMATION))
101  {
102  PDRIVER_BASIC_INFORMATION basicInfo;
103 
104  basicInfo = (PDRIVER_BASIC_INFORMATION)DriverInformation;
105  basicInfo->Flags = driverObject->Flags;
106  basicInfo->DriverStart = driverObject->DriverStart;
107  basicInfo->DriverSize = driverObject->DriverSize;
108  }
109  else
110  {
111  status = STATUS_INFO_LENGTH_MISMATCH;
112  }
113 
114  if (ReturnLength)
115  *ReturnLength = sizeof(DRIVER_BASIC_INFORMATION);
116  }
117  break;
118 
119  // The name of the driver - e.g. \Driver\KProcessHacker2.
121  {
122  if (DriverInformation)
123  {
124  /* Check buffer length. */
125  if (
126  sizeof(UNICODE_STRING) +
127  driverObject->DriverName.Length <=
128  DriverInformationLength
129  )
130  {
132  DriverInformation,
133  &driverObject->DriverName
134  );
135  }
136  else
137  {
138  status = STATUS_BUFFER_TOO_SMALL;
139  }
140  }
141 
142  if (ReturnLength)
143  *ReturnLength = sizeof(UNICODE_STRING) + driverObject->DriverName.Length;
144  }
145  break;
146 
147  // The name of the driver's service key - e.g. \REGISTRY\...
149  {
150  if (driverObject->DriverExtension)
151  {
152  if (DriverInformation)
153  {
154  if (
155  sizeof(UNICODE_STRING) +
156  driverObject->DriverExtension->ServiceKeyName.Length <=
157  DriverInformationLength
158  )
159  {
161  DriverInformation,
162  &driverObject->DriverExtension->ServiceKeyName
163  );
164  }
165  else
166  {
167  status = STATUS_BUFFER_TOO_SMALL;
168  }
169  }
170 
171  if (ReturnLength)
172  *ReturnLength = sizeof(UNICODE_STRING) +
173  driverObject->DriverExtension->ServiceKeyName.Length;
174  }
175  else
176  {
177  if (DriverInformation)
178  {
179  if (sizeof(UNICODE_STRING) <= DriverInformationLength)
180  {
181  // Zero the information buffer.
183  DriverInformation,
184  NULL
185  );
186  }
187  else
188  {
189  status = STATUS_BUFFER_TOO_SMALL;
190  }
191  }
192 
193  if (ReturnLength)
194  *ReturnLength = sizeof(UNICODE_STRING);
195  }
196  }
197  break;
198 
199  default:
200  {
201  status = STATUS_INVALID_INFO_CLASS;
202  }
203  }
204  }
205  __except (EXCEPTION_EXECUTE_HANDLER)
206  {
207  status = GetExceptionCode();
208  }
209 
210  ObDereferenceObject(driverObject);
211 
212  return status;
213 }
214 
216  __out PVOID Information,
217  __in_opt PUNICODE_STRING UnicodeString
218  )
219 {
220  PUNICODE_STRING targetUnicodeString = (PUNICODE_STRING)Information;
221 
222  PAGED_CODE();
223 
224  if (UnicodeString)
225  {
226  targetUnicodeString->Length = UnicodeString->Length;
227  targetUnicodeString->MaximumLength = targetUnicodeString->Length;
228  targetUnicodeString->Buffer = (PWSTR)((PCHAR)Information + sizeof(UNICODE_STRING));
229  memcpy(
230  targetUnicodeString->Buffer,
231  UnicodeString->Buffer,
232  targetUnicodeString->Length
233  );
234  }
235  else
236  {
237  targetUnicodeString->Length = 0;
238  targetUnicodeString->MaximumLength = 0;
239  targetUnicodeString->Buffer = NULL;
240  }
241 }