mirror of
https://github.com/BeneficialCode/WinArk.git
synced 2026-10-17 04:40:35 +08:00
621 lines
16 KiB
C++
621 lines
16 KiB
C++
#include "pch.h"
|
|
#include <tdikrnl.h>
|
|
|
|
#define KTDI_TAG 'NACS'
|
|
|
|
NTSTATUS tdi_open_transport_address(PUNICODE_STRING devName, ULONG addr, USHORT port,
|
|
BOOLEAN shared, PHANDLE addressHandle, PFILE_OBJECT* addressFileObject) {
|
|
OBJECT_ATTRIBUTES attr;
|
|
PFILE_FULL_EA_INFORMATION eaBuffer;
|
|
ULONG eaSize;
|
|
PTA_IP_ADDRESS localAddr;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, nullptr, nullptr);
|
|
|
|
eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[1]) +
|
|
TDI_TRANSPORT_ADDRESS_LENGTH + 1 + sizeof(TA_IP_ADDRESS);
|
|
|
|
eaBuffer = (PFILE_FULL_EA_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, eaSize, KTDI_TAG);
|
|
if (eaBuffer == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
eaBuffer->NextEntryOffset = 0;
|
|
eaBuffer->Flags = 0;
|
|
eaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
|
|
eaBuffer->EaValueLength = sizeof(TA_IP_ADDRESS);
|
|
|
|
RtlCopyMemory(eaBuffer->EaName, TdiTransportAddress, eaBuffer->EaNameLength + 1);
|
|
|
|
localAddr = (PTA_IP_ADDRESS)(eaBuffer->EaName + eaBuffer->EaNameLength + 1);
|
|
|
|
localAddr->TAAddressCount = 1;
|
|
localAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
|
|
localAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
|
localAddr->Address[0].Address[0].sin_port = port;
|
|
localAddr->Address[0].Address[0].in_addr = addr;
|
|
|
|
RtlZeroMemory(localAddr->Address[0].Address[0].sin_zero,
|
|
sizeof(localAddr->Address[0].Address[0].sin_zero));
|
|
|
|
status = ZwCreateFile(addressHandle,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
&attr,
|
|
&iosb,
|
|
nullptr,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
shared ? FILE_SHARE_READ | FILE_SHARE_WRITE : 0,
|
|
FILE_OPEN,
|
|
0,
|
|
eaBuffer,
|
|
eaSize);
|
|
|
|
ExFreePool(eaBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
status = ObReferenceObjectByHandle(*addressHandle, FILE_ALL_ACCESS, nullptr,
|
|
KernelMode, (PVOID*)addressFileObject, nullptr);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
ZwClose(*addressHandle);
|
|
return status;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS tdi_set_event_handler(PFILE_OBJECT addressFileObject, LONG eventType, PVOID eventHandler,
|
|
PVOID eventContext) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PIRP irp;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(addressFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, devObj, addressFileObject, &event, &iosb);
|
|
if (irp == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
TdiBuildSetEventHandler(irp, devObj, addressFileObject, nullptr, nullptr, eventType, eventHandler,
|
|
eventContext);
|
|
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS tdi_disconnect(PFILE_OBJECT connectionFileObject, ULONG flags) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PIRP irp;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(connectionFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, devObj, connectionFileObject, &event, &iosb);
|
|
|
|
if (irp == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
TdiBuildDisconnect(irp, devObj, connectionFileObject, nullptr, nullptr, nullptr,
|
|
flags, nullptr, nullptr);
|
|
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS tdi_unset_event_handler(PFILE_OBJECT addressFileObject, LONG eventType) {
|
|
return tdi_set_event_handler(addressFileObject, eventType, nullptr, nullptr);
|
|
}
|
|
|
|
NTSTATUS tdi_disassociate_address(PFILE_OBJECT connectionFileObject) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PIRP irp;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(connectionFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_DISASSOCIATE_ADDRESS, devObj, connectionFileObject, &event, &iosb);
|
|
if (irp == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
TdiBuildDisassociateAddress(irp, devObj, connectionFileObject, nullptr, nullptr);
|
|
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS tdi_open_connection_endpoint(PUNICODE_STRING devName, PVOID connectionContext, BOOLEAN shared,
|
|
PHANDLE connectionHandle, PFILE_OBJECT* connectionFileObject) {
|
|
OBJECT_ATTRIBUTES attr;
|
|
PFILE_FULL_EA_INFORMATION eaBuffer;
|
|
ULONG eaSize;
|
|
PVOID* context;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, nullptr, nullptr);
|
|
|
|
eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[1]) + TDI_CONNECTION_CONTEXT_LENGTH + 1 + sizeof(void*);
|
|
|
|
eaBuffer = (PFILE_FULL_EA_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, eaSize, KTDI_TAG);
|
|
|
|
if (eaBuffer == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
eaBuffer->NextEntryOffset = 0;
|
|
eaBuffer->Flags = 0;
|
|
eaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
|
|
eaBuffer->EaValueLength = sizeof(void*);
|
|
|
|
RtlCopyMemory(eaBuffer->EaName, TdiConnectionContext, eaBuffer->EaNameLength + 1);
|
|
|
|
context = (PVOID*)&(eaBuffer->EaName[eaBuffer->EaNameLength + 1]);
|
|
|
|
*context = connectionContext;
|
|
|
|
status = ZwCreateFile(
|
|
connectionHandle,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
&attr,
|
|
&iosb,
|
|
nullptr,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
shared ? FILE_SHARE_READ | FILE_SHARE_WRITE : 0,
|
|
FILE_OPEN,
|
|
0,
|
|
eaBuffer,
|
|
eaSize
|
|
);
|
|
|
|
ExFreePool(eaBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
status = ObReferenceObjectByHandle(*connectionHandle, FILE_ALL_ACCESS, nullptr,
|
|
KernelMode, (PVOID*)connectionFileObject, nullptr);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
ZwClose(*connectionHandle);
|
|
return status;
|
|
}
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS tdi_associate_address(PFILE_OBJECT connectionFileObject, HANDLE addressHandle) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PIRP irp;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(connectionFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, devObj, connectionFileObject, &event, &iosb);
|
|
|
|
if (irp == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
TdiBuildAssociateAddress(irp, devObj, connectionFileObject, nullptr, nullptr, addressHandle);
|
|
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS tdi_connect(PFILE_OBJECT connectionFileObject, ULONG addr, USHORT port) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PTDI_CONNECTION_INFORMATION remoteInfo;
|
|
PTA_IP_ADDRESS remoteAddr;
|
|
PTDI_CONNECTION_INFORMATION returnInfo;
|
|
PTA_IP_ADDRESS returnAddr;
|
|
PIRP irp;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(connectionFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
SIZE_T bytes = 2 * sizeof(TDI_CONNECTION_INFORMATION) + 2 * sizeof(TA_IP_ADDRESS);
|
|
remoteInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, bytes, KTDI_TAG);
|
|
|
|
if (remoteInfo == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(remoteInfo, bytes);
|
|
|
|
remoteInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);
|
|
remoteInfo->RemoteAddress = (PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION);
|
|
|
|
remoteAddr = (PTA_IP_ADDRESS)remoteInfo->RemoteAddress;
|
|
|
|
remoteAddr->TAAddressCount = 1;
|
|
remoteAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
|
|
remoteAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
|
remoteAddr->Address[0].Address[0].sin_port = port;
|
|
remoteAddr->Address[0].Address[0].in_addr = addr;
|
|
|
|
returnInfo = (PTDI_CONNECTION_INFORMATION)((PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));
|
|
|
|
returnInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);
|
|
returnInfo->RemoteAddress = (PUCHAR)returnInfo + sizeof(TDI_CONNECTION_INFORMATION);
|
|
|
|
returnAddr = (PTA_IP_ADDRESS)returnInfo->RemoteAddress;
|
|
|
|
returnAddr->TAAddressCount = 1;
|
|
returnAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
|
|
returnAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, devObj, connectionFileObject, &event, &iosb);
|
|
if (irp == nullptr) {
|
|
ExFreePool(remoteInfo);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
ExFreePool(remoteInfo);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS tdi_query_address(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PTRANSPORT_ADDRESS localInfo;
|
|
PTA_IP_ADDRESS localAddr;
|
|
PIRP irp;
|
|
PMDL mdl;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(addressFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
ULONG length = sizeof(TDI_ADDRESS_INFO) * 10;
|
|
localInfo = (PTRANSPORT_ADDRESS)ExAllocatePoolWithTag(NonPagedPool, length, KTDI_TAG);
|
|
if (localInfo == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(localInfo, length);
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, devObj, addressFileObject, &event, &iosb);
|
|
|
|
if (irp == nullptr) {
|
|
ExFreePool(localInfo);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
mdl = IoAllocateMdl(localInfo, length, FALSE, FALSE, nullptr);
|
|
if (mdl == nullptr) {
|
|
IoFreeIrp(irp);
|
|
ExFreePool(localInfo);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
__try {
|
|
MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER){
|
|
IoFreeMdl(mdl);
|
|
IoFreeIrp(irp);
|
|
ExFreePool(localInfo);
|
|
status = STATUS_INVALID_USER_BUFFER;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
TdiBuildQueryInformation(irp, devObj, addressFileObject, nullptr, nullptr, TDI_QUERY_ADDRESS_INFO, mdl);
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
localAddr = (PTA_IP_ADDRESS)&localInfo->Address[0];
|
|
if (addr) {
|
|
*addr = localAddr->Address[0].Address[0].in_addr;
|
|
}
|
|
|
|
if (port) {
|
|
*port = localAddr->Address[0].Address[0].sin_port;
|
|
}
|
|
|
|
ExFreePool(localInfo);
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS tdi_recv_dgram(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port, char* buf, int len, ULONG flags) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PTDI_CONNECTION_INFORMATION remoteInfo;
|
|
PTDI_CONNECTION_INFORMATION returnInfo;
|
|
PTA_IP_ADDRESS returnAddr;
|
|
PIRP irp;
|
|
PMDL mdl = nullptr;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(addressFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
SIZE_T size = 2 * sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS);
|
|
remoteInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, size, KTDI_TAG);
|
|
|
|
if (remoteInfo == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(remoteInfo, size);
|
|
|
|
remoteInfo->RemoteAddressLength = 0;
|
|
remoteInfo->RemoteAddress = nullptr;
|
|
|
|
returnInfo = (PTDI_CONNECTION_INFORMATION)((PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION));
|
|
|
|
returnInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);
|
|
returnInfo->RemoteAddress = (PUCHAR)returnInfo + sizeof(TDI_CONNECTION_INFORMATION);
|
|
|
|
returnAddr = (PTA_IP_ADDRESS)returnInfo->RemoteAddress;
|
|
|
|
returnAddr->TAAddressCount = 1;
|
|
returnAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
|
|
returnAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, devObj, addressFileObject, &event, &iosb);
|
|
|
|
if (irp == nullptr) {
|
|
ExFreePool(remoteInfo);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if (len) {
|
|
mdl = IoAllocateMdl(buf, len, FALSE, FALSE, nullptr);
|
|
if (mdl == nullptr) {
|
|
IoFreeIrp(irp);
|
|
ExFreePool(remoteInfo);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
__try {
|
|
MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
IoFreeMdl(mdl);
|
|
IoFreeIrp(irp);
|
|
ExFreePool(remoteInfo);
|
|
status = STATUS_INVALID_USER_BUFFER;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
TdiBuildReceiveDatagram(irp, devObj, addressFileObject, nullptr, nullptr,
|
|
len ? mdl : 0,
|
|
len,
|
|
remoteInfo,
|
|
returnInfo,
|
|
flags);
|
|
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
if (addr) {
|
|
*addr = returnAddr->Address[0].Address[0].in_addr;
|
|
}
|
|
if (port) {
|
|
*port = returnAddr->Address[0].Address[0].sin_port;
|
|
}
|
|
|
|
ExFreePool(remoteInfo);
|
|
|
|
return NT_SUCCESS(status) ? (int)iosb.Information : status;
|
|
}
|
|
|
|
NTSTATUS tdi_send_dgram(PFILE_OBJECT addressFileObject, ULONG addr, USHORT port, const char* buf, int len) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PTDI_CONNECTION_INFORMATION remoteInfo;
|
|
PTA_IP_ADDRESS remoteAddr;
|
|
PIRP irp;
|
|
PMDL mdl = nullptr;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(addressFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
SIZE_T size = sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS);
|
|
remoteInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, size, KTDI_TAG);
|
|
if (remoteInfo == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(remoteInfo, size);
|
|
|
|
remoteInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);
|
|
remoteInfo->RemoteAddress = (PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION);
|
|
|
|
remoteAddr = (PTA_IP_ADDRESS)remoteInfo->RemoteAddress;
|
|
|
|
remoteAddr->TAAddressCount = 1;
|
|
remoteAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
|
|
remoteAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
|
remoteAddr->Address[0].Address[0].sin_port = port;
|
|
remoteAddr->Address[0].Address[0].in_addr = addr;
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, devObj, addressFileObject, &event, &iosb);
|
|
|
|
if (irp == nullptr)
|
|
{
|
|
ExFreePool(remoteInfo);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if (len)
|
|
{
|
|
mdl = IoAllocateMdl((void*)buf, len, FALSE, FALSE, nullptr);
|
|
|
|
if (mdl == nullptr)
|
|
{
|
|
IoFreeIrp(irp);
|
|
ExFreePool(remoteInfo);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
__try
|
|
{
|
|
MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
IoFreeMdl(mdl);
|
|
IoFreeIrp(irp);
|
|
ExFreePool(remoteInfo);
|
|
status = STATUS_INVALID_USER_BUFFER;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
return status;
|
|
}
|
|
}
|
|
|
|
TdiBuildSendDatagram(irp, devObj, addressFileObject, nullptr, nullptr, len ? mdl : 0, len, remoteInfo);
|
|
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
ExFreePool(remoteInfo);
|
|
|
|
return NT_SUCCESS(status) ? (int)iosb.Information : status;
|
|
}
|
|
|
|
NTSTATUS tdi_recv_stream(PFILE_OBJECT connectionFileObject, char* buf, int len, ULONG flags) {
|
|
PDEVICE_OBJECT devObj;
|
|
KEVENT event;
|
|
PIRP irp;
|
|
PMDL mdl = nullptr;
|
|
IO_STATUS_BLOCK iosb;
|
|
NTSTATUS status;
|
|
|
|
devObj = IoGetRelatedDeviceObject(connectionFileObject);
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE, devObj, connectionFileObject, &event, &iosb);
|
|
|
|
if (irp == nullptr) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if (len) {
|
|
mdl = IoAllocateMdl(buf, len, FALSE, FALSE, nullptr);
|
|
if (mdl == nullptr) {
|
|
IoFreeIrp(irp);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
__try {
|
|
MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
IoFreeMdl(mdl);
|
|
IoFreeIrp(irp);
|
|
status = STATUS_INVALID_USER_BUFFER;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
TdiBuildReceive(irp, devObj, connectionFileObject, nullptr, nullptr, len ? mdl : 0, flags, len);
|
|
|
|
status = IoCallDriver(devObj, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, nullptr);
|
|
status = iosb.Status;
|
|
}
|
|
|
|
return NT_SUCCESS(status) ? (int)iosb.Information : status;
|
|
} |