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

📄 httpdisk.c

📁 This a virtual disk driver for Windows NT/2000/XP that uses one or more files to emulate physical
💻 C
📖 第 1 页 / 共 3 页
字号:
        device_extension->file_name,
        &Irp->IoStatus,
        &http_header
        );

    if (!NT_SUCCESS(Irp->IoStatus.Status))
    {
        HttpDiskGetHeader(
            device_extension->address,
            device_extension->port,
            device_extension->host_name,
            device_extension->file_name,
            &Irp->IoStatus,
            &http_header
            );
    }

    if (!NT_SUCCESS(Irp->IoStatus.Status))
    {
        if (device_extension->host_name != NULL)
        {
            ExFreePool(device_extension->host_name);
            device_extension->host_name = NULL;
        }

        if (device_extension->file_name != NULL)
        {
            ExFreePool(device_extension->file_name);
            device_extension->file_name = NULL;
        }

        return Irp->IoStatus.Status;
    }

    device_extension->file_size.QuadPart = http_header.ContentLength.QuadPart;

    device_extension->media_in_device = TRUE;

    return Irp->IoStatus.Status;
}

NTSTATUS
HttpDiskDisconnect (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
    )
{
    PDEVICE_EXTENSION device_extension;

    ASSERT(DeviceObject != NULL);
    ASSERT(Irp != NULL);

    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    device_extension->media_in_device = FALSE;

    if (device_extension->host_name != NULL)
    {
        ExFreePool(device_extension->host_name);
        device_extension->host_name = NULL;
    }

    if (device_extension->file_name != NULL)
    {
        ExFreePool(device_extension->file_name);
        device_extension->file_name = NULL;
    }

    if (device_extension->socket > 0)
    {
        close(device_extension->socket);
        device_extension->socket = -1;
    }

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    return STATUS_SUCCESS;
}

NTSTATUS
HttpDiskGetHeader (
    IN ULONG                Address,
    IN USHORT               Port,
    IN PUCHAR               HostName,
    IN PUCHAR               FileName,
    OUT PIO_STATUS_BLOCK    IoStatus,
    OUT PHTTP_HEADER        HttpHeader
    )
{
    int                 kSocket;
    struct sockaddr_in  toAddr;
    int                 status, nSent, nRecv;
    char                *request, *buffer, *pStr;

    ASSERT(HostName != NULL);
    ASSERT(FileName != NULL);
    ASSERT(IoStatus != NULL);
    ASSERT(HttpHeader != NULL);

    request = ExAllocatePool(PagedPool, PAGE_SIZE);

    if (request == NULL)
    {
        IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;
        return IoStatus->Status;
    }

    buffer = ExAllocatePool(PagedPool, BUFFER_SIZE);

    if (buffer == NULL)
    {
        ExFreePool(request);
        IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;
        return IoStatus->Status;
    }

    kSocket = socket(AF_INET, SOCK_STREAM, 0);

    if (kSocket < 0)
    {
        DbgPrint("HttpDisk: socket() error: %#x\n", kSocket);
        ExFreePool(request);
        ExFreePool(buffer);
        IoStatus->Status = kSocket;
        return IoStatus->Status;
    }

    toAddr.sin_family = AF_INET;
    toAddr.sin_port = Port;
    toAddr.sin_addr.s_addr = Address;

    status = connect(kSocket, (struct sockaddr*) &toAddr, sizeof(toAddr));

    if (status < 0)
    {
        DbgPrint("HttpDisk: connect() error: %#x\n", status);
        ExFreePool(request);
        ExFreePool(buffer);
        close(kSocket);
        IoStatus->Status = status;
        return IoStatus->Status;
    }

    // Example request:
    //  HEAD 'FileName' HTTP/1.1
    //  Host: 'HostName'
    //  Accept: */*
    //  User-Agent: HttpDisk/1.4
    //  Connection: close
    //
    // Interesting lines in response:
    //  HTTP/1.1 200 OK
    //  Accept-Ranges: bytes
    //  Content-Length: 'total file size'

    _snprintf(
        request,
        PAGE_SIZE,
        "HEAD %s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\nUser-Agent: HttpDisk/1.4\r\nConnection: close\r\n\r\n",
        FileName,
        HostName
        );

    nSent = send(kSocket, request, strlen(request), 0);

    if (nSent < 0)
    {
        DbgPrint("HttpDisk: send() error: %#x\n", nSent);
        ExFreePool(request);
        ExFreePool(buffer);
        close(kSocket);
        IoStatus->Status = nSent;
        return IoStatus->Status;
    }

    nRecv = recv(kSocket, buffer, BUFFER_SIZE, 0);

    if (nRecv < 0)
    {
        DbgPrint("HttpDisk: recv() error: %#x\n", nRecv);
        ExFreePool(request);
        ExFreePool(buffer);
        close(kSocket);
        IoStatus->Status = nRecv;
        return IoStatus->Status;
    }

    close(kSocket);

    buffer[BUFFER_SIZE - 1] = '\0';

    if (_strnicmp(buffer, "HTTP/1.1 200 OK", 15))
    {
        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);
        DbgPrint("HttpDisk: Request was:\n%s", request);
        ExFreePool(request);
        ExFreePool(buffer);
        IoStatus->Status = STATUS_NO_SUCH_FILE;
        return IoStatus->Status;
    }

    pStr = strstr(buffer, "Content-Length:");

    if (pStr == NULL || pStr + 16 >= buffer + BUFFER_SIZE)
    {
        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);
        DbgPrint("HttpDisk: Request was:\n%s", request);
        ExFreePool(request);
        ExFreePool(buffer);
        IoStatus->Status = STATUS_NO_SUCH_FILE;
        return IoStatus->Status;
    }

    HttpHeader->ContentLength.QuadPart = _atoi64(pStr + 16);

    if (HttpHeader->ContentLength.QuadPart == 0)
    {
        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);
        DbgPrint("HttpDisk: Request was:\n%s", request);
        ExFreePool(request);
        ExFreePool(buffer);
        IoStatus->Status = STATUS_NO_SUCH_FILE;
        return IoStatus->Status;
    }

    ExFreePool(request);
    ExFreePool(buffer);

    IoStatus->Status = STATUS_SUCCESS;
    IoStatus->Information = 0;

    return STATUS_SUCCESS;
}

NTSTATUS
HttpDiskGetBlock (
    IN int                  *Socket,
    IN ULONG                Address,
    IN USHORT               Port,
    IN PUCHAR               HostName,
    IN PUCHAR               FileName,
    IN PLARGE_INTEGER       Offset,
    IN ULONG                Length,
    OUT PIO_STATUS_BLOCK    IoStatus,
    OUT PVOID               SystemBuffer
    )
{
    struct sockaddr_in  toAddr;
    int                 status, nSent, nRecv;
    unsigned int        dataLen;
    char                *request, *buffer, *pDataPart;

    ASSERT(Socket != NULL);
    ASSERT(HostName != NULL);
    ASSERT(FileName != NULL);
    ASSERT(Offset != NULL);
    ASSERT(IoStatus != NULL);
    ASSERT(SystemBuffer != NULL);

    IoStatus->Information = 0;

    request = ExAllocatePool(PagedPool, PAGE_SIZE);

    if (request == NULL)
    {
        IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;
        return IoStatus->Status;
    }

    buffer = ExAllocatePool(PagedPool, BUFFER_SIZE + 1);

    if (buffer == NULL)
    {
        ExFreePool(request);
        IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;
        return IoStatus->Status;
    }

    // Example request:
    //  GET 'FileName' HTTP/1.1
    //  Host: 'HostName'
    //  Range: bytes='Offset'-'Offset + Length - 1'
    //  Accept: */*
    //  User-Agent: HttpDisk/1.4
    //
    // Interesting lines in response:
    //  HTTP/1.1 206 Partial content
    //  Content-Length: 'requested size'
    //  Content-Range: bytes 'start'-'end'/'total file size'
    //  Data follows after '\r\n\r\n'

    _snprintf(
        request,
        PAGE_SIZE,
        "GET %s HTTP/1.1\r\nHost: %s\r\nRange: bytes=%I64u-%I64u\r\nAccept: */*\r\nUser-Agent: HttpDisk/1.4\r\n\r\n",
        FileName,
        HostName,
        Offset->QuadPart,
        Offset->QuadPart + Length - 1
        );

    if (*Socket < 0)
    {
        *Socket = socket(AF_INET, SOCK_STREAM, 0);

        if (*Socket < 0)
        {
            ExFreePool(request);
            ExFreePool(buffer);
            *Socket = -1;
            IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;
            return IoStatus->Status;
        }

        toAddr.sin_family = AF_INET;
        toAddr.sin_port = Port;
        toAddr.sin_addr.s_addr = Address;

        status = connect(*Socket, (struct sockaddr*) &toAddr, sizeof(toAddr));

        if (status < 0)
        {
            DbgPrint("HttpDisk: connect() error: %#x\n", status);
            ExFreePool(request);
            ExFreePool(buffer);
            close(*Socket);
            *Socket = -1;
            IoStatus->Status = status;
            return IoStatus->Status;
        }
    }

    nSent = send(*Socket, request, strlen(request), 0);

    if (nSent < 0)
    {
        KdPrint(("HttpDisk: send() error: %#x\n", nSent));

        close(*Socket);

        *Socket = socket(AF_INET, SOCK_STREAM, 0);

        if (*Socket < 0)
        {
            ExFreePool(request);
            ExFreePool(buffer);
            *Socket = -1;
            IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;
            return IoStatus->Status;
        }

        toAddr.sin_family = AF_INET;
        toAddr.sin_port = Port;
        toAddr.sin_addr.s_addr = Address;

        status = connect(*Socket, (struct sockaddr*) &toAddr, sizeof(toAddr));

        if (status < 0)
        {
            DbgPrint("HttpDisk: connect() error: %#x\n", status);
            ExFreePool(request);
            ExFreePool(buffer);
            close(*Socket);
            *Socket = -1;
            IoStatus->Status = status;
            return IoStatus->Status;
        }

        nSent = send(*Socket, request, strlen(request), 0);

        if (nSent < 0)
        {
            DbgPrint("HttpDisk: send() error: %#x\n", nSent);
            ExFreePool(request);
            ExFreePool(buffer);
            close(*Socket);
            *Socket = -1;
            IoStatus->Status = nSent;
            return IoStatus->Status;
        }
    }

    nRecv = recv(*Socket, buffer, BUFFER_SIZE, 0);

    if (nRecv < 0)
    {
        KdPrint(("HttpDisk: recv() error: %#x\n", nRecv));

        close(*Socket);

        *Socket = socket(AF_INET, SOCK_STREAM, 0);

        if (*Socket < 0)
        {
            ExFreePool(request);
            ExFreePool(buffer);
            *Socket = -1;
            IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;
            return IoStatus->Status;
        }

        toAddr.sin_family = AF_INET;
        toAddr.sin_port = Port;
        toAddr.sin_addr.s_addr = Address;

        status = connect(*Socket, (struct sockaddr*) &toAddr, sizeof(toAddr));

        if (status < 0)
        {
            DbgPrint("HttpDisk: connect() error: %#x\n", status);
            ExFreePool(request);
            ExFreePool(buffer);
            close(*Socket);
            *Socket = -1;
            IoStatus->Status = status;
            return IoStatus->Status;
        }

        nSent = send(*Socket, request, strlen(request), 0);

        if (nSent < 0)
        {
            DbgPrint("HttpDisk: send() error: %#x\n", nSent);
            ExFreePool(request);
            ExFreePool(buffer);
            close(*Socket);
            *Socket = -1;
            IoStatus->Status = nSent;
            return IoStatus->Status;
        }

        nRecv = recv(*Socket, buffer, BUFFER_SIZE, 0);

        if (nRecv < 0)
        {
            DbgPrint("HttpDisk: recv() error: %#x\n", nRecv);
            ExFreePool(request);
            ExFreePool(buffer);
            close(*Socket);
            *Socket = -1;
            IoStatus->Status = nRecv;
            return IoStatus->Status;
        }
    }

    buffer[BUFFER_SIZE] = '\0';

    if (_strnicmp(buffer, "HTTP/1.1 206 Partial Content", 28))
    {
        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);
        DbgPrint("HttpDisk: Request was:\n%s", request);
        ExFreePool(request);
        ExFreePool(buffer);
        close(*Socket);
        *Socket = -1;
        IoStatus->Status = STATUS_UNSUCCESSFUL;
        return IoStatus->Status;
    }

    pDataPart = strstr(buffer, "\r\n\r\n") + 4;

    if (pDataPart == NULL || pDataPart < buffer || pDataPart >= buffer + BUFFER_SIZE)
    {
        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);
        DbgPrint("HttpDisk: Request was:\n%s", request);
        ExFreePool(request);
        ExFreePool(buffer);
        close(*Socket);
        *Socket = -1;
        IoStatus->Status = STATUS_UNSUCCESSFUL;
        return IoStatus->Status;
    }

    dataLen = nRecv - (pDataPart - buffer);

    if (dataLen > Length || pDataPart + dataLen > buffer + BUFFER_SIZE)
    {
        DbgPrint("HttpDisk: Invalid data length %u in HTTP response:\n%s", dataLen, buffer);
        DbgPrint("HttpDisk: Request was:\n%s", request);
        ExFreePool(request);
        ExFreePool(buffer);
        close(*Socket);
        *Socket = -1;
        IoStatus->Status = STATUS_UNSUCCESSFUL;
        return IoStatus->Status;
    }

    if (dataLen > 0)
    {
        RtlCopyMemory(
            SystemBuffer,
            pDataPart,
            dataLen
            );
    }

    while (dataLen < Length)
    {
        nRecv = recv(*Socket, buffer, BUFFER_SIZE, 0);
        if (nRecv < 0)
        {
            DbgPrint("HttpDisk: recv() error: %#x\n", nRecv);
            close(*Socket);
            *Socket = -1;
            break;
        }
        if (nRecv < 1 || dataLen + nRecv > Length || nRecv > BUFFER_SIZE)
        {
            DbgPrint("HttpDisk: Invalid data length %u+%u\n", dataLen, nRecv);
            DbgPrint("HttpDisk: Request was:\n%s", request);
            close(*Socket);
            *Socket = -1;
            break;
        }
        RtlCopyMemory(
            (PVOID)((PUCHAR) SystemBuffer + dataLen),
            buffer,
            nRecv
        );
        dataLen += nRecv;
    }

    if (dataLen != Length)
    {
        DbgPrint("HttpDisk: received data length: %u, expected data length: %u\n", dataLen, Length);
        DbgPrint("HttpDisk: Request was:\n%s", request);
    }

    ExFreePool(request);
    ExFreePool(buffer);
    IoStatus->Status = STATUS_SUCCESS;
    IoStatus->Information = dataLen;
    return IoStatus->Status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -