📄 swapfs.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(¶meter_path, RegistryPath);
RtlAppendUnicodeToString(¶meter_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 + -