#define MY_PORT 7609
HANDLE hTdiTransport = NULL; // handle to tdi transport
PFILE_OBJECT pTdiTransportObject = NULL; // pointer to tdi transport object
dStatus = TdiOpenTransport ( // open transport
L"//Device//Udp", // device name
MY_PORT, // port number
&hTdiTransport, // return transport handle
&pTdiTransportObject ); // return transport object
dStatus = TdiOpenTransport ( // open transport
L"//Device//Tcp", // device name
MY_PORT, // port number
&hTdiTransport, // return transport handle
&pTdiTransportObject ); // return transport object
if ( NT_SUCCESS ( dStatus ) )
{
QueryAddressInfo( pTdiTransportObject, pAddress, dwSizeAddress );
}
// **************************************************************************
int QueryAddressInfo( PFILE_OBJECT pFileObject, PVOID pAddress, ULONG dwSizeAddress )
{
PDEVICE_OBJECT pDeviceObject;
PTDI_ADDRESS_INFO pAddrInfo;
NTSTATUS NtStatus;
IO_STATUS_BLOCK IoStatusBlock;
int bRes;
ULONG dwSize;
if (KeGetCurrentIrql() != PASSIVE_LEVEL) //> DISPATCH_LEVEL)
return FALSE;
if ( pFileObject == NULL || pAddress == NULL)
return FALSE;
bRes = FALSE;
dwSize = sizeof(TDI_ADDRESS_INFO) + sizeof(TDI_ADDRESS_IP);
pDeviceObject = IoGetRelatedDeviceObject( pFileObject );
pAddrInfo = (PTDI_ADDRESS_INFO) ExAllocatePool( PagedPool, dwSize );
if (pAddrInfo != NULL)
{
PIRP pIrp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, pDeviceObject, pFileObject, NULL, NULL);
if (pIrp != NULL)
{
PMDL pMdl = IoAllocateMdl(pAddrInfo, dwSize, FALSE, FALSE, NULL);
if (pMdl != NULL)
{
__try
{
MmProbeAndLockPages(pMdl, KernelMode, IoModifyAccess); // probe & lock
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(pMdl);
pMdl = NULL;
}
if (pMdl != NULL)
{
TdiBuildQueryInformation(pIrp, pDeviceObject, pFileObject, NULL, NULL, TDI_QUERY_ADDRESS_INFO, pMdl);
NtStatus = TdiCall(pIrp, pDeviceObject, &IoStatusBlock);
if (NT_SUCCESS(NtStatus))
{
memcpy(pAddress, &(pAddrInfo->Address), dwSizeAddress);
}
}
}
}
ExFreePool( pAddrInfo );
}
return bRes;
}
// **************************************************************************
NTSTATUS TdiOpenTransport (
IN PWSTR pProtocol,
IN USHORT wPort,
OUT PHANDLE phTransport,
OUT PFILE_OBJECT *ppTransportObject )
{
PTA_IP_ADDRESS pAddress; // transport address
ULONG dEaLength; // buffer size
PFILE_FULL_EA_INFORMATION pEaInfo; // pointer to ea
NTSTATUS dStatus; // current status
dEaLength = sizeof ( FILE_FULL_EA_INFORMATION ) + // account for ea
sizeof ( TdiTransportAddress ) + // account for transport
sizeof ( TA_IP_ADDRESS ) + 1; // account for ip address
pEaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool (
NonPagedPool, dEaLength );
if ( pEaInfo ) // validate pointer
{
RtlZeroMemory ( pEaInfo, dEaLength ); // clear eabuffer
pEaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; // size
RtlCopyMemory ( pEaInfo->EaName, // copy transport name
TdiTransportAddress,
sizeof ( TdiTransportAddress ) );
pEaInfo->EaValueLength = sizeof ( TA_IP_ADDRESS ); // size of data
pAddress = (PTA_IP_ADDRESS)(pEaInfo->EaName +
sizeof ( TdiTransportAddress ));
pAddress->TAAddressCount = 1; // number of addresses
pAddress->Address[0].AddressLength = sizeof ( TDI_ADDRESS_IP );
pAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
pAddress->Address[0].Address[0].sin_port = // local port
W_LITTLE_TO_BIG_ENDIAN(wPort);
pAddress->Address[0].Address[0].in_addr = 0L; // local address
dStatus = TdiOpen ( // open tdi device
pProtocol, // tdi device name
dEaLength, // length of ea info
pEaInfo, // pointer to ea info
phTransport, // return transport handle
ppTransportObject ); // return transport object
ExFreePool ( pEaInfo ); // free buffer
}
return ( dStatus );
}
NTSTATUS TdiOpen (
IN PWSTR pProtocol,
IN ULONG dEaLength,
IN PFILE_FULL_EA_INFORMATION pEaInfo,
OUT PHANDLE phHandle,
OUT PFILE_OBJECT *ppObject )
{
UNICODE_STRING uName; // local name
OBJECT_ATTRIBUTES ObjectAttrib; // local object attribute
IO_STATUS_BLOCK IoStatusBlock; // local io status return
NTSTATUS dStatus; // current status
RtlInitUnicodeString ( &uName, pProtocol ); // get device name
InitializeObjectAttributes( &ObjectAttrib, // return object attribute
&uName, // resource name
OBJ_CASE_INSENSITIVE, // attributes
NULL, // root directory
NULL ); // security descriptor
dStatus = ZwCreateFile (
phHandle, // return file handle
GENERIC_READ | GENERIC_WRITE, // desired access
&ObjectAttrib, // local object attribute
&IoStatusBlock, // local io status
0L, // initial allocation size
FILE_ATTRIBUTE_NORMAL, // file attributes
FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
FILE_OPEN_IF, // create disposition
0L, // create options
pEaInfo, // eabuffer
dEaLength ); // ealength
if ( NT_SUCCESS ( dStatus ) ) // check for valid return
{
dStatus = ObReferenceObjectByHandle ( // reference file object
*phHandle, // handle to open file
GENERIC_READ | GENERIC_WRITE, // access mode
NULL, // object type
KernelMode, // access mode
(PVOID)ppObject, // pointer to object
NULL ); // handle information
if ( !NT_SUCCESS ( dStatus ) )
ZwClose ( *phHandle ); // close handle
}
return ( dStatus );
}
// **************************************************************************
NTSTATUS TdiCall (
IN PIRP pIrp,
IN PDEVICE_OBJECT pDeviceObject,
IN OUT PIO_STATUS_BLOCK pIoStatusBlock )
{
KEVENT kEvent; // signaling event
NTSTATUS dStatus = STATUS_INSUFFICIENT_RESOURCES; // local status
KeInitializeEvent ( &kEvent, NotificationEvent, FALSE ); // reset notification event
pIrp->UserEvent = &kEvent; // pointer to event
pIrp->UserIosb = pIoStatusBlock; // pointer to status block
dStatus = IoCallDriver ( pDeviceObject, pIrp ); // call next driver
if ( dStatus == STATUS_PENDING ) // make all request synchronous
{
(void)KeWaitForSingleObject (
(PVOID)&kEvent, // signaling object
Executive, // wait reason
KernelMode, // wait mode
TRUE, // alertable
NULL ); // timeout
}
dStatus = pIoStatusBlock->Status;
return ( dStatus ); // return with status
}
// **************************************************************************
NTSTATUS TdiClose (
IN HANDLE hHandle,
IN PFILE_OBJECT pObject )
{
if ( pObject ) // validate pointers
ObDereferenceObject( pObject ); // release the object
if ( hHandle )
ZwClose ( hHandle ); // close handle
return ( STATUS_SUCCESS );
}
HANDLE hTdiTransport = NULL; // handle to tdi transport
PFILE_OBJECT pTdiTransportObject = NULL; // pointer to tdi transport object
dStatus = TdiOpenTransport ( // open transport
L"//Device//Udp", // device name
MY_PORT, // port number
&hTdiTransport, // return transport handle
&pTdiTransportObject ); // return transport object
dStatus = TdiOpenTransport ( // open transport
L"//Device//Tcp", // device name
MY_PORT, // port number
&hTdiTransport, // return transport handle
&pTdiTransportObject ); // return transport object
if ( NT_SUCCESS ( dStatus ) )
{
QueryAddressInfo( pTdiTransportObject, pAddress, dwSizeAddress );
}
// **************************************************************************
int QueryAddressInfo( PFILE_OBJECT pFileObject, PVOID pAddress, ULONG dwSizeAddress )
{
PDEVICE_OBJECT pDeviceObject;
PTDI_ADDRESS_INFO pAddrInfo;
NTSTATUS NtStatus;
IO_STATUS_BLOCK IoStatusBlock;
int bRes;
ULONG dwSize;
if (KeGetCurrentIrql() != PASSIVE_LEVEL) //> DISPATCH_LEVEL)
return FALSE;
if ( pFileObject == NULL || pAddress == NULL)
return FALSE;
bRes = FALSE;
dwSize = sizeof(TDI_ADDRESS_INFO) + sizeof(TDI_ADDRESS_IP);
pDeviceObject = IoGetRelatedDeviceObject( pFileObject );
pAddrInfo = (PTDI_ADDRESS_INFO) ExAllocatePool( PagedPool, dwSize );
if (pAddrInfo != NULL)
{
PIRP pIrp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, pDeviceObject, pFileObject, NULL, NULL);
if (pIrp != NULL)
{
PMDL pMdl = IoAllocateMdl(pAddrInfo, dwSize, FALSE, FALSE, NULL);
if (pMdl != NULL)
{
__try
{
MmProbeAndLockPages(pMdl, KernelMode, IoModifyAccess); // probe & lock
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(pMdl);
pMdl = NULL;
}
if (pMdl != NULL)
{
TdiBuildQueryInformation(pIrp, pDeviceObject, pFileObject, NULL, NULL, TDI_QUERY_ADDRESS_INFO, pMdl);
NtStatus = TdiCall(pIrp, pDeviceObject, &IoStatusBlock);
if (NT_SUCCESS(NtStatus))
{
memcpy(pAddress, &(pAddrInfo->Address), dwSizeAddress);
}
}
}
}
ExFreePool( pAddrInfo );
}
return bRes;
}
// **************************************************************************
NTSTATUS TdiOpenTransport (
IN PWSTR pProtocol,
IN USHORT wPort,
OUT PHANDLE phTransport,
OUT PFILE_OBJECT *ppTransportObject )
{
PTA_IP_ADDRESS pAddress; // transport address
ULONG dEaLength; // buffer size
PFILE_FULL_EA_INFORMATION pEaInfo; // pointer to ea
NTSTATUS dStatus; // current status
dEaLength = sizeof ( FILE_FULL_EA_INFORMATION ) + // account for ea
sizeof ( TdiTransportAddress ) + // account for transport
sizeof ( TA_IP_ADDRESS ) + 1; // account for ip address
pEaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool (
NonPagedPool, dEaLength );
if ( pEaInfo ) // validate pointer
{
RtlZeroMemory ( pEaInfo, dEaLength ); // clear eabuffer
pEaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; // size
RtlCopyMemory ( pEaInfo->EaName, // copy transport name
TdiTransportAddress,
sizeof ( TdiTransportAddress ) );
pEaInfo->EaValueLength = sizeof ( TA_IP_ADDRESS ); // size of data
pAddress = (PTA_IP_ADDRESS)(pEaInfo->EaName +
sizeof ( TdiTransportAddress ));
pAddress->TAAddressCount = 1; // number of addresses
pAddress->Address[0].AddressLength = sizeof ( TDI_ADDRESS_IP );
pAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
pAddress->Address[0].Address[0].sin_port = // local port
W_LITTLE_TO_BIG_ENDIAN(wPort);
pAddress->Address[0].Address[0].in_addr = 0L; // local address
dStatus = TdiOpen ( // open tdi device
pProtocol, // tdi device name
dEaLength, // length of ea info
pEaInfo, // pointer to ea info
phTransport, // return transport handle
ppTransportObject ); // return transport object
ExFreePool ( pEaInfo ); // free buffer
}
return ( dStatus );
}
NTSTATUS TdiOpen (
IN PWSTR pProtocol,
IN ULONG dEaLength,
IN PFILE_FULL_EA_INFORMATION pEaInfo,
OUT PHANDLE phHandle,
OUT PFILE_OBJECT *ppObject )
{
UNICODE_STRING uName; // local name
OBJECT_ATTRIBUTES ObjectAttrib; // local object attribute
IO_STATUS_BLOCK IoStatusBlock; // local io status return
NTSTATUS dStatus; // current status
RtlInitUnicodeString ( &uName, pProtocol ); // get device name
InitializeObjectAttributes( &ObjectAttrib, // return object attribute
&uName, // resource name
OBJ_CASE_INSENSITIVE, // attributes
NULL, // root directory
NULL ); // security descriptor
dStatus = ZwCreateFile (
phHandle, // return file handle
GENERIC_READ | GENERIC_WRITE, // desired access
&ObjectAttrib, // local object attribute
&IoStatusBlock, // local io status
0L, // initial allocation size
FILE_ATTRIBUTE_NORMAL, // file attributes
FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
FILE_OPEN_IF, // create disposition
0L, // create options
pEaInfo, // eabuffer
dEaLength ); // ealength
if ( NT_SUCCESS ( dStatus ) ) // check for valid return
{
dStatus = ObReferenceObjectByHandle ( // reference file object
*phHandle, // handle to open file
GENERIC_READ | GENERIC_WRITE, // access mode
NULL, // object type
KernelMode, // access mode
(PVOID)ppObject, // pointer to object
NULL ); // handle information
if ( !NT_SUCCESS ( dStatus ) )
ZwClose ( *phHandle ); // close handle
}
return ( dStatus );
}
// **************************************************************************
NTSTATUS TdiCall (
IN PIRP pIrp,
IN PDEVICE_OBJECT pDeviceObject,
IN OUT PIO_STATUS_BLOCK pIoStatusBlock )
{
KEVENT kEvent; // signaling event
NTSTATUS dStatus = STATUS_INSUFFICIENT_RESOURCES; // local status
KeInitializeEvent ( &kEvent, NotificationEvent, FALSE ); // reset notification event
pIrp->UserEvent = &kEvent; // pointer to event
pIrp->UserIosb = pIoStatusBlock; // pointer to status block
dStatus = IoCallDriver ( pDeviceObject, pIrp ); // call next driver
if ( dStatus == STATUS_PENDING ) // make all request synchronous
{
(void)KeWaitForSingleObject (
(PVOID)&kEvent, // signaling object
Executive, // wait reason
KernelMode, // wait mode
TRUE, // alertable
NULL ); // timeout
}
dStatus = pIoStatusBlock->Status;
return ( dStatus ); // return with status
}
// **************************************************************************
NTSTATUS TdiClose (
IN HANDLE hHandle,
IN PFILE_OBJECT pObject )
{
if ( pObject ) // validate pointers
ObDereferenceObject( pObject ); // release the object
if ( hHandle )
ZwClose ( hHandle ); // close handle
return ( STATUS_SUCCESS );
}