|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
tdikrnl.h
Abstract:
This header file contains interface definitions for NT transport providers running in kernel mode. This interface is documented in the NT Transport Driver Interface (TDI) Specification, Version 2.
Revision History:
--*/
#ifndef _TDI_KRNL_ #define _TDI_KRNL_
#include <tdi.h> // get the user mode includes #include <netpnp.h>
// // In this TDI, a kernel mode client calls TDI using IoCallDriver with the // current Irp stack pointer set to 16 bytes of pointers to other structures. // each of the supported NtDeviceIoControlFile analogs has a somehat different // structure, laid out below. // // The IrpSP information passed by kernel mode clients looks like: //
typedef struct _TDI_REQUEST_KERNEL { ULONG_PTR RequestFlags; PTDI_CONNECTION_INFORMATION RequestConnectionInformation; PTDI_CONNECTION_INFORMATION ReturnConnectionInformation; PVOID RequestSpecific; } TDI_REQUEST_KERNEL, *PTDI_REQUEST_KERNEL;
// // defined request codes for the kernel clients. We make these the same // as the IOCTL codes mostly for convenience; either can be used with // the same results. //
#define TDI_ASSOCIATE_ADDRESS (0x01) #define TDI_DISASSOCIATE_ADDRESS (0x02) #define TDI_CONNECT (0x03) #define TDI_LISTEN (0x04) #define TDI_ACCEPT (0x05) #define TDI_DISCONNECT (0x06) #define TDI_SEND (0x07) #define TDI_RECEIVE (0x08) #define TDI_SEND_DATAGRAM (0x09) #define TDI_RECEIVE_DATAGRAM (0x0A) #define TDI_SET_EVENT_HANDLER (0x0B) #define TDI_QUERY_INFORMATION (0x0C) #define TDI_SET_INFORMATION (0x0D) #define TDI_ACTION (0x0E)
#define TDI_DIRECT_SEND (0x27) #define TDI_DIRECT_SEND_DATAGRAM (0x29)
// // TdiOpenAddress (Not Used) // TdiCloseAddress (Not Used) // TdiOpenConnection (Not Used) // TdiCloseConnection (Not Used) //
// // some useful constants for comparison when determining the file type; // not required. //
#define TDI_TRANSPORT_ADDRESS_FILE 1 #define TDI_CONNECTION_FILE 2 #define TDI_CONTROL_CHANNEL_FILE 3
// // Internal TDI IOCTLS //
#define IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER _TDI_CONTROL_CODE( 0x80, METHOD_NEITHER ) #define IOCTL_TDI_QUERY_DIRECT_SENDDG_HANDLER _TDI_CONTROL_CODE( 0x81, METHOD_NEITHER )
// // TdiAssociateAddress //
typedef struct _TDI_REQUEST_KERNEL_ASSOCIATE { HANDLE AddressHandle; } TDI_REQUEST_KERNEL_ASSOCIATE, *PTDI_REQUEST_KERNEL_ASSOCIATE;
// // TdiDisassociateAddress -- None supplied //
typedef TDI_REQUEST_KERNEL TDI_REQUEST_KERNEL_DISASSOCIATE, *PTDI_REQUEST_KERNEL_DISASSOCIATE;
// // TdiConnect uses the structure given above (TDI_REQUEST_KERNEL); it's // defined again below for convenience //
typedef TDI_REQUEST_KERNEL TDI_REQUEST_KERNEL_CONNECT, *PTDI_REQUEST_KERNEL_CONNECT;
// // TdiDisconnect uses the structure given above (TDI_REQUEST_KERNEL); it's // defined again below for convenience //
typedef TDI_REQUEST_KERNEL TDI_REQUEST_KERNEL_DISCONNECT, *PTDI_REQUEST_KERNEL_DISCONNECT;
// // TdiListen uses the structure given above (TDI_REQUEST_KERNEL); it's // defined again below for convenience //
typedef TDI_REQUEST_KERNEL TDI_REQUEST_KERNEL_LISTEN, *PTDI_REQUEST_KERNEL_LISTEN;
// // TdiAccept //
typedef struct _TDI_REQUEST_KERNEL_ACCEPT { PTDI_CONNECTION_INFORMATION RequestConnectionInformation; PTDI_CONNECTION_INFORMATION ReturnConnectionInformation; } TDI_REQUEST_KERNEL_ACCEPT, *PTDI_REQUEST_KERNEL_ACCEPT;
// // TdiSend //
typedef struct _TDI_REQUEST_KERNEL_SEND { ULONG SendLength; ULONG SendFlags; } TDI_REQUEST_KERNEL_SEND, *PTDI_REQUEST_KERNEL_SEND;
// // TdiReceive //
typedef struct _TDI_REQUEST_KERNEL_RECEIVE { ULONG ReceiveLength; ULONG ReceiveFlags; } TDI_REQUEST_KERNEL_RECEIVE, *PTDI_REQUEST_KERNEL_RECEIVE;
// // TdiSendDatagram //
typedef struct _TDI_REQUEST_KERNEL_SENDDG { ULONG SendLength; PTDI_CONNECTION_INFORMATION SendDatagramInformation; } TDI_REQUEST_KERNEL_SENDDG, *PTDI_REQUEST_KERNEL_SENDDG;
// // TdiReceiveDatagram //
typedef struct _TDI_REQUEST_KERNEL_RECEIVEDG { ULONG ReceiveLength; PTDI_CONNECTION_INFORMATION ReceiveDatagramInformation; PTDI_CONNECTION_INFORMATION ReturnDatagramInformation; ULONG ReceiveFlags; } TDI_REQUEST_KERNEL_RECEIVEDG, *PTDI_REQUEST_KERNEL_RECEIVEDG;
// // TdiSetEventHandler //
typedef struct _TDI_REQUEST_KERNEL_SET_EVENT { LONG EventType; PVOID EventHandler; PVOID EventContext; } TDI_REQUEST_KERNEL_SET_EVENT, *PTDI_REQUEST_KERNEL_SET_EVENT;
// // TdiQueryInformation //
typedef struct _TDI_REQUEST_KERNEL_QUERY_INFO { LONG QueryType; PTDI_CONNECTION_INFORMATION RequestConnectionInformation; } TDI_REQUEST_KERNEL_QUERY_INFORMATION, *PTDI_REQUEST_KERNEL_QUERY_INFORMATION;
// // TdiSetInformation //
typedef struct _TDI_REQUEST_KERNEL_SET_INFO { LONG SetType; PTDI_CONNECTION_INFORMATION RequestConnectionInformation; } TDI_REQUEST_KERNEL_SET_INFORMATION, *PTDI_REQUEST_KERNEL_SET_INFORMATION;
// // Event types that are known //
#define TDI_EVENT_CONNECT ((USHORT)0) // TDI_IND_CONNECT event handler. #define TDI_EVENT_DISCONNECT ((USHORT)1) // TDI_IND_DISCONNECT event handler. #define TDI_EVENT_ERROR ((USHORT)2) // TDI_IND_ERROR event handler. #define TDI_EVENT_RECEIVE ((USHORT)3) // TDI_IND_RECEIVE event handler. #define TDI_EVENT_RECEIVE_DATAGRAM ((USHORT)4) // TDI_IND_RECEIVE_DATAGRAM event handler. #define TDI_EVENT_RECEIVE_EXPEDITED ((USHORT)5) // TDI_IND_RECEIVE_EXPEDITED event handler. #define TDI_EVENT_SEND_POSSIBLE ((USHORT)6) // TDI_IND_SEND_POSSIBLE event handler #define TDI_EVENT_CHAINED_RECEIVE ((USHORT)7) // TDI_IND_CHAINED_RECEIVE event handler. #define TDI_EVENT_CHAINED_RECEIVE_DATAGRAM ((USHORT)8) // TDI_IND_CHAINED_RECEIVE_DATAGRAM event handler. #define TDI_EVENT_CHAINED_RECEIVE_EXPEDITED ((USHORT)9) // TDI_IND_CHAINED_RECEIVE_EXPEDITED event handler. #define TDI_EVENT_ERROR_EX ((USHORT)10) // TDI_IND_UNREACH_ERROR event handler.
// // indicate connection event prototype. This is invoked when a request for // connection has been received by the provider and the user wishes to either // accept or reject that request. //
typedef NTSTATUS (*PTDI_IND_CONNECT)( IN PVOID TdiEventContext, IN LONG RemoteAddressLength, IN PVOID RemoteAddress, IN LONG UserDataLength, IN PVOID UserData, IN LONG OptionsLength, IN PVOID Options, OUT CONNECTION_CONTEXT *ConnectionContext, OUT PIRP *AcceptIrp );
NTSTATUS TdiDefaultConnectHandler ( IN PVOID TdiEventContext, IN LONG RemoteAddressLength, IN PVOID RemoteAddress, IN LONG UserDataLength, IN PVOID UserData, IN LONG OptionsLength, IN PVOID Options, OUT CONNECTION_CONTEXT *ConnectionContext, OUT PIRP *AcceptIrp );
// // Disconnection indication prototype. This is invoked when a connection is // being disconnected for a reason other than the user requesting it. Note that // this is a change from TDI V1, which indicated only when the remote caused // a disconnection. Any non-directed disconnection will cause this indication. //
typedef NTSTATUS (*PTDI_IND_DISCONNECT)( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN LONG DisconnectDataLength, IN PVOID DisconnectData, IN LONG DisconnectInformationLength, IN PVOID DisconnectInformation, IN ULONG DisconnectFlags );
NTSTATUS TdiDefaultDisconnectHandler ( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN LONG DisconnectDataLength, IN PVOID DisconnectData, IN LONG DisconnectInformationLength, IN PVOID DisconnectInformation, IN ULONG DisconnectFlags );
// // A protocol error has occurred when this indication happens. This indication // occurs only for errors of the worst type; the address this indication is // delivered to is no longer usable for protocol-related operations, and // should not be used for operations henceforth. All connections associated // it are invalid. // For NetBIOS-type providers, this indication is also delivered when a name // in conflict or duplicate name occurs. //
typedef NTSTATUS (*PTDI_IND_ERROR)( IN PVOID TdiEventContext, // the endpoint's file object. IN NTSTATUS Status // status code indicating error type. );
typedef NTSTATUS (*PTDI_IND_ERROR_EX)( IN PVOID TdiEventContext, // the endpoint's file object. IN NTSTATUS Status, // status code indicating error type. IN PVOID Buffer );
NTSTATUS TdiDefaultErrorHandler ( IN PVOID TdiEventContext, // the endpoint's file object. IN NTSTATUS Status // status code indicating error type. );
// // TDI_IND_RECEIVE indication handler definition. This client routine is // called by the transport provider when a connection-oriented TSDU is received // that should be presented to the client. //
typedef NTSTATUS (*PTDI_IND_RECEIVE)( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT ULONG *BytesTaken, IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED. );
NTSTATUS TdiDefaultReceiveHandler ( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT ULONG *BytesTaken, IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED. );
// // TDI_IND_RECEIVE_DATAGRAM indication handler definition. This client routine // is called by the transport provider when a connectionless TSDU is received // that should be presented to the client. //
typedef NTSTATUS (*PTDI_IND_RECEIVE_DATAGRAM)( IN PVOID TdiEventContext, // the event context IN LONG SourceAddressLength, // length of the originator of the datagram IN PVOID SourceAddress, // string describing the originator of the datagram IN LONG OptionsLength, // options for the receive IN PVOID Options, // IN ULONG ReceiveDatagramFlags, // IN ULONG BytesIndicated, // number of bytes this indication IN ULONG BytesAvailable, // number of bytes in complete Tsdu OUT ULONG *BytesTaken, // number of bytes used IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED. );
NTSTATUS TdiDefaultRcvDatagramHandler ( IN PVOID TdiEventContext, // the event context IN LONG SourceAddressLength, // length of the originator of the datagram IN PVOID SourceAddress, // string describing the originator of the datagram IN LONG OptionsLength, // options for the receive IN PVOID Options, // IN ULONG ReceiveDatagramFlags, // IN ULONG BytesIndicated, // number of bytes this indication IN ULONG BytesAvailable, // number of bytes in complete Tsdu OUT ULONG *BytesTaken, // number of bytes used IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED. );
// // This indication is delivered if expedited data is received on the connection. // This will only occur in providers that support expedited data. //
typedef NTSTATUS (*PTDI_IND_RECEIVE_EXPEDITED)( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, // IN ULONG BytesIndicated, // number of bytes in this indication IN ULONG BytesAvailable, // number of bytes in complete Tsdu OUT ULONG *BytesTaken, // number of bytes used by indication routine IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED. );
NTSTATUS TdiDefaultRcvExpeditedHandler ( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, // IN ULONG BytesIndicated, // number of bytes in this indication IN ULONG BytesAvailable, // number of bytes in complete Tsdu OUT ULONG *BytesTaken, // number of bytes used by indication routine IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED. );
// // TDI_IND_CHAINED_RECEIVE indication handler definition. This client routine // is called by the transport provider when a connection-oriented TSDU is // received that should be presented to the client. The TSDU is stored in an // MDL chain. The client may take ownership of the TSDU and return it at a // later time. //
typedef NTSTATUS (*PTDI_IND_CHAINED_RECEIVE)( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG ReceiveLength, // length of client data in TSDU IN ULONG StartingOffset, // offset of start of client data in TSDU IN PMDL Tsdu, // TSDU data chain IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives );
NTSTATUS TdiDefaultChainedReceiveHandler ( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG ReceiveLength, // length of client data in TSDU IN ULONG StartingOffset, // offset of start of client data in TSDU IN PMDL Tsdu, // TSDU data chain IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives );
// // TDI_IND_CHAINED_RECEIVE_DATAGRAM indication handler definition. This client // routine is called by the transport provider when a connectionless TSDU is // received that should be presented to the client. The TSDU is stored in an // MDL chain. The client may take ownership of the TSDU and return it at a // later time. //
typedef NTSTATUS (*PTDI_IND_CHAINED_RECEIVE_DATAGRAM)( IN PVOID TdiEventContext, // the event context IN LONG SourceAddressLength, // length of the originator of the datagram IN PVOID SourceAddress, // string describing the originator of the datagram IN LONG OptionsLength, // options for the receive IN PVOID Options, // IN ULONG ReceiveDatagramFlags, // IN ULONG ReceiveDatagramLength, // length of client data in TSDU IN ULONG StartingOffset, // offset of start of client data in TSDU IN PMDL Tsdu, // TSDU data chain IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives );
NTSTATUS TdiDefaultChainedRcvDatagramHandler ( IN PVOID TdiEventContext, // the event context IN LONG SourceAddressLength, // length of the originator of the datagram IN PVOID SourceAddress, // string describing the originator of the datagram IN LONG OptionsLength, // options for the receive IN PVOID Options, // IN ULONG ReceiveDatagramFlags, // IN ULONG ReceiveDatagramLength, // length of client data in TSDU IN ULONG StartingOffset, // offset of start of client data in TSDU IN PMDL Tsdu, // TSDU data chain IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives );
// // This indication is delivered if expedited data is received on the connection. // This will only occur in providers that support expedited data. The TSDU is // stored in an MDL chain. The client may take ownership of the TSDU and // return it at a later time. //
typedef NTSTATUS (*PTDI_IND_CHAINED_RECEIVE_EXPEDITED)( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG ReceiveLength, // length of client data in TSDU IN ULONG StartingOffset, // offset of start of client data in TSDU IN PMDL Tsdu, // TSDU data chain IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives );
NTSTATUS TdiDefaultChainedRcvExpeditedHandler ( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG ReceiveLength, // length of client data in TSDU IN ULONG StartingOffset, // offset of start of client data in TSDU IN PMDL Tsdu, // TSDU data chain IN PVOID TsduDescriptor // for call to TdiReturnChainedReceives );
// // This indication is delivered if there is room for a send in the buffer of // a buffering protocol. //
typedef NTSTATUS (*PTDI_IND_SEND_POSSIBLE)( IN PVOID TdiEventContext, IN PVOID ConnectionContext, IN ULONG BytesAvailable);
NTSTATUS TdiDefaultSendPossibleHandler ( IN PVOID TdiEventContext, IN PVOID ConnectionContext, IN ULONG BytesAvailable);
// // defined MACROS to allow the kernel mode client to easily build an IRP for // any function. //
#define TdiBuildAssociateAddress(Irp, DevObj, FileObj, CompRoutine, Contxt, AddrHandle) \ { \ PTDI_REQUEST_KERNEL_ASSOCIATE p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_ASSOCIATE_ADDRESS; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_ASSOCIATE)&_IRPSP->Parameters; \ p->AddressHandle = (HANDLE)(AddrHandle); \ }
#define TdiBuildDisassociateAddress(Irp, DevObj, FileObj, CompRoutine, Contxt) \ { \ PTDI_REQUEST_KERNEL_DISASSOCIATE p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_DISASSOCIATE_ADDRESS; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_DISASSOCIATE)&_IRPSP->Parameters; \ }
#define TdiBuildConnect(Irp, DevObj, FileObj, CompRoutine, Contxt, Time, RequestConnectionInfo, ReturnConnectionInfo)\ { \ PTDI_REQUEST_KERNEL p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_CONNECT; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL)&_IRPSP->Parameters; \ p->RequestConnectionInformation = RequestConnectionInfo; \ p->ReturnConnectionInformation = ReturnConnectionInfo; \ p->RequestSpecific = (PVOID)Time; \ }
#define TdiBuildListen(Irp, DevObj, FileObj, CompRoutine, Contxt, Flags, RequestConnectionInfo, ReturnConnectionInfo)\ { \ PTDI_REQUEST_KERNEL p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_LISTEN; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL)&_IRPSP->Parameters; \ p->RequestFlags = Flags; \ p->RequestConnectionInformation = RequestConnectionInfo; \ p->ReturnConnectionInformation = ReturnConnectionInfo; \ }
#define TdiBuildAccept(Irp, DevObj, FileObj, CompRoutine, Contxt, RequestConnectionInfo, ReturnConnectionInfo)\ { \ PTDI_REQUEST_KERNEL_ACCEPT p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_ACCEPT; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_ACCEPT)&_IRPSP->Parameters; \ p->RequestConnectionInformation = RequestConnectionInfo; \ p->ReturnConnectionInformation = ReturnConnectionInfo; \ }
#define TdiBuildDisconnect(Irp, DevObj, FileObj, CompRoutine, Contxt, Time, Flags, RequestConnectionInfo, ReturnConnectionInfo)\ { \ PTDI_REQUEST_KERNEL p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_DISCONNECT; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL)&_IRPSP->Parameters; \ p->RequestFlags = Flags; \ p->RequestConnectionInformation = RequestConnectionInfo; \ p->ReturnConnectionInformation = ReturnConnectionInfo; \ p->RequestSpecific = (PVOID)Time; \ }
#define TdiBuildReceive(Irp, DevObj, FileObj, CompRoutine, Contxt, MdlAddr, InFlags, ReceiveLen)\ { \ PTDI_REQUEST_KERNEL_RECEIVE p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_RECEIVE; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_RECEIVE)&_IRPSP->Parameters; \ p->ReceiveFlags = InFlags; \ p->ReceiveLength = ReceiveLen; \ Irp->MdlAddress = MdlAddr; \ }
#define TdiBuildSend(Irp, DevObj, FileObj, CompRoutine, Contxt, MdlAddr, InFlags, SendLen)\ { \ PTDI_REQUEST_KERNEL_SEND p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_SEND; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_SEND)&_IRPSP->Parameters; \ p->SendFlags = InFlags; \ p->SendLength = SendLen; \ Irp->MdlAddress = MdlAddr; \ }
#define TdiBuildSendDatagram(Irp, DevObj, FileObj, CompRoutine, Contxt, MdlAddr, SendLen, SendDatagramInfo)\ { \ PTDI_REQUEST_KERNEL_SENDDG p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_SEND_DATAGRAM; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_SENDDG)&_IRPSP->Parameters; \ p->SendLength = SendLen; \ p->SendDatagramInformation = SendDatagramInfo; \ Irp->MdlAddress = MdlAddr; \ }
#define TdiBuildReceiveDatagram(Irp, DevObj, FileObj, CompRoutine, Contxt, MdlAddr, ReceiveLen, ReceiveDatagramInfo, ReturnInfo, InFlags)\ { \ PTDI_REQUEST_KERNEL_RECEIVEDG p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_RECEIVE_DATAGRAM; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_RECEIVEDG)&_IRPSP->Parameters; \ p->ReceiveLength = ReceiveLen; \ p->ReceiveDatagramInformation = ReceiveDatagramInfo; \ p->ReturnDatagramInformation = ReturnInfo; \ p->ReceiveFlags = InFlags; \ Irp->MdlAddress = MdlAddr; \ }
#define TdiBuildSetEventHandler(Irp, DevObj, FileObj, CompRoutine, Contxt, InEventType, InEventHandler, InEventContext) \ { \ PTDI_REQUEST_KERNEL_SET_EVENT p; \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_SET_EVENT_HANDLER; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_SET_EVENT)&_IRPSP->Parameters; \ p->EventType = InEventType; \ p->EventHandler = (PVOID)InEventHandler; \ p->EventContext = (PVOID)InEventContext; \ }
#define TdiBuildQueryInformation(Irp, DevObj, FileObj, CompRoutine, Contxt, QType, MdlAddr)\ { \ PTDI_REQUEST_KERNEL_QUERY_INFORMATION p; \ PIO_STACK_LOCATION _IRPSP; \ Irp->MdlAddress = MdlAddr; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_QUERY_INFORMATION; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&_IRPSP->Parameters; \ p->QueryType = (ULONG)QType; \ p->RequestConnectionInformation = NULL; \ }
#define TdiBuildSetInformation(Irp, DevObj, FileObj, CompRoutine, Contxt, SType, MdlAddr)\ { \ PTDI_REQUEST_KERNEL_SET_INFORMATION p; \ PIO_STACK_LOCATION _IRPSP; \ Irp->MdlAddress = MdlAddr; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_SET_INFORMATION; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ p = (PTDI_REQUEST_KERNEL_SET_INFORMATION)&_IRPSP->Parameters; \ p->SetType = (ULONG)SType; \ p->RequestConnectionInformation = NULL; \ }
#define TdiBuildAction(Irp, DevObj, FileObj, CompRoutine, Contxt, MdlAddr)\ { \ PIO_STACK_LOCATION _IRPSP; \ if ( CompRoutine != NULL) { \ IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\ } else { \ IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \ } \ _IRPSP = IoGetNextIrpStackLocation (Irp); \ _IRPSP->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ _IRPSP->MinorFunction = TDI_ACTION; \ _IRPSP->DeviceObject = DevObj; \ _IRPSP->FileObject = FileObj; \ Irp->MdlAddress = MdlAddr; \ }
// // definitions for the helper routines for TDI compliant transports and clients // // Note that the IOCTL used here for the Irp Function is not real; it is used // to avoid this IO routine having to map buffers (which we don't want). // //PIRP //TdiBuildInternalDeviceControlIrp ( // IN CCHAR IrpSubFunction, // IN PDEVICE_OBJECT DeviceObject, // IN PFILE_OBJECT FileObject, // IN PKEVENT Event, // IN PIO_STATUS_BLOCK IoStatusBlock // );
#define TdiBuildInternalDeviceControlIrp(IrpSubFunction,DeviceObject,FileObject,Event,IoStatusBlock) \ IoBuildDeviceIoControlRequest (\ 0x00000003,\ DeviceObject, \ NULL, \ 0, \ NULL, \ 0, \ TRUE, \ Event, \ IoStatusBlock)
// // VOID // TdiCopyLookaheadData( // IN PVOID Destination, // IN PVOID Source, // IN ULONG Length, // IN ULONG ReceiveFlags // ); //
#ifdef _M_IX86 #define TdiCopyLookaheadData(_Destination,_Source,_Length,_ReceiveFlags) \ RtlCopyMemory(_Destination,_Source,_Length) #else #define TdiCopyLookaheadData(_Destination,_Source,_Length,_ReceiveFlags) { \ if ((_ReceiveFlags) & TDI_RECEIVE_COPY_LOOKAHEAD) { \ RtlCopyMemory(_Destination,_Source,_Length); \ } else { \ PUCHAR _Src = (PUCHAR)(_Source); \ PUCHAR _Dest = (PUCHAR)(_Destination); \ PUCHAR _End = _Dest + (_Length); \ while (_Dest < _End) { \ *_Dest++ = *_Src++; \ } \ } \ } #endif
NTSTATUS TdiMapUserRequest( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp );
NTSTATUS TdiCopyBufferToMdl ( IN PVOID SourceBuffer, IN ULONG SourceOffset, IN ULONG SourceBytesToCopy, IN PMDL DestinationMdlChain, IN ULONG DestinationOffset, IN PULONG BytesCopied );
NTSTATUS TdiCopyMdlToBuffer( IN PMDL SourceMdlChain, IN ULONG SourceOffset, IN PVOID DestinationBuffer, IN ULONG DestinationOffset, IN ULONG DestinationBufferSize, OUT PULONG BytesCopied );
NTSTATUS TdiCopyMdlChainToMdlChain( IN PMDL SourceMdlChain, IN ULONG SourceOffset, IN PMDL DestinationMdlChain, IN ULONG DestinationOffset, OUT PULONG BytesCopied );
VOID TdiBuildNetbiosAddress ( IN PUCHAR NetbiosName, IN BOOLEAN IsGroupName, IN OUT PTA_NETBIOS_ADDRESS NetworkName );
NTSTATUS TdiBuildNetbiosAddressEa ( IN PUCHAR Buffer, IN BOOLEAN IsGroupName, IN PUCHAR NetbiosName );
//++ // // VOID // TdiCompleteRequest ( // IN PIRP Irp, // IN NTSTATUS Status // ); // // Routine Description: // // This routine is used to complete an IRP with the indicated // status. // // Arguments: // // Irp - Supplies a pointer to the Irp to complete // // Status - Supplies the completion status for the Irp // // Return Value: // // None. // //--
#define TdiCompleteRequest(IRP,STATUS) { \ (IRP)->IoStatus.Status = (STATUS); \ IoCompleteRequest( (IRP), IO_NETWORK_INCREMENT ); \ }
VOID TdiReturnChainedReceives( IN PVOID *TsduDescriptors, IN ULONG NumberOfTsdus );
// The type definition for a TDI Bind handler callout. This callout is // called when a new transport device arrives.
typedef VOID (*TDI_BIND_HANDLER)( IN PUNICODE_STRING DeviceName );
typedef VOID (*TDI_UNBIND_HANDLER)( IN PUNICODE_STRING DeviceName );
// The type definition for a TDI address handler callout. // This is typedefed defined at the end (with the others)
typedef VOID (*TDI_ADD_ADDRESS_HANDLER)( IN PTA_ADDRESS Address );
typedef VOID (*TDI_DEL_ADDRESS_HANDLER)( IN PTA_ADDRESS Address );
typedef VOID (* TDI_NET_READY_HANDLER)( IN NTSTATUS ProviderStatus );
typedef VOID (* ProviderPnPPowerComplete)( IN PNET_PNP_EVENT NetEvent, IN NTSTATUS ProviderStatus );
NTSTATUS TdiRegisterAddressChangeHandler( IN TDI_ADD_ADDRESS_HANDLER AddHandler, IN TDI_DEL_ADDRESS_HANDLER DeleteHandler, OUT HANDLE *BindingHandle );
NTSTATUS TdiDeregisterAddressChangeHandler( IN HANDLE BindingHandle );
NTSTATUS TdiRegisterNotificationHandler( IN TDI_BIND_HANDLER BindHandler, IN TDI_UNBIND_HANDLER UnbindHandler, OUT HANDLE *BindingHandle );
NTSTATUS TdiDeregisterNotificationHandler( IN HANDLE BindingHandle );
NTSTATUS TdiRegisterDeviceObject( IN PUNICODE_STRING DeviceName, OUT HANDLE *RegistrationHandle );
NTSTATUS TdiDeregisterDeviceObject( IN HANDLE RegistrationHandle );
NTSTATUS TdiDeregisterNetAddress( IN HANDLE RegistrationHandle );
VOID TdiInitialize( VOID );
// PnP extensions to TDI. Spec : TdiPnp.doc : MunilS
typedef enum _TDI_PNP_OPCODE { TDI_PNP_OP_MIN, TDI_PNP_OP_ADD, TDI_PNP_OP_DEL, TDI_PNP_OP_UPDATE, TDI_PNP_OP_PROVIDERREADY, TDI_PNP_OP_NETREADY, TDI_PNP_OP_ADD_IGNORE_BINDING, TDI_PNP_OP_DELETE_IGNORE_BINDING, TDI_PNP_OP_MAX, } TDI_PNP_OPCODE;
typedef struct _TDI_PNP_CONTEXT { USHORT ContextSize; USHORT ContextType; UCHAR POINTER_ALIGNMENT ContextData[1]; } TDI_PNP_CONTEXT, *PTDI_PNP_CONTEXT;
typedef VOID (*TDI_BINDING_HANDLER)( IN TDI_PNP_OPCODE PnPOpcode, IN PUNICODE_STRING DeviceName, IN PWSTR MultiSZBindList );
typedef VOID (*TDI_ADD_ADDRESS_HANDLER_V2)( IN PTA_ADDRESS Address, IN PUNICODE_STRING DeviceName, IN PTDI_PNP_CONTEXT Context );
typedef VOID (*TDI_DEL_ADDRESS_HANDLER_V2)( IN PTA_ADDRESS Address, IN PUNICODE_STRING DeviceName, IN PTDI_PNP_CONTEXT Context );
typedef NTSTATUS (*TDI_PNP_POWER_HANDLER)( IN PUNICODE_STRING DeviceName, IN PNET_PNP_EVENT PowerEvent, IN PTDI_PNP_CONTEXT Context1, IN PTDI_PNP_CONTEXT Context2 );
// When the user makes changes using the NCPA, a TdiMakeNCPAChanges request // is generated through NDIS. The following structure is used to communicate // these changes.
typedef struct _TDI_NCPA_BINDING_INFO { PUNICODE_STRING TdiClientName; PUNICODE_STRING TdiProviderName; PUNICODE_STRING BindList; PVOID ReconfigBuffer; unsigned int ReconfigBufferSize; TDI_PNP_OPCODE PnpOpcode; } TDI_NCPA_BINDING_INFO, *PTDI_NCPA_BINDING_INFO;
// // The following structure makes it easy for consistency/integrity checking // typedef struct _TDI_VERSION_ { union { struct { UCHAR MajorTdiVersion; UCHAR MinorTdiVersion; }; USHORT TdiVersion; }; } TDI_VERSION, *PTDI_VERSION;
#define TDI20 typedef struct _TDI20_CLIENT_INTERFACE_INFO { union { struct { UCHAR MajorTdiVersion; UCHAR MinorTdiVersion; }; USHORT TdiVersion; };
//TDI_VERSION TdiVersion; USHORT Unused; PUNICODE_STRING ClientName; TDI_PNP_POWER_HANDLER PnPPowerHandler;
union {
TDI_BINDING_HANDLER BindingHandler;
struct { // // Putting these back in for backward compatibility. //
TDI_BIND_HANDLER BindHandler; TDI_UNBIND_HANDLER UnBindHandler;
}; };
union { struct {
TDI_ADD_ADDRESS_HANDLER_V2 AddAddressHandlerV2; TDI_DEL_ADDRESS_HANDLER_V2 DelAddressHandlerV2;
}; struct {
// // Putting these back in for backward compatibility. //
TDI_ADD_ADDRESS_HANDLER AddAddressHandler; TDI_DEL_ADDRESS_HANDLER DelAddressHandler;
};
};
// TDI_NET_READY_HANDLER NetReadyHandler;
} TDI20_CLIENT_INTERFACE_INFO, *PTDI20_CLIENT_INTERFACE_INFO;
#ifdef TDI20
#define TDI_CURRENT_MAJOR_VERSION (2) #define TDI_CURRENT_MINOR_VERSION (0)
typedef TDI20_CLIENT_INTERFACE_INFO TDI_CLIENT_INTERFACE_INFO;
#define TDI_CURRENT_VERSION ((TDI_CURRENT_MINOR_VERSION) << 8 | \ (TDI_CURRENT_MAJOR_VERSION))
#endif // TDI20
#define TDI_VERSION_ONE 0x0001
typedef TDI_CLIENT_INTERFACE_INFO *PTDI_CLIENT_INTERFACE_INFO;
NTSTATUS TdiRegisterPnPHandlers( IN PTDI_CLIENT_INTERFACE_INFO ClientInterfaceInfo, IN ULONG InterfaceInfoSize, OUT HANDLE *BindingHandle );
NTSTATUS TdiDeregisterPnPHandlers( IN HANDLE BindingHandle );
NTSTATUS TdiPnPPowerRequest( IN PUNICODE_STRING DeviceName, IN PNET_PNP_EVENT PowerEvent, IN PTDI_PNP_CONTEXT Context1, IN PTDI_PNP_CONTEXT Context2, IN ProviderPnPPowerComplete ProtocolCompletionHandler );
VOID TdiPnPPowerComplete( IN HANDLE BindingHandle, //IN PUNICODE_STRING DeviceName, IN PNET_PNP_EVENT PowerEvent, IN NTSTATUS Status );
NTSTATUS TdiRegisterNetAddress( IN PTA_ADDRESS Address, IN PUNICODE_STRING DeviceName, IN PTDI_PNP_CONTEXT Context, OUT HANDLE *RegistrationHandle );
NTSTATUS TdiMakeNCPAChanges( IN TDI_NCPA_BINDING_INFO NcpaBindingInfo );
// // Enumerate all TDI addresses for a client // NTSTATUS TdiEnumerateAddresses( IN HANDLE BindingHandle );
// // Introducing the concept of Transport provider. //
NTSTATUS TdiRegisterProvider( PUNICODE_STRING ProviderName, HANDLE *ProviderHandle );
NTSTATUS TdiProviderReady( HANDLE ProviderHandle );
NTSTATUS TdiDeregisterProvider( HANDLE ProviderHandle );
BOOLEAN TdiMatchPdoWithChainedReceiveContext( IN PVOID TsduDescriptor, IN PVOID PDO );
#define TDI_STATUS_BAD_VERSION 0xC0010004L // same as NDIS, is that OK? #define TDI_STATUS_BAD_CHARACTERISTICS 0xC0010005L // ,,
// // PNP context types // #define TDI_PNP_CONTEXT_TYPE_IF_NAME 0x1 #define TDI_PNP_CONTEXT_TYPE_IF_ADDR 0x2 #define TDI_PNP_CONTEXT_TYPE_PDO 0x3 #define TDI_PNP_CONTEXT_TYPE_FIRST_OR_LAST_IF 0x4
// The following structures and macros are for handlers that support returning // ancillary data via a control structure //
// // Layout of ancillary data objects in the control buffer // typedef struct _TDI_CMSGHDR { SIZE_T cmsg_len; LONG cmsg_level; LONG cmsg_type; /* followed by UCHAR cmsg_data[] */ } TDI_CMSGHDR, *PTDI_CMSGHDR;
// // Alignment macros for header and data members of // the control buffer. // #define TDI_CMSGHDR_ALIGN(length) \ ( ((length) + TYPE_ALIGNMENT(TDI_CMSGHDR)-1) & \ (~(TYPE_ALIGNMENT(TDI_CMSGHDR)-1)) ) \
#define TDI_CMSGDATA_ALIGN(length) \ ( ((length) + MAX_NATURAL_ALIGNMENT-1) & \ (~(MAX_NATURAL_ALIGNMENT-1)) )
// Returns a pointer to the first byte of data (what is referred // to as the cmsg_data member though it is not defined in // the structure). // // UCHAR * // TDI_CMSG_DATA ( // PTDI_CMSGHDR pcmsg // ); // #define TDI_CMSG_DATA(cmsg) \ ( (UCHAR *)(cmsg) + TDI_CMSGDATA_ALIGN(sizeof(TDI_CMSGHDR)) )
// // Returns total size of an ancillary data object given // the amount of data. Used to allocate the correct amount // of space. // // SIZE_T // TDI_CMSG_SPACE ( // SIZE_T length // ); // #define TDI_CMSG_SPACE(length) \ (TDI_CMSGDATA_ALIGN(sizeof(TDI_CMSGHDR) + TDI_CMSGHDR_ALIGN(length)))
// Returns the value to store in cmsg_len given the amount of data. // // SIZE_T // TDI_CMSG_LEN ( // SIZE_T length // ); // #define TDI_CMSG_LEN(length) \ (TDI_CMSGDATA_ALIGN(sizeof(TDI_CMSGHDR)) + length)
// Initializes the members of a TDI_CMSGHDR structure // // VOID // TDI_INIT_CMSGHDR ( // PTDI_CMSGHDR cmsg, // INT level, // INT type, // SIZE_T length, // ); // #define TDI_INIT_CMSGHDR(cmsg, level, type, length) { \ ((TDI_CMSGHDR *) cmsg)->cmsg_level = level; \ ((TDI_CMSGHDR *) cmsg)->cmsg_type = type; \ ((TDI_CMSGHDR *) cmsg)->cmsg_len = TDI_CMSG_LEN(length); \ } #endif // _TDI_KRNL_
|