IRP管理文件

NTSTATUS IrpCreateFile(
	OUT PFILE_OBJECT *ppFileObject,
	IN ACCESS_MASK DesiredAccess,
	IN PUNICODE_STRING pustrFilePath,
	OUT PIO_STATUS_BLOCK IoStatusBlock,
	IN PLARGE_INTEGER AllocationSize OPTIONAL,
	IN ULONG FileAttributes,
	IN ULONG ShareAccess,
	IN ULONG CreateDisposition,
	IN ULONG CreateOptions,
	IN PVOID EaBuffer OPTIONAL,
	IN ULONG EaLength)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG ulFileNameMaxSize = 512;
	WCHAR wszName[100] = { 0 };
	UNICODE_STRING ustrRootPath;
	OBJECT_ATTRIBUTES objectAttributes = { 0 };
	HANDLE hRootFile = NULL;
	PFILE_OBJECT pRootFileObject = NULL, pFileObject = NULL;
	PDEVICE_OBJECT RootDeviceObject = NULL, RootRealDevice = NULL;
	PIRP pIrp = NULL;
	KEVENT kEvent = { 0 };
	ACCESS_STATE accessData = { 0 };
	AUX_ACCESS_DATA auxAccessData = { 0 };
	IO_SECURITY_CONTEXT ioSecurityContext = { 0 };
	PIO_STACK_LOCATION pIoStackLocation = NULL;

	// 打开磁盘根目录并获取句柄
	wcscpy(wszName, L"\\??\\A:\\");
	wszName[4] = pustrFilePath->Buffer[0];
	RtlInitUnicodeString(&ustrRootPath, wszName);
	DbgPrint("RootPath:%wZ\n", &ustrRootPath);
	InitializeObjectAttributes(&objectAttributes, &ustrRootPath, OBJ_KERNEL_HANDLE, NULL, NULL);
	status = IoCreateFile(&hRootFile, GENERIC_READ | SYNCHRONIZE,
		&objectAttributes, IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
		FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, 
		NULL, IO_NO_PARAMETER_CHECKING);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("IoCreateFile Error[0x%X]", status);
		return status;
	}
	
	// 获取磁盘根目录文件对象
	status = ObReferenceObjectByHandle(hRootFile, FILE_READ_ACCESS, *IoFileObjectType, KernelMode, &pRootFileObject, NULL);
	if (!NT_SUCCESS(status))
	{
		ZwClose(hRootFile);
		DbgPrint("ObReferenceObjectByHandle Error[0x%X]\n", status);
		return status;
	}

	// 获取磁盘根目录设备对象
	RootDeviceObject = pRootFileObject->Vpb->DeviceObject;
	RootRealDevice = pRootFileObject->Vpb->RealDevice;

	// 关闭磁盘根目录句柄和对象
	ObDereferenceObject(pRootFileObject);
	ZwClose(hRootFile);

	// 创建IRP
	pIrp = IoAllocateIrp(RootDeviceObject->StackSize, FALSE);
	if (NULL == pIrp)
	{
		ObDereferenceObject(pFileObject);
		DbgPrint("IoAllocateIrp Error!\n");
		return STATUS_UNSUCCESSFUL;
	}

	// 创建事件
	KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

	// 创建空文件对象
	InitializeObjectAttributes(&objectAttributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
	status = ObCreateObject(KernelMode, *IoFileObjectType, &objectAttributes, KernelMode, NULL, sizeof(FILE_OBJECT), 0, 0, &pFileObject);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("ObCreateObject Error[0x%X]\n", status);
		return status;
	}

	// 设置创建的文件对象 FILE_OBJECT
	RtlZeroMemory(pFileObject, sizeof(FILE_OBJECT));
	pFileObject->Type = IO_TYPE_FILE;
	pFileObject->Size = sizeof(FILE_OBJECT);
	pFileObject->DeviceObject = RootRealDevice;
	pFileObject->Flags = FO_SYNCHRONOUS_IO;

	// FILE_OBJECT中的FileName最好动态创建, 否则ObDereferenceObject文件句柄的时候会蓝屏
	pFileObject->FileName.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, ulFileNameMaxSize);
	pFileObject->FileName.MaximumLength = (USHORT)ulFileNameMaxSize;
	pFileObject->FileName.Length = pustrFilePath->Length - 4;
	RtlZeroMemory(pFileObject->FileName.Buffer, ulFileNameMaxSize);
	RtlCopyMemory(pFileObject->FileName.Buffer, &pustrFilePath->Buffer[2], pFileObject->FileName.Length);
	DbgPrint("pFileObject->FileName:%wZ\n", &pFileObject->FileName);
	KeInitializeEvent(&pFileObject->Lock, SynchronizationEvent, FALSE);
	KeInitializeEvent(&pFileObject->Event, NotificationEvent, FALSE);

	// 创建权限状态
	RtlZeroMemory(&auxAccessData, sizeof(auxAccessData));
	status = SeCreateAccessState(&accessData, &auxAccessData, DesiredAccess, IoGetFileObjectGenericMapping());
	if (!NT_SUCCESS(status))
	{
		IoFreeIrp(pIrp);
		ObDereferenceObject(pFileObject);
		DbgPrint("SeCreateAccessState Error[0x%X]\n", status);
		return status;
	}

	// 设置安全内容 IO_SECURITY_CONTEXT
	ioSecurityContext.SecurityQos = NULL;
	ioSecurityContext.AccessState = &accessData;
	ioSecurityContext.DesiredAccess = DesiredAccess;
	ioSecurityContext.FullCreateOptions = 0;

	// 设置IRP
	RtlZeroMemory(IoStatusBlock, sizeof(IO_STATUS_BLOCK));
	pIrp->MdlAddress = NULL;
	pIrp->AssociatedIrp.SystemBuffer = EaBuffer;
	pIrp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API;
	pIrp->RequestorMode = KernelMode;
	pIrp->UserIosb = IoStatusBlock;
	pIrp->UserEvent = &kEvent;
	pIrp->PendingReturned = FALSE;
	pIrp->Cancel = FALSE;
	pIrp->CancelRoutine = NULL;
	pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
	pIrp->Tail.Overlay.AuxiliaryBuffer = NULL;
	pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

	// 获取下一个IRP的IO_STACK_LOCATION并设置
	pIoStackLocation = IoGetNextIrpStackLocation(pIrp);
	pIoStackLocation->MajorFunction = IRP_MJ_CREATE;
	pIoStackLocation->DeviceObject = RootDeviceObject;
	pIoStackLocation->FileObject = pFileObject;
	pIoStackLocation->Parameters.Create.SecurityContext = &ioSecurityContext;
	pIoStackLocation->Parameters.Create.Options = (CreateDisposition << 24) | CreateOptions;
	pIoStackLocation->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
	pIoStackLocation->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
	pIoStackLocation->Parameters.Create.EaLength = EaLength;

	// 设置完成实例, 以便通知IRP处理完成, 释放资源
	IoSetCompletionRoutine(pIrp, MyCompleteRoutine, NULL, TRUE, TRUE, TRUE);

	// 发送IRP
	status = IoCallDriver(RootDeviceObject, pIrp);
	
	// 等待IRP的处理
	if (STATUS_PENDING == status)
	{
		KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, NULL);
	}

	// 判断IRP处理结果
	status = IoStatusBlock->Status;
	if (!NT_SUCCESS(status))
	{
		ObDereferenceObject(pFileObject);
		DbgPrint("IRP FAILED!\n");
		return status;
	}

	InterlockedIncrement(&pFileObject->DeviceObject->ReferenceCount);
	if (pFileObject->Vpb)
	{
		InterlockedIncrement(&pFileObject->Vpb->ReferenceCount);
	}
	
	// 返回文件对象
	*ppFileObject = pFileObject;
	
	return status;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值