📄 vcdrom.c
字号:
/*
This is a virtual disk driver for Windows NT/2000/XP that uses
one or more files to emulate physical disks.
Copyright (C) 1999-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
*/
//
//2008.01.01
//Microsoft Virtual CD-ROM driver, hacked by DongLinWang.
//
#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#include <ntverp.h>
#include <ntddvol.h>
#include "vcdrom.h"
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
VOID
VCDRomUnload (
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS
VCDRomDeleteDevice (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
VCDRomCreateClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
VCDRomRead (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
VCDRomDeviceControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
ULONG g_nVCDRomCount = 0;
FAST_MUTEX g_VCDRomFastMutex;
VOID
InitDeviceExtension(PDEVICE_OBJECT device_object)
{
PDEVICE_EXTENSION device_extension;
device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;
RtlZeroMemory(device_extension, sizeof(DEVICE_EXTENSION));
device_extension->PhysicalDeviceObject = device_object;
}
NTSTATUS
AllocateUnicodeString(
IN ULONG MaximumLength,
IN PUNICODE_STRING pUnicodeName)
{
NTSTATUS status;
pUnicodeName->Buffer = ExAllocatePool(NonPagedPool, MaximumLength);
pUnicodeName->Length = 0;
pUnicodeName->MaximumLength = (USHORT)MaximumLength;
if (pUnicodeName->Buffer == NULL)
{
status = STATUS_NO_MEMORY;
}
else
{
status = STATUS_SUCCESS;
}
return status;
}
VOID
FreeUnicodeString(
IN PUNICODE_STRING pUnicodeString
)
{
if (pUnicodeString->Buffer != NULL)
{
ExFreePool(pUnicodeString->Buffer);
pUnicodeString->Buffer = NULL;
}
pUnicodeString->Length = 0;
pUnicodeString->MaximumLength = 0;
}
NTSTATUS
VCDRomCreateDevice(
IN PDRIVER_OBJECT DriverObject,
IN ULONG Index,
IN PWSTR NameBuffer,
OUT PDEVICE_OBJECT *pOutDeviceObject
)
{
NTSTATUS status;
PDEVICE_OBJECT NewDeviceObject;
UNICODE_STRING DeviceName, SuffixName;
PDEVICE_EXTENSION DeviceExtension;
BOOLEAN bSuccess;
WCHAR Letter, DriveName[4];
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE LinkHandle;
status = STATUS_INVALID_PARAMETER;
NewDeviceObject = NULL;
*pOutDeviceObject = NULL;
AllocateUnicodeString(MAX_NAME_LENGTH, &DeviceName);
AllocateUnicodeString(MAX_NAME_LENGTH, &SuffixName);
ExAcquireFastMutex(&g_VCDRomFastMutex);
status = RtlIntegerToUnicodeString(g_nVCDRomCount, 10, &SuffixName);
g_nVCDRomCount++;
//InterlockedIncrement(&g_nVCDRomCount);
ExReleaseFastMutex(&g_VCDRomFastMutex);
if (!NT_SUCCESS(status))
{
goto exit1;
}
status = RtlAppendUnicodeToString(&DeviceName, DEVICE_DIR_NAME);
if (!NT_SUCCESS(status))
{
goto exit1;
}
status = RtlAppendUnicodeStringToString(&DeviceName, &SuffixName);
if (!NT_SUCCESS(status))
{
goto exit1;
}
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_CD_ROM, //0x02
FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE, //0x03
FALSE,
&NewDeviceObject
);
if (!NT_SUCCESS(status))
{
NewDeviceObject = NULL;
goto exit1;
}
DeviceExtension = (PDEVICE_EXTENSION) NewDeviceObject->DeviceExtension;
InitDeviceExtension(NewDeviceObject);
AllocateUnicodeString(
MAX_NAME_LENGTH,
&DeviceExtension->SymbolicLinkName
);
bSuccess = FALSE;
for (Letter = (WCHAR)Index; !bSuccess; Letter--)
{
if (Letter < L'A')
{
status = STATUS_INSUFFICIENT_RESOURCES; //0xC000009AL
break;
}
status = STATUS_INSUFFICIENT_RESOURCES;
DriveName[0] = Letter;
DriveName[1] = L':';
DriveName[2] = L'\0';
DeviceExtension->Flags = 0;
DeviceExtension->SymbolicLinkName.Length = 0;
status = RtlAppendUnicodeToString(
&DeviceExtension->SymbolicLinkName,
L"\\??\\"
);
if (!NT_SUCCESS(status))
{
break;
}
status = RtlAppendUnicodeToString(
&DeviceExtension->SymbolicLinkName,
DriveName
);
if (!NT_SUCCESS(status))
{
break;
}
InitializeObjectAttributes(
&ObjectAttributes,
&DeviceExtension->SymbolicLinkName,
OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, //0x50
NULL,
NULL
);
status = ZwOpenSymbolicLinkObject(
&LinkHandle,
GENERIC_READ, //0x80000000
&ObjectAttributes
);
if (!NT_SUCCESS(status))
{
status = IoCreateSymbolicLink(
&DeviceExtension->SymbolicLinkName,
&DeviceName
);
if (NT_SUCCESS(status))
{
NameBuffer[0] = Letter;
//
// Clear the DO_DEVICE_INITIALIZING flag
//
NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
NewDeviceObject->Flags |= DO_DIRECT_IO; //0x00000010
*pOutDeviceObject = NewDeviceObject;
bSuccess = TRUE;
}
}
else
{
ZwClose(LinkHandle);
status = STATUS_OBJECT_NAME_EXISTS; //0x40000000L
}
}
exit1:
FreeUnicodeString(&DeviceName);
FreeUnicodeString(&SuffixName);
if (!NT_SUCCESS(status) &&
status != STATUS_VERIFY_REQUIRED &&
NewDeviceObject != NULL)
{
IoDeleteDevice(NewDeviceObject);
}
return status;
}
NTSTATUS
VCDRomCreateFile(
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING FileName
)
{
NTSTATUS status;
PDEVICE_EXTENSION DeviceExtension;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE FileHandle;
IO_STATUS_BLOCK IoStatusBlock;
FILE_STANDARD_INFORMATION StandardInformation;
ULONG ReadData[2];
ULONG Count, Number;
status = STATUS_SUCCESS;
FileHandle = NULL;
DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
InitializeObjectAttributes(
&ObjectAttributes,
FileName,
OBJ_CASE_INSENSITIVE, //0x40
NULL,
NULL
);
status = ZwCreateFile(
&FileHandle,
SYNCHRONIZE | FILE_READ_DATA, //0x00100001
&ObjectAttributes,
&IoStatusBlock,
0,
FILE_ATTRIBUTE_NORMAL, //0x80
FILE_SHARE_READ, //0x01
FILE_OPEN, //0x01
FILE_SYNCHRONOUS_IO_NONALERT, //0x20
NULL,
0
);
if (!NT_SUCCESS(status))
{
return status;
}
status = ZwQueryInformationFile(
FileHandle,
&IoStatusBlock,
&StandardInformation,
sizeof(StandardInformation), //0x18
FileStandardInformation //0x05
);
if (!NT_SUCCESS(status))
{
ZwClose(FileHandle);
return status;
}
DeviceExtension->EndOfFile = StandardInformation.EndOfFile;
status = ZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
ReadData,
8,
NULL,
NULL
);
if (NT_SUCCESS(status) && ReadData[1] != 0 && ((ReadData[1] & 0x1FF) == 0))
{
DeviceExtension->BytesPerSector = ReadData[1];
}
else
{
DeviceExtension->BytesPerSector = 0x800;
}
Number = 0x200;
Count = 9;
for (; Number != DeviceExtension->BytesPerSector; Count++)
{
if (Number >= DeviceExtension->BytesPerSector)
{
break;
}
Number *= 2;
}
if (Number == DeviceExtension->BytesPerSector)
{
DeviceExtension->ShiftBits = Count;
}
else
{
DeviceExtension->ShiftBits = 0x0B;
}
status = ObReferenceObjectByHandle(
FileHandle,
0, //0x00
NULL,
KernelMode,
&DeviceExtension->FileObject,
NULL
);
if (!NT_SUCCESS(status))
{
ZwClose(FileHandle);
DeviceExtension->FileObject = NULL;
}
else
{
ZwClose(FileHandle);
DeviceExtension->Used++;
DeviceObject->Flags |= DO_VERIFY_VOLUME; //0x02
FreeUnicodeString(&DeviceExtension->FileName);
AllocateUnicodeString(
FileName->MaximumLength,
&DeviceExtension->FileName
);
RtlCopyUnicodeString(
&DeviceExtension->FileName,
FileName);
status = STATUS_SUCCESS;
}
return status;
}
ULONG
VCDRomCreate(
IN PDRIVER_OBJECT DriverObject,
IN ULONG Index,
IN PWSTR NameBuffer
)
{
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING FileName;
RtlInitUnicodeString(&FileName, NameBuffer);
DeviceObject = NULL;
VCDRomCreateDevice(DriverObject, Index, &NameBuffer[1], &DeviceObject);
VCDRomCreateFile(DeviceObject, &FileName);
return 1;
}
NTSTATUS
VCDRomQueryDevice(
IN PDRIVER_OBJECT DriverObject,
IN PCWSTR RegistryPath
)
{
NTSTATUS status;
CHAR Index;
UNICODE_STRING QueryTableName, FileName;
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
WCHAR wszDriveName[2];
WCHAR wszQueryName[100];
WCHAR wszFileName[100];
status = STATUS_SUCCESS;
for(Index = 'A'; Index <= 'Z'; Index++)
{
RtlZeroMemory(QueryTable, sizeof(QueryTable));
RtlZeroMemory(wszQueryName, sizeof(wszQueryName));
QueryTableName.Buffer = wszQueryName;
QueryTableName.Length = 0;
QueryTableName.MaximumLength = sizeof(wszQueryName); //0xC8
RtlAppendUnicodeToString(&QueryTableName, L"Parameters\\Device");
wszDriveName[0] = Index;
wszDriveName[1] = L'\0';
RtlAppendUnicodeToString(&QueryTableName, wszDriveName);
FileName.Buffer = wszFileName;
FileName.Length = 0;
FileName.MaximumLength = sizeof(wszFileName); //0xC8
QueryTable[0].Name = QueryTableName.Buffer;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; //0x01
QueryTable[1].Name = L"IMAGE";
QueryTable[1].EntryContext = (PVOID)&FileName;
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; //0x01
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE, //0x00
RegistryPath,
&QueryTable[0],
NULL,
NULL
);
if (NT_SUCCESS(status))
{
VCDRomCreate(DriverObject, Index, FileName.Buffer);
}
}
return status;
}
NTSTATUS
IoCommonComplete(
IN NTSTATUS Status,
IN ULONG Information,
IN PIRP Irp
)
{
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
return Status;
}
#pragma code_seg("INIT")
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
UNICODE_STRING device_name;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -