|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: utils.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains code that perform queueing and completion ! 12: manipulation on requests. ! 13: ! 14: Author: ! 15: ! 16: Anthony V. Ercolano 26-Sep-1991 ! 17: ! 18: Environment: ! 19: ! 20: Kernel mode ! 21: ! 22: Revision History : ! 23: ! 24: --*/ ! 25: ! 26: #include <stddef.h> ! 27: #include "ntddk.h" ! 28: #include "ntddser.h" ! 29: #include "serial.h" ! 30: #include "serialp.h" ! 31: ! 32: VOID ! 33: SerialRundownIrpRefs( ! 34: IN PIRP *CurrentOpIrp, ! 35: IN PKTIMER IntervalTimer, ! 36: IN PKTIMER TotalTimer ! 37: ); ! 38: ! 39: ! 40: VOID ! 41: SerialKillAllReadsOrWrites( ! 42: IN PDEVICE_OBJECT DeviceObject, ! 43: IN PLIST_ENTRY QueueToClean, ! 44: IN PIRP *CurrentOpIrp ! 45: ) ! 46: ! 47: /*++ ! 48: ! 49: Routine Description: ! 50: ! 51: This function is used to cancel all queued and the current irps ! 52: for reads or for writes. ! 53: ! 54: Arguments: ! 55: ! 56: DeviceObject - A pointer to the serial device object. ! 57: ! 58: QueueToClean - A pointer to the queue which we're going to clean out. ! 59: ! 60: CurrentOpIrp - Pointer to a pointer to the current irp. ! 61: ! 62: Return Value: ! 63: ! 64: None. ! 65: ! 66: --*/ ! 67: ! 68: { ! 69: ! 70: KIRQL cancelIrql; ! 71: PDRIVER_CANCEL cancelRoutine; ! 72: ! 73: // ! 74: // We acquire the cancel spin lock. This will prevent the ! 75: // irps from moving around. ! 76: // ! 77: ! 78: IoAcquireCancelSpinLock(&cancelIrql); ! 79: ! 80: // ! 81: // Clean the list from back to front. ! 82: // ! 83: ! 84: while (!IsListEmpty(QueueToClean)) { ! 85: ! 86: PIRP currentLastIrp = CONTAINING_RECORD( ! 87: QueueToClean->Blink, ! 88: IRP, ! 89: Tail.Overlay.ListEntry ! 90: ); ! 91: ! 92: RemoveEntryList(QueueToClean->Blink); ! 93: ! 94: cancelRoutine = currentLastIrp->CancelRoutine; ! 95: currentLastIrp->CancelIrql = cancelIrql; ! 96: currentLastIrp->CancelRoutine = NULL; ! 97: currentLastIrp->Cancel = TRUE; ! 98: ! 99: cancelRoutine( ! 100: DeviceObject, ! 101: currentLastIrp ! 102: ); ! 103: ! 104: IoAcquireCancelSpinLock(&cancelIrql); ! 105: ! 106: } ! 107: ! 108: // ! 109: // The queue is clean. Now go after the current if ! 110: // it's there. ! 111: // ! 112: ! 113: if (*CurrentOpIrp) { ! 114: ! 115: ! 116: cancelRoutine = (*CurrentOpIrp)->CancelRoutine; ! 117: (*CurrentOpIrp)->Cancel = TRUE; ! 118: ! 119: // ! 120: // If the current irp is not in a cancelable state ! 121: // then it *will* try to enter one and the above ! 122: // assignment will kill it. If it already is in ! 123: // a cancelable state then the following will kill it. ! 124: // ! 125: ! 126: if (cancelRoutine) { ! 127: ! 128: (*CurrentOpIrp)->CancelRoutine = NULL; ! 129: (*CurrentOpIrp)->CancelIrql = cancelIrql; ! 130: ! 131: // ! 132: // This irp is already in a cancelable state. We simply ! 133: // mark it as canceled and call the cancel routine for ! 134: // it. ! 135: // ! 136: ! 137: cancelRoutine( ! 138: DeviceObject, ! 139: *CurrentOpIrp ! 140: ); ! 141: ! 142: } else { ! 143: ! 144: IoReleaseCancelSpinLock(cancelIrql); ! 145: ! 146: } ! 147: ! 148: } else { ! 149: ! 150: IoReleaseCancelSpinLock(cancelIrql); ! 151: ! 152: } ! 153: ! 154: } ! 155: ! 156: VOID ! 157: SerialGetNextIrp( ! 158: IN PIRP *CurrentOpIrp, ! 159: IN PLIST_ENTRY QueueToProcess, ! 160: OUT PIRP *NextIrp, ! 161: IN BOOLEAN CompleteCurrent ! 162: ) ! 163: ! 164: /*++ ! 165: ! 166: Routine Description: ! 167: ! 168: This function is used to make the head of the particular ! 169: queue the current irp. It also completes the what ! 170: was the old current irp if desired. ! 171: ! 172: Arguments: ! 173: ! 174: CurrentOpIrp - Pointer to a pointer to the currently active ! 175: irp for the particular work list. Note that ! 176: this item is not actually part of the list. ! 177: ! 178: QueueToProcess - The list to pull the new item off of. ! 179: ! 180: NextIrp - The next Irp to process. Note that CurrentOpIrp ! 181: will be set to this value under protection of the ! 182: cancel spin lock. However, if *NextIrp is NULL when ! 183: this routine returns, it is not necessaryly true the ! 184: what is pointed to by CurrentOpIrp will also be NULL. ! 185: The reason for this is that if the queue is empty ! 186: when we hold the cancel spin lock, a new irp may come ! 187: in immediately after we release the lock. ! 188: ! 189: CompleteCurrent - If TRUE then this routine will complete the ! 190: irp pointed to by the pointer argument ! 191: CurrentOpIrp. ! 192: ! 193: Return Value: ! 194: ! 195: None. ! 196: ! 197: --*/ ! 198: ! 199: { ! 200: ! 201: PIRP oldIrp; ! 202: KIRQL oldIrql; ! 203: ! 204: IoAcquireCancelSpinLock(&oldIrql); ! 205: ! 206: oldIrp = *CurrentOpIrp; ! 207: ! 208: if (CompleteCurrent) { ! 209: ! 210: ASSERT(!oldIrp->CancelRoutine); ! 211: ! 212: } ! 213: ! 214: // ! 215: // Check to see if there is a new irp to start up. ! 216: // ! 217: ! 218: if (!IsListEmpty(QueueToProcess)) { ! 219: ! 220: PLIST_ENTRY headOfList; ! 221: ! 222: headOfList = RemoveHeadList(QueueToProcess); ! 223: ! 224: *CurrentOpIrp = CONTAINING_RECORD( ! 225: headOfList, ! 226: IRP, ! 227: Tail.Overlay.ListEntry ! 228: ); ! 229: ! 230: IoSetCancelRoutine( ! 231: *CurrentOpIrp, ! 232: NULL ! 233: ); ! 234: ! 235: } else { ! 236: ! 237: *CurrentOpIrp = NULL; ! 238: ! 239: } ! 240: ! 241: *NextIrp = *CurrentOpIrp; ! 242: IoReleaseCancelSpinLock(oldIrql); ! 243: ! 244: if (CompleteCurrent) { ! 245: ! 246: SerialDump( ! 247: SERIRPPATH, ! 248: ("SERIAL: Complete Irp: %x\n",oldIrp) ! 249: ); ! 250: IoCompleteRequest( ! 251: oldIrp, ! 252: IO_SERIAL_INCREMENT ! 253: ); ! 254: ! 255: } ! 256: ! 257: } ! 258: ! 259: VOID ! 260: SerialTryToCompleteCurrent( ! 261: IN PSERIAL_DEVICE_EXTENSION Extension, ! 262: IN PKSYNCHRONIZE_ROUTINE SynchRoutine OPTIONAL, ! 263: IN KIRQL IrqlForRelease, ! 264: IN NTSTATUS StatusToUse, ! 265: IN PIRP *CurrentOpIrp, ! 266: IN PLIST_ENTRY QueueToProcess OPTIONAL, ! 267: IN PKTIMER IntervalTimer OPTIONAL, ! 268: IN PKTIMER TotalTimer OPTIONAL, ! 269: IN PSERIAL_START_ROUTINE Starter OPTIONAL, ! 270: IN PSERIAL_GET_NEXT_ROUTINE GetNextIrp OPTIONAL ! 271: ) ! 272: ! 273: /*++ ! 274: ! 275: Routine Description: ! 276: ! 277: This routine attempts to kill all of the reasons there are ! 278: references on the current read/write. If everything can be killed ! 279: it will complete this read/write and try to start another. ! 280: ! 281: NOTE: This routine assumes that it is called with the cancel ! 282: spinlock held. ! 283: ! 284: Arguments: ! 285: ! 286: Extension - Simply a pointer to the device extension. ! 287: ! 288: SynchRoutine - A routine that will synchronize with the isr ! 289: and attempt to remove the knowledge of the ! 290: current irp from the isr. NOTE: This pointer ! 291: can be null. ! 292: ! 293: IrqlForRelease - This routine is called with the cancel spinlock held. ! 294: This is the irql that was current when the cancel ! 295: spinlock was acquired. ! 296: ! 297: StatusToUse - The irp's status field will be set to this value, if ! 298: this routine can complete the irp. ! 299: ! 300: ! 301: Return Value: ! 302: ! 303: None. ! 304: ! 305: --*/ ! 306: ! 307: { ! 308: ! 309: // ! 310: // We can decrement the reference to "remove" the fact ! 311: // that the caller no longer will be accessing this irp. ! 312: // ! 313: ! 314: SERIAL_DEC_REFERENCE(*CurrentOpIrp); ! 315: ! 316: if (SynchRoutine) { ! 317: ! 318: KeSynchronizeExecution( ! 319: Extension->Interrupt, ! 320: SynchRoutine, ! 321: Extension ! 322: ); ! 323: ! 324: } ! 325: ! 326: // ! 327: // Try to run down all other references to this irp. ! 328: // ! 329: ! 330: SerialRundownIrpRefs( ! 331: CurrentOpIrp, ! 332: IntervalTimer, ! 333: TotalTimer ! 334: ); ! 335: ! 336: // ! 337: // See if the ref count is zero after trying to kill everybody else. ! 338: // ! 339: ! 340: if (!SERIAL_REFERENCE_COUNT(*CurrentOpIrp)) { ! 341: ! 342: PIRP newIrp; ! 343: ! 344: ! 345: // ! 346: // The ref count was zero so we should complete this ! 347: // request. ! 348: // ! 349: // The following call will also cause the current irp to be ! 350: // completed. ! 351: // ! 352: ! 353: (*CurrentOpIrp)->IoStatus.Status = StatusToUse; ! 354: ! 355: if (StatusToUse == STATUS_CANCELLED) { ! 356: ! 357: (*CurrentOpIrp)->IoStatus.Information = 0; ! 358: ! 359: } ! 360: ! 361: if (GetNextIrp) { ! 362: ! 363: IoReleaseCancelSpinLock(IrqlForRelease); ! 364: GetNextIrp( ! 365: CurrentOpIrp, ! 366: QueueToProcess, ! 367: &newIrp, ! 368: TRUE ! 369: ); ! 370: ! 371: if (newIrp) { ! 372: ! 373: Starter(Extension); ! 374: ! 375: } ! 376: ! 377: } else { ! 378: ! 379: PIRP oldIrp = *CurrentOpIrp; ! 380: ! 381: // ! 382: // There was no get next routine. We will simply complete ! 383: // the irp. We should make sure that we null out the ! 384: // pointer to the pointer to this irp. ! 385: // ! 386: ! 387: *CurrentOpIrp = NULL; ! 388: ! 389: IoReleaseCancelSpinLock(IrqlForRelease); ! 390: SerialDump( ! 391: SERIRPPATH, ! 392: ("SERIAL: Complete Irp: %x\n",oldIrp) ! 393: ); ! 394: IoCompleteRequest( ! 395: oldIrp, ! 396: IO_SERIAL_INCREMENT ! 397: ); ! 398: ! 399: } ! 400: ! 401: } else { ! 402: ! 403: IoReleaseCancelSpinLock(IrqlForRelease); ! 404: ! 405: } ! 406: ! 407: } ! 408: ! 409: VOID ! 410: SerialRundownIrpRefs( ! 411: IN PIRP *CurrentOpIrp, ! 412: IN PKTIMER IntervalTimer OPTIONAL, ! 413: IN PKTIMER TotalTimer OPTIONAL ! 414: ) ! 415: ! 416: /*++ ! 417: ! 418: Routine Description: ! 419: ! 420: This routine runs through the various items that *could* ! 421: have a reference to the current read/write. It try's to kill ! 422: the reason. If it does succeed in killing the reason it ! 423: will decrement the reference count on the irp. ! 424: ! 425: NOTE: This routine assumes that it is called with the cancel ! 426: spin lock held. ! 427: ! 428: Arguments: ! 429: ! 430: CurrentOpIrp - Pointer to a pointer to current irp for the ! 431: particular operation. ! 432: ! 433: IntervalTimer - Pointer to the interval timer for the operation. ! 434: NOTE: This could be null. ! 435: ! 436: TotalTimer - Pointer to the total timer for the operation. ! 437: NOTE: This could be null. ! 438: ! 439: Return Value: ! 440: ! 441: None. ! 442: ! 443: --*/ ! 444: ! 445: ! 446: { ! 447: ! 448: // ! 449: // This routine is called with the cancel spin lock held ! 450: // so we know only one thread of execution can be in here ! 451: // at one time. ! 452: // ! 453: ! 454: // ! 455: // First we see if there is still a cancel routine. If ! 456: // so then we can decrement the count by one. ! 457: // ! 458: ! 459: if ((*CurrentOpIrp)->CancelRoutine) { ! 460: ! 461: SERIAL_DEC_REFERENCE(*CurrentOpIrp); ! 462: ! 463: IoSetCancelRoutine( ! 464: *CurrentOpIrp, ! 465: NULL ! 466: ); ! 467: ! 468: } ! 469: ! 470: if (IntervalTimer) { ! 471: ! 472: // ! 473: // Try to cancel the operations interval timer. If the operation ! 474: // returns true then the timer did have a reference to the ! 475: // irp. Since we've canceled this timer that reference is ! 476: // no longer valid and we can decrement the reference count. ! 477: // ! 478: // If the cancel returns false then this means either of two things: ! 479: // ! 480: // a) The timer has already fired. ! 481: // ! 482: // b) There never was an interval timer. ! 483: // ! 484: // In the case of "b" there is no need to decrement the reference ! 485: // count since the "timer" never had a reference to it. ! 486: // ! 487: // In the case of "a", then the timer itself will be coming ! 488: // along and decrement it's reference. Note that the caller ! 489: // of this routine might actually be the this timer, but it ! 490: // has already decremented the reference. ! 491: // ! 492: ! 493: if (KeCancelTimer(IntervalTimer)) { ! 494: ! 495: SERIAL_DEC_REFERENCE(*CurrentOpIrp); ! 496: ! 497: } ! 498: ! 499: } ! 500: ! 501: if (TotalTimer) { ! 502: ! 503: // ! 504: // Try to cancel the operations total timer. If the operation ! 505: // returns true then the timer did have a reference to the ! 506: // irp. Since we've canceled this timer that reference is ! 507: // no longer valid and we can decrement the reference count. ! 508: // ! 509: // If the cancel returns false then this means either of two things: ! 510: // ! 511: // a) The timer has already fired. ! 512: // ! 513: // b) There never was an total timer. ! 514: // ! 515: // In the case of "b" there is no need to decrement the reference ! 516: // count since the "timer" never had a reference to it. ! 517: // ! 518: // In the case of "a", then the timer itself will be coming ! 519: // along and decrement it's reference. Note that the caller ! 520: // of this routine might actually be the this timer, but it ! 521: // has already decremented the reference. ! 522: // ! 523: ! 524: if (KeCancelTimer(TotalTimer)) { ! 525: ! 526: SERIAL_DEC_REFERENCE(*CurrentOpIrp); ! 527: ! 528: } ! 529: ! 530: } ! 531: ! 532: } ! 533: ! 534: NTSTATUS ! 535: SerialStartOrQueue( ! 536: IN PSERIAL_DEVICE_EXTENSION Extension, ! 537: IN PIRP Irp, ! 538: IN PLIST_ENTRY QueueToExamine, ! 539: IN PIRP *CurrentOpIrp, ! 540: IN PSERIAL_START_ROUTINE Starter ! 541: ) ! 542: ! 543: /*++ ! 544: ! 545: Routine Description: ! 546: ! 547: This routine is used to either start or queue any requst ! 548: that can be queued in the driver. ! 549: ! 550: Arguments: ! 551: ! 552: Extension - Points to the serial device extension. ! 553: ! 554: Irp - The irp to either queue or start. In either ! 555: case the irp will be marked pending. ! 556: ! 557: QueueToExamine - The queue the irp will be place on if there ! 558: is already an operation in progress. ! 559: ! 560: CurrentOpIrp - Pointer to a pointer to the irp the is current ! 561: for the queue. The pointer pointed to will be ! 562: set with to Irp if what CurrentOpIrp points to ! 563: is NULL. ! 564: ! 565: Starter - The routine to call if the queue is empty. ! 566: ! 567: Return Value: ! 568: ! 569: This routine will return STATUS_PENDING if the queue is ! 570: not empty. Otherwise, it will return the status returned ! 571: from the starter routine (or cancel, if the cancel bit is ! 572: on in the irp). ! 573: ! 574: ! 575: --*/ ! 576: ! 577: { ! 578: ! 579: KIRQL oldIrql; ! 580: ! 581: IoAcquireCancelSpinLock(&oldIrql); ! 582: ! 583: // ! 584: // If this is a write irp then take the amount of characters ! 585: // to write and add it to the count of characters to write. ! 586: // ! 587: ! 588: if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction ! 589: == IRP_MJ_WRITE) { ! 590: ! 591: Extension->TotalCharsQueued += ! 592: IoGetCurrentIrpStackLocation(Irp) ! 593: ->Parameters.Write.Length; ! 594: ! 595: } else if ((IoGetCurrentIrpStackLocation(Irp)->MajorFunction ! 596: == IRP_MJ_DEVICE_CONTROL) && ! 597: ((IoGetCurrentIrpStackLocation(Irp) ! 598: ->Parameters.DeviceIoControl.IoControlCode == ! 599: IOCTL_SERIAL_IMMEDIATE_CHAR) || ! 600: (IoGetCurrentIrpStackLocation(Irp) ! 601: ->Parameters.DeviceIoControl.IoControlCode == ! 602: IOCTL_SERIAL_XOFF_COUNTER))) { ! 603: ! 604: Extension->TotalCharsQueued++; ! 605: ! 606: } ! 607: ! 608: if ((IsListEmpty(QueueToExamine)) && ! 609: !(*CurrentOpIrp)) { ! 610: ! 611: // ! 612: // There were no current operation. Mark this one as ! 613: // current and start it up. ! 614: // ! 615: ! 616: *CurrentOpIrp = Irp; ! 617: ! 618: IoReleaseCancelSpinLock(oldIrql); ! 619: ! 620: return Starter(Extension); ! 621: ! 622: } else { ! 623: ! 624: // ! 625: // We don't know how long the irp will be in the ! 626: // queue. So we need to handle cancel. ! 627: // ! 628: ! 629: if (Irp->Cancel) { ! 630: ! 631: IoReleaseCancelSpinLock(oldIrql); ! 632: ! 633: Irp->IoStatus.Status = STATUS_CANCELLED; ! 634: ! 635: SerialDump( ! 636: SERIRPPATH, ! 637: ("SERIAL: Complete Irp: %x\n",Irp) ! 638: ); ! 639: IoCompleteRequest( ! 640: Irp, ! 641: 0 ! 642: ); ! 643: ! 644: return STATUS_CANCELLED; ! 645: ! 646: } else { ! 647: ! 648: ! 649: Irp->IoStatus.Status = STATUS_PENDING; ! 650: IoMarkIrpPending(Irp); ! 651: ! 652: InsertTailList( ! 653: QueueToExamine, ! 654: &Irp->Tail.Overlay.ListEntry ! 655: ); ! 656: ! 657: IoSetCancelRoutine( ! 658: Irp, ! 659: SerialCancelQueued ! 660: ); ! 661: ! 662: IoReleaseCancelSpinLock(oldIrql); ! 663: ! 664: return STATUS_PENDING; ! 665: ! 666: } ! 667: ! 668: } ! 669: ! 670: } ! 671: ! 672: VOID ! 673: SerialCancelQueued( ! 674: PDEVICE_OBJECT DeviceObject, ! 675: PIRP Irp ! 676: ) ! 677: ! 678: /*++ ! 679: ! 680: Routine Description: ! 681: ! 682: This routine is used to cancel Irps that currently reside on ! 683: a queue. ! 684: ! 685: Arguments: ! 686: ! 687: DeviceObject - Pointer to the device object for this device ! 688: ! 689: Irp - Pointer to the IRP to be canceled. ! 690: ! 691: Return Value: ! 692: ! 693: None. ! 694: ! 695: --*/ ! 696: ! 697: { ! 698: ! 699: PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension; ! 700: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); ! 701: ! 702: Irp->IoStatus.Status = STATUS_CANCELLED; ! 703: Irp->IoStatus.Information = 0; ! 704: ! 705: RemoveEntryList(&Irp->Tail.Overlay.ListEntry); ! 706: ! 707: // ! 708: // If this is a write irp then take the amount of characters ! 709: // to write and subtract it from the count of characters to write. ! 710: // ! 711: ! 712: if (irpSp->MajorFunction == IRP_MJ_WRITE) { ! 713: ! 714: extension->TotalCharsQueued -= irpSp->Parameters.Write.Length; ! 715: ! 716: } else if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) { ! 717: ! 718: // ! 719: // If it's an immediate then we need to decrement the ! 720: // count of chars queued. If it's a resize then we ! 721: // need to deallocate the pool that we're passing on ! 722: // to the "resizing" routine. ! 723: // ! 724: ! 725: if ((irpSp->Parameters.DeviceIoControl.IoControlCode == ! 726: IOCTL_SERIAL_IMMEDIATE_CHAR) || ! 727: (irpSp->Parameters.DeviceIoControl.IoControlCode == ! 728: IOCTL_SERIAL_XOFF_COUNTER)) { ! 729: ! 730: extension->TotalCharsQueued--; ! 731: ! 732: } else if (irpSp->Parameters.DeviceIoControl.IoControlCode == ! 733: IOCTL_SERIAL_SET_QUEUE_SIZE) { ! 734: ! 735: // ! 736: // We shoved the pointer to the memory into the ! 737: // the type 3 buffer pointer which we KNOW we ! 738: // never use. ! 739: // ! 740: ! 741: ASSERT(irpSp->Parameters.DeviceIoControl.Type3InputBuffer); ! 742: ! 743: ExFreePool(irpSp->Parameters.DeviceIoControl.Type3InputBuffer); ! 744: ! 745: irpSp->Parameters.DeviceIoControl.Type3InputBuffer = NULL; ! 746: ! 747: } ! 748: ! 749: } ! 750: ! 751: IoReleaseCancelSpinLock(Irp->CancelIrql); ! 752: ! 753: SerialDump( ! 754: SERIRPPATH, ! 755: ("SERIAL: Complete Irp: %x\n",Irp) ! 756: ); ! 757: IoCompleteRequest( ! 758: Irp, ! 759: IO_SERIAL_INCREMENT ! 760: ); ! 761: ! 762: } ! 763: ! 764: NTSTATUS ! 765: SerialCompleteIfError( ! 766: PDEVICE_OBJECT DeviceObject, ! 767: PIRP Irp ! 768: ) ! 769: ! 770: /*++ ! 771: ! 772: Routine Description: ! 773: ! 774: If the current irp is not an IOCTL_SERIAL_GET_COMMSTATUS request and ! 775: there is an error and the application requested abort on errors, ! 776: then cancel the irp. ! 777: ! 778: Arguments: ! 779: ! 780: DeviceObject - Pointer to the device object for this device ! 781: ! 782: Irp - Pointer to the IRP to test. ! 783: ! 784: Return Value: ! 785: ! 786: STATUS_SUCCESS or STATUS_CANCELLED. ! 787: ! 788: --*/ ! 789: ! 790: { ! 791: ! 792: PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension; ! 793: ! 794: NTSTATUS status = STATUS_SUCCESS; ! 795: ! 796: if ((extension->HandFlow.ControlHandShake & ! 797: SERIAL_ERROR_ABORT) && extension->ErrorWord) { ! 798: ! 799: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); ! 800: ! 801: // ! 802: // There is a current error in the driver. No requests should ! 803: // come through except for the GET_COMMSTATUS. ! 804: // ! 805: ! 806: if ((irpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL) || ! 807: (irpSp->Parameters.DeviceIoControl.IoControlCode != ! 808: IOCTL_SERIAL_GET_COMMSTATUS)) { ! 809: ! 810: status = STATUS_CANCELLED; ! 811: Irp->IoStatus.Status = STATUS_CANCELLED; ! 812: Irp->IoStatus.Information = 0; ! 813: ! 814: SerialDump( ! 815: SERIRPPATH, ! 816: ("SERIAL: Complete Irp: %x\n",Irp) ! 817: ); ! 818: IoCompleteRequest( ! 819: Irp, ! 820: 0 ! 821: ); ! 822: ! 823: } ! 824: ! 825: } ! 826: ! 827: return status; ! 828: ! 829: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.