windows driver 映射大文件

//如果要做到掉电后仍然可以继续向下操作,可以记录文件的位置重新映射
	NTSTATUS status;
	UNICODE_STRING strFileSrc = RTL_CONSTANT_STRING(L"\\??\\C:\\win7旗舰版.iso");//3.11G
	UNICODE_STRING strFileDest = RTL_CONSTANT_STRING(L"\\??\\C:\\win7旗舰版1.iso");
	UNICODE_STRING strSectionName = RTL_CONSTANT_STRING(L"\\MySection");//可以是符号连接的方法,也可以用\\MySection,如果不加\\会报错
	HANDLE hFileSrc = NULL;
	HANDLE hFileDest = NULL;
	OBJECT_ATTRIBUTES oaSrc;
	OBJECT_ATTRIBUTES oaDest;
	OBJECT_ATTRIBUTES oaSection;
	IO_STATUS_BLOCK iosb;
	FILE_NETWORK_OPEN_INFORMATION fnoi;

	HANDLE hSection = NULL;
	PVOID pAddress = NULL;
	SIZE_T viewsize = 0;
	LARGE_INTEGER li_Section;
	LARGE_INTEGER li_Offset;
	LARGE_INTEGER li_WriteOffset;
	SIZE_T CommitSize = 64 * 1024 * 1024;//粒度为64Kb的倍数,参考windows核心编程.每次映射的基数
<span style="white-space:pre">						</span>//GetSysteminfo中的dwAllocationGranularity 就是分配粒度,通常是64kb
	InitializeObjectAttributes(&oaSrc, &strFileSrc, OBJ_KERNEL_HANDLE, NULL, NULL);
	InitializeObjectAttributes(&oaDest, &strFileDest, OBJ_KERNEL_HANDLE, NULL, NULL);
	InitializeObjectAttributes(&oaSection, &strSectionName, OBJ_KERNEL_HANDLE, NULL, NULL);

	status = ZwCreateFile(&hFileSrc, GENERIC_READ, &oaSrc, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
	if (!NT_SUCCESS(status)){
		ZwClose(hFileSrc);
		KdPrint(("hFileSrc: ZwCreateFile failed with error %I32X", status));
		return status;
	}

	status = ZwQueryFullAttributesFile(&oaSrc, &fnoi);
	if (!NT_SUCCESS(status)){
		ZwClose(hFileSrc);
		ZwClose(hSection);
		KdPrint(("ZwQueryFullAttributesFile failed with error %I32X", status));
		return status;
	}
	KdPrint(("文件大小:%I64d", fnoi.AllocationSize.QuadPart));
	li_Section.QuadPart = fnoi.AllocationSize.QuadPart;
	status = ZwCreateSection(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE, &oaSection, &li_Section, PAGE_READWRITE, SEC_RESERVE, hFileSrc);//只分配在虚拟内存中,不提交到物理内存.参考VirtualAlloc
	if (!NT_SUCCESS(status)){
		ZwClose(hFileSrc);
		ZwClose(hSection);
		KdPrint(("ZwCreateSection failed with error %I32X", status));
		return status;
	}

	status = ZwCreateFile(&hFileDest, 
							GENERIC_READ | GENERIC_WRITE,
							&oaDest,
							&iosb,
							&li_Section,//要创建的文件大小
							FILE_ATTRIBUTE_NORMAL,
							0,
							FILE_CREATE,
							FILE_NON_DIRECTORY_FILE,
							NULL,
							0);
	if (!NT_SUCCESS(status)){
		ZwClose(hFileSrc);
		ZwClose(hSection);
		ZwClose(hFileDest);
		KdPrint(("hFileDest: ZwCreateFile failed with error %I32X", status));
		return status;
	}

	li_Offset.QuadPart = 0;
	viewsize = CommitSize;
	while (li_Offset.QuadPart < li_Section.QuadPart){
		if ((li_Section.QuadPart - li_Offset.QuadPart) / CommitSize > 0){
			status = ZwMapViewOfSection(hSection,
										ZwCurrentProcess(),
										&pAddress,//BaseAddress 如果不为NULL,则分配在指定的位置,有可能失败
										0,//为NULL,表示可以分配在虚拟内存的任意位置,请参考windows核心编程里面的VirtualAlloc
										CommitSize,//文件大小
										&li_Offset,
										&viewsize,
										ViewUnmap,
										MEM_RESERVE | MEM_LARGE_PAGES ,
										PAGE_READWRITE);
			if (!NT_SUCCESS(status)){
				ZwClose(hFileSrc);
				ZwClose(hSection);
				ZwClose(hFileDest);
				ZwUnmapViewOfSection(hSection, pAddress);
				KdPrint(("ZwMapViewOfSection1 failed with error %I32X", status));
				return status;
			}

			li_WriteOffset.HighPart = -1;
			li_WriteOffset.LowPart = FILE_WRITE_TO_END_OF_FILE;
			ZwWriteFile(hFileDest, NULL, NULL, NULL, &iosb, pAddress, viewsize, &li_WriteOffset, NULL);//从文件末尾开始写数据
			ZwUnmapViewOfSection(ZwCurrentProcess(), pAddress);
			li_Offset.QuadPart += viewsize;
		}
		else{
			viewsize = (SIZE_T)(li_Section.QuadPart - li_Offset.QuadPart);//获得剩余多少数据还没有写入
			KdPrint(("view = %I64d %I32d %I64d", li_Offset.QuadPart, viewsize, li_Section.QuadPart));
			status = ZwMapViewOfSection(hSection,
										ZwCurrentProcess(),
										&pAddress,//BaseAddress 如果不为NULL,则分配在指定的位置,有可能失败
										0,//为NULL,表示可以分配在虚拟内存的任意位置,请参考windows核心编程里面的VirtualAlloc
										viewsize,//文件大小
										&li_Offset,
										&viewsize,
										ViewUnmap,
										MEM_RESERVE | MEM_LARGE_PAGES ,
										PAGE_READWRITE);
			if (!NT_SUCCESS(status)){
				ZwClose(hFileSrc);
				ZwClose(hSection);
				ZwClose(hFileDest);
				ZwUnmapViewOfSection(hSection, pAddress);
				KdPrint(("ZwMapViewOfSection2 failed with error %I32X", status));
				return status;
			}

			li_WriteOffset.HighPart = -1;
			li_WriteOffset.LowPart = FILE_WRITE_TO_END_OF_FILE;
			ZwWriteFile(hFileDest, NULL, NULL, NULL, &iosb, pAddress, viewsize, &li_WriteOffset, NULL);//参数ByteOffset为0表示从其实地址开始写数据,适用于小文件
			ZwUnmapViewOfSection(ZwCurrentProcess(), pAddress);
			li_Offset.QuadPart += viewsize;
		}
	}

	ZwClose(hSection);
	ZwClose(hFileDest);
	ZwClose(hFileSrc);
	KdPrint(("写文件成功"));
	return STATUS_SUCCESS;

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

posted @ 2014-11-13 20:25  QQ76211822  阅读(320)  评论(0编辑  收藏  举报