📄 filedisk.c
字号:
/*
This is a virtual disk driver for Windows NT/2000/XP that uses
one or more files to emulate physical disks, release 7.
Copyright (C) 1999, 2000, 2001, 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
The GNU General Public License is also available from:
http://www.gnu.org/copyleft/gpl.html
Please send comments, corrections and contributions to bosse@acc.umu.se
The most recent version of this program is available from:
http://www.acc.umu.se/~bosse/
Revision history:
7. 2002-02-28
Added support for CD-images.
6. 2002-01-21
Added support for impersonation so that FileDisk images can be stored
on network drives.
5. 2002-01-18
Updated for Windows XP by Robert A. Rose.
4. 2001-07-08
Formating to FAT on Windows 2000 now works.
3. 2001-05-14
Corrected the error messages from the usermode control application.
2. 2000-03-15
Added handling of IOCTL_DISK_CHECK_VERIFY to make the driver work on
Windows 2000 (tested on beta 3, build 2031). Formating to FAT still
doesn't work but formating to NTFS does.
1. 1999-06-09
Initial release.
*/
#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#include <ntverp.h>
//
// We include some stuff from newer DDK:s here so that one
// version of the driver for all versions of Windows can
// be compiled with the Windows NT 4.0 DDK.
//
#if (VER_PRODUCTBUILD < 2195)
#define FILE_DEVICE_MASS_STORAGE 0x0000002d
#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif
#if (VER_PRODUCTBUILD < 2600)
#define IOCTL_DISK_GET_PARTITION_INFO_EX CTL_CODE(IOCTL_DISK_BASE, 0x0012, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_GET_LENGTH_INFO CTL_CODE(IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS)
typedef enum _PARTITION_STYLE {
PARTITION_STYLE_MBR,
PARTITION_STYLE_GPT
} PARTITION_STYLE;
typedef unsigned __int64 ULONG64, *PULONG64;
typedef struct _PARTITION_INFORMATION_MBR {
UCHAR PartitionType;
BOOLEAN BootIndicator;
BOOLEAN RecognizedPartition;
ULONG HiddenSectors;
} PARTITION_INFORMATION_MBR, *PPARTITION_INFORMATION_MBR;
typedef struct _PARTITION_INFORMATION_GPT {
GUID PartitionType;
GUID PartitionId;
ULONG64 Attributes;
WCHAR Name[36];
} PARTITION_INFORMATION_GPT, *PPARTITION_INFORMATION_GPT;
typedef struct _PARTITION_INFORMATION_EX {
PARTITION_STYLE PartitionStyle;
LARGE_INTEGER StartingOffset;
LARGE_INTEGER PartitionLength;
ULONG PartitionNumber;
BOOLEAN RewritePartition;
union {
PARTITION_INFORMATION_MBR Mbr;
PARTITION_INFORMATION_GPT Gpt;
};
} PARTITION_INFORMATION_EX, *PPARTITION_INFORMATION_EX;
typedef struct _GET_LENGTH_INFORMATION {
LARGE_INTEGER Length;
} GET_LENGTH_INFORMATION, *PGET_LENGTH_INFORMATION;
#endif // (VER_PRODUCTBUILD < 2600)
//
// We include some stuff from ntifs.h here so that
// the driver can be compiled with only the DDK.
//
#define TOKEN_SOURCE_LENGTH 8
typedef enum _TOKEN_TYPE {
TokenPrimary = 1,
TokenImpersonation
} TOKEN_TYPE;
typedef struct _TOKEN_SOURCE {
CCHAR SourceName[TOKEN_SOURCE_LENGTH];
LUID SourceIdentifier;
} TOKEN_SOURCE, *PTOKEN_SOURCE;
typedef struct _TOKEN_CONTROL {
LUID TokenId;
LUID AuthenticationId;
LUID ModifiedId;
TOKEN_SOURCE TokenSource;
} TOKEN_CONTROL, *PTOKEN_CONTROL;
typedef struct _SECURITY_CLIENT_CONTEXT {
SECURITY_QUALITY_OF_SERVICE SecurityQos; //http://reactos.geldorp.nl/d1/d1c/struct__SECURITY__QUALITY__OF__SERVICE.html
PACCESS_TOKEN ClientToken;
BOOLEAN DirectlyAccessClientToken;
BOOLEAN DirectAccessEffectiveOnly;
BOOLEAN ServerIsRemote;
TOKEN_CONTROL ClientTokenControl;
} SECURITY_CLIENT_CONTEXT, *PSECURITY_CLIENT_CONTEXT;
#define PsDereferenceImpersonationToken(T) \
{if (ARGUMENT_PRESENT(T)) { \
(ObDereferenceObject((T))); \
} else { \
; \
} \
}
#define PsDereferencePrimaryToken(T) (ObDereferenceObject((T)))
/*
PsRevertToSelf: It should be called in the context of the thread
which should be reverted to its inherited context.
The routine does really nothing more than deleting
the thread imperonation information and dereferencing
the impersonation token, if any.
*/
NTKERNELAPI
VOID
PsRevertToSelf (
VOID
);
NTKERNELAPI
NTSTATUS
SeCreateClientSecurity (
IN PETHREAD Thread,
IN PSECURITY_QUALITY_OF_SERVICE QualityOfService,
IN BOOLEAN RemoteClient,
OUT PSECURITY_CLIENT_CONTEXT ClientContext
);
/*
Referenced by SeCreateClientSecurity().
00343 {
00344 NTSTATUS Status;
00345 OBJECT_ATTRIBUTES ObjectAttributes;
00346
00347 PAGED_CODE();
00348
00349 InitializeObjectAttributes(&ObjectAttributes,
00350 NULL,
00351 0,
00352 NULL,
00353 NULL);
00354 Status = SepDuplicateToken(Token, //http://www.reactos.org/doxygen/ntoskrnl/token_8c.html#a13
00355 &ObjectAttributes,
00356 FALSE,
00357 TokenImpersonation,
00358 Level,
00359 PreviousMode,
00360 (PTOKEN*)NewToken);
00361
00362 return(Status);
00363 }
*/
#define SeDeleteClientSecurity(C) { \
if (SeTokenType((C)->ClientToken) == TokenPrimary) { \
PsDereferencePrimaryToken( (C)->ClientToken ); \
} else { \
PsDereferenceImpersonationToken( (C)->ClientToken ); \
} \
}
NTKERNELAPI
VOID
SeImpersonateClient (
IN PSECURITY_CLIENT_CONTEXT ClientContext,
IN PETHREAD ServerThread OPTIONAL
);
NTKERNELAPI
TOKEN_TYPE
SeTokenType (
IN PACCESS_TOKEN Token //return ((PTOKEN)Token)->TokenType;
);
//
// For backward compatibility with Windows NT 4.0 by Bruce Engle.
//
#ifndef MmGetSystemAddressForMdlSafe
#define MmGetSystemAddressForMdlSafe(MDL, PRIORITY) MmGetSystemAddressForMdlPrettySafe(MDL)
PVOID
MmGetSystemAddressForMdlPrettySafe (
PMDL Mdl
)
{
CSHORT MdlMappingCanFail;
PVOID MappedSystemVa;
MdlMappingCanFail = Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL;
Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
MappedSystemVa = MmGetSystemAddressForMdl(Mdl);
if (MdlMappingCanFail == 0)
{
Mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
}
return MappedSystemVa;
}
#endif
#include "filedisk.h"
#define PARAMETER_KEY L"\\Parameters"
#define NUMBEROFDEVICES_VALUE L"NumberOfDevices"
#define DEFAULT_NUMBEROFDEVICES 4
#define SECTOR_SIZE 512
#define TOC_DATA_TRACK 0x04
HANDLE dir_handle;
typedef struct _DEVICE_EXTENSION {
BOOLEAN media_in_device;
HANDLE file_handle;
FILE_STANDARD_INFORMATION file_information;
BOOLEAN read_only;
PSECURITY_CLIENT_CONTEXT security_client_context;
LIST_ENTRY list_head;
KSPIN_LOCK list_lock;
KEVENT request_event;
PVOID thread_pointer;
BOOLEAN terminate_thread;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
NTSTATUS
FileDiskCreateDevice (
IN PDRIVER_OBJECT DriverObject,
IN ULONG Number
);
VOID
FileDiskUnload (
IN PDRIVER_OBJECT DriverObject
);
PDEVICE_OBJECT
FileDiskDeleteDevice (
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
FileDiskCreateClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskReadWrite (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskDeviceControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
FileDiskThread (
IN PVOID Context
);
NTSTATUS
FileDiskOpenFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskCloseFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
int swprintf(wchar_t *, const wchar_t *, ...);
#pragma code_seg("INIT")
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
UNICODE_STRING parameter_path;
RTL_QUERY_REGISTRY_TABLE query_table[2];
ULONG n_devices;
NTSTATUS status;
UNICODE_STRING device_dir_name;
OBJECT_ATTRIBUTES object_attributes;
ULONG n;
USHORT n_created_devices;
//从HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\FileDisk\
//PARAMETER_KEY = L"\\Parameters"
parameter_path.Length = 0;
parameter_path.MaximumLength = RegistryPath->Length + sizeof(PARAMETER_KEY);
parameter_path.Buffer = (PWSTR) ExAllocatePool(PagedPool, parameter_path.MaximumLength);
if (parameter_path.Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//将Registrypath的内容复制到parameter_path中
RtlCopyUnicodeString(¶meter_path, RegistryPath);
//EY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\*lass\Parameters
RtlAppendUnicodeToString(¶meter_path, PARAMETER_KEY);
RtlZeroMemory(&query_table[0], sizeof(query_table));
/////////////////////////////////////////////////////////
/*
typedef NTSTATUS(NTAPI * PRTL_QUERY_REGISTRY_ROUTINE)(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
00462 typedef struct _RTL_QUERY_REGISTRY_TABLE
00463 {
00464 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
00465 ULONG Flags;
00466 PWSTR Name;
00467 PVOID EntryContext;
00468 ULONG DefaultType;
00469 PVOID DefaultData;
00470 ULONG DefaultLength;
00471 } RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
*////////////////////////////////////////////////////////////
query_table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
query_table[0].Name = NUMBEROFDEVICES_VALUE;
query_table[0].EntryContext = &n_devices; //EntryContext 指向存储结果的地方
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE, //in
parameter_path.Buffer, //in
&query_table[0], //get the requirested data from parameter_path.Buffer
NULL, //in
NULL //in
);
ExFreePool(parameter_path.Buffer);
if (!NT_SUCCESS(status))
{
KdPrint(("FileDisk: Query registry failed, using default values.\n"));
n_devices = DEFAULT_NUMBEROFDEVICES;
}
RtlInitUnicodeString(&device_dir_name, DEVICE_DIR_NAME);
InitializeObjectAttributes(
&object_attributes, //out
&device_dir_name, //in
OBJ_PERMANENT, //in
NULL, //in
NULL //in
);
status = ZwCreateDirectoryObject(
&dir_handle, //out
DIRECTORY_ALL_ACCESS, //in
&object_attributes //in
);
if (!NT_SUCCESS(status))
{
return status;
}
//changes the attributes of an object to make it temporary.
ZwMakeTemporaryObject(dir_handle);
for (n = 0, n_created_devices = 0; n < n_devices; n++) // ? 创建n_devices个设备 ?
{
status = FileDiskCreateDevice(DriverObject, n);
if (NT_SUCCESS(status))
{
n_created_devices++;
}
}
if (n_created_devices == 0)
{
ZwClose(dir_handle);
return status;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = FileDiskCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FileDiskCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FileDiskReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = FileDiskReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FileDiskDeviceControl;
DriverObject->DriverUnload = FileDiskUnload;
return STATUS_SUCCESS;
}
NTSTATUS
FileDiskCreateDevice (
IN PDRIVER_OBJECT DriverObject,
IN ULONG Number
)
{
WCHAR device_name_buffer[MAXIMUM_FILENAME_LENGTH];
UNICODE_STRING device_name;
NTSTATUS status;
PDEVICE_OBJECT device_object;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -