2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/dispatch.h
5 * PURPOSE: TDI dispatch routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
9 * TODO: Validate device object in all dispatch routines
15 #include <pseh/pseh2.h>
17 typedef struct _QUERY_HW_WORK_ITEM
{
18 PIO_WORKITEM WorkItem
;
20 PIO_STACK_LOCATION IrpSp
;
21 PIP_INTERFACE Interface
;
22 LARGE_INTEGER StartTime
;
24 } QUERY_HW_WORK_ITEM
, *PQUERY_HW_WORK_ITEM
;
26 NTSTATUS
IRPFinish( PIRP Irp
, NTSTATUS Status
) {
29 if (Status
!= STATUS_PENDING
) {
30 Irp
->IoStatus
.Status
= Status
;
31 IoAcquireCancelSpinLock(&OldIrql
);
32 (void)IoSetCancelRoutine( Irp
, NULL
);
33 IoReleaseCancelSpinLock(OldIrql
);
35 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
41 NTSTATUS
DispPrepareIrpForCancel(
42 PTRANSPORT_CONTEXT Context
,
44 PDRIVER_CANCEL CancelRoutine
)
46 * FUNCTION: Prepare an IRP for cancellation
48 * Context = Pointer to context information
49 * Irp = Pointer to an I/O request packet
50 * CancelRoutine = Routine to be called when I/O request is cancelled
56 PIO_STACK_LOCATION IrpSp
;
57 PTRANSPORT_CONTEXT TransContext
;
59 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
61 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
62 TransContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
64 IoAcquireCancelSpinLock(&OldIrql
);
66 if (!Irp
->Cancel
&& !TransContext
->CancelIrps
) {
67 (void)IoSetCancelRoutine(Irp
, CancelRoutine
);
68 IoReleaseCancelSpinLock(OldIrql
);
70 TI_DbgPrint(DEBUG_IRP
, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp
));
72 return STATUS_SUCCESS
;
75 /* IRP has already been cancelled */
77 IoReleaseCancelSpinLock(OldIrql
);
79 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
80 Irp
->IoStatus
.Information
= 0;
82 TI_DbgPrint(DEBUG_IRP
, ("Leaving (IRP was already cancelled).\n"));
84 return Irp
->IoStatus
.Status
;
87 VOID
DispDataRequestComplete(
92 * FUNCTION: Completes a send/receive IRP
94 * Context = Pointer to context information (IRP)
95 * Status = Status of the request
96 * Count = Number of bytes sent or received
101 TI_DbgPrint(DEBUG_IRP
, ("Called for irp %x (%x, %d).\n",
102 Irp
, Status
, Count
));
104 Irp
->IoStatus
.Status
= Status
;
105 Irp
->IoStatus
.Information
= Count
;
107 TI_DbgPrint(MID_TRACE
, ("Irp->IoStatus.Status = %x\n",
108 Irp
->IoStatus
.Status
));
109 TI_DbgPrint(MID_TRACE
, ("Irp->IoStatus.Information = %d\n",
110 Irp
->IoStatus
.Information
));
111 TI_DbgPrint(DEBUG_IRP
, ("Completing IRP at (0x%X).\n", Irp
));
113 IRPFinish(Irp
, Status
);
115 TI_DbgPrint(DEBUG_IRP
, ("Done Completing IRP\n"));
118 VOID NTAPI
DispCancelRequest(
119 PDEVICE_OBJECT Device
,
122 * FUNCTION: Cancels an IRP
124 * Device = Pointer to device object
125 * Irp = Pointer to an I/O request packet
128 PIO_STACK_LOCATION IrpSp
;
129 PTRANSPORT_CONTEXT TranContext
;
130 PFILE_OBJECT FileObject
;
132 PCONNECTION_ENDPOINT Connection
;
133 BOOLEAN DequeuedIrp
= TRUE
;
135 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
137 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
139 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
140 FileObject
= IrpSp
->FileObject
;
141 TranContext
= (PTRANSPORT_CONTEXT
)FileObject
->FsContext
;
142 MinorFunction
= IrpSp
->MinorFunction
;
144 TI_DbgPrint(DEBUG_IRP
, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp
, MinorFunction
, IrpSp
));
146 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
147 Irp
->IoStatus
.Information
= 0;
151 TI_DbgPrint(MIN_TRACE
, ("Irp->Cancel is FALSE, should be TRUE.\n"));
154 /* Try canceling the request */
155 switch(MinorFunction
) {
158 DequeuedIrp
= TCPRemoveIRP( TranContext
->Handle
.ConnectionContext
, Irp
);
161 case TDI_SEND_DATAGRAM
:
162 if (FileObject
->FsContext2
!= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
) {
163 TI_DbgPrint(MIN_TRACE
, ("TDI_SEND_DATAGRAM, but no address file.\n"));
167 DequeuedIrp
= DGRemoveIRP(TranContext
->Handle
.AddressHandle
, Irp
);
170 case TDI_RECEIVE_DATAGRAM
:
171 if (FileObject
->FsContext2
!= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
) {
172 TI_DbgPrint(MIN_TRACE
, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
176 DequeuedIrp
= DGRemoveIRP(TranContext
->Handle
.AddressHandle
, Irp
);
180 DequeuedIrp
= TCPRemoveIRP(TranContext
->Handle
.ConnectionContext
, Irp
);
184 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
186 DequeuedIrp
= TCPRemoveIRP(TranContext
->Handle
.ConnectionContext
, Irp
);
189 if (KeCancelTimer(&Connection
->DisconnectTimer
))
191 DereferenceObject(Connection
);
197 TI_DbgPrint(MIN_TRACE
, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction
));
203 IRPFinish(Irp
, STATUS_CANCELLED
);
205 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
209 VOID NTAPI
DispCancelListenRequest(
210 PDEVICE_OBJECT Device
,
213 * FUNCTION: Cancels a listen IRP
215 * Device = Pointer to device object
216 * Irp = Pointer to an I/O request packet
219 PIO_STACK_LOCATION IrpSp
;
220 PTRANSPORT_CONTEXT TranContext
;
221 PFILE_OBJECT FileObject
;
222 PCONNECTION_ENDPOINT Connection
;
224 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
226 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
228 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
229 FileObject
= IrpSp
->FileObject
;
230 TranContext
= (PTRANSPORT_CONTEXT
)FileObject
->FsContext
;
231 ASSERT( TDI_LISTEN
== IrpSp
->MinorFunction
);
233 TI_DbgPrint(DEBUG_IRP
, ("IRP at (0x%X).\n", Irp
));
237 TI_DbgPrint(MIN_TRACE
, ("Irp->Cancel is FALSE, should be TRUE.\n"));
240 /* Try canceling the request */
241 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
243 if (TCPAbortListenForSocket(Connection
->AddressFile
->Listener
,
246 Irp
->IoStatus
.Information
= 0;
247 IRPFinish(Irp
, STATUS_CANCELLED
);
250 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
254 NTSTATUS
DispTdiAccept(
257 * FUNCTION: TDI_ACCEPT handler
259 * Irp = Pointer to an I/O request packet
261 * Status of operation
264 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
266 return STATUS_NOT_IMPLEMENTED
;
270 NTSTATUS
DispTdiAssociateAddress(
273 * FUNCTION: TDI_ASSOCIATE_ADDRESS handler
275 * Irp = Pointer to an I/O request packet
277 * Status of operation
280 PTDI_REQUEST_KERNEL_ASSOCIATE Parameters
;
281 PTRANSPORT_CONTEXT TranContext
;
282 PIO_STACK_LOCATION IrpSp
;
283 PCONNECTION_ENDPOINT Connection
, LastConnection
;
284 PFILE_OBJECT FileObject
;
285 PADDRESS_FILE AddrFile
= NULL
;
289 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
291 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
293 /* Get associated connection endpoint file object. Quit if none exists */
295 TranContext
= IrpSp
->FileObject
->FsContext
;
297 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
298 return STATUS_INVALID_PARAMETER
;
301 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
303 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
304 return STATUS_INVALID_PARAMETER
;
307 Parameters
= (PTDI_REQUEST_KERNEL_ASSOCIATE
)&IrpSp
->Parameters
;
309 Status
= ObReferenceObjectByHandle(
310 Parameters
->AddressHandle
,
316 if (!NT_SUCCESS(Status
)) {
317 TI_DbgPrint(MID_TRACE
, ("Bad address file object handle (0x%X): %x.\n",
318 Parameters
->AddressHandle
, Status
));
319 return STATUS_INVALID_PARAMETER
;
322 LockObject(Connection
, &OldIrql
);
324 if (Connection
->AddressFile
) {
325 ObDereferenceObject(FileObject
);
326 UnlockObject(Connection
, OldIrql
);
327 TI_DbgPrint(MID_TRACE
, ("An address file is already asscociated.\n"));
328 return STATUS_INVALID_PARAMETER
;
331 if (FileObject
->FsContext2
!= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
) {
332 ObDereferenceObject(FileObject
);
333 UnlockObject(Connection
, OldIrql
);
334 TI_DbgPrint(MID_TRACE
, ("Bad address file object. Magic (0x%X).\n",
335 FileObject
->FsContext2
));
336 return STATUS_INVALID_PARAMETER
;
339 /* Get associated address file object. Quit if none exists */
341 TranContext
= FileObject
->FsContext
;
343 ObDereferenceObject(FileObject
);
344 UnlockObject(Connection
, OldIrql
);
345 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
346 return STATUS_INVALID_PARAMETER
;
349 AddrFile
= (PADDRESS_FILE
)TranContext
->Handle
.AddressHandle
;
351 UnlockObject(Connection
, OldIrql
);
352 ObDereferenceObject(FileObject
);
353 TI_DbgPrint(MID_TRACE
, ("No address file object.\n"));
354 return STATUS_INVALID_PARAMETER
;
357 LockObjectAtDpcLevel(AddrFile
);
359 ReferenceObject(AddrFile
);
360 Connection
->AddressFile
= AddrFile
;
362 /* Add connection endpoint to the address file */
363 ReferenceObject(Connection
);
364 if (AddrFile
->Connection
== NULL
)
365 AddrFile
->Connection
= Connection
;
368 LastConnection
= AddrFile
->Connection
;
369 while (LastConnection
->Next
!= NULL
)
370 LastConnection
= LastConnection
->Next
;
371 LastConnection
->Next
= Connection
;
374 ObDereferenceObject(FileObject
);
376 UnlockObjectFromDpcLevel(AddrFile
);
377 UnlockObject(Connection
, OldIrql
);
379 return STATUS_SUCCESS
;
383 NTSTATUS
DispTdiConnect(
386 * FUNCTION: TDI_CONNECT handler
388 * Irp = Pointer to an I/O request packet
390 * Status of operation
393 PCONNECTION_ENDPOINT Connection
;
394 PTDI_REQUEST_KERNEL Parameters
;
395 PTRANSPORT_CONTEXT TranContext
;
396 PIO_STACK_LOCATION IrpSp
;
399 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
401 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
403 /* Get associated connection endpoint file object. Quit if none exists */
405 TranContext
= IrpSp
->FileObject
->FsContext
;
407 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
408 Status
= STATUS_INVALID_PARAMETER
;
412 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
414 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
415 Status
= STATUS_INVALID_PARAMETER
;
419 Parameters
= (PTDI_REQUEST_KERNEL
)&IrpSp
->Parameters
;
421 Status
= DispPrepareIrpForCancel(TranContext
->Handle
.ConnectionContext
,
425 if (NT_SUCCESS(Status
)) {
427 TranContext
->Handle
.ConnectionContext
,
428 Parameters
->RequestConnectionInformation
,
429 Parameters
->ReturnConnectionInformation
,
430 DispDataRequestComplete
,
435 if (Status
!= STATUS_PENDING
) {
436 DispDataRequestComplete(Irp
, Status
, 0);
438 IoMarkIrpPending(Irp
);
440 TI_DbgPrint(MAX_TRACE
, ("TCP Connect returned %08x\n", Status
));
446 NTSTATUS
DispTdiDisassociateAddress(
449 * FUNCTION: TDI_DISASSOCIATE_ADDRESS handler
451 * Irp = Pointer to an I/O request packet
453 * Status of operation
456 PCONNECTION_ENDPOINT Connection
;
457 PTRANSPORT_CONTEXT TranContext
;
458 PIO_STACK_LOCATION IrpSp
;
460 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
462 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
464 /* Get associated connection endpoint file object. Quit if none exists */
466 TranContext
= IrpSp
->FileObject
->FsContext
;
468 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
469 return STATUS_INVALID_PARAMETER
;
472 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
474 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
475 return STATUS_INVALID_PARAMETER
;
478 /* NO-OP because we need the address to deallocate the port when the connection closes */
480 return STATUS_SUCCESS
;
484 NTSTATUS
DispTdiDisconnect(
487 * FUNCTION: TDI_DISCONNECT handler
489 * Irp = Pointer to an I/O request packet
491 * Status of operation
495 PTDI_REQUEST_KERNEL_DISCONNECT DisReq
;
496 PCONNECTION_ENDPOINT Connection
;
497 PTRANSPORT_CONTEXT TranContext
;
498 PIO_STACK_LOCATION IrpSp
;
500 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
502 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
503 DisReq
= (PTDI_REQUEST_KERNEL_DISCONNECT
)&IrpSp
->Parameters
;
505 /* Get associated connection endpoint file object. Quit if none exists */
507 TranContext
= IrpSp
->FileObject
->FsContext
;
509 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
510 Status
= STATUS_INVALID_PARAMETER
;
514 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
516 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
517 Status
= STATUS_INVALID_PARAMETER
;
521 Status
= DispPrepareIrpForCancel
522 (TranContext
->Handle
.ConnectionContext
,
524 (PDRIVER_CANCEL
)DispCancelRequest
);
526 if (NT_SUCCESS(Status
))
528 Status
= TCPDisconnect(TranContext
->Handle
.ConnectionContext
,
529 DisReq
->RequestFlags
,
530 DisReq
->RequestSpecific
,
531 DisReq
->RequestConnectionInformation
,
532 DisReq
->ReturnConnectionInformation
,
533 DispDataRequestComplete
,
538 if (Status
!= STATUS_PENDING
) {
539 DispDataRequestComplete(Irp
, Status
, 0);
541 IoMarkIrpPending(Irp
);
543 TI_DbgPrint(MAX_TRACE
, ("TCP Disconnect returned %08x\n", Status
));
549 NTSTATUS
DispTdiListen(
552 * FUNCTION: TDI_LISTEN handler
554 * Irp = Pointer to an I/O request packet
556 * Status of operation
559 PCONNECTION_ENDPOINT Connection
;
560 PTDI_REQUEST_KERNEL Parameters
;
561 PTRANSPORT_CONTEXT TranContext
;
562 PIO_STACK_LOCATION IrpSp
;
563 NTSTATUS Status
= STATUS_SUCCESS
;
566 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
568 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
570 /* Get associated connection endpoint file object. Quit if none exists */
572 TranContext
= IrpSp
->FileObject
->FsContext
;
573 if (TranContext
== NULL
)
575 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
576 Status
= STATUS_INVALID_PARAMETER
;
580 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
581 if (Connection
== NULL
)
583 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
584 Status
= STATUS_INVALID_PARAMETER
;
588 Parameters
= (PTDI_REQUEST_KERNEL
)&IrpSp
->Parameters
;
590 Status
= DispPrepareIrpForCancel
591 (TranContext
->Handle
.ConnectionContext
,
593 (PDRIVER_CANCEL
)DispCancelListenRequest
);
595 LockObject(Connection
, &OldIrql
);
597 if (Connection
->AddressFile
== NULL
)
599 TI_DbgPrint(MID_TRACE
, ("No associated address file\n"));
600 UnlockObject(Connection
, OldIrql
);
601 Status
= STATUS_INVALID_PARAMETER
;
605 LockObjectAtDpcLevel(Connection
->AddressFile
);
607 /* Listening will require us to create a listening socket and store it in
608 * the address file. It will be signalled, and attempt to complete an irp
609 * when a new connection arrives. */
610 /* The important thing to note here is that the irp we'll complete belongs
611 * to the socket to be accepted onto, not the listener */
612 if( NT_SUCCESS(Status
) && !Connection
->AddressFile
->Listener
) {
613 Connection
->AddressFile
->Listener
=
614 TCPAllocateConnectionEndpoint( NULL
);
616 if( !Connection
->AddressFile
->Listener
)
617 Status
= STATUS_NO_MEMORY
;
619 if( NT_SUCCESS(Status
) ) {
620 ReferenceObject(Connection
->AddressFile
);
621 Connection
->AddressFile
->Listener
->AddressFile
=
622 Connection
->AddressFile
;
624 Status
= TCPSocket( Connection
->AddressFile
->Listener
,
625 Connection
->AddressFile
->Family
,
627 Connection
->AddressFile
->Protocol
);
630 if( NT_SUCCESS(Status
) ) {
631 ReferenceObject(Connection
->AddressFile
->Listener
);
632 Status
= TCPListen( Connection
->AddressFile
->Listener
, 1024 );
637 if( NT_SUCCESS(Status
) ) {
639 ( (PTDI_REQUEST
)Parameters
,
640 Connection
->AddressFile
->Listener
,
642 DispDataRequestComplete
,
646 UnlockObjectFromDpcLevel(Connection
->AddressFile
);
647 UnlockObject(Connection
, OldIrql
);
650 if (Status
!= STATUS_PENDING
) {
651 DispDataRequestComplete(Irp
, Status
, 0);
653 IoMarkIrpPending(Irp
);
655 TI_DbgPrint(MID_TRACE
,("Leaving %x\n", Status
));
661 NTSTATUS
DispTdiQueryInformation(
662 PDEVICE_OBJECT DeviceObject
,
665 * FUNCTION: TDI_QUERY_INFORMATION handler
667 * DeviceObject = Pointer to device object structure
668 * Irp = Pointer to an I/O request packet
670 * Status of operation
673 PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters
;
674 PTRANSPORT_CONTEXT TranContext
;
675 PIO_STACK_LOCATION IrpSp
;
677 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
679 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
680 Parameters
= (PTDI_REQUEST_KERNEL_QUERY_INFORMATION
)&IrpSp
->Parameters
;
682 TranContext
= IrpSp
->FileObject
->FsContext
;
684 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
685 return STATUS_INVALID_PARAMETER
;
688 switch (Parameters
->QueryType
)
690 case TDI_QUERY_ADDRESS_INFO
:
692 PTDI_ADDRESS_INFO AddressInfo
;
693 PADDRESS_FILE AddrFile
;
694 PTA_IP_ADDRESS Address
;
695 PCONNECTION_ENDPOINT Endpoint
= NULL
;
698 if (MmGetMdlByteCount(Irp
->MdlAddress
) <
699 (FIELD_OFFSET(TDI_ADDRESS_INFO
, Address
.Address
[0].Address
) +
700 sizeof(TDI_ADDRESS_IP
))) {
701 TI_DbgPrint(MID_TRACE
, ("MDL buffer too small.\n"));
702 return STATUS_BUFFER_TOO_SMALL
;
705 AddressInfo
= (PTDI_ADDRESS_INFO
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
706 Address
= (PTA_IP_ADDRESS
)&AddressInfo
->Address
;
708 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
709 case TDI_TRANSPORT_ADDRESS_FILE
:
710 AddrFile
= (PADDRESS_FILE
)TranContext
->Handle
.AddressHandle
;
712 Address
->TAAddressCount
= 1;
713 Address
->Address
[0].AddressLength
= TDI_ADDRESS_LENGTH_IP
;
714 Address
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
715 Address
->Address
[0].Address
[0].sin_port
= AddrFile
->Port
;
716 Address
->Address
[0].Address
[0].in_addr
= AddrFile
->Address
.Address
.IPv4Address
;
718 &Address
->Address
[0].Address
[0].sin_zero
,
719 sizeof(Address
->Address
[0].Address
[0].sin_zero
));
720 return STATUS_SUCCESS
;
722 case TDI_CONNECTION_FILE
:
724 (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
726 Address
->TAAddressCount
= 1;
727 Address
->Address
[0].AddressLength
= TDI_ADDRESS_LENGTH_IP
;
728 Address
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
729 Address
->Address
[0].Address
[0].sin_port
= Endpoint
->AddressFile
->Port
;
730 Address
->Address
[0].Address
[0].in_addr
= Endpoint
->AddressFile
->Address
.Address
.IPv4Address
;
732 &Address
->Address
[0].Address
[0].sin_zero
,
733 sizeof(Address
->Address
[0].Address
[0].sin_zero
));
734 return STATUS_SUCCESS
;
737 TI_DbgPrint(MIN_TRACE
, ("Invalid transport context\n"));
738 return STATUS_INVALID_PARAMETER
;
742 case TDI_QUERY_CONNECTION_INFO
:
744 PTDI_CONNECTION_INFO ConnectionInfo
;
745 //PCONNECTION_ENDPOINT Endpoint;
747 if (MmGetMdlByteCount(Irp
->MdlAddress
) < sizeof(*ConnectionInfo
)) {
748 TI_DbgPrint(MID_TRACE
, ("MDL buffer too small.\n"));
749 return STATUS_BUFFER_TOO_SMALL
;
752 ConnectionInfo
= (PTDI_CONNECTION_INFO
)
753 MmGetSystemAddressForMdl(Irp
->MdlAddress
);
755 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
756 case TDI_CONNECTION_FILE
:
757 //Endpoint = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
758 RtlZeroMemory(ConnectionInfo
, sizeof(*ConnectionInfo
));
759 return STATUS_SUCCESS
;
762 TI_DbgPrint(MIN_TRACE
, ("Invalid transport context\n"));
763 return STATUS_INVALID_PARAMETER
;
767 case TDI_QUERY_MAX_DATAGRAM_INFO
:
769 PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo
;
771 if (MmGetMdlByteCount(Irp
->MdlAddress
) < sizeof(*MaxDatagramInfo
)) {
772 TI_DbgPrint(MID_TRACE
, ("MDL buffer too small.\n"));
773 return STATUS_BUFFER_TOO_SMALL
;
776 MaxDatagramInfo
= (PTDI_MAX_DATAGRAM_INFO
)
777 MmGetSystemAddressForMdl(Irp
->MdlAddress
);
779 MaxDatagramInfo
->MaxDatagramSize
= 0xFFFF;
781 return STATUS_SUCCESS
;
785 return STATUS_NOT_IMPLEMENTED
;
789 NTSTATUS
DispTdiReceive(
792 * FUNCTION: TDI_RECEIVE handler
794 * Irp = Pointer to an I/O request packet
796 * Status of operation
799 PIO_STACK_LOCATION IrpSp
;
800 PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo
;
801 PTRANSPORT_CONTEXT TranContext
;
803 ULONG BytesReceived
= 0;
805 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
807 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
808 ReceiveInfo
= (PTDI_REQUEST_KERNEL_RECEIVE
)&(IrpSp
->Parameters
);
810 TranContext
= IrpSp
->FileObject
->FsContext
;
811 if (TranContext
== NULL
)
813 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
814 Status
= STATUS_INVALID_PARAMETER
;
818 if (TranContext
->Handle
.ConnectionContext
== NULL
)
820 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
821 Status
= STATUS_INVALID_PARAMETER
;
825 /* Initialize a receive request */
826 Status
= DispPrepareIrpForCancel
827 (TranContext
->Handle
.ConnectionContext
,
829 (PDRIVER_CANCEL
)DispCancelRequest
);
831 TI_DbgPrint(MID_TRACE
,("TCPIP<<< Got an MDL: %x\n", Irp
->MdlAddress
));
832 if (NT_SUCCESS(Status
))
834 Status
= TCPReceiveData(
835 TranContext
->Handle
.ConnectionContext
,
836 (PNDIS_BUFFER
)Irp
->MdlAddress
,
837 ReceiveInfo
->ReceiveLength
,
839 ReceiveInfo
->ReceiveFlags
,
840 DispDataRequestComplete
,
845 if (Status
!= STATUS_PENDING
) {
846 DispDataRequestComplete(Irp
, Status
, BytesReceived
);
848 IoMarkIrpPending(Irp
);
850 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status is (0x%X)\n", Status
));
856 NTSTATUS
DispTdiReceiveDatagram(
859 * FUNCTION: TDI_RECEIVE_DATAGRAM handler
861 * Irp = Pointer to an I/O request packet
863 * Status of operation
866 PIO_STACK_LOCATION IrpSp
;
867 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo
;
868 PTRANSPORT_CONTEXT TranContext
;
871 ULONG BytesReceived
= 0;
873 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
875 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
876 DgramInfo
= (PTDI_REQUEST_KERNEL_RECEIVEDG
)&(IrpSp
->Parameters
);
878 TranContext
= IrpSp
->FileObject
->FsContext
;
879 if (TranContext
== NULL
)
881 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
882 Status
= STATUS_INVALID_PARAMETER
;
886 /* Initialize a receive request */
887 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
888 Request
.RequestNotifyObject
= DispDataRequestComplete
;
889 Request
.RequestContext
= Irp
;
891 Status
= DispPrepareIrpForCancel(
892 IrpSp
->FileObject
->FsContext
,
894 (PDRIVER_CANCEL
)DispCancelRequest
);
896 if (NT_SUCCESS(Status
))
901 NdisQueryBuffer( (PNDIS_BUFFER
)Irp
->MdlAddress
,
905 Status
= DGReceiveDatagram(
906 Request
.Handle
.AddressHandle
,
907 DgramInfo
->ReceiveDatagramInformation
,
909 DgramInfo
->ReceiveLength
,
910 DgramInfo
->ReceiveFlags
,
911 DgramInfo
->ReturnDatagramInformation
,
913 (PDATAGRAM_COMPLETION_ROUTINE
)DispDataRequestComplete
,
919 if (Status
!= STATUS_PENDING
) {
920 DispDataRequestComplete(Irp
, Status
, BytesReceived
);
922 IoMarkIrpPending(Irp
);
924 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status is (0x%X)\n", Status
));
930 NTSTATUS
DispTdiSend(
933 * FUNCTION: TDI_SEND handler
935 * Irp = Pointer to an I/O request packet
937 * Status of operation
940 PIO_STACK_LOCATION IrpSp
;
941 PTDI_REQUEST_KERNEL_SEND SendInfo
;
942 PTRANSPORT_CONTEXT TranContext
;
946 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
948 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
949 SendInfo
= (PTDI_REQUEST_KERNEL_SEND
)&(IrpSp
->Parameters
);
951 TranContext
= IrpSp
->FileObject
->FsContext
;
952 if (TranContext
== NULL
)
954 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
955 Status
= STATUS_INVALID_PARAMETER
;
959 if (TranContext
->Handle
.ConnectionContext
== NULL
)
961 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
962 Status
= STATUS_INVALID_PARAMETER
;
966 Status
= DispPrepareIrpForCancel(
967 IrpSp
->FileObject
->FsContext
,
969 (PDRIVER_CANCEL
)DispCancelRequest
);
971 TI_DbgPrint(MID_TRACE
,("TCPIP<<< Got an MDL: %x\n", Irp
->MdlAddress
));
972 if (NT_SUCCESS(Status
))
977 NdisQueryBuffer( Irp
->MdlAddress
, &Data
, &Len
);
979 TI_DbgPrint(MID_TRACE
,("About to TCPSendData\n"));
980 Status
= TCPSendData(
981 TranContext
->Handle
.ConnectionContext
,
983 SendInfo
->SendLength
,
986 DispDataRequestComplete
,
991 if (Status
!= STATUS_PENDING
) {
992 DispDataRequestComplete(Irp
, Status
, BytesSent
);
994 IoMarkIrpPending(Irp
);
996 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status is (0x%X)\n", Status
));
1002 NTSTATUS
DispTdiSendDatagram(
1005 * FUNCTION: TDI_SEND_DATAGRAM handler
1007 * Irp = Pointer to an I/O request packet
1009 * Status of operation
1012 PIO_STACK_LOCATION IrpSp
;
1013 TDI_REQUEST Request
;
1014 PTDI_REQUEST_KERNEL_SENDDG DgramInfo
;
1015 PTRANSPORT_CONTEXT TranContext
;
1018 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
1020 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1021 DgramInfo
= (PTDI_REQUEST_KERNEL_SENDDG
)&(IrpSp
->Parameters
);
1023 TranContext
= IrpSp
->FileObject
->FsContext
;
1024 if (TranContext
== NULL
)
1026 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
1027 Status
= STATUS_INVALID_PARAMETER
;
1031 /* Initialize a send request */
1032 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
1033 Request
.RequestNotifyObject
= DispDataRequestComplete
;
1034 Request
.RequestContext
= Irp
;
1036 Status
= DispPrepareIrpForCancel(
1037 IrpSp
->FileObject
->FsContext
,
1039 (PDRIVER_CANCEL
)DispCancelRequest
);
1041 if (NT_SUCCESS(Status
)) {
1045 TI_DbgPrint(MID_TRACE
,("About to query buffer %x\n", Irp
->MdlAddress
));
1047 NdisQueryBuffer( (PNDIS_BUFFER
)Irp
->MdlAddress
,
1051 /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
1052 must be of type PTDI_ADDRESS_IP */
1053 TI_DbgPrint(MID_TRACE
,
1054 ("About to call send routine %x\n",
1055 (*((PADDRESS_FILE
)Request
.Handle
.AddressHandle
)->Send
)));
1057 if( (*((PADDRESS_FILE
)Request
.Handle
.AddressHandle
)->Send
!= NULL
) )
1060 Status
= (*((PADDRESS_FILE
)Request
.Handle
.AddressHandle
)->Send
)(
1061 Request
.Handle
.AddressHandle
,
1062 DgramInfo
->SendDatagramInformation
,
1066 Irp
->IoStatus
.Information
= DataUsed
;
1069 Status
= STATUS_UNSUCCESSFUL
;
1075 if (Status
!= STATUS_PENDING
) {
1076 DispDataRequestComplete(Irp
, Status
, Irp
->IoStatus
.Information
);
1078 IoMarkIrpPending(Irp
);
1080 TI_DbgPrint(DEBUG_IRP
, ("Leaving.\n"));
1086 NTSTATUS
DispTdiSetEventHandler(PIRP Irp
)
1088 * FUNCTION: TDI_SET_EVENT_HANDER handler
1090 * Irp = Pointer to a I/O request packet
1092 * Status of operation
1095 PTDI_REQUEST_KERNEL_SET_EVENT Parameters
;
1096 PTRANSPORT_CONTEXT TranContext
;
1097 PIO_STACK_LOCATION IrpSp
;
1098 PADDRESS_FILE AddrFile
;
1102 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
1104 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1106 /* Get associated address file object. Quit if none exists */
1108 TranContext
= IrpSp
->FileObject
->FsContext
;
1110 TI_DbgPrint(MIN_TRACE
, ("Bad transport context.\n"));
1111 return STATUS_INVALID_PARAMETER
;
1114 AddrFile
= (PADDRESS_FILE
)TranContext
->Handle
.AddressHandle
;
1116 TI_DbgPrint(MIN_TRACE
, ("No address file object.\n"));
1117 return STATUS_INVALID_PARAMETER
;
1120 Parameters
= (PTDI_REQUEST_KERNEL_SET_EVENT
)&IrpSp
->Parameters
;
1121 Status
= STATUS_SUCCESS
;
1123 LockObject(AddrFile
, &OldIrql
);
1125 /* Set the event handler. if an event handler is associated with
1126 a specific event, it's flag (RegisteredXxxHandler) is TRUE.
1127 If an event handler is not used it's flag is FALSE */
1128 switch (Parameters
->EventType
) {
1129 case TDI_EVENT_CONNECT
:
1130 if (!Parameters
->EventHandler
) {
1131 AddrFile
->ConnectHandlerContext
= NULL
;
1132 AddrFile
->RegisteredConnectHandler
= FALSE
;
1134 AddrFile
->ConnectHandler
=
1135 (PTDI_IND_CONNECT
)Parameters
->EventHandler
;
1136 AddrFile
->ConnectHandlerContext
= Parameters
->EventContext
;
1137 AddrFile
->RegisteredConnectHandler
= TRUE
;
1141 case TDI_EVENT_DISCONNECT
:
1142 if (!Parameters
->EventHandler
) {
1143 AddrFile
->DisconnectHandlerContext
= NULL
;
1144 AddrFile
->RegisteredDisconnectHandler
= FALSE
;
1146 AddrFile
->DisconnectHandler
=
1147 (PTDI_IND_DISCONNECT
)Parameters
->EventHandler
;
1148 AddrFile
->DisconnectHandlerContext
= Parameters
->EventContext
;
1149 AddrFile
->RegisteredDisconnectHandler
= TRUE
;
1153 case TDI_EVENT_ERROR
:
1154 if (Parameters
->EventHandler
== NULL
) {
1155 AddrFile
->ErrorHandlerContext
= NULL
;
1156 AddrFile
->RegisteredErrorHandler
= FALSE
;
1158 AddrFile
->ErrorHandler
=
1159 (PTDI_IND_ERROR
)Parameters
->EventHandler
;
1160 AddrFile
->ErrorHandlerContext
= Parameters
->EventContext
;
1161 AddrFile
->RegisteredErrorHandler
= TRUE
;
1165 case TDI_EVENT_RECEIVE
:
1166 if (Parameters
->EventHandler
== NULL
) {
1167 AddrFile
->ReceiveHandlerContext
= NULL
;
1168 AddrFile
->RegisteredReceiveHandler
= FALSE
;
1170 AddrFile
->ReceiveHandler
=
1171 (PTDI_IND_RECEIVE
)Parameters
->EventHandler
;
1172 AddrFile
->ReceiveHandlerContext
= Parameters
->EventContext
;
1173 AddrFile
->RegisteredReceiveHandler
= TRUE
;
1177 case TDI_EVENT_RECEIVE_DATAGRAM
:
1178 if (Parameters
->EventHandler
== NULL
) {
1179 AddrFile
->ReceiveDatagramHandlerContext
= NULL
;
1180 AddrFile
->RegisteredReceiveDatagramHandler
= FALSE
;
1182 AddrFile
->ReceiveDatagramHandler
=
1183 (PTDI_IND_RECEIVE_DATAGRAM
)Parameters
->EventHandler
;
1184 AddrFile
->ReceiveDatagramHandlerContext
= Parameters
->EventContext
;
1185 AddrFile
->RegisteredReceiveDatagramHandler
= TRUE
;
1189 case TDI_EVENT_RECEIVE_EXPEDITED
:
1190 if (Parameters
->EventHandler
== NULL
) {
1191 AddrFile
->ExpeditedReceiveHandlerContext
= NULL
;
1192 AddrFile
->RegisteredExpeditedReceiveHandler
= FALSE
;
1194 AddrFile
->ExpeditedReceiveHandler
=
1195 (PTDI_IND_RECEIVE_EXPEDITED
)Parameters
->EventHandler
;
1196 AddrFile
->ExpeditedReceiveHandlerContext
= Parameters
->EventContext
;
1197 AddrFile
->RegisteredExpeditedReceiveHandler
= TRUE
;
1201 case TDI_EVENT_CHAINED_RECEIVE
:
1202 if (Parameters
->EventHandler
== NULL
) {
1203 AddrFile
->ChainedReceiveHandlerContext
= NULL
;
1204 AddrFile
->RegisteredChainedReceiveHandler
= FALSE
;
1206 AddrFile
->ChainedReceiveHandler
=
1207 (PTDI_IND_CHAINED_RECEIVE
)Parameters
->EventHandler
;
1208 AddrFile
->ChainedReceiveHandlerContext
= Parameters
->EventContext
;
1209 AddrFile
->RegisteredChainedReceiveHandler
= TRUE
;
1213 case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
:
1214 if (Parameters
->EventHandler
== NULL
) {
1215 AddrFile
->ChainedReceiveDatagramHandlerContext
= NULL
;
1216 AddrFile
->RegisteredChainedReceiveDatagramHandler
= FALSE
;
1218 AddrFile
->ChainedReceiveDatagramHandler
=
1219 (PTDI_IND_CHAINED_RECEIVE_DATAGRAM
)Parameters
->EventHandler
;
1220 AddrFile
->ChainedReceiveDatagramHandlerContext
= Parameters
->EventContext
;
1221 AddrFile
->RegisteredChainedReceiveDatagramHandler
= TRUE
;
1225 case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
:
1226 if (Parameters
->EventHandler
== NULL
) {
1227 AddrFile
->ChainedReceiveExpeditedHandlerContext
= NULL
;
1228 AddrFile
->RegisteredChainedReceiveExpeditedHandler
= FALSE
;
1230 AddrFile
->ChainedReceiveExpeditedHandler
=
1231 (PTDI_IND_CHAINED_RECEIVE_EXPEDITED
)Parameters
->EventHandler
;
1232 AddrFile
->ChainedReceiveExpeditedHandlerContext
= Parameters
->EventContext
;
1233 AddrFile
->RegisteredChainedReceiveExpeditedHandler
= TRUE
;
1238 TI_DbgPrint(MIN_TRACE
, ("Unknown event type (0x%X).\n",
1239 Parameters
->EventType
));
1241 Status
= STATUS_INVALID_PARAMETER
;
1244 UnlockObject(AddrFile
, OldIrql
);
1250 NTSTATUS
DispTdiSetInformation(
1253 * FUNCTION: TDI_SET_INFORMATION handler
1255 * Irp = Pointer to an I/O request packet
1257 * Status of operation
1260 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
1262 return STATUS_NOT_IMPLEMENTED
;
1266 VOID
DispTdiQueryInformationExComplete(
1271 * FUNCTION: Completes a TDI QueryInformationEx request
1273 * Context = Pointer to the IRP for the request
1274 * Status = TDI status of the request
1275 * ByteCount = Number of bytes returned in output buffer
1278 PTI_QUERY_CONTEXT QueryContext
;
1280 QueryContext
= (PTI_QUERY_CONTEXT
)Context
;
1281 if (NT_SUCCESS(Status
)) {
1282 CopyBufferToBufferChain(
1283 QueryContext
->InputMdl
,
1284 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX
, Context
),
1285 (PCHAR
)&QueryContext
->QueryInfo
.Context
,
1289 MmUnlockPages(QueryContext
->InputMdl
);
1290 IoFreeMdl(QueryContext
->InputMdl
);
1291 if( QueryContext
->OutputMdl
) {
1292 MmUnlockPages(QueryContext
->OutputMdl
);
1293 IoFreeMdl(QueryContext
->OutputMdl
);
1296 QueryContext
->Irp
->IoStatus
.Information
= ByteCount
;
1297 QueryContext
->Irp
->IoStatus
.Status
= Status
;
1299 ExFreePoolWithTag(QueryContext
, QUERY_CONTEXT_TAG
);
1303 NTSTATUS
DispTdiQueryInformationEx(
1305 PIO_STACK_LOCATION IrpSp
)
1307 * FUNCTION: TDI QueryInformationEx handler
1309 * Irp = Pointer to I/O request packet
1310 * IrpSp = Pointer to current stack location of Irp
1312 * Status of operation
1315 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer
;
1316 PTRANSPORT_CONTEXT TranContext
;
1317 PTI_QUERY_CONTEXT QueryContext
;
1319 TDI_REQUEST Request
;
1321 UINT InputBufferLength
;
1322 UINT OutputBufferLength
;
1323 BOOLEAN InputMdlLocked
= FALSE
;
1324 BOOLEAN OutputMdlLocked
= FALSE
;
1325 PMDL InputMdl
= NULL
;
1326 PMDL OutputMdl
= NULL
;
1327 NTSTATUS Status
= STATUS_SUCCESS
;
1329 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
1331 TranContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
1333 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
1334 case TDI_TRANSPORT_ADDRESS_FILE
:
1335 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
1338 case TDI_CONNECTION_FILE
:
1339 Request
.Handle
.ConnectionContext
= TranContext
->Handle
.ConnectionContext
;
1342 case TDI_CONTROL_CHANNEL_FILE
:
1343 Request
.Handle
.ControlChannel
= TranContext
->Handle
.ControlChannel
;
1347 TI_DbgPrint(MIN_TRACE
, ("Invalid transport context\n"));
1348 return STATUS_INVALID_PARAMETER
;
1351 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
1352 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1354 /* Validate parameters */
1355 if ((InputBufferLength
== sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
)) &&
1356 (OutputBufferLength
!= 0)) {
1358 InputBuffer
= (PTCP_REQUEST_QUERY_INFORMATION_EX
)
1359 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
1360 OutputBuffer
= Irp
->UserBuffer
;
1362 QueryContext
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(TI_QUERY_CONTEXT
), QUERY_CONTEXT_TAG
);
1365 InputMdl
= IoAllocateMdl(InputBuffer
,
1366 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
),
1369 OutputMdl
= IoAllocateMdl(OutputBuffer
,
1370 OutputBufferLength
, FALSE
, TRUE
, NULL
);
1372 if (InputMdl
&& OutputMdl
) {
1374 MmProbeAndLockPages(InputMdl
, Irp
->RequestorMode
,
1377 InputMdlLocked
= TRUE
;
1379 MmProbeAndLockPages(OutputMdl
, Irp
->RequestorMode
,
1382 OutputMdlLocked
= TRUE
;
1384 RtlCopyMemory(&QueryContext
->QueryInfo
,
1385 InputBuffer
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
1387 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1388 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1389 Status
= _SEH2_GetExceptionCode();
1392 if (NT_SUCCESS(Status
)) {
1393 Size
= MmGetMdlByteCount(OutputMdl
);
1395 QueryContext
->Irp
= Irp
;
1396 QueryContext
->InputMdl
= InputMdl
;
1397 QueryContext
->OutputMdl
= OutputMdl
;
1399 Request
.RequestNotifyObject
= DispTdiQueryInformationExComplete
;
1400 Request
.RequestContext
= QueryContext
;
1401 Status
= InfoTdiQueryInformationEx(&Request
,
1402 &QueryContext
->QueryInfo
.ID
, OutputMdl
,
1403 &Size
, &QueryContext
->QueryInfo
.Context
);
1404 DispTdiQueryInformationExComplete(QueryContext
, Status
, Size
);
1406 TI_DbgPrint(MAX_TRACE
, ("Leaving. Status = (0x%X)\n", Status
));
1411 /* An error occurred if we get here */
1415 MmUnlockPages(InputMdl
);
1416 IoFreeMdl(InputMdl
);
1420 if (OutputMdlLocked
)
1421 MmUnlockPages(OutputMdl
);
1422 IoFreeMdl(OutputMdl
);
1425 ExFreePoolWithTag(QueryContext
, QUERY_CONTEXT_TAG
);
1427 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1428 } else if( InputBufferLength
==
1429 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
) ) {
1430 /* Handle the case where the user is probing the buffer for length */
1431 TI_DbgPrint(MAX_TRACE
, ("InputBufferLength %d OutputBufferLength %d\n",
1432 InputBufferLength
, OutputBufferLength
));
1433 InputBuffer
= (PTCP_REQUEST_QUERY_INFORMATION_EX
)
1434 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
1438 QueryContext
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(TI_QUERY_CONTEXT
), QUERY_CONTEXT_TAG
);
1439 if (!QueryContext
) return STATUS_INSUFFICIENT_RESOURCES
;
1442 InputMdl
= IoAllocateMdl(InputBuffer
,
1443 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
),
1446 MmProbeAndLockPages(InputMdl
, Irp
->RequestorMode
,
1449 InputMdlLocked
= TRUE
;
1450 Status
= STATUS_SUCCESS
;
1451 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1452 TI_DbgPrint(MAX_TRACE
, ("Failed to acquire client buffer\n"));
1453 Status
= _SEH2_GetExceptionCode();
1456 if( !NT_SUCCESS(Status
) || !InputMdl
) {
1457 if( InputMdl
) IoFreeMdl( InputMdl
);
1458 ExFreePoolWithTag(QueryContext
, QUERY_CONTEXT_TAG
);
1462 RtlCopyMemory(&QueryContext
->QueryInfo
,
1463 InputBuffer
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
1465 QueryContext
->Irp
= Irp
;
1466 QueryContext
->InputMdl
= InputMdl
;
1467 QueryContext
->OutputMdl
= NULL
;
1469 Request
.RequestNotifyObject
= DispTdiQueryInformationExComplete
;
1470 Request
.RequestContext
= QueryContext
;
1471 Status
= InfoTdiQueryInformationEx(&Request
,
1472 &QueryContext
->QueryInfo
.ID
,
1475 &QueryContext
->QueryInfo
.Context
);
1476 DispTdiQueryInformationExComplete(QueryContext
, Status
, Size
);
1477 TI_DbgPrint(MAX_TRACE
, ("Leaving. Status = (0x%X)\n", Status
));
1478 } else Status
= STATUS_INVALID_PARAMETER
;
1480 TI_DbgPrint(MIN_TRACE
, ("Leaving. Status = (0x%X)\n", Status
));
1486 NTSTATUS
DispTdiSetInformationEx(
1488 PIO_STACK_LOCATION IrpSp
)
1490 * FUNCTION: TDI SetInformationEx handler
1492 * Irp = Pointer to I/O request packet
1493 * IrpSp = Pointer to current stack location of Irp
1495 * Status of operation
1498 PTRANSPORT_CONTEXT TranContext
;
1499 PTCP_REQUEST_SET_INFORMATION_EX Info
;
1500 TDI_REQUEST Request
;
1503 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
1505 TranContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
1506 Info
= (PTCP_REQUEST_SET_INFORMATION_EX
)Irp
->AssociatedIrp
.SystemBuffer
;
1508 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
1509 case TDI_TRANSPORT_ADDRESS_FILE
:
1510 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
1513 case TDI_CONNECTION_FILE
:
1514 Request
.Handle
.ConnectionContext
= TranContext
->Handle
.ConnectionContext
;
1517 case TDI_CONTROL_CHANNEL_FILE
:
1518 Request
.Handle
.ControlChannel
= TranContext
->Handle
.ControlChannel
;
1522 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1523 Irp
->IoStatus
.Information
= 0;
1525 TI_DbgPrint(DEBUG_IRP
, ("Completing IRP at (0x%X).\n", Irp
));
1527 return Irp
->IoStatus
.Status
;
1530 Request
.RequestNotifyObject
= NULL
;
1531 Request
.RequestContext
= NULL
;
1533 Status
= InfoTdiSetInformationEx(&Request
, &Info
->ID
,
1534 &Info
->Buffer
, Info
->BufferSize
);
1539 /* TODO: Support multiple addresses per interface.
1540 * For now just set the nte context to the interface index.
1542 * Later on, create an NTE context and NTE instance
1545 NTSTATUS
DispTdiSetIPAddress( PIRP Irp
, PIO_STACK_LOCATION IrpSp
) {
1546 NTSTATUS Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
1547 PIP_SET_ADDRESS IpAddrChange
=
1548 (PIP_SET_ADDRESS
)Irp
->AssociatedIrp
.SystemBuffer
;
1551 TI_DbgPrint(MID_TRACE
,("Setting IP Address for adapter %d\n",
1552 IpAddrChange
->NteIndex
));
1554 ForEachInterface(IF
) {
1555 TI_DbgPrint(MID_TRACE
,("Looking at adapter %d\n", IF
->Index
));
1557 if( IF
->Unicast
.Address
.IPv4Address
== IpAddrChange
->Address
) {
1558 Status
= STATUS_DUPLICATE_OBJECTID
;
1561 if( IF
->Index
== IpAddrChange
->NteIndex
) {
1562 IPRemoveInterfaceRoute( IF
);
1564 IF
->Unicast
.Type
= IP_ADDRESS_V4
;
1565 IF
->Unicast
.Address
.IPv4Address
= IpAddrChange
->Address
;
1567 IF
->Netmask
.Type
= IP_ADDRESS_V4
;
1568 IF
->Netmask
.Address
.IPv4Address
= IpAddrChange
->Netmask
;
1570 IF
->Broadcast
.Type
= IP_ADDRESS_V4
;
1571 IF
->Broadcast
.Address
.IPv4Address
=
1572 IF
->Unicast
.Address
.IPv4Address
|
1573 ~IF
->Netmask
.Address
.IPv4Address
;
1575 TI_DbgPrint(MID_TRACE
,("New Unicast Address: %x\n",
1576 IF
->Unicast
.Address
.IPv4Address
));
1577 TI_DbgPrint(MID_TRACE
,("New Netmask : %x\n",
1578 IF
->Netmask
.Address
.IPv4Address
));
1580 IPAddInterfaceRoute( IF
);
1582 IpAddrChange
->Address
= IF
->Index
;
1583 Status
= STATUS_SUCCESS
;
1584 Irp
->IoStatus
.Information
= IF
->Index
;
1589 Irp
->IoStatus
.Status
= Status
;
1593 NTSTATUS
DispTdiDeleteIPAddress( PIRP Irp
, PIO_STACK_LOCATION IrpSp
) {
1594 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1595 PUSHORT NteIndex
= Irp
->AssociatedIrp
.SystemBuffer
;
1598 ForEachInterface(IF
) {
1599 if( IF
->Index
== *NteIndex
) {
1600 IPRemoveInterfaceRoute( IF
);
1601 IF
->Unicast
.Type
= IP_ADDRESS_V4
;
1602 IF
->Unicast
.Address
.IPv4Address
= 0;
1604 IF
->Netmask
.Type
= IP_ADDRESS_V4
;
1605 IF
->Netmask
.Address
.IPv4Address
= 0;
1607 IF
->Broadcast
.Type
= IP_ADDRESS_V4
;
1608 IF
->Broadcast
.Address
.IPv4Address
= 0;
1610 Status
= STATUS_SUCCESS
;
1614 Irp
->IoStatus
.Status
= Status
;
1619 WaitForHwAddress ( PDEVICE_OBJECT DeviceObject
, PVOID Context
) {
1620 PQUERY_HW_WORK_ITEM WorkItem
= (PQUERY_HW_WORK_ITEM
)Context
;
1625 PNEIGHBOR_CACHE_ENTRY NCE
= NULL
;
1626 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1628 IoFreeWorkItem(WorkItem
->WorkItem
);
1629 Irp
= WorkItem
->Irp
;
1630 AddrInitIPv4(&Remote
, WorkItem
->RemoteIP
);
1631 KeQuerySystemTime(&Now
);
1632 while (Now
.QuadPart
- WorkItem
->StartTime
.QuadPart
< 10000 * 1000 && !Irp
->Cancel
) {
1633 NCE
= NBLocateNeighbor(&Remote
, WorkItem
->Interface
);
1634 if (NCE
&& !(NCE
->State
& NUD_INCOMPLETE
)) {
1639 Wait
.QuadPart
= -10000;
1640 KeDelayExecutionThread(KernelMode
, FALSE
, &Wait
);
1641 KeQuerySystemTime(&Now
);
1647 if (NCE
->LinkAddressLength
> WorkItem
->IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
) {
1648 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1650 OutputBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
1651 RtlCopyMemory(OutputBuffer
, NCE
->LinkAddress
, NCE
->LinkAddressLength
);
1652 Irp
->IoStatus
.Information
= NCE
->LinkAddressLength
;
1653 Status
= STATUS_SUCCESS
;
1657 ExFreePoolWithTag(WorkItem
, QUERY_CONTEXT_TAG
);
1658 if (Irp
->Flags
& IRP_SYNCHRONOUS_API
) {
1659 Irp
->IoStatus
.Status
= Status
;
1661 IRPFinish(Irp
, Status
);
1665 NTSTATUS
DispTdiQueryIpHwAddress( PDEVICE_OBJECT DeviceObject
, PIRP Irp
, PIO_STACK_LOCATION IrpSp
) {
1668 IP_ADDRESS Remote
, Local
;
1669 PNEIGHBOR_CACHE_ENTRY NCE
;
1670 PIP_INTERFACE Interface
;
1671 PQUERY_HW_WORK_ITEM WorkItem
;
1673 Irp
->IoStatus
.Information
= 0;
1675 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< 2 * sizeof(ULONG
) ||
1676 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
== 0) {
1677 Status
= STATUS_INVALID_BUFFER_SIZE
;
1681 IPs
= (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
1682 AddrInitIPv4(&Remote
, IPs
[0]);
1683 AddrInitIPv4(&Local
, IPs
[1]);
1685 if (AddrIsUnspecified(&Remote
)) {
1686 Status
= STATUS_UNSUCCESSFUL
;
1690 Interface
= AddrLocateInterface(&Remote
);
1694 if (Interface
->AddressLength
> IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
) {
1695 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1699 OutputBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
1700 RtlCopyMemory(OutputBuffer
, Interface
->Address
, Interface
->AddressLength
);
1701 Irp
->IoStatus
.Information
= Interface
->AddressLength
;
1702 Status
= STATUS_SUCCESS
;
1706 if (AddrIsUnspecified(&Local
)) {
1707 NCE
= RouteGetRouteToDestination(&Remote
);
1709 Status
= STATUS_NETWORK_UNREACHABLE
;
1713 Interface
= NCE
->Interface
;
1716 Interface
= AddrLocateInterface(&Local
);
1717 if (Interface
== NULL
) {
1718 Interface
= GetDefaultInterface();
1719 if (Interface
== NULL
) {
1720 Status
= STATUS_NETWORK_UNREACHABLE
;
1726 WorkItem
= ExAllocatePoolWithTag(PagedPool
, sizeof(QUERY_HW_WORK_ITEM
), QUERY_CONTEXT_TAG
);
1727 if (WorkItem
== NULL
) {
1728 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1732 WorkItem
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
1733 if (WorkItem
->WorkItem
== NULL
) {
1734 ExFreePoolWithTag(WorkItem
, QUERY_CONTEXT_TAG
);
1735 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1739 WorkItem
->Irp
= Irp
;
1740 WorkItem
->IrpSp
= IrpSp
;
1741 WorkItem
->Interface
= Interface
;
1742 WorkItem
->RemoteIP
= IPs
[0];
1743 KeQuerySystemTime(&WorkItem
->StartTime
);
1745 NCE
= NBLocateNeighbor(&Remote
, Interface
);
1747 if (NCE
->LinkAddressLength
> IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
) {
1748 IoFreeWorkItem(WorkItem
->WorkItem
);
1749 ExFreePoolWithTag(WorkItem
, QUERY_CONTEXT_TAG
);
1750 Status
= STATUS_INVALID_BUFFER_SIZE
;
1754 if (!(NCE
->State
& NUD_INCOMPLETE
)) {
1755 PVOID LinkAddress
= ExAllocatePoolWithTag(PagedPool
, NCE
->LinkAddressLength
, QUERY_CONTEXT_TAG
);
1756 if (LinkAddress
== NULL
) {
1757 IoFreeWorkItem(WorkItem
->WorkItem
);
1758 ExFreePoolWithTag(WorkItem
, QUERY_CONTEXT_TAG
);
1759 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1762 memset(LinkAddress
, 0xff, NCE
->LinkAddressLength
);
1763 NBUpdateNeighbor(NCE
, LinkAddress
, NUD_INCOMPLETE
);
1764 ExFreePoolWithTag(LinkAddress
, QUERY_CONTEXT_TAG
);
1768 if (!ARPTransmit(&Remote
, NULL
, Interface
)) {
1769 IoFreeWorkItem(WorkItem
->WorkItem
);
1770 ExFreePoolWithTag(WorkItem
, QUERY_CONTEXT_TAG
);
1771 Status
= STATUS_UNSUCCESSFUL
;
1775 if (Irp
->Flags
& IRP_SYNCHRONOUS_API
) {
1776 WaitForHwAddress(DeviceObject
, WorkItem
);
1777 Status
= Irp
->IoStatus
.Status
;
1779 IoMarkIrpPending(Irp
);
1780 IoQueueWorkItem(WorkItem
->WorkItem
, WaitForHwAddress
, DelayedWorkQueue
, WorkItem
);
1781 Status
= STATUS_PENDING
;