Annotation of ntddk/src/network/tdi/request.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1989-1993  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     request.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains code which implements the TP_REQUEST object.
                     12:     Routines are provided to create, destroy, reference, and dereference,
                     13:     transport request objects.
                     14: 
                     15: Environment:
                     16: 
                     17:     Kernel mode
                     18: 
                     19: Revision History:
                     20: 
                     21: 
                     22: --*/
                     23: 
                     24: #include "st.h"
                     25: 
                     26: 
                     27: VOID
                     28: StTdiRequestTimeoutHandler(
                     29:     IN PKDPC Dpc,
                     30:     IN PVOID DeferredContext,
                     31:     IN PVOID SystemArgument1,
                     32:     IN PVOID SystemArgument2
                     33:     )
                     34: 
                     35: /*++
                     36: 
                     37: Routine Description:
                     38: 
                     39:     This routine is executed as a DPC at DISPATCH_LEVEL when a request
                     40:     such as TdiSend, TdiReceive, TdiSendDatagram, TdiReceiveDatagram, etc.,
                     41:     encounters a timeout.  This routine cleans up the activity and cancels it.
                     42: 
                     43: Arguments:
                     44: 
                     45:     Dpc - Pointer to a system DPC object.
                     46: 
                     47:     DeferredContext - Pointer to the TP_REQUEST block representing the
                     48:         request that has timed out.
                     49: 
                     50:     SystemArgument1 - Not used.
                     51: 
                     52:     SystemArgument2 - Not used.
                     53: 
                     54: Return Value:
                     55: 
                     56:     none.
                     57: 
                     58: --*/
                     59: 
                     60: {
                     61:     KIRQL oldirql;
                     62:     PTP_REQUEST Request;
                     63:     PTP_CONNECTION Connection;
                     64:     PIO_STACK_LOCATION IrpSp;
                     65: 
                     66:     UNREFERENCED_PARAMETER(Dpc);
                     67:     UNREFERENCED_PARAMETER(SystemArgument1);
                     68:     UNREFERENCED_PARAMETER(SystemArgument2);
                     69: 
                     70: 
                     71:     Request = (PTP_REQUEST)DeferredContext;
                     72: 
                     73:     ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
                     74:     Request->Flags &= ~REQUEST_FLAGS_TIMER;
                     75:     if ((Request->Flags & REQUEST_FLAGS_STOPPING) == 0) {
                     76: 
                     77:         //
                     78:         // find reason for timeout
                     79:         //
                     80: 
                     81:         IrpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
                     82:         if (IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) {
                     83:             switch (IrpSp->MinorFunction) {
                     84: 
                     85:                 //
                     86:                 // none of these should time out.
                     87:                 //
                     88: 
                     89:             case TDI_SEND:
                     90:             case TDI_ACCEPT:
                     91:             case TDI_SET_INFORMATION:
                     92:             case TDI_SET_EVENT_HANDLER:
                     93:             case TDI_SEND_DATAGRAM:
                     94:             case TDI_RECEIVE_DATAGRAM:
                     95:             case TDI_RECEIVE:
                     96: 
                     97:                 ASSERT (FALSE);
                     98:                 RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                     99:                 StCompleteRequest (Request, STATUS_IO_TIMEOUT, 0);
                    100:                 break;
                    101: 
                    102: 
                    103:             case TDI_LISTEN:
                    104:             case TDI_CONNECT:
                    105: 
                    106:                 Connection = (PTP_CONNECTION)(Request->Context);
                    107:                 RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                    108: 
                    109:                 //
                    110:                 // Since these requests are part of the connection
                    111:                 // itself, we just stop the connection and the
                    112:                 // request will get torn down then. If we get the
                    113:                 // situation where the request times out before
                    114:                 // it is queued to the connection, then the code
                    115:                 // that is about to queue it will check the STOPPING
                    116:                 // flag and complete it then.
                    117:                 //
                    118: 
                    119:                 StStopConnection (Connection, STATUS_IO_TIMEOUT);
                    120:                 break;
                    121: 
                    122:             case TDI_DISCONNECT:
                    123: 
                    124:                 //
                    125:                 // We don't create requests for TDI_DISCONNECT any more.
                    126:                 //
                    127: 
                    128:                 ASSERT(FALSE);
                    129:                 break;
                    130: 
                    131:             default:
                    132:                 RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                    133:                 break;
                    134: 
                    135:             }   // end of switch
                    136: 
                    137:         } else {
                    138: 
                    139:             RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                    140: 
                    141:         }
                    142: 
                    143:         StDereferenceRequest ("Timeout", Request);      // for the timeout
                    144: 
                    145:     } else {
                    146: 
                    147:         RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                    148:         StDereferenceRequest ("Timeout: stopping", Request); // for the timeout
                    149: 
                    150:     }
                    151: 
                    152:     return;
                    153: 
                    154: } /* RequestTimeoutHandler */
                    155: 
                    156: 
                    157: VOID
                    158: StAllocateRequest(
                    159:     IN PDEVICE_CONTEXT DeviceContext,
                    160:     OUT PTP_REQUEST *TransportRequest
                    161:     )
                    162: 
                    163: /*++
                    164: 
                    165: Routine Description:
                    166: 
                    167:     This routine allocates a request packet from nonpaged pool and initializes
                    168:     it to a known state.
                    169: 
                    170:     NOTE: This routine is called with the device context spinlock
                    171:     held, or at such a time as synchronization is unnecessary.
                    172: 
                    173: Arguments:
                    174: 
                    175:     DeviceContext - Pointer to the device context (which is really just
                    176:         the device object with its extension) to be associated with the
                    177:         address.
                    178: 
                    179:     TransportRequest - Pointer to a place where this routine will return
                    180:         a pointer to a transport request structure. It returns NULL if no
                    181:         storage can be allocated.
                    182: 
                    183: Return Value:
                    184: 
                    185:     None.
                    186: 
                    187: --*/
                    188: 
                    189: {
                    190:     PTP_REQUEST Request;
                    191: 
                    192:     if ((DeviceContext->MemoryLimit != 0) &&
                    193:             ((DeviceContext->MemoryUsage + sizeof(TP_REQUEST)) >
                    194:                 DeviceContext->MemoryLimit)) {
                    195:         PANIC("ST: Could not allocate request: limit\n");
                    196:         StWriteResourceErrorLog (DeviceContext, sizeof(TP_REQUEST), 104);
                    197:         *TransportRequest = NULL;
                    198:         return;
                    199:     }
                    200: 
                    201:     Request = (PTP_REQUEST)ExAllocatePool (NonPagedPool, sizeof (TP_REQUEST));
                    202:     if (Request == NULL) {
                    203:         PANIC("ST: Could not allocate request: no pool\n");
                    204:         StWriteResourceErrorLog (DeviceContext, sizeof(TP_REQUEST), 204);
                    205:         *TransportRequest = NULL;
                    206:         return;
                    207:     }
                    208:     RtlZeroMemory (Request, sizeof(TP_REQUEST));
                    209: 
                    210:     DeviceContext->MemoryUsage += sizeof(TP_REQUEST);
                    211:     ++DeviceContext->RequestAllocated;
                    212: 
                    213:     Request->Type = ST_REQUEST_SIGNATURE;
                    214:     Request->Size = sizeof (TP_REQUEST);
                    215: 
                    216:     Request->Provider = DeviceContext;
                    217:     Request->ProviderInterlock = &DeviceContext->Interlock;
                    218:     KeInitializeSpinLock (&Request->SpinLock);
                    219:     KeInitializeDpc (&Request->Dpc, StTdiRequestTimeoutHandler, (PVOID)Request);
                    220:     KeInitializeTimer (&Request->Timer);    // set to not-signaled state.
                    221: 
                    222:     *TransportRequest = Request;
                    223: 
                    224: }   /* StAllocateRequest */
                    225: 
                    226: 
                    227: VOID
                    228: StDeallocateRequest(
                    229:     IN PDEVICE_CONTEXT DeviceContext,
                    230:     IN PTP_REQUEST TransportRequest
                    231:     )
                    232: 
                    233: /*++
                    234: 
                    235: Routine Description:
                    236: 
                    237:     This routine frees a request packet.
                    238: 
                    239:     NOTE: This routine is called with the device context spinlock
                    240:     held, or at such a time as synchronization is unnecessary.
                    241: 
                    242: Arguments:
                    243: 
                    244:     DeviceContext - Pointer to the device context (which is really just
                    245:         the device object with its extension) to be associated with the
                    246:         address.
                    247: 
                    248:     TransportRequest - Pointer to a transport request structure.
                    249: 
                    250: Return Value:
                    251: 
                    252:     None.
                    253: 
                    254: --*/
                    255: 
                    256: {
                    257: 
                    258:     ExFreePool (TransportRequest);
                    259:     --DeviceContext->RequestAllocated;
                    260:     DeviceContext->MemoryUsage -= sizeof(TP_REQUEST);
                    261: 
                    262: }   /* StDeallocateRequest */
                    263: 
                    264: 
                    265: NTSTATUS
                    266: StCreateRequest(
                    267:     IN PIRP Irp,
                    268:     IN PVOID Context,
                    269:     IN ULONG Flags,
                    270:     IN PMDL Buffer2,
                    271:     IN ULONG Buffer2Length,
                    272:     IN LARGE_INTEGER Timeout,
                    273:     OUT PTP_REQUEST * TpRequest
                    274:     )
                    275: 
                    276: /*++
                    277: 
                    278: Routine Description:
                    279: 
                    280:     This routine creates a transport request and associates it with the
                    281:     specified IRP, context, and queue.  All major requests, including
                    282:     TdiSend, TdiSendDatagram, TdiReceive, and TdiReceiveDatagram requests,
                    283:     are composed in this manner.
                    284: 
                    285: Arguments:
                    286: 
                    287:     Irp - Pointer to an IRP which was received by the transport for this
                    288:         request.
                    289: 
                    290:     Context - Pointer to anything to associate this request with.  This
                    291:         value is not interpreted except at request cancelation time.
                    292: 
                    293:     Flags - A set of bitflags indicating the disposition of this request.
                    294: 
                    295:     Timeout - Timeout value (if non-zero) to start a timer for this request.
                    296:         If zero, then no timer is activated for the request.
                    297: 
                    298:     TpRequest - If the function returns STATUS_SUCCESS, this will return
                    299:         pointer to the TP_REQUEST structure allocated.
                    300: 
                    301: Return Value:
                    302: 
                    303:     NTSTATUS - status of operation.
                    304: 
                    305: --*/
                    306: 
                    307: {
                    308:     KIRQL oldirql;
                    309:     PDEVICE_CONTEXT DeviceContext;
                    310:     PTP_REQUEST Request;
                    311:     PLIST_ENTRY p;
                    312:     PIO_STACK_LOCATION irpSp;
                    313: 
                    314: 
                    315:     irpSp = IoGetCurrentIrpStackLocation(Irp);
                    316:     DeviceContext = (PDEVICE_CONTEXT)irpSp->FileObject->DeviceObject;
                    317: 
                    318:     ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
                    319: 
                    320:     p = RemoveHeadList (&DeviceContext->RequestPool);
                    321:     if (p == &DeviceContext->RequestPool) {
                    322: 
                    323:         if ((DeviceContext->RequestMaxAllocated == 0) ||
                    324:             (DeviceContext->RequestAllocated < DeviceContext->RequestMaxAllocated)) {
                    325: 
                    326:             StAllocateRequest (DeviceContext, &Request);
                    327: 
                    328:         } else {
                    329: 
                    330:             StWriteResourceErrorLog (DeviceContext, sizeof(TP_REQUEST), 404);
                    331:             Request = NULL;
                    332: 
                    333:         }
                    334: 
                    335:         if (Request == NULL) {
                    336:             ++DeviceContext->RequestExhausted;
                    337:             RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
                    338:             PANIC ("StCreateConnection: Could not allocate request object!\n");
                    339:             return STATUS_INSUFFICIENT_RESOURCES;
                    340:         }
                    341: 
                    342:     } else {
                    343: 
                    344:         Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
                    345: 
                    346:     }
                    347: 
                    348:     ++DeviceContext->RequestInUse;
                    349:     if (DeviceContext->RequestInUse > DeviceContext->RequestMaxInUse) {
                    350:         ++DeviceContext->RequestMaxInUse;
                    351:     }
                    352: 
                    353:     DeviceContext->RequestTotal += DeviceContext->RequestInUse;
                    354:     ++DeviceContext->RequestSamples;
                    355: 
                    356:     RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
                    357: 
                    358: 
                    359:     //
                    360:     // fill out the request.
                    361:     //
                    362: 
                    363:     // Request->Provider = DeviceContext;
                    364:     Request->IoRequestPacket = Irp;
                    365:     Request->Buffer2 = Buffer2;
                    366:     Request->Buffer2Length = Buffer2Length;
                    367:     Request->Flags = Flags;
                    368:     Request->Context = Context;
                    369:     Request->ReferenceCount = 1;                // initialize reference count.
                    370: 
                    371:     if ((Timeout.LowPart == 0) && (Timeout.HighPart == 0)) {
                    372: 
                    373:         // no timeout
                    374:     } else {
                    375: 
                    376:         Request->Flags |= REQUEST_FLAGS_TIMER;  // there is a timeout on this request.
                    377:         KeInitializeTimer (&Request->Timer);    // set to not-signaled state.
                    378:         StReferenceRequest ("Create: timer", Request);           // one for the timer
                    379:         KeSetTimer (&Request->Timer, Timeout, &Request->Dpc);
                    380:     }
                    381: 
                    382:     *TpRequest = Request;
                    383: 
                    384:     return STATUS_SUCCESS;
                    385: } /* StCreateRequest */
                    386: 
                    387: 
                    388: VOID
                    389: StDestroyRequest(
                    390:     IN PTP_REQUEST Request
                    391:     )
                    392: 
                    393: /*++
                    394: 
                    395: Routine Description:
                    396: 
                    397:     This routine returns a request block to the free pool.
                    398: 
                    399: Arguments:
                    400: 
                    401:     Request - Pointer to a TP_REQUEST block to return to the free pool.
                    402: 
                    403: Return Value:
                    404: 
                    405:     NTSTATUS - status of operation.
                    406: 
                    407: --*/
                    408: 
                    409: {
                    410:     KIRQL oldirql;
                    411:     PIO_STACK_LOCATION irpSp;
                    412:     PDEVICE_CONTEXT DeviceContext;
                    413: 
                    414:     //
                    415:     // Return the request to the caller with whatever status is in the IRP.
                    416:     //
                    417: 
                    418:     //
                    419:     // Now dereference the owner of this request so that we are safe when
                    420:     // we finally tear down the {connection, address}. The problem we're
                    421:     // facing here is that we can't allow the user to assume semantics;
                    422:     // the end of life for a connection must truly be the real end of life.
                    423:     // for that to occur, we reference the owning object when the request is
                    424:     // created and we dereference it just before we return it to the pool.
                    425:     //
                    426: 
                    427:     switch (Request->Owner) {
                    428:     case ConnectionType:
                    429:         if (!(Request->Flags & REQUEST_FLAGS_DELAY)) {
                    430:             StDereferenceConnection ("Removing Connection",((PTP_CONNECTION)Request->Context));
                    431:         }
                    432:         break;
                    433: 
                    434:     case AddressType:
                    435:         StDereferenceAddress ("Removing Address", ((PTP_ADDRESS)Request->Context));
                    436:         break;
                    437: 
                    438:     case DeviceContextType:
                    439:         StDereferenceDeviceContext ("Removing Address", ((PDEVICE_CONTEXT)Request->Context));
                    440:         break;
                    441:     }
                    442: 
                    443:     irpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
                    444:     DeviceContext = Request->Provider;
                    445: 
                    446:     if (Request->Flags & REQUEST_FLAGS_DELAY) {
                    447: 
                    448:         ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
                    449: 
                    450:         InsertTailList(
                    451:             &DeviceContext->IrpCompletionQueue,
                    452:             &Request->IoRequestPacket->Tail.Overlay.ListEntry);
                    453: 
                    454:     } else {
                    455: 
                    456:         IoCompleteRequest (Request->IoRequestPacket, IO_NETWORK_INCREMENT);
                    457: 
                    458:         ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
                    459: 
                    460:     }
                    461: 
                    462:     //
                    463:     // Put the request back on the free list. NOTE: we have the
                    464:     // lock held here.
                    465:     //
                    466: 
                    467: 
                    468:     DeviceContext->RequestTotal += DeviceContext->RequestInUse;
                    469:     ++DeviceContext->RequestSamples;
                    470:     --DeviceContext->RequestInUse;
                    471: 
                    472:     if ((DeviceContext->RequestAllocated - DeviceContext->RequestInUse) >
                    473:             DeviceContext->RequestInitAllocated) {
                    474:         StDeallocateRequest (DeviceContext, Request);
                    475:     } else {
                    476:         InsertTailList (&DeviceContext->RequestPool, &Request->Linkage);
                    477:     }
                    478: 
                    479:     RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
                    480: 
                    481: } /* StDestroyRequest */
                    482: 
                    483: 
                    484: VOID
                    485: StRefRequest(
                    486:     IN PTP_REQUEST Request
                    487:     )
                    488: 
                    489: /*++
                    490: 
                    491: Routine Description:
                    492: 
                    493:     This routine increments the reference count on a transport request.
                    494: 
                    495: Arguments:
                    496: 
                    497:     Request - Pointer to a TP_REQUEST block.
                    498: 
                    499: Return Value:
                    500: 
                    501:     none.
                    502: 
                    503: --*/
                    504: 
                    505: {
                    506:     INTERLOCKED_RESULT result;
                    507: 
                    508:     ASSERT (Request->ReferenceCount > 0);
                    509: 
                    510:     result = ExInterlockedIncrementLong (
                    511:               &Request->ReferenceCount,
                    512:               Request->ProviderInterlock);
                    513: 
                    514: } /* StRefRequest */
                    515: 
                    516: 
                    517: VOID
                    518: StDerefRequest(
                    519:     IN PTP_REQUEST Request
                    520:     )
                    521: 
                    522: /*++
                    523: 
                    524: Routine Description:
                    525: 
                    526:     This routine dereferences a transport request by decrementing the
                    527:     reference count contained in the structure.  If, after being
                    528:     decremented, the reference count is zero, then this routine calls
                    529:     StDestroyRequest to remove it from the system.
                    530: 
                    531: Arguments:
                    532: 
                    533:     Request - Pointer to a transport request object.
                    534: 
                    535: Return Value:
                    536: 
                    537:     none.
                    538: 
                    539: --*/
                    540: 
                    541: {
                    542:     INTERLOCKED_RESULT result;
                    543: 
                    544:     result = ExInterlockedDecrementLong (
                    545:                 &Request->ReferenceCount,
                    546:                 Request->ProviderInterlock);
                    547: 
                    548:     ASSERT (result != ResultNegative);
                    549: 
                    550:     //
                    551:     // If we have deleted all references to this request, then we can
                    552:     // destroy the object.  It is okay to have already released the spin
                    553:     // lock at this point because there is no possible way that another
                    554:     // stream of execution has access to the request any longer.
                    555:     //
                    556: 
                    557:     if (result == ResultZero) {
                    558:         StDestroyRequest (Request);
                    559:     }
                    560: 
                    561: } /* StDerefRequest */
                    562: 
                    563: 
                    564: VOID
                    565: StCompleteRequest(
                    566:     IN PTP_REQUEST Request,
                    567:     IN NTSTATUS Status,
                    568:     IN ULONG Information
                    569:     )
                    570: 
                    571: /*++
                    572: 
                    573: Routine Description:
                    574: 
                    575:     This routine completes a transport request object, completing the I/O,
                    576:     stopping the timeout, and freeing up the request object itself.
                    577: 
                    578: Arguments:
                    579: 
                    580:     Request - Pointer to a transport request object.
                    581: 
                    582:     Status - Actual return status to be assigned to the request.  This
                    583:         value may be overridden if the timed-out bitflag is set in the request.
                    584: 
                    585:     Information - the information field for the I/O Status Block.
                    586: 
                    587: Return Value:
                    588: 
                    589:     none.
                    590: 
                    591: --*/
                    592: 
                    593: {
                    594:     KIRQL oldirql;
                    595:     PIRP Irp;
                    596:     NTSTATUS FinalStatus = Status;
                    597:     BOOLEAN TimerWasSet;
                    598: 
                    599:     ASSERT (Status != STATUS_PENDING);
                    600: 
                    601:     if (Request->Flags & REQUEST_FLAGS_SEND_RCV) {
                    602: 
                    603:         //
                    604:         // Sends and receives we check for since we know
                    605:         // they don't have timers and should only complete
                    606:         // once.
                    607:         //
                    608: 
                    609:         Request->Flags |= REQUEST_FLAGS_STOPPING;
                    610:         Irp = Request->IoRequestPacket;
                    611:         Irp->IoStatus.Status = FinalStatus;
                    612:         Irp->IoStatus.Information = Information;
                    613: 
                    614:         StDereferenceRequest ("Complete", Request);     // remove creation reference.
                    615:         return;
                    616:     }
                    617: 
                    618: 
                    619:     ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
                    620: 
                    621:     if ((Request->Flags & REQUEST_FLAGS_STOPPING) == 0) {
                    622:         Request->Flags |= REQUEST_FLAGS_STOPPING;
                    623: 
                    624:         //
                    625:         // Cancel the pending timeout on this request.  Not all requests
                    626:         // have their timer set.  If this request has the TIMER bit set,
                    627:         // then the timer needs to be cancelled.  If it cannot be cancelled,
                    628:         // then the timer routine will be run, so we just return and let
                    629:         // the timer routine worry about cleaning up this request.
                    630:         //
                    631: 
                    632:         if ((Request->Flags & REQUEST_FLAGS_TIMER) != 0) {
                    633:             Request->Flags &= ~REQUEST_FLAGS_TIMER;
                    634:             RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                    635:             TimerWasSet = KeCancelTimer (&Request->Timer);
                    636: 
                    637:             if (TimerWasSet) {
                    638:                 StDereferenceRequest ("Complete: stop timer", Request);
                    639:             }
                    640: 
                    641:         } else {
                    642:             RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                    643:         }
                    644: 
                    645:         Irp = Request->IoRequestPacket;
                    646: 
                    647: 
                    648:         //
                    649:         // Install the return code in the IRP so that when we call StDestroyRequest,
                    650:         // it will get completed with the proper return status.
                    651:         //
                    652: 
                    653:         Irp->IoStatus.Status = FinalStatus;
                    654:         Irp->IoStatus.Information = Information;
                    655: 
                    656:         //
                    657:         // The entire transport is done with this request.
                    658:         //
                    659: 
                    660:         StDereferenceRequest ("Complete", Request);     // remove creation reference.
                    661: 
                    662:     } else {
                    663: 
                    664:         RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                    665: 
                    666:     }
                    667: 
                    668: } /* StCompleteRequest */
                    669: 
                    670: 
                    671: VOID
                    672: StRefSendIrp(
                    673:     IN PIO_STACK_LOCATION IrpSp
                    674:     )
                    675: 
                    676: /*++
                    677: 
                    678: Routine Description:
                    679: 
                    680:     This routine increments the reference count on a send IRP.
                    681: 
                    682: Arguments:
                    683: 
                    684:     IrpSp - Pointer to the IRP's stack location.
                    685: 
                    686: Return Value:
                    687: 
                    688:     none.
                    689: 
                    690: --*/
                    691: 
                    692: {
                    693:     INTERLOCKED_RESULT result;
                    694: 
                    695:     ASSERT (IRP_REFCOUNT(IrpSp) > 0);
                    696: 
                    697:     result = ExInterlockedIncrementLong (
                    698:               &IRP_REFCOUNT(IrpSp),
                    699:               &(IRP_DEVICE_CONTEXT(IrpSp)->Interlock));
                    700: 
                    701: } /* StRefSendIrp */
                    702: 
                    703: 
                    704: VOID
                    705: StDerefSendIrp(
                    706:     IN PIO_STACK_LOCATION IrpSp
                    707:     )
                    708: 
                    709: /*++
                    710: 
                    711: Routine Description:
                    712: 
                    713:     This routine dereferences a transport send IRP by decrementing the
                    714:     reference count contained in the structure.  If, after being
                    715:     decremented, the reference count is zero, then this routine calls
                    716:     IoCompleteRequest to actually complete the IRP.
                    717: 
                    718:     NOTE: This assume that IRP_CONNECTION(IrpSp) has been changed
                    719:     to point to the IRP instead of the connection.
                    720: 
                    721: Arguments:
                    722: 
                    723:     Request - Pointer to a transport send IRP's stack location.
                    724: 
                    725: Return Value:
                    726: 
                    727:     none.
                    728: 
                    729: --*/
                    730: 
                    731: {
                    732:     INTERLOCKED_RESULT result;
                    733: 
                    734:     result = ExInterlockedDecrementLong (
                    735:                 &IRP_REFCOUNT(IrpSp),
                    736:                 &(IRP_DEVICE_CONTEXT(IrpSp)->Interlock));
                    737: 
                    738:     ASSERT (result != ResultNegative);
                    739: 
                    740:     //
                    741:     // If we have deleted all references to this request, then we can
                    742:     // destroy the object.  It is okay to have already released the spin
                    743:     // lock at this point because there is no possible way that another
                    744:     // stream of execution has access to the request any longer.
                    745:     //
                    746: 
                    747:     if (result == ResultZero) {
                    748: 
                    749:         PIRP Irp = (PIRP)IRP_CONNECTION(IrpSp);
                    750: 
                    751:         IRP_REFCOUNT(IrpSp) = 0;
                    752:         IRP_CONNECTION (IrpSp) = NULL;
                    753: 
                    754:         IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
                    755: 
                    756:     }
                    757: 
                    758: } /* StDerefSendIrp */
                    759: 
                    760: 
                    761: VOID
                    762: StCompleteSendIrp(
                    763:     IN PIRP Irp,
                    764:     IN NTSTATUS Status,
                    765:     IN ULONG Information
                    766:     )
                    767: 
                    768: /*++
                    769: 
                    770: Routine Description:
                    771: 
                    772:     This routine completes a transport send IRP.
                    773: 
                    774: Arguments:
                    775: 
                    776:     Irp - Pointer to a send IRP.
                    777: 
                    778:     Status - Actual return status to be assigned to the request.  This
                    779:         value may be overridden if the timed-out bitflag is set in the request.
                    780: 
                    781:     Information - the information field for the I/O Status Block.
                    782: 
                    783: Return Value:
                    784: 
                    785:     none.
                    786: 
                    787: --*/
                    788: 
                    789: {
                    790:     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
                    791:     PTP_CONNECTION Connection;
                    792: 
                    793:     ASSERT (Status != STATUS_PENDING);
                    794: 
                    795:     Connection = IRP_CONNECTION(IrpSp);
                    796: 
                    797: 
                    798:     //
                    799:     // Sends and receives we check for since we know
                    800:     // they don't have timers and should only complete
                    801:     // once.
                    802:     //
                    803: 
                    804:     Irp->IoStatus.Status = Status;
                    805:     Irp->IoStatus.Information = Information;
                    806: 
                    807:     IRP_CONNECTION(IrpSp) = Irp;
                    808: 
                    809:     StDereferenceSendIrp ("Complete", IrpSp);     // remove creation reference.
                    810: 
                    811:     StDereferenceConnection ("Removing Connection", Connection);
                    812: 
                    813: } /* StCompleteSendIrp */

unix.superglobalmegacorp.com

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