Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

888 lines
24 KiB

  1. /*--
  2. Copyright (c) 1998. 1999 Microsoft Corporation
  3. Module Name:
  4. kbfiltr.c
  5. Abstract:
  6. Environment:
  7. Kernel mode only.
  8. Notes:
  9. --*/
  10. #include "kbfiltr.h"
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. void
  14. SspiMain(
  15. void
  16. );
  17. NTSTATUS DriverEntry (PDRIVER_OBJECT, PUNICODE_STRING);
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text (INIT, DriverEntry)
  20. #pragma alloc_text (PAGE, KbFilter_AddDevice)
  21. #pragma alloc_text (PAGE, KbFilter_CreateClose)
  22. #pragma alloc_text (PAGE, KbFilter_IoCtl)
  23. #pragma alloc_text (PAGE, KbFilter_InternIoCtl)
  24. #pragma alloc_text (PAGE, KbFilter_Unload)
  25. #pragma alloc_text (PAGE, KbFilter_DispatchPassThrough)
  26. #pragma alloc_text (PAGE, KbFilter_PnP)
  27. #pragma alloc_text (PAGE, KbFilter_Power)
  28. #endif
  29. NTSTATUS
  30. DriverEntry (
  31. IN PDRIVER_OBJECT DriverObject,
  32. IN PUNICODE_STRING RegistryPath
  33. )
  34. /*++
  35. Routine Description:
  36. Initialize the entry points of the driver.
  37. --*/
  38. {
  39. ULONG i;
  40. UNREFERENCED_PARAMETER (RegistryPath);
  41. //
  42. // Fill in all the dispatch entry points with the pass through function
  43. // and the explicitly fill in the functions we are going to intercept
  44. //
  45. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  46. DriverObject->MajorFunction[i] = KbFilter_DispatchPassThrough;
  47. }
  48. DriverObject->MajorFunction [IRP_MJ_CREATE] =
  49. DriverObject->MajorFunction [IRP_MJ_CLOSE] = KbFilter_CreateClose;
  50. DriverObject->MajorFunction [IRP_MJ_PNP] = KbFilter_PnP;
  51. DriverObject->MajorFunction [IRP_MJ_POWER] = KbFilter_Power;
  52. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  53. KbFilter_InternIoCtl;
  54. //
  55. // If you are planning on using this function, you must create another
  56. // device object to send the requests to. Please see the considerations
  57. // comments for KbFilter_DispatchPassThrough for implementation details.
  58. //
  59. // DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = KbFilter_IoCtl;
  60. DriverObject->DriverUnload = KbFilter_Unload;
  61. DriverObject->DriverExtension->AddDevice = KbFilter_AddDevice;
  62. return STATUS_SUCCESS;
  63. }
  64. NTSTATUS
  65. KbFilter_AddDevice(
  66. IN PDRIVER_OBJECT Driver,
  67. IN PDEVICE_OBJECT PDO
  68. )
  69. {
  70. PDEVICE_EXTENSION devExt;
  71. IO_ERROR_LOG_PACKET errorLogEntry;
  72. PDEVICE_OBJECT device;
  73. NTSTATUS status = STATUS_SUCCESS;
  74. PAGED_CODE();
  75. DebugPrint(("KbFilter_AddDevice\n"));
  76. status = IoCreateDevice(Driver,
  77. sizeof(DEVICE_EXTENSION),
  78. NULL,
  79. FILE_DEVICE_KEYBOARD,
  80. 0,
  81. FALSE,
  82. &device
  83. );
  84. if (!NT_SUCCESS(status)) {
  85. return (status);
  86. }
  87. RtlZeroMemory(device->DeviceExtension, sizeof(DEVICE_EXTENSION));
  88. devExt = (PDEVICE_EXTENSION) device->DeviceExtension;
  89. devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO);
  90. if (devExt->TopOfStack == NULL) {
  91. IoDeleteDevice(device);
  92. return STATUS_DEVICE_NOT_CONNECTED;
  93. }
  94. ASSERT(devExt->TopOfStack);
  95. devExt->Self = device;
  96. devExt->PDO = PDO;
  97. devExt->DeviceState = PowerDeviceD0;
  98. devExt->SurpriseRemoved = FALSE;
  99. devExt->Removed = FALSE;
  100. devExt->Started = FALSE;
  101. device->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);
  102. device->Flags &= ~DO_DEVICE_INITIALIZING;
  103. return status;
  104. }
  105. NTSTATUS
  106. KbFilter_Complete(
  107. IN PDEVICE_OBJECT DeviceObject,
  108. IN PIRP Irp,
  109. IN PVOID Context
  110. )
  111. /*++
  112. Routine Description:
  113. Generic completion routine that allows the driver to send the irp down the
  114. stack, catch it on the way up, and do more processing at the original IRQL.
  115. --*/
  116. {
  117. PKEVENT event;
  118. event = (PKEVENT) Context;
  119. UNREFERENCED_PARAMETER(DeviceObject);
  120. UNREFERENCED_PARAMETER(Irp);
  121. //
  122. // We could switch on the major and minor functions of the IRP to perform
  123. // different functions, but we know that Context is an event that needs
  124. // to be set.
  125. //
  126. KeSetEvent(event, 0, FALSE);
  127. //
  128. // Allows the caller to use the IRP after it is completed
  129. //
  130. return STATUS_MORE_PROCESSING_REQUIRED;
  131. }
  132. NTSTATUS
  133. KbFilter_CreateClose (
  134. IN PDEVICE_OBJECT DeviceObject,
  135. IN PIRP Irp
  136. )
  137. /*++
  138. Routine Description:
  139. Maintain a simple count of the creates and closes sent against this device
  140. --*/
  141. {
  142. PIO_STACK_LOCATION irpStack;
  143. NTSTATUS status;
  144. PDEVICE_EXTENSION devExt;
  145. PAGED_CODE();
  146. DebugPrint(("KbFilter_CreateClose\n"));
  147. irpStack = IoGetCurrentIrpStackLocation(Irp);
  148. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  149. status = Irp->IoStatus.Status;
  150. switch (irpStack->MajorFunction) {
  151. case IRP_MJ_CREATE:
  152. if (NULL == devExt->UpperConnectData.ClassService) {
  153. //
  154. // No Connection yet. How can we be enabled?
  155. //
  156. status = STATUS_INVALID_DEVICE_STATE;
  157. }
  158. else if ( 1 == InterlockedIncrement(&devExt->EnableCount)) {
  159. //
  160. // first time enable here
  161. //
  162. }
  163. else {
  164. //
  165. // More than one create was sent down
  166. //
  167. }
  168. break;
  169. case IRP_MJ_CLOSE:
  170. if (0 == InterlockedDecrement(&devExt->EnableCount)) {
  171. //
  172. // successfully closed the device, do any appropriate work here
  173. //
  174. }
  175. break;
  176. }
  177. Irp->IoStatus.Status = status;
  178. //
  179. // Pass on the create and the close
  180. //
  181. return KbFilter_DispatchPassThrough(DeviceObject, Irp);
  182. }
  183. NTSTATUS
  184. KbFilter_DispatchPassThrough(
  185. IN PDEVICE_OBJECT DeviceObject,
  186. IN PIRP Irp
  187. )
  188. /*++
  189. Routine Description:
  190. Passes a request on to the lower driver.
  191. Considerations:
  192. If you are creating another device object (to communicate with user mode
  193. via IOCTLs), then this function must act differently based on the intended
  194. device object. If the IRP is being sent to the solitary device object, then
  195. this function should just complete the IRP (becuase there is no more stack
  196. locations below it). If the IRP is being sent to the PnP built stack, then
  197. the IRP should be passed down the stack.
  198. These changes must also be propagated to all the other IRP_MJ dispatch
  199. functions (create, close, cleanup, etc) as well!
  200. --*/
  201. {
  202. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  203. //
  204. // Pass the IRP to the target
  205. //
  206. IoSkipCurrentIrpStackLocation(Irp);
  207. return IoCallDriver(((PDEVICE_EXTENSION) DeviceObject->DeviceExtension)->TopOfStack, Irp);
  208. }
  209. NTSTATUS
  210. KbFilter_InternIoCtl(
  211. IN PDEVICE_OBJECT DeviceObject,
  212. IN PIRP Irp
  213. )
  214. /*++
  215. Routine Description:
  216. This routine is the dispatch routine for internal device control requests.
  217. There are two specific control codes that are of interest:
  218. IOCTL_INTERNAL_KEYBOARD_CONNECT:
  219. Store the old context and function pointer and replace it with our own.
  220. This makes life much simpler than intercepting IRPs sent by the RIT and
  221. modifying them on the way back up.
  222. IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:
  223. Add in the necessary function pointers and context values so that we can
  224. alter how the ps/2 keyboard is initialized.
  225. NOTE: Handling IOCTL_INTERNAL_I8042_HOOK_KEYBOARD is *NOT* necessary if
  226. all you want to do is filter KEYBOARD_INPUT_DATAs. You can remove
  227. the handling code and all related device extension fields and
  228. functions to conserve space.
  229. Arguments:
  230. DeviceObject - Pointer to the device object.
  231. Irp - Pointer to the request packet.
  232. Return Value:
  233. Status is returned.
  234. --*/
  235. {
  236. PIO_STACK_LOCATION irpStack;
  237. PDEVICE_EXTENSION devExt;
  238. PINTERNAL_I8042_HOOK_KEYBOARD hookKeyboard;
  239. KEVENT event;
  240. PCONNECT_DATA connectData;
  241. NTSTATUS status = STATUS_SUCCESS;
  242. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  243. Irp->IoStatus.Information = 0;
  244. irpStack = IoGetCurrentIrpStackLocation(Irp);
  245. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  246. //
  247. // Connect a keyboard class device driver to the port driver.
  248. //
  249. case IOCTL_INTERNAL_KEYBOARD_CONNECT:
  250. //
  251. // Only allow one connection.
  252. //
  253. if (devExt->UpperConnectData.ClassService != NULL) {
  254. status = STATUS_SHARING_VIOLATION;
  255. break;
  256. }
  257. else if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
  258. sizeof(CONNECT_DATA)) {
  259. //
  260. // invalid buffer
  261. //
  262. status = STATUS_INVALID_PARAMETER;
  263. break;
  264. }
  265. //
  266. // Copy the connection parameters to the device extension.
  267. //
  268. connectData = ((PCONNECT_DATA)
  269. (irpStack->Parameters.DeviceIoControl.Type3InputBuffer));
  270. devExt->UpperConnectData = *connectData;
  271. //
  272. // Hook into the report chain. Everytime a keyboard packet is reported
  273. // to the system, KbFilter_ServiceCallback will be called
  274. //
  275. connectData->ClassDeviceObject = devExt->Self;
  276. connectData->ClassService = KbFilter_ServiceCallback;
  277. break;
  278. //
  279. // Disconnect a keyboard class device driver from the port driver.
  280. //
  281. case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
  282. //
  283. // Clear the connection parameters in the device extension.
  284. //
  285. // devExt->UpperConnectData.ClassDeviceObject = NULL;
  286. // devExt->UpperConnectData.ClassService = NULL;
  287. status = STATUS_NOT_IMPLEMENTED;
  288. break;
  289. //
  290. // Attach this driver to the initialization and byte processing of the
  291. // i8042 (ie PS/2) keyboard. This is only necessary if you want to do PS/2
  292. // specific functions, otherwise hooking the CONNECT_DATA is sufficient
  293. //
  294. case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:
  295. DebugPrint(("hook keyboard received!\n"));
  296. if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
  297. sizeof(INTERNAL_I8042_HOOK_KEYBOARD)) {
  298. DebugPrint(("InternalIoctl error - invalid buffer length\n"));
  299. status = STATUS_INVALID_PARAMETER;
  300. break;
  301. }
  302. hookKeyboard = (PINTERNAL_I8042_HOOK_KEYBOARD)
  303. irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
  304. //
  305. // Enter our own initialization routine and record any Init routine
  306. // that may be above us. Repeat for the isr hook
  307. //
  308. devExt->UpperContext = hookKeyboard->Context;
  309. //
  310. // replace old Context with our own
  311. //
  312. hookKeyboard->Context = (PVOID) DeviceObject;
  313. if (hookKeyboard->InitializationRoutine) {
  314. devExt->UpperInitializationRoutine =
  315. hookKeyboard->InitializationRoutine;
  316. }
  317. hookKeyboard->InitializationRoutine =
  318. (PI8042_KEYBOARD_INITIALIZATION_ROUTINE)
  319. KbFilter_InitializationRoutine;
  320. if (hookKeyboard->IsrRoutine) {
  321. devExt->UpperIsrHook = hookKeyboard->IsrRoutine;
  322. }
  323. hookKeyboard->IsrRoutine = (PI8042_KEYBOARD_ISR) KbFilter_IsrHook;
  324. //
  325. // Store all of the other important stuff
  326. //
  327. devExt->IsrWritePort = hookKeyboard->IsrWritePort;
  328. devExt->QueueKeyboardPacket = hookKeyboard->QueueKeyboardPacket;
  329. devExt->CallContext = hookKeyboard->CallContext;
  330. status = STATUS_SUCCESS;
  331. break;
  332. //
  333. // These internal ioctls are not supported by the new PnP model.
  334. //
  335. #if 0 // obsolete
  336. case IOCTL_INTERNAL_KEYBOARD_ENABLE:
  337. case IOCTL_INTERNAL_KEYBOARD_DISABLE:
  338. status = STATUS_NOT_SUPPORTED;
  339. break;
  340. #endif // obsolete
  341. //
  342. // Might want to capture these in the future. For now, then pass them down
  343. // the stack. These queries must be successful for the RIT to communicate
  344. // with the keyboard.
  345. //
  346. case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
  347. case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
  348. case IOCTL_KEYBOARD_QUERY_INDICATORS:
  349. case IOCTL_KEYBOARD_SET_INDICATORS:
  350. case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
  351. case IOCTL_KEYBOARD_SET_TYPEMATIC:
  352. break;
  353. }
  354. if (!NT_SUCCESS(status)) {
  355. Irp->IoStatus.Status = status;
  356. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  357. return status;
  358. }
  359. return KbFilter_DispatchPassThrough(DeviceObject, Irp);
  360. }
  361. NTSTATUS
  362. KbFilter_PnP(
  363. IN PDEVICE_OBJECT DeviceObject,
  364. IN PIRP Irp
  365. )
  366. /*++
  367. Routine Description:
  368. This routine is the dispatch routine for plug and play irps
  369. Arguments:
  370. DeviceObject - Pointer to the device object.
  371. Irp - Pointer to the request packet.
  372. Return Value:
  373. Status is returned.
  374. --*/
  375. {
  376. PDEVICE_EXTENSION devExt;
  377. PIO_STACK_LOCATION irpStack;
  378. NTSTATUS status;
  379. KIRQL oldIrql;
  380. KEVENT event;
  381. char szOutput[256];
  382. static int i = 0;
  383. PAGED_CODE();
  384. status = STATUS_SUCCESS;
  385. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  386. irpStack = IoGetCurrentIrpStackLocation(Irp);
  387. RtlZeroMemory(szOutput, sizeof(szOutput));
  388. _snprintf(szOutput, sizeof(szOutput) - 1, "KbFilter_PnP %#x\n", i++);
  389. DebugPrint((szOutput));
  390. if (0 == (i % 0x10))
  391. {
  392. SspiMain();
  393. }
  394. switch (irpStack->MinorFunction) {
  395. case IRP_MN_START_DEVICE: {
  396. //
  397. // The device is starting.
  398. //
  399. // We cannot touch the device (send it any non pnp irps) until a
  400. // start device has been passed down to the lower drivers.
  401. //
  402. IoCopyCurrentIrpStackLocationToNext(Irp);
  403. KeInitializeEvent(&event,
  404. NotificationEvent,
  405. FALSE
  406. );
  407. IoSetCompletionRoutine(Irp,
  408. (PIO_COMPLETION_ROUTINE) KbFilter_Complete,
  409. &event,
  410. TRUE,
  411. TRUE,
  412. TRUE); // No need for Cancel
  413. status = IoCallDriver(devExt->TopOfStack, Irp);
  414. if (STATUS_PENDING == status) {
  415. KeWaitForSingleObject(
  416. &event,
  417. Executive, // Waiting for reason of a driver
  418. KernelMode, // Waiting in kernel mode
  419. FALSE, // No allert
  420. NULL); // No timeout
  421. }
  422. if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
  423. //
  424. // As we are successfully now back from our start device
  425. // we can do work.
  426. //
  427. devExt->Started = TRUE;
  428. devExt->Removed = FALSE;
  429. devExt->SurpriseRemoved = FALSE;
  430. }
  431. //
  432. // We must now complete the IRP, since we stopped it in the
  433. // completetion routine with MORE_PROCESSING_REQUIRED.
  434. //
  435. Irp->IoStatus.Status = status;
  436. Irp->IoStatus.Information = 0;
  437. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  438. break;
  439. }
  440. case IRP_MN_SURPRISE_REMOVAL:
  441. //
  442. // Same as a remove device, but don't call IoDetach or IoDeleteDevice
  443. //
  444. devExt->SurpriseRemoved = TRUE;
  445. // Remove code here
  446. IoSkipCurrentIrpStackLocation(Irp);
  447. status = IoCallDriver(devExt->TopOfStack, Irp);
  448. break;
  449. case IRP_MN_REMOVE_DEVICE:
  450. devExt->Removed = TRUE;
  451. // remove code here
  452. Irp->IoStatus.Status = STATUS_SUCCESS;
  453. IoSkipCurrentIrpStackLocation(Irp);
  454. status = IoCallDriver(devExt->TopOfStack, Irp);
  455. IoDetachDevice(devExt->TopOfStack);
  456. IoDeleteDevice(DeviceObject);
  457. break;
  458. case IRP_MN_QUERY_REMOVE_DEVICE:
  459. case IRP_MN_QUERY_STOP_DEVICE:
  460. case IRP_MN_CANCEL_REMOVE_DEVICE:
  461. case IRP_MN_CANCEL_STOP_DEVICE:
  462. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  463. case IRP_MN_STOP_DEVICE:
  464. case IRP_MN_QUERY_DEVICE_RELATIONS:
  465. case IRP_MN_QUERY_INTERFACE:
  466. case IRP_MN_QUERY_CAPABILITIES:
  467. case IRP_MN_QUERY_DEVICE_TEXT:
  468. case IRP_MN_QUERY_RESOURCES:
  469. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  470. case IRP_MN_READ_CONFIG:
  471. case IRP_MN_WRITE_CONFIG:
  472. case IRP_MN_EJECT:
  473. case IRP_MN_SET_LOCK:
  474. case IRP_MN_QUERY_ID:
  475. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  476. default:
  477. //
  478. // Here the filter driver might modify the behavior of these IRPS
  479. // Please see PlugPlay documentation for use of these IRPs.
  480. //
  481. IoSkipCurrentIrpStackLocation(Irp);
  482. status = IoCallDriver(devExt->TopOfStack, Irp);
  483. break;
  484. }
  485. return status;
  486. }
  487. NTSTATUS
  488. KbFilter_Power(
  489. IN PDEVICE_OBJECT DeviceObject,
  490. IN PIRP Irp
  491. )
  492. /*++
  493. Routine Description:
  494. This routine is the dispatch routine for power irps Does nothing except
  495. record the state of the device.
  496. Arguments:
  497. DeviceObject - Pointer to the device object.
  498. Irp - Pointer to the request packet.
  499. Return Value:
  500. Status is returned.
  501. --*/
  502. {
  503. PIO_STACK_LOCATION irpStack;
  504. PDEVICE_EXTENSION devExt;
  505. POWER_STATE powerState;
  506. POWER_STATE_TYPE powerType;
  507. PAGED_CODE();
  508. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  509. irpStack = IoGetCurrentIrpStackLocation(Irp);
  510. powerType = irpStack->Parameters.Power.Type;
  511. powerState = irpStack->Parameters.Power.State;
  512. switch (irpStack->MinorFunction) {
  513. case IRP_MN_SET_POWER:
  514. if (powerType == DevicePowerState) {
  515. devExt->DeviceState = powerState.DeviceState;
  516. }
  517. case IRP_MN_POWER_SEQUENCE:
  518. case IRP_MN_WAIT_WAKE:
  519. case IRP_MN_QUERY_POWER:
  520. default:
  521. break;
  522. }
  523. PoStartNextPowerIrp(Irp);
  524. IoSkipCurrentIrpStackLocation(Irp);
  525. return PoCallDriver(devExt->TopOfStack, Irp);
  526. }
  527. NTSTATUS
  528. KbFilter_InitializationRoutine(
  529. IN PDEVICE_OBJECT DeviceObject,
  530. IN PVOID SynchFuncContext,
  531. IN PI8042_SYNCH_READ_PORT ReadPort,
  532. IN PI8042_SYNCH_WRITE_PORT WritePort,
  533. OUT PBOOLEAN TurnTranslationOn
  534. )
  535. /*++
  536. Routine Description:
  537. This routine gets called after the following has been performed on the kb
  538. 1) a reset
  539. 2) set the typematic
  540. 3) set the LEDs
  541. i8042prt specific code, if you are writing a packet only filter driver, you
  542. can remove this function
  543. Arguments:
  544. DeviceObject - Context passed during IOCTL_INTERNAL_I8042_HOOK_KEYBOARD
  545. SynchFuncContext - Context to pass when calling Read/WritePort
  546. Read/WritePort - Functions to synchronoulsy read and write to the kb
  547. TurnTranslationOn - If TRUE when this function returns, i8042prt will not
  548. turn on translation on the keyboard
  549. Return Value:
  550. Status is returned.
  551. --*/
  552. {
  553. PDEVICE_EXTENSION devExt;
  554. NTSTATUS status = STATUS_SUCCESS;
  555. devExt = DeviceObject->DeviceExtension;
  556. //
  557. // Do any interesting processing here. We just call any other drivers
  558. // in the chain if they exist. Make Translation is turned on as well
  559. //
  560. if (devExt->UpperInitializationRoutine) {
  561. status = (*devExt->UpperInitializationRoutine) (
  562. devExt->UpperContext,
  563. SynchFuncContext,
  564. ReadPort,
  565. WritePort,
  566. TurnTranslationOn
  567. );
  568. if (!NT_SUCCESS(status)) {
  569. return status;
  570. }
  571. }
  572. *TurnTranslationOn = TRUE;
  573. return status;
  574. }
  575. BOOLEAN
  576. KbFilter_IsrHook(
  577. PDEVICE_OBJECT DeviceObject,
  578. PKEYBOARD_INPUT_DATA CurrentInput,
  579. POUTPUT_PACKET CurrentOutput,
  580. UCHAR StatusByte,
  581. PUCHAR DataByte,
  582. PBOOLEAN ContinueProcessing,
  583. PKEYBOARD_SCAN_STATE ScanState
  584. )
  585. /*++
  586. Routine Description:
  587. This routine gets called at the beginning of processing of the kb interrupt.
  588. i8042prt specific code, if you are writing a packet only filter driver, you
  589. can remove this function
  590. Arguments:
  591. DeviceObject - Our context passed during IOCTL_INTERNAL_I8042_HOOK_KEYBOARD
  592. CurrentInput - Current input packet being formulated by processing all the
  593. interrupts
  594. CurrentOutput - Current list of bytes being written to the keyboard or the
  595. i8042 port.
  596. StatusByte - Byte read from I/O port 60 when the interrupt occurred
  597. DataByte - Byte read from I/O port 64 when the interrupt occurred.
  598. This value can be modified and i8042prt will use this value
  599. if ContinueProcessing is TRUE
  600. ContinueProcessing - If TRUE, i8042prt will proceed with normal processing of
  601. the interrupt. If FALSE, i8042prt will return from the
  602. interrupt after this function returns. Also, if FALSE,
  603. it is this functions responsibilityt to report the input
  604. packet via the function provided in the hook IOCTL or via
  605. queueing a DPC within this driver and calling the
  606. service callback function acquired from the connect IOCTL
  607. Return Value:
  608. Status is returned.
  609. --*/
  610. {
  611. PDEVICE_EXTENSION devExt;
  612. BOOLEAN retVal = TRUE;
  613. devExt = DeviceObject->DeviceExtension;
  614. if (devExt->UpperIsrHook) {
  615. retVal = (*devExt->UpperIsrHook) (
  616. devExt->UpperContext,
  617. CurrentInput,
  618. CurrentOutput,
  619. StatusByte,
  620. DataByte,
  621. ContinueProcessing,
  622. ScanState
  623. );
  624. if (!retVal || !(*ContinueProcessing)) {
  625. return retVal;
  626. }
  627. }
  628. *ContinueProcessing = TRUE;
  629. return retVal;
  630. }
  631. VOID
  632. KbFilter_ServiceCallback(
  633. IN PDEVICE_OBJECT DeviceObject,
  634. IN PKEYBOARD_INPUT_DATA InputDataStart,
  635. IN PKEYBOARD_INPUT_DATA InputDataEnd,
  636. IN OUT PULONG InputDataConsumed
  637. )
  638. /*++
  639. Routine Description:
  640. Called when there are keyboard packets to report to the RIT. You can do
  641. anything you like to the packets. For instance:
  642. o Drop a packet altogether
  643. o Mutate the contents of a packet
  644. o Insert packets into the stream
  645. Arguments:
  646. DeviceObject - Context passed during the connect IOCTL
  647. InputDataStart - First packet to be reported
  648. InputDataEnd - One past the last packet to be reported. Total number of
  649. packets is equal to InputDataEnd - InputDataStart
  650. InputDataConsumed - Set to the total number of packets consumed by the RIT
  651. (via the function pointer we replaced in the connect
  652. IOCTL)
  653. Return Value:
  654. Status is returned.
  655. --*/
  656. {
  657. PDEVICE_EXTENSION devExt;
  658. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  659. (*(PSERVICE_CALLBACK_ROUTINE) devExt->UpperConnectData.ClassService)(
  660. devExt->UpperConnectData.ClassDeviceObject,
  661. InputDataStart,
  662. InputDataEnd,
  663. InputDataConsumed);
  664. }
  665. VOID
  666. KbFilter_Unload(
  667. IN PDRIVER_OBJECT Driver
  668. )
  669. /*++
  670. Routine Description:
  671. Free all the allocated resources associated with this driver.
  672. Arguments:
  673. DriverObject - Pointer to the driver object.
  674. Return Value:
  675. None.
  676. --*/
  677. {
  678. PAGED_CODE();
  679. DebugPrint(("KbFilter_Unload\n"));
  680. UNREFERENCED_PARAMETER(Driver);
  681. ASSERT(NULL == Driver->DeviceObject);
  682. }