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

📄 swapfs.c

📁 This a disk filter driver for Windows NT/2000/XP that uses a Linux swap partition to provide a tem
💻 C
字号:
/*
    This is a disk filter driver for Windows NT/2000/XP that uses a Linux
    swap partition to provide a temporary storage area formated to the FAT
    file system.
    Copyright (C) 1999-2002 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
*/

/*
    If this driver is compiled for Windows NT 4.0 it will work on all version
    of Windows but it will not support Standby and Hibernation on Windows 2000
    and Windows XP.

    If this driver is compiled for Windows 2000 it will work on both Windows
    2000 and Windows XP and support Standby and Hibernation.
*/

#include <ntddk.h>
#include <ntdddisk.h>
#include <ntverp.h>
#include "swapfs.h"
#include "swap.h"

#define PARAMETER_KEY       L"\\Parameters"
#define SWAPDEVICE_VALUE    L"SwapDevice"

#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, SwapFsIsDeviceMounted)

NTSTATUS
DriverEntry (
    IN PDRIVER_OBJECT   DriverObject,
    IN PUNICODE_STRING  RegistryPath
    )
{
    ULONG                       i;
    UNICODE_STRING              parameter_path;
    UNICODE_STRING              device_name;
    RTL_QUERY_REGISTRY_TABLE    query_table[2];
    NTSTATUS                    status;
    PDEVICE_OBJECT              device_object;
    PDEVICE_EXTENSION           device_extension;

    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction[i] = SwapFsSendToNextDriver;
    }

    DriverObject->MajorFunction[IRP_MJ_READ]            = SwapFsReadWrite;
    DriverObject->MajorFunction[IRP_MJ_WRITE]           = SwapFsReadWrite;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = SwapFsDeviceControl;
#if (VER_PRODUCTBUILD >= 2195)
    DriverObject->MajorFunction[IRP_MJ_PNP]             = SwapFsPnp;
    DriverObject->MajorFunction[IRP_MJ_POWER]           = SwapFsPower;
#endif

    parameter_path.Length = 0;

    parameter_path.MaximumLength =
        RegistryPath->Length + sizeof(PARAMETER_KEY) + sizeof(WCHAR);

    parameter_path.Buffer =
        (PWSTR) ExAllocatePool(PagedPool, parameter_path.MaximumLength);

    if (!parameter_path.Buffer)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyUnicodeString(&parameter_path, RegistryPath);

    RtlAppendUnicodeToString(&parameter_path, PARAMETER_KEY);

    device_name.Length = 0;
    device_name.MaximumLength = 0;
    device_name.Buffer = NULL;

    RtlZeroMemory(&query_table[0], sizeof(query_table));

    query_table[0].Flags =
        RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
    query_table[0].Name = SWAPDEVICE_VALUE;
    query_table[0].EntryContext = &device_name;

    status = RtlQueryRegistryValues(
        RTL_REGISTRY_ABSOLUTE,
        parameter_path.Buffer,
        &query_table[0],
        NULL,
        NULL
        );

    ExFreePool(parameter_path.Buffer);

    if (!NT_SUCCESS(status) || !device_name.Buffer)
    {
        KdPrint(("SwapFs: DriverEntry: Query registry failed\n"));
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    if (SwapFsIsDeviceMounted(&device_name))
    {
        KdPrint(("SwapFs: DriverEntry: Device already mounted\n"));
        ExFreePool(device_name.Buffer);
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    status = IoCreateDevice(
        DriverObject,
        sizeof(DEVICE_EXTENSION),
        NULL,
        FILE_DEVICE_DISK,
#if (VER_PRODUCTBUILD >= 2195)
        FILE_DEVICE_SECURE_OPEN,
#else
        0,
#endif
        FALSE,
        &device_object
        );

    if (!NT_SUCCESS(status))
    {
        ExFreePool(device_name.Buffer);
        return status;
    }

    device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;

#if (VER_PRODUCTBUILD >= 2195)

    KeInitializeEvent(&device_extension->PagingPathCountEvent, NotificationEvent, TRUE);

    device_extension->PagingPathCount = 0;

#endif

    status = IoAttachDevice(
        device_object,
        &device_name,
        &device_extension->TargetDeviceObject
        );

    ExFreePool(device_name.Buffer);

    if (!NT_SUCCESS(status))
    {
        IoDeleteDevice(device_object);
        return status;
    }

    device_object->Flags |= (device_extension->TargetDeviceObject->Flags &
        (DO_BUFFERED_IO | DO_DIRECT_IO));

#if (VER_PRODUCTBUILD >= 2195)
    device_object->Flags |= (device_extension->TargetDeviceObject->Flags &
        DO_POWER_PAGABLE);
#endif

    device_object->Characteristics |=
        (device_extension->TargetDeviceObject->Characteristics &
         FILE_CHARACTERISTICS_PROPAGATED);

    status = SwapFsIsDeviceLinuxSwap(device_extension->TargetDeviceObject);

    if (!NT_SUCCESS(status))
    {
        KdPrint(("SwapFs: DriverEntry: Not a Linux swap device\n"));
        IoDetachDevice(device_extension->TargetDeviceObject);
        IoDeleteDevice(device_object);
        return status;
    }

    status = SwapFsFormatDeviceToFat(device_extension->TargetDeviceObject);

    if (!NT_SUCCESS(status))
    {
        KdPrint(("SwapFs: DriverEntry: FormatDeviceToFat failed\n"));
        IoDetachDevice(device_extension->TargetDeviceObject);
        IoDeleteDevice(device_object);
        return status;
    }

    return STATUS_SUCCESS;
}

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

    IoSkipCurrentIrpStackLocation(Irp);

    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    return IoCallDriver(device_extension->TargetDeviceObject, Irp);
}

NTSTATUS
SwapFsReadWrite (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
    )
{
    PIO_STACK_LOCATION  next_io_stack;
    PDEVICE_EXTENSION   device_extension;

    IoCopyCurrentIrpStackLocationToNext(Irp);

    next_io_stack = IoGetNextIrpStackLocation(Irp);

    next_io_stack->Parameters.Read.ByteOffset.QuadPart +=
        sizeof(union swap_header);

    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    return IoCallDriver(device_extension->TargetDeviceObject, Irp);
}

NTSTATUS
SwapFsDeviceControl (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
    )
{
    PIO_STACK_LOCATION  io_stack;
    PDEVICE_EXTENSION   device_extension;

    io_stack = IoGetCurrentIrpStackLocation(Irp);

    if (io_stack->Parameters.DeviceIoControl.IoControlCode ==
        IOCTL_DISK_SET_PARTITION_INFO
        ||
        io_stack->Parameters.DeviceIoControl.IoControlCode ==
        IOCTL_DISK_SET_PARTITION_INFO_EX
        )
    {
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }

    IoCopyCurrentIrpStackLocationToNext(Irp);

    IoSetCompletionRoutine(
        Irp,
        SwapFsDeviceControlCompletion,
        DeviceObject,
        TRUE,
        FALSE,
        FALSE
        );

    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    return IoCallDriver(device_extension->TargetDeviceObject, Irp);
}

NTSTATUS
SwapFsDeviceControlCompletion (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
{
    PIO_STACK_LOCATION io_stack;

    io_stack = IoGetCurrentIrpStackLocation(Irp);

    switch (io_stack->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_DISK_GET_PARTITION_INFO:
        {
        PPARTITION_INFORMATION p;
        p = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
        ASSERT(p != NULL);
        p->PartitionLength.QuadPart -= sizeof(union swap_header);
        break;
        }
    case IOCTL_DISK_GET_PARTITION_INFO_EX:
        {
        PPARTITION_INFORMATION_EX p;
        p = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer;
        ASSERT(p != NULL);
        p->PartitionLength.QuadPart -= sizeof(union swap_header);
        break;
        }
    case IOCTL_DISK_GET_LENGTH_INFO:
        {
        PGET_LENGTH_INFORMATION p;
        p = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
        ASSERT(p != NULL);
        p->Length.QuadPart -= sizeof(union swap_header);
        break;
        }
    }

    if (Irp->PendingReturned)
    {
        IoMarkIrpPending(Irp);
    }

    return STATUS_CONTINUE_COMPLETION;
}

BOOLEAN
SwapFsIsDeviceMounted (
    IN PUNICODE_STRING DeviceName
    )
{
    NTSTATUS        status;
    PFILE_OBJECT    file_object;
    PDEVICE_OBJECT  device_object;

    ASSERT(DeviceName != NULL);

    status = IoGetDeviceObjectPointer(
        DeviceName,
        FILE_READ_ATTRIBUTES,
        &file_object,
        &device_object
        );

    if (!NT_SUCCESS(status))
    {
        return FALSE;
    }

    ObDereferenceObject(file_object);

    if (device_object->Vpb && (device_object->Vpb->Flags & VPB_MOUNTED))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

⌨️ 快捷键说明

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