win-pvdrivers

view xenhide/xenhide.c @ 265:8fef16f8fc08

fix warnings on x64 build. Xen apparently limits PFNs to 32 bits, so make this limitation stand out a little more
author Andy Grover <andy.grover@oracle.com>
date Mon May 05 13:24:03 2008 -0700 (2008-05-05)
parents 253ec5052cb4
children 3673f1f07746
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 AutoEnumerate;
42 NTSTATUS
43 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
44 {
45 NTSTATUS status;
46 UNICODE_STRING RegKeyName;
47 UNICODE_STRING RegValueName;
48 HANDLE RegHandle;
49 OBJECT_ATTRIBUTES RegObjectAttributes;
50 char Buf[200];
51 ULONG BufLen = 200;
52 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
53 int State = 0;
54 size_t StartPos = 0;
55 WCHAR *SystemStartOptions;
56 size_t SystemStartOptionsLen;
57 size_t i;
59 UNREFERENCED_PARAMETER(RegistryPath);
61 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
62 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
64 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
65 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
66 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
67 if(!NT_SUCCESS(status))
68 {
69 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
70 }
72 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
73 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
74 if(!NT_SUCCESS(status))
75 {
76 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
77 }
78 else
79 ZwClose(RegHandle);
80 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
81 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
83 AutoEnumerate = FALSE;
85 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
87 for (i = 0; i <= SystemStartOptionsLen/2; i++)
88 {
89 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
91 switch (State)
92 {
93 case 0:
94 if (SystemStartOptions[i] == L'G')
95 {
96 StartPos = i;
97 State = 2;
98 } else if (SystemStartOptions[i] != L' ')
99 {
100 State = 1;
101 }
102 break;
103 case 1:
104 if (SystemStartOptions[i] == L' ')
105 State = 0;
106 break;
107 case 2:
108 if (SystemStartOptions[i] == L'P')
109 State = 3;
110 else
111 State = 0;
112 break;
113 case 3:
114 if (SystemStartOptions[i] == L'L')
115 State = 4;
116 else
117 State = 0;
118 break;
119 case 4:
120 if (SystemStartOptions[i] == L'P')
121 State = 5;
122 else
123 State = 0;
124 break;
125 case 5:
126 if (SystemStartOptions[i] == L'V')
127 State = 6;
128 else
129 State = 0;
130 break;
131 case 6:
132 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
133 AutoEnumerate = TRUE;
134 State = 0;
135 break;
136 }
137 }
139 KdPrint((__DRIVER_NAME " AutoEnumerate = %d\n", AutoEnumerate));
141 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
142 DriverObject->MajorFunction[i] = XenHide_Pass;
143 if (AutoEnumerate)
144 DriverObject->MajorFunction[IRP_MJ_PNP] = XenHide_Pnp;
145 DriverObject->DriverExtension->AddDevice = XenHide_AddDevice;
147 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
149 return status;
150 }
152 static NTSTATUS
153 XenHide_AddDevice(
154 PDRIVER_OBJECT DriverObject,
155 PDEVICE_OBJECT PhysicalDeviceObject
156 )
157 {
158 NTSTATUS status;
159 PDEVICE_OBJECT deviceObject = NULL;
160 PDEVICE_EXTENSION DeviceExtension;
161 ULONG Length;
162 WCHAR Buffer[256];
163 size_t StrLen;
164 int Match;
165 PWCHAR Ptr;
167 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
169 Length = sizeof(Buffer);
170 status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyHardwareID, Length, Buffer, &Length);
171 // KdPrint((__DRIVER_NAME " status = %08x, DevicePropertyHardwareID, = %ws\n", status, Buffer));
172 if (!NT_SUCCESS(status))
173 return STATUS_SUCCESS;
175 /* does end of HwID match PNP0A03? */
176 Match = 0;
177 RtlStringCchLengthW(Buffer, Length/2, &StrLen); // get strlen in wchars
178 if (StrLen >= 7)
179 {
180 Ptr = Buffer + (StrLen - 7);
181 if (wcscmp(Ptr, L"PNP0A03") == 0)
182 {
183 Match = 1;
184 }
185 }
186 if (!Match)
187 return STATUS_SUCCESS;
189 KdPrint((__DRIVER_NAME " Found\n"));
191 status = IoCreateDevice (DriverObject,
192 sizeof(DEVICE_EXTENSION),
193 NULL,
194 FILE_DEVICE_UNKNOWN,
195 FILE_DEVICE_SECURE_OPEN,
196 FALSE,
197 &deviceObject);
199 DeviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
201 DeviceExtension->NextLowerDevice = IoAttachDeviceToDeviceStack(
202 deviceObject,
203 PhysicalDeviceObject);
204 deviceObject->Flags |= DeviceExtension->NextLowerDevice->Flags;
206 deviceObject->DeviceType = DeviceExtension->NextLowerDevice->DeviceType;
208 deviceObject->Characteristics =
209 DeviceExtension->NextLowerDevice->Characteristics;
211 DeviceExtension->Self = deviceObject;
213 //INITIALIZE_PNP_STATE(DeviceExtension);
215 if (AutoEnumerate)
216 {
217 status = IoRegisterDeviceInterface(PhysicalDeviceObject, (LPGUID)&GUID_XENHIDE_IFACE, NULL, &DeviceExtension->InterfaceName);
218 if (!NT_SUCCESS(status))
219 {
220 KdPrint((__DRIVER_NAME " IoRegisterDeviceInterface failed 0x%08x\n", status));
221 return status;
222 }
223 // KdPrint((__DRIVER_NAME " IoRegisterDeviceInterface complete, SymbolicLinkName = %wZ\n", &DeviceExtension->InterfaceName));
224 status = IoSetDeviceInterfaceState(&DeviceExtension->InterfaceName, TRUE);
225 if (!NT_SUCCESS(status))
226 {
227 KdPrint((__DRIVER_NAME " IoSetDeviceInterfaceState failed 0x%08x\n", status));
228 return status;
229 }
230 }
231 else
232 {
233 // KdPrint((__DRIVER_NAME " Not registering Interface\n"));
234 }
236 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
238 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
240 return STATUS_SUCCESS;
241 }
243 static int
244 XenHide_StringMatches(PWCHAR String1, PWCHAR String2)
245 {
246 for(;*String1 != 0 && *String2 != 0 && *String1 == *String2; String1++, String2++);
247 return ((*String1 == 0 && *String2 == 0) || (*String1 == 0 && *String2 == L'\n') || (*String1 == L'\n' && *String2 == 0));
248 }
250 static NTSTATUS
251 XenHide_IoCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
252 {
253 ULONG i, j;
254 PDEVICE_RELATIONS Relations;
255 WCHAR Buffer[256];
256 PWCHAR Ptr;
257 ULONG Length;
258 size_t StrLen;
259 int Match;
260 int Offset = 0;
261 int FoundIde = 0;
262 PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)Context;
264 UNREFERENCED_PARAMETER(DeviceObject);
265 UNREFERENCED_PARAMETER(Context);
267 // KdPrint((__DRIVER_NAME " --> IoCompletion\n"));
269 Relations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
271 switch (DeviceExtension->InternalState)
272 {
273 case 0:
274 DeviceExtension->InternalState = 1;
275 for (i = 0; i < Relations->Count; i++)
276 {
277 KdPrint((__DRIVER_NAME " i = %d, DeviceType = 0x%08x\n", i, Relations->Objects[i]->DeviceType));
278 }
279 break;
280 case 1:
281 DeviceExtension->InternalState = 2;
282 if (Relations != NULL)
283 {
284 for (i = 0; i < Relations->Count; i++)
285 {
286 if (Offset != 0)
287 Relations->Objects[i - Offset] = Relations->Objects[i];
289 Match = 0;
290 for (j = 0; j < 2 && !Match; j++)
291 {
292 Length = sizeof(Buffer);
293 if (j == 0)
294 IoGetDeviceProperty(Relations->Objects[i - Offset], DevicePropertyCompatibleIDs, Length, Buffer, &Length);
295 else
296 IoGetDeviceProperty(Relations->Objects[i - Offset], DevicePropertyHardwareID, Length, Buffer, &Length);
297 StrLen = 0;
298 for (Ptr = Buffer; *Ptr != 0; Ptr += StrLen + 1)
299 {
300 // Qemu IDE
301 if (XenHide_StringMatches(Ptr, L"PCI\\VEN_8086&DEV_7010")) {
302 Match = 1;
303 FoundIde = 1;
304 break;
305 }
306 // Qemu Network
307 if (XenHide_StringMatches(Ptr, L"PCI\\VEN_10EC&DEV_8139")) {
308 Match = 1;
309 break;
310 }
311 RtlStringCchLengthW(Ptr, Length, &StrLen);
312 }
313 }
314 if (Match)
315 {
316 KdPrint((__DRIVER_NAME " Match at i = %d\n", i));
317 Offset++;
318 }
319 }
320 if (!FoundIde)
321 {
322 /*
323 We _must_ not let windows continue if the PV drivers have been
324 activated and we haven't managed to find and hide the IDE device.
325 Throwing a BSoD is the only option at this point.
326 */
327 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000002, 0x00000000, 0x00000000, 0x00000000);
328 }
329 Relations->Count -= Offset;
330 }
331 break;
332 default:
333 break;
334 }
335 // KdPrint((__DRIVER_NAME " <-- IoCompletion\n"));
337 return Irp->IoStatus.Status;
338 }
340 static NTSTATUS
341 XenHide_Pass(PDEVICE_OBJECT DeviceObject, PIRP Irp)
342 {
343 PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
344 NTSTATUS status;
346 IoSkipCurrentIrpStackLocation(Irp);
347 status = IoCallDriver(DeviceExtension->NextLowerDevice, Irp);
348 return status;
349 }
351 static NTSTATUS
352 XenHide_Pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
353 {
354 NTSTATUS Status = STATUS_SUCCESS;
355 PIO_STACK_LOCATION Stack;
356 PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
358 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
359 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
361 Stack = IoGetCurrentIrpStackLocation(Irp);
363 switch (Stack->MinorFunction) {
364 case IRP_MN_QUERY_DEVICE_RELATIONS:
365 // KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS\n"));
366 switch (Stack->Parameters.QueryDeviceRelations.Type)
367 {
368 case BusRelations:
369 // KdPrint((__DRIVER_NAME " BusRelations\n"));
370 IoCopyCurrentIrpStackLocationToNext(Irp);
371 IoSetCompletionRoutine(Irp, XenHide_IoCompletion, DeviceExtension, TRUE, TRUE, TRUE);
372 break;
373 default:
374 IoSkipCurrentIrpStackLocation(Irp);
375 break;
376 }
377 break;
378 default:
379 IoSkipCurrentIrpStackLocation(Irp);
380 break;
381 }
383 Status = IoCallDriver(DeviceExtension->NextLowerDevice, Irp);
385 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returning with status %08x)\n", Status));
387 return Status;
388 }