|
|
/*++
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_
|