win-pvdrivers

view xenhide/xenhide.c @ 405:4fee03f012ee

list_entry can be accessed at DISPATCH_LEVEL so make in NonPagedPool
author James Harper <james.harper@bendigoit.com.au>
date Thu Jul 24 19:53:37 2008 +1000 (2008-07-24)
parents abdcb860cfdf
children ee82244eed7c
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenhide.h"
21 #include <stdlib.h>
23 DRIVER_INITIALIZE DriverEntry;
24 static NTSTATUS
25 XenHide_AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject);
26 static NTSTATUS
27 XenHide_Pass(PDEVICE_OBJECT DeviceObject, PIRP Irp);
28 static NTSTATUS
29 XenHide_Pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
30 static NTSTATUS
31 XenHide_AddDevice();
32 //static NTSTATUS
33 //XenHide_Unload();
35 #ifdef ALLOC_PRAGMA
36 #pragma alloc_text (INIT, DriverEntry)
37 #pragma alloc_text (PAGE, XenHide_AddDevice)
38 #endif
40 static BOOLEAN gplpv;
41 static BOOLEAN qemu_ide_device_filter_installed;
42 static BOOLEAN qemu_scsi_device_filter_installed;
43 static KEVENT add_device_event;
44 static XENHIDE_DRIVER_DATA xenhide_global_data;
46 static NTSTATUS
47 XenHide_Power(PDEVICE_OBJECT device_object, PIRP irp)
48 {
49 NTSTATUS status;
50 PXENHIDE_DEVICE_DATA xhdd = (PXENHIDE_DEVICE_DATA)device_object->DeviceExtension;
52 PoStartNextPowerIrp(irp);
53 IoSkipCurrentIrpStackLocation(irp);
54 status = PoCallDriver(xhdd->lower_do, irp);
55 return status;
56 }
58 NTSTATUS
59 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
60 {
61 NTSTATUS status;
62 UNICODE_STRING RegKeyName;
63 UNICODE_STRING RegValueName;
64 HANDLE RegHandle;
65 OBJECT_ATTRIBUTES RegObjectAttributes;
66 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
67 ULONG BufLen = 300;
68 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
69 int State = 0;
70 size_t StartPos = 0;
71 WCHAR *SystemStartOptions;
72 size_t SystemStartOptionsLen;
73 size_t i;
75 UNREFERENCED_PARAMETER(RegistryPath);
77 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
79 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
80 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
81 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
82 if(!NT_SUCCESS(status))
83 {
84 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
85 }
87 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
88 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
89 if(!NT_SUCCESS(status))
90 {
91 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
92 }
93 else
94 ZwClose(RegHandle);
95 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
96 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
98 qemu_ide_device_filter_installed = FALSE;
99 qemu_scsi_device_filter_installed = FALSE;
100 KeInitializeEvent(&add_device_event, SynchronizationEvent, FALSE);
102 gplpv = FALSE;
104 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
106 for (i = 0; i <= SystemStartOptionsLen/2; i++)
107 {
108 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
110 switch (State)
111 {
112 case 0:
113 if (SystemStartOptions[i] == L'G')
114 {
115 StartPos = (int)i;
116 State = 2;
117 } else if (SystemStartOptions[i] != L' ')
118 {
119 State = 1;
120 }
121 break;
122 case 1:
123 if (SystemStartOptions[i] == L' ')
124 State = 0;
125 break;
126 case 2:
127 if (SystemStartOptions[i] == L'P')
128 State = 3;
129 else
130 State = 0;
131 break;
132 case 3:
133 if (SystemStartOptions[i] == L'L')
134 State = 4;
135 else
136 State = 0;
137 break;
138 case 4:
139 if (SystemStartOptions[i] == L'P')
140 State = 5;
141 else
142 State = 0;
143 break;
144 case 5:
145 if (SystemStartOptions[i] == L'V')
146 State = 6;
147 else
148 State = 0;
149 break;
150 case 6:
151 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
152 gplpv = TRUE;
153 State = 0;
154 break;
155 }
156 }
158 KdPrint((__DRIVER_NAME " gplpv = %d\n", gplpv));
160 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
161 DriverObject->MajorFunction[i] = XenHide_Pass;
162 DriverObject->MajorFunction[IRP_MJ_PNP] = XenHide_Pnp;
163 DriverObject->MajorFunction[IRP_MJ_POWER] = XenHide_Power;
164 DriverObject->DriverExtension->AddDevice = XenHide_AddDevice;
166 RtlZeroMemory(&xenhide_global_data, sizeof(XENHIDE_DRIVER_DATA));
168 InitializeListHead(&xenhide_global_data.hide_list_head);
169 KeInitializeSpinLock(&xenhide_global_data.hide_list_lock);
170 KeInitializeEvent(&xenhide_global_data.hide_list_event, SynchronizationEvent, FALSE);
172 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
174 return status;
175 }
177 static BOOLEAN
178 XenHide_IdSuffixMatches(PDEVICE_OBJECT pdo, PWCHAR matching_id)
179 {
180 NTSTATUS status;
181 ULONG remaining;
182 size_t string_length;
183 WCHAR ids[512];
184 PWCHAR ptr;
185 ULONG ids_length;
186 int i;
188 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
189 for (i = 0; i < 2; i++)
190 {
191 if (i == 0)
192 status = IoGetDeviceProperty(pdo, DevicePropertyCompatibleIDs, sizeof(ids), ids, &ids_length);
193 else
194 status = IoGetDeviceProperty(pdo, DevicePropertyHardwareID, sizeof(ids), ids, &ids_length);
196 if (!NT_SUCCESS(status))
197 {
198 // KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
199 continue;
200 }
202 remaining = ids_length / 2;
203 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
204 {
205 RtlStringCchLengthW(ptr, remaining, &string_length);
206 remaining -= (ULONG)string_length + 1;
207 if (string_length >= wcslen(matching_id))
208 {
209 ptr += string_length - wcslen(matching_id);
210 string_length = (ULONG)wcslen(matching_id);
211 }
212 // KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
213 if (wcscmp(ptr, matching_id) == 0)
214 {
215 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Match)\n"));
216 return TRUE;
217 }
218 }
219 }
220 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (No match)\n"));
221 return FALSE;
222 }
224 static NTSTATUS
225 XenHide_AddDevice(
226 PDRIVER_OBJECT DriverObject,
227 PDEVICE_OBJECT PhysicalDeviceObject
228 )
229 {
230 NTSTATUS status;
231 PDEVICE_OBJECT deviceObject = NULL;
232 PXENHIDE_DEVICE_DATA xhdd;
233 ULONG length;
234 GUID bus_type;
235 WCHAR device_description[256];
236 KIRQL old_irql;
237 USHORT hide_type;
238 PXENHIDE_HIDE_LIST_ENTRY list_entry;
240 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
243 length = 512;
244 status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDeviceDescription, length, device_description, &length);
245 if (!NT_SUCCESS(status))
246 {
247 device_description[0] = 0;
248 }
250 //KdPrint((__DRIVER_NAME " Checking '%S'\n", device_description));
252 length = sizeof(GUID);
253 status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyBusTypeGuid, length, &bus_type, &length);
254 if (!NT_SUCCESS(status))
255 {
256 RtlZeroMemory(&bus_type, sizeof(GUID));
257 }
259 hide_type = XENHIDE_TYPE_NONE;
260 if (gplpv)
261 {
262 /* hide only specific devices */
263 if (XenHide_IdSuffixMatches(PhysicalDeviceObject, L"VEN_8086&DEV_7010")) // Qemu IDE
264 {
265 hide_type = XENHIDE_TYPE_DEVICE;
266 qemu_ide_device_filter_installed = TRUE;
267 KeSetEvent(&add_device_event, IO_NO_INCREMENT, FALSE);
268 }
269 else if (XenHide_IdSuffixMatches(PhysicalDeviceObject, L"VEN_1000&DEV_0012"))// Qemu SCSI
270 {
271 hide_type = XENHIDE_TYPE_DEVICE;
272 qemu_scsi_device_filter_installed = TRUE;
273 KeSetEvent(&add_device_event, IO_NO_INCREMENT, FALSE);
274 }
275 else if (XenHide_IdSuffixMatches(PhysicalDeviceObject, L"VEN_10EC&DEV_8139")) // Qemu Network
276 {
277 hide_type = XENHIDE_TYPE_DEVICE;
278 }
279 else if (XenHide_IdSuffixMatches(PhysicalDeviceObject, L"PNP0A03"))
280 {
281 hide_type = XENHIDE_TYPE_PCI_BUS;
282 }
283 }
284 else
285 {
286 /* hide everything on the xen bus */
287 if (memcmp(&bus_type, &GUID_BUS_TYPE_XEN, sizeof(GUID)) == 0)
288 hide_type = XENHIDE_TYPE_DEVICE;
289 }
291 if (hide_type == XENHIDE_TYPE_NONE)
292 {
293 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
294 return STATUS_SUCCESS;
295 }
297 //KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
299 if (gplpv && hide_type == XENHIDE_TYPE_DEVICE)
300 {
301 KeAcquireSpinLock(&xenhide_global_data.hide_list_lock, &old_irql);
302 list_entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENHIDE_HIDE_LIST_ENTRY), XENHIDE_POOL_TAG);
303 list_entry->pdo = PhysicalDeviceObject;
304 InsertTailList(&xenhide_global_data.hide_list_head, (PLIST_ENTRY)list_entry);
305 KeReleaseSpinLock(&xenhide_global_data.hide_list_lock, old_irql);
306 KeSetEvent(&xenhide_global_data.hide_list_event, IO_NO_INCREMENT, FALSE);
307 ASSERT(xenhide_global_data.pci_bus_pdo);
308 IoInvalidateDeviceRelations(xenhide_global_data.pci_bus_pdo, BusRelations);
309 }
310 else if (hide_type == XENHIDE_TYPE_PCI_BUS)
311 {
312 ASSERT(!xenhide_global_data.pci_bus_pdo);
313 xenhide_global_data.pci_bus_pdo = PhysicalDeviceObject;
314 }
316 status = IoCreateDevice (DriverObject,
317 sizeof(XENHIDE_DEVICE_DATA),
318 NULL,
319 FILE_DEVICE_UNKNOWN,
320 FILE_DEVICE_SECURE_OPEN,
321 FALSE,
322 &deviceObject);
324 xhdd = (PXENHIDE_DEVICE_DATA)deviceObject->DeviceExtension;
326 xhdd->hide_type = hide_type;
328 xhdd->lower_do = IoAttachDeviceToDeviceStack(
329 deviceObject, PhysicalDeviceObject);
330 deviceObject->Flags |= xhdd->lower_do->Flags;
332 deviceObject->DeviceType = xhdd->lower_do->DeviceType;
334 deviceObject->Characteristics =
335 xhdd->lower_do->Characteristics;
337 xhdd->filter_do = deviceObject;
339 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
341 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
343 return STATUS_SUCCESS;
344 }
346 static NTSTATUS
347 XenHide_Pass(PDEVICE_OBJECT DeviceObject, PIRP Irp)
348 {
349 PXENHIDE_DEVICE_DATA xhdd = (PXENHIDE_DEVICE_DATA)DeviceObject->DeviceExtension;
350 NTSTATUS status;
352 IoSkipCurrentIrpStackLocation(Irp);
353 status = IoCallDriver(xhdd->lower_do, Irp);
354 return status;
355 }
357 static NTSTATUS
358 XenHide_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
359 {
360 PKEVENT event = (PKEVENT)context;
362 UNREFERENCED_PARAMETER(device_object);
364 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
366 if (irp->PendingReturned)
367 {
368 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
369 }
371 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
373 return STATUS_MORE_PROCESSING_REQUIRED;
374 }
376 static NTSTATUS
377 XenHide_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
378 {
379 NTSTATUS status;
380 PXENHIDE_DEVICE_DATA xhdd = (PXENHIDE_DEVICE_DATA)device_object->DeviceExtension;
381 KEVENT event;
383 UNREFERENCED_PARAMETER(device_object);
385 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
387 KeInitializeEvent(&event, NotificationEvent, FALSE);
389 IoCopyCurrentIrpStackLocationToNext(irp);
390 IoSetCompletionRoutine(irp, XenHide_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
392 status = IoCallDriver(xhdd->lower_do, irp);
394 if (status == STATUS_PENDING)
395 {
396 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
397 status = irp->IoStatus.Status;
398 }
400 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
402 return status;
403 }
405 static NTSTATUS
406 XenHide_Pnp(PDEVICE_OBJECT device_object, PIRP irp)
407 {
408 NTSTATUS status = STATUS_SUCCESS;
409 PIO_STACK_LOCATION stack;
410 PXENHIDE_DEVICE_DATA xhdd = (PXENHIDE_DEVICE_DATA)device_object->DeviceExtension;
411 PDEVICE_RELATIONS relations;
412 PXENHIDE_HIDE_LIST_ENTRY list_entry;
413 ULONG i, j;
414 KIRQL old_irql;
416 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
418 stack = IoGetCurrentIrpStackLocation(irp);
420 switch (stack->MinorFunction) {
421 case IRP_MN_START_DEVICE:
422 //KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
423 if (xhdd->hide_type == XENHIDE_TYPE_DEVICE)
424 {
425 //KdPrint((__DRIVER_NAME " hide_type == XENHIDE_TYPE_DEVICE\n"));
426 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
427 IoCompleteRequest(irp, IO_NO_INCREMENT);
428 }
429 else
430 {
431 //KdPrint((__DRIVER_NAME " hide_type != XENHIDE_TYPE_DEVICE\n"));
432 IoSkipCurrentIrpStackLocation(irp);
433 status = IoCallDriver(xhdd->lower_do, irp);
434 }
435 break;
436 case IRP_MN_QUERY_DEVICE_RELATIONS:
437 if (xhdd->hide_type == XENHIDE_TYPE_PCI_BUS && stack->Parameters.QueryDeviceRelations.Type == BusRelations)
438 {
439 //KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS - BusRelations\n"));
440 IoMarkIrpPending(irp);
441 status = XenHide_SendAndWaitForIrp(device_object, irp);
442 relations = (PDEVICE_RELATIONS)irp->IoStatus.Information;
443 for (i = 0, j = 0; i < relations->Count; i++)
444 {
445 if (i != j)
446 relations->Objects[j] = relations->Objects[i];
447 KeAcquireSpinLock(&xenhide_global_data.hide_list_lock, &old_irql);
448 list_entry = (PXENHIDE_HIDE_LIST_ENTRY)xenhide_global_data.hide_list_head.Flink;
449 while (list_entry != (PXENHIDE_HIDE_LIST_ENTRY)&xenhide_global_data.hide_list_head)
450 {
451 if (relations->Objects[i] == list_entry->pdo)
452 {
453 //KdPrint((__DRIVER_NAME " Hiding %p\n", relations->Objects[i]));
454 break;
455 }
456 list_entry = (PXENHIDE_HIDE_LIST_ENTRY)list_entry->entry.Flink;
457 }
458 if (list_entry == (PXENHIDE_HIDE_LIST_ENTRY)&xenhide_global_data.hide_list_head)
459 j++;
460 KeReleaseSpinLock(&xenhide_global_data.hide_list_lock, old_irql);
461 }
462 relations->Count = j;
463 irp->IoStatus.Status = status;
464 IoCompleteRequest (irp, IO_NO_INCREMENT);
465 }
466 else
467 {
468 IoSkipCurrentIrpStackLocation(irp);
469 status = IoCallDriver(xhdd->lower_do, irp);
470 }
471 break;
472 default:
473 IoSkipCurrentIrpStackLocation(irp);
474 status = IoCallDriver(xhdd->lower_do, irp);
475 break;
476 }
478 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returning with status %08x)\n", status));
480 return status;
481 }