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.

307 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. complete.c
  5. Abstract
  6. Completion routines for the major IRP functions.
  7. Author:
  8. Ervin P.
  9. Environment:
  10. Kernel mode only
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. /*
  15. ********************************************************************************
  16. * HidpSetMaxReportSize
  17. ********************************************************************************
  18. *
  19. * Set the maxReportSize field in the HID device extension
  20. *
  21. */
  22. ULONG HidpSetMaxReportSize(IN FDO_EXTENSION *fdoExtension)
  23. {
  24. PHIDP_DEVICE_DESC deviceDesc = &fdoExtension->deviceDesc;
  25. ULONG i;
  26. /*
  27. * For all reports (of all collections) for this device,
  28. * find the length of the longest one.
  29. */
  30. fdoExtension->maxReportSize = 0;
  31. for (i = 0; i < deviceDesc->ReportIDsLength; i++){
  32. PHIDP_REPORT_IDS reportIdent = &deviceDesc->ReportIDs[i];
  33. PHIDCLASS_COLLECTION collection = GetHidclassCollection(fdoExtension, reportIdent->CollectionNumber);
  34. if (collection){
  35. if (reportIdent->InputLength > fdoExtension->maxReportSize){
  36. fdoExtension->maxReportSize = reportIdent->InputLength;
  37. }
  38. }
  39. }
  40. DBGASSERT(fdoExtension->maxReportSize,
  41. ("Input length is zero for fdo %x.", fdoExtension->fdo),
  42. FALSE)
  43. return fdoExtension->maxReportSize;
  44. }
  45. /*
  46. ********************************************************************************
  47. * CompleteAllPendingReadsForFileExtension
  48. ********************************************************************************
  49. *
  50. *
  51. */
  52. VOID CompleteAllPendingReadsForFileExtension(
  53. PHIDCLASS_COLLECTION Collection,
  54. PHIDCLASS_FILE_EXTENSION fileExtension)
  55. {
  56. LIST_ENTRY irpsToComplete;
  57. PIRP irp;
  58. KIRQL oldIrql;
  59. ASSERT(fileExtension->Signature == HIDCLASS_FILE_EXTENSION_SIG);
  60. /*
  61. * Move the IRPs to a private queue before completing so they don't
  62. * get requeued on the completion thread, causing us to spin forever.
  63. */
  64. InitializeListHead(&irpsToComplete);
  65. LockFileExtension(fileExtension, &oldIrql);
  66. while (irp = DequeueInterruptReadIrp(Collection, fileExtension)){
  67. //
  68. // Irps are created from nonpaged pool,
  69. // so this is ok to call at Dispatch level.
  70. //
  71. InsertTailList(&irpsToComplete, &irp->Tail.Overlay.ListEntry);
  72. }
  73. UnlockFileExtension(fileExtension, oldIrql);
  74. /*
  75. * Complete all the dequeued read IRPs.
  76. */
  77. while (!IsListEmpty(&irpsToComplete)){
  78. PLIST_ENTRY listEntry = RemoveHeadList(&irpsToComplete);
  79. irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
  80. irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
  81. DBGVERBOSE(("Aborting pending read with status=%xh.", irp->IoStatus.Status))
  82. DBG_RECORD_READ(irp, 0, 0, TRUE)
  83. IoCompleteRequest(irp, IO_NO_INCREMENT);
  84. }
  85. }
  86. /*
  87. ********************************************************************************
  88. * CompleteAllPendingReadsForCollection
  89. ********************************************************************************
  90. *
  91. *
  92. */
  93. VOID CompleteAllPendingReadsForCollection(PHIDCLASS_COLLECTION Collection)
  94. {
  95. LIST_ENTRY tmpList;
  96. PLIST_ENTRY listEntry;
  97. KIRQL oldIrql;
  98. InitializeListHead(&tmpList);
  99. KeAcquireSpinLock(&Collection->FileExtensionListSpinLock, &oldIrql);
  100. /*
  101. * We want to process each fileExtension in the list once.
  102. * But we can't keep track of where to stop by just remembering
  103. * the first item because fileExtensions can get closed while
  104. * we're completing the reads. So copy all the file extensions
  105. * to a temporary list first.
  106. *
  107. * This can all probably get removed, since this only gets called
  108. * on a remove, when a create can not be received. In addition,
  109. * we would have received all close irps since remove only gets
  110. * sent when all closes have come through.
  111. *
  112. */
  113. while (!IsListEmpty(&Collection->FileExtensionList)){
  114. listEntry = RemoveHeadList(&Collection->FileExtensionList);
  115. InsertTailList(&tmpList, listEntry);
  116. }
  117. /*
  118. * Now put the fileExtensions back in the list
  119. * and cancel the reads on each file extension.
  120. */
  121. while (!IsListEmpty(&tmpList)){
  122. PHIDCLASS_FILE_EXTENSION fileExtension;
  123. listEntry = RemoveHeadList(&tmpList);
  124. /*
  125. * Put the fileExtension back in FileExtensionList first
  126. * so that it's there in case we get the close while
  127. * completing the pending irps.
  128. */
  129. InsertTailList(&Collection->FileExtensionList, listEntry);
  130. fileExtension = CONTAINING_RECORD(listEntry, HIDCLASS_FILE_EXTENSION, FileList);
  131. /*
  132. * We will be completing IRPs for this fileExtension.
  133. * Always release all spinlocks before calling outside the driver.
  134. */
  135. KeReleaseSpinLock(&Collection->FileExtensionListSpinLock, oldIrql);
  136. CompleteAllPendingReadsForFileExtension(Collection, fileExtension);
  137. KeAcquireSpinLock(&Collection->FileExtensionListSpinLock, &oldIrql);
  138. }
  139. KeReleaseSpinLock(&Collection->FileExtensionListSpinLock, oldIrql);
  140. }
  141. /*
  142. ********************************************************************************
  143. * CompleteAllPendingReadsForDevice
  144. ********************************************************************************
  145. *
  146. *
  147. */
  148. VOID CompleteAllPendingReadsForDevice(FDO_EXTENSION *fdoExt)
  149. {
  150. PHIDP_DEVICE_DESC deviceDesc = &fdoExt->deviceDesc;
  151. ULONG i;
  152. for (i = 0; i < deviceDesc->CollectionDescLength; i++){
  153. PHIDCLASS_COLLECTION collection = &fdoExt->classCollectionArray[i];
  154. CompleteAllPendingReadsForCollection(collection);
  155. }
  156. }
  157. /*
  158. ********************************************************************************
  159. * HidpFreePowerEvent
  160. ********************************************************************************
  161. *
  162. *
  163. */
  164. VOID
  165. HidpFreePowerEventIrp(
  166. PHIDCLASS_COLLECTION Collection
  167. )
  168. {
  169. PIRP powerEventIrpToComplete = NULL;
  170. KIRQL oldIrql;
  171. /*
  172. * If a power event IRP is queued for this collection,
  173. * fail it now.
  174. */
  175. KeAcquireSpinLock(&Collection->powerEventSpinLock, &oldIrql);
  176. if (ISPTR(Collection->powerEventIrp)){
  177. PDRIVER_CANCEL oldCancelRoutine;
  178. powerEventIrpToComplete = Collection->powerEventIrp;
  179. oldCancelRoutine = IoSetCancelRoutine(powerEventIrpToComplete, NULL);
  180. if (oldCancelRoutine){
  181. ASSERT(oldCancelRoutine == PowerEventCancelRoutine);
  182. }
  183. else {
  184. /*
  185. * The IRP was cancelled and the cancel routine WAS called.
  186. * The cancel routine will complete the IRP as soon as we drop the spinlock,
  187. * so don't touch the IRP.
  188. */
  189. ASSERT(powerEventIrpToComplete->Cancel);
  190. powerEventIrpToComplete = NULL;
  191. }
  192. Collection->powerEventIrp = BAD_POINTER;
  193. }
  194. KeReleaseSpinLock(&Collection->powerEventSpinLock, oldIrql);
  195. if (powerEventIrpToComplete){
  196. powerEventIrpToComplete->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
  197. *(PULONG)powerEventIrpToComplete->AssociatedIrp.SystemBuffer = 0;
  198. powerEventIrpToComplete->IoStatus.Information = 0;
  199. IoCompleteRequest(powerEventIrpToComplete, IO_NO_INCREMENT);
  200. }
  201. }
  202. /*
  203. ********************************************************************************
  204. * HidpDestroyCollection
  205. ********************************************************************************
  206. *
  207. *
  208. */
  209. VOID HidpDestroyCollection(FDO_EXTENSION *fdoExt, PHIDCLASS_COLLECTION Collection)
  210. {
  211. #if DBG
  212. static int reentrancyCounter = 0;
  213. if (reentrancyCounter++ != 0) TRAP;
  214. ASSERT(Collection->Signature == HIDCLASS_COLLECTION_SIG);
  215. #endif
  216. CompleteAllPendingReadsForCollection(Collection);
  217. if (Collection->hidCollectionInfo.Polled){
  218. StopPollingLoop(Collection, TRUE);
  219. }
  220. HidpFreePowerEventIrp(Collection);
  221. #if DBG
  222. Collection->Signature = ~HIDCLASS_COLLECTION_SIG;
  223. reentrancyCounter--;
  224. #endif
  225. }
  226. /*
  227. ********************************************************************************
  228. * HidpQueryCapsCompletion
  229. ********************************************************************************
  230. *
  231. *
  232. */
  233. NTSTATUS HidpQueryCapsCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
  234. {
  235. PKEVENT event = Context;
  236. DBG_COMMON_ENTRY()
  237. KeSetEvent(event, 1, FALSE);
  238. DBG_COMMON_EXIT()
  239. return STATUS_MORE_PROCESSING_REQUIRED;
  240. }