win-pvdrivers

view xenhide/xenhide.c @ 363:097ab7d19ea2

Merge bug fixer from WDF to WDM.
author Wayne Gong <wayne.gong@oracle.com>
date Mon Jul 07 14:03:39 2008 +0800 (2008-07-07)
parents cb12e8b450a8
children 649b05070ede
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 XENHIDE_DRIVER_DATA xenhide_global_data;
43 static NTSTATUS
44 XenHide_Power(PDEVICE_OBJECT device_object, PIRP irp)
45 {
46 NTSTATUS status;
47 PXENHIDE_DEVICE_DATA xhdd = (PXENHIDE_DEVICE_DATA)device_object->DeviceExtension;
49 PoStartNextPowerIrp(irp);
50 IoSkipCurrentIrpStackLocation(irp);
51 status = PoCallDriver(xhdd->lower_do, irp);
52 return status;
53 }
55 NTSTATUS
56 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
57 {
58 NTSTATUS status;
59 UNICODE_STRING RegKeyName;
60 UNICODE_STRING RegValueName;
61 HANDLE RegHandle;
62 OBJECT_ATTRIBUTES RegObjectAttributes;
63 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
64 ULONG BufLen = 300;
65 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
66 int State = 0;
67 size_t StartPos = 0;
68 WCHAR *SystemStartOptions;
69 size_t SystemStartOptionsLen;
70 size_t i;
72 UNREFERENCED_PARAMETER(RegistryPath);
74 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
76 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
77 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
78 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
79 if(!NT_SUCCESS(status))
80 {
81 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
82 }
84 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
85 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
86 if(!NT_SUCCESS(status))
87 {
88 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
89 }
90 else
91 ZwClose(RegHandle);
92 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
93 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
95 gplpv = FALSE;
97 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
99 for (i = 0; i <= SystemStartOptionsLen/2; i++)
100 {
101 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
103 switch (State)
104 {
105 case 0:
106 if (SystemStartOptions[i] == L'G')
107 {
108 StartPos = (int)i;
109 State = 2;
110 } else if (SystemStartOptions[i] != L' ')
111 {
112 State = 1;
113 }
114 break;
115 case 1:
116 if (SystemStartOptions[i] == L' ')
117 State = 0;
118 break;
119 case 2:
120 if (SystemStartOptions[i] == L'P')
121 State = 3;
122 else
123 State = 0;
124 break;
125 case 3:
126 if (SystemStartOptions[i] == L'L')
127 State = 4;
128 else
129 State = 0;
130 break;
131 case 4:
132 if (SystemStartOptions[i] == L'P')
133 State = 5;
134 else
135 State = 0;
136 break;
137 case 5:
138 if (SystemStartOptions[i] == L'V')
139 State = 6;
140 else
141 State = 0;
142 break;
143 case 6:
144 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
145 gplpv = TRUE;
146 State = 0;
147 break;
148 }
149 }
151 KdPrint((__DRIVER_NAME " gplpv = %d\n", gplpv));
153 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
154 DriverObject->MajorFunction[i] = XenHide_Pass;
155 DriverObject->MajorFunction[IRP_MJ_PNP] = XenHide_Pnp;
156 DriverObject->MajorFunction[IRP_MJ_POWER] = XenHide_Power;
157 DriverObject->DriverExtension->AddDevice = XenHide_AddDevice;
159 RtlZeroMemory(&xenhide_global_data, sizeof(XENHIDE_DRIVER_DATA));
161 InitializeListHead(&xenhide_global_data.hide_list_head);
162 KeInitializeSpinLock(&xenhide_global_data.hide_list_lock);
163 KeInitializeEvent(&xenhide_global_data.hide_list_event, SynchronizationEvent, FALSE);
165 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
167 return status;
168 }
170 static BOOLEAN
171 XenHide_IdSuffixMatches(PDEVICE_OBJECT pdo, PWCHAR matching_id)
172 {
173 NTSTATUS status;
174 ULONG remaining;
175 ULONG string_length;
176 WCHAR ids[512];
177 PWCHAR ptr;
178 ULONG ids_length;
179 int i;
181 for (i = 0; i < 2; i++)
182 {
183 if (i == 0)
184 status = IoGetDeviceProperty(pdo, DevicePropertyCompatibleIDs, sizeof(ids), ids, &ids_length);
185 else
186 status = IoGetDeviceProperty(pdo, DevicePropertyHardwareID, sizeof(ids), ids, &ids_length);
188 if (!NT_SUCCESS(status))
189 {
190 //KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
191 continue;
192 }
194 remaining = ids_length / 2;
195 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
196 {
197 RtlStringCchLengthW(ptr, remaining, (size_t *)&string_length);
198 remaining -= string_length - 1;
199 if (string_length >= wcslen(matching_id))
200 {
201 ptr += string_length - wcslen(matching_id);
202 string_length -= (ULONG)wcslen(matching_id);
203 }
204 //KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
205 if (wcscmp(ptr, matching_id) == 0)
206 return TRUE;
207 }
208 }
209 //KdPrint((__DRIVER_NAME " No match\n"));
210 return FALSE;
211 }
213 static NTSTATUS
214 XenHide_AddDevice(
215 PDRIVER_OBJECT DriverObject,
216 PDEVICE_OBJECT PhysicalDeviceObject
217 )
218 {
219 NTSTATUS status;
220 PDEVICE_OBJECT deviceObject = NULL;
221 PXENHIDE_DEVICE_DATA xhdd;
222 ULONG length;
223 GUID bus_type;
224 WCHAR device_description[256];
225 KIRQL old_irql;
226 USHORT hide_type;
227 PXENHIDE_HIDE_LIST_ENTRY list_entry;
229 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
232 length = 512;
233 status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDeviceDescription, length, device_description, &length);
234 if (!NT_SUCCESS(status))
235 {
236 device_description[0] = 0;
237 }
239 //KdPrint((__DRIVER_NAME " Checking '%S'\n", device_description));
241 length = sizeof(GUID);
242 status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyBusTypeGuid, length, &bus_type, &length);
243 if (!NT_SUCCESS(status))
244 {
245 RtlZeroMemory(&bus_type, sizeof(GUID));
246 }
248 hide_type = XENHIDE_TYPE_NONE;
249 if (gplpv)
250 {
251 /* hide only specific devices */
252 if (XenHide_IdSuffixMatches(PhysicalDeviceObject, L"VEN_8086&DEV_7010") // Qemu IDE
253 || XenHide_IdSuffixMatches(PhysicalDeviceObject, L"VEN_10EC&DEV_8139") // Qemu Network
254 || XenHide_IdSuffixMatches(PhysicalDeviceObject, L"VEN_1000&DEV_0012"))// Qemu SCSI
255 {
256 hide_type = XENHIDE_TYPE_DEVICE;
257 }
258 else if (XenHide_IdSuffixMatches(PhysicalDeviceObject, L"PNP0A03"))
259 {
260 hide_type = XENHIDE_TYPE_PCI_BUS;
261 }
262 }
263 else
264 {
265 /* hide everything on the xen bus */
266 if (memcmp(&bus_type, &GUID_BUS_TYPE_XEN, sizeof(GUID)) == 0)
267 hide_type = XENHIDE_TYPE_DEVICE;
268 }
270 if (hide_type == XENHIDE_TYPE_NONE)
271 {
272 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
273 return STATUS_SUCCESS;
274 }
276 //KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
278 if (gplpv && hide_type == XENHIDE_TYPE_DEVICE)
279 {
280 KeAcquireSpinLock(&xenhide_global_data.hide_list_lock, &old_irql);
281 list_entry = ExAllocatePoolWithTag(PagedPool, sizeof(XENHIDE_HIDE_LIST_ENTRY), XENHIDE_POOL_TAG);
282 list_entry->pdo = PhysicalDeviceObject;
283 InsertTailList(&xenhide_global_data.hide_list_head, (PLIST_ENTRY)list_entry);
284 KeReleaseSpinLock(&xenhide_global_data.hide_list_lock, old_irql);
285 KeSetEvent(&xenhide_global_data.hide_list_event, IO_NO_INCREMENT, FALSE);
286 ASSERT(xenhide_global_data.pci_bus_pdo);
287 IoInvalidateDeviceRelations(xenhide_global_data.pci_bus_pdo, BusRelations);
288 }
289 else if (hide_type == XENHIDE_TYPE_PCI_BUS)
290 {
291 ASSERT(!xenhide_global_data.pci_bus_pdo);
292 xenhide_global_data.pci_bus_pdo = PhysicalDeviceObject;
293 }
295 status = IoCreateDevice (DriverObject,
296 sizeof(XENHIDE_DEVICE_DATA),
297 NULL,
298 FILE_DEVICE_UNKNOWN,
299 FILE_DEVICE_SECURE_OPEN,
300 FALSE,
301 &deviceObject);
303 xhdd = (PXENHIDE_DEVICE_DATA)deviceObject->DeviceExtension;
305 xhdd->hide_type = hide_type;
307 xhdd->lower_do = IoAttachDeviceToDeviceStack(
308 deviceObject, PhysicalDeviceObject);
309 deviceObject->Flags |= xhdd->lower_do->Flags;
311 deviceObject->DeviceType = xhdd->lower_do->DeviceType;
313 deviceObject->Characteristics =
314 xhdd->lower_do->Characteristics;
316 xhdd->filter_do = deviceObject;
318 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
320 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
322 return STATUS_SUCCESS;
323 }
325 static NTSTATUS
326 XenHide_Pass(PDEVICE_OBJECT DeviceObject, PIRP Irp)
327 {
328 PXENHIDE_DEVICE_DATA xhdd = (PXENHIDE_DEVICE_DATA)DeviceObject->DeviceExtension;
329 NTSTATUS status;
331 IoSkipCurrentIrpStackLocation(Irp);
332 status = IoCallDriver(xhdd->lower_do, Irp);
333 return status;
334 }
336 static NTSTATUS
337 XenHide_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
338 {
339 PKEVENT event = (PKEVENT)context;
341 UNREFERENCED_PARAMETER(device_object);
343 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
345 if (irp->PendingReturned)
346 {
347 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
348 }
350 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
352 return STATUS_MORE_PROCESSING_REQUIRED;
353 }
355 static NTSTATUS
356 XenHide_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
357 {
358 NTSTATUS status;
359 PXENHIDE_DEVICE_DATA xhdd = (PXENHIDE_DEVICE_DATA)device_object->DeviceExtension;
360 KEVENT event;
362 UNREFERENCED_PARAMETER(device_object);
364 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
366 KeInitializeEvent(&event, NotificationEvent, FALSE);
368 IoCopyCurrentIrpStackLocationToNext(irp);
369 IoSetCompletionRoutine(irp, XenHide_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
371 status = IoCallDriver(xhdd->lower_do, irp);
373 if (status == STATUS_PENDING)
374 {
375 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
376 status = irp->IoStatus.Status;
377 }
379 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
381 return status;
382 }
384 static NTSTATUS
385 XenHide_Pnp(PDEVICE_OBJECT device_object, PIRP irp)
386 {
387 NTSTATUS status = STATUS_SUCCESS;
388 PIO_STACK_LOCATION stack;
389 PXENHIDE_DEVICE_DATA xhdd = (PXENHIDE_DEVICE_DATA)device_object->DeviceExtension;
390 PDEVICE_RELATIONS relations;
391 PXENHIDE_HIDE_LIST_ENTRY list_entry;
392 ULONG i, j;
393 KIRQL old_irql;
395 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
397 stack = IoGetCurrentIrpStackLocation(irp);
399 switch (stack->MinorFunction) {
400 case IRP_MN_START_DEVICE:
401 //KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE\n"));
402 if (xhdd->hide_type == XENHIDE_TYPE_DEVICE)
403 {
404 //KdPrint((__DRIVER_NAME " hide_type == XENHIDE_TYPE_DEVICE\n"));
405 status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
406 IoCompleteRequest(irp, IO_NO_INCREMENT);
407 }
408 else
409 {
410 //KdPrint((__DRIVER_NAME " hide_type != XENHIDE_TYPE_DEVICE\n"));
411 IoSkipCurrentIrpStackLocation(irp);
412 status = IoCallDriver(xhdd->lower_do, irp);
413 }
414 break;
415 case IRP_MN_QUERY_DEVICE_RELATIONS:
416 if (xhdd->hide_type == XENHIDE_TYPE_PCI_BUS && stack->Parameters.QueryDeviceRelations.Type == BusRelations)
417 {
418 //KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS - BusRelations\n"));
419 IoMarkIrpPending(irp);
420 status = XenHide_SendAndWaitForIrp(device_object, irp);
421 relations = (PDEVICE_RELATIONS)irp->IoStatus.Information;
422 for (i = 0, j = 0; i < relations->Count; i++)
423 {
424 if (i != j)
425 relations->Objects[j] = relations->Objects[i];
426 KeAcquireSpinLock(&xenhide_global_data.hide_list_lock, &old_irql);
427 list_entry = (PXENHIDE_HIDE_LIST_ENTRY)xenhide_global_data.hide_list_head.Flink;
428 while (list_entry != (PXENHIDE_HIDE_LIST_ENTRY)&xenhide_global_data.hide_list_head)
429 {
430 if (relations->Objects[i] == list_entry->pdo)
431 {
432 //KdPrint((__DRIVER_NAME " Hiding %p\n", relations->Objects[i]));
433 break;
434 }
435 list_entry = (PXENHIDE_HIDE_LIST_ENTRY)list_entry->entry.Flink;
436 }
437 if (list_entry == (PXENHIDE_HIDE_LIST_ENTRY)&xenhide_global_data.hide_list_head)
438 j++;
439 KeReleaseSpinLock(&xenhide_global_data.hide_list_lock, old_irql);
440 }
441 relations->Count = j;
442 irp->IoStatus.Status = status;
443 IoCompleteRequest (irp, IO_NO_INCREMENT);
444 }
445 else
446 {
447 IoSkipCurrentIrpStackLocation(irp);
448 status = IoCallDriver(xhdd->lower_do, irp);
449 }
450 break;
451 default:
452 IoSkipCurrentIrpStackLocation(irp);
453 status = IoCallDriver(xhdd->lower_do, irp);
454 break;
455 }
457 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returning with status %08x)\n", status));
459 return status;
460 }