//
//
// NewbieCoder[0GiNr]
//
// 15:36 2009-1-13
//
// http://0ginr.com
//
//
#include <ntifs.h>
#include <tdikrnl.h>
#define XHR_IS_BIG_COW_TAG 'XHR_'
#define TCP_DEVICE_NAME_W L"//Device//TCP"
NTSTATUS
OpenTransportAddress(
OUT HANDLE *TransportHandle,
OUT PFILE_OBJECT *TransportObject
);
NTSTATUS
OpenConnection(
OUT HANDLE *ConnectionHandle,
OUT PFILE_OBJECT *ConnectionObject,
IN PVOID Context
);
NTSTATUS
AssociateTransportAndConnection(
IN HANDLE TransportHandle,
IN PFILE_OBJECT ConnectionObject
);
NTSTATUS
DisassociateTransportAndConnection(
IN PFILE_OBJECT ConnectionObject
);
NTSTATUS
SetEventHandler(
IN PFILE_OBJECT ConnectionObject,
IN LONG EventType,
IN PVOID EventHandler,
IN PVOID EventContext
);
NTSTATUS
Connect(
IN ULONG Address,
IN USHORT PortNumber,
IN PFILE_OBJECT ConnectionObject
);
NTSTATUS
Disconnect(
IN PFILE_OBJECT ConnectionObject
);
NTSTATUS
Listen(
OUT USHORT PortNumber,
IN PFILE_OBJECT ConnectionObject
);
NTSTATUS
Receive(
IN PFILE_OBJECT ConnectionObject,
IN PVOID ReceiveBuffer,
IN ULONG LengthToReceive,
OUT ULONG *ReceivedLength
);
NTSTATUS
Send(
IN PFILE_OBJECT ConnectionObject,
IN PVOID SendBuffer,
IN ULONG LengthToSend,
OUT ULONG *SentLength
);
//
PFILE_FULL_EA_INFORMATION
BuildEaInformation(
IN PVOID EaName,
IN UCHAR NameLength,
IN PVOID EaValue,
IN USHORT ValueLength,
OUT USHORT * EaLength
)
{
PFILE_FULL_EA_INFORMATION FileFullEaInfo;
*EaLength = (USHORT)(FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + NameLength + 1 + ValueLength);
FileFullEaInfo=(PFILE_FULL_EA_INFORMATION)ExAllocatePoolWithTag(
NonPagedPool,
*EaLength,
XHR_IS_BIG_COW_TAG
);
if (!FileFullEaInfo)
{
return NULL;
}
RtlZeroMemory(FileFullEaInfo,*EaLength);
FileFullEaInfo->NextEntryOffset=0;
RtlCopyMemory(FileFullEaInfo->EaName,EaName,NameLength+1);
FileFullEaInfo->EaNameLength=NameLength;
FileFullEaInfo->EaValueLength=ValueLength;
if (EaValue && ValueLength)
{
RtlCopyMemory(&FileFullEaInfo->EaName[NameLength+1],EaValue,ValueLength);
}
return FileFullEaInfo;
}
NTSTATUS
OpenTransportAddress(
OUT HANDLE *TransportHandle,
OUT PFILE_OBJECT *TransportObject
)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
PFILE_FULL_EA_INFORMATION FileFullEaInfo=NULL;
USHORT EaLength;
UNICODE_STRING TcpDeviceName;
HANDLE TcpDeviceFileHandle;
PFILE_OBJECT TcpDeviceFileObject;
TA_IP_ADDRESS AddressIP;
RtlInitUnicodeString(
&TcpDeviceName,
TCP_DEVICE_NAME_W
);
InitializeObjectAttributes(
&ObjectAttributes,
&TcpDeviceName,
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
(HANDLE)0,
NULL
);
AddressIP.TAAddressCount=1;
AddressIP.Address[0].AddressType=TDI_ADDRESS_TYPE_IP;
AddressIP.Address[0].AddressLength=TDI_ADDRESS_LENGTH_IP;
AddressIP.Address[0].Address[0].in_addr=0;
AddressIP.Address[0].Address[0].sin_port=0;
FileFullEaInfo=BuildEaInformation(
TdiTransportAddress,
TDI_TRANSPORT_ADDRESS_LENGTH,
&AddressIP,
sizeof(TA_IP_ADDRESS),
&EaLength
);
if (!FileFullEaInfo)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status=ZwCreateFile(
&TcpDeviceFileHandle,
FILE_READ_DATA|FILE_READ_EA|FILE_WRITE_EA,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
0,
FileFullEaInfo,
EaLength
);
ExFreePoolWithTag(
FileFullEaInfo,
XHR_IS_BIG_COW_TAG
);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status=ObReferenceObjectByHandle(
TcpDeviceFileHandle,
GENERIC_READ|GENERIC_WRITE,
NULL,
KernelMode,
(PVOID *)&TcpDeviceFileObject,
NULL
);
if (!NT_SUCCESS(Status))
{
ZwClose(TcpDeviceFileHandle);
return Status;
}
*TransportHandle=TcpDeviceFileHandle;
*TransportObject=TcpDeviceFileObject;
return STATUS_SUCCESS;
}
NTSTATUS
OpenConnection(
OUT HANDLE *ConnectionHandle,
OUT PFILE_OBJECT *ConnectionObject,
IN PVOID Context
)
{
NTSTATUS Status;
UNICODE_STRING TcpDeviceName;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
PFILE_FULL_EA_INFORMATION FileFullEaInfo;
USHORT EaLength;
HANDLE TcpDeviceFileHandle;
PFILE_OBJECT TcpDeviceFileObject;
RtlInitUnicodeString(
&TcpDeviceName,
TCP_DEVICE_NAME_W
);
InitializeObjectAttributes(
&ObjectAttributes,
&TcpDeviceName,
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
(HANDLE)0,
NULL
);
EaLength=TDI_CONNECTION_CONTEXT_LENGTH+sizeof(FILE_FULL_EA_INFORMATION);
FileFullEaInfo=BuildEaInformation(
TdiConnectionContext,
TDI_CONNECTION_CONTEXT_LENGTH,
&Context,
sizeof(PVOID),
&EaLength
);
if (!FileFullEaInfo)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status=ZwCreateFile(
&TcpDeviceFileHandle,
FILE_READ_DATA|FILE_READ_EA|FILE_WRITE_EA,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
0,
FileFullEaInfo,
EaLength
);
ExFreePoolWithTag(
FileFullEaInfo,
XHR_IS_BIG_COW_TAG
);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status=ObReferenceObjectByHandle(
TcpDeviceFileHandle,
GENERIC_READ|GENERIC_WRITE,
NULL,
KernelMode,
(PVOID *)&TcpDeviceFileObject,
NULL
);
if (!NT_SUCCESS(Status))
{
ZwClose(TcpDeviceFileHandle);
return Status;
}
*ConnectionHandle=TcpDeviceFileHandle;
*ConnectionObject=TcpDeviceFileObject;
return STATUS_SUCCESS;
}
NTSTATUS
NetworkCompleteRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PMDL CurrentMdl;
PMDL NextMdl;
if (CurrentMdl=Irp->MdlAddress)
{
while (CurrentMdl)
{
NextMdl=CurrentMdl->Next;
MmUnlockPages(CurrentMdl);
IoFreeMdl(CurrentMdl);
CurrentMdl=NextMdl;
}
}
IoFreeIrp(Irp);
KeSetEvent((PKEVENT)Context,IO_NO_INCREMENT,FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
AssociateTransportAndConnection(
IN HANDLE TransportHandle,
IN PFILE_OBJECT ConnectionObject
)
{
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT TcpDeviceObject;
KEVENT CompleteEvent;
KeInitializeEvent(
&CompleteEvent,
NotificationEvent,
FALSE
);
TcpDeviceObject=IoGetRelatedDeviceObject(ConnectionObject);
Irp=TdiBuildInternalDeviceControlIrp(
TDI_ASSOCIATION_ADDRESS,
TcpDeviceObject,
ConnectionObject,
&CompleteEvent,
&IoStatusBlock
);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildAssociateAddress(
Irp,
TcpDeviceObject,
ConnectionObject,
NetworkCompleteRoutine,
&CompleteEvent,
TransportHandle
);
Status=IoCallDriver(
TcpDeviceObject,
Irp
);
if (Status==STATUS_PENDING)
{
KeWaitForSingleObject(
&CompleteEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Status=IoStatusBlock.Status;
if (!NT_SUCCESS(Status))
{
}
}
return Status;
}
NTSTATUS
DisassociateTransportAndConnection(
IN PFILE_OBJECT ConnectionObject
)
{
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT TcpDeviceObject;
KEVENT CompleteEvent;
KeInitializeEvent(
&CompleteEvent,
NotificationEvent,
FALSE
);
TcpDeviceObject=IoGetRelatedDeviceObject(ConnectionObject);
Irp=TdiBuildInternalDeviceControlIrp(
TDI_DISASSOCIATE_ADDRESS,
TcpDeviceObject,
ConnectionObject,
&CompleteEvent,
&IoStatusBlock
);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildDisassociateAddress(
Irp,
TcpDeviceObject,
ConnectionObject,
NetworkCompleteRoutine,
&CompleteEvent
);
Status=IoCallDriver(
TcpDeviceObject,
Irp
);
if (Status==STATUS_PENDING)
{
KeWaitForSingleObject(
&CompleteEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Status=IoStatusBlock.Status;
if (!NT_SUCCESS(Status))
{
}
}
return Status;
}
NTSTATUS
SetEventHandler(
IN PFILE_OBJECT ConnectionObject,
IN LONG EventType,
IN PVOID EventHandler,
IN PVOID EventContext
)
{
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT TcpDeviceObject;
KEVENT CompleteEvent;
KeInitializeEvent(
&CompleteEvent,
NotificationEvent,
FALSE
);
TcpDeviceObject=IoGetRelatedDeviceObject(ConnectionObject);
Irp=TdiBuildInternalDeviceControlIrp(
TDI_SET_EVENT_HANDLER,
TcpDeviceObject,
ConnectionObject,
&CompleteEvent,
&IoStatusBlock
);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildSetEventHandler(
Irp,
TcpDeviceObject,
ConnectionObject,
NetworkCompleteRoutine,
&CompleteEvent,
EventType,
EventHandler,
EventContext
);
Status=IoCallDriver(
TcpDeviceObject,
Irp
);
if (Status==STATUS_PENDING)
{
KeWaitForSingleObject(
&CompleteEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Status=IoStatusBlock.Status;
if (!NT_SUCCESS(Status))
{
}
}
return Status;
}
NTSTATUS
Connect(
IN ULONG Address,
IN USHORT PortNumber,
IN PFILE_OBJECT ConnectionObject
)
{
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT TcpDeviceObject;
KEVENT CompleteEvent;
TDI_CONNECTION_INFORMATION RequestConnect;
TA_IP_ADDRESS IpAddress;
KeInitializeEvent(
&CompleteEvent,
NotificationEvent,
FALSE
);
TcpDeviceObject=IoGetRelatedDeviceObject(ConnectionObject);
Irp=TdiBuildInternalDeviceControlIrp(
TDI_CONNECT,
TcpDeviceObject,
ConnectionObject,
&CompleteEvent,
&IoStatusBlock
);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(&RequestConnect,sizeof(TDI_CONNECTION_INFORMATION));
RtlZeroMemory(&IpAddress,sizeof(TA_IP_ADDRESS));
IpAddress.TAAddressCount=1;
IpAddress.Address[0].AddressType=TDI_ADDRESS_TYPE_IP;
IpAddress.Address[0].AddressLength=TDI_ADDRESS_LENGTH_IP;
IpAddress.Address[0].Address[0].in_addr=Address;
IpAddress.Address[0].Address[0].sin_port=PortNumber;
RequestConnect.RemoteAddressLength=sizeof(TA_IP_ADDRESS);
RequestConnect.RemoteAddress=(PVOID)&IpAddress;
TdiBuildConnect(
Irp,
TcpDeviceObject,
ConnectionObject,
NetworkCompleteRoutine,
&CompleteEvent,
NULL,
&RequestConnect,
&RequestConnect
);
Status=IoCallDriver(
TcpDeviceObject,
Irp
);
if (Status==STATUS_PENDING)
{
KeWaitForSingleObject(
&CompleteEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Status=IoStatusBlock.Status;
if (!NT_SUCCESS(Status))
{
}
}
return Status;
}
NTSTATUS
Disconnect(
IN PFILE_OBJECT ConnectionObject
)
{
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT TcpDeviceObject;
KEVENT CompleteEvent;
TDI_CONNECTION_INFORMATION RequestDisconnect;
KeInitializeEvent(
&CompleteEvent,
NotificationEvent,
FALSE
);
TcpDeviceObject=IoGetRelatedDeviceObject(ConnectionObject);
Irp=TdiBuildInternalDeviceControlIrp(
TDI_DISCONNECT,
TcpDeviceObject,
ConnectionObject,
&CompleteEvent,
&IoStatusBlock
);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(&RequestDisconnect,sizeof(TDI_CONNECTION_INFORMATION));
TdiBuildDisconnect(
Irp,
TcpDeviceObject,
ConnectionObject,
NetworkCompleteRoutine,
&CompleteEvent,
NULL,
TDI_DISCONNECT_ABORT,
&RequestDisconnect,
&RequestDisconnect
);
Status=IoCallDriver(
TcpDeviceObject,
Irp
);
if (Status==STATUS_PENDING)
{
KeWaitForSingleObject(
&CompleteEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Status=IoStatusBlock.Status;
if (!NT_SUCCESS(Status))
{
}
}
return Status;
}
NTSTATUS
Listen(
OUT USHORT PortNumber,
IN PFILE_OBJECT ConnectionObject
)
{
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT TcpDeviceObject;
KEVENT CompleteEvent;
TDI_CONNECTION_INFORMATION RequestListen;
TA_IP_ADDRESS IpAddress;
KeInitializeEvent(
&CompleteEvent,
NotificationEvent,
FALSE
);
TcpDeviceObject=IoGetRelatedDeviceObject(ConnectionObject);
Irp=TdiBuildInternalDeviceControlIrp(
TDI_LISTEN,
TcpDeviceObject,
ConnectionObject,
&CompleteEvent,
&IoStatusBlock
);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(&RequestListen,sizeof(TDI_CONNECTION_INFORMATION));
RtlZeroMemory(&IpAddress,sizeof(TA_IP_ADDRESS));
IpAddress.TAAddressCount=1;
IpAddress.Address[0].AddressType=TDI_ADDRESS_TYPE_IP;
IpAddress.Address[0].AddressLength=TDI_ADDRESS_LENGTH_IP;
IpAddress.Address[0].Address[0].in_addr=0;
IpAddress.Address[0].Address[0].sin_port=PortNumber;
RequestListen.RemoteAddressLength=sizeof(TA_IP_ADDRESS);
RequestListen.RemoteAddress=(PVOID)&IpAddress;
TdiBuildListen(
Irp,
TcpDeviceObject,
ConnectionObject,
NetworkCompleteRoutine,
&CompleteEvent,
0,
&RequestListen,
&RequestListen
);
Status=IoCallDriver(
TcpDeviceObject,
Irp
);
if (Status==STATUS_PENDING)
{
KeWaitForSingleObject(
&CompleteEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Status=IoStatusBlock.Status;
if (!NT_SUCCESS(Status))
{
}
}
return Status;
}
NTSTATUS
Receive(
IN PFILE_OBJECT ConnectionObject,
IN PVOID ReceiveBuffer,
IN ULONG LengthToReceive,
OUT ULONG *ReceivedLength
)
{
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT TcpDeviceObject;
KEVENT CompleteEvent;
PMDL ReceiveMdl;
*ReceivedLength=0;
KeInitializeEvent(
&CompleteEvent,
NotificationEvent,
FALSE
);
ReceiveMdl=IoAllocateMdl(
ReceiveBuffer,
LengthToReceive,
FALSE,
FALSE,
NULL
);
if (ReceiveMdl)
{
__try
{
MmProbeAndLockPages(
ReceiveMdl,
KernelMode,
IoWriteAccess); // freed in NetworkCompleteRoutine
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(ReceiveMdl);
return GetExceptionCode();
}
}
TcpDeviceObject=IoGetRelatedDeviceObject(ConnectionObject);
Irp=TdiBuildInternalDeviceControlIrp(
TDI_RECEIVE,
TcpDeviceObject,
ConnectionObject,
&CompleteEvent,
&IoStatusBlock
);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildReceive(
Irp,
TcpDeviceObject,
ConnectionObject,
NetworkCompleteRoutine,
&CompleteEvent,
ReceiveMdl,
TDI_RECEIVE_NORMAL,
LengthToReceive
);
Status=IoCallDriver(
TcpDeviceObject,
Irp
);
if (Status==STATUS_PENDING)
{
KeWaitForSingleObject(
&CompleteEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Status=IoStatusBlock.Status;
*ReceivedLength=IoStatusBlock.Information;
if (!NT_SUCCESS(Status))
{
}
}
return Status;
}
NTSTATUS
Send(
IN PFILE_OBJECT ConnectionObject,
IN PVOID SendBuffer,
IN ULONG LengthToSend,
OUT ULONG *SentLength
)
{
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT TcpDeviceObject;
KEVENT CompleteEvent;
PMDL SendMdl;
*SentLength=0;
KeInitializeEvent(
&CompleteEvent,
NotificationEvent,
FALSE
);
SendMdl=IoAllocateMdl(
SendBuffer,
LengthToSend,
FALSE,
FALSE,
NULL
);
if (SendMdl)
{
__try
{
MmProbeAndLockPages(
SendMdl,
KernelMode,
IoReadAccess); // freed in NetworkCompleteRoutine
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(SendMdl);
return GetExceptionCode();
}
}
TcpDeviceObject=IoGetRelatedDeviceObject(ConnectionObject);
Irp=TdiBuildInternalDeviceControlIrp(
TDI_SEND,
TcpDeviceObject,
ConnectionObject,
&CompleteEvent,
&IoStatusBlock
);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildSend(
Irp,
TcpDeviceObject,
ConnectionObject,
NetworkCompleteRoutine,
&CompleteEvent,
SendMdl,
0,
LengthToSend
);
Status=IoCallDriver(
TcpDeviceObject,
Irp
);
if (Status==STATUS_PENDING)
{
KeWaitForSingleObject(
&CompleteEvent,
Executive,
KernelMode,
FALSE,
NULL
);
Status=IoStatusBlock.Status;
*SentLength=IoStatusBlock.Information;
if (!NT_SUCCESS(Status))
{
}
}
return Status;
}