#include <ntifs.h> #include <tdikrnl.h> #include <ntstatus.h>
#define COMM_TCP_DEV_NAME L"\\Device\\Tcp"
#define INETADDR(a, b, c, d) (a + (b<<8) + (c<<16) + (d<<24)) #define HTONL(a) (((a & 0xFF)<<24) + ((a & 0xFF00)<<8) + ((a & 0xFF0000)>>8) + (a&0xFF000000)>>24) #define HTONS(a) (((a & 0xFF)<<8) + ((a & 0xFF00)>>8))
NTSTATUS TdiCompletionRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext) { if (NULL != pContext) { KeSetEvent((PKEVENT)pContext, IO_NO_INCREMENT, FALSE); } return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS TdiOpen(PDEVICE_OBJECT *ppTdiAddressDevObj, PFILE_OBJECT *ppTdiEndPointFileObject, HANDLE *phTdiAddress, HANDLE *phTdiEndPoint) { NTSTATUS status = STATUS_UNSUCCESSFUL; PFILE_FULL_EA_INFORMATION pAddressEaBuffer = NULL; ULONG ulAddressEaBufferLength = 0; PTA_IP_ADDRESS pTaIpAddr = NULL; UNICODE_STRING ustrTDIDevName; OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; IO_STATUS_BLOCK iosb = { 0 }; HANDLE hTdiAddress = NULL; PFILE_OBJECT pTdiAddressFileObject = NULL; PDEVICE_OBJECT pTdiAddressDevObj = NULL; PFILE_FULL_EA_INFORMATION pContextEaBuffer = NULL; ULONG ulContextEaBufferLength = 0; HANDLE hTdiEndPoint = NULL; PFILE_OBJECT pTdiEndPointFileObject = NULL; KEVENT irpCompleteEvent = { 0 }; PIRP pIrp = NULL;
do { ulAddressEaBufferLength = sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_IP_ADDRESS); pAddressEaBuffer = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, ulAddressEaBufferLength); if (NULL == pAddressEaBuffer) { break; } RtlZeroMemory(pAddressEaBuffer, ulAddressEaBufferLength); RtlCopyMemory(pAddressEaBuffer->EaName, TdiTransportAddress, (1 + TDI_TRANSPORT_ADDRESS_LENGTH)); pAddressEaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; pAddressEaBuffer->EaValueLength = sizeof(TA_IP_ADDRESS);
pTaIpAddr = (PTA_IP_ADDRESS)((PUCHAR)pAddressEaBuffer->EaName + pAddressEaBuffer->EaNameLength + 1); pTaIpAddr->TAAddressCount = 1; pTaIpAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; pTaIpAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; pTaIpAddr->Address[0].Address[0].sin_port = 0; pTaIpAddr->Address[0].Address[0].in_addr = 0; RtlZeroMemory(pTaIpAddr->Address[0].Address[0].sin_zero, sizeof(pTaIpAddr->Address[0].Address[0].sin_zero));
RtlInitUnicodeString(&ustrTDIDevName, COMM_TCP_DEV_NAME); InitializeObjectAttributes(&ObjectAttributes, &ustrTDIDevName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwCreateFile(&hTdiAddress, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 0, pAddressEaBuffer, ulAddressEaBufferLength); if (!NT_SUCCESS(status)) { break; }
status = ObReferenceObjectByHandle(hTdiAddress, FILE_ANY_ACCESS, 0, KernelMode, &pTdiAddressFileObject, NULL); if (!NT_SUCCESS(status)) { break; }
pTdiAddressDevObj = IoGetRelatedDeviceObject(pTdiAddressFileObject); if (NULL == pTdiAddressDevObj) { break; }
ulContextEaBufferLength = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) + TDI_CONNECTION_CONTEXT_LENGTH + 1 + sizeof(CONNECTION_CONTEXT); pContextEaBuffer = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, ulContextEaBufferLength); if (NULL == pContextEaBuffer) { break; } RtlZeroMemory(pContextEaBuffer, ulContextEaBufferLength); RtlCopyMemory(pContextEaBuffer->EaName, TdiConnectionContext, (1 + TDI_CONNECTION_CONTEXT_LENGTH)); pContextEaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH; pContextEaBuffer->EaValueLength = sizeof(CONNECTION_CONTEXT);
status = ZwCreateFile(&hTdiEndPoint, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 0, pContextEaBuffer, ulContextEaBufferLength); if (!NT_SUCCESS(status)) { break; } status = ObReferenceObjectByHandle(hTdiEndPoint, FILE_ANY_ACCESS, 0, KernelMode, &pTdiEndPointFileObject, NULL); if (!NT_SUCCESS(status)) { break; }
KeInitializeEvent(&irpCompleteEvent, NotificationEvent, FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, pTdiAddressDevObj, pTdiEndPointFileObject, &irpCompleteEvent, &iosb); if (NULL == pIrp) { break; }
TdiBuildAssociateAddress(pIrp, pTdiAddressDevObj, pTdiEndPointFileObject, NULL, NULL, hTdiAddress);
IoSetCompletionRoutine(pIrp, TdiCompletionRoutine, &irpCompleteEvent, TRUE, TRUE, TRUE);
status = IoCallDriver(pTdiAddressDevObj, pIrp); if (STATUS_PENDING == status) { KeWaitForSingleObject(&irpCompleteEvent, Executive, KernelMode, FALSE, NULL); }
*ppTdiAddressDevObj = pTdiAddressDevObj; *ppTdiEndPointFileObject = pTdiEndPointFileObject; *phTdiAddress = hTdiAddress; *phTdiEndPoint = hTdiEndPoint;
} while (FALSE);
if (pTdiAddressFileObject) { ObDereferenceObject(pTdiAddressFileObject); } if (pContextEaBuffer) { ExFreePool(pContextEaBuffer); } if (pAddressEaBuffer) { ExFreePool(pAddressEaBuffer); } return status; }
NTSTATUS TdiConnection(PDEVICE_OBJECT pTdiAddressDevObj, PFILE_OBJECT pTdiEndPointFileObject, LONG *pServerIp, LONG lServerPort) { NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK iosb = { 0 }; PIRP pIrp = NULL; KEVENT connEvent = { 0 }; TA_IP_ADDRESS serverTaIpAddr = { 0 }; ULONG serverIpAddr = 0; USHORT serverPort = 0; TDI_CONNECTION_INFORMATION serverConnection = { 0 };
KeInitializeEvent(&connEvent, NotificationEvent, FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, pTdiAddressDevObj, pTdiEndPointFileObject, &connEvent, &iosb); if (NULL == pIrp) { return STATUS_INSUFFICIENT_RESOURCES; }
serverIpAddr = INETADDR(pServerIp[0], pServerIp[1], pServerIp[2], pServerIp[3]); serverPort = HTONS(lServerPort); serverTaIpAddr.TAAddressCount = 1; serverTaIpAddr.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; serverTaIpAddr.Address[0].AddressType = TDI_ADDRESS_TYPE_IP; serverTaIpAddr.Address[0].Address[0].sin_port = serverPort; serverTaIpAddr.Address[0].Address[0].in_addr = serverIpAddr; serverConnection.UserDataLength = 0; serverConnection.UserData = 0; serverConnection.OptionsLength = 0; serverConnection.Options = 0; serverConnection.RemoteAddressLength = sizeof(TA_IP_ADDRESS); serverConnection.RemoteAddress = &serverTaIpAddr;
TdiBuildConnect(pIrp, pTdiAddressDevObj, pTdiEndPointFileObject, NULL, NULL, NULL, &serverConnection, 0);
IoSetCompletionRoutine(pIrp, TdiCompletionRoutine, &connEvent, TRUE, TRUE, TRUE);
status = IoCallDriver(pTdiAddressDevObj, pIrp); if (STATUS_PENDING == status) { KeWaitForSingleObject(&connEvent, Executive, KernelMode, FALSE, NULL); } return status; }
NTSTATUS TdiSend(PDEVICE_OBJECT pTdiAddressDevObj, PFILE_OBJECT pTdiEndPointFileObject, PUCHAR pSendData, ULONG ulSendDataLength) { NTSTATUS status = STATUS_SUCCESS; KEVENT sendEvent; PIRP pIrp = NULL; IO_STATUS_BLOCK iosb = { 0 }; PMDL pSendMdl = NULL;
KeInitializeEvent(&sendEvent, NotificationEvent, FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_SEND, pTdiAddressDevObj, pTdiEndPointFileObject, &sendEvent, &iosb); if (NULL == pIrp) { return STATUS_INSUFFICIENT_RESOURCES; }
pSendMdl = IoAllocateMdl(pSendData, ulSendDataLength, FALSE, FALSE, pIrp); if (NULL == pSendMdl) { return STATUS_INSUFFICIENT_RESOURCES; } MmProbeAndLockPages(pSendMdl, KernelMode, IoModifyAccess);
TdiBuildSend(pIrp, pTdiAddressDevObj, pTdiEndPointFileObject, NULL, NULL, pSendMdl, 0, ulSendDataLength);
IoSetCompletionRoutine(pIrp, TdiCompletionRoutine, &sendEvent, TRUE, TRUE, TRUE);
status = IoCallDriver(pTdiAddressDevObj, pIrp); if (STATUS_PENDING == status) { KeWaitForSingleObject(&sendEvent, Executive, KernelMode, FALSE, NULL); }
if (pSendMdl) { IoFreeMdl(pSendMdl); } return status; }
ULONG_PTR TdiRecv(PDEVICE_OBJECT pTdiAddressDevObj, PFILE_OBJECT pTdiEndPointFileObject, PUCHAR pRecvData, ULONG ulRecvDataLength) { NTSTATUS status = STATUS_SUCCESS; KEVENT recvEvent; PIRP pIrp = NULL; IO_STATUS_BLOCK iosb = { 0 }; PMDL pRecvMdl = NULL; ULONG_PTR ulRecvSize = 0;
KeInitializeEvent(&recvEvent, NotificationEvent, FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_RECV, pTdiAddressDevObj, pTdiEndPointFileObject, &recvEvent, &iosb); if (NULL == pIrp) { return STATUS_INSUFFICIENT_RESOURCES; }
pRecvMdl = IoAllocateMdl(pRecvData, ulRecvDataLength, FALSE, FALSE, pIrp); if (NULL == pRecvMdl) { return STATUS_INSUFFICIENT_RESOURCES; } MmProbeAndLockPages(pRecvMdl, KernelMode, IoModifyAccess);
TdiBuildReceive(pIrp, pTdiAddressDevObj, pTdiEndPointFileObject, NULL, NULL, pRecvMdl, TDI_RECEIVE_NORMAL, ulRecvDataLength);
IoSetCompletionRoutine(pIrp, TdiCompletionRoutine, &recvEvent, TRUE, TRUE, TRUE);
status = IoCallDriver(pTdiAddressDevObj, pIrp); if (STATUS_PENDING == status) { KeWaitForSingleObject(&recvEvent, Executive, KernelMode, FALSE, NULL); }
ulRecvSize = pIrp->IoStatus.Information;
if (pRecvMdl) { IoFreeMdl(pRecvMdl); } return status; }
VOID TdiClose(PFILE_OBJECT pTdiEndPointFileObject, HANDLE hTdiAddress, HANDLE hTdiEndPoint) { if (pTdiEndPointFileObject) { ObDereferenceObject(pTdiEndPointFileObject); } if (hTdiEndPoint) { ZwClose(hTdiEndPoint); } if (hTdiAddress) { ZwClose(hTdiAddress); } }
|