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
19 NTSTATUS
DispPrepareIrpForCancel(
20 PTRANSPORT_CONTEXT Context
,
22 PDRIVER_CANCEL CancelRoutine
)
24 * FUNCTION: Prepare an IRP for cancellation
26 * Context = Pointer to context information
27 * Irp = Pointer to an I/O request packet
28 * CancelRoutine = Routine to be called when I/O request is cancelled
35 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
37 IoAcquireCancelSpinLock(&OldIrql
);
40 IoMarkIrpPending(Irp
);
41 IoSetCancelRoutine(Irp
, CancelRoutine
);
43 IoReleaseCancelSpinLock(OldIrql
);
45 TI_DbgPrint(DEBUG_IRP
, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp
));
47 return STATUS_SUCCESS
;
50 /* IRP has already been cancelled */
52 IoReleaseCancelSpinLock(OldIrql
);
54 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
55 Irp
->IoStatus
.Information
= 0;
57 TI_DbgPrint(DEBUG_IRP
, ("Leaving (IRP was already cancelled).\n"));
59 return IRPFinish(Irp
, STATUS_CANCELLED
);
63 VOID
DispCancelComplete(
66 * FUNCTION: Completes a cancel request
68 * Context = Pointer to context information (FILE_OBJECT)
72 PFILE_OBJECT FileObject
;
73 PTRANSPORT_CONTEXT TranContext
;
75 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
77 FileObject
= (PFILE_OBJECT
)Context
;
78 TranContext
= (PTRANSPORT_CONTEXT
)FileObject
->FsContext
;
80 IoAcquireCancelSpinLock(&OldIrql
);
82 /* Remove the reference taken by the cancel routine */
83 TranContext
->RefCount
--;
85 if (TranContext
->RefCount
== 0) {
86 TI_DbgPrint(DEBUG_IRP
, ("Setting TranContext->CleanupEvent to signaled.\n"));
87 /* Set the cleanup event */
88 KeSetEvent(&TranContext
->CleanupEvent
, 0, FALSE
);
91 TI_DbgPrint(DEBUG_REFCOUNT
, ("TranContext->RefCount (%d).\n", TranContext
->RefCount
));
93 IoReleaseCancelSpinLock(OldIrql
);
95 TI_DbgPrint(DEBUG_IRP
, ("Leaving.\n"));
99 VOID
DispCancelRequest(
100 PDEVICE_OBJECT Device
,
103 * FUNCTION: Cancels an IRP
105 * Device = Pointer to device object
106 * Irp = Pointer to an I/O request packet
109 PIO_STACK_LOCATION IrpSp
;
110 PTRANSPORT_CONTEXT TranContext
;
111 PFILE_OBJECT FileObject
;
113 NTSTATUS Status
= STATUS_SUCCESS
;
115 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
117 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
118 FileObject
= IrpSp
->FileObject
;
119 TranContext
= (PTRANSPORT_CONTEXT
)FileObject
->FsContext
;
120 MinorFunction
= IrpSp
->MinorFunction
;
122 TI_DbgPrint(DEBUG_IRP
, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp
, MinorFunction
, IrpSp
));
126 TI_DbgPrint(MIN_TRACE
, ("Irp->Cancel is FALSE, should be TRUE.\n"));
129 /* Increase reference count to prevent accidential closure
130 of the object while inside the cancel routine */
131 TranContext
->RefCount
++;
133 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
135 /* Try canceling the request */
136 switch(MinorFunction
) {
140 /* FIXME: Close connection */
143 case TDI_SEND_DATAGRAM
:
144 if (FileObject
->FsContext2
!= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
) {
145 TI_DbgPrint(MIN_TRACE
, ("TDI_SEND_DATAGRAM, but no address file.\n"));
149 DGCancelSendRequest(TranContext
->Handle
.AddressHandle
, Irp
);
152 case TDI_RECEIVE_DATAGRAM
:
153 if (FileObject
->FsContext2
!= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
) {
154 TI_DbgPrint(MIN_TRACE
, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
158 DGCancelReceiveRequest(TranContext
->Handle
.AddressHandle
, Irp
);
162 TI_DbgPrint(MIN_TRACE
, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction
));
166 if (Status
!= STATUS_PENDING
)
167 DispCancelComplete(FileObject
);
169 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
173 VOID
DispDataRequestComplete(
178 * FUNCTION: Completes a send/receive IRP
180 * Context = Pointer to context information (IRP)
181 * Status = Status of the request
182 * Count = Number of bytes sent or received
186 PIO_STACK_LOCATION IrpSp
;
187 PTRANSPORT_CONTEXT TranContext
;
190 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
193 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
194 TranContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
196 IoAcquireCancelSpinLock(&OldIrql
);
198 IoSetCancelRoutine(Irp
, NULL
);
199 TranContext
->RefCount
--;
200 TI_DbgPrint(DEBUG_REFCOUNT
, ("TranContext->RefCount (%d).\n", TranContext
->RefCount
));
201 if (TranContext
->RefCount
== 0) {
202 TI_DbgPrint(DEBUG_IRP
, ("Setting TranContext->CleanupEvent to signaled.\n"));
204 KeSetEvent(&TranContext
->CleanupEvent
, 0, FALSE
);
207 if (Irp
->Cancel
|| TranContext
->CancelIrps
) {
208 /* The IRP has been cancelled */
210 TI_DbgPrint(DEBUG_IRP
, ("IRP is cancelled.\n"));
212 Status
= STATUS_CANCELLED
;
216 IoReleaseCancelSpinLock(OldIrql
);
218 Irp
->IoStatus
.Status
= Status
;
219 Irp
->IoStatus
.Information
= Count
;
221 TI_DbgPrint(DEBUG_IRP
, ("Completing IRP at (0x%X).\n", Irp
));
223 IRPFinish(Irp
, STATUS_SUCCESS
);
227 NTSTATUS
DispTdiAccept(
230 * FUNCTION: TDI_ACCEPT handler
232 * Irp = Pointer to an I/O request packet
234 * Status of operation
237 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
239 return STATUS_NOT_IMPLEMENTED
;
243 NTSTATUS
DispTdiAssociateAddress(
246 * FUNCTION: TDI_ASSOCIATE_ADDRESS handler
248 * Irp = Pointer to an I/O request packet
250 * Status of operation
253 PTDI_REQUEST_KERNEL_ASSOCIATE Parameters
;
254 PTRANSPORT_CONTEXT TranContext
;
255 PIO_STACK_LOCATION IrpSp
;
256 PCONNECTION_ENDPOINT Connection
;
257 PFILE_OBJECT FileObject
;
258 PADDRESS_FILE AddrFile
;
261 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
263 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
265 /* Get associated connection endpoint file object. Quit if none exists */
267 TranContext
= IrpSp
->FileObject
->FsContext
;
269 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
270 return STATUS_INVALID_PARAMETER
;
273 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
275 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
276 return STATUS_INVALID_PARAMETER
;
279 if (Connection
->AddressFile
) {
280 TI_DbgPrint(MID_TRACE
, ("An address file is already asscociated.\n"));
281 return STATUS_INVALID_PARAMETER
;
284 Parameters
= (PTDI_REQUEST_KERNEL_ASSOCIATE
)&IrpSp
->Parameters
;
286 Status
= ObReferenceObjectByHandle(
287 Parameters
->AddressHandle
,
293 if (!NT_SUCCESS(Status
)) {
294 TI_DbgPrint(MID_TRACE
, ("Bad address file object handle (0x%X).\n",
295 Parameters
->AddressHandle
));
296 return STATUS_INVALID_PARAMETER
;
299 if (FileObject
->FsContext2
!= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
) {
300 ObDereferenceObject(FileObject
);
301 TI_DbgPrint(MID_TRACE
, ("Bad address file object. Magic (0x%X).\n",
302 FileObject
->FsContext2
));
303 return STATUS_INVALID_PARAMETER
;
306 /* Get associated address file object. Quit if none exists */
308 TranContext
= FileObject
->FsContext
;
310 ObDereferenceObject(FileObject
);
311 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
312 return STATUS_INVALID_PARAMETER
;
315 AddrFile
= (PADDRESS_FILE
)TranContext
->Handle
.AddressHandle
;
317 ObDereferenceObject(FileObject
);
318 TI_DbgPrint(MID_TRACE
, ("No address file object.\n"));
319 return STATUS_INVALID_PARAMETER
;
322 /* The connection endpoint references the address file object */
323 ReferenceObject(AddrFile
);
324 Connection
->AddressFile
= AddrFile
;
326 /* Add connection endpoint to the address file */
327 AddrFile
->Connection
= Connection
;
329 /* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
330 ObDereferenceObject(FileObject
);
332 return STATUS_SUCCESS
;
336 NTSTATUS
DispTdiConnect(
339 * FUNCTION: TDI_CONNECT handler
341 * Irp = Pointer to an I/O request packet
343 * Status of operation
346 PCONNECTION_ENDPOINT Connection
;
347 PTDI_REQUEST_KERNEL Parameters
;
348 PTRANSPORT_CONTEXT TranContext
;
349 PIO_STACK_LOCATION IrpSp
;
353 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
355 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
357 /* Get associated connection endpoint file object. Quit if none exists */
359 TranContext
= IrpSp
->FileObject
->FsContext
;
361 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
362 return STATUS_INVALID_CONNECTION
;
365 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
367 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
368 return STATUS_INVALID_CONNECTION
;
371 Parameters
= (PTDI_REQUEST_KERNEL
)&IrpSp
->Parameters
;
373 /* Initialize a connect request */
374 Request
.Handle
.ConnectionContext
= TranContext
->Handle
.ConnectionContext
;
375 Request
.RequestNotifyObject
= DispDataRequestComplete
;
376 Request
.RequestContext
= Irp
;
378 /* XXX Handle connected UDP, etc... */
381 Parameters
->RequestConnectionInformation
,
382 Parameters
->ReturnConnectionInformation
);
384 TI_DbgPrint(MAX_TRACE
, ("TCP Connect returned %08x\n", Status
));
390 NTSTATUS
DispTdiDisassociateAddress(
393 * FUNCTION: TDI_DISASSOCIATE_ADDRESS handler
395 * Irp = Pointer to an I/O request packet
397 * Status of operation
400 PCONNECTION_ENDPOINT Connection
;
401 PTRANSPORT_CONTEXT TranContext
;
402 PIO_STACK_LOCATION IrpSp
;
405 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
407 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
409 /* Get associated connection endpoint file object. Quit if none exists */
411 TranContext
= IrpSp
->FileObject
->FsContext
;
413 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
414 return STATUS_INVALID_PARAMETER
;
417 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
419 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
420 return STATUS_INVALID_PARAMETER
;
423 if (!Connection
->AddressFile
) {
424 TI_DbgPrint(MID_TRACE
, ("No address file is asscociated.\n"));
425 return STATUS_INVALID_PARAMETER
;
428 /* Remove the reference put on the address file object */
429 KeAcquireSpinLock(&Connection
->Lock
, &OldIrql
);
430 DereferenceObject(Connection
->AddressFile
);
431 KeReleaseSpinLock(&Connection
->Lock
, OldIrql
);
433 return STATUS_SUCCESS
;
437 NTSTATUS
DispTdiDisconnect(
440 * FUNCTION: TDI_DISCONNECT handler
442 * Irp = Pointer to an I/O request packet
444 * Status of operation
447 PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters
;
448 PTRANSPORT_CONTEXT TranContext
;
449 PIO_STACK_LOCATION IrpSp
;
451 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
453 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
454 Parameters
= (PTDI_REQUEST_KERNEL_QUERY_INFORMATION
)&IrpSp
->Parameters
;
456 TranContext
= IrpSp
->FileObject
->FsContext
;
458 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
459 return STATUS_INVALID_CONNECTION
;
462 switch (Parameters
->QueryType
)
464 case TDI_QUERY_ADDRESS_INFO
:
466 PTDI_ADDRESS_INFO AddressInfo
;
467 PADDRESS_FILE AddrFile
;
468 PTA_IP_ADDRESS Address
;
470 AddressInfo
= (PTDI_ADDRESS_INFO
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
472 switch ((ULONG
)IrpSp
->FileObject
->FsContext2
) {
473 case TDI_TRANSPORT_ADDRESS_FILE
:
474 AddrFile
= (PADDRESS_FILE
)TranContext
->Handle
.AddressHandle
;
477 case TDI_CONNECTION_FILE
:
478 AddrFile
= ((PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
)->AddressFile
;
482 TI_DbgPrint(MIN_TRACE
, ("Invalid transport context\n"));
483 return STATUS_INVALID_PARAMETER
;
487 TI_DbgPrint(MID_TRACE
, ("No address file object.\n"));
488 return STATUS_INVALID_PARAMETER
;
491 if (MmGetMdlByteCount(Irp
->MdlAddress
) <
492 (sizeof(TDI_ADDRESS_INFO
) + sizeof(TDI_ADDRESS_IP
))) {
493 TI_DbgPrint(MID_TRACE
, ("MDL buffer too small.\n"));
494 return STATUS_BUFFER_OVERFLOW
;
497 /* FIXME: Is this count really the one we should return? */
498 AddressInfo
->ActivityCount
= AddrFile
->RefCount
;
500 Address
= (PTA_IP_ADDRESS
)&AddressInfo
->Address
;
501 Address
->TAAddressCount
= 1;
502 Address
->Address
[0].AddressLength
= TDI_ADDRESS_LENGTH_IP
;
503 Address
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
504 Address
->Address
[0].Address
[0].sin_port
= AddrFile
->Port
;
505 Address
->Address
[0].Address
[0].in_addr
= AddrFile
->ADE
->Address
->Address
.IPv4Address
;
507 &Address
->Address
[0].Address
[0].sin_zero
,
508 sizeof(Address
->Address
[0].Address
[0].sin_zero
));
510 return STATUS_SUCCESS
;
514 return STATUS_NOT_IMPLEMENTED
;
518 NTSTATUS
DispTdiListen(
521 * FUNCTION: TDI_LISTEN handler
523 * Irp = Pointer to an I/O request packet
525 * Status of operation
528 PCONNECTION_ENDPOINT Connection
;
529 PTDI_REQUEST_KERNEL Parameters
;
530 PTRANSPORT_CONTEXT TranContext
;
531 PIO_STACK_LOCATION IrpSp
;
532 PTDI_REQUEST Request
;
536 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
538 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
540 /* Get associated connection endpoint file object. Quit if none exists */
542 TranContext
= IrpSp
->FileObject
->FsContext
;
543 if (TranContext
== NULL
)
545 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
546 return STATUS_INVALID_CONNECTION
;
549 Connection
= (PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
;
550 if (Connection
== NULL
)
552 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
553 return STATUS_INVALID_CONNECTION
;
556 Parameters
= (PTDI_REQUEST_KERNEL
)&IrpSp
->Parameters
;
558 Status
= TCPListen( Request
, 1024 /* BACKLOG */ );
564 NTSTATUS
DispTdiQueryInformation(
565 PDEVICE_OBJECT DeviceObject
,
568 * FUNCTION: TDI_QUERY_INFORMATION handler
570 * DeviceObject = Pointer to device object structure
571 * Irp = Pointer to an I/O request packet
573 * Status of operation
576 PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters
;
577 PTRANSPORT_CONTEXT TranContext
;
578 PIO_STACK_LOCATION IrpSp
;
580 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
582 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
583 Parameters
= (PTDI_REQUEST_KERNEL_QUERY_INFORMATION
)&IrpSp
->Parameters
;
585 TranContext
= IrpSp
->FileObject
->FsContext
;
587 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
588 return STATUS_INVALID_CONNECTION
;
591 switch (Parameters
->QueryType
)
593 case TDI_QUERY_ADDRESS_INFO
:
595 PTDI_ADDRESS_INFO AddressInfo
;
596 PADDRESS_FILE AddrFile
;
597 PTA_IP_ADDRESS Address
;
599 AddressInfo
= (PTDI_ADDRESS_INFO
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
601 switch ((ULONG
)IrpSp
->FileObject
->FsContext2
) {
602 case TDI_TRANSPORT_ADDRESS_FILE
:
603 AddrFile
= (PADDRESS_FILE
)TranContext
->Handle
.AddressHandle
;
606 case TDI_CONNECTION_FILE
:
607 AddrFile
= ((PCONNECTION_ENDPOINT
)TranContext
->Handle
.ConnectionContext
)->AddressFile
;
611 TI_DbgPrint(MIN_TRACE
, ("Invalid transport context\n"));
612 return STATUS_INVALID_PARAMETER
;
616 TI_DbgPrint(MID_TRACE
, ("No address file object.\n"));
617 return STATUS_INVALID_PARAMETER
;
620 if (MmGetMdlByteCount(Irp
->MdlAddress
) <
621 (sizeof(TDI_ADDRESS_INFO
) + sizeof(TDI_ADDRESS_IP
))) {
622 TI_DbgPrint(MID_TRACE
, ("MDL buffer too small.\n"));
623 return STATUS_BUFFER_OVERFLOW
;
626 /* FIXME: Is this count really the one we should return? */
627 AddressInfo
->ActivityCount
= AddrFile
->RefCount
;
629 Address
= (PTA_IP_ADDRESS
)&AddressInfo
->Address
;
630 Address
->TAAddressCount
= 1;
631 Address
->Address
[0].AddressLength
= TDI_ADDRESS_LENGTH_IP
;
632 Address
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
633 Address
->Address
[0].Address
[0].sin_port
= AddrFile
->Port
;
634 Address
->Address
[0].Address
[0].in_addr
= AddrFile
->ADE
->Address
->Address
.IPv4Address
;
636 &Address
->Address
[0].Address
[0].sin_zero
,
637 sizeof(Address
->Address
[0].Address
[0].sin_zero
));
639 return STATUS_SUCCESS
;
643 return STATUS_NOT_IMPLEMENTED
;
647 NTSTATUS
DispTdiReceive(
650 * FUNCTION: TDI_RECEIVE handler
652 * Irp = Pointer to an I/O request packet
654 * Status of operation
657 PIO_STACK_LOCATION IrpSp
;
658 PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo
;
659 PTRANSPORT_CONTEXT TranContext
;
664 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
666 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
667 ReceiveInfo
= (PTDI_REQUEST_KERNEL_RECEIVE
)&(IrpSp
->Parameters
);
669 TranContext
= IrpSp
->FileObject
->FsContext
;
670 if (TranContext
== NULL
)
672 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
673 return STATUS_INVALID_CONNECTION
;
676 if (TranContext
->Handle
.ConnectionContext
== NULL
)
678 TI_DbgPrint(MID_TRACE
, ("No connection endpoint file object.\n"));
679 return STATUS_INVALID_CONNECTION
;
682 /* Initialize a receive request */
683 Request
.Handle
.ConnectionContext
= TranContext
->Handle
.ConnectionContext
;
684 Request
.RequestNotifyObject
= DispDataRequestComplete
;
685 Request
.RequestContext
= Irp
;
686 Status
= DispPrepareIrpForCancel(
687 IrpSp
->FileObject
->FsContext
,
689 (PDRIVER_CANCEL
)DispCancelRequest
);
690 if (NT_SUCCESS(Status
))
692 Status
= TCPReceiveData(
694 (PNDIS_BUFFER
)Irp
->MdlAddress
,
695 ReceiveInfo
->ReceiveLength
,
696 ReceiveInfo
->ReceiveFlags
,
698 if (Status
!= STATUS_PENDING
)
700 DispDataRequestComplete(Irp
, Status
, BytesReceived
);
704 if (Status
!= STATUS_PENDING
)
706 IrpSp
->Control
&= ~SL_PENDING_RETURNED
;
709 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status is (0x%X)\n", Status
));
715 NTSTATUS
DispTdiReceiveDatagram(
718 * FUNCTION: TDI_RECEIVE_DATAGRAM handler
720 * Irp = Pointer to an I/O request packet
722 * Status of operation
725 PIO_STACK_LOCATION IrpSp
;
726 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo
;
727 PTRANSPORT_CONTEXT TranContext
;
732 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
734 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
735 DgramInfo
= (PTDI_REQUEST_KERNEL_RECEIVEDG
)&(IrpSp
->Parameters
);
737 TranContext
= IrpSp
->FileObject
->FsContext
;
738 if (TranContext
== NULL
)
740 TI_DbgPrint(MID_TRACE
, ("Bad transport context.\n"));
741 return STATUS_INVALID_ADDRESS
;
744 /* Initialize a receive request */
745 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
746 Request
.RequestNotifyObject
= DispDataRequestComplete
;
747 Request
.RequestContext
= Irp
;
748 Status
= DispPrepareIrpForCancel(
749 IrpSp
->FileObject
->FsContext
,
751 (PDRIVER_CANCEL
)DispCancelRequest
);
752 if (NT_SUCCESS(Status
))
754 Status
= UDPReceiveDatagram(
756 DgramInfo
->ReceiveDatagramInformation
,
757 (PNDIS_BUFFER
)Irp
->MdlAddress
,
758 DgramInfo
->ReceiveLength
,
759 DgramInfo
->ReceiveFlags
,
760 DgramInfo
->ReturnDatagramInformation
,
762 if (Status
!= STATUS_PENDING
)
764 DispDataRequestComplete(Irp
, Status
, BytesReceived
);
768 if (Status
!= STATUS_PENDING
)
770 IrpSp
->Control
&= ~SL_PENDING_RETURNED
;
773 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status is (0x%X)\n", Status
));
779 NTSTATUS
DispTdiSend(
782 * FUNCTION: TDI_SEND handler
784 * Irp = Pointer to an I/O request packet
786 * Status of operation
789 PIO_STACK_LOCATION IrpSp
;
791 PTDI_REQUEST_KERNEL_SEND SendInfo
;
792 PTRANSPORT_CONTEXT TranContext
;
795 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
797 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
798 SendInfo
= (PTDI_REQUEST_KERNEL_SEND
)&(IrpSp
->Parameters
);
799 TranContext
= IrpSp
->FileObject
->FsContext
;
801 /* Initialize a send request */
802 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
803 Request
.RequestNotifyObject
= DispDataRequestComplete
;
804 Request
.RequestContext
= Irp
;
806 Status
= DispPrepareIrpForCancel(
807 IrpSp
->FileObject
->FsContext
,
809 (PDRIVER_CANCEL
)DispCancelRequest
);
810 if (NT_SUCCESS(Status
)) {
812 /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
813 must be of type PTDI_ADDRESS_IP */
815 Status
= (*((PADDRESS_FILE
)Request
.Handle
.AddressHandle
)->Send
)(
817 (PNDIS_BUFFER
)Irp
->MdlAddress
, SendInfo
->SendLength
);
818 if (Status
!= STATUS_PENDING
) {
819 DispDataRequestComplete(Irp
, Status
, 0);
820 /* Return STATUS_PENDING because DispPrepareIrpForCancel
821 marks Irp as pending */
822 Status
= STATUS_PENDING
;
826 TI_DbgPrint(DEBUG_IRP
, ("Leaving.\n"));
832 NTSTATUS
DispTdiSendDatagram(
835 * FUNCTION: TDI_SEND_DATAGRAM handler
837 * Irp = Pointer to an I/O request packet
839 * Status of operation
842 PIO_STACK_LOCATION IrpSp
;
844 PTDI_REQUEST_KERNEL_SENDDG DgramInfo
;
845 PTRANSPORT_CONTEXT TranContext
;
848 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
850 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
851 DgramInfo
= (PTDI_REQUEST_KERNEL_SENDDG
)&(IrpSp
->Parameters
);
852 TranContext
= IrpSp
->FileObject
->FsContext
;
854 /* Initialize a send request */
855 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
856 Request
.RequestNotifyObject
= DispDataRequestComplete
;
857 Request
.RequestContext
= Irp
;
859 Status
= DispPrepareIrpForCancel(
860 IrpSp
->FileObject
->FsContext
,
862 (PDRIVER_CANCEL
)DispCancelRequest
);
863 if (NT_SUCCESS(Status
)) {
865 /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
866 must be of type PTDI_ADDRESS_IP */
868 Status
= (*((PADDRESS_FILE
)Request
.Handle
.AddressHandle
)->Send
)(
869 &Request
, DgramInfo
->SendDatagramInformation
,
870 (PNDIS_BUFFER
)Irp
->MdlAddress
, DgramInfo
->SendLength
);
871 if (Status
!= STATUS_PENDING
) {
872 DispDataRequestComplete(Irp
, Status
, 0);
873 /* Return STATUS_PENDING because DispPrepareIrpForCancel
874 marks Irp as pending */
875 Status
= STATUS_PENDING
;
879 TI_DbgPrint(DEBUG_IRP
, ("Leaving.\n"));
885 NTSTATUS
DispTdiSetEventHandler(
888 * FUNCTION: TDI_SET_EVENT_HANDER handler
890 * Irp = Pointer to a I/O request packet
892 * Status of operation
895 PTDI_REQUEST_KERNEL_SET_EVENT Parameters
;
896 PTRANSPORT_CONTEXT TranContext
;
897 PIO_STACK_LOCATION IrpSp
;
898 PADDRESS_FILE AddrFile
;
902 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
904 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
906 /* Get associated address file object. Quit if none exists */
908 TranContext
= IrpSp
->FileObject
->FsContext
;
910 TI_DbgPrint(MIN_TRACE
, ("Bad transport context.\n"));
911 return STATUS_INVALID_PARAMETER
;
914 AddrFile
= (PADDRESS_FILE
)TranContext
->Handle
.AddressHandle
;
916 TI_DbgPrint(MIN_TRACE
, ("No address file object.\n"));
917 return STATUS_INVALID_PARAMETER
;
920 Parameters
= (PTDI_REQUEST_KERNEL_SET_EVENT
)&IrpSp
->Parameters
;
921 Status
= STATUS_SUCCESS
;
923 KeAcquireSpinLock(&AddrFile
->Lock
, &OldIrql
);
925 /* Set the event handler. if an event handler is associated with
926 a specific event, it's flag (RegisteredXxxHandler) is TRUE.
927 If an event handler is not used it's flag is FALSE */
928 switch (Parameters
->EventType
) {
929 case TDI_EVENT_CONNECT
:
930 if (!Parameters
->EventHandler
) {
931 AddrFile
->ConnectHandlerContext
= NULL
;
932 AddrFile
->RegisteredConnectHandler
= FALSE
;
934 AddrFile
->ConnectHandler
=
935 (PTDI_IND_CONNECT
)Parameters
->EventHandler
;
936 AddrFile
->ConnectHandlerContext
= Parameters
->EventContext
;
937 AddrFile
->RegisteredConnectHandler
= TRUE
;
941 case TDI_EVENT_DISCONNECT
:
942 if (!Parameters
->EventHandler
) {
943 AddrFile
->DisconnectHandlerContext
= NULL
;
944 AddrFile
->RegisteredDisconnectHandler
= FALSE
;
946 AddrFile
->DisconnectHandler
=
947 (PTDI_IND_DISCONNECT
)Parameters
->EventHandler
;
948 AddrFile
->DisconnectHandlerContext
= Parameters
->EventContext
;
949 AddrFile
->RegisteredDisconnectHandler
= TRUE
;
953 case TDI_EVENT_ERROR
:
954 if (Parameters
->EventHandler
== NULL
) {
955 AddrFile
->ErrorHandlerContext
= NULL
;
956 AddrFile
->RegisteredErrorHandler
= FALSE
;
958 AddrFile
->ErrorHandler
=
959 (PTDI_IND_ERROR
)Parameters
->EventHandler
;
960 AddrFile
->ErrorHandlerContext
= Parameters
->EventContext
;
961 AddrFile
->RegisteredErrorHandler
= TRUE
;
965 case TDI_EVENT_RECEIVE
:
966 if (Parameters
->EventHandler
== NULL
) {
967 AddrFile
->ReceiveHandlerContext
= NULL
;
968 AddrFile
->RegisteredReceiveHandler
= FALSE
;
970 AddrFile
->ReceiveHandler
=
971 (PTDI_IND_RECEIVE
)Parameters
->EventHandler
;
972 AddrFile
->ReceiveHandlerContext
= Parameters
->EventContext
;
973 AddrFile
->RegisteredReceiveHandler
= TRUE
;
977 case TDI_EVENT_RECEIVE_DATAGRAM
:
978 if (Parameters
->EventHandler
== NULL
) {
979 AddrFile
->ReceiveDatagramHandlerContext
= NULL
;
980 AddrFile
->RegisteredReceiveDatagramHandler
= FALSE
;
982 AddrFile
->ReceiveDatagramHandler
=
983 (PTDI_IND_RECEIVE_DATAGRAM
)Parameters
->EventHandler
;
984 AddrFile
->ReceiveDatagramHandlerContext
= Parameters
->EventContext
;
985 AddrFile
->RegisteredReceiveDatagramHandler
= TRUE
;
989 case TDI_EVENT_RECEIVE_EXPEDITED
:
990 if (Parameters
->EventHandler
== NULL
) {
991 AddrFile
->ExpeditedReceiveHandlerContext
= NULL
;
992 AddrFile
->RegisteredExpeditedReceiveHandler
= FALSE
;
994 AddrFile
->ExpeditedReceiveHandler
=
995 (PTDI_IND_RECEIVE_EXPEDITED
)Parameters
->EventHandler
;
996 AddrFile
->ExpeditedReceiveHandlerContext
= Parameters
->EventContext
;
997 AddrFile
->RegisteredExpeditedReceiveHandler
= TRUE
;
1001 case TDI_EVENT_CHAINED_RECEIVE
:
1002 if (Parameters
->EventHandler
== NULL
) {
1003 AddrFile
->ChainedReceiveHandlerContext
= NULL
;
1004 AddrFile
->RegisteredChainedReceiveHandler
= FALSE
;
1006 AddrFile
->ChainedReceiveHandler
=
1007 (PTDI_IND_CHAINED_RECEIVE
)Parameters
->EventHandler
;
1008 AddrFile
->ChainedReceiveHandlerContext
= Parameters
->EventContext
;
1009 AddrFile
->RegisteredChainedReceiveHandler
= TRUE
;
1013 case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
:
1014 if (Parameters
->EventHandler
== NULL
) {
1015 AddrFile
->ChainedReceiveDatagramHandlerContext
= NULL
;
1016 AddrFile
->RegisteredChainedReceiveDatagramHandler
= FALSE
;
1018 AddrFile
->ChainedReceiveDatagramHandler
=
1019 (PTDI_IND_CHAINED_RECEIVE_DATAGRAM
)Parameters
->EventHandler
;
1020 AddrFile
->ChainedReceiveDatagramHandlerContext
= Parameters
->EventContext
;
1021 AddrFile
->RegisteredChainedReceiveDatagramHandler
= TRUE
;
1025 case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
:
1026 if (Parameters
->EventHandler
== NULL
) {
1027 AddrFile
->ChainedReceiveExpeditedHandlerContext
= NULL
;
1028 AddrFile
->RegisteredChainedReceiveExpeditedHandler
= FALSE
;
1030 AddrFile
->ChainedReceiveExpeditedHandler
=
1031 (PTDI_IND_CHAINED_RECEIVE_EXPEDITED
)Parameters
->EventHandler
;
1032 AddrFile
->ChainedReceiveExpeditedHandlerContext
= Parameters
->EventContext
;
1033 AddrFile
->RegisteredChainedReceiveExpeditedHandler
= TRUE
;
1038 TI_DbgPrint(MIN_TRACE
, ("Unknown event type (0x%X).\n",
1039 Parameters
->EventType
));
1041 Status
= STATUS_INVALID_PARAMETER
;
1044 KeReleaseSpinLock(&AddrFile
->Lock
, OldIrql
);
1050 NTSTATUS
DispTdiSetInformation(
1053 * FUNCTION: TDI_SET_INFORMATION handler
1055 * Irp = Pointer to an I/O request packet
1057 * Status of operation
1060 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
1062 return STATUS_NOT_IMPLEMENTED
;
1066 VOID
DispTdiQueryInformationExComplete(
1071 * FUNCTION: Completes a TDI QueryInformationEx request
1073 * Context = Pointer to the IRP for the request
1074 * Status = TDI status of the request
1075 * ByteCount = Number of bytes returned in output buffer
1078 PTI_QUERY_CONTEXT QueryContext
;
1081 QueryContext
= (PTI_QUERY_CONTEXT
)Context
;
1082 if (NT_SUCCESS(Status
)) {
1083 Count
= CopyBufferToBufferChain(
1084 QueryContext
->InputMdl
,
1085 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX
, Context
),
1086 (PUCHAR
)&QueryContext
->QueryInfo
.Context
,
1090 MmUnlockPages(QueryContext
->InputMdl
);
1091 IoFreeMdl(QueryContext
->InputMdl
);
1092 MmUnlockPages(QueryContext
->OutputMdl
);
1093 IoFreeMdl(QueryContext
->OutputMdl
);
1095 QueryContext
->Irp
->IoStatus
.Information
= ByteCount
;
1096 QueryContext
->Irp
->IoStatus
.Status
= Status
;
1098 ExFreePool(QueryContext
);
1102 NTSTATUS
DispTdiQueryInformationEx(
1104 PIO_STACK_LOCATION IrpSp
)
1106 * FUNCTION: TDI QueryInformationEx handler
1108 * Irp = Pointer to I/O request packet
1109 * IrpSp = Pointer to current stack location of Irp
1111 * Status of operation
1114 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer
;
1115 PTRANSPORT_CONTEXT TranContext
;
1116 PTI_QUERY_CONTEXT QueryContext
;
1118 TDI_REQUEST Request
;
1120 UINT InputBufferLength
;
1121 UINT OutputBufferLength
;
1122 BOOLEAN InputMdlLocked
= FALSE
;
1123 BOOLEAN OutputMdlLocked
= FALSE
;
1124 PMDL InputMdl
= NULL
;
1125 PMDL OutputMdl
= NULL
;
1126 NTSTATUS Status
= STATUS_SUCCESS
;
1128 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
1130 TranContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
1132 switch ((ULONG
)IrpSp
->FileObject
->FsContext2
) {
1133 case TDI_TRANSPORT_ADDRESS_FILE
:
1134 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
1137 case TDI_CONNECTION_FILE
:
1138 Request
.Handle
.ConnectionContext
= TranContext
->Handle
.ConnectionContext
;
1141 case TDI_CONTROL_CHANNEL_FILE
:
1142 Request
.Handle
.ControlChannel
= TranContext
->Handle
.ControlChannel
;
1146 TI_DbgPrint(MIN_TRACE
, ("Invalid transport context\n"));
1147 return STATUS_INVALID_PARAMETER
;
1150 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
1151 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1153 /* Validate parameters */
1154 if ((InputBufferLength
== sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
)) &&
1155 (OutputBufferLength
!= 0)) {
1157 InputBuffer
= (PTCP_REQUEST_QUERY_INFORMATION_EX
)
1158 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
1159 OutputBuffer
= Irp
->UserBuffer
;
1161 QueryContext
= ExAllocatePool(NonPagedPool
, sizeof(TI_QUERY_CONTEXT
));
1166 InputMdl
= IoAllocateMdl(InputBuffer
,
1167 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
),
1170 OutputMdl
= IoAllocateMdl(OutputBuffer
,
1171 OutputBufferLength
, FALSE
, TRUE
, NULL
);
1173 if (InputMdl
&& OutputMdl
) {
1175 MmProbeAndLockPages(InputMdl
, Irp
->RequestorMode
,
1178 InputMdlLocked
= TRUE
;
1180 MmProbeAndLockPages(OutputMdl
, Irp
->RequestorMode
,
1183 OutputMdlLocked
= TRUE
;
1185 RtlCopyMemory(&QueryContext
->QueryInfo
,
1186 InputBuffer
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
1189 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1191 } except(EXCEPTION_EXECUTE_HANDLER
) {
1192 Status
= GetExceptionCode();
1195 if (NT_SUCCESS(Status
)) {
1196 Size
= MmGetMdlByteCount(OutputMdl
);
1198 QueryContext
->Irp
= Irp
;
1199 QueryContext
->InputMdl
= InputMdl
;
1200 QueryContext
->OutputMdl
= OutputMdl
;
1202 Request
.RequestNotifyObject
= DispTdiQueryInformationExComplete
;
1203 Request
.RequestContext
= QueryContext
;
1204 Status
= InfoTdiQueryInformationEx(&Request
,
1205 &QueryContext
->QueryInfo
.ID
, OutputMdl
,
1206 &Size
, &QueryContext
->QueryInfo
.Context
);
1207 DispTdiQueryInformationExComplete(QueryContext
, Status
, Size
);
1209 TI_DbgPrint(MAX_TRACE
, ("Leaving. Status = (0x%X)\n", Status
));
1214 /* An error occurred if we get here */
1218 MmUnlockPages(InputMdl
);
1219 IoFreeMdl(InputMdl
);
1223 if (OutputMdlLocked
)
1224 MmUnlockPages(OutputMdl
);
1225 IoFreeMdl(OutputMdl
);
1228 ExFreePool(QueryContext
);
1230 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1232 Status
= STATUS_INVALID_PARAMETER
;
1234 TI_DbgPrint(MIN_TRACE
, ("Leaving. Status = (0x%X)\n", Status
));
1240 NTSTATUS
DispTdiSetInformationEx(
1242 PIO_STACK_LOCATION IrpSp
)
1244 * FUNCTION: TDI SetInformationEx handler
1246 * Irp = Pointer to I/O request packet
1247 * IrpSp = Pointer to current stack location of Irp
1249 * Status of operation
1252 PTRANSPORT_CONTEXT TranContext
;
1253 PTCP_REQUEST_SET_INFORMATION_EX Info
;
1254 TDI_REQUEST Request
;
1258 TI_DbgPrint(DEBUG_IRP
, ("Called.\n"));
1260 TranContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
1261 Info
= (PTCP_REQUEST_SET_INFORMATION_EX
)Irp
->AssociatedIrp
.SystemBuffer
;
1263 switch ((ULONG
)IrpSp
->FileObject
->FsContext2
) {
1264 case TDI_TRANSPORT_ADDRESS_FILE
:
1265 Request
.Handle
.AddressHandle
= TranContext
->Handle
.AddressHandle
;
1268 case TDI_CONNECTION_FILE
:
1269 Request
.Handle
.ConnectionContext
= TranContext
->Handle
.ConnectionContext
;
1272 case TDI_CONTROL_CHANNEL_FILE
:
1273 Request
.Handle
.ControlChannel
= TranContext
->Handle
.ControlChannel
;
1277 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1278 Irp
->IoStatus
.Information
= 0;
1280 TI_DbgPrint(DEBUG_IRP
, ("Completing IRP at (0x%X).\n", Irp
));
1282 return IRPFinish(Irp
, STATUS_INVALID_PARAMETER
);
1285 Status
= DispPrepareIrpForCancel(TranContext
, Irp
, NULL
);
1286 if (NT_SUCCESS(Status
)) {
1287 Request
.RequestNotifyObject
= DispDataRequestComplete
;
1288 Request
.RequestContext
= Irp
;
1290 Status
= InfoTdiSetInformationEx(&Request
, &Info
->ID
,
1291 &Info
->Buffer
, Info
->BufferSize
);
1293 if (Status
!= STATUS_PENDING
) {
1294 IoAcquireCancelSpinLock(&OldIrql
);
1295 IoSetCancelRoutine(Irp
, NULL
);
1296 IoReleaseCancelSpinLock(OldIrql
);