Source code of Windows XP (NT5)
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.

1036 lines
27 KiB

  1. /*--
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. neckbadd.c
  5. Abstract:
  6. Environment:
  7. Kernel mode only.
  8. Notes:
  9. Revision History:
  10. --*/
  11. #include "neckbadd.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text (INIT, DriverEntry)
  14. #pragma alloc_text (PAGE, NecKbdCreateClose)
  15. #pragma alloc_text (PAGE, NecKbdInternIoCtl)
  16. #pragma alloc_text (PAGE, NecKbdUnload)
  17. #endif
  18. NTSTATUS
  19. DriverEntry (
  20. IN PDRIVER_OBJECT DriverObject,
  21. IN PUNICODE_STRING RegistryPath
  22. )
  23. /*++
  24. Routine Description:
  25. Initialize the entry points of the driver.
  26. --*/
  27. {
  28. NTSTATUS status = STATUS_SUCCESS;
  29. ULONG i;
  30. UNREFERENCED_PARAMETER (RegistryPath);
  31. //
  32. // Fill in all the dispatch entry points with the pass through function
  33. // and the explicitly fill in the functions we are going to intercept
  34. //
  35. for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
  36. DriverObject->MajorFunction[i] = NecKbdDispatchPassThrough;
  37. }
  38. DriverObject->MajorFunction [IRP_MJ_CREATE] =
  39. DriverObject->MajorFunction [IRP_MJ_CLOSE] = NecKbdCreateClose;
  40. DriverObject->MajorFunction [IRP_MJ_PNP] = NecKbdPnP;
  41. DriverObject->MajorFunction [IRP_MJ_POWER] = NecKbdPower;
  42. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] = NecKbdInternIoCtl;
  43. DriverObject->DriverUnload = NecKbdUnload;
  44. DriverObject->DriverExtension->AddDevice = NecKbdAddDevice;
  45. NecKbdServiceParameters(RegistryPath);
  46. return STATUS_SUCCESS;
  47. }
  48. NTSTATUS
  49. NecKbdAddDevice(
  50. IN PDRIVER_OBJECT Driver,
  51. IN PDEVICE_OBJECT PDO
  52. )
  53. {
  54. PDEVICE_EXTENSION devExt;
  55. IO_ERROR_LOG_PACKET errorLogEntry;
  56. PDEVICE_OBJECT device;
  57. NTSTATUS status = STATUS_SUCCESS;
  58. PAGED_CODE();
  59. status = IoCreateDevice(Driver, // driver
  60. sizeof(DEVICE_EXTENSION), // size of extension
  61. NULL, // device name
  62. FILE_DEVICE_8042_PORT, // device type
  63. 0, // device characteristics
  64. FALSE, // exclusive
  65. &device // new device
  66. );
  67. if (!NT_SUCCESS(status)) {
  68. return (status);
  69. }
  70. RtlZeroMemory(device->DeviceExtension, sizeof(DEVICE_EXTENSION));
  71. devExt = (PDEVICE_EXTENSION) device->DeviceExtension;
  72. devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO);
  73. if (devExt->TopOfStack == NULL) {
  74. IoDeleteDevice(device);
  75. return STATUS_DEVICE_NOT_CONNECTED;
  76. }
  77. ASSERT(devExt->TopOfStack);
  78. devExt->Self = device;
  79. devExt->PDO = PDO;
  80. devExt->DeviceState = PowerDeviceD0;
  81. devExt->Removed = FALSE;
  82. devExt->Started = FALSE;
  83. device->Flags |= DO_BUFFERED_IO;
  84. device->Flags |= DO_POWER_PAGABLE;
  85. device->Flags &= ~DO_DEVICE_INITIALIZING;
  86. return status;
  87. }
  88. NTSTATUS
  89. NecKbdComplete(
  90. IN PDEVICE_OBJECT DeviceObject,
  91. IN PIRP Irp,
  92. IN PVOID Context
  93. )
  94. {
  95. PKEVENT event;
  96. PIO_STACK_LOCATION irpStack;
  97. NTSTATUS status = STATUS_SUCCESS;
  98. event = (PKEVENT) Context;
  99. UNREFERENCED_PARAMETER(DeviceObject);
  100. if (Irp->PendingReturned) {
  101. IoMarkIrpPending(Irp);
  102. }
  103. //
  104. // We could switch on the major and minor functions of the IRP to perform
  105. // different functions, but we know that Context is an event that needs
  106. // to be set.
  107. //
  108. KeSetEvent(event, 0, FALSE);
  109. //
  110. // Allows the caller to use the IRP after it is completed
  111. //
  112. return STATUS_MORE_PROCESSING_REQUIRED;
  113. }
  114. NTSTATUS
  115. NecKbdCreateClose (
  116. IN PDEVICE_OBJECT DeviceObject,
  117. IN PIRP Irp
  118. )
  119. /*++
  120. Routine Description:
  121. Maintain a simple count of the creates and closes sent against this device
  122. --*/
  123. {
  124. PIO_STACK_LOCATION irpStack;
  125. NTSTATUS status = STATUS_SUCCESS;
  126. PDEVICE_EXTENSION devExt;
  127. PAGED_CODE();
  128. irpStack = IoGetCurrentIrpStackLocation(Irp);
  129. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  130. switch (irpStack->MajorFunction) {
  131. case IRP_MJ_CREATE:
  132. if (NULL == devExt->UpperConnectData.ClassService) {
  133. //
  134. // No Connection yet. How can we be enabled?
  135. //
  136. status = STATUS_INVALID_DEVICE_STATE;
  137. }
  138. break;
  139. case IRP_MJ_CLOSE:
  140. break;
  141. }
  142. Irp->IoStatus.Status = status;
  143. //
  144. // Pass on the create and the close
  145. //
  146. return NecKbdDispatchPassThrough(DeviceObject, Irp);
  147. }
  148. NTSTATUS
  149. NecKbdDispatchPassThrough(
  150. IN PDEVICE_OBJECT DeviceObject,
  151. IN PIRP Irp
  152. )
  153. /*++
  154. Routine Description:
  155. Passes a request on to the lower driver.
  156. --*/
  157. {
  158. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  159. //
  160. // Pass the IRP to the target
  161. //
  162. IoSkipCurrentIrpStackLocation(Irp);
  163. return IoCallDriver(
  164. ((PDEVICE_EXTENSION) DeviceObject->DeviceExtension)->TopOfStack,
  165. Irp);
  166. }
  167. NTSTATUS
  168. NecKbdInternIoCtl(
  169. IN PDEVICE_OBJECT DeviceObject,
  170. IN PIRP Irp
  171. )
  172. /*++
  173. Routine Description:
  174. This routine is the dispatch routine for internal device control requests.
  175. Arguments:
  176. DeviceObject - Pointer to the device object.
  177. Irp - Pointer to the request packet.
  178. Return Value:
  179. Status is returned.
  180. --*/
  181. {
  182. PIO_STACK_LOCATION irpStack;
  183. PDEVICE_EXTENSION devExt;
  184. KEVENT event;
  185. PCONNECT_DATA connectData;
  186. PKEYBOARD_TYPEMATIC_PARAMETERS TypematicParameters;
  187. NTSTATUS status = STATUS_SUCCESS;
  188. //
  189. // Get a pointer to the device extension.
  190. //
  191. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  192. //
  193. // Initialize the returned Information field.
  194. //
  195. Irp->IoStatus.Information = 0;
  196. //
  197. // Get a pointer to the current parameters for this request. The
  198. // information is contained in the current stack location.
  199. //
  200. irpStack = IoGetCurrentIrpStackLocation(Irp);
  201. //
  202. // Case on the device control subfunction that is being performed by the
  203. // requestor.
  204. //
  205. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  206. //
  207. // Connect a keyboard class device driver to the port driver.
  208. //
  209. case IOCTL_INTERNAL_KEYBOARD_CONNECT:
  210. //
  211. // Only allow a connection if the keyboard hardware is present.
  212. // Also, only allow one connection.
  213. //
  214. if (devExt->UpperConnectData.ClassService != NULL) {
  215. status = STATUS_SHARING_VIOLATION;
  216. break;
  217. }
  218. else if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
  219. sizeof(CONNECT_DATA)) {
  220. //
  221. // invalid buffer
  222. //
  223. status = STATUS_INVALID_PARAMETER;
  224. break;
  225. }
  226. //
  227. // Copy the connection parameters to the device extension.
  228. //
  229. connectData = ((PCONNECT_DATA)
  230. (irpStack->Parameters.DeviceIoControl.Type3InputBuffer));
  231. devExt->UpperConnectData = *connectData;
  232. connectData->ClassDeviceObject = devExt->Self;
  233. connectData->ClassService = NecKbdServiceCallback;
  234. break;
  235. //
  236. // Disconnect a keyboard class device driver from the port driver.
  237. //
  238. case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
  239. //
  240. // Clear the connection parameters in the device extension.
  241. //
  242. // devExt->UpperConnectData.ClassDeviceObject = NULL;
  243. // devExt->UpperConnectData.ClassService = NULL;
  244. status = STATUS_NOT_IMPLEMENTED;
  245. break;
  246. case IOCTL_KEYBOARD_SET_TYPEMATIC:
  247. //
  248. // Might want to capture these in the future
  249. //
  250. case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
  251. case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
  252. case IOCTL_KEYBOARD_QUERY_INDICATORS:
  253. case IOCTL_KEYBOARD_SET_INDICATORS:
  254. case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
  255. default:
  256. break;
  257. }
  258. if (!NT_SUCCESS(status)) {
  259. return status;
  260. }
  261. return NecKbdDispatchPassThrough(DeviceObject, Irp);
  262. }
  263. NTSTATUS
  264. NecKbdPnP(
  265. IN PDEVICE_OBJECT DeviceObject,
  266. IN PIRP Irp
  267. )
  268. /*++
  269. Routine Description:
  270. This routine is the dispatch routine for plug and play irps
  271. Arguments:
  272. DeviceObject - Pointer to the device object.
  273. Irp - Pointer to the request packet.
  274. Return Value:
  275. Status is returned.
  276. --*/
  277. {
  278. PDEVICE_EXTENSION devExt;
  279. PIO_STACK_LOCATION irpStack;
  280. NTSTATUS status = STATUS_SUCCESS;
  281. KIRQL oldIrql;
  282. KEVENT event;
  283. PAGED_CODE();
  284. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  285. irpStack = IoGetCurrentIrpStackLocation(Irp);
  286. switch (irpStack->MinorFunction) {
  287. case IRP_MN_START_DEVICE: {
  288. //
  289. // The device is starting.
  290. //
  291. // We cannot touch the device (send it any non pnp irps) until a
  292. // start device has been passed down to the lower drivers.
  293. //
  294. IoCopyCurrentIrpStackLocationToNext(Irp);
  295. KeInitializeEvent(&event,
  296. NotificationEvent,
  297. FALSE
  298. );
  299. IoSetCompletionRoutine(Irp,
  300. (PIO_COMPLETION_ROUTINE) NecKbdComplete,
  301. &event,
  302. TRUE,
  303. TRUE,
  304. TRUE); // No need for Cancel
  305. status = IoCallDriver(devExt->TopOfStack, Irp);
  306. if (STATUS_PENDING == status) {
  307. KeWaitForSingleObject(
  308. &event,
  309. Executive, // Waiting for reason of a driver
  310. KernelMode, // Waiting in kernel mode
  311. FALSE, // No allert
  312. NULL); // No timeout
  313. }
  314. if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
  315. //
  316. // As we are successfully now back from our start device
  317. // we can do work.
  318. //
  319. devExt->Started = TRUE;
  320. devExt->Removed = FALSE;
  321. }
  322. //
  323. // We must now complete the IRP, since we stopped it in the
  324. // completetion routine with MORE_PROCESSING_REQUIRED.
  325. //
  326. Irp->IoStatus.Status = status;
  327. Irp->IoStatus.Information = 0;
  328. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  329. break;
  330. }
  331. case IRP_MN_REMOVE_DEVICE:
  332. IoSkipCurrentIrpStackLocation(Irp);
  333. IoCallDriver(devExt->TopOfStack, Irp);
  334. devExt->Removed = TRUE;
  335. IoDetachDevice(devExt->TopOfStack);
  336. IoDeleteDevice(DeviceObject);
  337. status = STATUS_SUCCESS;
  338. break;
  339. case IRP_MN_QUERY_REMOVE_DEVICE:
  340. case IRP_MN_QUERY_STOP_DEVICE:
  341. case IRP_MN_CANCEL_REMOVE_DEVICE:
  342. case IRP_MN_CANCEL_STOP_DEVICE:
  343. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  344. case IRP_MN_STOP_DEVICE:
  345. case IRP_MN_QUERY_DEVICE_RELATIONS:
  346. case IRP_MN_QUERY_INTERFACE:
  347. case IRP_MN_QUERY_CAPABILITIES:
  348. case IRP_MN_QUERY_DEVICE_TEXT:
  349. case IRP_MN_QUERY_RESOURCES:
  350. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  351. case IRP_MN_READ_CONFIG:
  352. case IRP_MN_WRITE_CONFIG:
  353. case IRP_MN_EJECT:
  354. case IRP_MN_SET_LOCK:
  355. case IRP_MN_QUERY_ID:
  356. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  357. default:
  358. //
  359. // Here the filter driver might modify the behavior of these IRPS
  360. // Please see PlugPlay documentation for use of these IRPs.
  361. //
  362. IoSkipCurrentIrpStackLocation(Irp);
  363. status = IoCallDriver(devExt->TopOfStack, Irp);
  364. break;
  365. }
  366. return status;
  367. }
  368. NTSTATUS
  369. NecKbdPower(
  370. IN PDEVICE_OBJECT DeviceObject,
  371. IN PIRP Irp
  372. )
  373. /*++
  374. Routine Description:
  375. This routine is the dispatch routine for power irps Does nothing except
  376. record the state of the device.
  377. Arguments:
  378. DeviceObject - Pointer to the device object.
  379. Irp - Pointer to the request packet.
  380. Return Value:
  381. Status is returned.
  382. --*/
  383. {
  384. PIO_STACK_LOCATION irpStack;
  385. NTSTATUS status;
  386. PDEVICE_EXTENSION devExt;
  387. POWER_STATE powerState;
  388. POWER_STATE_TYPE powerType;
  389. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  390. irpStack = IoGetCurrentIrpStackLocation(Irp);
  391. powerType = irpStack->Parameters.Power.Type;
  392. powerState = irpStack->Parameters.Power.State;
  393. switch (irpStack->MinorFunction) {
  394. case IRP_MN_SET_POWER:
  395. Print(("NecKbdPower:Power Setting %s state to %d\n",
  396. ((powerType == SystemPowerState) ? "System"
  397. : "Device"),
  398. powerState.SystemState));
  399. if (powerType == DevicePowerState) {
  400. devExt->DeviceState = powerState.DeviceState;
  401. }
  402. break;
  403. case IRP_MN_QUERY_POWER:
  404. Print(("NecKbdPower:Power query %s status to %d\n",
  405. ((powerType == SystemPowerState) ? "System"
  406. : "Device"),
  407. powerState.SystemState));
  408. break;
  409. default:
  410. Print(("NecKbdPower:Power minor (0x%x) no known\n",
  411. irpStack->MinorFunction));
  412. break;
  413. }
  414. PoStartNextPowerIrp(Irp);
  415. IoSkipCurrentIrpStackLocation(Irp);
  416. PoCallDriver(devExt->TopOfStack, Irp);
  417. return STATUS_SUCCESS;
  418. }
  419. VOID
  420. NecKbdServiceCallback(
  421. IN PDEVICE_OBJECT DeviceObject,
  422. IN PKEYBOARD_INPUT_DATA InputDataStart,
  423. IN PKEYBOARD_INPUT_DATA InputDataEnd,
  424. IN OUT PULONG InputDataConsumed
  425. )
  426. {
  427. PDEVICE_EXTENSION devExt;
  428. PKEYBOARD_INPUT_DATA CurrentInputData,
  429. CurrentInputDataStart;
  430. KEYBOARD_INPUT_DATA TempInputData[2];
  431. devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  432. RtlZeroMemory(TempInputData, sizeof(KEYBOARD_INPUT_DATA) * 2);
  433. CurrentInputData = CurrentInputDataStart = InputDataStart;
  434. while (CurrentInputData < InputDataEnd) {
  435. // Print(("NecKbdServiceCallBack: captured scancode: 0x%2x(%2x)\n",
  436. // CurrentInputData->MakeCode,
  437. // CurrentInputData->Flags
  438. // ));
  439. if (devExt->KeyStatusFlags & STOP_PREFIX) {
  440. if (((CurrentInputData->MakeCode != NUMLOCK_KEY) ||
  441. ((CurrentInputData->Flags & (KEY_E0|KEY_E1)) != 0) ||
  442. ((CurrentInputData->Flags & KEY_BREAK) != (devExt->CachedInputData.Flags & KEY_BREAK)))) {
  443. Print(("NecKbdServiceCallBack: clearing prefix of STOP(%s)\n",
  444. (CurrentInputData->Flags & KEY_BREAK) ? "Break" : "Make"
  445. ));
  446. //
  447. // send cached input data
  448. //
  449. CLASSSERVICE_CALLBACK(
  450. &(devExt->CachedInputData),
  451. &(devExt->CachedInputData) + 1);
  452. devExt->KeyStatusFlags &= ~STOP_PREFIX;
  453. }
  454. }
  455. switch (CurrentInputData->MakeCode) {
  456. case CAPS_KEY:
  457. case KANA_KEY:
  458. if (CurrentInputData->Flags & (KEY_E0|KEY_E1)) {
  459. break;
  460. }
  461. if (!(CurrentInputData->Flags & KEY_BREAK)) {
  462. Print(("NecKbdServiceCallBack: Captured %s (Make)\n",
  463. ((CurrentInputData->MakeCode == CAPS_KEY) ? "CAPS" : "KANA")
  464. ));
  465. if (((CurrentInputData->MakeCode == CAPS_KEY)&&(devExt->KeyStatusFlags & CAPS_PRESSING))||
  466. ((CurrentInputData->MakeCode == KANA_KEY)&&(devExt->KeyStatusFlags & KANA_PRESSING))) {
  467. //
  468. // ignore repeated make code
  469. //
  470. Print(("NecKbdServiceCallBack: ignoring repeated %s(Break)\n",
  471. ((CurrentInputData->MakeCode == CAPS_KEY) ? "CAPS" : "KANA")
  472. ));
  473. } else {
  474. if (CurrentInputDataStart <= CurrentInputData) {
  475. CLASSSERVICE_CALLBACK(
  476. CurrentInputDataStart,
  477. CurrentInputData + 1);
  478. }
  479. //
  480. // Send break code
  481. //
  482. RtlCopyMemory(
  483. (PCHAR)&(TempInputData[0]),
  484. (PCHAR)CurrentInputData,
  485. sizeof(KEYBOARD_INPUT_DATA)
  486. );
  487. TempInputData[0].Flags |= KEY_BREAK;
  488. Print(("NecKbdServiceCallBack: Sending %s(Break)\n",
  489. ((CurrentInputData->MakeCode == CAPS_KEY) ? "CAPS" : "KANA")
  490. ));
  491. CLASSSERVICE_CALLBACK(
  492. &(TempInputData[0]),
  493. &(TempInputData[1]));
  494. }
  495. if (CurrentInputData->MakeCode == CAPS_KEY) {
  496. devExt->KeyStatusFlags |= CAPS_PRESSING;
  497. } else {
  498. devExt->KeyStatusFlags |= KANA_PRESSING;
  499. }
  500. } else {
  501. //
  502. // Break generates no scancode.
  503. //
  504. Print(("NecKbdServiceCallBack: ignoring %s(Break)\n",
  505. ((CurrentInputData->MakeCode == CAPS_KEY) ? "CAPS" : "KANA")
  506. ));
  507. if (CurrentInputDataStart < CurrentInputData) {
  508. CLASSSERVICE_CALLBACK(
  509. CurrentInputDataStart,
  510. CurrentInputData);
  511. }
  512. if (CurrentInputData->MakeCode == CAPS_KEY) {
  513. devExt->KeyStatusFlags &= ~CAPS_PRESSING;
  514. } else {
  515. devExt->KeyStatusFlags &= ~KANA_PRESSING;
  516. }
  517. }
  518. CurrentInputDataStart = CurrentInputData + 1;
  519. break;
  520. case CTRL_KEY:
  521. if ((CurrentInputData->Flags & (KEY_E0|KEY_E1)) == KEY_E1) {
  522. Print(("NecKbdServiceCallBack: prefix of STOP(%s)\n",
  523. (CurrentInputData->Flags & KEY_BREAK) ? "Break" : "Make"
  524. ));
  525. if (CurrentInputDataStart < CurrentInputData) {
  526. CLASSSERVICE_CALLBACK(
  527. CurrentInputDataStart,
  528. CurrentInputData);
  529. }
  530. RtlCopyMemory(
  531. (PCHAR)&(devExt->CachedInputData),
  532. (PCHAR)CurrentInputData,
  533. sizeof(KEYBOARD_INPUT_DATA)
  534. );
  535. devExt->KeyStatusFlags |= STOP_PREFIX;
  536. CurrentInputDataStart = CurrentInputData + 1;
  537. }
  538. break;
  539. case NUMLOCK_KEY:
  540. if ((CurrentInputData->Flags & (KEY_E0|KEY_E1)) == 0) {
  541. if (devExt->KeyStatusFlags & STOP_PREFIX) {
  542. if ((CurrentInputData->Flags & KEY_BREAK) == (devExt->CachedInputData.Flags & KEY_BREAK)) {
  543. //
  544. // it is STOP key
  545. //
  546. Print(("NecKbdServiceCallBack: Captured STOP(%s)\n",
  547. ((CurrentInputData->Flags & KEY_BREAK) ? "Break" : "Make")
  548. ));
  549. devExt->KeyStatusFlags &= ~STOP_PREFIX;
  550. //
  551. // make packets for 0x1d
  552. //
  553. RtlCopyMemory(
  554. (PCHAR)&(TempInputData[0]),
  555. (PCHAR)CurrentInputData,
  556. sizeof(KEYBOARD_INPUT_DATA)
  557. );
  558. TempInputData[0].MakeCode = CTRL_KEY;
  559. TempInputData[0].Flags &= ~(KEY_E0|KEY_E1);
  560. //
  561. // make packet for 0x46+E0
  562. //
  563. RtlCopyMemory(
  564. (PCHAR)&(TempInputData[1]),
  565. (PCHAR)CurrentInputData,
  566. sizeof(KEYBOARD_INPUT_DATA)
  567. );
  568. TempInputData[1].MakeCode = STOP_KEY;
  569. TempInputData[1].Flags |= KEY_E0;
  570. TempInputData[1].Flags &= ~KEY_E1;
  571. //
  572. // send packets 0x1d, 0x46+E0
  573. //
  574. CLASSSERVICE_CALLBACK(
  575. &(TempInputData[0]),
  576. &(TempInputData[2]));
  577. CurrentInputDataStart = CurrentInputData + 1;
  578. } else {
  579. //
  580. // invalid prefix. send it as is.
  581. //
  582. Print(("NecKbdServiceCallBack: invalid prefix for STOP(%s)\n",
  583. ((CurrentInputData->Flags & KEY_BREAK) ? "Break" : "Make")
  584. ));
  585. }
  586. } else {
  587. //
  588. // it is vf3 key. it behaves as F13 or NumLock
  589. //
  590. Print(("NecKbdServiceCallBack: Captured vf3(VfKeyEmulation is %s)\n",
  591. ((VfKeyEmulation) ? "On" : "Off")
  592. ));
  593. if (!(VfKeyEmulation)) {
  594. CurrentInputData->MakeCode = VF3_KEY;
  595. CurrentInputData->Flags &= ~(KEY_E0|KEY_E1);
  596. }
  597. }
  598. }
  599. break;
  600. //
  601. // ScrollLock can emulate VF4
  602. //
  603. case SCROLL_LOCK_KEY:
  604. if ((CurrentInputData->Flags & (KEY_E0|KEY_E1)) == 0) {
  605. Print(("NecKbdServiceCallBack: Captured vf4(VfKeyEmulation is %s)\n",
  606. ((VfKeyEmulation) ? "On" : "Off")
  607. ));
  608. if (!(VfKeyEmulation)) {
  609. CurrentInputData->MakeCode = VF4_KEY;
  610. CurrentInputData->Flags &= ~(KEY_E0|KEY_E1);
  611. }
  612. }
  613. break;
  614. //
  615. // hankaku/zenkaku can emulate VF5
  616. //
  617. case HANKAKU_ZENKAKU_KEY:
  618. if ((CurrentInputData->Flags & (KEY_E0|KEY_E1)) == 0) {
  619. Print(("NecKbdServiceCallBack: Captured vf5(VfKeyEmulation is %s)\n",
  620. ((VfKeyEmulation) ? "On" : "Off")
  621. ));
  622. if (!(VfKeyEmulation)) {
  623. CurrentInputData->MakeCode = VF5_KEY;
  624. CurrentInputData->Flags &= ~(KEY_E0|KEY_E1);
  625. }
  626. }
  627. break;
  628. //
  629. // the others(sent as is)
  630. //
  631. default:
  632. break;
  633. }
  634. CurrentInputData++;
  635. }
  636. //
  637. // flush InputData
  638. //
  639. if (CurrentInputDataStart < InputDataEnd) {
  640. if (devExt->KeyStatusFlags & STOP_PREFIX) {
  641. CLASSSERVICE_CALLBACK(
  642. CurrentInputDataStart,
  643. InputDataEnd - 1);
  644. } else {
  645. CLASSSERVICE_CALLBACK(
  646. CurrentInputDataStart,
  647. InputDataEnd);
  648. }
  649. }
  650. }
  651. VOID
  652. NecKbdUnload(
  653. IN PDRIVER_OBJECT Driver
  654. )
  655. /*++
  656. Routine Description:
  657. Free all the allocated resources associated with this driver.
  658. Arguments:
  659. DriverObject - Pointer to the driver object.
  660. Return Value:
  661. None.
  662. --*/
  663. {
  664. PAGED_CODE();
  665. ASSERT(NULL == Driver->DeviceObject);
  666. return;
  667. }
  668. VOID
  669. NecKbdServiceParameters(
  670. IN PUNICODE_STRING RegistryPath
  671. )
  672. /*++
  673. Routine Description:
  674. This routine retrieves this driver's service parameters information
  675. from the registry.
  676. Arguments:
  677. RegistryPath - Pointer to the null-terminated Unicode name of the
  678. registry path for this driver.
  679. Return Value:
  680. None.
  681. --*/
  682. {
  683. NTSTATUS Status = STATUS_SUCCESS;
  684. PRTL_QUERY_REGISTRY_TABLE Parameters = NULL;
  685. PWSTR Path = NULL;
  686. UNICODE_STRING ParametersPath;
  687. ULONG QueriedVfKeyEmulation = 0;
  688. ULONG DefaultVfKeyEmulation = 0;
  689. USHORT queries = 1;
  690. PAGED_CODE();
  691. ParametersPath.Buffer = NULL;
  692. //
  693. // Registry path is already null-terminated, so just use it.
  694. //
  695. Path = RegistryPath->Buffer;
  696. if (NT_SUCCESS(Status)) {
  697. //
  698. // Allocate the Rtl query table.
  699. //
  700. Parameters = ExAllocatePool(
  701. PagedPool,
  702. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  703. );
  704. if (!Parameters) {
  705. Print(("NecKbdServiceParameters: couldn't allocate table for Rtl query to %ws for %ws\n",
  706. pwParameters,
  707. Path
  708. ));
  709. Status = STATUS_UNSUCCESSFUL;
  710. } else {
  711. RtlZeroMemory(
  712. Parameters,
  713. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  714. );
  715. //
  716. // Form a path to this driver's Parameters subkey.
  717. //
  718. RtlInitUnicodeString( &ParametersPath, NULL );
  719. ParametersPath.MaximumLength = RegistryPath->Length +
  720. (wcslen(pwParameters) * sizeof(WCHAR) ) + sizeof(UNICODE_NULL);
  721. ParametersPath.Buffer = ExAllocatePool(
  722. PagedPool,
  723. ParametersPath.MaximumLength
  724. );
  725. if (!ParametersPath.Buffer) {
  726. Print(("NecKbdServiceParameters: Couldn't allocate string for path to %ws for %ws\n",
  727. pwParameters,
  728. Path
  729. ));
  730. Status = STATUS_UNSUCCESSFUL;
  731. }
  732. }
  733. }
  734. if (NT_SUCCESS(Status)) {
  735. //
  736. // Form the parameters path.
  737. //
  738. RtlZeroMemory(
  739. ParametersPath.Buffer,
  740. ParametersPath.MaximumLength
  741. );
  742. RtlAppendUnicodeToString(
  743. &ParametersPath,
  744. Path
  745. );
  746. RtlAppendUnicodeToString(
  747. &ParametersPath,
  748. pwParameters
  749. );
  750. //
  751. // Gather all of the "user specified" information from
  752. // the registry.
  753. //
  754. Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  755. Parameters[0].Name = pwVfKeyEmulation;
  756. Parameters[0].EntryContext = &QueriedVfKeyEmulation;
  757. Parameters[0].DefaultType = REG_DWORD;
  758. Parameters[0].DefaultData = &DefaultVfKeyEmulation;
  759. Parameters[0].DefaultLength = sizeof(ULONG);
  760. Status = RtlQueryRegistryValues(
  761. RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  762. ParametersPath.Buffer,
  763. Parameters,
  764. NULL,
  765. NULL
  766. );
  767. if (!NT_SUCCESS(Status)) {
  768. Print(("NecKbdServiceParameters: RtlQueryRegistryValues failed (0x%x)\n", Status));
  769. }
  770. }
  771. if (!NT_SUCCESS(Status)) {
  772. //
  773. // assign driver defaults.
  774. //
  775. VfKeyEmulation = (DefaultVfKeyEmulation == 0) ? FALSE : TRUE;
  776. } else {
  777. VfKeyEmulation = (QueriedVfKeyEmulation == 0) ? FALSE : TRUE;
  778. }
  779. Print(("NecKbdServiceParameters: VfKeyEmulation is %s\n",
  780. VfKeyEmulation ? "Enable" : "Disable"));
  781. //
  782. // Free the allocated memory before returning.
  783. //
  784. if (ParametersPath.Buffer)
  785. ExFreePool(ParametersPath.Buffer);
  786. if (Parameters)
  787. ExFreePool(Parameters);
  788. }