Annotation of ntddk/src/comm/serial/utils.c, revision 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.