驱动层文件高级操作

创建文件夹

//   文件名的格式为:     \\??\\C:\\dale
NTSTATUS CreateDirectory(PWCHAR wsDesFileName)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	OBJECT_ATTRIBUTES oa;
	UNICODE_STRING usDesFileName;
	IO_STATUS_BLOCK IoStatusBlock;
	HANDLE FileHandle = NULL;
	RtlInitUnicodeString(&usDesFileName, wsDesFileName);
	InitializeObjectAttributes(&oa,
		&usDesFileName,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
		NULL,
		NULL
		);

	//把内存中的数据写入到文件中
	status = ZwCreateFile(
		&FileHandle,
		GENERIC_READ,
		&oa,
		&IoStatusBlock,
		0,
		FILE_ATTRIBUTE_NORMAL | SYNCHRONIZE,
		FILE_SHARE_WRITE | FILE_SHARE_READ,
		FILE_CREATE,
		FILE_DIRECTORY_FILE,
		NULL,
		0
		);

	if (!NT_SUCCESS(status))
	{
		KdPrint(("目标文件创建失败 错误码:%x\n", status));
		return status;
	}
	ZwClose(FileHandle);
	return STATUS_SUCCESS;
}

文件复制

内核中文件路径格式为 “\??\C:\dale”
wsSrcFileName 要复制的源文件名 已存在的文件
wsDesFileName 复制到的目标文件 需要程序创建的文件

//   文件名的格式为:     \\??\\C:\\dale
NTSTATUS CopyFile(PCWSTR wsDesFileName, PCWSTR wsSrcFileName)
{
	NTSTATUS status = STATUS_SUCCESS;
	//打开文件
	HANDLE hSrcFile=NULL;
	HANDLE hDesFile=NULL;
	PUCHAR buffer = NULL;
	OBJECT_ATTRIBUTES oa;
	UNICODE_STRING usSrcFileName;


	//参数有效性检查
	if (!wsDesFileName || !wsSrcFileName)
	{
		KdPrint(("路径不能为空\n"));
		return STATUS_INVALID_PARAMETER;
	}

	do
	{
		RtlInitUnicodeString(&usSrcFileName, wsSrcFileName);
		InitializeObjectAttributes(&oa,
			&usSrcFileName,
			OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
			NULL,
			NULL
			);

		IO_STATUS_BLOCK IoStatusBlock;

		//打开需要复制的源文件
		status = ZwCreateFile(&hSrcFile,
			GENERIC_ALL,
			&oa,
			&IoStatusBlock,
			NULL,
			FILE_ATTRIBUTE_NORMAL,
			FILE_SHARE_VALID_FLAGS,
			FILE_OPEN,
			FILE_SYNCHRONOUS_IO_NONALERT,
			NULL,
			0);
		if (!NT_SUCCESS(status))
		{
			KdPrint(("源文件打开失败 错误码:%x\n", status));
			return status;
		}

		//获取源文件大小
		FILE_STANDARD_INFORMATION fsi = { 0 };
		status = ZwQueryInformationFile(hSrcFile, &IoStatusBlock, &fsi, sizeof(fsi), FileStandardInformation);
		if (!NT_SUCCESS(status) || !fsi.EndOfFile.QuadPart)
		{
			KdPrint(("查询源文件信息失败 错误码:%x\n", status));
			break;
		}


		//申请源文件大小的内存
		buffer = (PUCHAR)ExAllocatePoolWithTag(PagedPool, fsi.EndOfFile.LowPart, 'dale');
		if (!buffer)
		{
			KdPrint(("内存申请失败\n"));
			break;
		}
		RtlZeroMemory(buffer, fsi.EndOfFile.LowPart);

		//把文件读到一块内存中
		status = ZwReadFile(hSrcFile,
			NULL, NULL, NULL,
			&IoStatusBlock,
			buffer,	//保存读取内容的buffer
			fsi.EndOfFile.LowPart,//读取的长度
			0,//始读取的位置
			NULL
			);
		if (!NT_SUCCESS(status))
		{
			KdPrint(("读取文件内容失败 错误码:%x\n", status));
			break;
		}

		UNICODE_STRING usDesFileName;
		RtlInitUnicodeString(&usDesFileName, wsDesFileName);
		InitializeObjectAttributes(&oa,
			&usDesFileName,
			OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
			NULL,
			NULL
			);

		//把内存中的数据写入到文件中
		status = ZwCreateFile(&hDesFile,
			GENERIC_ALL,
			&oa,
			&IoStatusBlock,
			NULL,
			FILE_ATTRIBUTE_NORMAL,
			FILE_SHARE_VALID_FLAGS,
			FILE_OVERWRITE_IF,
			FILE_SYNCHRONOUS_IO_NONALERT,
			NULL,
			0);

		if (!NT_SUCCESS(status))
		{
			KdPrint(("目标文件创建失败 错误码:%x\n", status));
			break;
		}


		status = ZwWriteFile(hDesFile, NULL, NULL, NULL, &IoStatusBlock, buffer, fsi.EndOfFile.LowPart, 0, NULL);
		if (!NT_SUCCESS(status))
		{
			KdPrint(("写入目标文件失败 错误码:%x\n", status));
			break;
		}
	} while (FALSE);
	
	//关闭源文件句柄
	if (NULL != hSrcFile)
	{
		ZwClose(hSrcFile);
		hSrcFile = NULL;
	}

	//关闭目标文件句柄
	if (NULL != hDesFile)
	{
		ZwClose(hDesFile);
		hSrcFile = NULL;
	}

	if (NULL!= buffer)
	{
		ExFreePoolWithTag(buffer, 'dale');
		buffer = NULL;
	}
	return status;
}


文件删除操作

调用函数ZwDeleteFile即可删除文件,也可以删除文件夹 ,需要包含头文件Ntifs.h 并且要在ntddk.h的前面
只能删除空文件家或者文件

#include < Ntifs.h>
#include <ntddk.h>
NTSTATUS KeDeleteFile(PCWSTR DesFileName)
{
	if(!DesFileName)
	{
		KdPrint(("要删除的文件路径不能为空\n"));
		return STATUS_INVALID_PARAMETER;
	}
	NTSTATUS status=STATUS_SUCCESS;
	OBJECT_ATTRIBUTES oa;
	UNICODE_STRING FileName;
	RtlInitUnicodeString(&FileName, DesFileName);
	InitializeObjectAttributes(&oa, &FileName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,NULL);
	status=ZwDeleteFile(&oa);
	if(!NT_SUCCESS(status))
	{
		KdPrint(("文件删除失败,错误码:%x\n",status));
		return status;
	}
	return status;
}

文件重命名

NTSTATUS ReNameFile(PCWSTR NewFileName, PCWSTR OriginalFileName)
{
	NTSTATUS status=STATUS_SUCCESS;
	
	//打开文件
	HANDLE hSrcFile;
	OBJECT_ATTRIBUTES oa;
	UNICODE_STRING usSrcFileName;
	if (!NewFileName || !OriginalFileName)
	{
		KdPrint(("路径不能为空\n"));
		return STATUS_INVALID_PARAMETER;
	}

	RtlInitUnicodeString(&usSrcFileName, OriginalFileName);
	InitializeObjectAttributes(&oa,
		&usSrcFileName,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
		NULL,
		NULL
		);

	IO_STATUS_BLOCK IoStatusBlock;
	status = ZwCreateFile(&hSrcFile,
		GENERIC_ALL,
		&oa,
		&IoStatusBlock,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("源文件打开失败 错误码:%x\n", status));
		return status;
	}
	
	//计算出需要分配的内存大小,结构体PFILE_RENAME_INFORMATION+重命名的长度
	ULONG BufferLength = sizeof(FILE_RENAME_INFORMATION) + wcslen(NewFileName)*sizeof(WCHAR);

	//分配内存
	PFILE_RENAME_INFORMATION pri = (PFILE_RENAME_INFORMATION)ExAllocatePoolWithTag(PagedPool, BufferLength, 'dale');
	if (!pri)
	{
		KdPrint(("文件名分配失败\n"));
		ZwClose(hSrcFile);
		return STATUS_UNSUCCESSFUL;
	}
	//初始化内存
	RtlZeroMemory(pri, BufferLength);

	//把文件名复制到结构体中
	RtlCopyMemory(pri->FileName, NewFileName, wcslen(NewFileName)*sizeof(WCHAR));
	pri->FileNameLength = wcslen(NewFileName)*sizeof(WCHAR);
	pri->ReplaceIfExists = TRUE; //如果文件名存在就替换文件

	//设置文件信息 
	status = ZwSetInformationFile(hSrcFile, &IoStatusBlock, pri, BufferLength, FileRenameInformation);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("重命名文件失败,status=%x\n",status));
	}
	
	ExFreePoolWithTag(pri, 'dale');
	ZwClose(hSrcFile);
	return status;
}

遍历文件

typedef struct _FILE_BOTH_DIR_INFORMATION {
    ULONG NextEntryOffset;	//到下一个entry的偏移  这个值也可以看成是这个块的大小.
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;	//文件属性
    ULONG FileNameLength;	//文件名的长度
    ULONG EaSize;
    CCHAR ShortNameLength;
    WCHAR ShortName[12];
    WCHAR FileName[1];	//文件名
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
NTSTATUS Ergodic(PCWSTR FileDirName)
{
	NTSTATUS status = STATUS_SUCCESS;
	//打开文件
	HANDLE hFileDir;
	OBJECT_ATTRIBUTES oa;
	UNICODE_STRING usSrcFileName;

	if (!FileDirName)
	{
		KdPrint(("路径不能为空\n"));
		return STATUS_INVALID_PARAMETER;
	}

	RtlInitUnicodeString(&usSrcFileName, FileDirName);
	InitializeObjectAttributes(&oa,
		&usSrcFileName,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
		NULL,
		NULL
		);

	IO_STATUS_BLOCK IoStatusBlock;
	status = ZwCreateFile(&hFileDir,
		FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_ANY_ACCESS,
		&oa,
		&IoStatusBlock,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		FILE_OPEN,
		FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT,
		NULL,
		0);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("源文件打开失败 错误码:%x\n", status));
		return status;
	}

	IO_STATUS_BLOCK IoStackBlock;
	PFILE_BOTH_DIR_INFORMATION pbdi;

	pbdi = (PFILE_BOTH_DIR_INFORMATION)ExAllocatePoolWithTag(PagedPool, 1024*1024, 'dale');
	if (!pbdi)
	{
		KdPrint(("内存分配失败, status=%x\n", status));
		ZwClose(hFileDir);
	}

	RtlZeroMemory(pbdi, 1024*1024);
	WCHAR buffer[200] = { 0 };

	status = ZwQueryDirectoryFile(hFileDir,
		NULL,
		NULL,
		NULL,
		&IoStatusBlock,
		pbdi,
		1024*1024,
		FileBothDirectoryInformation,
		FALSE,//如果只需要返回一个条目,就设置为TRUE
		NULL,
		FALSE//如果要从目录中的第一个条目开始扫描,则设置为true。如果从上一次调用恢复扫描,则设置为false。
		);

	//怎样在不分配较大内存的情况下获得这个需要分配的值?
	KdPrint(("需要分配的内存大小是:%x\n",IoStatusBlock.Information));
	
	if (!NT_SUCCESS(status))
	{
		KdPrint(("查询目录失败,status=%x\n", status));
		ZwClose(hFileDir);
		ExFreePoolWithTag(pbdi, 'dale');
		return status;
	}
	PFILE_BOTH_DIR_INFORMATION pcdi = pbdi;
	while (TRUE)
	{
		RtlZeroMemory(buffer,sizeof(buffer));
		RtlCopyMemory(buffer, pcdi->FileName, pcdi->FileNameLength);
		KdPrint(("文件名:%S  \n", buffer));

		if (pcdi->NextEntryOffset == 0)
		{
			break;
		}
		//在64位下类型转换出现了错误,使用ULONG会蓝屏,要使用ULONG_PTR
		pcdi = (PFILE_BOTH_DIR_INFORMATION)((ULONG_PTR)pcdi + pcdi->NextEntryOffset);
	}  
	ExFreePoolWithTag(pbdi, 'dale');
	ZwClose(hFileDir);

	return status;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值