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

📄 devicethread.c

📁 使用DELPHI制作地虚拟光驱
💻 C
字号:
#include <ntddk.h>
#include <ntdef.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#include <ntverp.h>
#include <ntifs.h>
#include <stdio.h>
#include <DeviceThread.h>
#include <VCD.h>



//////////////////////////////////////////////////////////////////////////


NTSTATUS
VCDOpenFile (
			 IN PDEVICE_OBJECT   DeviceObject,
			 IN PIRP             Irp
			 )
{
	PDEVICE_EXTENSION               device_extension;
	PCHAR                           filename;
	UCHAR                           afile_name[MAX_PATH] = {0};
	UNICODE_STRING                  ufile_name;
	NTSTATUS                        status;
	OBJECT_ATTRIBUTES               object_attributes;
	FILE_END_OF_FILE_INFORMATION    file_eof;
	FILE_BASIC_INFORMATION          file_basic;
	FILE_STANDARD_INFORMATION       file_standard;
	FILE_ALIGNMENT_INFORMATION      file_alignment;

	DbgPrint("VCDOpenFile\n");

	device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

	filename = (PCHAR)Irp->AssociatedIrp.SystemBuffer;

	RtlCopyMemory(device_extension->oldfile_name,
		          filename,
				  MAX_PATH);

	if (filename[0] == '\\')
	{
		if (filename[1] == '\\')
			// \\server\share\path\XXX.iso  ->\??\UNC\\server\share\path\XXX.iso
		{
			strcpy(afile_name, "\\??\\UNC");
			strcat(afile_name, filename);
		}
		else
			// \Device\Harddisk0\Partition1\path\XXX.iso 不变
		{
			strcpy(afile_name, filename);
		}
	}
	else
		// c:\path\XXX.iso   ->\??\c:\path\XXX.iso
	{
		strcpy(afile_name, "\\??\\");
		strcat(afile_name, filename);
	}

	device_extension->file_name.Length = (USHORT)strlen(afile_name);
	device_extension->file_name.MaximumLength = device_extension->file_name.Length;
	device_extension->file_name.Buffer = ExAllocatePool(NonPagedPool, device_extension->file_name.Length);

	RtlCopyMemory(
		device_extension->file_name.Buffer,
		afile_name,
		device_extension->file_name.Length
		);

	status = RtlAnsiStringToUnicodeString(
		&ufile_name,
		&device_extension->file_name,
		TRUE
		);

	if (!NT_SUCCESS(status))
	{
		ExFreePool(device_extension->file_name.Buffer);
		Irp->IoStatus.Status = status;
		Irp->IoStatus.Information = 0;
		return status;
	}

	InitializeObjectAttributes(
		&object_attributes,
		&ufile_name,
		OBJ_CASE_INSENSITIVE,
		NULL,
		NULL
		);

	status = ZwCreateFile(
		&device_extension->file_handle,
		GENERIC_READ,
		&object_attributes,
		&Irp->IoStatus,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN,
		FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS |	FILE_NO_INTERMEDIATE_BUFFERING | FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0
		);

	if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NO_SUCH_FILE)
	{
		//如果长度是0
			ExFreePool(device_extension->file_name.Buffer);
			RtlFreeUnicodeString(&ufile_name);

			Irp->IoStatus.Status = STATUS_NO_SUCH_FILE;
			Irp->IoStatus.Information = 0;

			DbgPrint("文件不存在!\n");
			return STATUS_NO_SUCH_FILE;
	}
	else if (!NT_SUCCESS(status))
	{
		ExFreePool(device_extension->file_name.Buffer);
		RtlFreeUnicodeString(&ufile_name);
		DbgPrint("打开文件失败!\n");
		return status;
	}

	RtlFreeUnicodeString(&ufile_name);
    //获取虚拟光盘文件基础信息
	status = ZwQueryInformationFile(
		device_extension->file_handle,
		&Irp->IoStatus,
		&file_basic,
		sizeof(FILE_BASIC_INFORMATION),
		FileBasicInformation
		);

	if (!NT_SUCCESS(status))
	{
		ExFreePool(device_extension->file_name.Buffer);
		ZwClose(device_extension->file_handle);
		DbgPrint("1获取文件信息失败!\n");
		return status;
	}

	status = ZwQueryInformationFile(
		device_extension->file_handle,
		&Irp->IoStatus,
		&file_standard,
		sizeof(FILE_STANDARD_INFORMATION),
		FileStandardInformation
		);

	if (!NT_SUCCESS(status))
	{
		ExFreePool(device_extension->file_name.Buffer);
		ZwClose(device_extension->file_handle);
		DbgPrint("2获取文件信息失败!\n");
		return status;
	}

	device_extension->file_size.QuadPart = file_standard.EndOfFile.QuadPart;
    DbgPrint("文件长度[%d]!\n",device_extension->file_size.QuadPart);

	status = ZwQueryInformationFile(
		device_extension->file_handle,
		&Irp->IoStatus,
		&file_alignment,
		sizeof(FILE_ALIGNMENT_INFORMATION),
		FileAlignmentInformation
		);

	if (!NT_SUCCESS(status))
	{
		ExFreePool(device_extension->file_name.Buffer);
		ZwClose(device_extension->file_handle);
		DbgPrint("3获取文件信息失败!\n");
		return status;
	}

	DeviceObject->AlignmentRequirement = file_alignment.AlignmentRequirement;
    //只读 
    DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;

	//媒体在光驱内
	device_extension->media_in_device = TRUE;

	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;

	return STATUS_SUCCESS;
}

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

	DbgPrint("VCDCloseFile\n");

	ASSERT(DeviceObject != NULL);
	ASSERT(Irp != NULL);

	device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

	ExFreePool(device_extension->file_name.Buffer);

	ZwClose(device_extension->file_handle);

	device_extension->media_in_device = FALSE;

	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;

	return STATUS_SUCCESS;
}


//////////////////////////////////////////////////////////////////////////


VOID
DeviceThread (
			  IN PVOID Context
			  )
{
	PDEVICE_OBJECT      device_object;
	PDEVICE_EXTENSION   device_extension;
	PLIST_ENTRY         request;
	PIRP                irp;
	PIO_STACK_LOCATION  io_stack;
	PUCHAR              system_buffer;
	PUCHAR              buffer;


	DbgPrint("DeviceThread\n");

	device_object = (PDEVICE_OBJECT) Context;

	device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;

	//把线程自身优先级设置较低-----必须如此才能保证对文件读写正常.否则内核模式优先级别高的话写文件会失败
	KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);

	for (;;)
	{
		//等待事件被触发
		KeWaitForSingleObject(
			&device_extension->k_event,
			Executive,
			KernelMode,
			FALSE,
			NULL
			);
		DbgPrint("KeWaitForSingleObject被触发\n");
        //如果线程结束标志被设置了,就结束自身
		if (device_extension->terminate_thread)
		{
			PsTerminateSystemThread(STATUS_SUCCESS);
		}
        //解锁 
		while (request = ExInterlockedRemoveHeadList(
			&device_extension->list_head,
			&device_extension->list_lock
			))
		{

			irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry);

			io_stack = IoGetCurrentIrpStackLocation(irp);
            DbgPrint("io_stack->MajorFunction=[%u]\n",io_stack->MajorFunction);
			switch (io_stack->MajorFunction)
			{
            //读
			case IRP_MJ_READ:
				system_buffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
				if (system_buffer == NULL)
				{
					irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
					irp->IoStatus.Information = 0;
					break;
				}
				buffer = (PUCHAR) ExAllocatePool(PagedPool, io_stack->Parameters.Read.Length);
				if (buffer == NULL)
				{
					irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
					irp->IoStatus.Information = 0;
					break;
				}
				ZwReadFile(
					device_extension->file_handle,
					NULL,
					NULL,
					NULL,
					&irp->IoStatus,
					buffer,
					io_stack->Parameters.Read.Length,
					&io_stack->Parameters.Read.ByteOffset,
					NULL
					);
				RtlCopyMemory(system_buffer, buffer, io_stack->Parameters.Read.Length);
				ExFreePool(buffer);
				break;
            //写,直接返回写保护
            case IRP_MJ_WRITE:
                irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;
				break; 
            //设备控制
			case IRP_MJ_DEVICE_CONTROL:
				switch (io_stack->Parameters.DeviceIoControl.IoControlCode)
				{
                //我们定义的打开文件 
				case IOCTL_VCD_OPEN_FILE:

					SeImpersonateClient(device_extension->security_client_context, NULL);

					irp->IoStatus.Status = VCDOpenFile(device_object, irp);
                    DbgPrint("VCDOpenFile=[%u]\n",irp->IoStatus.Status) ;
					PsRevertToSelf();
                    DbgPrint("PsRevertToSelf\n") ;
					break;
                //我们定义的关闭文件 
				case IOCTL_VCD_CLOSE_FILE:
					irp->IoStatus.Status = VCDCloseFile(device_object, irp);
					break;

				default:
					irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
				}
				break;

			default:
				irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
			}

			IoCompleteRequest(
				              irp,
				              (CCHAR) (NT_SUCCESS(irp->IoStatus.Status) ?IO_DISK_INCREMENT : IO_NO_INCREMENT)
					          );
		}
	}
}

⌨️ 快捷键说明

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