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.

283 lines
7.5 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. Create.c
  5. Abstract:
  6. This module contains the code for IRP_MJ_CREATE and IRP_MJ_CLOSE
  7. and IRP_MJ_DEVICE_CONTROL
  8. Environment:
  9. Kernel & user mode
  10. Revision History:
  11. Nov-96 : Created by Kenneth D. Ray
  12. --*/
  13. #include "kbdhid.h"
  14. NTSTATUS
  15. KbdHid_CreateComplete (
  16. IN PDEVICE_OBJECT DeviceObject,
  17. IN PIRP Irp,
  18. IN PVOID Context
  19. )
  20. /*++
  21. Routine Description:
  22. The pnp IRP is in the process of completing.
  23. signal
  24. Arguments:
  25. Context set to the device object in question.
  26. --*/
  27. {
  28. PIO_STACK_LOCATION stack;
  29. UNREFERENCED_PARAMETER (DeviceObject);
  30. stack = IoGetCurrentIrpStackLocation (Irp);
  31. if (Irp->PendingReturned) {
  32. IoMarkIrpPending( Irp );
  33. }
  34. KeSetEvent ((PKEVENT) Context, 0, FALSE);
  35. return STATUS_MORE_PROCESSING_REQUIRED;
  36. }
  37. NTSTATUS
  38. KbdHid_Create (
  39. IN PDEVICE_OBJECT DeviceObject, // the kbdhid device object
  40. IN PIRP Irp
  41. )
  42. /*++
  43. Routine Description:
  44. This is the dispatch routine for create/open requests. This request
  45. completes successfully, unless the filename's length is non-zero.
  46. Arguments:
  47. DeviceObject - Pointer to the device object.
  48. Irp - Pointer to the request packet.
  49. Return Value:
  50. NT status code.
  51. --*/
  52. {
  53. PIO_STACK_LOCATION irpSp = NULL;
  54. NTSTATUS status = STATUS_SUCCESS;
  55. PDEVICE_EXTENSION data = NULL;
  56. KEVENT event;
  57. Print(DBG_CC_TRACE, ("DispatchCreate: Enter.\n"));
  58. data = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  59. //
  60. // Get a pointer to the current parameters for this request. The
  61. // information is contained in the current stack location.
  62. //
  63. irpSp = IoGetCurrentIrpStackLocation (Irp);
  64. //
  65. // Determine if request is trying to open a subdirectory of the
  66. // given device object. This is not allowed.
  67. //
  68. if (0 != irpSp->FileObject->FileName.Length) {
  69. Print(DBG_CC_ERROR, ("ERROR: Create Access Denied.\n"));
  70. status = STATUS_ACCESS_DENIED;
  71. goto KbdHid_CreateReject;
  72. }
  73. status = IoAcquireRemoveLock (&data->RemoveLock, Irp);
  74. if (!NT_SUCCESS (status)) {
  75. goto KbdHid_CreateReject;
  76. }
  77. ExAcquireFastMutex (&data->CreateCloseMutex);
  78. if (NULL == data->ConnectData.ClassService) {
  79. //
  80. // No Connection yet. How can we be enabled?
  81. //
  82. Print (DBG_IOCTL_ERROR, ("ERROR: enable before connect!\n"));
  83. status = STATUS_UNSUCCESSFUL;
  84. } else {
  85. IoCopyCurrentIrpStackLocationToNext (Irp);
  86. KeInitializeEvent(&event, NotificationEvent, FALSE);
  87. IoSetCompletionRoutine (Irp,
  88. KbdHid_CreateComplete,
  89. &event,
  90. TRUE,
  91. TRUE,
  92. TRUE);
  93. status = IoCallDriver (data->TopOfStack, Irp);
  94. if (STATUS_PENDING == status) {
  95. KeWaitForSingleObject(&event,
  96. Executive, // Waiting for reason of a driver
  97. KernelMode, // Waiting in kernel mode
  98. FALSE, // No allert
  99. NULL); // No timeout
  100. }
  101. if (NT_SUCCESS (status)) {
  102. status = Irp->IoStatus.Status;
  103. }
  104. if (NT_SUCCESS (status)) {
  105. InterlockedIncrement(&data->EnableCount);
  106. if (NULL == data->ReadFile &&
  107. (irpSp->Parameters.Create.SecurityContext->DesiredAccess & FILE_READ_DATA)) {
  108. //
  109. // We want to start the read pump.
  110. //
  111. Print (DBG_IOCTL_INFO, ("Enabling Keyboard \n"));
  112. data->ReadFile = irpSp->FileObject;
  113. KeResetEvent (&data->ReadCompleteEvent);
  114. data->ReadInterlock = KBDHID_END_READ;
  115. // Acquire another time for the read irp.
  116. IoAcquireRemoveLock (&data->RemoveLock, data->ReadIrp);
  117. data->ReadIrp->IoStatus.Status = STATUS_SUCCESS;
  118. status = KbdHid_StartRead (data);
  119. if (STATUS_PENDING == status) {
  120. status = STATUS_SUCCESS;
  121. } else if (!NT_SUCCESS(status)) {
  122. //
  123. // Set it back to NULL so that a future open tries again.
  124. // Read should not fail if open passed. ASSERT!
  125. //
  126. ASSERT(NT_SUCCESS(status));
  127. data->ReadFile = NULL;
  128. }
  129. }
  130. ASSERT (data->EnableCount < 100);
  131. ASSERT (0 < data->EnableCount);
  132. }
  133. }
  134. ExReleaseFastMutex (&data->CreateCloseMutex);
  135. Irp->IoStatus.Status = status;
  136. Irp->IoStatus.Information = 0;
  137. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  138. IoReleaseRemoveLock (&data->RemoveLock, Irp);
  139. Print(DBG_CC_TRACE, ("DispatchCreate: Exit (%x).\n", status));
  140. return status;
  141. KbdHid_CreateReject:
  142. Irp->IoStatus.Status = status;
  143. Irp->IoStatus.Information = 0;
  144. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  145. Print(DBG_CC_TRACE, ("DispatchCreate: Exit (%x).\n", status));
  146. return status;
  147. }
  148. NTSTATUS
  149. KbdHid_Close (
  150. IN PDEVICE_OBJECT DeviceObject, // the kbdhid device object
  151. IN PIRP Irp
  152. )
  153. /*++
  154. Routine Description:
  155. This is the dispatch routine for close requests. This request
  156. completes successfully, unless the file name length is zero.
  157. Arguments:
  158. DeviceObject - Pointer to the device object.
  159. Irp - Pointer to the request packet.
  160. Return Value:
  161. NT status code.
  162. --*/
  163. {
  164. PDEVICE_EXTENSION data;
  165. PIO_STACK_LOCATION stack;
  166. LARGE_INTEGER time;
  167. Print(DBG_CC_TRACE, ("DispatchClose: Enter\n"));
  168. data = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  169. stack = IoGetCurrentIrpStackLocation (Irp);
  170. ExAcquireFastMutex (&data->CreateCloseMutex);
  171. ASSERT (data->EnableCount < 100);
  172. ASSERT (0 < data->EnableCount);
  173. if (0 == InterlockedDecrement(&data->EnableCount)) {
  174. Print (DBG_IOCTL_INFO, ("Disabling Keyboard \n"));
  175. KeWaitForSingleObject (&data->ReadSentEvent,
  176. Executive,
  177. KernelMode,
  178. FALSE,
  179. NULL
  180. );
  181. if (IoCancelIrp (data->ReadIrp)) {
  182. KeWaitForSingleObject (&data->ReadCompleteEvent,
  183. Executive,
  184. KernelMode,
  185. FALSE,
  186. NULL
  187. );
  188. }
  189. ASSERT (NULL != data->ReadFile);
  190. // ASSERT (data->ReadFile == stack->FileObject);
  191. time = data->AutoRepeatDelay;
  192. KeCancelTimer (&data->AutoRepeatTimer);
  193. #if KEYBOARD_HW_CHATTERY_FIX
  194. KeCancelTimer (&data->InitiateStartReadTimer);
  195. //
  196. // NB the time is a negative (relative) number;
  197. //
  198. if (data->InitiateStartReadDelay.QuadPart < time.QuadPart) {
  199. time = data->InitiateStartReadDelay;
  200. }
  201. #endif // KEYBOARD_HW_CHATTERY_FIX
  202. time.QuadPart *= 2;
  203. KeDelayExecutionThread (KernelMode, FALSE, &time);
  204. data->ReadFile = NULL;
  205. }
  206. ExReleaseFastMutex (&data->CreateCloseMutex);
  207. IoSkipCurrentIrpStackLocation (Irp);
  208. Print(DBG_CC_TRACE, ("DispatchClose: Exit \n"));
  209. return IoCallDriver (data->TopOfStack, Irp);
  210. }