Annotation of ntddk/src/comm/serial/utils.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.