⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ktdi.c

📁 This a virtual disk driver for Windows NT/2000/XP that uses one or more files to emulate physical
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
    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 + -