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

📄 vcdrom.c

📁 微软 发布的 虚拟光驱工具 带 c原代码 效果可以。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
    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 + -