TDI code 1

2009-01-13 15:36


//
//
// 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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值