📄 ktdi.c
字号:
/*
HTTP Virtual Disk.
Copyright (C) 2006 Bo Brant閚.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <ntddk.h>
#include <tdikrnl.h>
#include "ktdi.h"
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;
#if (VER_PRODUCTBUILD >= 2195)
InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
#else
InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE, NULL, NULL);
#endif
eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +
TDI_TRANSPORT_ADDRESS_LENGTH +
1 +
sizeof(TA_IP_ADDRESS);
eaBuffer = (PFILE_FULL_EA_INFORMATION) ExAllocatePool(PagedPool, eaSize);
if (eaBuffer == NULL)
{
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,
NULL,
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, NULL, KernelMode, addressFileObject, NULL);
if (!NT_SUCCESS(status))
{
ZwClose(*addressHandle);
return status;
}
return STATUS_SUCCESS;
}
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;
#if (VER_PRODUCTBUILD >= 2195)
InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
#else
InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE, NULL, NULL);
#endif
eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +
TDI_CONNECTION_CONTEXT_LENGTH +
1 +
sizeof(int);
eaBuffer = (PFILE_FULL_EA_INFORMATION) ExAllocatePool(PagedPool, eaSize);
if (eaBuffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
eaBuffer->NextEntryOffset = 0;
eaBuffer->Flags = 0;
eaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
eaBuffer->EaValueLength = sizeof(int);
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,
NULL,
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, NULL, KernelMode, connectionFileObject, NULL);
if (!NT_SUCCESS(status))
{
ZwClose(*connectionHandle);
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 == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildSetEventHandler(irp, devObj, addressFileObject, NULL, NULL, eventType, eventHandler, eventContext);
status = IoCallDriver(devObj, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = iosb.Status;
}
return status;
}
NTSTATUS tdi_unset_event_handler(PFILE_OBJECT addressFileObject, LONG eventType)
{
return tdi_set_event_handler(addressFileObject, eventType, NULL, NULL);
}
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 == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildAssociateAddress(irp, devObj, connectionFileObject, NULL, NULL, addressHandle);
status = IoCallDriver(devObj, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = iosb.Status;
}
return status;
}
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 == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildDisassociateAddress(irp, devObj, connectionFileObject, NULL, NULL);
status = IoCallDriver(devObj, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
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);
remoteInfo = (PTDI_CONNECTION_INFORMATION) ExAllocatePool(NonPagedPool, 2 * sizeof(TDI_CONNECTION_INFORMATION) + 2 * sizeof(TA_IP_ADDRESS));
if (remoteInfo == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(remoteInfo, 2 * sizeof(TDI_CONNECTION_INFORMATION) + 2 * sizeof(TA_IP_ADDRESS));
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 == NULL)
{
ExFreePool(remoteInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildConnect(irp, devObj, connectionFileObject, NULL, NULL, NULL, remoteInfo, returnInfo);
status = IoCallDriver(devObj, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = iosb.Status;
}
ExFreePool(remoteInfo);
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 == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildDisconnect(irp, devObj, connectionFileObject, NULL, NULL, NULL, flags, NULL, NULL);
status = IoCallDriver(devObj, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = iosb.Status;
}
return 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;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
devObj = IoGetRelatedDeviceObject(addressFileObject);
KeInitializeEvent(&event, NotificationEvent, FALSE);
remoteInfo = (PTDI_CONNECTION_INFORMATION) ExAllocatePool(NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -