win-pvdrivers

view xenpci/xenpci.c @ 827:ef7a509365b5

Fix driver load order under W2K
author James Harper <james.harper@bendigoit.com.au>
date Tue Jan 11 21:00:39 2011 +1100 (2011-01-11)
parents 4e6f162a054c
children 95159ee58473
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_UNLOAD XenPci_EvtDriverUnload;
34 static EVT_WDF_DRIVER_DEVICE_ADD XenPci_EvtDeviceAdd;
35 static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenPci_EvtDeviceUsageNotification;
36 static EVT_WDF_DEVICE_PREPARE_HARDWARE XenHide_EvtDevicePrepareHardware;
38 static VOID
39 XenPci_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
40 {
41 FUNCTION_ENTER();
43 UNREFERENCED_PARAMETER(device);
44 UNREFERENCED_PARAMETER(is_in_notification_path);
46 switch (notification_type)
47 {
48 case WdfSpecialFilePaging:
49 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
50 break;
51 case WdfSpecialFileHibernation:
52 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
53 break;
54 case WdfSpecialFileDump:
55 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
56 break;
57 default:
58 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
59 break;
60 }
62 FUNCTION_EXIT();
63 }
65 static NTSTATUS
66 XenPci_EvtDeviceAdd_XenPci(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
67 {
68 NTSTATUS status;
69 // PDEVICE_OBJECT fdo = NULL;
70 // PNP_BUS_INFORMATION busInfo;
71 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
72 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
73 WDF_CHILD_LIST_CONFIG child_list_config;
74 WDFDEVICE device;
75 PXENPCI_DEVICE_DATA xpdd;
76 UNICODE_STRING reference;
77 WDF_OBJECT_ATTRIBUTES device_attributes;
78 PNP_BUS_INFORMATION pbi;
79 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
80 WDF_INTERRUPT_CONFIG interrupt_config;
81 WDF_OBJECT_ATTRIBUTES file_attributes;
82 WDF_FILEOBJECT_CONFIG file_config;
83 WDF_IO_QUEUE_CONFIG queue_config;
84 WDFCOLLECTION veto_devices;
85 WDFKEY param_key;
86 DECLARE_CONST_UNICODE_STRING(veto_devices_name, L"veto_devices");
87 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
88 int i;
90 UNREFERENCED_PARAMETER(driver);
92 FUNCTION_ENTER();
94 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
95 pnp_power_callbacks.EvtDeviceD0Entry = XenPci_EvtDeviceD0Entry;
96 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
97 pnp_power_callbacks.EvtDeviceD0Exit = XenPci_EvtDeviceD0Exit;
98 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
99 pnp_power_callbacks.EvtDevicePrepareHardware = XenPci_EvtDevicePrepareHardware;
100 pnp_power_callbacks.EvtDeviceReleaseHardware = XenPci_EvtDeviceReleaseHardware;
101 pnp_power_callbacks.EvtDeviceQueryRemove = XenPci_EvtDeviceQueryRemove;
102 pnp_power_callbacks.EvtDeviceUsageNotification = XenPci_EvtDeviceUsageNotification;
104 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
106 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
107 WdfDeviceInitSetExclusive(device_init, FALSE);
109 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENPCI_PDO_IDENTIFICATION_DESCRIPTION), XenPci_EvtChildListCreateDevice);
110 child_list_config.EvtChildListScanForChildren = XenPci_EvtChildListScanForChildren;
111 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
113 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&file_attributes, XENPCI_DEVICE_INTERFACE_DATA);
114 WDF_FILEOBJECT_CONFIG_INIT(&file_config, XenPci_EvtDeviceFileCreate, XenPci_EvtFileClose, XenPci_EvtFileCleanup);
115 WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attributes);
117 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
119 WdfDeviceInitSetPowerNotPageable(device_init);
121 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENPCI_DEVICE_DATA);
122 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
123 if (!NT_SUCCESS(status))
124 {
125 KdPrint(("Error creating device %08x\n", status));
126 return status;
127 }
129 xpdd = GetXpdd(device);
130 xpdd->wdf_device = device;
131 xpdd->child_list = WdfFdoGetDefaultChildList(device);
133 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &veto_devices);
134 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
135 if (NT_SUCCESS(status))
136 {
137 status = WdfRegistryQueryMultiString(param_key, &veto_devices_name, WDF_NO_OBJECT_ATTRIBUTES, veto_devices);
138 if (!NT_SUCCESS(status))
139 {
140 KdPrint(("Error reading parameters/veto_devices value %08x\n", status));
141 }
142 WdfRegistryClose(param_key);
143 }
144 else
145 {
146 KdPrint(("Error opening parameters key %08x\n", status));
147 }
149 InitializeListHead(&xpdd->veto_list);
150 for (i = 0; i < (int)WdfCollectionGetCount(veto_devices); i++)
151 {
152 WDFOBJECT ws;
153 UNICODE_STRING val;
154 ANSI_STRING s;
155 PVOID entry;
156 ws = WdfCollectionGetItem(veto_devices, i);
157 WdfStringGetUnicodeString(ws, &val);
158 RtlUnicodeStringToAnsiString(&s, &val, TRUE);
159 entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(LIST_ENTRY) + s.Length + 1, XENPCI_POOL_TAG);
160 memcpy((PUCHAR)entry + sizeof(LIST_ENTRY), s.Buffer, s.Length + 1);
161 RtlFreeAnsiString(&s);
162 InsertTailList(&xpdd->veto_list, (PLIST_ENTRY)entry);
163 }
164 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
165 power_capabilities.DeviceD1 = WdfTrue;
166 power_capabilities.WakeFromD1 = WdfTrue;
167 power_capabilities.DeviceWake = PowerDeviceD1;
168 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
169 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
170 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
171 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
172 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
173 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
174 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
176 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
177 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
178 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
180 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
181 queue_config.EvtIoDefault = XenPci_EvtIoDefault;
182 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
183 if (!NT_SUCCESS(status)) {
184 KdPrint(("Error creating queue 0x%x\n", status));
185 return status;
186 }
188 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
189 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
190 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
192 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
193 if (!NT_SUCCESS(status))
194 {
195 KdPrint(("Error creating interrupt 0x%x\n", status));
196 return status;
197 }
199 RtlInitUnicodeString(&reference, L"xenbus");
200 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
201 if (!NT_SUCCESS(status)) {
202 KdPrint(("Error registering device interface 0x%x\n", status));
203 return status;
204 }
206 RtlInitUnicodeString(&reference, L"evtchn");
207 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_EVTCHN, &reference);
208 if (!NT_SUCCESS(status)) {
209 KdPrint(("Error registering device interface 0x%x\n", status));
210 return status;
211 }
213 RtlInitUnicodeString(&reference, L"gntdev");
214 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_GNTDEV, &reference);
215 if (!NT_SUCCESS(status)) {
216 KdPrint(("Error registering device interface 0x%x\n", status));
217 return status;
218 }
220 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
221 pbi.LegacyBusType = PNPBus;
222 pbi.BusNumber = 0;
223 WdfDeviceSetBusInformationForChildren(device, &pbi);
225 xpdd->removable = TRUE;
227 FUNCTION_EXIT();
228 return status;
229 }
231 NTSTATUS
232 XenHide_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
233 {
234 UNREFERENCED_PARAMETER(device);
235 UNREFERENCED_PARAMETER(resources_raw);
236 UNREFERENCED_PARAMETER(resources_translated);
237 FUNCTION_ENTER();
238 FUNCTION_EXIT();
239 return STATUS_UNSUCCESSFUL;
240 }
242 static BOOLEAN
243 XenPci_IdSuffixMatches(PWDFDEVICE_INIT device_init, PWCHAR matching_id)
244 {
245 NTSTATUS status;
246 WDFMEMORY memory;
247 ULONG remaining;
248 size_t string_length;
249 PWCHAR ids;
250 PWCHAR ptr;
251 size_t ids_length;
252 ULONG properties[] = {DevicePropertyCompatibleIDs, DevicePropertyHardwareID};
253 int i;
255 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
256 for (i = 0; i < ARRAY_SIZE(properties); i++)
257 {
259 status = WdfFdoInitAllocAndQueryProperty(device_init, properties[i], NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
260 if (!NT_SUCCESS(status))
261 continue;
262 ids = WdfMemoryGetBuffer(memory, &ids_length);
264 if (!NT_SUCCESS(status))
265 {
266 // KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
267 continue;
268 }
270 remaining = (ULONG)ids_length / 2;
271 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
272 {
273 RtlStringCchLengthW(ptr, remaining, &string_length);
274 remaining -= (ULONG)string_length + 1;
275 if (string_length >= wcslen(matching_id))
276 {
277 ptr += string_length - wcslen(matching_id);
278 string_length = wcslen(matching_id);
279 }
280 // KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
281 if (wcscmp(ptr, matching_id) == 0)
282 {
283 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Match)\n"));
284 WdfObjectDelete(memory);
285 return TRUE;
286 }
287 }
288 WdfObjectDelete(memory);
289 }
290 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (No match)\n"));
291 return FALSE;
292 }
294 WDFCOLLECTION qemu_hide_devices;
295 USHORT qemu_hide_flags_value;
297 static NTSTATUS
298 XenPci_EvtDeviceAdd_XenHide(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
299 {
300 NTSTATUS status;
301 WDFMEMORY memory;
302 PWCHAR device_description;
303 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
304 WDF_OBJECT_ATTRIBUTES device_attributes;
305 BOOLEAN hide_required = FALSE;
306 WDFDEVICE device;
307 ULONG i;
309 UNREFERENCED_PARAMETER(driver);
311 FUNCTION_ENTER();
313 status = WdfFdoInitAllocAndQueryProperty(device_init, DevicePropertyDeviceDescription, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
314 if (NT_SUCCESS(status))
315 {
316 device_description = WdfMemoryGetBuffer(memory, NULL);
317 }
318 else
319 {
320 device_description = L"<unknown device>";
321 }
323 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++)
324 {
325 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
326 UNICODE_STRING unicode_string;
327 WdfStringGetUnicodeString(wdf_string, &unicode_string);
328 if (XenPci_IdSuffixMatches(device_init, unicode_string.Buffer))
329 {
330 hide_required = TRUE;
331 break;
332 }
333 }
334 if (!hide_required)
335 {
336 WdfObjectDelete(memory);
337 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
338 return STATUS_SUCCESS;
339 }
341 KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
343 WdfFdoInitSetFilter(device_init);
344 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
345 WdfDeviceInitSetExclusive(device_init, FALSE);
347 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
348 pnp_power_callbacks.EvtDevicePrepareHardware = XenHide_EvtDevicePrepareHardware;
349 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
351 WDF_OBJECT_ATTRIBUTES_INIT(&device_attributes);
352 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
353 if (!NT_SUCCESS(status))
354 {
355 KdPrint(("Error creating device %08x\n", status));
356 WdfObjectDelete(memory);
357 FUNCTION_EXIT();
358 return status;
359 }
361 WdfObjectDelete(memory);
362 FUNCTION_EXIT();
364 return status;
365 }
367 static NTSTATUS
368 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
369 {
370 if (XenPci_IdSuffixMatches(device_init, L"VEN_5853&DEV_0001"))
371 {
372 KdPrint((__DRIVER_NAME " Xen PCI device found - must be fdo\n"));
373 return XenPci_EvtDeviceAdd_XenPci(driver, device_init);
374 }
375 else if (WdfCollectionGetCount(qemu_hide_devices) > 0)
376 {
377 KdPrint((__DRIVER_NAME " Xen PCI device not found - must be filter\n"));
378 return XenPci_EvtDeviceAdd_XenHide(driver, device_init);
379 }
380 else
381 return STATUS_SUCCESS;
382 }
384 ULONG qemu_protocol_version;
385 ULONG tpr_patch_requested;
386 extern PULONG InitSafeBootMode;
388 VOID
389 XenPci_HideQemuDevices()
390 {
391 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, (USHORT)qemu_hide_flags_value); //QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
392 KdPrint((__DRIVER_NAME " Disabled qemu devices %02x\n", qemu_hide_flags_value));
393 }
395 static BOOLEAN
396 XenPci_CheckHideQemuDevices()
397 {
398 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
399 {
400 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
401 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
402 switch(qemu_protocol_version)
403 {
404 case 1:
405 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
406 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
407 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
408 {
409 KdPrint((__DRIVER_NAME " Blacklisted\n"));
410 break;
411 }
412 /* fall through */
413 case 0:
414 return TRUE;
415 default:
416 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
417 break;
418 }
419 }
420 return FALSE;
421 }
423 /*
424 make sure the load order is System Reserved, Dummy Group, WdfLoadGroup, XenPCI, Boot Bus Extender
425 */
427 static VOID
428 XenPci_FixLoadOrder()
429 {
430 NTSTATUS status;
431 WDFCOLLECTION old_load_order, new_load_order;
432 DECLARE_CONST_UNICODE_STRING(sgo_name, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder");
433 DECLARE_CONST_UNICODE_STRING(list_name, L"List");
434 WDFKEY sgo_key;
435 ULONG i;
436 LONG dummy_group_index = -1;
437 LONG boot_bus_extender_index = -1;
438 LONG xenpci_group_index = -1;
439 LONG wdf_load_group_index = -1;
440 DECLARE_CONST_UNICODE_STRING(dummy_group_name, L"Dummy Group");
441 DECLARE_CONST_UNICODE_STRING(wdf_load_group_name, L"WdfLoadGroup");
442 DECLARE_CONST_UNICODE_STRING(xenpci_group_name, L"XenPCI Group");
443 DECLARE_CONST_UNICODE_STRING(boot_bus_extender_name, L"Boot Bus Extender");
445 FUNCTION_ENTER();
447 status = WdfRegistryOpenKey(NULL, &sgo_name, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &sgo_key);
448 if (!NT_SUCCESS(status))
449 {
450 KdPrint((__DRIVER_NAME " Error opening ServiceGroupOrder key %08x\n", status));
451 return;
452 }
453 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &old_load_order);
454 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &new_load_order);
455 status = WdfRegistryQueryMultiString(sgo_key, &list_name, WDF_NO_OBJECT_ATTRIBUTES, old_load_order);
456 if (!NT_SUCCESS(status))
457 {
458 KdPrint((__DRIVER_NAME " Error reading ServiceGroupOrder\\List value %08x\n", status));
459 WdfObjectDelete(new_load_order);
460 WdfObjectDelete(old_load_order);
461 return;
462 }
463 //KdPrint((__DRIVER_NAME " Current Order:\n"));
464 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
465 {
466 WDFOBJECT ws = WdfCollectionGetItem(old_load_order, i);
467 UNICODE_STRING val;
468 WdfStringGetUnicodeString(ws, &val);
469 if (!RtlCompareUnicodeString(&val, &dummy_group_name, TRUE))
470 dummy_group_index = (ULONG)i;
471 if (!RtlCompareUnicodeString(&val, &wdf_load_group_name, TRUE))
472 wdf_load_group_index = (ULONG)i;
473 if (!RtlCompareUnicodeString(&val, &xenpci_group_name, TRUE))
474 xenpci_group_index = (ULONG)i;
475 if (!RtlCompareUnicodeString(&val, &boot_bus_extender_name, TRUE))
476 boot_bus_extender_index = (ULONG)i;
477 //KdPrint((__DRIVER_NAME " %wZ\n", &val));
478 }
479 KdPrint((__DRIVER_NAME " dummy_group_index = %d\n", dummy_group_index));
480 KdPrint((__DRIVER_NAME " wdf_load_group_index = %d\n", wdf_load_group_index));
481 KdPrint((__DRIVER_NAME " xenpci_group_index = %d\n", xenpci_group_index));
482 KdPrint((__DRIVER_NAME " boot_bus_extender_index = %d\n", boot_bus_extender_index));
483 if (boot_bus_extender_index == -1)
484 {
485 WdfObjectDelete(new_load_order);
486 WdfObjectDelete(old_load_order);
487 WdfRegistryClose(sgo_key);
488 return; /* something is very wrong */
489 }
490 if (dummy_group_index == 1 && wdf_load_group_index != -1 &&
491 (dummy_group_index < wdf_load_group_index
492 && wdf_load_group_index < xenpci_group_index
493 && xenpci_group_index < boot_bus_extender_index))
494 {
495 FUNCTION_EXIT();
496 return; /* our work here is done */
497 }
498 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
499 {
500 WDFOBJECT ws;
501 if (i == 1)
502 {
503 WDFSTRING tmp_wdf_string;
504 WdfStringCreate(&dummy_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
505 WdfCollectionAdd(new_load_order, tmp_wdf_string);
506 WdfObjectDelete(tmp_wdf_string);
507 }
508 if (i == 1)
509 {
510 WDFSTRING tmp_wdf_string;
511 WdfStringCreate(&wdf_load_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
512 WdfCollectionAdd(new_load_order, tmp_wdf_string);
513 WdfObjectDelete(tmp_wdf_string);
514 }
515 if (i == 1)
516 {
517 WDFSTRING tmp_wdf_string;
518 WdfStringCreate(&xenpci_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
519 WdfCollectionAdd(new_load_order, tmp_wdf_string);
520 WdfObjectDelete(tmp_wdf_string);
521 }
522 if (i == (ULONG)dummy_group_index || i == (ULONG)wdf_load_group_index || i == (ULONG)xenpci_group_index)
523 continue;
524 ws = WdfCollectionGetItem(old_load_order, i);
525 WdfCollectionAdd(new_load_order, ws);
526 }
527 WdfRegistryAssignMultiString(sgo_key, &list_name, new_load_order);
528 //KdPrint((__DRIVER_NAME " New Order:\n"));
529 for (i = 0; i < WdfCollectionGetCount(new_load_order); i++)
530 {
531 WDFOBJECT ws = WdfCollectionGetItem(new_load_order, i);
532 UNICODE_STRING val;
533 WdfStringGetUnicodeString(ws, &val);
534 //KdPrint((__DRIVER_NAME " %wZ\n", &val));
535 }
536 WdfObjectDelete(new_load_order);
537 WdfObjectDelete(old_load_order);
538 WdfRegistryClose(sgo_key);
540 FUNCTION_EXIT();
542 return;
543 }
545 VOID
546 XenPci_EvtDriverUnload(WDFDRIVER driver)
547 {
548 UNREFERENCED_PARAMETER(driver);
550 #if DBG
551 XenPci_UnHookDbgPrint();
552 #endif
553 }
555 NTSTATUS
556 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
557 {
558 NTSTATUS status = STATUS_SUCCESS;
559 WDF_DRIVER_CONFIG config;
560 WDFDRIVER driver;
561 WDF_OBJECT_ATTRIBUTES parent_attributes;
562 PCONFIGURATION_INFORMATION conf_info;
563 WDFKEY control_key;
564 WDFKEY param_key;
565 ULONG always_patch = 0;
566 ULONG always_hide = 0;
567 DECLARE_CONST_UNICODE_STRING(control_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
568 DECLARE_CONST_UNICODE_STRING(system_start_options_name, L"SystemStartOptions");
569 DECLARE_CONST_UNICODE_STRING(txt_always_hide_name, L"txt_hide_qemu_always");
570 DECLARE_CONST_UNICODE_STRING(hide_devices_name, L"hide_devices");
571 DECLARE_CONST_UNICODE_STRING(txt_always_patch_name, L"txt_patch_tpr_always");
572 WDFSTRING wdf_system_start_options;
573 UNICODE_STRING system_start_options;
575 UNREFERENCED_PARAMETER(RegistryPath);
577 FUNCTION_ENTER();
579 KdPrint((__DRIVER_NAME " " VER_FILEVERSION_STR "\n"));
581 #if DBG
582 XenPci_HookDbgPrint();
583 #endif
585 /* again after enabling DbgPrint hooking */
586 KdPrint((__DRIVER_NAME " " VER_FILEVERSION_STR "\n"));
588 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
589 config.EvtDriverUnload = XenPci_EvtDriverUnload;
590 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
591 if (!NT_SUCCESS(status))
592 {
593 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%x\n", status));
594 FUNCTION_EXIT();
595 #if DBG
596 XenPci_UnHookDbgPrint();
597 #endif
598 return status;
599 }
600 WDF_OBJECT_ATTRIBUTES_INIT(&parent_attributes);
601 parent_attributes.ParentObject = driver;
603 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, &parent_attributes, &param_key);
604 if (!NT_SUCCESS(status))
605 {
606 KdPrint(("Error opening parameters key %08x\n", status));
607 goto error;
608 }
610 status = AuxKlibInitialize();
611 if(!NT_SUCCESS(status))
612 {
613 KdPrint((__DRIVER_NAME " AuxKlibInitialize failed %08x\n", status));
614 goto error;
615 }
617 XenPci_FixLoadOrder();
619 RtlInitUnicodeString(&system_start_options, L"failed to read");
620 status = WdfRegistryOpenKey(NULL, &control_key_name, GENERIC_READ, &parent_attributes, &control_key);
621 if (NT_SUCCESS(status))
622 {
623 status = WdfStringCreate(NULL, &parent_attributes, &wdf_system_start_options);
624 status = WdfRegistryQueryString(control_key, &system_start_options_name, wdf_system_start_options);
625 if (NT_SUCCESS(status))
626 WdfStringGetUnicodeString(wdf_system_start_options, &system_start_options);
627 }
628 WdfRegistryClose(control_key);
630 KdPrint((__DRIVER_NAME " SystemStartOptions = %S\n", system_start_options));
632 always_patch = 0;
633 WdfRegistryQueryULong(param_key, &txt_always_patch_name, &always_patch);
634 if (always_patch || (system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"PATCHTPR")))
635 {
636 DECLARE_CONST_UNICODE_STRING(verifier_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
637 WDFKEY memory_key;
638 ULONG verifier_value;
640 KdPrint((__DRIVER_NAME " PATCHTPR found\n"));
642 tpr_patch_requested = TRUE;
643 status = WdfRegistryOpenKey(NULL, &verifier_key_name, KEY_READ, &parent_attributes, &memory_key);
644 if (NT_SUCCESS(status))
645 {
646 DECLARE_CONST_UNICODE_STRING(verifier_value_name, L"VerifyDriverLevel");
647 status = WdfRegistryQueryULong(memory_key, &verifier_value_name, &verifier_value);
648 if (NT_SUCCESS(status) && verifier_value != 0)
649 {
650 KdPrint((__DRIVER_NAME " Verifier active - not patching\n"));
651 tpr_patch_requested = FALSE;
652 }
653 WdfRegistryClose(memory_key);
654 }
655 }
657 WdfCollectionCreate(&parent_attributes, &qemu_hide_devices);
658 WdfRegistryQueryULong(param_key, &txt_always_hide_name, &always_hide);
659 conf_info = IoGetConfigurationInformation();
660 if (always_hide || ((conf_info == NULL || conf_info->DiskCount == 0)
661 && !(system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"NOGPLPV"))
662 && !*InitSafeBootMode))
663 {
664 if (!(system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"GPLPVUSEFILTERHIDE")) && XenPci_CheckHideQemuDevices())
665 {
666 DECLARE_CONST_UNICODE_STRING(qemu_hide_flags_name, L"qemu_hide_flags");
667 DECLARE_CONST_UNICODE_STRING(txt_qemu_hide_flags_name, L"txt_qemu_hide_flags");
668 WDFCOLLECTION qemu_hide_flags;
669 ULONG i;
671 WdfCollectionCreate(&parent_attributes, &qemu_hide_flags);
672 WdfRegistryQueryMultiString(param_key, &qemu_hide_flags_name, &parent_attributes, qemu_hide_flags);
673 WdfRegistryQueryMultiString(param_key, &txt_qemu_hide_flags_name, &parent_attributes, qemu_hide_flags);
674 for (i = 0; i < WdfCollectionGetCount(qemu_hide_flags); i++)
675 {
676 ULONG value;
677 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_flags, i);
678 UNICODE_STRING unicode_string;
679 WdfStringGetUnicodeString(wdf_string, &unicode_string);
680 status = RtlUnicodeStringToInteger(&unicode_string, 0, &value);
681 qemu_hide_flags_value |= value;
682 }
683 WdfObjectDelete(qemu_hide_flags);
684 XenPci_HideQemuDevices();
685 }
686 else
687 {
688 WdfRegistryQueryMultiString(param_key, &hide_devices_name, &parent_attributes, qemu_hide_devices);
689 }
690 }
691 WdfRegistryClose(param_key);
692 FUNCTION_EXIT();
693 return STATUS_SUCCESS;
695 error:
696 #if DBG
697 XenPci_UnHookDbgPrint();
698 #endif
699 KdPrint(("Failed, returning %08x\n", status));
700 FUNCTION_EXIT();
701 return status;
702 }