NTSTATUS StSendConnect( IN PTP_CONNECTION Connection ) /*++ Routine Description: This routine sends a CONNECT frame of the appropriate type given the state of the specified connection. Arguments: Connection - Pointer to a transport connection object. Return Value: none. --*/ { NTSTATUS Status; PDEVICE_CONTEXT DeviceContext; PUCHAR SourceRouting; UINT SourceRoutingLength; UINT HeaderLength; PSEND_PACKET_TAG SendTag; PTP_PACKET Packet; PST_HEADER StHeader; DeviceContext = Connection->Provider; // // Allocate a packet from the pool. // Status = StCreatePacket (DeviceContext, &Packet); if (!NT_SUCCESS (Status)) { // couldn't make frame. return STATUS_INSUFFICIENT_RESOURCES; } SendTag = (PSEND_PACKET_TAG)(Packet->NdisPacket->ProtocolReserved); SendTag->Type = TYPE_C_FRAME; SendTag->Packet = Packet; SendTag->Owner = (PVOID)Connection; // // Build the MAC header. // // // CONNECT frames go out as // single-route source routing. // MacReturnSingleRouteSR( &DeviceContext->MacInfo, &SourceRouting, &SourceRoutingLength); MacConstructHeader ( &DeviceContext->MacInfo, Packet->Header, DeviceContext->MulticastAddress.Address, DeviceContext->LocalAddress.Address, sizeof(ST_HEADER), SourceRouting, SourceRoutingLength, &HeaderLength); // // Build the header: 'C', dest, source // StHeader = (PST_HEADER)(&Packet->Header[HeaderLength]); StHeader->Signature = ST_SIGNATURE; StHeader->Command = ST_CMD_CONNECT; StHeader->Flags = 0; RtlCopyMemory (StHeader->Destination, Connection->CalledAddress.NetbiosName, 16); RtlCopyMemory (StHeader->Source, Connection->AddressFile->Address->NetworkName->NetbiosName, 16); HeaderLength += sizeof(ST_HEADER); // // Modify the packet length and send the it. // StSetNdisPacketLength(Packet->NdisPacket, HeaderLength); StNdisSend (Packet); return STATUS_SUCCESS; } /* StSendConnect */
VOID NbfTdiRequestTimeoutHandler( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) /*++ Routine Description: This routine is executed as a DPC at DISPATCH_LEVEL when a request such as TdiSend, TdiReceive, TdiSendDatagram, TdiReceiveDatagram, etc., encounters a timeout. This routine cleans up the activity and cancels it. Arguments: Dpc - Pointer to a system DPC object. DeferredContext - Pointer to the TP_REQUEST block representing the request that has timed out. SystemArgument1 - Not used. SystemArgument2 - Not used. Return Value: none. --*/ { KIRQL oldirql; PTP_REQUEST Request; PTP_CONNECTION Connection; #if DBG LARGE_INTEGER time, difference; #endif PIO_STACK_LOCATION IrpSp; PTDI_REQUEST_KERNEL_QUERY_INFORMATION query; PDEVICE_CONTEXT DeviceContext; Dpc, SystemArgument1, SystemArgument2; // prevent compiler warnings ENTER_NBF; Request = (PTP_REQUEST)DeferredContext; IF_NBFDBG (NBF_DEBUG_REQUEST) { NbfPrint1 ("RequestTimeoutHandler: Entered, Request %lx\n", Request); } ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql); Request->Flags &= ~REQUEST_FLAGS_TIMER; if ((Request->Flags & REQUEST_FLAGS_STOPPING) == 0) { #if DBG KeQuerySystemTime (&time); difference.QuadPart = time.QuadPart - (Request->Time).QuadPart; NbfPrint1 ("RequestTimeoutHandler: Request timed out, queued for %ld seconds\n", difference.LowPart / SECONDS); #endif // // find reason for timeout // IrpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket); if (IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) { switch (IrpSp->MinorFunction) { // // none of these should time out. // case TDI_SEND: case TDI_ACCEPT: case TDI_SET_INFORMATION: case TDI_SET_EVENT_HANDLER: case TDI_SEND_DATAGRAM: case TDI_RECEIVE_DATAGRAM: case TDI_RECEIVE: #if DBG NbfPrint1 ("RequestTimeoutHandler: Request: %lx Timed out, and shouldn't have!\n", Request); #endif ASSERT (FALSE); RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql); NbfCompleteRequest (Request, STATUS_IO_TIMEOUT, 0); break; case TDI_LISTEN: case TDI_CONNECT: #if DBG NbfPrint2 ("RequestTimeoutHandler: %s Failed, Request: %lx\n", IrpSp->MinorFunction == TDI_LISTEN ? "Listen" : IrpSp->MinorFunction == TDI_CONNECT ? "Connect" : "Disconnect", Request); #endif Connection = (PTP_CONNECTION)(Request->Context); RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql); // // Since these requests are part of the connection // itself, we just stop the connection and the // request will get torn down then. If we get the // situation where the request times out before // it is queued to the connection, then the code // that is about to queue it will check the STOPPING // flag and complete it then. // // Don't stop the connection if an automatic connection // is in progress. // #ifdef RASAUTODIAL #if DBG DbgPrint("RequestTimeoutHandler: AUTOCONNECTING=0x%x\n", Connection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTING); #endif if (!(Connection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTING)) NbfStopConnection (Connection, STATUS_IO_TIMEOUT); break; #endif case TDI_DISCONNECT: // // We don't create requests for TDI_DISCONNECT any more. // ASSERT(FALSE); break; case TDI_QUERY_INFORMATION: DeviceContext = (PDEVICE_CONTEXT)IrpSp->FileObject->DeviceObject; query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters; IF_NBFDBG (NBF_DEBUG_DEVCTX) { NbfPrint1 ("RequestTimeout: %lx:\n", DeviceContext); } // // Determine if the request is done, or if we should // requeue it. // --Request->Retries; if (Request->Retries > 0) { RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql); // // Send another packet out, and restart the timer. // if (query->QueryType == TDI_QUERY_FIND_NAME) { NbfSendQueryFindName ( DeviceContext, Request); } else if (query->QueryType == TDI_QUERY_ADAPTER_STATUS) { PUCHAR SingleSR; UINT SingleSRLength; // // Send the STATUS_QUERY frames out as // single-route source routing. // // On a second status query this should // really be sent directed, but currently we // don't record the address anywhere. // MacReturnSingleRouteSR( &DeviceContext->MacInfo, &SingleSR, &SingleSRLength); NbfSendStatusQuery ( DeviceContext, Request, &DeviceContext->NetBIOSAddress, SingleSR, SingleSRLength); } else { ASSERT (FALSE); } } else { RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql); // // That's it, we retried enough, complete it. // ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql); RemoveEntryList (&Request->Linkage); RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); if (Request->BytesWritten > 0) { NbfCompleteRequest (Request, STATUS_SUCCESS, Request->BytesWritten); } else { NbfCompleteRequest (Request, STATUS_IO_TIMEOUT, Request->BytesWritten); } } break; default: #if DBG NbfPrint2 ("RequestTimeoutHandler: Unknown Request Timed out, Request: %lx Type: %x\n", Request, IrpSp->MinorFunction); #endif RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql); break; } // end of switch } else {