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.

632 lines
20 KiB

  1. #include "precomp.h" // Precompiled header
  2. /************************************************************************/
  3. /* */
  4. /* Title : Specialix Generic Dispatch Functions. */
  5. /* */
  6. /* Author : N.P.Vassallo */
  7. /* */
  8. /* Creation : 29th September 1998 */
  9. /* */
  10. /* Version : 1.0.0 */
  11. /* */
  12. /* Description : Dispatch entry points are routed here */
  13. /* for PnP/Power filtering before being */
  14. /* passed to the main functions: */
  15. /* Spx_Flush */
  16. /* Spx_Write */
  17. /* Spx_Read */
  18. /* Spx_IoControl */
  19. /* Spx_InternalIoControl */
  20. /* Spx_CreateOpen */
  21. /* Spx_Close */
  22. /* Spx_Cleanup */
  23. /* Spx_QueryInformationFile */
  24. /* Spx_SetInformationFile */
  25. /* */
  26. /* Spx_UnstallIRPs */
  27. /* Spx_KillStalledIRPs */
  28. /* */
  29. /************************************************************************/
  30. /* History...
  31. 1.0.0 29/09/98 NPV Creation.
  32. */
  33. #define FILE_ID SPX_DISP_C // File ID for Event Logging see SPX_DEFS.H for values.
  34. /*****************************************************************************
  35. ******************************* *******************************
  36. ******************************* Prototypes *******************************
  37. ******************************* *******************************
  38. *****************************************************************************/
  39. NTSTATUS Spx_FilterIRPs(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp);
  40. VOID Spx_FilterCancelQueued(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);
  41. /*****************************************************************************
  42. ******************************** Spx_Flush *******************************
  43. *****************************************************************************/
  44. NTSTATUS Spx_Flush(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  45. {
  46. NTSTATUS status;
  47. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  48. {
  49. pIrp->IoStatus.Status = status;
  50. if(status != STATUS_PENDING)
  51. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  52. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  53. ClearUnstallingFlag(pDevObject->DeviceExtension);
  54. }
  55. else
  56. status = SerialFlush(pDevObject,pIrp);
  57. return(status);
  58. } // End Spx_Flush
  59. /*****************************************************************************
  60. ******************************** Spx_Write *******************************
  61. *****************************************************************************/
  62. NTSTATUS Spx_Write(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  63. {
  64. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  65. NTSTATUS status;
  66. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  67. {
  68. pIrp->IoStatus.Status = status;
  69. if(status != STATUS_PENDING)
  70. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  71. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  72. ClearUnstallingFlag(pDevObject->DeviceExtension);
  73. }
  74. else
  75. status = SerialWrite(pDevObject,pIrp);
  76. return(status);
  77. } // End Spx_Write
  78. /*****************************************************************************
  79. ******************************** Spx_Read ********************************
  80. *****************************************************************************/
  81. NTSTATUS Spx_Read(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  82. {
  83. NTSTATUS status;
  84. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  85. {
  86. pIrp->IoStatus.Status = status;
  87. if(status != STATUS_PENDING)
  88. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  89. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  90. ClearUnstallingFlag(pDevObject->DeviceExtension);
  91. }
  92. else
  93. status = SerialRead(pDevObject,pIrp);
  94. return(status);
  95. } // End Spx_Read
  96. /*****************************************************************************
  97. ****************************** Spx_IoControl *****************************
  98. *****************************************************************************/
  99. NTSTATUS Spx_IoControl(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  100. {
  101. NTSTATUS status;
  102. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  103. {
  104. pIrp->IoStatus.Status = status;
  105. if(status != STATUS_PENDING)
  106. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  107. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  108. ClearUnstallingFlag(pDevObject->DeviceExtension);
  109. }
  110. else
  111. status = SerialIoControl(pDevObject,pIrp);
  112. return(status);
  113. } // End Spx_IoControl
  114. /*****************************************************************************
  115. ************************** Spx_InternalIoControl *************************
  116. *****************************************************************************/
  117. NTSTATUS Spx_InternalIoControl(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  118. {
  119. NTSTATUS status;
  120. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  121. {
  122. pIrp->IoStatus.Status = status;
  123. if(status != STATUS_PENDING)
  124. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  125. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  126. ClearUnstallingFlag(pDevObject->DeviceExtension);
  127. }
  128. else
  129. status = Spx_SerialInternalIoControl(pDevObject,pIrp);
  130. return(status);
  131. } // Spx_InternalIoControl
  132. /*****************************************************************************
  133. ***************************** Spx_CreateOpen *****************************
  134. *****************************************************************************/
  135. NTSTATUS Spx_CreateOpen(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  136. {
  137. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  138. NTSTATUS status;
  139. if(pDevObject->DeviceType != FILE_DEVICE_SERIAL_PORT)
  140. {
  141. pIrp->IoStatus.Status = STATUS_ACCESS_DENIED;
  142. pIrp->IoStatus.Information = 0;
  143. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  144. return(STATUS_ACCESS_DENIED);
  145. }
  146. // Lock out state Query stop and Query remove IRPs from changing the state
  147. // of the port part way through openening the port.
  148. ExAcquireFastMutex(&pPort->OpenMutex);
  149. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  150. {
  151. pIrp->IoStatus.Status = status;
  152. if(status != STATUS_PENDING)
  153. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  154. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  155. ClearUnstallingFlag(pDevObject->DeviceExtension);
  156. }
  157. else
  158. {
  159. if(pPort->DeviceIsOpen) // Is port already open?
  160. {
  161. status = STATUS_ACCESS_DENIED; // Yes, deny access
  162. pIrp->IoStatus.Status = status;
  163. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  164. }
  165. else
  166. status = SerialCreateOpen(pDevObject,pIrp);
  167. }
  168. ExReleaseFastMutex(&pPort->OpenMutex);
  169. return(status);
  170. } // End Spx_CreateOpen
  171. /*****************************************************************************
  172. ******************************** Spx_Close *******************************
  173. *****************************************************************************/
  174. NTSTATUS Spx_Close(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  175. {
  176. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  177. NTSTATUS status;
  178. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  179. {
  180. if(status == STATUS_DELETE_PENDING) // Successful close if device is removed
  181. {
  182. pPort->BufferSize = 0;
  183. SpxFreeMem(pPort->InterruptReadBuffer);
  184. pPort->InterruptReadBuffer = NULL;
  185. status = STATUS_SUCCESS;
  186. }
  187. pIrp->IoStatus.Status = status;
  188. if(status != STATUS_PENDING)
  189. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  190. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  191. ClearUnstallingFlag(pDevObject->DeviceExtension);
  192. }
  193. else
  194. status = SerialClose(pDevObject,pIrp);
  195. return(status);
  196. } // End Spx_Close
  197. /*****************************************************************************
  198. ******************************* Spx_Cleanup ******************************
  199. *****************************************************************************/
  200. NTSTATUS Spx_Cleanup(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  201. {
  202. NTSTATUS status;
  203. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  204. {
  205. if(status == STATUS_DELETE_PENDING)
  206. {
  207. status = STATUS_SUCCESS;
  208. }
  209. pIrp->IoStatus.Status = status;
  210. if(status != STATUS_PENDING)
  211. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  212. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  213. ClearUnstallingFlag(pDevObject->DeviceExtension);
  214. }
  215. else
  216. {
  217. Spx_KillStalledIRPs(pDevObject);
  218. status = SerialCleanup(pDevObject,pIrp);
  219. }
  220. return(status);
  221. } // End Spx_Cleanup
  222. /*****************************************************************************
  223. ************************ Spx_QueryInformationFile ************************
  224. *****************************************************************************/
  225. NTSTATUS Spx_QueryInformationFile(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  226. {
  227. NTSTATUS status;
  228. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  229. {
  230. pIrp->IoStatus.Status = status;
  231. if(status != STATUS_PENDING)
  232. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  233. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  234. ClearUnstallingFlag(pDevObject->DeviceExtension);
  235. }
  236. else status = SerialQueryInformationFile(pDevObject,pIrp);
  237. return(status);
  238. } // End Spx_QueryInformationFile
  239. /*****************************************************************************
  240. ************************* Spx_SetInformationFile *************************
  241. *****************************************************************************/
  242. NTSTATUS Spx_SetInformationFile(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  243. {
  244. NTSTATUS status;
  245. if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
  246. {
  247. pIrp->IoStatus.Status = status;
  248. if(status != STATUS_PENDING)
  249. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  250. if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
  251. ClearUnstallingFlag(pDevObject->DeviceExtension);
  252. }
  253. else
  254. status = SerialSetInformationFile(pDevObject,pIrp);
  255. return(status);
  256. } // End Spx_SetInformationFile
  257. /*****************************************************************************
  258. ***************************** *****************************
  259. ***************************** Spx_FilterIRPs *****************************
  260. ***************************** *****************************
  261. ******************************************************************************
  262. prototype: NTSTATUS Spx_FilterIRPs(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  263. description: Filter incoming SERIAL IRPs (except PNP and POWER) to check
  264. the current PNP/POWER states and return an NT status code to
  265. just complete the IRP if device is blocked for the following reasons:
  266. parameters: pDevObject points to the device object for this IRP
  267. pIrp points to the IRP to filter
  268. returns: NT Status Code
  269. */
  270. NTSTATUS Spx_FilterIRPs(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
  271. {
  272. PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
  273. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  274. KIRQL oldIrqlFlags;
  275. KIRQL StalledOldIrql;
  276. LARGE_INTEGER delay;
  277. if(pIrpStack->MajorFunction == IRP_MJ_PNP) // Don't filter Plug and Play IRPs
  278. return(STATUS_SUCCESS);
  279. if(pIrpStack->MajorFunction == IRP_MJ_POWER) // Don't filter Plug and Play IRPs
  280. return(STATUS_SUCCESS);
  281. if(pIrpStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL) // Don't filter WMI IRPs
  282. return(STATUS_SUCCESS);
  283. if(pPort->IsFDO) // Don't filter card IRPs
  284. return(STATUS_SUCCESS);
  285. if(pIrpStack->MajorFunction != IRP_MJ_PNP)
  286. {
  287. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X\n",
  288. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
  289. }
  290. KeAcquireSpinLock(&pPort->PnpPowerFlagsLock, &oldIrqlFlags);
  291. if(pPort->PnpPowerFlags & PPF_REMOVED) // Has this object been "removed"?
  292. {
  293. KeReleaseSpinLock(&pPort->PnpPowerFlagsLock,oldIrqlFlags);
  294. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_SUCCESS\n",
  295. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
  296. return(STATUS_NO_SUCH_DEVICE);
  297. }
  298. if(pPort->PnpPowerFlags & PPF_REMOVE_PENDING) // Removing the device?
  299. {
  300. KeReleaseSpinLock(&pPort->PnpPowerFlagsLock,oldIrqlFlags);
  301. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_DELETE_PENDING\n",
  302. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
  303. return(STATUS_DELETE_PENDING);
  304. }
  305. if((pPort->PnpPowerFlags & PPF_STOP_PENDING) // Device stopping?
  306. ||(!(pPort->PnpPowerFlags & PPF_POWERED)) // Device not powered?
  307. ||(!(pPort->PnpPowerFlags & PPF_STARTED))) // Device not started?
  308. {
  309. KIRQL oldIrql;
  310. KeReleaseSpinLock(&pPort->PnpPowerFlagsLock,oldIrqlFlags);
  311. KeAcquireSpinLock(&pPort->StalledIrpLock, &StalledOldIrql);
  312. while(pPort->UnstallingFlag) // We do not wish to add any more IRPs to the queue if have started unstalling those currently queued.
  313. {
  314. KeReleaseSpinLock(&pPort->StalledIrpLock, StalledOldIrql);
  315. delay = RtlLargeIntegerNegate(RtlConvertUlongToLargeInteger(1000000)); // 1mS
  316. KeDelayExecutionThread(KernelMode, FALSE, &delay);
  317. KeAcquireSpinLock(&pPort->StalledIrpLock, &StalledOldIrql);
  318. }
  319. pPort->UnstallingFlag = TRUE;
  320. KeReleaseSpinLock(&pPort->StalledIrpLock, StalledOldIrql);
  321. IoAcquireCancelSpinLock(&oldIrql);
  322. if(pIrp->Cancel) // Has IRP been cancelled?
  323. { // Yes
  324. IoReleaseCancelSpinLock(oldIrql);
  325. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_CANCELLED\n",
  326. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
  327. return(STATUS_CANCELLED);
  328. }
  329. // Mark the IRP as pending and queue on the stalled list...
  330. pIrp->IoStatus.Status = STATUS_PENDING; // Mark IRP as pending
  331. IoMarkIrpPending(pIrp);
  332. InsertTailList(&pPort->StalledIrpQueue,&pIrp->Tail.Overlay.ListEntry);
  333. IoSetCancelRoutine(pIrp,Spx_FilterCancelQueued);
  334. IoReleaseCancelSpinLock(oldIrql);
  335. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_PENDING\n",
  336. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
  337. return(STATUS_PENDING);
  338. }
  339. KeReleaseSpinLock(&pPort->PnpPowerFlagsLock,oldIrqlFlags);
  340. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_SUCCESS\n",
  341. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
  342. return(STATUS_SUCCESS);
  343. } // End Spx_FilterIRPs
  344. /*****************************************************************************
  345. ***************************** ****************************
  346. ***************************** Spx_UnstallIRPs ****************************
  347. ***************************** ****************************
  348. ******************************************************************************
  349. prototype: VOID Spx_UnstallIrps(IN PPORT_DEVICE_EXTENSION pPort)
  350. description: Restart all IRPs stored on the temporary stalled list.
  351. parameters: pPort points to the device extension to unstall
  352. returns: None
  353. */
  354. VOID Spx_UnstallIrps(IN PPORT_DEVICE_EXTENSION pPort)
  355. {
  356. PLIST_ENTRY pIrpLink;
  357. PIRP pIrp;
  358. PIO_STACK_LOCATION pIrpStack;
  359. PDEVICE_OBJECT pDevObj;
  360. PDRIVER_OBJECT pDrvObj;
  361. KIRQL oldIrql;
  362. KIRQL StalledOldIrql;
  363. LARGE_INTEGER delay;
  364. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_UnstallIRPs Entry\n",
  365. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber));
  366. KeAcquireSpinLock(&pPort->StalledIrpLock, &StalledOldIrql);
  367. while(pPort->UnstallingFlag) // We do not unstall any queued IRPs if some one is just about to be added to the queue.
  368. {
  369. KeReleaseSpinLock(&pPort->StalledIrpLock, StalledOldIrql);
  370. delay = RtlLargeIntegerNegate(RtlConvertUlongToLargeInteger(1000000)); // 1mS
  371. KeDelayExecutionThread(KernelMode, FALSE, &delay);
  372. KeAcquireSpinLock(&pPort->StalledIrpLock, &StalledOldIrql);
  373. }
  374. pPort->UnstallingFlag = TRUE;
  375. KeReleaseSpinLock(&pPort->StalledIrpLock, StalledOldIrql);
  376. IoAcquireCancelSpinLock(&oldIrql);
  377. pIrpLink = pPort->StalledIrpQueue.Flink;
  378. // Restart each waiting IRP on the stalled list...
  379. while(pIrpLink != &pPort->StalledIrpQueue)
  380. {
  381. pIrp = CONTAINING_RECORD(pIrpLink,IRP,Tail.Overlay.ListEntry);
  382. pIrpLink = pIrp->Tail.Overlay.ListEntry.Flink;
  383. RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
  384. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  385. pDevObj = pIrpStack->DeviceObject;
  386. pDrvObj = pDevObj->DriverObject;
  387. IoSetCancelRoutine(pIrp,NULL);
  388. IoReleaseCancelSpinLock(oldIrql);
  389. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Unstalling IRP 0x%X, Major %02X, Minor %02X\n",
  390. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,
  391. pIrp,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
  392. pDrvObj->MajorFunction[pIrpStack->MajorFunction](pDevObj,pIrp);
  393. IoAcquireCancelSpinLock(&oldIrql);
  394. }
  395. IoReleaseCancelSpinLock(oldIrql);
  396. ClearUnstallingFlag(pPort);
  397. SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_UnstallIRPs Exit\n",
  398. PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber));
  399. } // End Spx_UnstallIRPs
  400. /*****************************************************************************
  401. ************************* *************************
  402. ************************* Spx_FilterCancelQueued *************************
  403. ************************* *************************
  404. ******************************************************************************
  405. prototype: VOID Spx_FilterCancelQueued(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
  406. description: Routine to cancel IRPs queued on the stalled list
  407. parameters: pDevObj the device object containing the queue
  408. pIrp points to the IRP to cancel
  409. returns: None
  410. */
  411. VOID Spx_FilterCancelQueued(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
  412. {
  413. PPORT_DEVICE_EXTENSION pPort = pDevObj->DeviceExtension;
  414. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  415. pIrp->IoStatus.Status = STATUS_CANCELLED;
  416. pIrp->IoStatus.Information = 0;
  417. RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
  418. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  419. } // End Spx_FilterCancelQueued
  420. /*****************************************************************************
  421. *************************** **************************
  422. *************************** Spx_KillStalledIRPs **************************
  423. *************************** **************************
  424. ******************************************************************************
  425. prototype: VOID Spx_KillStalledIRPs(IN PDEVICE_OBJECT pDevObj)
  426. description: Kill all IRPs queued on the stalled list
  427. parameters: pDevObj the device object containing the queue
  428. returns: None
  429. */
  430. VOID Spx_KillStalledIRPs(IN PDEVICE_OBJECT pDevObj)
  431. {
  432. PPORT_DEVICE_EXTENSION pPort = pDevObj->DeviceExtension;
  433. PDRIVER_CANCEL cancelRoutine;
  434. KIRQL cancelIrql;
  435. IoAcquireCancelSpinLock(&cancelIrql);
  436. // Call the cancel routine of all IRPs queued on the stalled list...
  437. while(!IsListEmpty(&pPort->StalledIrpQueue))
  438. {
  439. PIRP pIrp = CONTAINING_RECORD(pPort->StalledIrpQueue.Blink, IRP, Tail.Overlay.ListEntry);
  440. RemoveEntryList(pPort->StalledIrpQueue.Blink);
  441. cancelRoutine = pIrp->CancelRoutine; // Get the cancel routine for this IRP
  442. pIrp->CancelIrql = cancelIrql;
  443. pIrp->CancelRoutine = NULL;
  444. pIrp->Cancel = TRUE;
  445. cancelRoutine(pDevObj,pIrp); // Call the cancel routine
  446. IoAcquireCancelSpinLock(&cancelIrql);
  447. }
  448. IoReleaseCancelSpinLock(cancelIrql);
  449. } // End Spx_KillStalledIRPs
  450. // End of SPX_DISP.C