|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1989-1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: rcveng.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains code that implements the receive engine for the ! 12: Sample transport provider. ! 13: ! 14: Environment: ! 15: ! 16: Kernel mode ! 17: ! 18: Revision History: ! 19: ! 20: --*/ ! 21: ! 22: #include "st.h" ! 23: ! 24: ! 25: VOID ! 26: ActivateReceive( ! 27: PTP_CONNECTION Connection ! 28: ) ! 29: ! 30: /*++ ! 31: ! 32: Routine Description: ! 33: ! 34: This routine activates the next TdiReceive request on the specified ! 35: connection object if there is no active request on that connection ! 36: already. This allows the request to accept data on the connection. ! 37: ! 38: Arguments: ! 39: ! 40: Connection - Pointer to a TP_CONNECTION object. ! 41: ! 42: Return Value: ! 43: ! 44: none. ! 45: ! 46: --*/ ! 47: ! 48: { ! 49: KIRQL oldirql; ! 50: PTP_REQUEST Request; ! 51: ! 52: // ! 53: // The ACTIVE_RECEIVE bitflag will be set on the connection if ! 54: // the receive-fields in the CONNECTION object are valid. If ! 55: // this flag is cleared, then we try to make the next TdiReceive ! 56: // request in the ReceiveQueue the active request. ! 57: // ! 58: ! 59: ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql); ! 60: if (!(Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE)) { ! 61: if (!IsListEmpty (&Connection->ReceiveQueue)) { ! 62: ! 63: // ! 64: // Found a receive, so make it the active one. ! 65: // ! 66: ! 67: Connection->Flags |= CONNECTION_FLAGS_ACTIVE_RECEIVE; ! 68: ! 69: Request = CONTAINING_RECORD ( ! 70: Connection->ReceiveQueue.Flink, ! 71: TP_REQUEST, ! 72: Linkage); ! 73: Connection->MessageBytesReceived = 0; ! 74: Connection->MessageBytesAcked = 0; ! 75: Connection->CurrentReceiveRequest = Request; ! 76: Connection->CurrentReceiveMdl = Request->Buffer2; ! 77: Connection->ReceiveLength = Request->Buffer2Length; ! 78: Connection->ReceiveByteOffset = 0; ! 79: } ! 80: } ! 81: ! 82: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 83: ! 84: } /* ActivateReceive */ ! 85: ! 86: ! 87: VOID ! 88: AwakenReceive( ! 89: PTP_CONNECTION Connection ! 90: ) ! 91: ! 92: /*++ ! 93: ! 94: Routine Description: ! 95: ! 96: This routine is called to reactivate a sleeping connection with the ! 97: RECEIVE_WAKEUP bitflag set because data arrived for which no receive ! 98: was available. The caller has made a receive available at the connection, ! 99: so here we activate the next receive, and send the appropriate protocol ! 100: to restart the message at the first byte offset past the one received ! 101: by the last receive. ! 102: ! 103: Arguments: ! 104: ! 105: Connection - Pointer to a TP_CONNECTION object. ! 106: ! 107: Return Value: ! 108: ! 109: none. ! 110: ! 111: --*/ ! 112: ! 113: { ! 114: KIRQL oldirql; ! 115: ! 116: // ! 117: // If the RECEIVE_WAKEUP bitflag is set, then awaken the connection. ! 118: // ! 119: ! 120: ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql); ! 121: if (Connection->Flags & CONNECTION_FLAGS_RECEIVE_WAKEUP) { ! 122: if (Connection->ReceiveQueue.Flink != &Connection->ReceiveQueue) { ! 123: Connection->Flags &= ~CONNECTION_FLAGS_RECEIVE_WAKEUP; ! 124: ! 125: // ! 126: // Found a receive, so turn off the wakeup flag, and activate ! 127: // the next receive. ! 128: // ! 129: ! 130: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 131: ActivateReceive (Connection); ! 132: ! 133: return; ! 134: } ! 135: } ! 136: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 137: } /* AwakenReceive */ ! 138: ! 139: ! 140: VOID ! 141: CompleteReceive( ! 142: PTP_CONNECTION Connection, ! 143: BOOLEAN EndOfRecord, ! 144: KIRQL ConnectionIrql, ! 145: KIRQL CancelIrql ! 146: ) ! 147: ! 148: /*++ ! 149: ! 150: Routine Description: ! 151: ! 152: This routine is called by ProcessIncomingData when the current receive ! 153: must be completed. Depending on whether the current frame being ! 154: processed is a DATA_FIRST_MIDDLE or DATA_ONLY_LAST, and also whether ! 155: all of the data was processed, the EndOfRecord flag will be set accordingly ! 156: by the caller to indicate that a message boundary was received. ! 157: ! 158: NOTE: This function is called with the connection and cancel ! 159: IRQLs held, and returns with them released. ! 160: ! 161: Arguments: ! 162: ! 163: Connection - Pointer to a TP_CONNECTION object. ! 164: ! 165: EndOfRecord - BOOLEAN set to true if TDI_END_OF_RECORD should be reported. ! 166: ! 167: ConnectionIrql - The IRQL at which the connection spinlock was acquired. ! 168: ! 169: CancelIrql - The IRQL at which the cancel spinlock was acquired. ! 170: ! 171: Return Value: ! 172: ! 173: none. ! 174: ! 175: --*/ ! 176: ! 177: { ! 178: PLIST_ENTRY p; ! 179: PTP_REQUEST Request; ! 180: KIRQL oldirql = ConnectionIrql; ! 181: KIRQL cancelirql = CancelIrql; ! 182: ULONG BytesReceived; ! 183: ! 184: ! 185: if (IsListEmpty (&Connection->ReceiveQueue)) { ! 186: ! 187: ASSERT ((Connection->Flags & CONNECTION_FLAGS_STOPPING) != 0); ! 188: ! 189: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 190: IoReleaseCancelSpinLock(cancelirql); ! 191: return; ! 192: } ! 193: ! 194: Connection->Flags &= ~CONNECTION_FLAGS_ACTIVE_RECEIVE; ! 195: BytesReceived = Connection->MessageBytesReceived; ! 196: ! 197: ! 198: // ! 199: // Complete the TdiReceive request at the head of the ! 200: // connection's ReceiveQueue. ! 201: // ! 202: ! 203: p = RemoveHeadList (&Connection->ReceiveQueue); ! 204: Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage); ! 205: ! 206: Request->IoRequestPacket->CancelRoutine = (PDRIVER_CANCEL)NULL; ! 207: ! 208: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 209: IoReleaseCancelSpinLock(cancelirql); ! 210: ! 211: ! 212: Request->Flags |= REQUEST_FLAGS_DELAY; ! 213: ! 214: StCompleteRequest( ! 215: Request, ! 216: EndOfRecord ? STATUS_SUCCESS : STATUS_BUFFER_OVERFLOW, ! 217: BytesReceived); ! 218: ! 219: } /* CompleteReceive */ ! 220: ! 221: ! 222: VOID ! 223: StCancelReceive( ! 224: IN PDEVICE_OBJECT DeviceObject, ! 225: IN PIRP Irp ! 226: ) ! 227: ! 228: /*++ ! 229: ! 230: Routine Description: ! 231: ! 232: This routine is called by the I/O system to cancel a receive. ! 233: The receive is found on the connection's receive queue; if it ! 234: is the current request it is cancelled and the connection ! 235: goes into "cancelled receive" mode, otherwise it is cancelled ! 236: silently. ! 237: ! 238: In "cancelled receive" mode the connection makes it appear to ! 239: the remote the data is being received, but in fact it is not ! 240: indicated to the transport or buffered on our end ! 241: ! 242: NOTE: This routine is called with the CancelSpinLock held and ! 243: is responsible for releasing it. ! 244: ! 245: Arguments: ! 246: ! 247: DeviceObject - Pointer to the device object for this driver. ! 248: ! 249: Irp - Pointer to the request packet representing the I/O request. ! 250: ! 251: Return Value: ! 252: ! 253: none. ! 254: ! 255: --*/ ! 256: ! 257: { ! 258: KIRQL oldirql; ! 259: PIO_STACK_LOCATION IrpSp; ! 260: PTP_CONNECTION Connection; ! 261: PTP_REQUEST Request; ! 262: PLIST_ENTRY p; ! 263: ULONG BytesReceived; ! 264: BOOLEAN Found; ! 265: ! 266: UNREFERENCED_PARAMETER (DeviceObject); ! 267: ! 268: // ! 269: // Get a pointer to the current stack location in the IRP. This is where ! 270: // the function codes and parameters are stored. ! 271: // ! 272: ! 273: IrpSp = IoGetCurrentIrpStackLocation (Irp); ! 274: ! 275: ASSERT ((IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) && ! 276: (IrpSp->MinorFunction == TDI_RECEIVE)); ! 277: ! 278: Connection = IrpSp->FileObject->FsContext; ! 279: ! 280: // ! 281: // Since this IRP is still in the cancellable state, we know ! 282: // that the connection is still around (although it may be in ! 283: // the process of being torn down). ! 284: // ! 285: ! 286: // ! 287: // See if this is the IRP for the current receive request. ! 288: // ! 289: ! 290: ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql); ! 291: ! 292: BytesReceived = Connection->MessageBytesReceived; ! 293: ! 294: p = Connection->ReceiveQueue.Flink; ! 295: ! 296: // ! 297: // If there is a receive active, then see if this is it. ! 298: // ! 299: ! 300: if ((Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE) != 0) { ! 301: ! 302: Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage); ! 303: ! 304: if (Request->IoRequestPacket == Irp) { ! 305: ! 306: // ! 307: // yes, it is the active receive. Turn on the RCV_CANCELLED ! 308: // bit instructing the connection to drop the rest of the ! 309: // data received (until the DOL comes in). ! 310: // ! 311: ! 312: Connection->Flags2 |= CONNECTION_FLAGS2_RCV_CANCELLED; ! 313: Connection->Flags &= ~CONNECTION_FLAGS_ACTIVE_RECEIVE; ! 314: ! 315: (VOID)RemoveHeadList (&Connection->ReceiveQueue); ! 316: ! 317: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 318: IoReleaseCancelSpinLock (Irp->CancelIrql); ! 319: ! 320: // ! 321: // The following dereference will complete the I/O, provided removes ! 322: // the last reference on the request object. The I/O will complete ! 323: // with the status and information stored in the Irp. Therefore, ! 324: // we set those values here before the dereference. ! 325: // ! 326: ! 327: StCompleteRequest (Request, STATUS_CANCELLED, 0); ! 328: return; ! 329: ! 330: } ! 331: ! 332: } ! 333: ! 334: ! 335: // ! 336: // If we fall through to here, the IRP was not the active receive. ! 337: // Scan through the list, looking for this IRP. ! 338: // ! 339: ! 340: Found = FALSE; ! 341: ! 342: while (p != &Connection->ReceiveQueue) { ! 343: ! 344: Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage); ! 345: if (Request->IoRequestPacket == Irp) { ! 346: ! 347: // ! 348: // Found it, remove it from the list here. ! 349: // ! 350: ! 351: RemoveEntryList (p); ! 352: Found = TRUE; ! 353: ! 354: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 355: IoReleaseCancelSpinLock (Irp->CancelIrql); ! 356: ! 357: // ! 358: // The following dereference will complete the I/O, provided removes ! 359: // the last reference on the request object. The I/O will complete ! 360: // with the status and information stored in the Irp. Therefore, ! 361: // we set those values here before the dereference. ! 362: // ! 363: ! 364: StCompleteRequest (Request, STATUS_CANCELLED, 0); ! 365: break; ! 366: ! 367: } ! 368: ! 369: p = p->Flink; ! 370: ! 371: } ! 372: ! 373: if (!Found) { ! 374: ! 375: // ! 376: // We didn't find it! ! 377: // ! 378: ! 379: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql); ! 380: IoReleaseCancelSpinLock (Irp->CancelIrql); ! 381: } ! 382: ! 383: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.