win-pvdrivers

view xenpci/xenpci.c @ 789:65a687a0933e

Turn off debugprint hooking if free build.
Turn off some debugging prints.
author James Harper <james.harper@bendigoit.com.au>
date Fri Mar 12 09:35:56 2010 +1100 (2010-03-12)
parents f43c89df09b2
children eddfbeb4689f
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 #define INITGUID
21 #include "xenpci.h"
22 #include <aux_klib.h>
23 #include <stdlib.h>
25 #define SYSRQ_PATH "control/sysrq"
26 #define SHUTDOWN_PATH "control/shutdown"
27 #define BALLOON_PATH "memory/target"
29 #pragma warning(disable : 4200) // zero-sized array
31 /* Not really necessary but keeps PREfast happy */
32 DRIVER_INITIALIZE DriverEntry;
33 static EVT_WDF_DRIVER_DEVICE_ADD XenPci_EvtDeviceAdd;
34 static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenPci_EvtDeviceUsageNotification;
35 static EVT_WDF_DEVICE_PREPARE_HARDWARE XenHide_EvtDevicePrepareHardware;
37 static VOID
38 XenPci_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
39 {
40 FUNCTION_ENTER();
42 UNREFERENCED_PARAMETER(device);
43 UNREFERENCED_PARAMETER(is_in_notification_path);
45 switch (notification_type)
46 {
47 case WdfSpecialFilePaging:
48 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
49 break;
50 case WdfSpecialFileHibernation:
51 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
52 break;
53 case WdfSpecialFileDump:
54 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
55 break;
56 default:
57 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
58 break;
59 }
61 FUNCTION_EXIT();
62 }
64 static NTSTATUS
65 XenPci_EvtDeviceAdd_XenPci(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
66 {
67 NTSTATUS status;
68 // PDEVICE_OBJECT fdo = NULL;
69 // PNP_BUS_INFORMATION busInfo;
70 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
71 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
72 WDF_CHILD_LIST_CONFIG child_list_config;
73 WDFDEVICE device;
74 PXENPCI_DEVICE_DATA xpdd;
75 UNICODE_STRING reference;
76 WDF_OBJECT_ATTRIBUTES device_attributes;
77 PNP_BUS_INFORMATION pbi;
78 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
79 WDF_INTERRUPT_CONFIG interrupt_config;
80 WDF_OBJECT_ATTRIBUTES file_attributes;
81 WDF_FILEOBJECT_CONFIG file_config;
82 WDF_IO_QUEUE_CONFIG queue_config;
83 WDFCOLLECTION veto_devices;
84 WDFKEY param_key;
85 DECLARE_CONST_UNICODE_STRING(veto_devices_name, L"veto_devices");
86 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
87 int i;
89 UNREFERENCED_PARAMETER(driver);
91 FUNCTION_ENTER();
93 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
94 pnp_power_callbacks.EvtDeviceD0Entry = XenPci_EvtDeviceD0Entry;
95 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
96 pnp_power_callbacks.EvtDeviceD0Exit = XenPci_EvtDeviceD0Exit;
97 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
98 pnp_power_callbacks.EvtDevicePrepareHardware = XenPci_EvtDevicePrepareHardware;
99 pnp_power_callbacks.EvtDeviceReleaseHardware = XenPci_EvtDeviceReleaseHardware;
100 pnp_power_callbacks.EvtDeviceQueryRemove = XenPci_EvtDeviceQueryRemove;
101 pnp_power_callbacks.EvtDeviceUsageNotification = XenPci_EvtDeviceUsageNotification;
103 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
105 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
106 WdfDeviceInitSetExclusive(device_init, FALSE);
108 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENPCI_PDO_IDENTIFICATION_DESCRIPTION), XenPci_EvtChildListCreateDevice);
109 child_list_config.EvtChildListScanForChildren = XenPci_EvtChildListScanForChildren;
110 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
112 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&file_attributes, XENPCI_DEVICE_INTERFACE_DATA);
113 WDF_FILEOBJECT_CONFIG_INIT(&file_config, XenPci_EvtDeviceFileCreate, XenPci_EvtFileClose, XenPci_EvtFileCleanup);
114 WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attributes);
116 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
118 WdfDeviceInitSetPowerNotPageable(device_init);
120 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENPCI_DEVICE_DATA);
121 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
122 if (!NT_SUCCESS(status))
123 {
124 KdPrint(("Error creating device %08x\n", status));
125 return status;
126 }
128 xpdd = GetXpdd(device);
129 xpdd->wdf_device = device;
130 xpdd->child_list = WdfFdoGetDefaultChildList(device);
132 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &veto_devices);
133 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
134 if (NT_SUCCESS(status))
135 {
136 status = WdfRegistryQueryMultiString(param_key, &veto_devices_name, WDF_NO_OBJECT_ATTRIBUTES, veto_devices);
137 if (!NT_SUCCESS(status))
138 {
139 KdPrint(("Error reading parameters/veto_devices value %08x\n", status));
140 }
141 WdfRegistryClose(param_key);
142 }
143 else
144 {
145 KdPrint(("Error opening parameters key %08x\n", status));
146 }
148 InitializeListHead(&xpdd->veto_list);
149 for (i = 0; i < (int)WdfCollectionGetCount(veto_devices); i++)
150 {
151 WDFOBJECT ws;
152 UNICODE_STRING val;
153 ANSI_STRING s;
154 PVOID entry;
155 ws = WdfCollectionGetItem(veto_devices, i);
156 WdfStringGetUnicodeString(ws, &val);
157 RtlUnicodeStringToAnsiString(&s, &val, TRUE);
158 entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(LIST_ENTRY) + s.Length + 1, XENPCI_POOL_TAG);
159 memcpy((PUCHAR)entry + sizeof(LIST_ENTRY), s.Buffer, s.Length + 1);
160 RtlFreeAnsiString(&s);
161 InsertTailList(&xpdd->veto_list, (PLIST_ENTRY)entry);
162 }
163 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
164 power_capabilities.DeviceD1 = WdfTrue;
165 power_capabilities.WakeFromD1 = WdfTrue;
166 power_capabilities.DeviceWake = PowerDeviceD1;
167 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
168 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
169 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
170 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
171 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
172 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
173 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
175 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
176 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
177 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
179 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
180 queue_config.EvtIoDefault = XenPci_EvtIoDefault;
181 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
182 if (!NT_SUCCESS(status)) {
183 KdPrint(("Error creating queue 0x%x\n", status));
184 return status;
185 }
187 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
188 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
189 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
191 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
192 if (!NT_SUCCESS(status))
193 {
194 KdPrint(("Error creating interrupt 0x%x\n", status));
195 return status;
196 }
198 RtlInitUnicodeString(&reference, L"xenbus");
199 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
200 if (!NT_SUCCESS(status)) {
201 KdPrint(("Error registering device interface 0x%x\n", status));
202 return status;
203 }
205 RtlInitUnicodeString(&reference, L"evtchn");
206 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_EVTCHN, &reference);
207 if (!NT_SUCCESS(status)) {
208 KdPrint(("Error registering device interface 0x%x\n", status));
209 return status;
210 }
212 RtlInitUnicodeString(&reference, L"gntdev");
213 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_GNTDEV, &reference);
214 if (!NT_SUCCESS(status)) {
215 KdPrint(("Error registering device interface 0x%x\n", status));
216 return status;
217 }
219 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
220 pbi.LegacyBusType = PNPBus;
221 pbi.BusNumber = 0;
222 WdfDeviceSetBusInformationForChildren(device, &pbi);
224 xpdd->removable = TRUE;
226 FUNCTION_EXIT();
227 return status;
228 }
230 NTSTATUS
231 XenHide_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
232 {
233 UNREFERENCED_PARAMETER(device);
234 UNREFERENCED_PARAMETER(resources_raw);
235 UNREFERENCED_PARAMETER(resources_translated);
236 FUNCTION_ENTER();
237 FUNCTION_EXIT();
238 return STATUS_UNSUCCESSFUL;
239 }
241 static BOOLEAN
242 XenPci_IdSuffixMatches(PWDFDEVICE_INIT device_init, PWCHAR matching_id)
243 {
244 NTSTATUS status;
245 WDFMEMORY memory;
246 ULONG remaining;
247 size_t string_length;
248 PWCHAR ids;
249 PWCHAR ptr;
250 size_t ids_length;
251 ULONG properties[] = {DevicePropertyCompatibleIDs, DevicePropertyHardwareID};
252 int i;
254 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
255 for (i = 0; i < ARRAY_SIZE(properties); i++)
256 {
258 status = WdfFdoInitAllocAndQueryProperty(device_init, properties[i], NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
259 if (!NT_SUCCESS(status))
260 continue;
261 ids = WdfMemoryGetBuffer(memory, &ids_length);
263 if (!NT_SUCCESS(status))
264 {
265 // KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
266 continue;
267 }
269 remaining = (ULONG)ids_length / 2;
270 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
271 {
272 RtlStringCchLengthW(ptr, remaining, &string_length);
273 remaining -= (ULONG)string_length + 1;
274 if (string_length >= wcslen(matching_id))
275 {
276 ptr += string_length - wcslen(matching_id);
277 string_length = wcslen(matching_id);
278 }
279 // KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
280 if (wcscmp(ptr, matching_id) == 0)
281 {
282 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Match)\n"));
283 WdfObjectDelete(memory);
284 return TRUE;
285 }
286 }
287 WdfObjectDelete(memory);
288 }
289 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (No match)\n"));
290 return FALSE;
291 }
293 WDFCOLLECTION qemu_hide_devices;
294 USHORT qemu_hide_flags_value;
296 static NTSTATUS
297 XenPci_EvtDeviceAdd_XenHide(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
298 {
299 NTSTATUS status;
300 WDFMEMORY memory;
301 PWCHAR device_description;
302 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
303 WDF_OBJECT_ATTRIBUTES device_attributes;
304 BOOLEAN hide_required = FALSE;
305 WDFDEVICE device;
306 ULONG i;
308 UNREFERENCED_PARAMETER(driver);
310 FUNCTION_ENTER();
312 status = WdfFdoInitAllocAndQueryProperty(device_init, DevicePropertyDeviceDescription, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
313 if (NT_SUCCESS(status))
314 {
315 device_description = WdfMemoryGetBuffer(memory, NULL);
316 }
317 else
318 {
319 device_description = L"<unknown device>";
320 }
322 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++)
323 {
324 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
325 UNICODE_STRING unicode_string;
326 WdfStringGetUnicodeString(wdf_string, &unicode_string);
327 if (XenPci_IdSuffixMatches(device_init, unicode_string.Buffer))
328 {
329 hide_required = TRUE;
330 break;
331 }
332 }
333 if (!hide_required)
334 {
335 WdfObjectDelete(memory);
336 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
337 return STATUS_SUCCESS;
338 }
340 KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
342 WdfFdoInitSetFilter(device_init);
343 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
344 WdfDeviceInitSetExclusive(device_init, FALSE);
346 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
347 pnp_power_callbacks.EvtDevicePrepareHardware = XenHide_EvtDevicePrepareHardware;
348 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
350 WDF_OBJECT_ATTRIBUTES_INIT(&device_attributes);
351 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
352 if (!NT_SUCCESS(status))
353 {
354 KdPrint(("Error creating device %08x\n", status));
355 WdfObjectDelete(memory);
356 FUNCTION_EXIT();
357 return status;
358 }
360 WdfObjectDelete(memory);
361 FUNCTION_EXIT();
363 return status;
364 }
366 static NTSTATUS
367 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
368 {
369 if (XenPci_IdSuffixMatches(device_init, L"VEN_5853&DEV_0001"))
370 {
371 KdPrint((__DRIVER_NAME " Xen PCI device found - must be fdo\n"));
372 return XenPci_EvtDeviceAdd_XenPci(driver, device_init);
373 }
374 else if (WdfCollectionGetCount(qemu_hide_devices) > 0)
375 {
376 KdPrint((__DRIVER_NAME " Xen PCI device not found - must be filter\n"));
377 return XenPci_EvtDeviceAdd_XenHide(driver, device_init);
378 }
379 else
380 return STATUS_SUCCESS;
381 }
383 ULONG qemu_protocol_version;
384 ULONG tpr_patch_requested;
385 extern PULONG InitSafeBootMode;
387 VOID
388 XenPci_HideQemuDevices()
389 {
390 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, (USHORT)qemu_hide_flags_value); //QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
391 KdPrint((__DRIVER_NAME " Disabled qemu devices\n"));\
392 }
394 static BOOLEAN
395 XenPci_CheckHideQemuDevices()
396 {
397 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
398 {
399 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
400 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
401 switch(qemu_protocol_version)
402 {
403 case 1:
404 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
405 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
406 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
407 {
408 KdPrint((__DRIVER_NAME " Blacklisted\n"));
409 break;
410 }
411 /* fall through */
412 case 0:
413 return TRUE;
414 default:
415 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
416 break;
417 }
418 }
419 return FALSE;
420 }
422 /*
423 make sure the load order is System Reserved, Dummy Group, WdfLoadGroup, XenPCI, Boot Bus Extender
424 */
426 static VOID
427 XenPci_FixLoadOrder()
428 {
429 NTSTATUS status;
430 WDFCOLLECTION old_load_order, new_load_order;
431 DECLARE_CONST_UNICODE_STRING(sgo_name, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder");
432 DECLARE_CONST_UNICODE_STRING(list_name, L"List");
433 WDFKEY sgo_key;
434 ULONG i;
435 LONG dummy_group_index = -1;
436 LONG boot_bus_extender_index = -1;
437 LONG xenpci_group_index = -1;
438 LONG wdf_load_group_index = -1;
439 DECLARE_CONST_UNICODE_STRING(dummy_group_name, L"Dummy Group");
440 DECLARE_CONST_UNICODE_STRING(wdf_load_group_name, L"WdfLoadGroup");
441 DECLARE_CONST_UNICODE_STRING(xenpci_group_name, L"XenPCI Group");
442 DECLARE_CONST_UNICODE_STRING(boot_bus_extender_name, L"Boot Bus Extender");
444 FUNCTION_ENTER();
446 status = WdfRegistryOpenKey(NULL, &sgo_name, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &sgo_key);
447 if (!NT_SUCCESS(status))
448 {
449 KdPrint((__DRIVER_NAME " Error opening ServiceGroupOrder key %08x\n", status));
450 return;
451 }
452 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &old_load_order);
453 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &new_load_order);
454 status = WdfRegistryQueryMultiString(sgo_key, &list_name, WDF_NO_OBJECT_ATTRIBUTES, old_load_order);
455 if (!NT_SUCCESS(status))
456 {
457 KdPrint((__DRIVER_NAME " Error reading ServiceGroupOrder\\List value %08x\n", status));
458 WdfObjectDelete(new_load_order);
459 WdfObjectDelete(old_load_order);
460 return;
461 }
462 //KdPrint((__DRIVER_NAME " Current Order:\n"));
463 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
464 {
465 WDFOBJECT ws = WdfCollectionGetItem(old_load_order, i);
466 UNICODE_STRING val;
467 WdfStringGetUnicodeString(ws, &val);
468 if (!RtlCompareUnicodeString(&val, &dummy_group_name, TRUE))
469 dummy_group_index = (ULONG)i;
470 if (!RtlCompareUnicodeString(&val, &wdf_load_group_name, TRUE))
471 wdf_load_group_index = (ULONG)i;
472 if (!RtlCompareUnicodeString(&val, &xenpci_group_name, TRUE))
473 xenpci_group_index = (ULONG)i;
474 if (!RtlCompareUnicodeString(&val, &boot_bus_extender_name, TRUE))
475 boot_bus_extender_index = (ULONG)i;
476 //KdPrint((__DRIVER_NAME " %wZ\n", &val));
477 }
478 KdPrint((__DRIVER_NAME " dummy_group_index = %d\n", dummy_group_index));
479 KdPrint((__DRIVER_NAME " wdf_load_group_index = %d\n", wdf_load_group_index));
480 KdPrint((__DRIVER_NAME " xenpci_group_index = %d\n", xenpci_group_index));
481 KdPrint((__DRIVER_NAME " boot_bus_extender_index = %d\n", boot_bus_extender_index));
482 if (boot_bus_extender_index == -1)
483 {
484 WdfObjectDelete(new_load_order);
485 WdfObjectDelete(old_load_order);
486 WdfRegistryClose(sgo_key);
487 return; /* something is very wrong */
488 }
489 if (dummy_group_index == 1 && (wdf_load_group_index == -1 ||
490 (dummy_group_index < wdf_load_group_index
491 && wdf_load_group_index < xenpci_group_index
492 && xenpci_group_index < boot_bus_extender_index)))
493 {
494 return; /* our work here is done */
495 }
496 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
497 {
498 WDFOBJECT ws;
499 if (i == 1)
500 {
501 WDFSTRING tmp_wdf_string;
502 WdfStringCreate(&dummy_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
503 WdfCollectionAdd(new_load_order, tmp_wdf_string);
504 WdfObjectDelete(tmp_wdf_string);
505 }
506 if (i == 1 && wdf_load_group_index != -1)
507 {
508 WDFSTRING tmp_wdf_string;
509 WdfStringCreate(&wdf_load_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
510 WdfCollectionAdd(new_load_order, tmp_wdf_string);
511 WdfObjectDelete(tmp_wdf_string);
512 }
513 if (i == 1)
514 {
515 WDFSTRING tmp_wdf_string;
516 WdfStringCreate(&xenpci_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
517 WdfCollectionAdd(new_load_order, tmp_wdf_string);
518 WdfObjectDelete(tmp_wdf_string);
519 }
520 if (i == (ULONG)dummy_group_index || i == (ULONG)wdf_load_group_index || i == (ULONG)xenpci_group_index)
521 continue;
522 ws = WdfCollectionGetItem(old_load_order, i);
523 WdfCollectionAdd(new_load_order, ws);
524 }
525 WdfRegistryAssignMultiString(sgo_key, &list_name, new_load_order);
526 //KdPrint((__DRIVER_NAME " New Order:\n"));
527 for (i = 0; i < WdfCollectionGetCount(new_load_order); i++)
528 {
529 WDFOBJECT ws = WdfCollectionGetItem(new_load_order, i);
530 UNICODE_STRING val;
531 WdfStringGetUnicodeString(ws, &val);
532 //KdPrint((__DRIVER_NAME " %wZ\n", &val));
533 }
534 WdfObjectDelete(new_load_order);
535 WdfObjectDelete(old_load_order);
536 WdfRegistryClose(sgo_key);
538 FUNCTION_EXIT();
540 return;
541 }
543 NTSTATUS
544 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
545 {
546 NTSTATUS status = STATUS_SUCCESS;
547 WDF_DRIVER_CONFIG config;
548 WDFDRIVER driver;
549 PCONFIGURATION_INFORMATION conf_info;
550 WCHAR *SystemStartOptions;
551 UNICODE_STRING RegKeyName;
552 UNICODE_STRING RegValueName;
553 HANDLE RegHandle;
554 OBJECT_ATTRIBUTES RegObjectAttributes;
555 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
556 ULONG BufLen = 300;
557 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
559 UNREFERENCED_PARAMETER(RegistryPath);
561 KdPrint((__DRIVER_NAME " " VER_FILEVERSION_STR "\n"));
563 FUNCTION_ENTER();
565 status = AuxKlibInitialize();
566 if(!NT_SUCCESS(status))
567 {
568 KdPrint((__DRIVER_NAME " AuxKlibInitialize failed %08x - expect a crash soon\n", status));
569 }
571 #if DBG
572 XenPci_HookDbgPrint();
573 #endif
575 XenPci_FixLoadOrder();
577 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
578 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
579 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
580 if(!NT_SUCCESS(status))
581 {
582 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
583 }
585 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
586 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
587 if(!NT_SUCCESS(status))
588 {
589 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
590 }
591 else
592 ZwClose(RegHandle);
593 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
594 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
596 KdPrint((__DRIVER_NAME " SystemStartOptions = %S\n", SystemStartOptions));
598 if (wcsstr(SystemStartOptions, L"PATCHTPR"))
599 {
600 WDFKEY memory_key;
601 UNICODE_STRING verifier_key_name;
602 UNICODE_STRING verifier_value_name;
603 ULONG verifier_value;
605 KdPrint((__DRIVER_NAME " PATCHTPR found\n"));
607 RtlInitUnicodeString(&verifier_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
608 status = WdfRegistryOpenKey(NULL, &verifier_key_name, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &memory_key);
609 if (!NT_SUCCESS(status))
610 {
611 tpr_patch_requested = TRUE;
612 }
613 else
614 {
615 RtlInitUnicodeString(&verifier_value_name, L"VerifyDriverLevel");
616 status = WdfRegistryQueryULong(memory_key, &verifier_value_name, &verifier_value);
617 if (NT_SUCCESS(status) && verifier_value != 0)
618 {
619 KdPrint((__DRIVER_NAME " Verifier active - not patching\n"));
620 }
621 else
622 {
623 tpr_patch_requested = TRUE;
624 }
625 WdfRegistryClose(memory_key);
626 }
627 }
629 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
630 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
632 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &qemu_hide_devices);
634 if (!NT_SUCCESS(status)) {
635 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%x\n", status));
636 FUNCTION_EXIT();
637 return status;
638 }
640 qemu_hide_flags_value = 0;
642 if (wcsstr(SystemStartOptions, L"NOGPLPV"))
643 KdPrint((__DRIVER_NAME " NOGPLPV found\n"));
644 conf_info = IoGetConfigurationInformation();
645 if ((conf_info == NULL || conf_info->DiskCount == 0)
646 && !wcsstr(SystemStartOptions, L"NOGPLPV")
647 && !*InitSafeBootMode)
648 {
649 if (wcsstr(SystemStartOptions, L"GPLPVUSEFILTERHIDE") == 0 && XenPci_CheckHideQemuDevices())
650 {
651 DECLARE_CONST_UNICODE_STRING(qemu_hide_flags_name, L"qemu_hide_flags");
652 WDFCOLLECTION qemu_hide_flags;
653 WDFKEY param_key;
654 ULONG i;
656 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &qemu_hide_flags);
657 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
658 if (NT_SUCCESS(status))
659 {
660 status = WdfRegistryQueryMultiString(param_key, &qemu_hide_flags_name, WDF_NO_OBJECT_ATTRIBUTES, qemu_hide_flags);
661 if (!NT_SUCCESS(status))
662 {
663 KdPrint(("Error reading parameters/qemu_hide_flags value %08x\n", status));
664 }
665 else
666 {
667 for (i = 0; i < WdfCollectionGetCount(qemu_hide_flags); i++)
668 {
669 ULONG value;
670 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_flags, i);
671 UNICODE_STRING unicode_string;
672 WdfStringGetUnicodeString(wdf_string, &unicode_string);
673 KdPrint(("\n", status));
674 status = RtlUnicodeStringToInteger(&unicode_string, 0, &value);
675 qemu_hide_flags_value |= value;
676 }
677 }
678 WdfRegistryClose(param_key);
679 }
680 else
681 {
682 KdPrint(("Error opening parameters key %08x\n", status));
683 }
684 XenPci_HideQemuDevices();
685 }
686 else
687 {
688 DECLARE_CONST_UNICODE_STRING(hide_devices_name, L"hide_devices");
689 WDFKEY param_key;
690 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
691 if (NT_SUCCESS(status))
692 {
693 status = WdfRegistryQueryMultiString(param_key, &hide_devices_name, WDF_NO_OBJECT_ATTRIBUTES, qemu_hide_devices);
694 if (!NT_SUCCESS(status))
695 {
696 KdPrint(("Error reading parameters/hide_devices value %08x\n", status));
697 }
698 WdfRegistryClose(param_key);
699 }
700 else
701 {
702 KdPrint(("Error opening parameters key %08x\n", status));
703 }
704 }
705 }
707 FUNCTION_EXIT();
709 return STATUS_SUCCESS;
710 }