1 ///////////////////////////////////////////////////////////////////////////////
\r
2 // Driver for Madotsukai no Yu^utsu for Windows2000
\r
7 #include <devioctl.h>
\r
9 #pragma warning(3 : 4061 4100 4132 4701 4706)
\r
14 //#define USE_TOUCHPAD // very experimental!
\r
17 // Enable debug logging only on checked build:
\r
18 // We use macro to avoid function call overhead
\r
19 // in non-logging case, and use double paren such
\r
20 // as DEBUG_LOG((...)) because of va_list in macro.
\r
22 #define DEBUG_LOG_INIT(x) mayuLogInit x
\r
23 #define DEBUG_LOG_TERM(x) mayuLogTerm x
\r
24 #define DEBUG_LOG(x) mayuLogEnque x
\r
25 #define DEBUG_LOG_RETRIEVE(x) mayuLogDeque x
\r
27 #define DEBUG_LOG_INIT(x)
\r
28 #define DEBUG_LOG_TERM(x)
\r
29 #define DEBUG_LOG(x)
\r
30 #define DEBUG_LOG_RETRIEVE(x) STATUS_INVALID_DEVICE_REQUEST
\r
33 ///////////////////////////////////////////////////////////////////////////////
\r
34 // Device Extensions
\r
36 struct _DetourDeviceExtension;
\r
37 struct _FilterDeviceExtension;
\r
39 typedef struct _DetourDeviceExtension {
\r
40 PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
\r
42 KSPIN_LOCK lock; // lock below datum
\r
43 PDEVICE_OBJECT filterDevObj;
\r
45 BOOLEAN wasCleanupInitiated; //
\r
47 KeyQue readQue; // when IRP_MJ_READ, the contents of readQue are returned
\r
48 } DetourDeviceExtension;
\r
50 typedef struct _FilterDeviceExtension {
\r
51 PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
\r
53 PDEVICE_OBJECT detourDevObj;
\r
54 PDEVICE_OBJECT kbdClassDevObj; // keyboard class device object
\r
59 KSPIN_LOCK lock; // lock below datum
\r
61 KeyQue readQue; // when IRP_MJ_READ, the contents of readQue are returned
\r
65 } FilterDeviceExtension;
\r
67 ///////////////////////////////////////////////////////////////////////////////
\r
68 // Protorypes (TODO)
\r
71 NTSTATUS DriverEntry (IN PDRIVER_OBJECT, IN PUNICODE_STRING);
\r
72 NTSTATUS mayuAddDevice (IN PDRIVER_OBJECT, IN PDEVICE_OBJECT);
\r
73 VOID mayuUnloadDriver (IN PDRIVER_OBJECT);
\r
74 VOID mayuDetourReadCancel (IN PDEVICE_OBJECT, IN PIRP);
\r
76 NTSTATUS filterGenericCompletion (IN PDEVICE_OBJECT, IN PIRP, IN PVOID);
\r
77 NTSTATUS filterReadCompletion (IN PDEVICE_OBJECT, IN PIRP, IN PVOID);
\r
79 NTSTATUS mayuGenericDispatch (IN PDEVICE_OBJECT, IN PIRP);
\r
80 NTSTATUS detourCreate (IN PDEVICE_OBJECT, IN PIRP);
\r
81 NTSTATUS detourClose (IN PDEVICE_OBJECT, IN PIRP);
\r
82 NTSTATUS detourRead (IN PDEVICE_OBJECT, IN PIRP);
\r
83 NTSTATUS detourWrite (IN PDEVICE_OBJECT, IN PIRP);
\r
84 NTSTATUS detourCleanup (IN PDEVICE_OBJECT, IN PIRP);
\r
85 NTSTATUS detourDeviceControl (IN PDEVICE_OBJECT, IN PIRP);
\r
86 NTSTATUS filterRead (IN PDEVICE_OBJECT, IN PIRP);
\r
87 NTSTATUS filterPassThrough (IN PDEVICE_OBJECT, IN PIRP);
\r
88 NTSTATUS detourPnP (IN PDEVICE_OBJECT, IN PIRP);
\r
89 NTSTATUS filterPnP (IN PDEVICE_OBJECT, IN PIRP);
\r
91 NTSTATUS detourPower (IN PDEVICE_OBJECT, IN PIRP);
\r
92 NTSTATUS filterPower (IN PDEVICE_OBJECT, IN PIRP);
\r
93 #endif // !MAYUD_NT4
\r
95 BOOLEAN CancelKeyboardClassRead(IN PIRP, IN PDEVICE_OBJECT);
\r
96 NTSTATUS readq(KeyQue*, PIRP);
\r
99 NTSTATUS filterTouchpadCompletion (IN PDEVICE_OBJECT, IN PIRP, IN PVOID);
\r
100 NTSTATUS filterTouchpad (IN PDEVICE_OBJECT, IN PIRP);
\r
103 #ifdef ALLOC_PRAGMA
\r
104 #pragma alloc_text( init, DriverEntry )
\r
105 #endif // ALLOC_PRAGMA
\r
108 ///////////////////////////////////////////////////////////////////////////////
\r
109 // Global Constants / Variables
\r
113 ULONG g_SpinLock_offset;
\r
114 ULONG g_RequestIsPending_offset;
\r
117 #define UnicodeString(str) { sizeof(str) - sizeof(UNICODE_NULL), \
\r
118 sizeof(str) - sizeof(UNICODE_NULL), str }
\r
120 static UNICODE_STRING MayuDetourDeviceName =
\r
121 UnicodeString(L"\\Device\\MayuDetour0");
\r
123 static UNICODE_STRING MayuDetourWin32DeviceName =
\r
124 UnicodeString(L"\\DosDevices\\MayuDetour1");
\r
126 static UNICODE_STRING KeyboardClassDeviceName =
\r
127 UnicodeString(DD_KEYBOARD_DEVICE_NAME_U L"0");
\r
129 static UNICODE_STRING KeyboardClassDriverName =
\r
130 UnicodeString(L"\\Driver\\kbdclass");
\r
132 #ifdef USE_TOUCHPAD
\r
133 #define TOUCHPAD_PRESSURE_OFFSET 7
\r
136 // Global Variables
\r
137 PDRIVER_DISPATCH _IopInvalidDeviceRequest; // Default dispatch function
\r
140 #define MAYUD_MODE L""
\r
141 static UNICODE_STRING MayuDriverVersion =
\r
142 UnicodeString(L"$Revision: 1.27 $" MAYUD_MODE);
\r
145 ///////////////////////////////////////////////////////////////////////////////
\r
148 void DEBUG_LOGChain(PDRIVER_OBJECT driverObject)
\r
150 PDEVICE_OBJECT deviceObject = driverObject->DeviceObject;
\r
152 if (deviceObject) {
\r
153 while (deviceObject->NextDevice) {
\r
154 DEBUG_LOG(("%x->", deviceObject));
\r
155 deviceObject = deviceObject->NextDevice;
\r
157 DEBUG_LOG(("%x", deviceObject));
\r
162 // initialize driver
\r
163 NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject,
\r
164 IN PUNICODE_STRING registryPath)
\r
167 BOOLEAN is_symbolicLinkCreated = FALSE;
\r
169 PDEVICE_OBJECT detourDevObj = NULL;
\r
170 DetourDeviceExtension *detourDevExt = NULL;
\r
172 RTL_QUERY_REGISTRY_TABLE query[2];
\r
174 UNREFERENCED_PARAMETER(registryPath);
\r
176 DEBUG_LOG_INIT(("mayud: start logging"));
\r
178 // Environment specific initialize
\r
179 RtlZeroMemory(query, sizeof(query));
\r
180 query[0].Name = L"Start";
\r
181 query[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
182 query[0].EntryContext = &start;
\r
183 RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, L"mayud", query, NULL, NULL);
\r
184 if (start == 0x03) {
\r
186 DEBUG_LOG(("is PnP"));
\r
189 DEBUG_LOG(("is not PnP"));
\r
193 g_SpinLock_offset = 48;
\r
194 g_RequestIsPending_offset = 0;
\r
195 #else /* !MAYUD_NT4 */
\r
196 if (IoIsWdmVersionAvailable(1, 0x20)) { // is WindowsXP
\r
197 DEBUG_LOG(("is WindowsXp"));
\r
199 g_SpinLock_offset = 108;
\r
200 g_RequestIsPending_offset = 0;
\r
201 } else if (IoIsWdmVersionAvailable(1, 0x10)) { // is Windows2000
\r
202 DEBUG_LOG(("is Windows2000"));
\r
204 g_SpinLock_offset = 116;
\r
205 g_RequestIsPending_offset = 48;
\r
206 } else { // Unknown version
\r
207 DEBUG_LOG(("unknown Windows"));
\r
208 status = STATUS_UNKNOWN_REVISION;
\r
211 #endif /* MAYUD_NT4 */
\r
213 // initialize global variables
\r
214 _IopInvalidDeviceRequest = driverObject->MajorFunction[IRP_MJ_CREATE];
\r
216 // set major functions
\r
217 driverObject->DriverUnload = mayuUnloadDriver;
\r
218 if (g_isPnP == TRUE) {
\r
219 driverObject->DriverExtension->AddDevice = mayuAddDevice;
\r
221 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
\r
223 if (i != IRP_MJ_POWER)
\r
224 #endif // MAYUD_NT4
\r
225 driverObject->MajorFunction[i] = mayuGenericDispatch;
\r
226 if (g_isPnP == TRUE) {
\r
227 driverObject->MajorFunction[IRP_MJ_PNP] = mayuGenericDispatch;
\r
232 // create detour device
\r
233 status = IoCreateDevice(driverObject, sizeof(DetourDeviceExtension),
\r
234 &MayuDetourDeviceName, FILE_DEVICE_KEYBOARD,
\r
235 0, FALSE, &detourDevObj);
\r
237 if (!NT_SUCCESS(status)) goto error;
\r
238 DEBUG_LOG(("create detour device: %x", detourDevObj));
\r
239 DEBUG_LOGChain(driverObject);
\r
240 detourDevObj->Flags |= DO_BUFFERED_IO;
\r
242 detourDevObj->Flags |= DO_POWER_PAGABLE;
\r
243 #endif // !MAYUD_NT4
\r
245 // initialize detour device extension
\r
246 detourDevExt = (DetourDeviceExtension*)detourDevObj->DeviceExtension;
\r
247 RtlZeroMemory(detourDevExt, sizeof(DetourDeviceExtension));
\r
248 detourDevExt->filterDevObj = NULL;
\r
250 KeInitializeSpinLock(&detourDevExt->lock);
\r
251 detourDevExt->isOpen = FALSE;
\r
252 detourDevExt->wasCleanupInitiated = FALSE;
\r
253 detourDevExt->irpq = NULL;
\r
254 status = KqInitialize(&detourDevExt->readQue);
\r
255 if (!NT_SUCCESS(status)) goto error;
\r
257 // create symbolic link for detour
\r
259 IoCreateSymbolicLink(&MayuDetourWin32DeviceName, &MayuDetourDeviceName);
\r
260 if (!NT_SUCCESS(status)) goto error;
\r
261 is_symbolicLinkCreated = TRUE;
\r
263 if (g_isPnP == FALSE)
\r
264 // attach filter device to keyboard class device
\r
267 PDEVICE_OBJECT kbdClassDevObj;
\r
269 status = IoGetDeviceObjectPointer(&KeyboardClassDeviceName,
\r
270 FILE_ALL_ACCESS, &f,
\r
272 if (!NT_SUCCESS(status)) goto error;
\r
273 ObDereferenceObject(f);
\r
274 status = mayuAddDevice(driverObject, kbdClassDevObj);
\r
276 // why cannot I do below ?
\r
277 // status = IoAttachDevice(filterDevObj, &KeyboardClassDeviceName,
\r
278 // &filterDevExt->kbdClassDevObj);
\r
279 if (!NT_SUCCESS(status)) goto error;
\r
282 // initialize Major Functions
\r
283 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
\r
284 detourDevExt->MajorFunction[i] = _IopInvalidDeviceRequest;
\r
287 detourDevExt->MajorFunction[IRP_MJ_READ] = detourRead;
\r
288 detourDevExt->MajorFunction[IRP_MJ_WRITE] = detourWrite;
\r
289 detourDevExt->MajorFunction[IRP_MJ_CREATE] = detourCreate;
\r
290 detourDevExt->MajorFunction[IRP_MJ_CLOSE] = detourClose;
\r
291 detourDevExt->MajorFunction[IRP_MJ_CLEANUP] = detourCleanup;
\r
292 detourDevExt->MajorFunction[IRP_MJ_DEVICE_CONTROL] = detourDeviceControl;
\r
295 detourDevExt->MajorFunction[IRP_MJ_POWER] = detourPower;
\r
296 #endif // !MAYUD_NT4
\r
297 if (g_isPnP == TRUE) {
\r
298 detourDevExt->MajorFunction[IRP_MJ_PNP] = detourPnP;
\r
301 detourDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
\r
303 return STATUS_SUCCESS;
\r
306 if (is_symbolicLinkCreated)
\r
307 IoDeleteSymbolicLink(&MayuDetourWin32DeviceName);
\r
308 if (detourDevObj) {
\r
309 KqFinalize(&detourDevExt->readQue);
\r
310 IoDeleteDevice(detourDevObj);
\r
316 NTSTATUS mayuAddDevice(IN PDRIVER_OBJECT driverObject,
\r
317 IN PDEVICE_OBJECT kbdClassDevObj)
\r
320 PDEVICE_OBJECT devObj;
\r
321 PDEVICE_OBJECT filterDevObj;
\r
322 PDEVICE_OBJECT attachedDevObj;
\r
323 DetourDeviceExtension *detourDevExt;
\r
324 FilterDeviceExtension *filterDevExt;
\r
327 DEBUG_LOG(("attach to device: %x", kbdClassDevObj));
\r
328 DEBUG_LOG(("type of device: %x", kbdClassDevObj->DeviceType));
\r
329 DEBUG_LOG(("name of driver: %T", &(kbdClassDevObj->DriverObject->DriverName)));
\r
331 // create filter device
\r
332 status = IoCreateDevice(driverObject, sizeof(FilterDeviceExtension),
\r
333 NULL, FILE_DEVICE_KEYBOARD,
\r
334 0, FALSE, &filterDevObj);
\r
335 DEBUG_LOG(("add filter device: %x", filterDevObj));
\r
336 DEBUG_LOGChain(driverObject);
\r
337 if (!NT_SUCCESS(status)) return status;
\r
338 filterDevObj->Flags |= DO_BUFFERED_IO;
\r
340 filterDevObj->Flags |= DO_POWER_PAGABLE;
\r
341 #endif // !MAYUD_NT4
\r
343 // initialize filter device extension
\r
344 filterDevExt = (FilterDeviceExtension*)filterDevObj->DeviceExtension;
\r
345 RtlZeroMemory(filterDevExt, sizeof(FilterDeviceExtension));
\r
347 KeInitializeSpinLock(&filterDevExt->lock);
\r
348 filterDevExt->irpq = NULL;
\r
349 status = KqInitialize(&filterDevExt->readQue);
\r
350 if (!NT_SUCCESS(status)) goto error;
\r
351 #ifdef USE_TOUCHPAD
\r
352 filterDevExt->isKeyboard = FALSE;
\r
353 filterDevExt->isTouched = FALSE;
\r
356 attachedDevObj = kbdClassDevObj->AttachedDevice;
\r
357 while (attachedDevObj) {
\r
358 DEBUG_LOG(("attached to %T", &(attachedDevObj->DriverObject->DriverName)));
\r
359 DEBUG_LOG(("type of attched device: %x", attachedDevObj->DeviceType));
\r
360 #ifdef USE_TOUCHPAD
\r
361 if (RtlCompareUnicodeString(&KeyboardClassDriverName, &attachedDevObj->DriverObject->DriverName, TRUE) == 0)
\r
362 filterDevExt->isKeyboard = TRUE;
\r
364 attachedDevObj = attachedDevObj->AttachedDevice;
\r
367 devObj = filterDevObj->NextDevice;
\r
368 while (devObj->NextDevice) {
\r
369 devObj = devObj->NextDevice;
\r
371 filterDevExt->detourDevObj = devObj;
\r
372 detourDevExt = (DetourDeviceExtension*)devObj->DeviceExtension;
\r
373 if (!detourDevExt->filterDevObj) {
\r
374 detourDevExt->filterDevObj = filterDevObj;
\r
377 filterDevExt->kbdClassDevObj =
\r
378 IoAttachDeviceToDeviceStack(filterDevObj, kbdClassDevObj);
\r
379 if (!filterDevExt->kbdClassDevObj) goto error;
\r
381 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
\r
382 filterDevExt->MajorFunction[i] =
\r
383 (filterDevExt->kbdClassDevObj->DriverObject->MajorFunction[i]
\r
384 == _IopInvalidDeviceRequest) ?
\r
385 _IopInvalidDeviceRequest : filterPassThrough;
\r
387 #ifdef USE_TOUCHPAD
\r
388 if (filterDevExt->isKeyboard == FALSE) {
\r
389 DEBUG_LOG(("filter read: GlidePoint"));
\r
390 filterDevObj->DeviceType = FILE_DEVICE_MOUSE;
\r
391 filterDevExt->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = filterTouchpad;
\r
395 DEBUG_LOG(("filter read: Keyboard"));
\r
396 filterDevExt->MajorFunction[IRP_MJ_READ] = filterRead;
\r
399 filterDevExt->MajorFunction[IRP_MJ_POWER] = filterPower;
\r
400 #endif // !MAYUD_NT4
\r
401 if (g_isPnP == TRUE) {
\r
402 filterDevExt->MajorFunction[IRP_MJ_PNP] = filterPnP;
\r
404 filterDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
\r
406 return STATUS_SUCCESS;
\r
409 DEBUG_LOG(("mayuAddDevice: error"));
\r
410 if (filterDevObj) {
\r
411 KqFinalize(&filterDevExt->readQue);
\r
412 IoDeleteDevice(filterDevObj);
\r
417 BOOLEAN CancelKeyboardClassRead(PIRP cancelIrp, PDEVICE_OBJECT kbdClassDevObj)
\r
419 PVOID kbdClassDevExt;
\r
421 PKSPIN_LOCK SpinLock;
\r
424 kbdClassDevExt = kbdClassDevObj->DeviceExtension;
\r
425 SpinLock = (PKSPIN_LOCK)((ULONG)kbdClassDevExt + g_SpinLock_offset);
\r
426 KeAcquireSpinLock(SpinLock, ¤tIrql);
\r
427 if (g_isXp == TRUE) {
\r
428 isSafe = cancelIrp->CancelRoutine ? TRUE : FALSE;
\r
430 isSafe = *(BOOLEAN*)((ULONG)kbdClassDevExt + g_RequestIsPending_offset);
\r
432 if (isSafe == TRUE) {
\r
433 KeReleaseSpinLock(SpinLock, currentIrql);
\r
434 IoCancelIrp(cancelIrp);
\r
436 DEBUG_LOG(("cancel irp not pending"));
\r
437 KeReleaseSpinLock(SpinLock, currentIrql);
\r
443 VOID mayuUnloadDriver(IN PDRIVER_OBJECT driverObject)
\r
447 PDEVICE_OBJECT devObj;
\r
448 DetourDeviceExtension *detourDevExt;
\r
450 // walk on device chain(the last one is detour device?)
\r
451 devObj = driverObject->DeviceObject;
\r
452 while (devObj->NextDevice) {
\r
453 FilterDeviceExtension *filterDevExt
\r
454 = (FilterDeviceExtension*)devObj->DeviceExtension;
\r
455 PDEVICE_OBJECT delObj;
\r
456 PDEVICE_OBJECT kbdClassDevObj;
\r
459 IoDetachDevice(filterDevExt->kbdClassDevObj);
\r
460 // cancel filter IRP_MJ_READ
\r
461 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
462 // TODO: at this point, the irp may be completed (but what can I do for it ?)
\r
463 // finalize read que
\r
464 KqFinalize(&filterDevExt->readQue);
\r
465 cancelIrp = filterDevExt->irpq;
\r
466 filterDevExt->irpq = NULL;
\r
467 kbdClassDevObj = filterDevExt->kbdClassDevObj;
\r
468 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
470 while (CancelKeyboardClassRead(cancelIrp, kbdClassDevObj) != TRUE);
\r
472 // delete device objects
\r
474 devObj = devObj->NextDevice;
\r
475 IoDeleteDevice(delObj);
\r
478 detourDevExt = (DetourDeviceExtension*)devObj->DeviceExtension;
\r
479 // cancel filter IRP_MJ_READ
\r
480 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
481 // TODO: at this point, the irp may be completed (but what can I do for it ?)
\r
482 cancelIrp = detourDevExt->irpq;
\r
483 // finalize read que
\r
484 KqFinalize(&detourDevExt->readQue);
\r
485 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
487 IoCancelIrp(cancelIrp);
\r
488 // delete device objects
\r
489 IoDeleteDevice(devObj);
\r
491 // delete symbolic link
\r
492 IoDeleteSymbolicLink(&MayuDetourWin32DeviceName);
\r
493 DEBUG_LOG_TERM(());
\r
497 ///////////////////////////////////////////////////////////////////////////////
\r
498 // Cancel Functionss
\r
501 // detour read cancel
\r
502 VOID mayuDetourReadCancel(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
504 DetourDeviceExtension *devExt =
\r
505 (DetourDeviceExtension *)deviceObject->DeviceExtension;
\r
508 KeAcquireSpinLock(&devExt->lock, ¤tIrql);
\r
509 devExt->irpq = NULL;
\r
510 KeReleaseSpinLock(&devExt->lock, currentIrql);
\r
511 IoReleaseCancelSpinLock(irp->CancelIrql);
\r
512 DEBUG_LOG(("detourReadCancel:"));
\r
514 KeAcquireSpinLock(&devExt->lock, ¤tIrql);
\r
515 if (devExt->irpq && irp == deviceObject->CurrentIrp)
\r
516 // the current request is being cancelled
\r
518 deviceObject->CurrentIrp = NULL;
\r
519 devExt->irpq = NULL;
\r
520 KeReleaseSpinLock(&devExt->lock, currentIrql);
\r
521 IoStartNextPacket(deviceObject, TRUE);
\r
523 // Cancel a request in the device queue
\r
526 IoAcquireCancelSpinLock(&cancelIrql);
\r
527 KeRemoveEntryDeviceQueue(&deviceObject->DeviceQueue,
\r
528 &irp->Tail.Overlay.DeviceQueueEntry);
\r
529 IoReleaseCancelSpinLock(cancelIrql);
\r
530 KeReleaseSpinLock(&devExt->lock, currentIrql);
\r
534 irp->IoStatus.Status = STATUS_CANCELLED;
\r
535 irp->IoStatus.Information = 0;
\r
536 IoCompleteRequest(irp, IO_KEYBOARD_INCREMENT);
\r
539 ///////////////////////////////////////////////////////////////////////////////
\r
540 // Complete Functions
\r
544 NTSTATUS filterGenericCompletion(IN PDEVICE_OBJECT deviceObject,
\r
545 IN PIRP irp, IN PVOID context)
\r
547 UNREFERENCED_PARAMETER(deviceObject);
\r
548 UNREFERENCED_PARAMETER(context);
\r
550 if (irp->PendingReturned)
\r
551 IoMarkIrpPending(irp);
\r
552 return STATUS_SUCCESS;
\r
557 NTSTATUS filterReadCompletion(IN PDEVICE_OBJECT deviceObject,
\r
558 IN PIRP irp, IN PVOID context)
\r
561 KIRQL currentIrql, cancelIrql;
\r
562 PIRP irpCancel = NULL;
\r
563 FilterDeviceExtension *filterDevExt =
\r
564 (FilterDeviceExtension*)deviceObject->DeviceExtension;
\r
565 PDEVICE_OBJECT detourDevObj = filterDevExt->detourDevObj;
\r
566 DetourDeviceExtension *detourDevExt =
\r
567 (DetourDeviceExtension*)detourDevObj->DeviceExtension;
\r
569 UNREFERENCED_PARAMETER(context);
\r
571 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
572 filterDevExt->irpq = NULL;
\r
573 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
574 if (irp->PendingReturned) {
\r
575 status = STATUS_PENDING;
\r
576 IoMarkIrpPending(irp);
\r
578 status = STATUS_SUCCESS;
\r
581 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
582 if (detourDevExt->isOpen && !detourDevExt->wasCleanupInitiated) {
\r
583 // if detour is opened, key datum are forwarded to detour
\r
584 if (irp->IoStatus.Status == STATUS_SUCCESS) {
\r
585 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
\r
587 KqEnque(&detourDevExt->readQue,
\r
588 (KEYBOARD_INPUT_DATA *)irp->AssociatedIrp.SystemBuffer,
\r
589 irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA));
\r
591 irp->IoStatus.Status = STATUS_CANCELLED;
\r
592 irp->IoStatus.Information = 0;
\r
593 detourDevExt->filterDevObj = deviceObject;
\r
596 IoAcquireCancelSpinLock(&cancelIrql);
\r
597 if (detourDevExt->irpq) {
\r
598 if (readq(&detourDevExt->readQue, detourDevExt->irpq) ==
\r
600 IoSetCancelRoutine(detourDevExt->irpq, NULL);
\r
601 IoCompleteRequest(detourDevExt->irpq, IO_KEYBOARD_INCREMENT);
\r
602 detourDevExt->irpq = NULL;
\r
605 IoReleaseCancelSpinLock(cancelIrql);
\r
606 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
608 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
609 status = readq(&filterDevExt->readQue, irp);
\r
610 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
612 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
615 if (status == STATUS_SUCCESS)
\r
616 irp->IoStatus.Status = STATUS_SUCCESS;
\r
617 return irp->IoStatus.Status;
\r
620 NTSTATUS readq(KeyQue *readQue, PIRP irp)
\r
622 if (!KqIsEmpty(readQue)) {
\r
623 PIO_STACK_LOCATION irpSp;
\r
626 irpSp = IoGetCurrentIrpStackLocation(irp);
\r
627 len = KqDeque(readQue,
\r
628 (KEYBOARD_INPUT_DATA *)irp->AssociatedIrp.SystemBuffer,
\r
629 irpSp->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA));
\r
630 irp->IoStatus.Status = STATUS_SUCCESS;
\r
631 irp->IoStatus.Information = len * sizeof(KEYBOARD_INPUT_DATA);
\r
632 irpSp->Parameters.Read.Length = irp->IoStatus.Information;
\r
633 return STATUS_SUCCESS;
\r
635 irp->IoStatus.Status = STATUS_PENDING;
\r
636 irp->IoStatus.Information = 0;
\r
637 return STATUS_PENDING;
\r
641 ///////////////////////////////////////////////////////////////////////////////
\r
642 // Dispatch Functions
\r
645 // Generic Dispatcher
\r
646 NTSTATUS mayuGenericDispatch(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
648 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
\r
650 if (deviceObject->NextDevice) {
\r
651 FilterDeviceExtension *filterDevExt =
\r
652 (FilterDeviceExtension *)deviceObject->DeviceExtension;
\r
654 #ifdef USE_TOUCHPAD
\r
655 if (filterDevExt->isKeyboard == FALSE) {
\r
656 DEBUG_LOG(("MajorFunction: %x", irpSp->MajorFunction));
\r
659 return filterDevExt->MajorFunction[irpSp->MajorFunction](deviceObject, irp);
\r
661 DetourDeviceExtension *detourDevExt =
\r
662 (DetourDeviceExtension *)deviceObject->DeviceExtension;
\r
664 return detourDevExt->MajorFunction[irpSp->MajorFunction](deviceObject, irp);
\r
669 // detour IRP_MJ_CREATE
\r
670 NTSTATUS detourCreate(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
672 DetourDeviceExtension *detourDevExt =
\r
673 (DetourDeviceExtension*)deviceObject->DeviceExtension;
\r
675 if (1 < InterlockedIncrement(&detourDevExt->isOpen))
\r
676 // mayu detour device can be opend only once at a time
\r
678 InterlockedDecrement(&detourDevExt->isOpen);
\r
679 irp->IoStatus.Status = STATUS_INTERNAL_ERROR;
\r
683 PDEVICE_OBJECT filterDevObj;
\r
685 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
686 detourDevExt->wasCleanupInitiated = FALSE;
\r
687 KqClear(&detourDevExt->readQue);
\r
688 filterDevObj = detourDevExt->filterDevObj;
\r
689 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
690 if (filterDevObj) {
\r
691 FilterDeviceExtension *filterDevExt =
\r
692 (FilterDeviceExtension*)filterDevObj->DeviceExtension;
\r
693 PDEVICE_OBJECT kbdClassDevObj;
\r
695 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
696 irpCancel = filterDevExt->kbdClassDevObj->CurrentIrp;
\r
697 kbdClassDevObj = filterDevExt->kbdClassDevObj;
\r
698 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
700 CancelKeyboardClassRead(irpCancel, kbdClassDevObj);
\r
704 irp->IoStatus.Status = STATUS_SUCCESS;
\r
706 irp->IoStatus.Information = 0;
\r
707 IoCompleteRequest(irp, IO_NO_INCREMENT);
\r
708 return irp->IoStatus.Status;
\r
712 // detour IRP_MJ_CLOSE
\r
713 NTSTATUS detourClose(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
715 DetourDeviceExtension *detourDevExt =
\r
716 (DetourDeviceExtension*)deviceObject->DeviceExtension;
\r
719 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
720 InterlockedDecrement(&detourDevExt->isOpen);
\r
721 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
722 irp->IoStatus.Status = STATUS_SUCCESS;
\r
723 irp->IoStatus.Information = 0;
\r
724 IoCompleteRequest(irp, IO_NO_INCREMENT);
\r
725 DEBUG_LOG_TERM(());
\r
726 return STATUS_SUCCESS;
\r
730 // detour IRP_MJ_READ
\r
731 NTSTATUS detourRead(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
734 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
\r
735 DetourDeviceExtension *detourDevExt =
\r
736 (DetourDeviceExtension*)deviceObject->DeviceExtension;
\r
737 KIRQL currentIrql, cancelIrql;
\r
739 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
740 if (irpSp->Parameters.Read.Length == 0)
\r
741 status = STATUS_SUCCESS;
\r
742 else if (irpSp->Parameters.Read.Length % sizeof(KEYBOARD_INPUT_DATA))
\r
743 status = STATUS_BUFFER_TOO_SMALL;
\r
745 status = readq(&detourDevExt->readQue, irp);
\r
746 if (status == STATUS_PENDING) {
\r
747 IoAcquireCancelSpinLock(&cancelIrql);
\r
748 IoMarkIrpPending(irp);
\r
749 detourDevExt->irpq = irp;
\r
750 IoSetCancelRoutine(irp, mayuDetourReadCancel);
\r
751 IoReleaseCancelSpinLock(cancelIrql);
\r
753 IoCompleteRequest(irp, IO_KEYBOARD_INCREMENT);
\r
755 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
760 // detour IRP_MJ_WRITE
\r
761 NTSTATUS detourWrite(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
764 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
\r
765 ULONG len = irpSp->Parameters.Write.Length;
\r
766 DetourDeviceExtension *detourDevExt =
\r
767 (DetourDeviceExtension*)deviceObject->DeviceExtension;
\r
769 irp->IoStatus.Information = 0;
\r
771 status = STATUS_SUCCESS;
\r
772 else if (len % sizeof(KEYBOARD_INPUT_DATA))
\r
773 status = STATUS_INVALID_PARAMETER;
\r
775 // write to filter que
\r
776 KIRQL cancelIrql, currentIrql;
\r
778 PDEVICE_OBJECT filterDevObj;
\r
780 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
781 filterDevObj = detourDevExt->filterDevObj;
\r
782 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
783 // enque filter que
\r
784 if (filterDevObj) {
\r
785 FilterDeviceExtension *filterDevExt =
\r
786 (FilterDeviceExtension*)filterDevObj->DeviceExtension;
\r
787 PDEVICE_OBJECT kbdClassDevObj;
\r
789 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
791 len /= sizeof(KEYBOARD_INPUT_DATA);
\r
792 len = KqEnque(&filterDevExt->readQue,
\r
793 (KEYBOARD_INPUT_DATA *)irp->AssociatedIrp.SystemBuffer,
\r
795 irp->IoStatus.Information = len * sizeof(KEYBOARD_INPUT_DATA);
\r
796 irpSp->Parameters.Write.Length = irp->IoStatus.Information;
\r
797 // cancel filter irp
\r
798 irpCancel = filterDevExt->irpq;
\r
799 filterDevExt->irpq = NULL;
\r
800 kbdClassDevObj = filterDevExt->kbdClassDevObj;
\r
801 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
803 CancelKeyboardClassRead(irpCancel, kbdClassDevObj);
\r
805 status = STATUS_SUCCESS;
\r
807 irp->IoStatus.Information = 0;
\r
808 irpSp->Parameters.Write.Length = irp->IoStatus.Information;
\r
809 status = STATUS_CANCELLED;
\r
812 IoCompleteRequest(irp, IO_NO_INCREMENT);
\r
817 // detour IRP_MJ_CLEANUP
\r
818 NTSTATUS detourCleanup(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
820 KIRQL currentIrql, cancelIrql;
\r
821 PIO_STACK_LOCATION irpSp;
\r
822 PIRP currentIrp = NULL, irpCancel;
\r
823 DetourDeviceExtension *detourDevExt =
\r
824 (DetourDeviceExtension*)deviceObject->DeviceExtension;
\r
826 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
827 IoAcquireCancelSpinLock(&cancelIrql);
\r
828 irpSp = IoGetCurrentIrpStackLocation(irp);
\r
829 detourDevExt->wasCleanupInitiated = TRUE;
\r
831 // Complete all requests queued by this thread with STATUS_CANCELLED
\r
832 currentIrp = deviceObject->CurrentIrp;
\r
833 deviceObject->CurrentIrp = NULL;
\r
834 detourDevExt->irpq = NULL;
\r
836 while (currentIrp != NULL) {
\r
837 IoSetCancelRoutine(currentIrp, NULL);
\r
838 currentIrp->IoStatus.Status = STATUS_CANCELLED;
\r
839 currentIrp->IoStatus.Information = 0;
\r
841 IoReleaseCancelSpinLock(cancelIrql);
\r
842 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
843 IoCompleteRequest(currentIrp, IO_NO_INCREMENT);
\r
844 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
845 IoAcquireCancelSpinLock(&cancelIrql);
\r
847 // Dequeue the next packet (IRP) from the device work queue.
\r
849 PKDEVICE_QUEUE_ENTRY packet =
\r
850 KeRemoveDeviceQueue(&deviceObject->DeviceQueue);
\r
851 currentIrp = packet ?
\r
852 CONTAINING_RECORD(packet, IRP, Tail.Overlay.DeviceQueueEntry) : NULL;
\r
856 IoReleaseCancelSpinLock(cancelIrql);
\r
857 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
859 // Complete the cleanup request with STATUS_SUCCESS.
\r
860 irp->IoStatus.Status = STATUS_SUCCESS;
\r
861 irp->IoStatus.Information = 0;
\r
862 IoCompleteRequest(irp, IO_NO_INCREMENT);
\r
864 return STATUS_SUCCESS;
\r
868 // detour IRP_MJ_DEVICE_CONTROL
\r
869 NTSTATUS detourDeviceControl(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
872 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
\r
873 DetourDeviceExtension *detourDevExt =
\r
874 (DetourDeviceExtension*)deviceObject->DeviceExtension;
\r
876 irp->IoStatus.Information = 0;
\r
877 if (irpSp->Parameters.DeviceIoControl.IoControlCode != IOCTL_MAYU_GET_LOG) DEBUG_LOG(("DeviceIoControl: %x", irpSp->Parameters.DeviceIoControl.IoControlCode));
\r
878 status = STATUS_INVALID_DEVICE_REQUEST;
\r
879 switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
\r
880 case IOCTL_MAYU_DETOUR_CANCEL: {
\r
882 PIRP irpCancel = NULL;
\r
884 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
885 if (detourDevExt->isOpen)
\r
886 irpCancel = detourDevExt->irpq;
\r
887 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
890 IoCancelIrp(irpCancel);// at this point, the irpCancel may be completed
\r
891 status = STATUS_SUCCESS;
\r
894 case IOCTL_MAYU_GET_VERSION: {
\r
895 if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
\r
896 MayuDriverVersion.Length) {
\r
897 status = STATUS_INVALID_PARAMETER;
\r
900 RtlCopyMemory(irp->AssociatedIrp.SystemBuffer,
\r
901 MayuDriverVersion.Buffer, MayuDriverVersion.Length);
\r
902 irp->IoStatus.Information = MayuDriverVersion.Length;
\r
903 DEBUG_LOG(("Version: %T", &MayuDriverVersion));
\r
904 status = STATUS_SUCCESS;
\r
907 case IOCTL_MAYU_GET_LOG:
\r
908 status = DEBUG_LOG_RETRIEVE((irp));
\r
910 case IOCTL_MAYU_FORCE_KEYBOARD_INPUT: {
\r
911 KIRQL currentIrql, cancelIrql;
\r
913 // if detour is opened, key datum are forwarded to detour
\r
914 if (irpSp->Parameters.DeviceIoControl.InputBufferLength %
\r
915 sizeof(KEYBOARD_INPUT_DATA)) {
\r
916 status = STATUS_INVALID_PARAMETER;
\r
919 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
920 KqEnque(&detourDevExt->readQue,
\r
921 (KEYBOARD_INPUT_DATA *)irp->AssociatedIrp.SystemBuffer,
\r
922 irpSp->Parameters.DeviceIoControl.InputBufferLength
\r
923 / sizeof(KEYBOARD_INPUT_DATA));
\r
925 if (detourDevExt->irpq) {
\r
926 if (readq(&detourDevExt->readQue, detourDevExt->irpq) ==
\r
928 IoAcquireCancelSpinLock(&cancelIrql);
\r
929 IoSetCancelRoutine(detourDevExt->irpq, NULL);
\r
930 IoReleaseCancelSpinLock(cancelIrql);
\r
931 IoCompleteRequest(detourDevExt->irpq, IO_KEYBOARD_INCREMENT);
\r
932 detourDevExt->irpq = NULL;
\r
935 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
936 status = STATUS_SUCCESS;
\r
940 status = STATUS_INVALID_DEVICE_REQUEST;
\r
943 irp->IoStatus.Status = status;
\r
944 if (status != STATUS_PENDING)
\r
945 IoCompleteRequest(irp, IO_NO_INCREMENT);
\r
952 // detour IRP_MJ_POWER
\r
953 NTSTATUS detourPower(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
955 UNREFERENCED_PARAMETER(deviceObject);
\r
957 PoStartNextPowerIrp(irp);
\r
958 irp->IoStatus.Status = STATUS_SUCCESS;
\r
959 irp->IoStatus.Information = 0;
\r
960 IoCompleteRequest(irp, IO_NO_INCREMENT);
\r
961 return STATUS_SUCCESS;
\r
963 #endif // !MAYUD_NT4
\r
966 // filter IRP_MJ_READ
\r
967 NTSTATUS filterRead(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
970 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
\r
971 FilterDeviceExtension *filterDevExt =
\r
972 (FilterDeviceExtension*)deviceObject->DeviceExtension;
\r
973 DetourDeviceExtension *detourDevExt =
\r
974 (DetourDeviceExtension*)filterDevExt->detourDevObj->DeviceExtension;
\r
977 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
978 if (detourDevExt->isOpen && !detourDevExt->wasCleanupInitiated)
\r
981 ULONG len = irpSp->Parameters.Read.Length;
\r
983 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
984 irp->IoStatus.Information = 0;
\r
985 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
987 status = STATUS_SUCCESS;
\r
988 else if (len % sizeof(KEYBOARD_INPUT_DATA))
\r
989 status = STATUS_BUFFER_TOO_SMALL;
\r
991 status = readq(&filterDevExt->readQue, irp);
\r
992 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
993 if (status != STATUS_PENDING) {
\r
994 irp->IoStatus.Status = status;
\r
995 IoCompleteRequest(irp, IO_NO_INCREMENT);
\r
999 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
1001 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
1002 filterDevExt->irpq = irp;
\r
1003 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
1005 *IoGetNextIrpStackLocation(irp) = *irpSp;
\r
1006 IoSetCompletionRoutine(irp, filterReadCompletion, NULL, TRUE, TRUE, TRUE);
\r
1007 return IoCallDriver(filterDevExt->kbdClassDevObj, irp);
\r
1011 // pass throught irp to keyboard class driver
\r
1012 NTSTATUS filterPassThrough(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
1014 FilterDeviceExtension *filterDevExt =
\r
1015 (FilterDeviceExtension*)deviceObject->DeviceExtension;
\r
1017 *IoGetNextIrpStackLocation(irp) = *IoGetCurrentIrpStackLocation(irp);
\r
1018 IoSetCompletionRoutine(irp, filterGenericCompletion,
\r
1019 NULL, TRUE, TRUE, TRUE);
\r
1020 return IoCallDriver(filterDevExt->kbdClassDevObj, irp);
\r
1025 // filter IRP_MJ_POWER
\r
1026 NTSTATUS filterPower(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
1028 FilterDeviceExtension *filterDevExt =
\r
1029 (FilterDeviceExtension*)deviceObject->DeviceExtension;
\r
1031 PoStartNextPowerIrp(irp);
\r
1032 IoSkipCurrentIrpStackLocation(irp);
\r
1033 return PoCallDriver(filterDevExt->kbdClassDevObj, irp);
\r
1035 #endif // !MAYUD_NT4
\r
1036 NTSTATUS filterPnP(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
1038 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
\r
1039 FilterDeviceExtension *filterDevExt =
\r
1040 (FilterDeviceExtension*)deviceObject->DeviceExtension;
\r
1041 DetourDeviceExtension *detourDevExt =
\r
1042 (DetourDeviceExtension*)filterDevExt->detourDevObj->DeviceExtension;
\r
1043 KIRQL currentIrql;
\r
1047 PDRIVER_OBJECT driverObject = deviceObject->DriverObject;
\r
1049 minor = irpSp->MinorFunction;
\r
1050 IoSkipCurrentIrpStackLocation(irp);
\r
1051 status = IoCallDriver(filterDevExt->kbdClassDevObj, irp);
\r
1052 DEBUG_LOG(("filterPnP: minor=%d(%x)", minor, minor));
\r
1054 case IRP_MN_SURPRISE_REMOVAL:
\r
1055 case IRP_MN_REMOVE_DEVICE:
\r
1056 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
1057 if (detourDevExt->filterDevObj == deviceObject) {
\r
1058 PDEVICE_OBJECT devObj = deviceObject->DriverObject->DeviceObject;
\r
1060 DEBUG_LOG(("filterPnP: current filter(%x) was removed", deviceObject));
\r
1061 detourDevExt->filterDevObj = NULL;
\r
1062 while (devObj->NextDevice) {
\r
1063 if (devObj != deviceObject) {
\r
1064 detourDevExt->filterDevObj = devObj;
\r
1067 devObj = devObj->NextDevice;
\r
1069 DEBUG_LOG(("filterPnP: current filter was changed to %x", detourDevExt->filterDevObj));
\r
1071 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
1073 IoDetachDevice(filterDevExt->kbdClassDevObj);
\r
1075 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
1076 // TODO: at this point, the irp may be completed (but what can I do for it ?)
\r
1077 cancelIrp = filterDevExt->irpq;
\r
1078 KqFinalize(&filterDevExt->readQue);
\r
1080 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
1082 IoCancelIrp(cancelIrp);
\r
1084 IoDeleteDevice(deviceObject);
\r
1085 DEBUG_LOG(("delete filter device: %x", deviceObject));
\r
1086 DEBUG_LOGChain(driverObject);
\r
1095 #ifdef USE_TOUCHPAD
\r
1097 NTSTATUS filterTouchpadCompletion(IN PDEVICE_OBJECT deviceObject,
\r
1098 IN PIRP irp, IN PVOID context)
\r
1100 KIRQL currentIrql;
\r
1101 FilterDeviceExtension *filterDevExt =
\r
1102 (FilterDeviceExtension*)deviceObject->DeviceExtension;
\r
1103 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
\r
1104 //PIO_STACK_LOCATION irpSp = IoGetNextIrpStackLocation(irp);
\r
1105 UCHAR *data = irp->UserBuffer;
\r
1108 UNREFERENCED_PARAMETER(context);
\r
1110 if (irp->PendingReturned)
\r
1111 IoMarkIrpPending(irp);
\r
1114 pressure = data[TOUCHPAD_PRESSURE_OFFSET];
\r
1119 ULONG *p = (ULONG*)data;
\r
1120 //DEBUG_LOG(("UserBuffer: %2x %2x %2x %2x", data[4], data[5], data[6], data[7]));
\r
1121 //DEBUG_LOG(("UserBuffer: %x %x %x %x %x %x %x %x", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]));
\r
1123 KeAcquireSpinLock(&filterDevExt->lock, ¤tIrql);
\r
1124 if (filterDevExt->isTouched == FALSE && pressure) {
\r
1125 KIRQL currentIrql, cancelIrql;
\r
1126 PDEVICE_OBJECT detourDevObj = filterDevExt->detourDevObj;
\r
1127 DetourDeviceExtension *detourDevExt =
\r
1128 (DetourDeviceExtension*)detourDevObj->DeviceExtension;
\r
1129 if (detourDevExt->isOpen) {
\r
1130 KEYBOARD_INPUT_DATA PadKey = {0, TOUCHPAD_SCANCODE, 0, 0, 0};
\r
1131 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
1132 // if detour is opened, key datum are forwarded to detour
\r
1133 KqEnque(&detourDevExt->readQue, &PadKey, 1);
\r
1134 detourDevExt->filterDevObj = deviceObject;
\r
1136 if (detourDevExt->irpq) {
\r
1137 if (readq(&detourDevExt->readQue, detourDevExt->irpq) ==
\r
1139 IoAcquireCancelSpinLock(&cancelIrql);
\r
1140 IoSetCancelRoutine(detourDevExt->irpq, NULL);
\r
1141 IoReleaseCancelSpinLock(cancelIrql);
\r
1142 IoCompleteRequest(detourDevExt->irpq, IO_KEYBOARD_INCREMENT);
\r
1143 detourDevExt->irpq = NULL;
\r
1146 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
1148 filterDevExt->isTouched = TRUE;
\r
1150 if (filterDevExt->isTouched == TRUE && pressure == 0) {
\r
1151 KIRQL currentIrql, cancelIrql;
\r
1152 PDEVICE_OBJECT detourDevObj = filterDevExt->detourDevObj;
\r
1153 DetourDeviceExtension *detourDevExt =
\r
1154 (DetourDeviceExtension*)detourDevObj->DeviceExtension;
\r
1155 if (detourDevExt->isOpen) {
\r
1156 KEYBOARD_INPUT_DATA PadKey = {0, TOUCHPAD_SCANCODE, 1, 0, 0};
\r
1157 KeAcquireSpinLock(&detourDevExt->lock, ¤tIrql);
\r
1158 // if detour is opened, key datum are forwarded to detour
\r
1159 KqEnque(&detourDevExt->readQue, &PadKey, 1);
\r
1160 detourDevExt->filterDevObj = deviceObject;
\r
1162 if (detourDevExt->irpq) {
\r
1163 if (readq(&detourDevExt->readQue, detourDevExt->irpq) ==
\r
1165 IoAcquireCancelSpinLock(&cancelIrql);
\r
1166 IoSetCancelRoutine(detourDevExt->irpq, NULL);
\r
1167 IoReleaseCancelSpinLock(cancelIrql);
\r
1168 IoCompleteRequest(detourDevExt->irpq, IO_KEYBOARD_INCREMENT);
\r
1169 detourDevExt->irpq = NULL;
\r
1172 KeReleaseSpinLock(&detourDevExt->lock, currentIrql);
\r
1174 filterDevExt->isTouched = FALSE;
\r
1177 //DEBUG_LOG(("touchpad pressed: out=%u in=%u code=%u status=%x SystemBuffer=%x UserBuffer=%x", irpSp->Parameters.DeviceIoControl.OutputBufferLength, irpSp->Parameters.DeviceIoControl.InputBufferLength, irpSp->Parameters.DeviceIoControl.IoControlCode, irp->IoStatus.Status, irp->AssociatedIrp.SystemBuffer, irp->UserBuffer));
\r
1178 KeReleaseSpinLock(&filterDevExt->lock, currentIrql);
\r
1179 return STATUS_SUCCESS;
\r
1183 // filter touchpad input
\r
1184 NTSTATUS filterTouchpad(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
1186 FilterDeviceExtension *filterDevExt =
\r
1187 (FilterDeviceExtension*)deviceObject->DeviceExtension;
\r
1189 *IoGetNextIrpStackLocation(irp) = *IoGetCurrentIrpStackLocation(irp);
\r
1190 IoSetCompletionRoutine(irp, filterTouchpadCompletion,
\r
1191 NULL, TRUE, TRUE, TRUE);
\r
1192 return IoCallDriver(filterDevExt->kbdClassDevObj, irp);
\r
1197 NTSTATUS detourPnP(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
\r
1199 UNREFERENCED_PARAMETER(deviceObject);
\r
1201 IoSkipCurrentIrpStackLocation(irp);
\r
1202 irp->IoStatus.Status = STATUS_SUCCESS;
\r
1203 irp->IoStatus.Information = 0;
\r
1204 IoCompleteRequest(irp, IO_NO_INCREMENT);
\r
1205 return STATUS_SUCCESS;
\r